mirror of
https://github.com/stenzek/duckstation.git
synced 2024-11-23 05:49:43 +00:00
ImGuiFullscreen: Allow smooth scrolling
This commit is contained in:
parent
e93dea5ad8
commit
891d5cefbe
@ -5,8 +5,8 @@
|
||||
<ClInclude Include="include\imconfig.h" />
|
||||
<ClInclude Include="include\imgui.h" />
|
||||
<ClInclude Include="include\imgui_freetype.h" />
|
||||
<ClInclude Include="include\imgui_internal.h" />
|
||||
<ClInclude Include="include\imgui_stdlib.h" />
|
||||
<ClInclude Include="src\imgui_internal.h" />
|
||||
<ClInclude Include="src\imstb_rectpack.h" />
|
||||
<ClInclude Include="src\imstb_textedit.h" />
|
||||
<ClInclude Include="src\imstb_truetype.h" />
|
||||
|
@ -3,12 +3,12 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\imconfig.h" />
|
||||
<ClInclude Include="include\imgui.h" />
|
||||
<ClInclude Include="src\imgui_internal.h" />
|
||||
<ClInclude Include="src\imstb_rectpack.h" />
|
||||
<ClInclude Include="src\imstb_textedit.h" />
|
||||
<ClInclude Include="src\imstb_truetype.h" />
|
||||
<ClInclude Include="include\imgui_stdlib.h" />
|
||||
<ClInclude Include="include\imgui_freetype.h" />
|
||||
<ClInclude Include="include\imgui_internal.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\imgui_widgets.cpp" />
|
||||
|
@ -1717,6 +1717,7 @@ enum ImGuiStyleVar_
|
||||
ImGuiStyleVar_SeparatorTextBorderSize, // float SeparatorTextBorderSize
|
||||
ImGuiStyleVar_SeparatorTextAlign, // ImVec2 SeparatorTextAlign
|
||||
ImGuiStyleVar_SeparatorTextPadding, // ImVec2 SeparatorTextPadding
|
||||
ImGuiStyleVar_ScrollSmooth, // float ScrollSmooth
|
||||
ImGuiStyleVar_COUNT
|
||||
};
|
||||
|
||||
@ -2180,6 +2181,8 @@ struct ImGuiStyle
|
||||
ImGuiHoveredFlags HoverFlagsForTooltipMouse;// Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using mouse.
|
||||
ImGuiHoveredFlags HoverFlagsForTooltipNav; // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using keyboard/gamepad.
|
||||
|
||||
float ScrollSmooth; // Smooth scrolling amount: 1.0f no smoothing. Anything above 1.0f will make the scroll delta more smooth.
|
||||
|
||||
IMGUI_API ImGuiStyle();
|
||||
IMGUI_API void ScaleAllSizes(float scale_factor);
|
||||
};
|
||||
|
@ -2618,7 +2618,8 @@ struct IMGUI_API ImGuiWindow
|
||||
ImGuiID MoveId; // == window->GetID("#MOVE")
|
||||
ImGuiID ChildId; // ID of corresponding item in parent window (for navigation to return from child window to parent window)
|
||||
ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling)
|
||||
ImVec2 Scroll;
|
||||
ImVec2 Scroll; // Current Visible Scroll position
|
||||
ImVec2 ScrollExpected; // Current Expected Scroll position
|
||||
ImVec2 ScrollMax;
|
||||
ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change)
|
||||
ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered
|
||||
|
@ -1303,6 +1303,7 @@ ImGuiStyle::ImGuiStyle()
|
||||
HoverDelayNormal = 0.40f; // Delay for IsItemHovered(ImGuiHoveredFlags_DelayNormal). "
|
||||
HoverFlagsForTooltipMouse = ImGuiHoveredFlags_Stationary | ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_AllowWhenDisabled; // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using mouse.
|
||||
HoverFlagsForTooltipNav = ImGuiHoveredFlags_NoSharedDelay | ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_AllowWhenDisabled; // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using keyboard/gamepad.
|
||||
ScrollSmooth = 1.0f; // Disabled by default. It's just immediate jump from ScrollExpected to the visual Scroll.
|
||||
|
||||
// Default theme
|
||||
ImGui::StyleColorsDark(this);
|
||||
@ -3297,6 +3298,7 @@ static const ImGuiDataVarInfo GStyleVarInfo[] =
|
||||
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, SeparatorTextBorderSize)}, // ImGuiStyleVar_SeparatorTextBorderSize
|
||||
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SeparatorTextAlign) }, // ImGuiStyleVar_SeparatorTextAlign
|
||||
{ ImGuiDataType_Float, 2, (ImU32)offsetof(ImGuiStyle, SeparatorTextPadding) }, // ImGuiStyleVar_SeparatorTextPadding
|
||||
{ ImGuiDataType_Float, 1, (ImU32)offsetof(ImGuiStyle, ScrollSmooth) }, // ImGuiStyleVar_ScrollSmooth
|
||||
};
|
||||
|
||||
const ImGuiDataVarInfo* ImGui::GetStyleVarInfo(ImGuiStyleVar idx)
|
||||
@ -3926,6 +3928,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, const char* name) : DrawListInst(NUL
|
||||
IDStack.push_back(ID);
|
||||
MoveId = GetID("#MOVE");
|
||||
ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
|
||||
ScrollExpected = ImVec2(0, 0);
|
||||
ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f);
|
||||
AutoFitFramesX = AutoFitFramesY = -1;
|
||||
AutoPosLastDirection = ImGuiDir_None;
|
||||
@ -9524,7 +9527,7 @@ void ImGui::UpdateMouseWheel()
|
||||
LockWheelingWindow(window, wheel.x);
|
||||
float max_step = window->InnerRect.GetWidth() * 0.67f;
|
||||
float scroll_step = ImTrunc(ImMin(2 * window->CalcFontSize(), max_step));
|
||||
SetScrollX(window, window->Scroll.x - wheel.x * scroll_step);
|
||||
SetScrollX(window, window->ScrollExpected.x - wheel.x * scroll_step);
|
||||
g.WheelingWindowScrolledFrame = g.FrameCount;
|
||||
}
|
||||
if (do_scroll[ImGuiAxis_Y])
|
||||
@ -9532,7 +9535,7 @@ void ImGui::UpdateMouseWheel()
|
||||
LockWheelingWindow(window, wheel.y);
|
||||
float max_step = window->InnerRect.GetHeight() * 0.67f;
|
||||
float scroll_step = ImTrunc(ImMin(5 * window->CalcFontSize(), max_step));
|
||||
SetScrollY(window, window->Scroll.y - wheel.y * scroll_step);
|
||||
SetScrollY(window, window->ScrollExpected.y - wheel.y * scroll_step);
|
||||
g.WheelingWindowScrolledFrame = g.FrameCount;
|
||||
}
|
||||
}
|
||||
@ -10761,11 +10764,46 @@ static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window)
|
||||
float snap_max = window->ScrollMax[axis] + window->SizeFull[axis] - decoration_size[axis];
|
||||
scroll_target = CalcScrollEdgeSnap(scroll_target, snap_min, snap_max, window->ScrollTargetEdgeSnapDist[axis], center_ratio);
|
||||
}
|
||||
scroll[axis] = scroll_target - center_ratio * (window->SizeFull[axis] - decoration_size[axis]);
|
||||
window->ScrollExpected[axis] = scroll_target - center_ratio * (window->SizeFull[axis] - decoration_size[axis]);
|
||||
}
|
||||
scroll[axis] = IM_ROUND(ImMax(scroll[axis], 0.0f));
|
||||
|
||||
// Based on https://github.com/ocornut/imgui/pull/7348
|
||||
// TODO: Make it not dependent on frame rate, easiest way would be to multiply by delta_time / (1/60).
|
||||
// Smooth scroll.
|
||||
// Instead use "Scroll" value in the window, all setters that sets the scroll absolutely now points to
|
||||
// "ScrollExpected" Here, we take from ScrollTarget (from some functions like ScrollHere + mouse wheel) to set
|
||||
// the ScrollExpected value Also, Scroll var in window is processed to meet ScrollExpected Value
|
||||
//
|
||||
// The formula is pretty simple to generate a smooth scrolling that can be tweaked just by one float value.
|
||||
//
|
||||
// The Float is "ImGuiStyleVar_ScrollSmooth". Can be set on the style or via PushStyleVar.
|
||||
// A Value of 1.0f is just inmediate (transported from ScrollExpected to Scroll).
|
||||
// A Value higher of 1.0f will make the scrolling smoother.
|
||||
//
|
||||
// The ScrollExpected is also clamped (as previously the "Scroll" value) from 0 to sScrollMax
|
||||
//
|
||||
// The approach is frame bounded and not time bounded.
|
||||
// It should be prefereable use a time bounded approach but this is pretty simple so we don't need to add extra
|
||||
// vars to save a scrolling "start" time to have a delta / deal with posible increments during the scrolling
|
||||
// itself (restar timer) Anyway it should not be complicated to add but this approach is small, simple, can be
|
||||
// user or not and works pretty well
|
||||
//
|
||||
window->ScrollExpected[axis] = IM_ROUND(ImMax(window->ScrollExpected[axis], 0.0f));
|
||||
if (!window->Collapsed && !window->SkipItems)
|
||||
scroll[axis] = ImMin(scroll[axis], window->ScrollMax[axis]);
|
||||
window->ScrollExpected[axis] = ImMin(window->ScrollExpected[axis], window->ScrollMax[axis]);
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiStyle& style = g.Style;
|
||||
if (scroll[axis] != window->ScrollExpected[axis])
|
||||
{
|
||||
const float multiplier = GImGui->IO.DeltaTime / (1.0f / 60.0f);
|
||||
const float diff = window->ScrollExpected[axis] - scroll[axis];
|
||||
if (diff > 0)
|
||||
scroll[axis] += ImMin(diff, (diff / (style.ScrollSmooth * multiplier)));
|
||||
else
|
||||
scroll[axis] -= ImMin(-diff, (-diff / (style.ScrollSmooth * multiplier)));
|
||||
|
||||
scroll[axis] = window->Appearing ? window->ScrollExpected[axis] : scroll[axis];
|
||||
}
|
||||
}
|
||||
return scroll;
|
||||
}
|
||||
@ -10858,13 +10896,13 @@ ImVec2 ImGui::ScrollToRectEx(ImGuiWindow* window, const ImRect& item_rect, ImGui
|
||||
float ImGui::GetScrollX()
|
||||
{
|
||||
ImGuiWindow* window = GImGui->CurrentWindow;
|
||||
return window->Scroll.x;
|
||||
return window->ScrollExpected.x;
|
||||
}
|
||||
|
||||
float ImGui::GetScrollY()
|
||||
{
|
||||
ImGuiWindow* window = GImGui->CurrentWindow;
|
||||
return window->Scroll.y;
|
||||
return window->ScrollExpected.y;
|
||||
}
|
||||
|
||||
float ImGui::GetScrollMaxX()
|
||||
|
@ -933,9 +933,9 @@ void ImGui::Scrollbar(ImGuiAxis axis)
|
||||
}
|
||||
float size_visible = window->InnerRect.Max[axis] - window->InnerRect.Min[axis];
|
||||
float size_contents = window->ContentSize[axis] + window->WindowPadding[axis] * 2.0f;
|
||||
ImS64 scroll = (ImS64)window->Scroll[axis];
|
||||
ImS64 scroll = (ImS64)window->ScrollExpected[axis];
|
||||
ScrollbarEx(bb, id, axis, &scroll, (ImS64)size_visible, (ImS64)size_contents, rounding_corners);
|
||||
window->Scroll[axis] = (float)scroll;
|
||||
window->ScrollExpected[axis] = (float)scroll;
|
||||
}
|
||||
|
||||
// Vertical/Horizontal scrollbar
|
||||
|
@ -571,6 +571,7 @@ bool FullscreenUI::Initialize()
|
||||
return false;
|
||||
|
||||
ImGuiFullscreen::SetTheme(Host::GetBaseBoolSettingValue("Main", "UseLightFullscreenUITheme", false));
|
||||
ImGuiFullscreen::SetSmoothScrolling(Host::GetBaseBoolSettingValue("Main", "FullscreenUISmoothScrolling", true));
|
||||
ImGuiFullscreen::UpdateLayoutScale();
|
||||
|
||||
if (!ImGuiManager::AddFullscreenFontsIfMissing() || !ImGuiFullscreen::Initialize("images/placeholder.png") ||
|
||||
@ -3114,6 +3115,13 @@ void FullscreenUI::DrawInterfaceSettingsPage()
|
||||
ImGuiFullscreen::SetTheme(bsi->GetBoolValue("Main", "UseLightFullscreenUITheme", false));
|
||||
}
|
||||
|
||||
if (DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_LIST, "Smooth Scrolling"),
|
||||
FSUI_CSTR("Enables smooth scrolling of menus in Big Picture UI."), "Main",
|
||||
"FullscreenUISmoothScrolling", true))
|
||||
{
|
||||
ImGuiFullscreen::SetSmoothScrolling(bsi->GetBoolValue("Main", "FullscreenUISmoothScrolling", false));
|
||||
}
|
||||
|
||||
{
|
||||
// Have to do this the annoying way, because it's host-derived.
|
||||
const auto language_list = Host::GetAvailableLanguageList();
|
||||
@ -7381,6 +7389,7 @@ TRANSLATE_NOOP("FullscreenUI", "Enables alignment and bus exceptions. Not needed
|
||||
TRANSLATE_NOOP("FullscreenUI", "Enables an additional 6MB of RAM to obtain a total of 2+6 = 8MB, usually present on dev consoles.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Enables an additional three controller slots on each port. Not supported in all games.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Enables more precise frame pacing at the cost of battery life.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Enables smooth scrolling of menus in Big Picture UI.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Enables the older, less accurate MDEC decoding routines. May be required for old replacement backgrounds to match/load.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Enables the replacement of background textures in supported games.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Encore Mode");
|
||||
@ -7704,6 +7713,7 @@ TRANSLATE_NOOP("FullscreenUI", "Simulates the system ahead of time and rolls bac
|
||||
TRANSLATE_NOOP("FullscreenUI", "Skip Duplicate Frame Display");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Skips the presentation/display of frames that are not unique. Can result in worse frame pacing.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Slow Boot");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Smooth Scrolling");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Smooths out blockyness between colour transitions in 24-bit content, usually FMVs.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Smooths out the blockiness of magnified textures on 2D objects.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Smooths out the blockiness of magnified textures on 3D objects.");
|
||||
|
@ -41,6 +41,7 @@ namespace ImGuiFullscreen {
|
||||
using MessageDialogCallbackVariant = std::variant<InfoMessageDialogCallback, ConfirmMessageDialogCallback>;
|
||||
|
||||
static constexpr float MENU_BACKGROUND_ANIMATION_TIME = 0.5f;
|
||||
static constexpr float SMOOTH_SCROLLING_SPEED = 3.5f;
|
||||
|
||||
static std::optional<RGBA8Image> LoadTextureImage(std::string_view path);
|
||||
static std::shared_ptr<GPUTexture> UploadTexture(std::string_view path, const RGBA8Image& image);
|
||||
@ -90,6 +91,7 @@ static u32 s_menu_button_index = 0;
|
||||
static u32 s_close_button_state = 0;
|
||||
static FocusResetType s_focus_reset_queued = FocusResetType::None;
|
||||
static bool s_light_theme = false;
|
||||
static bool s_smooth_scrolling = false;
|
||||
|
||||
static LRUCache<std::string, std::shared_ptr<GPUTexture>> s_texture_cache(128, true);
|
||||
static std::shared_ptr<GPUTexture> s_placeholder_texture;
|
||||
@ -275,6 +277,11 @@ void ImGuiFullscreen::Shutdown()
|
||||
s_message_dialog_callback = {};
|
||||
}
|
||||
|
||||
void ImGuiFullscreen::SetSmoothScrolling(bool enabled)
|
||||
{
|
||||
s_smooth_scrolling = enabled;
|
||||
}
|
||||
|
||||
const std::shared_ptr<GPUTexture>& ImGuiFullscreen::GetPlaceholderTexture()
|
||||
{
|
||||
return s_placeholder_texture;
|
||||
@ -763,6 +770,7 @@ bool ImGuiFullscreen::BeginFullscreenWindow(const ImVec2& position, const ImVec2
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(padding));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(rounding));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ScrollSmooth, s_smooth_scrolling ? SMOOTH_SCROLLING_SPEED : 1.0f);
|
||||
|
||||
return ImGui::Begin(name, nullptr,
|
||||
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize |
|
||||
@ -772,7 +780,7 @@ bool ImGuiFullscreen::BeginFullscreenWindow(const ImVec2& position, const ImVec2
|
||||
void ImGuiFullscreen::EndFullscreenWindow()
|
||||
{
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar(3);
|
||||
ImGui::PopStyleVar(4);
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
|
@ -120,6 +120,7 @@ ImRect CenterImage(const ImRect& fit_rect, const ImVec2& image_size);
|
||||
bool Initialize(const char* placeholder_image_path);
|
||||
|
||||
void SetTheme(bool light);
|
||||
void SetSmoothScrolling(bool enabled);
|
||||
void SetFonts(ImFont* medium_font, ImFont* large_font);
|
||||
bool UpdateLayoutScale();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user