Refactor XCUI editor module layout

This commit is contained in:
2026-04-10 00:41:28 +08:00
parent 4b47764f26
commit 02a0e626fe
263 changed files with 12396 additions and 7592 deletions

View File

@@ -1,9 +1,9 @@
#ifndef NOMINMAX
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <XCEditor/Core/UIEditorWorkspaceController.h>
#include <XCEditor/Core/UIEditorWorkspaceLayoutPersistence.h>
#include <XCEditor/Shell/UIEditorWorkspaceController.h>
#include <XCEditor/Shell/UIEditorWorkspaceLayoutPersistence.h>
#include "Host/AutoScreenshot.h"
#include "Host/NativeRenderer.h"
@@ -732,13 +732,13 @@ private:
const UIRect footerRect(margin, height - 100.0f, width - margin * 2.0f, 80.0f);
DrawCard(drawList, headerRect, "测试功能Editor Layout Persistence", "只验证 Save / Load / Load Invalid / Reset 的布局恢复链路;不验证业务面板。");
drawList.AddText(UIPoint(headerRect.x + 18.0f, headerRect.y + 70.0f), "1. 点 `1 Hide Active`,把 Document A 隐藏active 应切到 doc-bvisible 应变成 `doc-b, details`。", kTextPrimary, 13.0f);
drawList.AddText(UIPoint(headerRect.x + 18.0f, headerRect.y + 70.0f), "1. 点 `1 Hide Active`,把 Document A 隐藏active 应切到 `doc-b`visible 应变成 `doc-b, details`。", kTextPrimary, 13.0f);
drawList.AddText(UIPoint(headerRect.x + 18.0f, headerRect.y + 92.0f), "2. 点 `2 Save Layout` 保存当前布局;右侧 Saved 摘要必须记录刚才的 active/visible。", kTextPrimary, 13.0f);
drawList.AddText(UIPoint(headerRect.x + 18.0f, headerRect.y + 114.0f), "3. 再点 `3 Close Doc B` 或 `5 Activate Details` 改状态,然后点 `4 Load Layout`;当前状态必须恢复到保存时。", kTextPrimary, 13.0f);
drawList.AddText(UIPoint(headerRect.x + 18.0f, headerRect.y + 136.0f), "4. 点 `6 Load Invalid`Result 必须是 Rejected且当前 active/visible 不得被污染。", kTextPrimary, 13.0f);
drawList.AddText(UIPoint(headerRect.x + 18.0f, headerRect.y + 136.0f), "4. 点 `6 Load Invalid`Result 必须是 Rejected且当前 active/visible 不得被污染。", kTextPrimary, 13.0f);
drawList.AddText(UIPoint(headerRect.x + 18.0f, headerRect.y + 158.0f), "5. `R Reset` 必须回到基线 active=doc-a按 `F12` 保存当前窗口截图。", kTextPrimary, 13.0f);
DrawCard(drawList, actionRect, "操作区", "只保留这一步需要检查的布局保存/恢复动作。");
DrawCard(drawList, actionRect, "操作区", "这里只保留这一步需要检查的布局保存/恢复动作。");
DrawCard(drawList, stateRect, "状态摘要", "左侧看 Current右侧看 Saved重点检查 active、visible 和坏数据恢复。");
DrawCard(drawList, footerRect, "最近结果", "显示最近一次操作、状态和当前 validation。");

View File

