diff --git a/src/xrEngine/xr_level_controller.cpp b/src/xrEngine/xr_level_controller.cpp index 35aadce11d1..cf5815ccf1f 100644 --- a/src/xrEngine/xr_level_controller.cpp +++ b/src/xrEngine/xr_level_controller.cpp @@ -1036,7 +1036,7 @@ class CCC_DefControls : public CCC_UnBindAll // Talk: { kTALK_SWITCH_TO_TRADE, { SDL_SCANCODE_X, SDL_SCANCODE_UNKNOWN, XR_CONTROLLER_BUTTON_X } }, - { kTALK_LOG_SCROLL, { SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, XR_CONTROLLER_AXIS_RIGHT } }, + { kTALK_LOG_SCROLL, { SDL_SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN, XR_CONTROLLER_AXIS_LEFT } }, { kTALK_LOG_SCROLL_UP, { SDL_SCANCODE_E, SDL_SCANCODE_PAGEUP, XR_CONTROLLER_AXIS_TRIGGER_LEFT } }, { kTALK_LOG_SCROLL_DOWN, { SDL_SCANCODE_Q, SDL_SCANCODE_PAGEDOWN, XR_CONTROLLER_AXIS_TRIGGER_RIGHT } }, diff --git a/src/xrGame/ui/UITalkDialogWnd.cpp b/src/xrGame/ui/UITalkDialogWnd.cpp index 57f78d2490c..3b41ccf368d 100644 --- a/src/xrGame/ui/UITalkDialogWnd.cpp +++ b/src/xrGame/ui/UITalkDialogWnd.cpp @@ -345,6 +345,89 @@ void CUITalkDialogWnd::TryScrollAnswersList(bool down) UIAnswersList->ScrollBar()->TryScrollInc(); } +void CUITalkDialogWnd::FocusOnNextQuestion(bool next, bool loop) const +{ + auto& focus = UI().Focus(); + + const auto focused = focus.GetFocused(); + + if (auto questionItem = focused ? dynamic_cast(focused->GetParent()) : nullptr) + { + const Fvector2 vec = focused->GetAbsoluteCenterPos(); + const auto direction = next ? FocusDirection::Down : FocusDirection::Up; + const auto [target, direct] = focus.FindClosestFocusable(vec, direction); + + questionItem = target ? dynamic_cast(target->GetParent()) : nullptr; + + if (questionItem) + { + focus.SetFocused(target); + GetUICursor().WarpToWindow(target); + } + else if (loop) + { + if (next) + FocusOnFirstQuestion(); + else + FocusOnLastQuestion(); + } + return; + } + + // Failed to find something, let's try first + FocusOnFirstQuestion(); +} + +void CUITalkDialogWnd::FocusOnFirstQuestion() const +{ + const auto questions = UIQuestionsList->Items(); + if (questions.empty()) + return; + + const auto questionItem = dynamic_cast(questions.front()); + if (!questionItem) + return; + + UI().Focus().SetFocused(questionItem->m_text); + UI().GetUICursor().WarpToWindow(questionItem->m_text); +} + +void CUITalkDialogWnd::FocusOnLastQuestion() const +{ + const auto questions = UIQuestionsList->Items(); + if (questions.empty()) + return; + + const auto questionItem = dynamic_cast(questions.back()); + if (!questionItem) + return; + + UI().Focus().SetFocused(questionItem->m_text); + UI().GetUICursor().WarpToWindow(questionItem->m_text); +} + +bool CUITalkDialogWnd::OnKeyboardAction(int dik, EUIMessages keyboard_action) +{ + if (CUIWindow::OnKeyboardAction(dik, keyboard_action)) + return true; + + if (keyboard_action == WINDOW_KEY_PRESSED) + { + const auto focused = UIQuestionsList->CursorOverWindow() ? UI().Focus().GetFocused() : nullptr; + + if (focused && IsBinded(kUI_ACCEPT, dik, EKeyContext::UI)) + { + if (const auto questionItem = dynamic_cast(focused->GetParent())) + { + questionItem->OnTextClicked(nullptr, nullptr); + return true; + } + } + } + + return false; +} + void CUIQuestionItem::SendMessage(CUIWindow* pWnd, s16 msg, void* pData) { CUIWndCallback::OnEvent(pWnd, msg, pData); } CUIQuestionItem::CUIQuestionItem(CUIXml* xml_doc, LPCSTR path) : CUIWindow("CUIQuestionItem") diff --git a/src/xrGame/ui/UITalkDialogWnd.h b/src/xrGame/ui/UITalkDialogWnd.h index 32111499ef4..ace31438e26 100644 --- a/src/xrGame/ui/UITalkDialogWnd.h +++ b/src/xrGame/ui/UITalkDialogWnd.h @@ -69,6 +69,11 @@ class CUITalkDialogWnd final : public CUIWindow, public CUIWndCallback void UpdateButtonsLayout(bool b_disable_break, bool trade_enabled); void TryScrollAnswersList(bool down); + void FocusOnNextQuestion(bool next, bool loop) const; + void FocusOnFirstQuestion() const; + void FocusOnLastQuestion() const; + + bool OnKeyboardAction(int dik, EUIMessages keyboard_action) override; private: // List of questions we can ask the character diff --git a/src/xrGame/ui/UITalkWnd.cpp b/src/xrGame/ui/UITalkWnd.cpp index a61f9164896..42bd00bb90a 100644 --- a/src/xrGame/ui/UITalkWnd.cpp +++ b/src/xrGame/ui/UITalkWnd.cpp @@ -139,6 +139,9 @@ void CUITalkWnd::UpdateQuestions() UpdateQuestions(); } } + + UITalkDialogWnd->FocusOnFirstQuestion(); + m_bNeedToUpdateQuestions = false; } @@ -355,9 +358,8 @@ bool CUITalkWnd::OnKeyboardAction(int dik, EUIMessages keyboard_action) return true; } } - switch (GetBindedAction(dik, EKeyContext::Talk)) + else if (IsBinded(kTALK_SWITCH_TO_TRADE, dik, EKeyContext::Talk)) { - case kTALK_SWITCH_TO_TRADE: if (!m_pOthersInvOwner->NeedOsoznanieMode()) { if (UITalkDialogWnd->mechanic_mode) @@ -366,7 +368,6 @@ bool CUITalkWnd::OnKeyboardAction(int dik, EUIMessages keyboard_action) SwitchToTrade(); return true; } - break; } } else if (keyboard_action == WINDOW_KEY_HOLD) @@ -375,27 +376,68 @@ bool CUITalkWnd::OnKeyboardAction(int dik, EUIMessages keyboard_action) { case kTALK_LOG_SCROLL_UP: UITalkDialogWnd->TryScrollAnswersList(false); - break; + return true; case kTALK_LOG_SCROLL_DOWN: UITalkDialogWnd->TryScrollAnswersList(true); - break; + return true; } } + + if (keyboard_action == WINDOW_KEY_PRESSED || keyboard_action == WINDOW_KEY_HOLD) + { + switch (GetBindedAction(dik, EKeyContext::UI)) + { + case kUI_MOVE_LEFT: + case kUI_MOVE_RIGHT: + // Suppress focus system activation + return true; + + case kUI_MOVE_UP: + UITalkDialogWnd->FocusOnNextQuestion(false, keyboard_action != WINDOW_KEY_HOLD); + return true; + + case kUI_MOVE_DOWN: + UITalkDialogWnd->FocusOnNextQuestion(true, keyboard_action != WINDOW_KEY_HOLD); + return true; + } // switch (GetBindedAction(dik, EKeyContext::UI)) + } + return inherited::OnKeyboardAction(dik, keyboard_action); } bool CUITalkWnd::OnControllerAction(int axis, float x, float y, EUIMessages controller_action) { - if (controller_action == WINDOW_KEY_PRESSED) + if (controller_action == WINDOW_KEY_HOLD) { switch (GetBindedAction(axis, EKeyContext::Talk)) { - default: - return OnKeyboardAction(axis, controller_action); case kTALK_LOG_SCROLL: + if (y > 0) + UITalkDialogWnd->TryScrollAnswersList(false); + else + UITalkDialogWnd->TryScrollAnswersList(true); return true; } } + + if (controller_action == WINDOW_KEY_PRESSED || controller_action == WINDOW_KEY_HOLD) + { + switch (GetBindedAction(axis, EKeyContext::UI)) + { + case kUI_MOVE_LEFT: + case kUI_MOVE_RIGHT: + // Suppress focus system activation + return true; + + case kUI_MOVE: + if (y > 0) + UITalkDialogWnd->FocusOnNextQuestion(true, controller_action != WINDOW_KEY_HOLD); + else + UITalkDialogWnd->FocusOnNextQuestion(false, controller_action != WINDOW_KEY_HOLD); + return true; + } // switch (GetBindedAction(axis, EKeyContext::UI)) + } + return inherited::OnControllerAction(axis, x, y, controller_action); }