Skip to content

Commit

Permalink
Proper gamepad interaction in PDA (#943)
Browse files Browse the repository at this point in the history
This is huge. Mainly for the map page, ranking and log pages can be
missing something.
  • Loading branch information
Xottab-DUTY committed Jan 18, 2025
1 parent db86e89 commit dbc8a5c
Show file tree
Hide file tree
Showing 12 changed files with 278 additions and 171 deletions.
1 change: 0 additions & 1 deletion src/xrEngine/key_binding_registrator_script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,6 @@ SCRIPT_EXPORT(KeyBindings, (),
value("kPDA_MAP_SHOW_LEGEND", int(kPDA_MAP_SHOW_LEGEND)),

value("kPDA_FILTER_TOGGLE", int(kPDA_FILTER_TOGGLE)),
value("kPDA_TASKS_TOGGLE", int(kPDA_TASKS_TOGGLE)),

// Talk:
value("kTALK_SWITCH_TO_TRADE", int(kTALK_SWITCH_TO_TRADE)),
Expand Down
2 changes: 0 additions & 2 deletions src/xrEngine/xr_level_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ game_action actions[] =
{ "pda_map_show_legend", kPDA_MAP_SHOW_LEGEND, _sp, EKeyContext::PDA },

{ "pda_filter_toggle", kPDA_FILTER_TOGGLE, _sp, EKeyContext::PDA },
{ "pda_tasks_toggle", kPDA_TASKS_TOGGLE, _sp, EKeyContext::PDA },

// Talk:
{ "talk_switch_to_trade", kTALK_SWITCH_TO_TRADE, _sp, EKeyContext::Talk },
Expand Down Expand Up @@ -1038,7 +1037,6 @@ class CCC_DefControls : public CCC_UnBindAll
{ kPDA_MAP_SHOW_LEGEND, { SDL_SCANCODE_V, SDL_SCANCODE_KP_MULTIPLY, XR_CONTROLLER_BUTTON_INVALID } },

{ kPDA_FILTER_TOGGLE, { SDL_SCANCODE_B, SDL_SCANCODE_UNKNOWN, XR_CONTROLLER_BUTTON_Y } },
{ kPDA_TASKS_TOGGLE, { SDL_SCANCODE_TAB, SDL_SCANCODE_UNKNOWN, XR_CONTROLLER_BUTTON_X } },

// Talk:
{ kTALK_SWITCH_TO_TRADE, { SDL_SCANCODE_X, SDL_SCANCODE_UNKNOWN, XR_CONTROLLER_BUTTON_X } },
Expand Down
1 change: 0 additions & 1 deletion src/xrEngine/xr_level_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,6 @@ enum EGameActions : u32
kPDA_MAP_SHOW_LEGEND,

kPDA_FILTER_TOGGLE,
kPDA_TASKS_TOGGLE,

// Talk:
kTALK_SWITCH_TO_TRADE, // _OR_UPGRADE
Expand Down
208 changes: 115 additions & 93 deletions src/xrGame/ui/UIMapFilters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,10 @@ CUIMapFilters::CUIMapFilters() : CUIWindow("Map locations filters") {}

bool CUIMapFilters::Init(CUIXml& xml)
{
if (!CUIXmlInit::InitWindow(xml, "filters_wnd", 0, this, false))
{
if (const auto parent = GetParent())
{
SetWndPos(parent->GetWndPos());
SetWndSize(parent->GetWndSize());
}
}
bool result = false;

const bool convertPosToOurs = !CUIXmlInit::InitWindow(xml, "filters_wnd", 0, this, false);

constexpr std::tuple<eSpotsFilter, pcstr> filters[] =
{
{ Treasures, "filter_treasures" },
Expand All @@ -28,138 +24,164 @@ bool CUIMapFilters::Init(CUIXml& xml)
{
auto& filter = m_filters[filter_id];
filter = UIHelper::CreateCheck(xml, filter_section, this, false);
if (filter)
if (!filter)
continue;

filter->SetMessageTarget(this);
filter->SetWindowName(filter_section);
filter->SetCheck(true);

result = true;
}

if (result && convertPosToOurs)
{
// Adjust this window rect first
Frect rect{ type_max<float>, type_max<float>, 0, 0 };

for (const auto filter : m_filters)
{
filter->SetMessageTarget(this);
filter->SetWindowName(filter_section);
filter->SetCheck(true);
if (!filter)
continue;
rect.lt.min(filter->GetWndPos());
Frect filterRect;
filter->GetWndRect(filterRect);
rect.rb.max(filterRect.rb);
}

SetWndRect(rect);

// Adjust filters positions
for (const auto filter : m_filters)
{
if (!filter)
continue;
Fvector2 ourAbsPos;
GetAbsolutePos(ourAbsPos);
const Fvector2& pos = filter->GetWndPos();
filter->SetWndPos({ pos.x - ourAbsPos.x, pos.y - ourAbsPos.y });
}
m_filters_state[filter_id] = true;
}

return true;
return result;
}

void CUIMapFilters::Reset()
{
inherited::Reset();
SelectFilter(false);
Activate(false);
}

bool CUIMapFilters::OnKeyboardAction(int dik, EUIMessages keyboard_action)
bool CUIMapFilters::Activate(bool activate)
{
if (const auto filter = GetSelectedFilter())
m_activated = activate;

auto& focus = UI().Focus();
if (activate)
{
if (keyboard_action != WINDOW_KEY_PRESSED)
return true; // intercept all
GetMessageTarget()->SetKeyboardCapture(this, true);
focus.LockToWindow(this);
focus.SetFocused(m_filters[0]);
}
else
{
if (GetMessageTarget()->GetKeyboardCapturer() == this)
GetMessageTarget()->SetKeyboardCapture(nullptr, true);
if (focus.GetLocker() == this)
focus.Unlock();
GetMessageTarget()->SendMessage(GetMessageTarget(), WINDOW_KEYBOARD_CAPTURE_LOST, this);
}
return true;
}

switch (GetBindedAction(dik, EKeyContext::UI))
bool CUIMapFilters::OnKeyboardAction(int dik, EUIMessages keyboard_action)
{
if (!m_activated)
{
if (IsBinded(kPDA_FILTER_TOGGLE, dik, EKeyContext::PDA))
{
case kUI_BACK:
SelectFilter(false);
Activate(true);
return true;
}
return false;
}

case kUI_ACCEPT:
filter->OnMouseDown(MOUSE_1);
return true;
if (inherited::OnKeyboardAction(dik, keyboard_action))
return true;

case kUI_MOVE_LEFT:
case kUI_MOVE_DOWN:
SelectFilter(true, false);
return true;
auto action = GetBindedAction(dik, EKeyContext::UI);
if (action == kNOTBINDED)
action = GetBindedAction(dik);

case kUI_MOVE_RIGHT:
case kUI_MOVE_UP:
SelectFilter(true, true);
return true;
switch (action)
{
case kQUIT:
case kUI_BACK:
Activate(false);
return true;

case kENTER:
case kUI_ACCEPT:
if (keyboard_action == WINDOW_KEY_PRESSED)
{
if (const auto filter = GetSelectedFilter())
filter->OnMouseDown(MOUSE_1);
}
}
return inherited::OnKeyboardAction(dik, keyboard_action);
}
return true;

bool CUIMapFilters::OnControllerAction(int axis, float x, float y, EUIMessages controller_action)
{
switch (GetBindedAction(axis, EKeyContext::UI))
{
default:
return OnKeyboardAction(axis, controller_action);
case kUI_MOVE:
if (GetSelectedFilter())
return true; // just screw it for now
case kUI_ACTION_1:
case kUI_ACTION_2:
return true; // intercept
}
return inherited::OnControllerAction(axis, x, y, controller_action);

return false;
}

void CUIMapFilters::SendMessage(CUIWindow* pWnd, s16 msg, void* pData)
{
// This cycle could be implemented through CUIWndCallback,
// but we don't need it too much here
for (u32 i = 0; i < Filter_Count; ++i)
if (msg == BUTTON_CLICKED)
{
if (m_filters[i] == pWnd && msg == BUTTON_CLICKED)
// This cycle could be implemented through CUIWndCallback,
// but we don't need it too much here
for (const auto filter : m_filters)
{
m_filters_state[i] = m_filters[i]->GetCheck();
GetMessageTarget()->SendMessage(this, PDA_TASK_RELOAD_FILTERS, nullptr);
return;
if (filter == pWnd)
{
GetMessageTarget()->SendMessage(this, PDA_TASK_RELOAD_FILTERS, nullptr);
return;
}
}
}
if (msg == PDA_TASK_SELECT_FILTERS)
else if (msg == WINDOW_KEYBOARD_CAPTURE_LOST && pWnd == GetMessageTarget())
{
SelectFilter(!GetSelectedFilter());
if (m_activated)
Activate(false);
return;
}
if (msg == WINDOW_KEYBOARD_CAPTURE_LOST && pWnd == GetMessageTarget())
else if (msg == WINDOW_FOCUS_LOST && pWnd == this)
{
SelectFilter(false);
return;
}
if (msg == WINDOW_FOCUS_LOST && pWnd == this)
{
SelectFilter(false);
if (m_activated)
Activate(false);
return;
}
inherited::SendMessage(pWnd, msg, pData);
}

CUICheckButton* CUIMapFilters::GetSelectedFilter() const
{
if (m_selected_filter == -1)
return nullptr;
return m_filters[m_selected_filter];
auto focused = UI().Focus().GetFocused();
if (IsChild(focused))
return static_cast<CUICheckButton*>(focused);
return nullptr;
}

void CUIMapFilters::SelectFilter(bool select, bool next /*= true*/)
bool CUIMapFilters::IsFilterEnabled(eSpotsFilter filter) const
{
auto& cursor = GetUICursor();

if (!select)
{
m_selected_filter = -1;
cursor.WarpToWindow(nullptr);
}
else
{
if (next)
{
if (m_selected_filter < int(m_filters.size() - 1))
m_selected_filter++;
else
m_selected_filter = 0;
}
else // prev
{
if (m_selected_filter > 0)
m_selected_filter--;
else
m_selected_filter = int(m_filters.size() - 1);
}
cursor.WarpToWindow(m_filters[m_selected_filter]);
}
return m_filters[filter] && m_filters[filter]->GetCheck();
}

void CUIMapFilters::SetFilterEnabled(eSpotsFilter filter, bool enable)
void CUIMapFilters::SetFilterEnabled(eSpotsFilter filter, bool enable) const
{
m_filters_state[filter] = enable;
if (m_filters[filter])
m_filters[filter]->SetCheck(enable);
}
18 changes: 7 additions & 11 deletions src/xrGame/ui/UIMapFilters.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,29 @@ class CUIMapFilters final : public CUIWindow

private:
std::array<CUICheckButton*, Filter_Count> m_filters{};
std::array<bool, Filter_Count> m_filters_state{};
int m_selected_filter{ -1 };
bool m_activated{};

public:
CUIMapFilters();

bool Init(CUIXml& xml);

pcstr GetDebugType() override { return "CUIMapFilters"; }

void Reset() override;

bool Activate(bool activate);

bool OnKeyboardAction(int dik, EUIMessages keyboard_action) override;
bool OnControllerAction(int axis, float x, float y, EUIMessages controller_action) override;

void SendMessage(CUIWindow* pWnd, s16 msg, void* pData) override;

[[nodiscard]]
bool IsFilterEnabled(eSpotsFilter filter) const
{
return m_filters_state[filter];
}
bool IsFilterEnabled(eSpotsFilter filter) const;

void SetFilterEnabled(eSpotsFilter filter, bool enable) const;

void SetFilterEnabled(eSpotsFilter filter, bool enable);
pcstr GetDebugType() override { return "CUIMapFilters"; }

private:
CUICheckButton* GetSelectedFilter() const;
void SelectFilter(bool select, bool next = true);
};

20 changes: 12 additions & 8 deletions src/xrGame/ui/UIPdaWnd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ void CUIPdaWnd::Init()
}

m_btn_close = UIHelper::Create3tButton(uiXml, "close_button", this);
m_btn_close->SetAccelerator(kQUIT, false, 2);
m_btn_close->SetAccelerator(kUI_BACK, false, 3);
UI().Focus().UnregisterFocusable(m_btn_close);

m_hint_wnd = UIHelper::CreateHint(uiXml, "hint_wnd");

if (IsGameTypeSingle())
Expand Down Expand Up @@ -175,8 +179,6 @@ void CUIPdaWnd::SendMessage(CUIWindow* pWnd, s16 msg, void* pData)
{
const auto& id = UITabControl->GetActiveId();
SetActiveSubdialog(id);
if (pInput->IsCurrentInputTypeController())
UI().GetUICursor().WarpToWindow(UITabControl->GetButtonById(id));
}
break;
}
Expand Down Expand Up @@ -249,6 +251,7 @@ void CUIPdaWnd::SetActiveSubdialog(const shared_str& section)
{
if (UIMainPdaFrame->IsChild(m_pActiveDialog))
UIMainPdaFrame->DetachChild(m_pActiveDialog);
UIMainPdaFrame->SetKeyboardCapture(nullptr, true);
m_pActiveDialog->Show(false);
}

Expand Down Expand Up @@ -290,6 +293,7 @@ void CUIPdaWnd::SetActiveSubdialog(const shared_str& section)
{
if (!UIMainPdaFrame->IsChild(m_pActiveDialog))
UIMainPdaFrame->AttachChild(m_pActiveDialog);
UIMainPdaFrame->SetKeyboardCapture(m_pActiveDialog, true);
m_pActiveDialog->Show(true);
m_sActiveSection = section;
SetActiveCaption();
Expand Down Expand Up @@ -440,13 +444,13 @@ bool CUIPdaWnd::OnKeyboardAction(int dik, EUIMessages keyboard_action)
if (inherited::OnKeyboardAction(dik, keyboard_action))
return true;

switch (GetBindedAction(dik, EKeyContext::UI))
{
case kUI_BACK:
if (WINDOW_KEY_PRESSED == keyboard_action)
HideDialog();
return false;
}

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

return false;
}
Loading

0 comments on commit dbc8a5c

Please sign in to comment.