engine: sync editor rendering and ui changes
This commit is contained in:
@@ -21,6 +21,8 @@ set(EDITOR_UI_UNIT_TEST_SOURCES
|
||||
test_ui_editor_theme.cpp
|
||||
test_ui_editor_bool_field.cpp
|
||||
test_ui_editor_bool_field_interaction.cpp
|
||||
test_ui_editor_color_field.cpp
|
||||
test_ui_editor_color_field_interaction.cpp
|
||||
test_ui_editor_dock_host.cpp
|
||||
test_ui_editor_list_view.cpp
|
||||
test_ui_editor_list_view_interaction.cpp
|
||||
|
||||
140
tests/UI/Editor/unit/test_ui_editor_color_field.cpp
Normal file
140
tests/UI/Editor/unit/test_ui_editor_color_field.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <XCEngine/UI/DrawData.h>
|
||||
#include <XCEditor/Widgets/UIEditorColorField.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::UI::UIDrawCommandType;
|
||||
using XCEngine::UI::UIPoint;
|
||||
using XCEngine::UI::UIRect;
|
||||
using XCEngine::UI::Editor::Widgets::AppendUIEditorColorField;
|
||||
using XCEngine::UI::Editor::Widgets::BuildUIEditorColorFieldLayout;
|
||||
using XCEngine::UI::Editor::Widgets::FormatUIEditorColorFieldHexText;
|
||||
using XCEngine::UI::Editor::Widgets::FormatUIEditorColorFieldRgbaText;
|
||||
using XCEngine::UI::Editor::Widgets::HitTestUIEditorColorField;
|
||||
using XCEngine::UI::Editor::Widgets::UIEditorColorFieldHitTargetKind;
|
||||
using XCEngine::UI::Editor::Widgets::UIEditorColorFieldSpec;
|
||||
using XCEngine::UI::Editor::Widgets::UIEditorColorFieldState;
|
||||
|
||||
TEST(UIEditorColorFieldTest, FormatsHexTextWithAndWithoutAlpha) {
|
||||
UIEditorColorFieldSpec spec = {};
|
||||
spec.value = XCEngine::UI::UIColor(1.0f, 0.5f, 0.25f, 0.75f);
|
||||
spec.showAlpha = true;
|
||||
|
||||
EXPECT_EQ(FormatUIEditorColorFieldHexText(spec), "#FF8040BF");
|
||||
|
||||
spec.showAlpha = false;
|
||||
EXPECT_EQ(FormatUIEditorColorFieldHexText(spec), "#FF8040");
|
||||
}
|
||||
|
||||
TEST(UIEditorColorFieldTest, FormatsRgbaReadoutForInspectorSummary) {
|
||||
UIEditorColorFieldSpec spec = {};
|
||||
spec.value = XCEngine::UI::UIColor(0.25f, 0.5f, 0.75f, 1.0f);
|
||||
|
||||
EXPECT_EQ(FormatUIEditorColorFieldRgbaText(spec), "RGBA 64, 128, 191, 255");
|
||||
}
|
||||
|
||||
TEST(UIEditorColorFieldTest, LayoutKeepsInspectorColumnAndCompactSwatch) {
|
||||
UIEditorColorFieldSpec spec = {};
|
||||
spec.fieldId = "albedo";
|
||||
spec.label = "Albedo";
|
||||
|
||||
const auto layout = BuildUIEditorColorFieldLayout(
|
||||
UIRect(0.0f, 0.0f, 360.0f, 22.0f),
|
||||
spec);
|
||||
|
||||
EXPECT_FLOAT_EQ(layout.swatchRect.x, 236.0f);
|
||||
EXPECT_FLOAT_EQ(layout.swatchRect.width, 54.0f);
|
||||
EXPECT_FLOAT_EQ(layout.swatchRect.height, 18.0f);
|
||||
EXPECT_EQ(
|
||||
HitTestUIEditorColorField(
|
||||
layout,
|
||||
false,
|
||||
UIPoint(layout.swatchRect.x + 2.0f, layout.swatchRect.y + 2.0f)).kind,
|
||||
UIEditorColorFieldHitTargetKind::Swatch);
|
||||
}
|
||||
|
||||
TEST(UIEditorColorFieldTest, PopupLayoutExposesHueWheelAndChannelTargets) {
|
||||
UIEditorColorFieldSpec spec = {};
|
||||
spec.showAlpha = true;
|
||||
|
||||
const auto layout = BuildUIEditorColorFieldLayout(
|
||||
UIRect(10.0f, 20.0f, 360.0f, 22.0f),
|
||||
spec,
|
||||
{},
|
||||
UIRect(0.0f, 0.0f, 800.0f, 600.0f));
|
||||
|
||||
EXPECT_GT(layout.saturationValueRect.width, 0.0f);
|
||||
EXPECT_GT(layout.hueWheelOuterRadius, layout.hueWheelInnerRadius);
|
||||
EXPECT_GT(layout.redSliderRect.width, 0.0f);
|
||||
EXPECT_GT(layout.alphaSliderRect.width, 0.0f);
|
||||
EXPECT_EQ(
|
||||
HitTestUIEditorColorField(
|
||||
layout,
|
||||
true,
|
||||
UIPoint(
|
||||
layout.hueWheelCenter.x + (layout.hueWheelInnerRadius + layout.hueWheelOuterRadius) * 0.5f,
|
||||
layout.hueWheelCenter.y)).kind,
|
||||
UIEditorColorFieldHitTargetKind::HueWheel);
|
||||
EXPECT_EQ(
|
||||
HitTestUIEditorColorField(
|
||||
layout,
|
||||
true,
|
||||
UIPoint(layout.saturationValueRect.x + 5.0f, layout.saturationValueRect.y + 5.0f)).kind,
|
||||
UIEditorColorFieldHitTargetKind::SaturationValue);
|
||||
EXPECT_EQ(
|
||||
HitTestUIEditorColorField(
|
||||
layout,
|
||||
true,
|
||||
UIPoint(layout.redSliderRect.x + 2.0f, layout.redSliderRect.y + 2.0f)).kind,
|
||||
UIEditorColorFieldHitTargetKind::RedChannel);
|
||||
EXPECT_EQ(
|
||||
HitTestUIEditorColorField(
|
||||
layout,
|
||||
true,
|
||||
UIPoint(layout.alphaSliderRect.x + 2.0f, layout.alphaSliderRect.y + 2.0f)).kind,
|
||||
UIEditorColorFieldHitTargetKind::AlphaChannel);
|
||||
}
|
||||
|
||||
TEST(UIEditorColorFieldTest, PopupDrawEmitsHeaderWheelHandlesAndHexadecimalLabel) {
|
||||
UIEditorColorFieldSpec spec = {};
|
||||
spec.label = "Tint";
|
||||
spec.value = XCEngine::UI::UIColor(0.8f, 0.4f, 0.2f, 0.5f);
|
||||
spec.showAlpha = true;
|
||||
|
||||
UIEditorColorFieldState state = {};
|
||||
state.popupOpen = true;
|
||||
|
||||
XCEngine::UI::UIDrawData drawData = {};
|
||||
auto& drawList = drawData.EmplaceDrawList("ColorField");
|
||||
AppendUIEditorColorField(
|
||||
drawList,
|
||||
UIRect(0.0f, 0.0f, 360.0f, 22.0f),
|
||||
spec,
|
||||
state,
|
||||
{},
|
||||
{},
|
||||
UIRect(0.0f, 0.0f, 800.0f, 600.0f));
|
||||
|
||||
bool hasFilledCircle = false;
|
||||
bool hasCircleOutline = false;
|
||||
bool hasLine = false;
|
||||
bool hasTitleText = false;
|
||||
bool hasHexLabel = false;
|
||||
for (const auto& command : drawList.GetCommands()) {
|
||||
hasFilledCircle = hasFilledCircle || command.type == UIDrawCommandType::FilledCircle;
|
||||
hasCircleOutline = hasCircleOutline || command.type == UIDrawCommandType::CircleOutline;
|
||||
hasLine = hasLine || command.type == UIDrawCommandType::Line;
|
||||
hasTitleText = hasTitleText || command.text == "Color";
|
||||
hasHexLabel = hasHexLabel || command.text == "Hexadecimal";
|
||||
}
|
||||
|
||||
EXPECT_TRUE(hasFilledCircle);
|
||||
EXPECT_TRUE(hasCircleOutline);
|
||||
EXPECT_TRUE(hasLine);
|
||||
EXPECT_TRUE(hasTitleText);
|
||||
EXPECT_TRUE(hasHexLabel);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
138
tests/UI/Editor/unit/test_ui_editor_color_field_interaction.cpp
Normal file
138
tests/UI/Editor/unit/test_ui_editor_color_field_interaction.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <XCEditor/Core/UIEditorColorFieldInteraction.h>
|
||||
|
||||
#include <XCEngine/Input/InputTypes.h>
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::Input::KeyCode;
|
||||
using XCEngine::UI::UIInputEvent;
|
||||
using XCEngine::UI::UIInputEventType;
|
||||
using XCEngine::UI::UIPoint;
|
||||
using XCEngine::UI::UIPointerButton;
|
||||
using XCEngine::UI::UIRect;
|
||||
using XCEngine::UI::Editor::UIEditorColorFieldInteractionState;
|
||||
using XCEngine::UI::Editor::UpdateUIEditorColorFieldInteraction;
|
||||
using XCEngine::UI::Editor::Widgets::UIEditorColorFieldSpec;
|
||||
|
||||
UIInputEvent MakePointer(UIInputEventType type, float x, float y, UIPointerButton button = UIPointerButton::None) {
|
||||
UIInputEvent event = {};
|
||||
event.type = type;
|
||||
event.position = UIPoint(x, y);
|
||||
event.pointerButton = button;
|
||||
return event;
|
||||
}
|
||||
|
||||
UIInputEvent MakeKey(KeyCode keyCode) {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::KeyDown;
|
||||
event.keyCode = static_cast<std::int32_t>(keyCode);
|
||||
return event;
|
||||
}
|
||||
|
||||
TEST(UIEditorColorFieldInteractionTest, ClickSwatchOpensPopupAndEscapeClosesIt) {
|
||||
UIEditorColorFieldSpec spec = {};
|
||||
spec.fieldId = "tint";
|
||||
spec.label = "Tint";
|
||||
spec.showAlpha = true;
|
||||
spec.value = XCEngine::UI::UIColor(0.8f, 0.4f, 0.2f, 0.5f);
|
||||
|
||||
UIEditorColorFieldInteractionState state = {};
|
||||
auto frame = UpdateUIEditorColorFieldInteraction(
|
||||
state,
|
||||
spec,
|
||||
UIRect(0.0f, 0.0f, 360.0f, 32.0f),
|
||||
{});
|
||||
|
||||
frame = UpdateUIEditorColorFieldInteraction(
|
||||
state,
|
||||
spec,
|
||||
UIRect(0.0f, 0.0f, 360.0f, 32.0f),
|
||||
{
|
||||
MakePointer(
|
||||
UIInputEventType::PointerButtonDown,
|
||||
frame.layout.swatchRect.x + 2.0f,
|
||||
frame.layout.swatchRect.y + 2.0f,
|
||||
UIPointerButton::Left),
|
||||
MakePointer(
|
||||
UIInputEventType::PointerButtonUp,
|
||||
frame.layout.swatchRect.x + 2.0f,
|
||||
frame.layout.swatchRect.y + 2.0f,
|
||||
UIPointerButton::Left)
|
||||
});
|
||||
EXPECT_TRUE(frame.result.popupOpened);
|
||||
EXPECT_TRUE(state.colorFieldState.popupOpen);
|
||||
|
||||
frame = UpdateUIEditorColorFieldInteraction(
|
||||
state,
|
||||
spec,
|
||||
UIRect(0.0f, 0.0f, 360.0f, 32.0f),
|
||||
{ MakeKey(KeyCode::Escape) });
|
||||
EXPECT_TRUE(frame.result.popupClosed);
|
||||
EXPECT_FALSE(state.colorFieldState.popupOpen);
|
||||
}
|
||||
|
||||
TEST(UIEditorColorFieldInteractionTest, DraggingHueWheelAndAlphaChannelUpdatesColor) {
|
||||
UIEditorColorFieldSpec spec = {};
|
||||
spec.fieldId = "tint";
|
||||
spec.label = "Tint";
|
||||
spec.showAlpha = true;
|
||||
spec.value = XCEngine::UI::UIColor(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
UIEditorColorFieldInteractionState state = {};
|
||||
auto frame = UpdateUIEditorColorFieldInteraction(
|
||||
state,
|
||||
spec,
|
||||
UIRect(0.0f, 0.0f, 360.0f, 32.0f),
|
||||
{});
|
||||
|
||||
frame = UpdateUIEditorColorFieldInteraction(
|
||||
state,
|
||||
spec,
|
||||
UIRect(0.0f, 0.0f, 360.0f, 32.0f),
|
||||
{
|
||||
MakePointer(
|
||||
UIInputEventType::PointerButtonDown,
|
||||
frame.layout.swatchRect.x + 2.0f,
|
||||
frame.layout.swatchRect.y + 2.0f,
|
||||
UIPointerButton::Left),
|
||||
MakePointer(
|
||||
UIInputEventType::PointerButtonUp,
|
||||
frame.layout.swatchRect.x + 2.0f,
|
||||
frame.layout.swatchRect.y + 2.0f,
|
||||
UIPointerButton::Left)
|
||||
});
|
||||
ASSERT_TRUE(state.colorFieldState.popupOpen);
|
||||
|
||||
const float hueRadius = (frame.layout.hueWheelInnerRadius + frame.layout.hueWheelOuterRadius) * 0.5f;
|
||||
const float hueX = frame.layout.hueWheelCenter.x - hueRadius;
|
||||
const float hueY = frame.layout.hueWheelCenter.y;
|
||||
frame = UpdateUIEditorColorFieldInteraction(
|
||||
state,
|
||||
spec,
|
||||
UIRect(0.0f, 0.0f, 360.0f, 32.0f),
|
||||
{
|
||||
MakePointer(UIInputEventType::PointerButtonDown, hueX, hueY, UIPointerButton::Left),
|
||||
MakePointer(UIInputEventType::PointerMove, hueX, hueY),
|
||||
MakePointer(UIInputEventType::PointerButtonUp, hueX, hueY, UIPointerButton::Left)
|
||||
});
|
||||
EXPECT_TRUE(frame.result.colorChanged);
|
||||
EXPECT_GT(spec.value.b, 0.0f);
|
||||
|
||||
const float alphaX = frame.layout.alphaSliderRect.x + frame.layout.alphaSliderRect.width * 0.25f;
|
||||
const float alphaY = frame.layout.alphaSliderRect.y + frame.layout.alphaSliderRect.height * 0.5f;
|
||||
frame = UpdateUIEditorColorFieldInteraction(
|
||||
state,
|
||||
spec,
|
||||
UIRect(0.0f, 0.0f, 360.0f, 32.0f),
|
||||
{
|
||||
MakePointer(UIInputEventType::PointerButtonDown, alphaX, alphaY, UIPointerButton::Left),
|
||||
MakePointer(UIInputEventType::PointerMove, alphaX, alphaY),
|
||||
MakePointer(UIInputEventType::PointerButtonUp, alphaX, alphaY, UIPointerButton::Left)
|
||||
});
|
||||
EXPECT_TRUE(frame.result.colorChanged);
|
||||
EXPECT_LT(spec.value.a, 0.5f);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -37,6 +37,28 @@ Style::UITheme BuildEditorFieldTheme() {
|
||||
definition.SetToken("editor.size.field.dropdown_arrow_width", Style::UIStyleValue(14.0f));
|
||||
definition.SetToken("editor.space.field.dropdown_arrow_inset_x", Style::UIStyleValue(4.0f));
|
||||
definition.SetToken("editor.space.field.dropdown_arrow_inset_y", Style::UIStyleValue(4.0f));
|
||||
definition.SetToken("editor.size.field.color_popup_width", Style::UIStyleValue(320.0f));
|
||||
definition.SetToken("editor.size.field.color_popup_top_row", Style::UIStyleValue(36.0f));
|
||||
definition.SetToken("editor.size.field.color_preview_width", Style::UIStyleValue(108.0f));
|
||||
definition.SetToken("editor.size.field.color_preview_height", Style::UIStyleValue(26.0f));
|
||||
definition.SetToken("editor.size.field.color_wheel_outer_radius", Style::UIStyleValue(112.0f));
|
||||
definition.SetToken("editor.size.field.color_wheel_ring_thickness", Style::UIStyleValue(22.0f));
|
||||
definition.SetToken("editor.size.field.color_sv_square", Style::UIStyleValue(118.0f));
|
||||
definition.SetToken("editor.size.field.color_wheel_region_height", Style::UIStyleValue(224.0f));
|
||||
definition.SetToken("editor.size.field.color_channel_row_height", Style::UIStyleValue(21.0f));
|
||||
definition.SetToken("editor.size.field.color_numeric_box_width", Style::UIStyleValue(66.0f));
|
||||
definition.SetToken("editor.size.field.color_channel_label_width", Style::UIStyleValue(14.0f));
|
||||
definition.SetToken("editor.size.field.color_hex_label_width", Style::UIStyleValue(90.0f));
|
||||
definition.SetToken("editor.space.field.color_control_row_spacing", Style::UIStyleValue(7.0f));
|
||||
definition.SetToken("editor.space.field.color_popup_field_inset", Style::UIStyleValue(5.0f));
|
||||
definition.SetToken("editor.color.field.color_popup_surface", Style::UIStyleValue(Math::Color(0.22f, 0.22f, 0.22f, 1.0f)));
|
||||
definition.SetToken("editor.color.field.color_popup_header", Style::UIStyleValue(Math::Color(0.48f, 0.28f, 0.10f, 1.0f)));
|
||||
definition.SetToken("editor.color.field.color_popup_close", Style::UIStyleValue(Math::Color(0.74f, 0.34f, 0.32f, 1.0f)));
|
||||
definition.SetToken("editor.color.field.color_popup_close_hover", Style::UIStyleValue(Math::Color(0.80f, 0.38f, 0.36f, 1.0f)));
|
||||
definition.SetToken("editor.color.field.color_popup_slider_border", Style::UIStyleValue(Math::Color(0.11f, 0.11f, 0.11f, 1.0f)));
|
||||
definition.SetToken("editor.color.field.color_popup_numeric_box", Style::UIStyleValue(Math::Color(0.17f, 0.17f, 0.17f, 1.0f)));
|
||||
definition.SetToken("editor.color.field.color_popup_numeric_box_text", Style::UIStyleValue(Math::Color(0.93f, 0.93f, 0.93f, 1.0f)));
|
||||
definition.SetToken("editor.color.field.color_popup_handle_outline", Style::UIStyleValue(Math::Color(0.10f, 0.10f, 0.10f, 0.5f)));
|
||||
definition.SetToken("editor.radius.field.row", Style::UIStyleValue(2.0f));
|
||||
definition.SetToken("editor.radius.field.control", Style::UIStyleValue(2.0f));
|
||||
definition.SetToken("editor.border.field", Style::UIStyleValue(1.0f));
|
||||
@@ -244,6 +266,25 @@ TEST(UIEditorThemeTest, FieldResolversReadEditorThemeTokens) {
|
||||
EXPECT_FLOAT_EQ(enumMetrics.dropdownArrowFontSize, 10.0f);
|
||||
EXPECT_FLOAT_EQ(enumPalette.arrowColor.r, 0.88f);
|
||||
|
||||
const auto colorMetrics = Editor::ResolveUIEditorColorFieldMetrics(theme);
|
||||
const auto colorPalette = Editor::ResolveUIEditorColorFieldPalette(theme);
|
||||
EXPECT_FLOAT_EQ(colorMetrics.popupWidth, 320.0f);
|
||||
EXPECT_FLOAT_EQ(colorMetrics.popupTopRowHeight, 36.0f);
|
||||
EXPECT_FLOAT_EQ(colorMetrics.popupPreviewWidth, 108.0f);
|
||||
EXPECT_FLOAT_EQ(colorMetrics.wheelOuterRadius, 112.0f);
|
||||
EXPECT_FLOAT_EQ(colorMetrics.wheelRingThickness, 22.0f);
|
||||
EXPECT_FLOAT_EQ(colorMetrics.saturationValueSize, 118.0f);
|
||||
EXPECT_FLOAT_EQ(colorMetrics.channelRowHeight, 21.0f);
|
||||
EXPECT_FLOAT_EQ(colorMetrics.numericBoxWidth, 66.0f);
|
||||
EXPECT_FLOAT_EQ(colorMetrics.hexLabelWidth, 90.0f);
|
||||
EXPECT_FLOAT_EQ(colorPalette.popupColor.r, 0.22f);
|
||||
EXPECT_FLOAT_EQ(colorPalette.popupHeaderColor.r, 0.48f);
|
||||
EXPECT_FLOAT_EQ(colorPalette.closeButtonColor.r, 0.74f);
|
||||
EXPECT_FLOAT_EQ(colorPalette.closeButtonHoverColor.r, 0.80f);
|
||||
EXPECT_FLOAT_EQ(colorPalette.sliderBorderColor.r, 0.11f);
|
||||
EXPECT_FLOAT_EQ(colorPalette.numericBoxTextColor.r, 0.93f);
|
||||
EXPECT_FLOAT_EQ(colorPalette.handleStrokeColor.r, 0.10f);
|
||||
|
||||
const auto popupMetrics = Editor::ResolveUIEditorMenuPopupMetrics(theme);
|
||||
const auto popupPalette = Editor::ResolveUIEditorMenuPopupPalette(theme);
|
||||
EXPECT_FLOAT_EQ(popupMetrics.contentPaddingX, 6.0f);
|
||||
@@ -386,6 +427,18 @@ TEST(UIEditorThemeTest, HostedFieldBuildersInheritPropertyGridMetricsAndPalette)
|
||||
EXPECT_FLOAT_EQ(enumMetrics.valueTextInsetX, 5.0f);
|
||||
EXPECT_FLOAT_EQ(enumMetrics.dropdownArrowFontSize, 12.0f);
|
||||
EXPECT_FLOAT_EQ(enumPalette.arrowColor.r, 0.9f);
|
||||
|
||||
const auto colorMetrics = Editor::BuildUIEditorHostedColorFieldMetrics(propertyMetrics);
|
||||
const auto colorPalette = Editor::BuildUIEditorHostedColorFieldPalette(propertyPalette);
|
||||
EXPECT_FLOAT_EQ(colorMetrics.controlTrailingInset, 5.0f);
|
||||
EXPECT_FLOAT_EQ(colorMetrics.swatchInsetY, 2.0f);
|
||||
EXPECT_FLOAT_EQ(colorMetrics.labelFontSize, 10.0f);
|
||||
EXPECT_FLOAT_EQ(colorMetrics.valueFontSize, 12.0f);
|
||||
EXPECT_FLOAT_EQ(colorMetrics.popupHeaderHeight, 30.0f);
|
||||
EXPECT_FLOAT_EQ(colorPalette.labelColor.r, 0.8f);
|
||||
EXPECT_FLOAT_EQ(colorPalette.popupBorderColor.r, 0.15f);
|
||||
EXPECT_FLOAT_EQ(colorPalette.popupHeaderColor.r, 0.43f);
|
||||
EXPECT_FLOAT_EQ(colorPalette.swatchBorderColor.r, 0.5f);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user