mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
overlay: fix Options tab contents jitter (#751)
## Link to GitHub Issue or related Pull Request, if one exists #747 ## Description of change The old approach called ImGui’s `SetScrollHereY()` while the options list was still being laid out. That caused one-frame scroll corrections and edge-snap jitter near scroll boundaries. The new approach in `build_options_tab()`: 1. **On click** - set a flag (`options_scroll_pending` for categories, `options_scroll_top` for group headers). 2. **During layout** - when building the target category, record its content position with `GetCursorPosY()` (don’t scroll yet). 3. **After all options are built** - apply scroll once by setting `window->Scroll.y` directly, and only if the position actually needs to change (0.5px threshold). That deferred, single-pass scroll avoids the shake while still supporting scroll-up, scroll-down, and re-click-to-recenter. ## Testing In spicecfg.exe and in-game overlay, Options tab: Open groups with many categories Scroll content down manually, then click a higher category in the left nav - content scrolls up to that section Re-click the same category after manual scroll - jumps back without shake Rapid re-clicks when already aligned - no jitter Switch group headers - still scrolls to top; re-click at top - no shake
This commit is contained in:
@@ -406,19 +406,18 @@ namespace overlay::windows {
|
||||
|
||||
// content: only the options belonging to the selected group.
|
||||
ImGui::BeginChild("OptionsContent", ImVec2(0, content_height), false);
|
||||
if (this->options_scroll_top) {
|
||||
ImGui::SetScrollY(0.0f);
|
||||
this->options_scroll_top = false;
|
||||
}
|
||||
|
||||
const bool scroll_to_top = this->options_scroll_top;
|
||||
this->options_scroll_top = false;
|
||||
float scroll_to_category_y = -1.0f;
|
||||
|
||||
// breathing room at the top of the content area
|
||||
ImGui::Dummy(ImVec2(0.0f, overlay::apply_scaling(4)));
|
||||
|
||||
// when a category was clicked in the nav, scroll the content to its section
|
||||
auto scroll_anchor = [this](const std::string &category) {
|
||||
// when a category was clicked in the nav, record its Y for deferred scroll
|
||||
auto scroll_anchor = [this, &scroll_to_category_y](const std::string &category) {
|
||||
if (this->options_scroll_pending && this->options_category_selected == category) {
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
ImGui::SetScrollHereY(0.0f);
|
||||
scroll_to_category_y = ImGui::GetCursorPosY();
|
||||
this->options_scroll_pending = false;
|
||||
}
|
||||
};
|
||||
@@ -474,6 +473,23 @@ namespace overlay::windows {
|
||||
}
|
||||
}
|
||||
|
||||
// apply scroll after content layout to avoid mid-layout jitter
|
||||
ImGuiWindow *content_window = ImGui::GetCurrentWindow();
|
||||
if (scroll_to_top) {
|
||||
if (content_window->Scroll.y > 0.0f) {
|
||||
content_window->Scroll.y = 0.0f;
|
||||
}
|
||||
content_window->ScrollTarget.y = FLT_MAX;
|
||||
} else if (scroll_to_category_y >= 0.0f) {
|
||||
const float spacing_y = ImMax(
|
||||
content_window->WindowPadding.y, ImGui::GetStyle().ItemSpacing.y);
|
||||
const float desired_scroll = ImMax(0.0f, scroll_to_category_y - spacing_y);
|
||||
if (fabsf(content_window->Scroll.y - desired_scroll) > 0.5f) {
|
||||
content_window->Scroll.y = desired_scroll;
|
||||
}
|
||||
content_window->ScrollTarget.y = FLT_MAX;
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user