Коммит b91375bc создал по автору xottab-duty's avatar xottab-duty
Просмотр файлов

Reworked PDA filter selection mechanism

More robust, fixed few known and possible edge cases bugs
владелец ca6a831b
......@@ -2378,6 +2378,8 @@ set(SRC_FILES
"ui/UIMap.cpp"
"ui/UIMapDesc.cpp"
"ui/UIMapDesc.h"
"ui/UIMapFilters.cpp"
"ui/UIMapFilters.h"
"ui/UIMap.h"
"ui/UIMapInfo.cpp"
"ui/UIMapInfo.h"
......
#include "StdAfx.h"
#include "UIMapFilters.h"
#include "UIHelper.h"
#include "xrUICore/Buttons/UICheckButton.h"
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());
}
}
constexpr std::tuple<eSpotsFilter, pcstr> filters[] =
{
{ Treasures, "filter_treasures" },
{ QuestNpcs, "filter_primary_objects" },
{ SecondaryTasks, "filter_secondary_tasks" },
{ PrimaryObjects, "filter_quest_npcs" },
};
for (const auto& [filter_id, filter_section] : filters)
{
auto& filter = m_filters[filter_id];
filter = UIHelper::CreateCheck(xml, filter_section, this, false);
if (filter)
{
filter->SetMessageTarget(this);
filter->SetWindowName(filter_section);
filter->SetCheck(true);
}
m_filters_state[filter_id] = true;
}
return true;
}
void CUIMapFilters::Reset()
{
inherited::Reset();
SelectFilter(false);
}
bool CUIMapFilters::OnKeyboardAction(int dik, EUIMessages keyboard_action)
{
if (const auto filter = GetSelectedFilter())
{
if (keyboard_action != WINDOW_KEY_PRESSED)
return true; // intercept all
switch (GetBindedAction(dik, EKeyContext::UI))
{
case kUI_BACK:
SelectFilter(false);
return true;
case kUI_ACCEPT:
filter->OnMouseDown(MOUSE_1);
return true;
case kUI_MOVE_LEFT:
case kUI_MOVE_DOWN:
SelectFilter(true, false);
return true;
case kUI_MOVE_RIGHT:
case kUI_MOVE_UP:
SelectFilter(true, true);
return true;
}
}
return inherited::OnKeyboardAction(dik, keyboard_action);
}
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
}
return inherited::OnControllerAction(axis, x, y, controller_action);
}
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 (m_filters[i] == pWnd && msg == BUTTON_CLICKED)
{
m_filters_state[i] = m_filters[i]->GetCheck();
GetMessageTarget()->SendMessage(this, PDA_TASK_RELOAD_FILTERS, nullptr);
return;
}
}
if (msg == PDA_TASK_SELECT_FILTERS)
{
SelectFilter(!GetSelectedFilter());
return;
}
if (msg == WINDOW_KEYBOARD_CAPTURE_LOST || msg == WINDOW_FOCUS_LOST)
{
SelectFilter(false);
return;
}
inherited::SendMessage(pWnd, msg, pData);
}
CUICheckButton* CUIMapFilters::GetSelectedFilter() const
{
if (m_selected_filter == -1)
return nullptr;
return m_filters[m_selected_filter];
}
void CUIMapFilters::SelectFilter(bool select, bool next /*= true*/)
{
auto& cursor = GetUICursor();
if (!select)
{
m_selected_filter = -1;
cursor.WarpToWindow(nullptr, pInput->IsCurrentInputTypeController());
}
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]);
cursor.PauseAutohiding(true);
}
}
void CUIMapFilters::SetFilterEnabled(eSpotsFilter filter, bool enable)
{
m_filters_state[filter] = enable;
if (m_filters[filter])
m_filters[filter]->SetCheck(enable);
}
#pragma once
#include "xrUICore/Windows/UIWindow.h"
class CUICheckButton;
class CUIMapFilters final : public CUIWindow
{
typedef CUIWindow inherited;
public:
enum eSpotsFilter
{
Treasures,
QuestNpcs,
SecondaryTasks,
PrimaryObjects,
Filter_Count
};
private:
std::array<CUICheckButton*, Filter_Count> m_filters{};
std::array<bool, Filter_Count> m_filters_state{};
int m_selected_filter{ -1 };
public:
CUIMapFilters();
bool Init(CUIXml& xml);
pcstr GetDebugType() override { return "CUIMapFilters"; }
void Reset() override;
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];
}
void SetFilterEnabled(eSpotsFilter filter, bool enable);
private:
CUICheckButton* GetSelectedFilter() const;
void SelectFilter(bool select, bool next = true);
};
......@@ -402,6 +402,9 @@ void RearrangeTabButtons(CUITabControl* pTab)
bool CUIPdaWnd::OnKeyboardAction(int dik, EUIMessages keyboard_action)
{
if (inherited::OnKeyboardAction(dik, keyboard_action))
return true;
switch (GetBindedAction(dik, EKeyContext::UI))
{
case kUI_TAB_PREV:
......@@ -424,5 +427,5 @@ bool CUIPdaWnd::OnKeyboardAction(int dik, EUIMessages keyboard_action)
if (IsBinded(kACTIVE_JOBS, dik))
goto hide_pda;
return inherited::OnKeyboardAction(dik, keyboard_action);
return false;
}
......@@ -51,25 +51,9 @@ bool CUITaskWnd::Init()
m_task_split = UIHelper::CreateFrameLine(xml, "task_split", this, false);
constexpr std::tuple<eSpotsFilter, pcstr> filters[] =
{
{ eSpotsFilterTreasures, "filter_treasures" },
{ eSpotsFilterQuestNpcs, "filter_primary_objects" },
{ eSpotsFilterSecondaryTasks, "filter_secondary_tasks" },
{ eSpotsFilterPrimaryObjects, "filter_quest_npcs" },
};
for (const auto& [filter_id, filter_section] : filters)
{
auto& filter = m_filters[filter_id];
filter = UIHelper::CreateCheck(xml, filter_section, this, false);
if (filter)
{
filter->SetCheck(true);
AddCallback(filter, BUTTON_CLICKED, void_function(this, &CUITaskWnd::OnMapSpotFilterClicked));
}
m_filters_state[filter_id] = true;
}
AttachChild(&m_filters);
m_filters.SetMessageTarget(this);
m_filters.Init(xml);
m_pMapWnd = xr_new<CUIMapWnd>(hint_wnd);
m_pMapWnd->SetAutoDelete(false);
......@@ -161,84 +145,26 @@ void CUITaskWnd::Update()
void CUITaskWnd::Draw() { inherited::Draw(); }
void CUITaskWnd::DrawHint() { m_pMapWnd->DrawHint(); }
void CUITaskWnd::DropFilterSelection()
{
m_selected_filter = -1;
GetUICursor().WarpToWindow(nullptr, pInput->IsCurrentInputTypeController());
}
bool CUITaskWnd::OnKeyboardAction(int dik, EUIMessages keyboard_action)
{
if (inherited::OnKeyboardAction(dik, keyboard_action))
return true;
if (keyboard_action == WINDOW_KEY_PRESSED)
{
if (IsBinded(kPDA_FILTER_TOGGLE, dik, EKeyContext::PDA) && m_selected_filter == -1)
{
m_selected_filter = 0;
GetUICursor().WarpToWindow(m_filters[m_selected_filter]);
GetUICursor().PauseAutohiding(true);
return true;
}
if (m_selected_filter >= 0)
switch (GetBindedAction(dik, EKeyContext::PDA))
{
if (IsBinded(kQUIT, dik))
{
DropFilterSelection();
return false; // allow PDA to hide
}
switch (GetBindedAction(dik, EKeyContext::UI))
{
case kUI_BACK:
DropFilterSelection();
return true;
case kUI_ACCEPT:
m_filters[m_selected_filter]->OnMouseDown(MOUSE_1);
return true;
case kUI_MOVE_LEFT:
case kUI_MOVE_DOWN:
if (m_selected_filter > 0)
m_selected_filter--;
else
m_selected_filter = int(m_filters.size() - 1);
break;
case kUI_MOVE_RIGHT:
case kUI_MOVE_UP:
if (m_selected_filter < int(m_filters.size() - 1))
m_selected_filter++;
else
m_selected_filter = 0;
break;
} // switch (GetBindedAction(dik, EKeyContext::UI))
if (IsBinded(kPDA_FILTER_TOGGLE, dik, EKeyContext::PDA))
{
DropFilterSelection();
return true;
}
GetUICursor().WarpToWindow(m_filters[m_selected_filter]);
case kPDA_FILTER_TOGGLE:
if (m_pKeyboardCapturer == &m_filters)
SetKeyboardCapture(nullptr, false);
else
SetKeyboardCapture(&m_filters, true);
m_filters.SendMessage(this, PDA_TASK_SELECT_FILTERS, nullptr);
return true;
}
}
return inherited::OnKeyboardAction(dik, keyboard_action);
}
bool CUITaskWnd::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 (m_selected_filter >= 0)
return true; // just screw it for now
}
return inherited::OnControllerAction(axis, x, y, controller_action);
return false;
}
void CUITaskWnd::SendMessage(CUIWindow* pWnd, s16 msg, void* pData)
......@@ -273,6 +199,11 @@ void CUITaskWnd::SendMessage(CUIWindow* pWnd, s16 msg, void* pData)
m_pMapWnd->HideCurHint();
return;
}
if (msg == PDA_TASK_RELOAD_FILTERS)
{
ReloadTaskInfo();
return;
}
inherited::SendMessage(pWnd, msg, pData);
CUIWndCallback::OnEvent(pWnd, msg, pData);
......@@ -390,7 +321,6 @@ void CUITaskWnd::Show(bool status)
}
}
void CUITaskWnd::Reset() { inherited::Reset(); }
void CUITaskWnd::OnNextTaskClicked() {}
void CUITaskWnd::OnPrevTaskClicked() {}
void CUITaskWnd::OnShowTaskListWnd(CUIWindow* w, void* d)
......@@ -459,16 +389,6 @@ void CUITaskWnd::OnTask2DbClicked(CUIWindow*, void*)
void CUITaskWnd::ShowMapLegend(bool status) const { m_map_legend_wnd->Show(status); }
void CUITaskWnd::Switch_ShowMapLegend() const { m_map_legend_wnd->Show(!m_map_legend_wnd->IsShown()); }
void CUITaskWnd::OnMapSpotFilterClicked(CUIWindow* ui, void* d)
{
for (u32 i = 0; i < eSpotsFilter_Count; ++i)
{
if (m_filters[i] == ui)
m_filters_state[i] = m_filters[i]->GetCheck();
}
ReloadTaskInfo();
}
// --------------------------------------------------------------------------------------------------
CUITaskItem::CUITaskItem()
: CUIWindow("CUITaskItem"),
......
#pragma once
#include "xrUICore/Windows/UIWindow.h"
#include "xrUICore/Callbacks/UIWndCallback.h"
#include "xrCore/Containers/AssociativeVector.hpp"
#include "GameTaskDefs.h"
#include "xrUICore/Buttons/UICheckButton.h"
#include "UIMapFilters.h"
class CUIMapWnd;
class CUIStatic;
......@@ -13,7 +14,6 @@ class CUITaskItem;
class CUI3tButton;
class CUIFrameLineWnd;
class CUIFrameWindow;
class CUICheckButton;
class UITaskListWnd;
class UIMapLegend;
class UIHint;
......@@ -42,18 +42,7 @@ private:
CUI3tButton* m_btn_focus;
CUI3tButton* m_btn_focus2;
enum eSpotsFilter
{
eSpotsFilterTreasures,
eSpotsFilterQuestNpcs,
eSpotsFilterSecondaryTasks,
eSpotsFilterPrimaryObjects,
eSpotsFilter_Count
};
std::array<CUICheckButton*, eSpotsFilter_Count> m_filters;
std::array<bool, eSpotsFilter_Count> m_filters_state;
int m_selected_filter{ -1 };
CUIMapFilters m_filters;
UITaskListWnd* m_task_wnd;
bool m_task_wnd_show;
......@@ -69,60 +58,31 @@ public:
pcstr GetDebugType() override { return "CUITaskWnd"; }
bool OnKeyboardAction(int dik, EUIMessages keyboard_action) override;
bool OnControllerAction(int axis, float x, float y, EUIMessages controller_action) override;
virtual void SendMessage(CUIWindow* pWnd, s16 msg, void* pData);
bool Init();
virtual void Update();
virtual void Draw();
void DrawHint();
virtual void Show(bool status);
virtual void Reset();
void ReloadTaskInfo();
void ShowMapLegend(bool status) const;
void Switch_ShowMapLegend() const;
void Show_TaskListWnd(bool status);
[[nodiscard]]
bool IsTreasuresEnabled() const { return m_filters_state[eSpotsFilterTreasures]; }
bool IsTreasuresEnabled() const { return m_filters.IsFilterEnabled(CUIMapFilters::Treasures); }
[[nodiscard]]
bool IsQuestNpcsEnabled() const { return m_filters_state[eSpotsFilterQuestNpcs]; }
bool IsQuestNpcsEnabled() const { return m_filters.IsFilterEnabled(CUIMapFilters::QuestNpcs); }
[[nodiscard]]
bool IsSecondaryTasksEnabled() const { return m_filters_state[eSpotsFilterSecondaryTasks]; }
bool IsSecondaryTasksEnabled() const { return m_filters.IsFilterEnabled(CUIMapFilters::SecondaryTasks); }
[[nodiscard]]
bool IsPrimaryObjectsEnabled() const { return m_filters_state[eSpotsFilterPrimaryObjects]; }
void TreasuresEnabled(bool enable)
{
m_filters_state[eSpotsFilterTreasures] = enable;
if (m_filters[eSpotsFilterTreasures])
m_filters[eSpotsFilterTreasures]->SetCheck(enable);
}
void QuestNpcsEnabled(bool enable)
{
m_filters_state[eSpotsFilterQuestNpcs] = enable;
if (m_filters[eSpotsFilterQuestNpcs])
m_filters[eSpotsFilterQuestNpcs]->SetCheck(enable);
}
void SecondaryTasksEnabled(bool enable)
{
m_filters_state[eSpotsFilterSecondaryTasks] = enable;
if (m_filters[eSpotsFilterSecondaryTasks])
m_filters[eSpotsFilterSecondaryTasks]->SetCheck(enable);
}
void PrimaryObjectsEnabled(bool enable)
{
m_filters_state[eSpotsFilterPrimaryObjects] = enable;
if (m_filters[eSpotsFilterPrimaryObjects])
m_filters[eSpotsFilterPrimaryObjects]->SetCheck(enable);
}
bool IsPrimaryObjectsEnabled() const { return m_filters.IsFilterEnabled(CUIMapFilters::PrimaryObjects); }
void Show_TaskListWnd(bool status);
void TreasuresEnabled(bool enable) { m_filters.SetFilterEnabled(CUIMapFilters::Treasures, enable); }
void QuestNpcsEnabled(bool enable) { m_filters.SetFilterEnabled(CUIMapFilters::QuestNpcs, enable); }
void SecondaryTasksEnabled(bool enable) { m_filters.SetFilterEnabled(CUIMapFilters::SecondaryTasks, enable); }
void PrimaryObjectsEnabled(bool enable) { m_filters.SetFilterEnabled(CUIMapFilters::PrimaryObjects, enable); }
private:
void TaskSetTargetMap(CGameTask* task);
......@@ -133,10 +93,6 @@ private:
void OnShowTaskListWnd(CUIWindow* w, void* d);
void OnTask1DbClicked(CUIWindow*, void*);
void OnTask2DbClicked(CUIWindow*, void*);
void OnMapSpotFilterClicked(CUIWindow*, void*);
void DropFilterSelection();
};
class CUITaskItem final : public CUIWindow
......
......@@ -1345,6 +1345,7 @@
<ClInclude Include="ui\UIMainIngameWnd.h" />
<ClInclude Include="ui\UIMap.h" />
<ClInclude Include="ui\UIMapDesc.h" />
<ClInclude Include="ui\UIMapFilters.h" />
<ClInclude Include="ui\UIMapInfo.h" />
<ClInclude Include="ui\UIMapLegend.h" />
<ClInclude Include="ui\UIMapList.h" />
......@@ -3301,6 +3302,7 @@
<ClCompile Include="ui\UIMainIngameWnd.cpp" />
<ClCompile Include="ui\UIMap.cpp" />
<ClCompile Include="ui\UIMapDesc.cpp" />
<ClCompile Include="ui\UIMapFilters.cpp" />
<ClCompile Include="ui\UIMapInfo.cpp" />
<ClCompile Include="ui\UIMapInfo_script.cpp">
<PrecompiledHeaderFile>pch_script.h</PrecompiledHeaderFile>
......
......@@ -6495,6 +6495,9 @@
<ClInclude Include="game_cl_mp_script.h">
<Filter>Core\Server\Games\client\mp_script</Filter>
</ClInclude>
<ClInclude Include="ui\UIMapFilters.h">
<Filter>UI\Common\PDA\Tasks</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="damage_manager.cpp">
......@@ -9857,6 +9860,9 @@
<ClCompile Include="CustomOutfit_script.cpp">
<Filter>Core\Client\Objects\items &amp; weapons\Outfit</Filter>
</ClCompile>
<ClCompile Include="ui\UIMapFilters.cpp">
<Filter>UI\Common\PDA\Tasks</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Natvis Include="..\OpenXRay.natvis" />
......
......@@ -91,6 +91,8 @@ enum EUIMessages
PDA_TASK_HIDE_MAP_SPOT,
PDA_TASK_SHOW_HINT,
PDA_TASK_HIDE_HINT,
PDA_TASK_SELECT_FILTERS,
PDA_TASK_RELOAD_FILTERS,
// CUIInventroyWnd
INVENTORY_DROP_ACTION,
......
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать