#pragma once #include #include #include #include #include #include namespace XCEngine::UI::Editor::Widgets { inline constexpr std::size_t UIEditorVector2FieldInvalidComponentIndex = static_cast(-1); enum class UIEditorVector2FieldHitTargetKind : std::uint8_t { None = 0, Row, Component }; struct UIEditorVector2FieldSpec { std::string fieldId = {}; std::string label = {}; std::array values = { 0.0, 0.0 }; std::array componentLabels = { std::string("X"), std::string("Y") }; double step = 0.1; double minValue = -1000000.0; double maxValue = 1000000.0; bool integerMode = false; bool readOnly = false; }; struct UIEditorVector2FieldState { UIEditorVector2FieldHitTargetKind hoveredTarget = UIEditorVector2FieldHitTargetKind::None; UIEditorVector2FieldHitTargetKind activeTarget = UIEditorVector2FieldHitTargetKind::None; std::size_t hoveredComponentIndex = UIEditorVector2FieldInvalidComponentIndex; std::size_t activeComponentIndex = UIEditorVector2FieldInvalidComponentIndex; std::size_t selectedComponentIndex = UIEditorVector2FieldInvalidComponentIndex; bool focused = false; bool editing = false; std::size_t caretOffset = 0u; std::uint64_t caretBlinkStartNanoseconds = 0u; std::array displayTexts = { std::string(), std::string() }; }; struct UIEditorVector2FieldMetrics { float rowHeight = 22.0f; float horizontalPadding = 12.0f; float labelControlGap = 20.0f; float controlColumnStart = 236.0f; float controlMinWidth = 0.0f; float controlTrailingInset = 8.0f; float controlInsetY = 1.0f; float componentGap = 6.0f; float componentMinWidth = 72.0f; float componentPrefixWidth = 9.0f; float componentLabelGap = 4.0f; float labelTextInsetY = 0.0f; float labelFontSize = 11.0f; float valueTextInsetX = 5.0f; float valueTextInsetY = 0.0f; float valueFontSize = 12.0f; float prefixTextInsetX = 0.0f; float prefixTextInsetY = -1.0f; float prefixFontSize = 11.0f; float cornerRounding = 0.0f; float componentRounding = 2.0f; float borderThickness = 1.0f; float focusedBorderThickness = 1.0f; }; struct UIEditorVector2FieldPalette { ::XCEngine::UI::UIColor surfaceColor = ::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f); ::XCEngine::UI::UIColor borderColor = ::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f); ::XCEngine::UI::UIColor focusedBorderColor = ::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f); ::XCEngine::UI::UIColor rowHoverColor = ::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f); ::XCEngine::UI::UIColor rowActiveColor = ::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f); ::XCEngine::UI::UIColor componentColor = ::XCEngine::UI::UIColor(0.12f, 0.12f, 0.12f, 1.0f); ::XCEngine::UI::UIColor componentHoverColor = ::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f); ::XCEngine::UI::UIColor componentEditingColor = ::XCEngine::UI::UIColor(0.17f, 0.17f, 0.17f, 1.0f); ::XCEngine::UI::UIColor readOnlyColor = ::XCEngine::UI::UIColor(0.10f, 0.10f, 0.10f, 1.0f); ::XCEngine::UI::UIColor componentBorderColor = ::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f); ::XCEngine::UI::UIColor componentFocusedBorderColor = ::XCEngine::UI::UIColor(0.19f, 0.19f, 0.19f, 1.0f); ::XCEngine::UI::UIColor prefixColor = ::XCEngine::UI::UIColor(0.13f, 0.13f, 0.13f, 1.0f); ::XCEngine::UI::UIColor prefixBorderColor = ::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f); ::XCEngine::UI::UIColor labelColor = ::XCEngine::UI::UIColor(0.72f, 0.72f, 0.72f, 1.0f); ::XCEngine::UI::UIColor valueColor = ::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f); ::XCEngine::UI::UIColor readOnlyValueColor = ::XCEngine::UI::UIColor(0.60f, 0.60f, 0.60f, 1.0f); ::XCEngine::UI::UIColor axisXColor = ::XCEngine::UI::UIColor(0.78f, 0.42f, 0.42f, 1.0f); ::XCEngine::UI::UIColor axisYColor = ::XCEngine::UI::UIColor(0.56f, 0.72f, 0.46f, 1.0f); }; struct UIEditorVector2FieldLayout { ::XCEngine::UI::UIRect bounds = {}; ::XCEngine::UI::UIRect labelRect = {}; ::XCEngine::UI::UIRect controlRect = {}; std::array<::XCEngine::UI::UIRect, 2u> componentRects = {}; std::array<::XCEngine::UI::UIRect, 2u> componentPrefixRects = {}; std::array<::XCEngine::UI::UIRect, 2u> componentValueRects = {}; }; struct UIEditorVector2FieldHitTarget { UIEditorVector2FieldHitTargetKind kind = UIEditorVector2FieldHitTargetKind::None; std::size_t componentIndex = UIEditorVector2FieldInvalidComponentIndex; }; bool IsUIEditorVector2FieldPointInside( const ::XCEngine::UI::UIRect& rect, const ::XCEngine::UI::UIPoint& point); double NormalizeUIEditorVector2FieldComponentValue( const UIEditorVector2FieldSpec& spec, double value); bool TryParseUIEditorVector2FieldComponentValue( const UIEditorVector2FieldSpec& spec, std::string_view text, double& outValue); std::string FormatUIEditorVector2FieldComponentValue( const UIEditorVector2FieldSpec& spec, std::size_t componentIndex); UIEditorVector2FieldLayout BuildUIEditorVector2FieldLayout( const ::XCEngine::UI::UIRect& bounds, const UIEditorVector2FieldSpec& spec, const UIEditorVector2FieldMetrics& metrics = {}); UIEditorVector2FieldHitTarget HitTestUIEditorVector2Field( const UIEditorVector2FieldLayout& layout, const ::XCEngine::UI::UIPoint& point); void AppendUIEditorVector2FieldBackground( ::XCEngine::UI::UIDrawList& drawList, const UIEditorVector2FieldLayout& layout, const UIEditorVector2FieldSpec& spec, const UIEditorVector2FieldState& state, const UIEditorVector2FieldPalette& palette = {}, const UIEditorVector2FieldMetrics& metrics = {}); void AppendUIEditorVector2FieldForeground( ::XCEngine::UI::UIDrawList& drawList, const UIEditorVector2FieldLayout& layout, const UIEditorVector2FieldSpec& spec, const UIEditorVector2FieldState& state, const UIEditorVector2FieldPalette& palette = {}, const UIEditorVector2FieldMetrics& metrics = {}, const ::XCEngine::UI::Editor::UIEditorTextMeasurer* textMeasurer = nullptr); void AppendUIEditorVector2Field( ::XCEngine::UI::UIDrawList& drawList, const ::XCEngine::UI::UIRect& bounds, const UIEditorVector2FieldSpec& spec, const UIEditorVector2FieldState& state, const UIEditorVector2FieldPalette& palette = {}, const UIEditorVector2FieldMetrics& metrics = {}, const ::XCEngine::UI::Editor::UIEditorTextMeasurer* textMeasurer = nullptr); } // namespace XCEngine::UI::Editor::Widgets