#include #include #include #include namespace XCEngine::UI::Editor::Widgets { namespace { float ClampNonNegative(float value) { return (std::max)(0.0f, value); } bool ContainsPoint(const ::XCEngine::UI::UIRect& rect, const ::XCEngine::UI::UIPoint& point) { return point.x >= rect.x && point.x <= rect.x + rect.width && point.y >= rect.y && point.y <= rect.y + rect.height; } void AppendCheckMark( ::XCEngine::UI::UIDrawList& drawList, const ::XCEngine::UI::UIRect& rect, const ::XCEngine::UI::UIColor& color) { const float size = (std::min)(rect.width, rect.height); const float pad = (std::max)(size * 0.22f, 2.0f); const ::XCEngine::UI::UIPoint a(rect.x + pad, rect.y + size * 0.56f); const ::XCEngine::UI::UIPoint b(rect.x + size * 0.44f, rect.y + size - pad); const ::XCEngine::UI::UIPoint c(rect.x + size - pad, rect.y + pad); drawList.AddLine(a, b, color, 2.0f); drawList.AddLine(b, c, color, 2.0f); } } // namespace UIEditorBoolFieldLayout BuildUIEditorBoolFieldLayout( const ::XCEngine::UI::UIRect& bounds, const UIEditorBoolFieldSpec&, const UIEditorBoolFieldMetrics& metrics) { const UIEditorFieldRowLayout hostLayout = BuildUIEditorFieldRowLayout( bounds, metrics.checkboxSize, UIEditorFieldRowLayoutMetrics { metrics.rowHeight, metrics.horizontalPadding, metrics.labelControlGap, metrics.controlColumnStart, metrics.controlMinWidth, metrics.controlTrailingInset, 0.0f, }); UIEditorBoolFieldLayout layout = {}; layout.bounds = hostLayout.bounds; layout.labelRect = hostLayout.labelRect; layout.controlRect = hostLayout.controlRect; layout.checkboxRect = ::XCEngine::UI::UIRect( layout.controlRect.x, layout.bounds.y + ClampNonNegative((layout.bounds.height - metrics.checkboxSize) * 0.5f), metrics.checkboxSize, metrics.checkboxSize); layout.checkmarkRect = layout.checkboxRect; return layout; } UIEditorBoolFieldHitTarget HitTestUIEditorBoolField( const UIEditorBoolFieldLayout& layout, const ::XCEngine::UI::UIPoint& point) { if (!ContainsPoint(layout.bounds, point)) { return {}; } if (ContainsPoint(layout.controlRect, point)) { return { UIEditorBoolFieldHitTargetKind::Checkbox }; } return { UIEditorBoolFieldHitTargetKind::Row }; } void AppendUIEditorBoolFieldBackground( ::XCEngine::UI::UIDrawList& drawList, const UIEditorBoolFieldLayout& layout, const UIEditorBoolFieldSpec& spec, const UIEditorBoolFieldState& state, const UIEditorBoolFieldPalette& palette, const UIEditorBoolFieldMetrics& metrics) { const bool checkboxHovered = state.hoveredTarget == UIEditorBoolFieldHitTargetKind::Checkbox; const ::XCEngine::UI::UIColor checkboxColor = spec.readOnly ? palette.checkboxReadOnlyColor : (checkboxHovered ? palette.checkboxHoverColor : palette.checkboxColor); drawList.AddFilledRect(layout.checkboxRect, checkboxColor, metrics.checkboxRounding); drawList.AddRectOutline( layout.checkboxRect, palette.checkboxBorderColor, metrics.borderThickness, metrics.checkboxRounding); } void AppendUIEditorBoolFieldForeground( ::XCEngine::UI::UIDrawList& drawList, const UIEditorBoolFieldLayout& layout, const UIEditorBoolFieldSpec& spec, const UIEditorBoolFieldPalette& palette, const UIEditorBoolFieldMetrics& metrics) { drawList.PushClipRect(ResolveUIEditorTextClipRect(layout.labelRect, metrics.labelFontSize)); drawList.AddText( ::XCEngine::UI::UIPoint( layout.labelRect.x, ResolveUIEditorTextTop(layout.labelRect, metrics.labelFontSize, metrics.labelTextInsetY)), spec.label, palette.labelColor, metrics.labelFontSize); drawList.PopClipRect(); if (spec.value) { AppendCheckMark(drawList, layout.checkmarkRect, palette.checkboxMarkColor); } } void AppendUIEditorBoolField( ::XCEngine::UI::UIDrawList& drawList, const ::XCEngine::UI::UIRect& bounds, const UIEditorBoolFieldSpec& spec, const UIEditorBoolFieldState& state, const UIEditorBoolFieldPalette& palette, const UIEditorBoolFieldMetrics& metrics) { const UIEditorBoolFieldLayout layout = BuildUIEditorBoolFieldLayout(bounds, spec, metrics); AppendUIEditorBoolFieldBackground(drawList, layout, spec, state, palette, metrics); AppendUIEditorBoolFieldForeground(drawList, layout, spec, palette, metrics); } } // namespace XCEngine::UI::Editor::Widgets