imgui icon indicating copy to clipboard operation
imgui copied to clipboard

Gamepad friendly reorderable list?

Open wn2000 opened this issue 1 year ago • 3 comments

Version/Branch of Dear ImGui:

Version 1.89.7

Back-ends:

imgui_impl_sdl2.cpp + imgui_impl_sdlrenderer2.cpp

Compiler, OS:

Linux gcc

Full config/build information:

No response

Details:

I need to display a list of items (text entries), where the user can change their order to indicate priorities.

The application is a retro game frontend, so normally there's no mouse involved and it's purely operated by a gamepad.

The expected behavior of the UI is as the following:

  • User can use Up/Down dpad to scroll through the list of items.
  • User can press the A button to highlight an item.
  • Once highlighted, subsequent Up/Down presses move the highlighted item to change its order among the list. This is similar to dragging the item in a desktop UI.
  • User can press the A button again to de-highlight the item. Subsequent Up/Down presses then resume scrolling the list.

Any suggestion or pseudo code to help me get started? Thanks in advance!

Screenshots/Video:

No response

Minimal, Complete and Verifiable Example code:

No response

wn2000 avatar Jan 16 '24 05:01 wn2000

You can use ImGuiWindowFlags_NoNavInputs to disable the default navigation and implement a custom one. Useful functions are ImGui::IsKeyPressed(), ImGui::SetKeyboardFocusHere() and ImGui::SetScrollHereY().

GamingMinds-DanielC avatar Jan 16 '24 09:01 GamingMinds-DanielC

Presumably at some point you would want the same menu to be usable with gamepad, with elements activable instead of allowing to reorder? So you would need some kind of state, e.g. pressing a Config button sets a mode.

When this mode is active:

  • You may set ImGuiWindowFlags_NoNavInputs on the window.
  • (I was going to suggest an alternative, to do something like if (g.NavWindow == g.CurrentWindow && NavMoveRequestButNoResultYet()) NavMoveRequestCancel() to disable ongoing nav requests, but that wouldn't catch e.g. activation requests.
  • Then you can decide if you want your manual up/down system to work using Nav variable, aka use IsItemFocused() and FocusItem(). The public API SetKeyboardFocusHere() is very similar to FocusItem(), it does activate input field + has an extra param but ultimately FocusItem() is likely all your need. OR you might decide to completely bypass it, if your widget don't query Nav data you could technically maintain current index yourself etc. But it may be nicer to use Nav system.

Pseudo-code would be:

static ImGuiID g_MovingItemID = 0;
[...]
YourItem(); // Would highlight when id == g.NavID, and highlight differently when id == g_MovingItemID for moving.
ImGuiID item_id = GetItemID();
if (g_MovingItemID == 0 && IsItemFocused() && IsKeyPressed(ImGuiKey_NavGamepadActivate))
   g_MovingItemID = item_id;
else if (g_MovingItemID == item_id && IsKeyPressed(ImGuiKey_GamepadDpadUp))
{
   ...
}
if (g_MovingItemID != 0)
{
    // Display on-screen help about pressing UP/DOWN to re-order, A to finish, B to cancel etc.
}

ocornut avatar Jan 16 '24 10:01 ocornut

Thanks a lot for the help. I will experiment with the ideas.

wn2000 avatar Jan 17 '24 07:01 wn2000