@@ -1,9 +1,9 @@
#ifndef NOMINMAX
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <XCEditor/Core/UIEditorPanelHostLifecycle.h>
#include <XCEditor/Core/UIEditorWorkspaceController.h>
#include <XCEditor/Shell/UIEditorPanelHostLifecycle.h>
#include <XCEditor/Shell/UIEditorWorkspaceController.h>
#include "Host/AutoScreenshot.h"
#include "Host/NativeRenderer.h"
@@ -247,7 +247,7 @@ void DrawHostStateCard(
if (!attached) {
footer = "host 已 detached";
} else if (!visible) {
footer = "host 保 attach但当前不在屏幕";
footer = "host 保 attached,但当前不在屏幕";
} else if (focused) {
footer = "当前 host 已 visible + active + focused";
} else if (active) {
@@ -500,7 +500,8 @@ private:
if (action == ActionId::Capture) {
m_autoScreenshot.RequestCapture("manual_button");
m_lastStatus = "Ready";
m_lastMessage = "截图已排队,输出到 tests/UI/Editor/integration/state/panel_host_lifecycle/captures/。";
m_lastMessage =
"截图已排队,输出到 tests/UI/Editor/integration/state/panel_host_lifecycle/captures/。";
return;
}
@@ -560,10 +561,14 @@ private:
UIDrawList& drawList = drawData.EmplaceDrawList("PanelHostLifecycle");
drawList.AddFilledRect(UIRect(0.0f, 0.0f, width, height), kWindowBg);
DrawCard(drawList, m_introRect, "这个测试验证什么功能", "只验证 Editor panel host lifecycle contract不做业务面板。");
DrawCard(
drawList,
m_introRect,
"这个测试验证什么功能?",
"只验证 Editor panel host lifecycle contract不做业务面板。");
drawList.AddText(UIPoint(m_introRect.x + 18.0f, m_introRect.y + 72.0f), "1. 验证 attach/detach 由 panel open/close 驱动,而不是由 visible 驱动。", kTextPrimary, 12.0f);
drawList.AddText(UIPoint(m_introRect.x + 18.0f, m_introRect.y + 94.0f), "2. 验证非选中 tab 依然 attached但 visible=false。", kTextPrimary, 12.0f);
drawList.AddText(UIPoint(m_introRect.x + 18.0f, m_introRect.y + 116.0f), "3. 验证 active focused 是两层不同状态focus 由外部 request 决定。", kTextPrimary, 12.0f);
drawList.AddText(UIPoint(m_introRect.x + 18.0f, m_introRect.y + 116.0f), "3. 验证 active focused 是两层不同状态focus 由外部 request 决定。", kTextPrimary, 12.0f);
drawList.AddText(UIPoint(m_introRect.x + 18.0f, m_introRect.y + 138.0f), "4. 验证 hide/close/reopen/activate 会输出稳定的 lifecycle events。", kTextPrimary, 12.0f);
drawList.AddText(UIPoint(m_introRect.x + 18.0f, m_introRect.y + 164.0f), "建议操作:先看 doc-b 默认 attached 但 hidden再点 Hide Active / Focus Active / Close Doc B / Open Doc B。", kTextWeak, 11.0f);

View File

@@ -1,8 +1,8 @@
#ifndef NOMINMAX
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <XCEditor/Core/UIEditorWorkspaceController.h>
#include <XCEditor/Shell/UIEditorWorkspaceController.h>
#include "Host/AutoScreenshot.h"
#include "Host/NativeRenderer.h"
@@ -510,7 +510,7 @@ private:
const UIRect footerRect(margin, height - 96.0f, width - margin * 2.0f, 76.0f);
DrawCard(drawList, headerRect, "测试功能Editor Command Dispatch + Workspace Controller", "只验证命令分发、状态变更结果和 panel session 联动;不验证业务面板。");
drawList.AddText(UIPoint(headerRect.x + 18.0f, headerRect.y + 70.0f), "1. 点 `1 Hide Active`Result 应是 Changedactive 从 doc-a 切到 doc-bselected tab 也同步到 B。", kTextPrimary, 13.0f);
drawList.AddText(UIPoint(headerRect.x + 18.0f, headerRect.y + 70.0f), "1. 点 `1 Hide Active`Result 应是 Changedactive 从 doc-a 切到 doc-bselected tab 也同步到 B。", kTextPrimary, 13.0f);
drawList.AddText(UIPoint(headerRect.x + 18.0f, headerRect.y + 92.0f), "2. 再点 `1 Hide Active`,如果当前 panel 已 hiddenResult 应变成 NoOp而不是乱改状态。", kTextPrimary, 13.0f);
drawList.AddText(UIPoint(headerRect.x + 18.0f, headerRect.y + 114.0f), "3. 点 `3 Close Doc B` 后再点 `5 Activate Details` / `4 Open Doc B`,检查 Changed / Rejected / NoOp 是否符合提示。", kTextPrimary, 13.0f);
drawList.AddText(UIPoint(headerRect.x + 18.0f, headerRect.y + 136.0f), "4. `R Reset` 必须把状态拉回基线;按 `F12` 保存当前窗口截图。", kTextPrimary, 13.0f);

View File

@@ -1,8 +1,8 @@
#ifndef NOMINMAX
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <XCEditor/Core/UIEditorShortcutManager.h>
#include <XCEditor/Foundation/UIEditorShortcutManager.h>
#include "Host/AutoScreenshot.h"
#include "Host/InputModifierTracker.h"
#include "Host/NativeRenderer.h"

View File

@@ -1,9 +1,9 @@
#ifndef NOMINMAX
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <XCEditor/Core/UIEditorViewportInputBridge.h>
#include <XCEditor/Widgets/UIEditorViewportSlot.h>
#include <XCEditor/Shell/UIEditorViewportInputBridge.h>
#include <XCEditor/Shell/UIEditorViewportSlot.h>
#include "Host/AutoScreenshot.h"
#include "Host/InputModifierTracker.h"
#include "Host/NativeRenderer.h"
@@ -58,7 +58,7 @@ using XCEngine::UI::Editor::Widgets::UIEditorViewportSlotToolItem;
using XCEngine::UI::Editor::Widgets::UIEditorViewportSlotToolSlot;
constexpr const wchar_t* kWindowClassName = L"XCUIEditorViewportInputBridgeBasicValidation";
constexpr const wchar_t* kWindowTitle = L"XCUI Editor | Viewport Input Bridge";
constexpr const wchar_t* kWindowTitle = L"XCUI 编辑器 | 视口输入桥接";
constexpr UIColor kWindowBg(0.12f, 0.12f, 0.12f, 1.0f);
constexpr UIColor kCardBg(0.18f, 0.18f, 0.18f, 1.0f);
@@ -98,7 +98,7 @@ bool ContainsPoint(const UIRect& rect, float x, float y) {
}
std::string BoolText(bool value) {
return value ? "On" : "Off";
return value ? "" : "";
}
std::string FormatFloat(float value) {
@@ -473,7 +473,7 @@ private:
m_bridgeState = {};
m_bridgeFrame = {};
m_pendingEvents.clear();
m_lastResult = "Ready";
m_lastResult = "就绪";
}
void QueuePointerEvent(UIInputEventType type, UIPointerButton button, WPARAM wParam, LPARAM lParam) {
@@ -565,12 +565,12 @@ private:
if (buttonState.action == ActionId::Reset) {
ResetScenario();
m_lastResult = "状态已重置";
m_lastResult = "场景已重置";
} else {
m_autoScreenshot.RequestCapture("manual_button");
InvalidateRect(m_hwnd, nullptr, FALSE);
UpdateWindow(m_hwnd);
m_lastResult = "截图已排队";
m_lastResult = "截图已加入队列";
}
break;
@@ -583,8 +583,8 @@ private:
UIEditorViewportSlotChrome BuildChrome() const {
UIEditorViewportSlotChrome chrome = {};
chrome.title = "Scene View";
chrome.subtitle = "ViewportInputBridge 验证面板";
chrome.title = "场景视图";
chrome.subtitle = "视口输入桥接验证";
chrome.showTopBar = true;
chrome.showBottomBar = true;
chrome.topBarHeight = 40.0f;
@@ -597,23 +597,23 @@ private:
frame.hasTexture = true;
frame.texture = { 1u, 1280u, 720u };
frame.presentedSize = { 1280.0f, 720.0f };
frame.statusText = "Fake viewport frame";
frame.statusText = "模拟视口帧";
return frame;
}
std::vector<UIEditorViewportSlotToolItem> BuildToolItems() const {
return {
{ "mode", "Perspective", UIEditorViewportSlotToolSlot::Leading, true, true, 98.0f },
{ "input", "Input", UIEditorViewportSlotToolSlot::Trailing, true, true, 58.0f }
{ "mode", "透视", UIEditorViewportSlotToolSlot::Leading, true, true, 98.0f },
{ "input", "输入", UIEditorViewportSlotToolSlot::Trailing, true, true, 58.0f }
};
}
std::vector<UIEditorStatusBarSegment> BuildStatusSegments() const {
return {
{ "hover", std::string("Hover ") + BoolText(m_bridgeFrame.hovered), UIEditorStatusBarSlot::Leading, {}, true, true, 96.0f },
{ "focus", std::string("Focus ") + BoolText(m_bridgeFrame.focused), UIEditorStatusBarSlot::Leading, {}, true, false, 92.0f },
{ "capture", std::string("Capture ") + BoolText(m_bridgeFrame.captured), UIEditorStatusBarSlot::Trailing, {}, true, true, 110.0f },
{ "wheel", "Wheel " + FormatFloat(m_bridgeFrame.wheelDelta), UIEditorStatusBarSlot::Trailing, {}, true, false, 86.0f }
{ "hover", std::string("悬停 ") + BoolText(m_bridgeFrame.hovered), UIEditorStatusBarSlot::Leading, {}, true, true, 96.0f },
{ "focus", std::string("焦点 ") + BoolText(m_bridgeFrame.focused), UIEditorStatusBarSlot::Leading, {}, true, false, 92.0f },
{ "capture", std::string("捕获 ") + BoolText(m_bridgeFrame.captured), UIEditorStatusBarSlot::Trailing, {}, true, true, 110.0f },
{ "wheel", "滚轮 " + FormatFloat(m_bridgeFrame.wheelDelta), UIEditorStatusBarSlot::Trailing, {}, true, false, 86.0f }
};
}
@@ -645,7 +645,7 @@ private:
const float buttonHeight = 34.0f;
m_buttons = {
{ ActionId::Reset, "Reset", UIRect(m_controlsRect.x + 16.0f, m_controlsRect.y + 54.0f, m_controlsRect.width - 32.0f, buttonHeight) },
{ ActionId::Reset, "重置", UIRect(m_controlsRect.x + 16.0f, m_controlsRect.y + 54.0f, m_controlsRect.width - 32.0f, buttonHeight) },
{ ActionId::Capture, "截图", UIRect(m_controlsRect.x + 16.0f, m_controlsRect.y + 98.0f, m_controlsRect.width - 32.0f, buttonHeight) }
};
@@ -676,25 +676,25 @@ private:
m_layout.inputRect,
frameEvents);
if (m_bridgeFrame.focusLost) {
m_lastResult = "FocusLost";
m_lastResult = "焦点丢失";
} else if (m_bridgeFrame.focusGained) {
m_lastResult = "FocusGained";
m_lastResult = "获得焦点";
} else if (m_bridgeFrame.captureStarted) {
m_lastResult = "CaptureStarted";
m_lastResult = "开始捕获";
} else if (m_bridgeFrame.captureEnded) {
m_lastResult = "CaptureEnded";
m_lastResult = "结束捕获";
} else if (!m_bridgeFrame.characters.empty()) {
m_lastResult = "Char " + DescribeCharacters(m_bridgeFrame);
m_lastResult = "字符 " + DescribeCharacters(m_bridgeFrame);
} else if (!m_bridgeFrame.pressedKeyCodes.empty()) {
m_lastResult = "KeyDown " + FormatKeyCodes(m_bridgeFrame.pressedKeyCodes);
m_lastResult = "按键按下 " + FormatKeyCodes(m_bridgeFrame.pressedKeyCodes);
} else if (!m_bridgeFrame.releasedKeyCodes.empty()) {
m_lastResult = "KeyUp " + FormatKeyCodes(m_bridgeFrame.releasedKeyCodes);
m_lastResult = "按键抬起 " + FormatKeyCodes(m_bridgeFrame.releasedKeyCodes);
} else if (m_bridgeFrame.wheelDelta != 0.0f) {
m_lastResult = "Wheel " + std::to_string(static_cast<int>(m_bridgeFrame.wheelDelta));
m_lastResult = "滚轮 " + std::to_string(static_cast<int>(m_bridgeFrame.wheelDelta));
} else if (m_bridgeFrame.pointerPressedInside) {
m_lastResult = "PointerDownInside";
m_lastResult = "内部按下";
} else if (m_bridgeFrame.pointerReleasedInside) {
m_lastResult = "PointerUpInside";
m_lastResult = "内部抬起";
}
UIEditorViewportSlotState slotState = {};
@@ -711,35 +711,35 @@ private:
drawList,
m_introRect,
"测试功能ViewportInputBridge",
"只验证 Editor viewport 输入桥,不混入 Scene/Game 业务。");
"只验证 Editor viewport 输入桥,不混入 Scene/Game 业务。");
drawList.AddText(
UIPoint(m_introRect.x + 16.0f, m_introRect.y + 66.0f),
"检查1hover / focus / capture / local 坐标。",
"检查hover / focus / capture / local 坐标。",
kTextMuted,
11.0f);
drawList.AddText(
UIPoint(m_introRect.x + 16.0f, m_introRect.y + 86.0f),
"检查2surface 内左键按下后Focus + Capture 进入。",
"检查surface 内左键按下后Focus + Capture 进入。",
kTextMuted,
11.0f);
drawList.AddText(
UIPoint(m_introRect.x + 16.0f, m_introRect.y + 106.0f),
"检查3drag 出 surface 后Capture 保留Local Pos 继续更新。",
"检查drag 出 surface 后Capture 保留Local Pos 继续更新。",
kTextMuted,
11.0f);
drawList.AddText(
UIPoint(m_introRect.x + 16.0f, m_introRect.y + 126.0f),
"检查4release 后Capture 必须释放。",
"检查release 后Capture 必须释放。",
kTextMuted,
11.0f);
drawList.AddText(
UIPoint(m_introRect.x + 16.0f, m_introRect.y + 146.0f),
"检查5:滚轮 / 按键 / 字符只在 Focus 下进入 frame。",
"检查:滚轮 / 按键 / 字符只在 Focus 下进入 frame。",
kTextMuted,
11.0f);
drawList.AddText(
UIPoint(m_introRect.x + 16.0f, m_introRect.y + 166.0f),
"操作hoverclickdragwheelA/W/F/Space输入字符。",
"操作hoverclickdragwheelA/W/F/Space输入字符。",
kTextMuted,
11.0f);
drawList.AddText(
@@ -753,7 +753,7 @@ private:
kTextWeak,
11.0f);
DrawCard(drawList, m_controlsRect, "操作", "只保留 Reset / 截图两个辅助操作。");
DrawCard(drawList, m_controlsRect, "操作", "只保留 Reset / 截图 两个辅助操作。");
for (const ButtonState& button : m_buttons) {
DrawButton(drawList, button);
}
@@ -796,7 +796,7 @@ private:
addStateLine("Result: " + m_lastResult, kTextMuted);
addStateLine(captureSummary, kTextWeak);
DrawCard(drawList, m_previewRect, "Preview", "这里只放一个 ViewportSlot用它承载输入边界。");
DrawCard(drawList, m_previewRect, "预览", "这里只放一个 ViewportSlot用它承载输入边界。");
drawList.AddFilledRect(
UIRect(
m_previewRect.x + 12.0f,