134 lines
4.8 KiB
C++
134 lines
4.8 KiB
C++
|
|
#include <XCEditor/Widgets/UIEditorBoolField.h>
|
||
|
|
|
||
|
|
#include <algorithm>
|
||
|
|
|
||
|
|
namespace XCEngine::UI::Editor::Widgets {
|
||
|
|
|
||
|
|
namespace {
|
||
|
|
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace
|
||
|
|
|
||
|
|
UIEditorBoolFieldLayout BuildUIEditorBoolFieldLayout(
|
||
|
|
const ::XCEngine::UI::UIRect& bounds,
|
||
|
|
const UIEditorBoolFieldSpec& spec,
|
||
|
|
const UIEditorBoolFieldMetrics& metrics) {
|
||
|
|
UIEditorBoolFieldLayout layout = {};
|
||
|
|
layout.bounds = bounds;
|
||
|
|
|
||
|
|
const float controlX = (std::min)(
|
||
|
|
bounds.x + bounds.width - metrics.horizontalPadding - metrics.toggleWidth,
|
||
|
|
bounds.x + metrics.controlColumnStart);
|
||
|
|
const float labelWidth = (std::max)(
|
||
|
|
0.0f,
|
||
|
|
controlX - bounds.x - metrics.horizontalPadding - metrics.labelControlGap);
|
||
|
|
layout.labelRect = ::XCEngine::UI::UIRect(
|
||
|
|
bounds.x + metrics.horizontalPadding,
|
||
|
|
bounds.y,
|
||
|
|
labelWidth,
|
||
|
|
bounds.height);
|
||
|
|
layout.toggleRect = ::XCEngine::UI::UIRect(
|
||
|
|
controlX,
|
||
|
|
bounds.y + (std::max)(0.0f, (bounds.height - metrics.toggleHeight) * 0.5f),
|
||
|
|
metrics.toggleWidth,
|
||
|
|
metrics.toggleHeight);
|
||
|
|
|
||
|
|
const float knobSize = (std::max)(0.0f, layout.toggleRect.height - metrics.toggleKnobInset * 2.0f);
|
||
|
|
const float knobX = spec.value
|
||
|
|
? layout.toggleRect.x + layout.toggleRect.width - metrics.toggleKnobInset - knobSize
|
||
|
|
: layout.toggleRect.x + metrics.toggleKnobInset;
|
||
|
|
layout.knobRect = ::XCEngine::UI::UIRect(
|
||
|
|
knobX,
|
||
|
|
layout.toggleRect.y + metrics.toggleKnobInset,
|
||
|
|
knobSize,
|
||
|
|
knobSize);
|
||
|
|
return layout;
|
||
|
|
}
|
||
|
|
|
||
|
|
UIEditorBoolFieldHitTarget HitTestUIEditorBoolField(
|
||
|
|
const UIEditorBoolFieldLayout& layout,
|
||
|
|
const ::XCEngine::UI::UIPoint& point) {
|
||
|
|
if (!ContainsPoint(layout.bounds, point)) {
|
||
|
|
return {};
|
||
|
|
}
|
||
|
|
|
||
|
|
if (ContainsPoint(layout.toggleRect, point)) {
|
||
|
|
return { UIEditorBoolFieldHitTargetKind::Toggle };
|
||
|
|
}
|
||
|
|
|
||
|
|
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 hovered = state.hoveredTarget != UIEditorBoolFieldHitTargetKind::None;
|
||
|
|
const ::XCEngine::UI::UIColor rowColor =
|
||
|
|
state.active ? palette.rowActiveColor :
|
||
|
|
(hovered ? palette.rowHoverColor : palette.surfaceColor);
|
||
|
|
drawList.AddFilledRect(layout.bounds, rowColor, metrics.cornerRounding);
|
||
|
|
drawList.AddRectOutline(
|
||
|
|
layout.bounds,
|
||
|
|
state.focused ? palette.focusedBorderColor : palette.borderColor,
|
||
|
|
state.focused ? metrics.focusedBorderThickness : metrics.borderThickness,
|
||
|
|
metrics.cornerRounding);
|
||
|
|
|
||
|
|
const ::XCEngine::UI::UIColor toggleColor =
|
||
|
|
spec.readOnly ? palette.toggleReadOnlyColor :
|
||
|
|
(spec.value ? palette.toggleOnColor : palette.toggleOffColor);
|
||
|
|
drawList.AddFilledRect(layout.toggleRect, toggleColor, layout.toggleRect.height * 0.5f);
|
||
|
|
drawList.AddRectOutline(
|
||
|
|
layout.toggleRect,
|
||
|
|
palette.toggleBorderColor,
|
||
|
|
metrics.borderThickness,
|
||
|
|
layout.toggleRect.height * 0.5f);
|
||
|
|
drawList.AddFilledRect(layout.knobRect, palette.knobColor, layout.knobRect.height * 0.5f);
|
||
|
|
}
|
||
|
|
|
||
|
|
void AppendUIEditorBoolFieldForeground(
|
||
|
|
::XCEngine::UI::UIDrawList& drawList,
|
||
|
|
const UIEditorBoolFieldLayout& layout,
|
||
|
|
const UIEditorBoolFieldSpec& spec,
|
||
|
|
const UIEditorBoolFieldPalette& palette,
|
||
|
|
const UIEditorBoolFieldMetrics& metrics) {
|
||
|
|
drawList.PushClipRect(layout.labelRect);
|
||
|
|
drawList.AddText(
|
||
|
|
::XCEngine::UI::UIPoint(layout.labelRect.x, layout.labelRect.y + metrics.textInsetY),
|
||
|
|
spec.label,
|
||
|
|
palette.labelColor,
|
||
|
|
12.0f);
|
||
|
|
drawList.PopClipRect();
|
||
|
|
|
||
|
|
drawList.AddText(
|
||
|
|
::XCEngine::UI::UIPoint(
|
||
|
|
layout.toggleRect.x - 42.0f,
|
||
|
|
layout.bounds.y + metrics.textInsetY),
|
||
|
|
spec.value ? "On" : "Off",
|
||
|
|
palette.valueColor,
|
||
|
|
12.0f);
|
||
|
|
}
|
||
|
|
|
||
|
|
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
|