ui: add typed editor field foundations
This commit is contained in:
@@ -3,6 +3,7 @@ add_executable(editor_ui_enum_field_basic_validation WIN32
|
||||
)
|
||||
|
||||
target_include_directories(editor_ui_enum_field_basic_validation PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/tests/UI/Editor/integration/shared/src
|
||||
${CMAKE_SOURCE_DIR}/new_editor/include
|
||||
${CMAKE_SOURCE_DIR}/new_editor/app
|
||||
${CMAKE_SOURCE_DIR}/engine/include
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
#endif
|
||||
|
||||
#include <XCEditor/Core/UIEditorEnumFieldInteraction.h>
|
||||
#include <XCEditor/Core/UIEditorTheme.h>
|
||||
#include <XCEditor/Widgets/UIEditorEnumField.h>
|
||||
#include <XCEditor/Widgets/UIEditorMenuPopup.h>
|
||||
#include "EditorValidationTheme.h"
|
||||
#include "Host/AutoScreenshot.h"
|
||||
#include "Host/NativeRenderer.h"
|
||||
|
||||
@@ -41,24 +44,18 @@ using XCEngine::UI::Editor::UIEditorEnumFieldInteractionResult;
|
||||
using XCEngine::UI::Editor::UIEditorEnumFieldInteractionState;
|
||||
using XCEngine::UI::Editor::UpdateUIEditorEnumFieldInteraction;
|
||||
using XCEngine::UI::Editor::Widgets::AppendUIEditorEnumField;
|
||||
using XCEngine::UI::Editor::Widgets::AppendUIEditorMenuPopup;
|
||||
using XCEngine::UI::Editor::Widgets::HitTestUIEditorEnumField;
|
||||
using XCEngine::UI::Editor::Widgets::ResolveUIEditorEnumFieldValueText;
|
||||
using XCEngine::UI::Editor::Widgets::UIEditorEnumFieldHitTarget;
|
||||
using XCEngine::UI::Editor::Widgets::UIEditorEnumFieldHitTargetKind;
|
||||
using XCEngine::UI::Editor::Widgets::UIEditorEnumFieldSpec;
|
||||
using XCEngine::UI::Editor::Widgets::UIEditorMenuPopupInvalidIndex;
|
||||
namespace Style = XCEngine::UI::Style;
|
||||
|
||||
constexpr const wchar_t* kWindowClassName = L"XCUIEditorEnumFieldBasicValidation";
|
||||
constexpr const wchar_t* kWindowTitle = L"XCUI Editor | EnumField Basic";
|
||||
|
||||
constexpr UIColor kWindowBg(0.13f, 0.13f, 0.13f, 1.0f);
|
||||
constexpr UIColor kCardBg(0.18f, 0.18f, 0.18f, 1.0f);
|
||||
constexpr UIColor kCardBorder(0.29f, 0.29f, 0.29f, 1.0f);
|
||||
constexpr UIColor kTextPrimary(0.94f, 0.94f, 0.94f, 1.0f);
|
||||
constexpr UIColor kTextMuted(0.72f, 0.72f, 0.72f, 1.0f);
|
||||
constexpr UIColor kTextWeak(0.56f, 0.56f, 0.56f, 1.0f);
|
||||
constexpr UIColor kButtonBg(0.25f, 0.25f, 0.25f, 1.0f);
|
||||
constexpr UIColor kButtonHoverBg(0.32f, 0.32f, 0.32f, 1.0f);
|
||||
|
||||
enum class ActionId : unsigned char {
|
||||
Reset = 0,
|
||||
Capture
|
||||
@@ -87,6 +84,11 @@ std::filesystem::path ResolveRepoRootPath() {
|
||||
return std::filesystem::path(root).lexically_normal();
|
||||
}
|
||||
|
||||
std::filesystem::path ResolveValidationThemePath() {
|
||||
return (ResolveRepoRootPath() / "tests/UI/Editor/integration/shared/themes/editor_validation.xctheme")
|
||||
.lexically_normal();
|
||||
}
|
||||
|
||||
bool ContainsPoint(const UIRect& rect, float x, float y) {
|
||||
return x >= rect.x &&
|
||||
x <= rect.x + rect.width &&
|
||||
@@ -96,34 +98,41 @@ bool ContainsPoint(const UIRect& rect, float x, float y) {
|
||||
|
||||
std::int32_t MapEnumFieldKey(UINT keyCode) {
|
||||
switch (keyCode) {
|
||||
case VK_LEFT:
|
||||
return static_cast<std::int32_t>(KeyCode::Left);
|
||||
case VK_RIGHT:
|
||||
return static_cast<std::int32_t>(KeyCode::Right);
|
||||
case VK_UP:
|
||||
return static_cast<std::int32_t>(KeyCode::Up);
|
||||
case VK_DOWN:
|
||||
return static_cast<std::int32_t>(KeyCode::Down);
|
||||
case VK_HOME:
|
||||
return static_cast<std::int32_t>(KeyCode::Home);
|
||||
case VK_END:
|
||||
return static_cast<std::int32_t>(KeyCode::End);
|
||||
case VK_RETURN:
|
||||
return static_cast<std::int32_t>(KeyCode::Enter);
|
||||
case VK_SPACE:
|
||||
return static_cast<std::int32_t>(KeyCode::Space);
|
||||
case VK_ESCAPE:
|
||||
return static_cast<std::int32_t>(KeyCode::Escape);
|
||||
default:
|
||||
return static_cast<std::int32_t>(KeyCode::None);
|
||||
}
|
||||
}
|
||||
|
||||
ScenarioLayout BuildScenarioLayout(float width, float height) {
|
||||
constexpr float margin = 20.0f;
|
||||
constexpr float leftWidth = 430.0f;
|
||||
constexpr float gap = 16.0f;
|
||||
ScenarioLayout BuildScenarioLayout(
|
||||
float width,
|
||||
float height,
|
||||
const XCEngine::Tests::EditorUI::EditorValidationShellMetrics& shellMetrics) {
|
||||
const float margin = shellMetrics.margin;
|
||||
constexpr float leftWidth = 440.0f;
|
||||
const float gap = shellMetrics.gap;
|
||||
|
||||
ScenarioLayout layout = {};
|
||||
layout.introRect = UIRect(margin, margin, leftWidth, 220.0f);
|
||||
layout.introRect = UIRect(margin, margin, leftWidth, 240.0f);
|
||||
layout.controlRect = UIRect(margin, layout.introRect.y + layout.introRect.height + gap, leftWidth, 84.0f);
|
||||
layout.stateRect = UIRect(
|
||||
margin,
|
||||
layout.controlRect.y + layout.controlRect.height + gap,
|
||||
leftWidth,
|
||||
(std::max)(220.0f, height - (layout.controlRect.y + layout.controlRect.height + gap) - margin));
|
||||
(std::max)(250.0f, height - (layout.controlRect.y + layout.controlRect.height + gap) - margin));
|
||||
layout.previewRect = UIRect(
|
||||
leftWidth + margin * 2.0f,
|
||||
margin,
|
||||
@@ -132,7 +141,7 @@ ScenarioLayout BuildScenarioLayout(float width, float height) {
|
||||
layout.fieldRect = UIRect(
|
||||
layout.previewRect.x + 24.0f,
|
||||
layout.previewRect.y + 82.0f,
|
||||
320.0f,
|
||||
340.0f,
|
||||
32.0f);
|
||||
|
||||
const float buttonWidth = (layout.controlRect.width - 44.0f) * 0.5f;
|
||||
@@ -147,31 +156,48 @@ ScenarioLayout BuildScenarioLayout(float width, float height) {
|
||||
void DrawCard(
|
||||
UIDrawList& drawList,
|
||||
const UIRect& rect,
|
||||
const XCEngine::Tests::EditorUI::EditorValidationShellPalette& shellPalette,
|
||||
const XCEngine::Tests::EditorUI::EditorValidationShellMetrics& shellMetrics,
|
||||
std::string_view title,
|
||||
std::string_view subtitle = {}) {
|
||||
drawList.AddFilledRect(rect, kCardBg, 10.0f);
|
||||
drawList.AddRectOutline(rect, kCardBorder, 1.0f, 10.0f);
|
||||
drawList.AddText(UIPoint(rect.x + 16.0f, rect.y + 14.0f), std::string(title), kTextPrimary, 17.0f);
|
||||
drawList.AddFilledRect(rect, shellPalette.cardBackground, shellMetrics.cardRadius);
|
||||
drawList.AddRectOutline(rect, shellPalette.cardBorder, 1.0f, shellMetrics.cardRadius);
|
||||
drawList.AddText(
|
||||
UIPoint(rect.x + 16.0f, rect.y + 14.0f),
|
||||
std::string(title),
|
||||
shellPalette.textPrimary,
|
||||
shellMetrics.titleFontSize);
|
||||
if (!subtitle.empty()) {
|
||||
drawList.AddText(UIPoint(rect.x + 16.0f, rect.y + 40.0f), std::string(subtitle), kTextMuted, 12.0f);
|
||||
drawList.AddText(
|
||||
UIPoint(rect.x + 16.0f, rect.y + 40.0f),
|
||||
std::string(subtitle),
|
||||
shellPalette.textMuted,
|
||||
shellMetrics.bodyFontSize);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawButton(
|
||||
UIDrawList& drawList,
|
||||
const ButtonLayout& button,
|
||||
const XCEngine::Tests::EditorUI::EditorValidationShellPalette& shellPalette,
|
||||
const XCEngine::Tests::EditorUI::EditorValidationShellMetrics& shellMetrics,
|
||||
bool hovered) {
|
||||
drawList.AddFilledRect(button.rect, hovered ? kButtonHoverBg : kButtonBg, 8.0f);
|
||||
drawList.AddRectOutline(button.rect, kCardBorder, 1.0f, 8.0f);
|
||||
drawList.AddText(UIPoint(button.rect.x + 16.0f, button.rect.y + 10.0f), button.label, kTextPrimary, 12.0f);
|
||||
drawList.AddFilledRect(
|
||||
button.rect,
|
||||
hovered ? shellPalette.buttonHoverBackground : shellPalette.buttonBackground,
|
||||
shellMetrics.buttonRadius);
|
||||
drawList.AddRectOutline(button.rect, shellPalette.cardBorder, 1.0f, shellMetrics.buttonRadius);
|
||||
drawList.AddText(
|
||||
UIPoint(button.rect.x + 16.0f, button.rect.y + 10.0f),
|
||||
button.label,
|
||||
shellPalette.textPrimary,
|
||||
shellMetrics.bodyFontSize);
|
||||
}
|
||||
|
||||
std::string DescribeHitTarget(const UIEditorEnumFieldHitTarget& hitTarget) {
|
||||
switch (hitTarget.kind) {
|
||||
case UIEditorEnumFieldHitTargetKind::PreviousButton:
|
||||
return "previous";
|
||||
case UIEditorEnumFieldHitTargetKind::NextButton:
|
||||
return "next";
|
||||
case UIEditorEnumFieldHitTargetKind::DropdownArrow:
|
||||
return "dropdown_arrow";
|
||||
case UIEditorEnumFieldHitTargetKind::ValueBox:
|
||||
return "value_box";
|
||||
case UIEditorEnumFieldHitTargetKind::Row:
|
||||
@@ -361,6 +387,14 @@ private:
|
||||
m_captureRoot =
|
||||
ResolveRepoRootPath() / "tests/UI/Editor/integration/shell/enum_field_basic/captures";
|
||||
m_autoScreenshot.Initialize(m_captureRoot);
|
||||
const auto themeLoad =
|
||||
XCEngine::Tests::EditorUI::LoadEditorValidationTheme(ResolveValidationThemePath());
|
||||
if (themeLoad.succeeded) {
|
||||
m_theme = themeLoad.theme;
|
||||
m_themeStatus = "loaded";
|
||||
} else {
|
||||
m_themeStatus = themeLoad.error.empty() ? "fallback" : themeLoad.error;
|
||||
}
|
||||
|
||||
ResetScenario();
|
||||
return true;
|
||||
@@ -386,7 +420,20 @@ private:
|
||||
GetClientRect(m_hwnd, &clientRect);
|
||||
const float width = static_cast<float>((std::max)(1L, clientRect.right - clientRect.left));
|
||||
const float height = static_cast<float>((std::max)(1L, clientRect.bottom - clientRect.top));
|
||||
return BuildScenarioLayout(width, height);
|
||||
return BuildScenarioLayout(
|
||||
width,
|
||||
height,
|
||||
XCEngine::Tests::EditorUI::ResolveEditorValidationShellMetrics(m_theme));
|
||||
}
|
||||
|
||||
UIRect GetViewportRect() const {
|
||||
RECT clientRect = {};
|
||||
GetClientRect(m_hwnd, &clientRect);
|
||||
return UIRect(
|
||||
0.0f,
|
||||
0.0f,
|
||||
static_cast<float>((std::max)(1L, clientRect.right - clientRect.left)),
|
||||
static_cast<float>((std::max)(1L, clientRect.bottom - clientRect.top)));
|
||||
}
|
||||
|
||||
void ResetScenario() {
|
||||
@@ -410,14 +457,19 @@ private:
|
||||
return;
|
||||
}
|
||||
|
||||
m_spec.selectedIndex = m_selectedIndex;
|
||||
const ScenarioLayout layout = GetLayout();
|
||||
const auto fieldMetrics = XCEngine::UI::Editor::ResolveUIEditorEnumFieldMetrics(m_theme);
|
||||
const auto popupMetrics = XCEngine::UI::Editor::ResolveUIEditorMenuPopupMetrics(m_theme);
|
||||
m_spec.selectedIndex = m_selectedIndex;
|
||||
m_frame = UpdateUIEditorEnumFieldInteraction(
|
||||
m_interactionState,
|
||||
m_selectedIndex,
|
||||
layout.fieldRect,
|
||||
m_spec,
|
||||
{});
|
||||
{},
|
||||
fieldMetrics,
|
||||
popupMetrics,
|
||||
GetViewportRect());
|
||||
m_spec.selectedIndex = m_selectedIndex;
|
||||
}
|
||||
|
||||
@@ -511,13 +563,18 @@ private:
|
||||
|
||||
UIEditorEnumFieldInteractionResult PumpEvents(std::vector<UIInputEvent> events) {
|
||||
const ScenarioLayout layout = GetLayout();
|
||||
const auto fieldMetrics = XCEngine::UI::Editor::ResolveUIEditorEnumFieldMetrics(m_theme);
|
||||
const auto popupMetrics = XCEngine::UI::Editor::ResolveUIEditorMenuPopupMetrics(m_theme);
|
||||
m_spec.selectedIndex = m_selectedIndex;
|
||||
m_frame = UpdateUIEditorEnumFieldInteraction(
|
||||
m_interactionState,
|
||||
m_selectedIndex,
|
||||
layout.fieldRect,
|
||||
m_spec,
|
||||
std::move(events));
|
||||
std::move(events),
|
||||
fieldMetrics,
|
||||
popupMetrics,
|
||||
GetViewportRect());
|
||||
m_spec.selectedIndex = m_selectedIndex;
|
||||
return m_frame.result;
|
||||
}
|
||||
@@ -527,6 +584,14 @@ private:
|
||||
m_lastResult = std::string("已切换到: ") + m_spec.options[m_selectedIndex];
|
||||
return;
|
||||
}
|
||||
if (result.popupOpened) {
|
||||
m_lastResult = "下拉菜单已展开";
|
||||
return;
|
||||
}
|
||||
if (result.popupClosed) {
|
||||
m_lastResult = "下拉菜单已关闭";
|
||||
return;
|
||||
}
|
||||
if (result.consumed) {
|
||||
m_lastResult = "控件已消费输入";
|
||||
return;
|
||||
@@ -534,6 +599,16 @@ private:
|
||||
m_lastResult = "等待交互";
|
||||
}
|
||||
|
||||
std::string ResolveHighlightedText() const {
|
||||
if (!m_frame.popupOpen ||
|
||||
m_frame.popupState.hoveredIndex == UIEditorMenuPopupInvalidIndex ||
|
||||
m_frame.popupState.hoveredIndex >= m_spec.options.size()) {
|
||||
return "(none)";
|
||||
}
|
||||
|
||||
return m_spec.options[m_frame.popupState.hoveredIndex];
|
||||
}
|
||||
|
||||
void ExecuteAction(ActionId action) {
|
||||
switch (action) {
|
||||
case ActionId::Reset:
|
||||
@@ -551,77 +626,103 @@ private:
|
||||
return;
|
||||
}
|
||||
|
||||
RECT clientRect = {};
|
||||
GetClientRect(m_hwnd, &clientRect);
|
||||
const float width = static_cast<float>((std::max)(1L, clientRect.right - clientRect.left));
|
||||
const float height = static_cast<float>((std::max)(1L, clientRect.bottom - clientRect.top));
|
||||
const ScenarioLayout layout = BuildScenarioLayout(width, height);
|
||||
const UIRect viewportRect = GetViewportRect();
|
||||
const auto shellMetrics = XCEngine::Tests::EditorUI::ResolveEditorValidationShellMetrics(m_theme);
|
||||
const auto shellPalette = XCEngine::Tests::EditorUI::ResolveEditorValidationShellPalette(m_theme);
|
||||
const ScenarioLayout layout = BuildScenarioLayout(viewportRect.width, viewportRect.height, shellMetrics);
|
||||
RefreshFrame();
|
||||
|
||||
const UIEditorEnumFieldHitTarget currentHit =
|
||||
HitTestUIEditorEnumField(m_frame.layout, m_mousePosition);
|
||||
const auto enumMetrics = XCEngine::UI::Editor::ResolveUIEditorEnumFieldMetrics(m_theme);
|
||||
const auto enumPalette = XCEngine::UI::Editor::ResolveUIEditorEnumFieldPalette(m_theme);
|
||||
const auto popupMetrics = XCEngine::UI::Editor::ResolveUIEditorMenuPopupMetrics(m_theme);
|
||||
const auto popupPalette = XCEngine::UI::Editor::ResolveUIEditorMenuPopupPalette(m_theme);
|
||||
|
||||
UIDrawData drawData = {};
|
||||
UIDrawList& drawList = drawData.EmplaceDrawList("EditorEnumFieldBasic");
|
||||
drawList.AddFilledRect(UIRect(0.0f, 0.0f, width, height), kWindowBg);
|
||||
drawList.AddFilledRect(viewportRect, shellPalette.windowBackground);
|
||||
|
||||
DrawCard(
|
||||
drawList,
|
||||
layout.introRect,
|
||||
shellPalette,
|
||||
shellMetrics,
|
||||
"这个测试在验证什么功能",
|
||||
"只验证 Editor EnumField 基础控件,不涉及 PropertyGrid 或业务 Inspector。");
|
||||
"只验证 Editor EnumField 的基础交互契约,不涉及 PropertyGrid 或业务 Inspector。");
|
||||
drawList.AddText(
|
||||
UIPoint(layout.introRect.x + 16.0f, layout.introRect.y + 72.0f),
|
||||
"1. 点击 < / > 按钮,检查枚举选项是否稳定切换。",
|
||||
kTextPrimary,
|
||||
12.0f);
|
||||
"1. 点击 value box 或 dropdown arrow,检查下拉菜单是否展开/收起。",
|
||||
shellPalette.textPrimary,
|
||||
shellMetrics.bodyFontSize);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.introRect.x + 16.0f, layout.introRect.y + 94.0f),
|
||||
"2. 控件获得 focus 后按 Left / Right / Home / End,检查键盘切换。",
|
||||
kTextPrimary,
|
||||
12.0f);
|
||||
"2. 展开后 hover 列表项,检查高亮是否稳定跟随。",
|
||||
shellPalette.textPrimary,
|
||||
shellMetrics.bodyFontSize);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.introRect.x + 16.0f, layout.introRect.y + 116.0f),
|
||||
"3. 检查 Hover / Focus / Selected / Result 是否同步更新。",
|
||||
kTextPrimary,
|
||||
12.0f);
|
||||
"3. 获得 focus 后按 Up / Down / Home / End,再按 Enter / Space 选中,Esc 关闭。",
|
||||
shellPalette.textPrimary,
|
||||
shellMetrics.bodyFontSize);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.introRect.x + 16.0f, layout.introRect.y + 138.0f),
|
||||
"4. 这个场景只覆盖基础交互契约,不提前承载任何业务面板。",
|
||||
kTextPrimary,
|
||||
12.0f);
|
||||
"4. 检查 Hover / Popup / Highlight / Selected / Result 是否同步更新。",
|
||||
shellPalette.textPrimary,
|
||||
shellMetrics.bodyFontSize);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.introRect.x + 16.0f, layout.introRect.y + 160.0f),
|
||||
"5. 按 F12 或点击截图按钮,确认自动截图路径正确。",
|
||||
shellPalette.textPrimary,
|
||||
shellMetrics.bodyFontSize);
|
||||
|
||||
DrawCard(drawList, layout.controlRect, "操作");
|
||||
DrawCard(drawList, layout.controlRect, shellPalette, shellMetrics, "操作");
|
||||
for (const ButtonLayout& button : layout.buttons) {
|
||||
DrawButton(drawList, button, m_hasHoveredAction && m_hoveredAction == button.action);
|
||||
DrawButton(
|
||||
drawList,
|
||||
button,
|
||||
shellPalette,
|
||||
shellMetrics,
|
||||
m_hasHoveredAction && m_hoveredAction == button.action);
|
||||
}
|
||||
|
||||
DrawCard(drawList, layout.stateRect, "状态摘要");
|
||||
DrawCard(
|
||||
drawList,
|
||||
layout.stateRect,
|
||||
shellPalette,
|
||||
shellMetrics,
|
||||
"状态摘要",
|
||||
"重点检查 hit / popup / highlight / selected / result。");
|
||||
drawList.AddText(
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 70.0f),
|
||||
"Hover: " + DescribeHitTarget(currentHit),
|
||||
kTextPrimary,
|
||||
12.0f);
|
||||
shellPalette.textPrimary,
|
||||
shellMetrics.bodyFontSize);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 94.0f),
|
||||
std::string("Focused: ") + (m_interactionState.fieldState.focused ? "是" : "否"),
|
||||
kTextPrimary,
|
||||
12.0f);
|
||||
shellPalette.textPrimary,
|
||||
shellMetrics.bodyFontSize);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 118.0f),
|
||||
std::string("Active: ") + (m_interactionState.fieldState.active ? "是" : "否"),
|
||||
kTextPrimary,
|
||||
12.0f);
|
||||
std::string("Popup: ") + (m_frame.popupOpen ? "open" : "closed"),
|
||||
shellPalette.textPrimary,
|
||||
shellMetrics.bodyFontSize);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 142.0f),
|
||||
"Selected: " + ResolveUIEditorEnumFieldValueText(m_spec),
|
||||
kTextPrimary,
|
||||
12.0f);
|
||||
"Highlight: " + ResolveHighlightedText(),
|
||||
shellPalette.textPrimary,
|
||||
shellMetrics.bodyFontSize);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 166.0f),
|
||||
"Selected: " + ResolveUIEditorEnumFieldValueText(m_spec),
|
||||
shellPalette.textPrimary,
|
||||
shellMetrics.bodyFontSize);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 190.0f),
|
||||
"Result: " + m_lastResult,
|
||||
kTextPrimary,
|
||||
12.0f);
|
||||
shellPalette.textPrimary,
|
||||
shellMetrics.bodyFontSize);
|
||||
|
||||
const std::string captureSummary =
|
||||
m_autoScreenshot.HasPendingCapture()
|
||||
@@ -630,24 +731,46 @@ private:
|
||||
? std::string("F12 -> tests/UI/Editor/integration/shell/enum_field_basic/captures/")
|
||||
: m_autoScreenshot.GetLastCaptureSummary());
|
||||
drawList.AddText(
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 190.0f),
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 214.0f),
|
||||
captureSummary,
|
||||
kTextWeak,
|
||||
12.0f);
|
||||
shellPalette.textWeak,
|
||||
shellMetrics.bodyFontSize);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 238.0f),
|
||||
"Theme: " + m_themeStatus,
|
||||
shellPalette.textWeak,
|
||||
shellMetrics.bodyFontSize);
|
||||
|
||||
DrawCard(drawList, layout.previewRect, "EnumField 预览", "这里只放一个 EnumField。");
|
||||
DrawCard(
|
||||
drawList,
|
||||
layout.previewRect,
|
||||
shellPalette,
|
||||
shellMetrics,
|
||||
"EnumField 预览",
|
||||
"这里只放一个 Unity 风格 EnumField。");
|
||||
AppendUIEditorEnumField(
|
||||
drawList,
|
||||
layout.fieldRect,
|
||||
m_spec,
|
||||
m_interactionState.fieldState);
|
||||
m_interactionState.fieldState,
|
||||
enumPalette,
|
||||
enumMetrics);
|
||||
if (m_frame.popupOpen) {
|
||||
AppendUIEditorMenuPopup(
|
||||
drawList,
|
||||
m_frame.popupLayout.popupRect,
|
||||
m_frame.popupItems,
|
||||
m_frame.popupState,
|
||||
popupPalette,
|
||||
popupMetrics);
|
||||
}
|
||||
|
||||
const bool framePresented = m_renderer.Render(drawData);
|
||||
m_autoScreenshot.CaptureIfRequested(
|
||||
m_renderer,
|
||||
drawData,
|
||||
static_cast<unsigned int>(width),
|
||||
static_cast<unsigned int>(height),
|
||||
static_cast<unsigned int>(viewportRect.width),
|
||||
static_cast<unsigned int>(viewportRect.height),
|
||||
framePresented);
|
||||
}
|
||||
|
||||
@@ -660,10 +783,12 @@ private:
|
||||
std::size_t m_selectedIndex = 0u;
|
||||
UIEditorEnumFieldInteractionState m_interactionState = {};
|
||||
UIEditorEnumFieldInteractionFrame m_frame = {};
|
||||
Style::UITheme m_theme = {};
|
||||
UIPoint m_mousePosition = UIPoint(-1000.0f, -1000.0f);
|
||||
ActionId m_hoveredAction = ActionId::Reset;
|
||||
bool m_hasHoveredAction = false;
|
||||
std::string m_lastResult = {};
|
||||
std::string m_themeStatus = "fallback";
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user