#pragma once #include #include #include #include #include #include #include namespace XCEngine::UI::Editor::Widgets { inline constexpr std::size_t UIEditorVector4FieldInvalidComponentIndex = static_cast(-1); enum class UIEditorVector4FieldHitTargetKind : std::uint8_t { None = 0, Row, Component }; struct UIEditorVector4FieldSpec { std::string fieldId = {}; std::string label = {}; std::array values = { 0.0, 0.0, 0.0, 0.0 }; std::array componentLabels = { std::string("X"), std::string("Y"), std::string("Z"), std::string("W") }; double step = 0.1; double minValue = -1000000.0; double maxValue = 1000000.0; bool integerMode = false; bool readOnly = false; }; struct UIEditorVector4FieldState { UIEditorVector4FieldHitTargetKind hoveredTarget = UIEditorVector4FieldHitTargetKind::None; UIEditorVector4FieldHitTargetKind activeTarget = UIEditorVector4FieldHitTargetKind::None; std::size_t hoveredComponentIndex = UIEditorVector4FieldInvalidComponentIndex; std::size_t activeComponentIndex = UIEditorVector4FieldInvalidComponentIndex; std::size_t selectedComponentIndex = UIEditorVector4FieldInvalidComponentIndex; bool focused = false; bool editing = false; std::size_t caretOffset = 0u; std::uint64_t caretBlinkStartNanoseconds = 0u; std::array displayTexts = { std::string(), std::string(), std::string(), std::string() }; }; struct UIEditorVector4FieldMetrics { 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 UIEditorVector4FieldPalette { ::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); ::XCEngine::UI::UIColor axisZColor = ::XCEngine::UI::UIColor(0.45f, 0.62f, 0.82f, 1.0f); ::XCEngine::UI::UIColor axisWColor = ::XCEngine::UI::UIColor(0.76f, 0.66f, 0.42f, 1.0f); }; struct UIEditorVector4FieldLayout { ::XCEngine::UI::UIRect bounds = {}; ::XCEngine::UI::UIRect labelRect = {}; ::XCEngine::UI::UIRect controlRect = {}; std::array<::XCEngine::UI::UIRect, 4u> componentRects = {}; std::array<::XCEngine::UI::UIRect, 4u> componentPrefixRects = {}; std::array<::XCEngine::UI::UIRect, 4u> componentValueRects = {}; }; struct UIEditorVector4FieldHitTarget { UIEditorVector4FieldHitTargetKind kind = UIEditorVector4FieldHitTargetKind::None; std::size_t componentIndex = UIEditorVector4FieldInvalidComponentIndex; }; bool IsUIEditorVector4FieldPointInside( const ::XCEngine::UI::UIRect& rect, const ::XCEngine::UI::UIPoint& point); double NormalizeUIEditorVector4FieldComponentValue( const UIEditorVector4FieldSpec& spec, double value); bool TryParseUIEditorVector4FieldComponentValue( const UIEditorVector4FieldSpec& spec, std::string_view text, double& outValue); std::string FormatUIEditorVector4FieldComponentValue( const UIEditorVector4FieldSpec& spec, std::size_t componentIndex); UIEditorVector4FieldLayout BuildUIEditorVector4FieldLayout( const ::XCEngine::UI::UIRect& bounds, const UIEditorVector4FieldSpec& spec, const UIEditorVector4FieldMetrics& metrics = {}); UIEditorVector4FieldHitTarget HitTestUIEditorVector4Field( const UIEditorVector4FieldLayout& layout, const ::XCEngine::UI::UIPoint& point); void AppendUIEditorVector4FieldBackground( ::XCEngine::UI::UIDrawList& drawList, const UIEditorVector4FieldLayout& layout, const UIEditorVector4FieldSpec& spec, const UIEditorVector4FieldState& state, const UIEditorVector4FieldPalette& palette = {}, const UIEditorVector4FieldMetrics& metrics = {}); void AppendUIEditorVector4FieldForeground( ::XCEngine::UI::UIDrawList& drawList, const UIEditorVector4FieldLayout& layout, const UIEditorVector4FieldSpec& spec, const UIEditorVector4FieldState& state, const UIEditorVector4FieldPalette& palette = {}, const UIEditorVector4FieldMetrics& metrics = {}, const ::XCEngine::UI::Editor::UIEditorTextMeasurer* textMeasurer = nullptr); void AppendUIEditorVector4Field( ::XCEngine::UI::UIDrawList& drawList, const ::XCEngine::UI::UIRect& bounds, const UIEditorVector4FieldSpec& spec, const UIEditorVector4FieldState& state, const UIEditorVector4FieldPalette& palette = {}, const UIEditorVector4FieldMetrics& metrics = {}, const ::XCEngine::UI::Editor::UIEditorTextMeasurer* textMeasurer = nullptr); } // namespace XCEngine::UI::Editor::Widgets