diff --git a/src/xrEngine/editor_base.h b/src/xrEngine/editor_base.h index 0b31f1eb541..8466eafb9db 100644 --- a/src/xrEngine/editor_base.h +++ b/src/xrEngine/editor_base.h @@ -5,6 +5,7 @@ #define IMGUI_DISABLE_OBSOLETE_KEYIO #define IMGUI_DISABLE_OBSOLETE_FUNCTIONS +#define IMGUI_DEFINE_MATH_OPERATORS #include namespace xray::editor diff --git a/src/xrUICore/ui_debug.cpp b/src/xrUICore/ui_debug.cpp index 017bb9c0614..5e1ffb7bcc6 100644 --- a/src/xrUICore/ui_debug.cpp +++ b/src/xrUICore/ui_debug.cpp @@ -107,6 +107,11 @@ void CUIDebugger::on_tool_frame() imgui::ItemHelp("Non-valuable window hovered by in-game cursor"); ImGui::EndDisabled(); + imgui::ColorEdit4("Direction arrow", colors.directionArrow); + imgui::ItemHelp("The color of the arrow being drawn when examining the focus system"); + imgui::ColorEdit4("Direction text", colors.directionText); + imgui::ItemHelp("The color of the text being drawn when examining the focus system"); + ImGui::EndMenu(); } ImGui::EndMenuBar(); @@ -153,6 +158,8 @@ void CUIDebugger::reset_settings() /*.focusableValuableHovered =*/ color_rgba(0, 255, 0, 255), /*.focusableNonValuable =*/ color_rgba(255, 0, 0, 200), /*.focusableNonValuableHovered =*/ color_rgba(255, 0, 0, 255), + /*.directionArrow =*/ color_rgba(192, 192, 192, 255), + /*.directionText =*/ color_rgba(255, 0, 0, 255), }, /*.drawWndRects =*/ true, /*.coloredRects =*/ false, @@ -185,6 +192,10 @@ void CUIDebugger::apply_setting(pcstr line) settings.colors.focusableNonValuable = color; else if (sscanf(line, "FocusableNonValuableHoveredColor=0x%X", &color) == 1) settings.colors.focusableNonValuableHovered = color; + else if (sscanf(line, "DirectionArrowColor=0x%X", &color) == 1) + settings.colors.directionArrow = color; + else if (sscanf(line, "DirectionTextColor=0x%X", &color) == 1) + settings.colors.directionText = color; } void CUIDebugger::save_settings(ImGuiTextBuffer* buffer) const @@ -203,6 +214,8 @@ void CUIDebugger::save_settings(ImGuiTextBuffer* buffer) const buffer->appendf("FocusableValuableHoveredColor=0x%X\n", colors.focusableValuableHovered); buffer->appendf("FocusableNonValuableColor=0x%X\n", colors.focusableNonValuable); buffer->appendf("FocusableNonValuableHoveredColor=0x%X\n", colors.focusableNonValuableHovered); + buffer->appendf("DirectionArrowColor=0x%X\n", colors.directionArrow); + buffer->appendf("DirectionTextColor=0x%X\n", colors.directionText); } size_t CUIDebugger::estimate_settings_size() const @@ -243,5 +256,11 @@ size_t CUIDebugger::estimate_settings_size() const // "FocusableNonValuableHoveredColor=0x%X\n" size += std::size("FocusableNonValuableHoveredColor=0x") + HEXNUMBER_SIZE; + // "DirectionArrowColor=0x%X\n" + size += std::size("DirectionArrowColor=0x") + HEXNUMBER_SIZE; + + // "DirectionTextColor=0x%X\n" + size += std::size("DirectionTextColor=0x") + HEXNUMBER_SIZE; + return size; } diff --git a/src/xrUICore/ui_debug.h b/src/xrUICore/ui_debug.h index 931acab65aa..912bc323ba1 100644 --- a/src/xrUICore/ui_debug.h +++ b/src/xrUICore/ui_debug.h @@ -20,7 +20,7 @@ inline pcstr CUIDebuggable::GetDebugType() { return "CUIDebuggable"; } struct CUIDebuggerSettings { - struct + struct Colors { // Just a window u32 normal; @@ -38,6 +38,10 @@ struct CUIDebuggerSettings u32 focusableNonValuable; // Non-valuable window hovered by in-game cursor u32 focusableNonValuableHovered; + // The color of the arrow being drawn when examining the focus system + u32 directionArrow; + // The color of the text being drawn when examining the focus system + u32 directionText; } colors; bool drawWndRects; diff --git a/src/xrUICore/ui_focus.cpp b/src/xrUICore/ui_focus.cpp index 780ba9d6552..e4b8387764c 100644 --- a/src/xrUICore/ui_focus.cpp +++ b/src/xrUICore/ui_focus.cpp @@ -21,11 +21,30 @@ limitations under the License. #include "Cursor/UICursor.h" #include "xrCore/buffer_vector.h" +#include "xrEngine/editor_helper.h" #include namespace { +constexpr cpcstr short_direction(FocusDirection direction) +{ + switch (direction) + { + case FocusDirection::Same: return "S"; + case FocusDirection::Up: return "U"; + case FocusDirection::Down: return "D"; + case FocusDirection::Left: return "L"; + case FocusDirection::Right: return "R"; + case FocusDirection::UpperLeft: return "UL"; + case FocusDirection::UpperRight: return "UR"; + case FocusDirection::LowerLeft: return "LL"; + case FocusDirection::LowerRight: return "LR"; + } + XR_ASSUME(false); + return ""; +} + std::array allowed_directions(FocusDirection direction) { switch (direction) @@ -253,8 +272,27 @@ bool CUIFocusSystem::FillDebugTree(const CUIDebugState& debugState) { if (ImGui::TreeNode(&m_valuable, "Valuable: %zu", m_valuable.size())) { - for (auto& window : m_valuable) + const auto prevExamined = debugState.examined; + // Make sure we only draw debug data only in the focus system tree structure + debugState.examined = nullptr; + + for (const auto& window : m_valuable) + { const_cast(window)->FillDebugTree(debugState); + } + + if (CUIWindow* examinedWindow = dynamic_cast(debugState.examined)) + { + const auto& colors = debugState.settings.colors; + for (const auto& window : m_valuable) + { + if (window == examinedWindow) + continue; + DrawDebugInfo(*examinedWindow, *window, colors.directionArrow, colors.directionText); + } + } + + debugState.examined = prevExamined; ImGui::TreePop(); } } @@ -289,3 +327,31 @@ void CUIFocusSystem::FillDebugInfo() ImGui::LabelText("Locker", "%s", m_focus_locker ? m_focus_locker->WindowName().c_str() : "none"); #endif } + +void CUIFocusSystem::DrawDebugInfo(const CUIWindow& from, const CUIWindow& to, u32 color, u32 textColor) const +{ +#ifndef MASTER_GOLD + const auto mainVP = ImGui::GetMainViewport(); + const auto draw_list = ImGui::GetForegroundDrawList(mainVP); + + auto fromPos = from.GetAbsoluteCenterPos(); + auto toPos = to.GetAbsoluteCenterPos(); + + UI().ClientToScreenScaled(fromPos); + UI().ClientToScreenScaled(toPos); + + const auto direction = get_focus_direction(fromPos, toPos); + const auto text = short_direction(direction); + ImVec2 text_size = ImGui::CalcTextSize(text); + + Fcolor clr = color; + const float radius = text_size.x > text_size.y ? text_size.x / 1.5f : text_size.y / 1.5f; + + draw_list->AddLine((ImVec2&)fromPos, (ImVec2&)toPos, clr.get_windows(), 2.0f); + draw_list->AddCircleFilled((ImVec2&)toPos, radius, clr.get_windows()); + + clr = textColor; + toPos.sub((Fvector2&)(text_size /= 2)); + draw_list->AddText((ImVec2&)toPos, clr.get_windows(), text); +#endif +} diff --git a/src/xrUICore/ui_focus.h b/src/xrUICore/ui_focus.h index 1fc7fd6ff64..6268500a81d 100644 --- a/src/xrUICore/ui_focus.h +++ b/src/xrUICore/ui_focus.h @@ -69,4 +69,6 @@ class XRUICORE_API CUIFocusSystem : public CUIDebuggable pcstr GetDebugType() override { return "CUIFocusSystem"; } bool FillDebugTree(const CUIDebugState& debugState) override; void FillDebugInfo() override; + + void DrawDebugInfo(const CUIWindow& from, const CUIWindow& to, u32 color, u32 textColor) const; };