Skip to content

Commit

Permalink
CUIScrollView: added own gamepad navigation code (#943)
Browse files Browse the repository at this point in the history
Currently disabled due to problems when CUITabControl is being in the
CUIScrollView. CUITabControl needs its own navigation code to be
implemented too.
Navigation based on the focus system works better in this case.
  • Loading branch information
Xottab-DUTY committed Jan 15, 2025
1 parent 8d087cd commit 105d53d
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 0 deletions.
120 changes: 120 additions & 0 deletions src/xrUICore/ScrollView/UIScrollView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,46 @@ bool CUIScrollView::OnMouseAction(float x, float y, EUIMessages mouse_action)
return res;
}

bool CUIScrollView::OnKeyboardAction(int dik, EUIMessages keyboard_action)
{
if (inherited::OnKeyboardAction(dik, keyboard_action))
return true;

/*if (CursorOverWindow() && keyboard_action == WINDOW_KEY_PRESSED)
{
switch (GetBindedAction(dik, EKeyContext::UI))
{
case kUI_MOVE_UP:
return SelectNext(false, false);
case kUI_MOVE_DOWN:
return SelectNext(true, false);
}
}*/

return false;
}

bool CUIScrollView::OnControllerAction(int axis, float x, float y, EUIMessages controller_action)
{
if (inherited::OnControllerAction(axis, x, y, controller_action))
return true;

/*if (CursorOverWindow())
{
if (IsBinded(kUI_MOVE, axis, EKeyContext::UI))
{
if (fis_zero(x))
{
if (y > 0)
return SelectNext(true, false);
return SelectNext(false, false);
}
}
}*/

return false;
}

int CUIScrollView::GetMinScrollPos() const { return m_VScrollBar->GetMinRange(); }
int CUIScrollView::GetMaxScrollPos() const { return m_VScrollBar->GetMaxRange(); }
int CUIScrollView::GetCurrentScrollPos() const { return m_VScrollBar->GetScrollPos(); }
Expand Down Expand Up @@ -409,6 +449,86 @@ void CUIScrollView::SetSelected(CUIWindow* w)
}
}

bool CUIScrollView::SelectNext(bool next, bool loop)
{
if (Empty())
return false;

auto& focus = UI().Focus();

bool found = false; // iterator of the current selected item found
CUIWindow* item = nullptr; // item to be selected

CUIWindow* currentSelected = nullptr;
if (!m_flags.test(eItemsSelectabe) && focus.GetFocused())
currentSelected = focus.GetFocused()->GetWindowBeforeParent(m_pad);

// Iterate forward or backward
auto it = next ? Items().cbegin() : Items().cend() - 1;
const auto ite = next ? Items().cend() : Items().cbegin() - 1;

while (it != ite)
{
if (found)
{
item = *it;
break;
}

if (m_flags.test(eItemsSelectabe))
{
if (smart_cast<CUISelectable*>(*it)->GetSelected())
{
found = true;
currentSelected = *it;
}
}
else if (*it == currentSelected)
found = true;

next ? ++it : --it;
}

// If no item is selected, always select first
if (!found)
{
item = Items().front();
}
// Found current selected, but it is last
else if (!item && loop)
{
item = next ? Items().front() : Items().back();
}

if (item)
{
// Update CUIScrollView native logic
ScrollToWindow(item);
if (m_flags.test(eItemsSelectabe))
item->OnMouseDown(MOUSE_1);

// Update focus system:
// Set item as focused, if possible
if (focus.IsRegistered(item))
focus.SetFocused(item);
else
{
// Set any suitable child as focused
item->ProcessFunctor([&](const CUIWindow* wnd)
{
if (focus.IsRegistered(wnd))
{
focus.SetFocused(wnd);
return true;
}
return false;
});
}
return true;
}
return false;
}

CUIWindow* CUIScrollView::GetSelected()
{
if (!m_flags.test(eItemsSelectabe))
Expand Down
3 changes: 3 additions & 0 deletions src/xrUICore/ScrollView/UIScrollView.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class XRUICORE_API CUIScrollView : public CUIWindow, public CUIWndCallback
void InitScrollView(); // need parent to be initialized
virtual void SendMessage(CUIWindow* pWnd, s16 msg, void* pData = NULL);
virtual bool OnMouseAction(float x, float y, EUIMessages mouse_action);
bool OnKeyboardAction(int dik, EUIMessages keyboard_action) override;
bool OnControllerAction(int axis, float x, float y, EUIMessages controller_action) override;
virtual void Draw();
virtual void Update();
void AddWindow(CUIWindow* pWnd, bool auto_delete);
Expand All @@ -68,6 +70,7 @@ class XRUICORE_API CUIScrollView : public CUIWindow, public CUIWndCallback
void SetFixedScrollBar(bool b);
float GetDesiredChildWidth() const;
virtual void SetSelected(CUIWindow*);
bool SelectNext(bool next, bool loop);
CUIWindow* GetSelected();
Fvector2 GetPadSize();
void ForceUpdate();
Expand Down
16 changes: 16 additions & 0 deletions src/xrUICore/Windows/UIWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@ class XRUICORE_API CUIWindow : public CUISimpleWindow, public CUIDebuggable
return nullptr;
}

template <typename F>
void ProcessFunctor(const F& functor) const
{
static_assert(std::is_invocable_r_v<bool, F, CUIWindow*>);

for (auto it = m_ChildWndList.rbegin(); it != m_ChildWndList.rend(); ++it)
{
if (!(*it)->IsEnabled())
continue;

if (functor(*it))
break;
(*it)->ProcessFunctor(functor);
}
}

//получить окно самого верхнего уровня
[[nodiscard]]
CUIWindow* GetTop()
Expand Down

0 comments on commit 105d53d

Please sign in to comment.