Sync editor rendering and UI workspace updates
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
@@ -2,11 +2,12 @@
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <XCEditor/Core/UIEditorTreeViewInteraction.h>
|
||||
#include <XCEditor/Widgets/UIEditorTreeView.h>
|
||||
#include <XCEditor/Collections/UIEditorTreeView.h>
|
||||
#include <XCEditor/Collections/UIEditorTreeViewInteraction.h>
|
||||
#include "Host/AutoScreenshot.h"
|
||||
#include "Host/NativeRenderer.h"
|
||||
|
||||
#include <XCEngine/Input/InputTypes.h>
|
||||
#include <XCEngine/UI/DrawData.h>
|
||||
#include <XCEngine/UI/Widgets/UIExpansionModel.h>
|
||||
#include <XCEngine/UI/Widgets/UISelectionModel.h>
|
||||
@@ -28,6 +29,7 @@
|
||||
|
||||
namespace {
|
||||
|
||||
using XCEngine::Input::KeyCode;
|
||||
using XCEngine::UI::UIColor;
|
||||
using XCEngine::UI::UIDrawData;
|
||||
using XCEngine::UI::UIDrawList;
|
||||
@@ -101,6 +103,25 @@ bool ContainsPoint(const UIRect& rect, float x, float y) {
|
||||
y <= rect.y + rect.height;
|
||||
}
|
||||
|
||||
std::int32_t MapTreeNavigationKey(UINT keyCode) {
|
||||
switch (keyCode) {
|
||||
case VK_UP:
|
||||
return static_cast<std::int32_t>(KeyCode::Up);
|
||||
case VK_DOWN:
|
||||
return static_cast<std::int32_t>(KeyCode::Down);
|
||||
case VK_LEFT:
|
||||
return static_cast<std::int32_t>(KeyCode::Left);
|
||||
case VK_RIGHT:
|
||||
return static_cast<std::int32_t>(KeyCode::Right);
|
||||
case VK_HOME:
|
||||
return static_cast<std::int32_t>(KeyCode::Home);
|
||||
case VK_END:
|
||||
return static_cast<std::int32_t>(KeyCode::End);
|
||||
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;
|
||||
@@ -204,10 +225,11 @@ std::string JoinVisibleItems(
|
||||
constexpr std::size_t kMaxVisibleLabels = 5u;
|
||||
std::ostringstream stream = {};
|
||||
const std::size_t labelCount = (std::min)(layout.visibleItemIndices.size(), kMaxVisibleLabels);
|
||||
for (std::size_t index = 0; index < labelCount; ++index) {
|
||||
for (std::size_t index = 0u; index < labelCount; ++index) {
|
||||
if (index > 0u) {
|
||||
stream << " | ";
|
||||
}
|
||||
|
||||
const std::size_t itemIndex = layout.visibleItemIndices[index];
|
||||
if (itemIndex < items.size()) {
|
||||
stream << items[itemIndex].label;
|
||||
@@ -225,7 +247,7 @@ std::string DescribeHitTarget(
|
||||
const UIEditorTreeViewHitTarget& hitTarget,
|
||||
const std::vector<UIEditorTreeViewItem>& items) {
|
||||
if (hitTarget.itemIndex >= items.size()) {
|
||||
return "无";
|
||||
return "(none)";
|
||||
}
|
||||
|
||||
const std::string& label = items[hitTarget.itemIndex].label;
|
||||
@@ -236,7 +258,7 @@ std::string DescribeHitTarget(
|
||||
return "row: " + label;
|
||||
case UIEditorTreeViewHitTargetKind::None:
|
||||
default:
|
||||
return "无";
|
||||
return "(none)";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,6 +273,13 @@ UIInputEvent MakePointerEvent(
|
||||
return event;
|
||||
}
|
||||
|
||||
UIInputEvent MakeKeyEvent(std::int32_t keyCode) {
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::KeyDown;
|
||||
event.keyCode = keyCode;
|
||||
return event;
|
||||
}
|
||||
|
||||
class ScenarioApp {
|
||||
public:
|
||||
int Run(HINSTANCE hInstance, int nCmdShow) {
|
||||
@@ -328,11 +357,19 @@ private:
|
||||
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
if (app != nullptr && wParam == VK_F12) {
|
||||
app->m_autoScreenshot.RequestCapture("manual_f12");
|
||||
app->m_lastResult = "已请求截图,输出到 captures/latest.png";
|
||||
InvalidateRect(hwnd, nullptr, FALSE);
|
||||
return 0;
|
||||
if (app != nullptr) {
|
||||
if (wParam == VK_F12) {
|
||||
app->m_autoScreenshot.RequestCapture("manual_f12");
|
||||
app->m_lastResult = "已请求截图,输出到 captures/latest.png";
|
||||
InvalidateRect(hwnd, nullptr, FALSE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::int32_t keyCode = MapTreeNavigationKey(static_cast<UINT>(wParam));
|
||||
if (keyCode != static_cast<std::int32_t>(KeyCode::None)) {
|
||||
app->HandleNavigationKey(keyCode);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -528,6 +565,14 @@ private:
|
||||
InvalidateRect(m_hwnd, nullptr, FALSE);
|
||||
}
|
||||
|
||||
void HandleNavigationKey(std::int32_t keyCode) {
|
||||
const bool wasFocused = m_interactionState.treeViewState.focused;
|
||||
const UIEditorTreeViewInteractionResult result =
|
||||
PumpTreeEvents({ MakeKeyEvent(keyCode) });
|
||||
UpdateResultText(result, wasFocused, true);
|
||||
InvalidateRect(m_hwnd, nullptr, FALSE);
|
||||
}
|
||||
|
||||
void UpdateHoveredAction(const ScenarioLayout& layout, float x, float y) {
|
||||
const ButtonLayout* button = HitTestAction(layout, x, y);
|
||||
if (button == nullptr) {
|
||||
@@ -558,7 +603,7 @@ private:
|
||||
m_expansionModel,
|
||||
layout.treeRect,
|
||||
m_items,
|
||||
events);
|
||||
std::move(events));
|
||||
return m_treeFrame.result;
|
||||
}
|
||||
|
||||
@@ -566,6 +611,21 @@ private:
|
||||
const UIEditorTreeViewInteractionResult& result,
|
||||
bool wasFocused,
|
||||
bool insideTree) {
|
||||
if (result.keyboardNavigated && result.expansionChanged && !result.toggledItemId.empty()) {
|
||||
m_lastResult = "键盘切换展开: " + result.toggledItemId;
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.keyboardNavigated && !result.selectedItemId.empty()) {
|
||||
m_lastResult = "键盘选择: " + result.selectedItemId;
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.expansionChanged && result.selectionChanged && !result.selectedItemId.empty()) {
|
||||
m_lastResult = "折叠后回收 selection: " + result.selectedItemId;
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.expansionChanged && !result.toggledItemId.empty()) {
|
||||
m_lastResult = "切换展开: " + result.toggledItemId;
|
||||
return;
|
||||
@@ -582,7 +642,7 @@ private:
|
||||
}
|
||||
|
||||
if (insideTree) {
|
||||
m_lastResult = "点击树内空白: 只更新 focus / hover";
|
||||
m_lastResult = "点击树内空白: 仅更新 focus / hover";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -624,31 +684,31 @@ private:
|
||||
DrawCard(
|
||||
drawList,
|
||||
layout.introRect,
|
||||
"这个测试在验证什么功能",
|
||||
"只验证 Editor TreeView 基础控件,不涉及任何业务面板。");
|
||||
"这个测试在验证什么功能?",
|
||||
"只验证 Editor TreeView 的单选、层级展开/折叠和键盘导航契约,不涉及任何业务面板。");
|
||||
drawList.AddText(
|
||||
UIPoint(layout.introRect.x + 16.0f, layout.introRect.y + 72.0f),
|
||||
"1. 验证行缩进是否正确:Scene 的子项右移一层,Directional Light 再右移一层。",
|
||||
"1. 点击 row:只切换 selection,hover / selected / focused 必须能明确区分。",
|
||||
kTextPrimary,
|
||||
12.0f);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.introRect.x + 16.0f, layout.introRect.y + 94.0f),
|
||||
"2. 点击 disclosure 只切换展开/折叠,不应误改 selection。",
|
||||
"2. 点击 disclosure:只切换展开/折叠,不应误改 selection。",
|
||||
kTextPrimary,
|
||||
12.0f);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.introRect.x + 16.0f, layout.introRect.y + 116.0f),
|
||||
"3. 点击行只切换 selection;hover、selected、focused 三种视觉状态要能区分。",
|
||||
"3. 按 Left / Right:验证折叠、展开,以及父子层级跳转。",
|
||||
kTextPrimary,
|
||||
12.0f);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.introRect.x + 16.0f, layout.introRect.y + 138.0f),
|
||||
"4. 点击树外空白后 focus 应清除,但 selection 不应丢失。",
|
||||
"4. 按 Up / Down / Home / End:验证可见行导航,以及 current 与 selection 同步。",
|
||||
kTextPrimary,
|
||||
12.0f);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.introRect.x + 16.0f, layout.introRect.y + 160.0f),
|
||||
"5. 按 F12 手动截图;设置 XCUI_AUTO_CAPTURE_ON_STARTUP=1 可自动截图。",
|
||||
"5. 点击树外空白清除 focus;F12 手动截图;XCUI_AUTO_CAPTURE_ON_STARTUP=1 自动截图。",
|
||||
kTextPrimary,
|
||||
12.0f);
|
||||
|
||||
@@ -660,7 +720,7 @@ private:
|
||||
m_hasHoveredAction && m_hoveredAction == button.action);
|
||||
}
|
||||
|
||||
DrawCard(drawList, layout.stateRect, "状态摘要", "重点检查 hit / focus / selection / expanded / visible。");
|
||||
DrawCard(drawList, layout.stateRect, "状态摘要", "重点检查 hit / focus / selection / current / expanded / visible。");
|
||||
drawList.AddText(
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 70.0f),
|
||||
"Hover: " + DescribeHitTarget(currentHit, m_items),
|
||||
@@ -668,7 +728,7 @@ private:
|
||||
12.0f);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 94.0f),
|
||||
std::string("Focused: ") + (m_interactionState.treeViewState.focused ? "开" : "关"),
|
||||
std::string("Focused: ") + (m_interactionState.treeViewState.focused ? "on" : "off"),
|
||||
kTextPrimary,
|
||||
12.0f);
|
||||
drawList.AddText(
|
||||
@@ -679,17 +739,25 @@ private:
|
||||
12.0f);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 142.0f),
|
||||
"Expanded: " + JoinExpandedItems(m_items, m_expansionModel),
|
||||
std::string("Current: ") +
|
||||
(m_interactionState.keyboardNavigation.HasCurrentIndex()
|
||||
? std::to_string(m_interactionState.keyboardNavigation.GetCurrentIndex())
|
||||
: std::string("(none)")),
|
||||
kTextMuted,
|
||||
12.0f);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 166.0f),
|
||||
"Expanded: " + JoinExpandedItems(m_items, m_expansionModel),
|
||||
kTextMuted,
|
||||
12.0f);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 190.0f),
|
||||
"Visible(" + std::to_string(m_treeFrame.layout.visibleItemIndices.size()) + "): " +
|
||||
JoinVisibleItems(m_items, m_treeFrame.layout),
|
||||
kTextMuted,
|
||||
12.0f);
|
||||
drawList.AddText(
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 190.0f),
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 214.0f),
|
||||
"Result: " + m_lastResult,
|
||||
kTextPrimary,
|
||||
12.0f);
|
||||
@@ -701,12 +769,12 @@ private:
|
||||
? std::string("F12 -> tests/UI/Editor/integration/shell/tree_view_basic/captures/")
|
||||
: m_autoScreenshot.GetLastCaptureSummary());
|
||||
drawList.AddText(
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 216.0f),
|
||||
UIPoint(layout.stateRect.x + 16.0f, layout.stateRect.y + 238.0f),
|
||||
captureSummary,
|
||||
kTextWeak,
|
||||
12.0f);
|
||||
|
||||
DrawCard(drawList, layout.previewRect, "TreeView 预览", "这里只放一个 TreeView,不混入 Hierarchy/Inspector 等业务内容。");
|
||||
DrawCard(drawList, layout.previewRect, "TreeView 预览", "这里只放一个 TreeView,不混入 Hierarchy / Inspector 等业务内容。");
|
||||
AppendUIEditorTreeViewBackground(
|
||||
drawList,
|
||||
m_treeFrame.layout,
|
||||
|
||||
Reference in New Issue
Block a user