Merge pull request #53 from r2dliu/volume

Volume
This commit is contained in:
David Liu 2020-09-06 01:34:48 -04:00 committed by GitHub
commit f2e766c022
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 5257 additions and 4228 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -15,6 +15,7 @@
#include "Core/ConfigManager.h"
#include "Core/Slippi/SlippiPlayback.h"
#include "VideoCommon/OnScreenDisplay.h"
#include "AudioCommon/AudioCommon.h"
#ifdef IS_PLAYBACK
#ifndef IMGUI_DEFINE_MATH_OPERATORS
@ -205,7 +206,7 @@ bool ButtonCustom(const char* label, const ImVec2& size_arg, ImGuiButtonFlags fl
return pressed;
}
bool SliderCustomBehavior(const ImRect& bb, ImGuiID id, int* v, int v_min, int v_max, float power, ImGuiSliderFlags flags, ImVec4 color, ImVec2 valuesize, const char* label, char* value)
bool SeekBarBehavior(const ImRect& bb, ImGuiID id, int* v, int v_min, int v_max, float power, ImGuiSliderFlags flags, ImVec4 color, ImVec2 valuesize, const char* label, char* value)
{
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
@ -235,9 +236,13 @@ bool SliderCustomBehavior(const ImRect& bb, ImGuiID id, int* v, int v_min, int v
bool isActive = g.ActiveId == id;
static bool isHeld = false;
const bool hovered = ImGui::ItemHoverable(bb, id);
if (hovered) {
INFO_LOG(SLIPPI, "is Hovered: %d", id);
}
if (!isDown && isActive)
if (!isHeld && isActive) {
ImGui::ClearActiveID();
}
// Calculate mouse position if hovered
int new_value = 0;
@ -279,6 +284,7 @@ bool SliderCustomBehavior(const ImRect& bb, ImGuiID id, int* v, int v_min, int v
}
if (isHeld) {
ImGui::SetActiveID(id, window);
isHeld = isHeld && isDown;
// If no longer held, slider was let go. Trigger mark edited
if (!isHeld) {
@ -343,19 +349,138 @@ bool SliderCustomBehavior(const ImRect& bb, ImGuiID id, int* v, int v_min, int v
return value_changed;
}
bool SliderCustom(const char* label, ImVec4 color, int* v, int v_min, int v_max, float power, const char* format)
bool VolumeBarBehavior(const ImRect& bb, ImGuiID id, int* v, int v_min, int v_max, float power,
ImGuiSliderFlags flags, ImVec4 color)
{
ImGuiWindow* window = ImGui::GetCurrentWindow();
if (window->SkipItems)
return false;
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
ImGuiWindow* window = ImGui::GetCurrentWindow();
const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;
const bool is_decimal = false; // TODO handle other types
const bool is_power = (power != 1.0f) && is_decimal;
const float slider_sz = (bb.Max[axis] - bb.Min[axis]);
const float slider_usable_pos_min = bb.Min[axis];
const float slider_usable_pos_max = bb.Max[axis];
float linear_zero_pos = 0.0f;
if (is_power && v_min * v_max < 0.0f)
{
const float linear_dist_min_to_0 =
ImPow(v_min >= 0 ? (float)v_min : -(float)v_min, (float)1.0f / power);
const float linear_dist_max_to_0 =
ImPow(v_max >= 0 ? (float)v_max : -(float)v_max, (float)1.0f / power);
linear_zero_pos = (float)(linear_dist_min_to_0 / (linear_dist_min_to_0 + linear_dist_max_to_0));
}
else
{
linear_zero_pos = v_min < 0.0f ? 1.0f : 0.0f;
}
const bool isDown = g.IO.MouseDown[0];
const bool hovered = ImGui::ItemHoverable(bb, id);
static bool isHeld = false;
bool value_changed = false;
bool isActive = g.ActiveId == id;
if (!isHeld && isActive)
ImGui::ClearActiveID();
if (isHeld)
ImGui::SetActiveID(id, window);
// Calculate mouse position if clicked or held
int new_value = 0;
if (isHeld || hovered)
{
const float mouse_abs_pos = g.IO.MousePos[axis];
float clicked_t = (slider_sz > 0.0f) ?
ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_sz, 0.0f, 1.0f) :
0.0f;
if (axis == ImGuiAxis_Y)
clicked_t = 1.0f - clicked_t;
if (is_power)
{
if (clicked_t < linear_zero_pos)
{
float a = 1.0f - (clicked_t / linear_zero_pos);
a = ImPow(a, power);
new_value = ImLerp(ImMin(v_max, 0), v_min, a);
}
else
{
float a;
if (ImFabs(linear_zero_pos - 1.0f) > 1.e-6f)
a = (clicked_t - linear_zero_pos) / (1.0f - linear_zero_pos);
else
a = clicked_t;
a = ImPow(a, power);
new_value = ImLerp(ImMax(v_min, 0), v_max, a);
}
}
else
{
new_value = ImLerp(v_min, v_max, clicked_t);
}
// Only change value if left mouse button is actually down
if (*v != new_value && isDown)
{
value_changed = true;
*v = new_value;
}
}
isHeld = isHeld ? isHeld && isDown : hovered && isDown;
float grab_t = ImGui::SliderCalcRatioFromValueT<int, float>(ImGuiDataType_S32, *v, v_min,
v_max, power, linear_zero_pos);
if (axis == ImGuiAxis_Y)
{
grab_t = 1.0f - grab_t;
}
const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
ImRect grab_bb;
if (axis == ImGuiAxis_X)
{
grab_bb = ImRect(ImVec2(grab_pos, bb.Min.y), ImVec2(grab_pos, bb.Max.y));
}
else
{
grab_bb = ImRect(ImVec2(bb.Min.x, grab_pos), ImVec2(bb.Max.x, grab_pos));
}
// Grey background line
window->DrawList->AddLine(
ImVec2(bb.Min.x, bb.Min.y + 5), ImVec2(bb.Max.x, bb.Min.y + 5),
ImGui::ColorConvertFloat4ToU32(ImVec4(1.0f, 1.0f, 1.0f, 0.5f * style.Alpha)), 4);
// Colored line and circle indicator
window->DrawList->AddLine(ImVec2(bb.Min.x, bb.Min.y + 5), ImVec2(grab_bb.Min.x, bb.Min.y + 5), ImGui::ColorConvertFloat4ToU32(ImVec4(1.0f, 1.0f, 1.0f, 0.8f * style.Alpha)), 4);
if (isHeld)
window->DrawList->AddCircleFilled(
ImVec2(grab_bb.Min.x, grab_bb.Min.y + 5), 6,
ImGui::ColorConvertFloat4ToU32(ImVec4(1.0f, 1.0f, 1.0f, 0.8f * style.Alpha)));
return value_changed;
}
bool SeekBar(const char* label, ImVec4 color, int* v, int v_min, int v_max, float power, const char* format)
{
ImGuiWindow* window = ImGui::GetCurrentWindow();
if (window->SkipItems) {
INFO_LOG(SLIPPI, "skip");
return false;
}
const ImGuiID id = window->GetID(label);
const float w = ImGui::CalcItemWidth();
const float w = ImGui::GetWindowWidth() - 10;
const ImVec2 label_size = ImGui::CalcTextSize(label, NULL, true) * 1.0f;
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y));
const ImRect frame_bb(window->DC.CursorPos + ImVec2(5, 0), window->DC.CursorPos + ImVec2(w, label_size.y));
const bool hovered = ImGui::ItemHoverable(frame_bb, id);
if (hovered)
@ -364,28 +489,28 @@ bool SliderCustom(const char* label, ImVec4 color, int* v, int v_min, int v_max,
if (!format)
format = "%d";
bool start_text_input = false;
const bool tab_focus_requested = ImGui::FocusableItemRegister(window, g.ActiveId == id);
if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]))
{
ImGui::SetActiveID(id, window);
ImGui::FocusWindow(window);
if (tab_focus_requested || g.IO.KeyCtrl)
{
start_text_input = true;
g.ScalarAsInputTextId = 0;
}
}
if (start_text_input || (g.ActiveId == id && g.ScalarAsInputTextId == id))
return ImGui::InputScalarAsWidgetReplacement(frame_bb, id, label, ImGuiDataType_S32, v, format);
char value_buf[64];
const char* value_buf_end = value_buf + ImFormatString(value_buf, IM_ARRAYSIZE(value_buf), format, *v);
const bool value_changed = SliderCustomBehavior(frame_bb, id, v, v_min, v_max, power, ImGuiSliderFlags_None, color, ImGui::CalcTextSize(value_buf, NULL, true), value_buf_end, value_buf);
const bool value_changed = SeekBarBehavior(frame_bb, id, v, v_min, v_max, power, ImGuiSliderFlags_None, color, ImGui::CalcTextSize(value_buf, NULL, true), value_buf_end, value_buf);
if (label_size.x > 0.0f)
ImGui::RenderText(ImVec2(frame_bb.Min.x + style.ItemInnerSpacing.x, frame_bb.Min.y + 25), label);
return value_changed;
}
bool VolumeBar(const char* label, ImVec4 color, int* v, int v_min, int v_max, float power)
{
ImGuiWindow* window = ImGui::GetCurrentWindow();
if (window->SkipItems)
return false;
const ImGuiID id = window->GetID(label);
const ImRect frame_bb(window->DC.CursorPos + ImVec2(0, -6), window->DC.CursorPos + ImVec2(50, 5));
const bool hovered = ImGui::ItemHoverable(frame_bb, id);
if (hovered) {
ImGui::SetHoveredID(id);
}
const bool value_changed =
VolumeBarBehavior(frame_bb, id, v, v_min, v_max, power, ImGuiSliderFlags_None, color);
return value_changed;
}
@ -421,9 +546,8 @@ void DrawSlippiPlaybackControls()
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoBackground |
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing))
{
ImGui::PushItemWidth(ImGui::GetWindowWidth());
ImGui::SetCursorPos(ImVec2(0.0f, ImGui::GetWindowHeight() - 44));
if (SliderCustom("", ImVec4(1.0f, 0.0f, 0.0f, 1.0f), &frame, Slippi::PLAYBACK_FIRST_SAVE, g_playbackStatus->lastFrame, 1.0, "%d")) {
if (SeekBar("SlippiSeek", ImVec4(1.0f, 0.0f, 0.0f, 1.0f), &frame, Slippi::PLAYBACK_FIRST_SAVE, g_playbackStatus->lastFrame, 1.0, "%d")) {
INFO_LOG(SLIPPI, "seeking to %d", g_playbackStatus->targetFrameNum);
Host_PlaybackSeek();
}
@ -443,7 +567,17 @@ void DrawSlippiPlaybackControls()
Host_PlaybackSeek();
}
}
ImGui::SameLine(0.0f, 0.0f);
if (ImGui::IsItemHovered()) {
ImGui::GetWindowDrawList()->AddRectFilled(
ImVec2(6.0f, ImGui::GetWindowHeight() - 62.0f),
ImVec2(175.0f, ImGui::GetWindowHeight() - 42.0f),
ImGui::ColorConvertFloat4ToU32(ImVec4(0.0f, 0.0f, 0.0f, 0.9f)));
ImGui::SetCursorPos(ImVec2(8.0f, ImGui::GetWindowHeight() - 60.0f));
ImGui::Text("Jump Back (Shift + Left Arrow)");
}
// Step back
ImGui::SetCursorPos(ImVec2(32.0f, ImGui::GetWindowHeight() - 30));
if (ButtonCustom(ICON_FA_STEP_BACKWARD, ImVec2(32.0f, 32.0f))) {
INFO_LOG(SLIPPI, "step back");
if (g_playbackStatus->targetFrameNum == INT_MAX) {
@ -451,7 +585,17 @@ void DrawSlippiPlaybackControls()
Host_PlaybackSeek();
}
}
ImGui::SameLine(0.0f, 0.0f);
if (ImGui::IsItemHovered()) {
ImGui::GetWindowDrawList()->AddRectFilled(
ImVec2(6.0f, ImGui::GetWindowHeight() - 62.0f),
ImVec2(131.0f, ImGui::GetWindowHeight() - 42.0f),
ImGui::ColorConvertFloat4ToU32(ImVec4(0.0f, 0.0f, 0.0f, 0.9f)));
ImGui::SetCursorPos(ImVec2(8.0f, ImGui::GetWindowHeight() - 60.0f));
ImGui::Text("Step Back (Left Arrow)");
}
// Step forward
ImGui::SetCursorPos(ImVec2(64.0f, ImGui::GetWindowHeight() - 30));
if (ButtonCustom(ICON_FA_STEP_FORWARD, ImVec2(32.0f, 32.0f))) {
INFO_LOG(SLIPPI, "step forward");
if (g_playbackStatus->targetFrameNum == INT_MAX) {
@ -459,7 +603,17 @@ void DrawSlippiPlaybackControls()
Host_PlaybackSeek();
}
}
ImGui::SameLine(0.0f, 0.0f);
if (ImGui::IsItemHovered()) {
ImGui::GetWindowDrawList()->AddRectFilled(
ImVec2(12.0f, ImGui::GetWindowHeight() - 62.0f),
ImVec2(162.0f, ImGui::GetWindowHeight() - 42.0f),
ImGui::ColorConvertFloat4ToU32(ImVec4(0.0f, 0.0f, 0.0f, 0.9f)));
ImGui::SetCursorPos(ImVec2(14.0f, ImGui::GetWindowHeight() - 60.0f));
ImGui::Text("Step Forward (Right Arrow)");
}
// Jump forward
ImGui::SetCursorPos(ImVec2(96.0f, ImGui::GetWindowHeight() - 30));
if (ButtonCustom(ICON_FA_FAST_FORWARD, ImVec2(32.0f, 32.0f))) {
INFO_LOG(SLIPPI, "fast_foward");
if (g_playbackStatus->targetFrameNum == INT_MAX) {
@ -467,20 +621,43 @@ void DrawSlippiPlaybackControls()
Host_PlaybackSeek();
}
}
ImGui::SameLine(ImGui::GetWindowWidth() - 64.0f);
if (ImGui::IsItemHovered()) {
ImGui::GetWindowDrawList()->AddRectFilled(
ImVec2(30.0f, ImGui::GetWindowHeight() - 62.0f),
ImVec2(222.0f, ImGui::GetWindowHeight() - 42.0f),
ImGui::ColorConvertFloat4ToU32(ImVec4(0.0f, 0.0f, 0.0f, 0.9f)));
ImGui::SetCursorPos(ImVec2(32.0f, ImGui::GetWindowHeight() - 60.0f));
ImGui::Text("Jump Forward (Shift + Right Arrow)");
}
// Volume
static bool isIconHovered = false;
static bool isVolumeVisible = false;
int* volume = &SConfig::GetInstance().m_Volume;
static int prev;
ImGui::SetCursorPos(ImVec2(128.0f, ImGui::GetWindowHeight() - 30));
if (ButtonCustom(*volume == 0 ? ICON_FA_VOLUME_OFF : ICON_FA_VOLUME_UP, ImVec2(32.0f, 32.0f))) {
INFO_LOG(SLIPPI, "muting");
if (*volume == 0) {
*volume = prev == 0 ? 30 : prev; // todo: find good default value
}
else {
prev = *volume;
*volume = 0;
}
AudioCommon::UpdateSoundStream();
}
ImGui::SetCursorPos(ImVec2(160.0f, ImGui::GetWindowHeight() - 15));
if (VolumeBar("SlippiVolume", ImVec4(1.0f, 0.0f, 0.0f, 1.0f), volume, 0, 100, 1.0)) {
AudioCommon::UpdateSoundStream();
}
// Help
ImGui::SetCursorPos(ImVec2(ImGui::GetWindowWidth() - 64.0f, ImGui::GetWindowHeight() - 30));
if (ButtonCustom(ICON_FA_QUESTION_CIRCLE, ImVec2(32.0f, 32.0f))) {
showHelp = !showHelp;
}
ImGui::SameLine(ImGui::GetWindowWidth() - 32.0f);
if (ButtonCustom(ICON_FA_EXPAND, ImVec2(32.0f, 32.0f))) {
INFO_LOG(SLIPPI, "fullscreen");
Host_Fullscreen();
}
if (g_playbackStatus->isHardFFW) {
INFO_LOG(SLIPPI, "Ffw");
}
if (showHelp) {
ImGui::GetWindowDrawList()->AddRectFilled(
ImVec2(ImGui::GetWindowWidth() - 300.0f, ImGui::GetWindowHeight() - 200.0f),
@ -501,11 +678,34 @@ void DrawSlippiPlaybackControls()
ImGui::SetCursorPos(ImVec2(ImGui::GetWindowWidth() - 290.0f, ImGui::GetWindowHeight() - 70.0f));
ImGui::Text("Big jumps/seeks may take several seconds.");
}
if (ImGui::IsItemHovered()) {
ImGui::GetWindowDrawList()->AddRectFilled(
ImVec2(ImGui::GetWindowWidth() - 75.0f, ImGui::GetWindowHeight() - 62.0f),
ImVec2(ImGui::GetWindowWidth() - 16.0f, ImGui::GetWindowHeight() - 42.0f),
ImGui::ColorConvertFloat4ToU32(ImVec4(0.0f, 0.0f, 0.0f, 0.9f)));
ImGui::SetCursorPos(ImVec2(ImGui::GetWindowWidth() - 73.0f, ImGui::GetWindowHeight() - 60.0f));
ImGui::Text("View Help");
}
// Fullscreen
ImGui::SetCursorPos(ImVec2(ImGui::GetWindowWidth() - 32.0f, ImGui::GetWindowHeight() - 30));
if (ButtonCustom(ICON_FA_EXPAND, ImVec2(32.0f, 32.0f))) {
INFO_LOG(SLIPPI, "fullscreen");
Host_Fullscreen();
}
if (ImGui::IsItemHovered()) {
ImGui::GetWindowDrawList()->AddRectFilled(
ImVec2(ImGui::GetWindowWidth() - 172.0f, ImGui::GetWindowHeight() - 62.0f),
ImVec2(ImGui::GetWindowWidth() - 6.0f, ImGui::GetWindowHeight() - 42.0f),
ImGui::ColorConvertFloat4ToU32(ImVec4(0.0f, 0.0f, 0.0f, 0.9f)));
ImGui::SetCursorPos(ImVec2(ImGui::GetWindowWidth() - 170.0f, ImGui::GetWindowHeight() - 60.0f));
ImGui::Text("Toggle Fullscreen (Alt + Enter)");
}
ImGui::PopStyleVar();
ImGuiWindow* window = ImGui::GetCurrentWindow();
ImGui::SetCursorPos(ImVec2(135.0f, window->DC.CursorPosPrevLine.y + 6.0f));
// Time text
ImGui::SetCursorPos(ImVec2(220.0f, ImGui::GetWindowHeight() - 23.5f));
auto playbackTime = GetTimeForFrame(g_playbackStatus->currentPlaybackFrame);
auto endTime = GetTimeForFrame(g_playbackStatus->lastFrame);
auto timeString = playbackTime + " / " + endTime;