@@ -0,0 +1,456 @@
# ifndef NOMINMAX
# define NOMINMAX
# endif
# include <XCEditor/Core/UIEditorTheme.h>
# include <XCEditor/Core/UIEditorVector4FieldInteraction.h>
# include <XCEditor/Widgets/UIEditorVector4Field.h>
# include "EditorValidationTheme.h"
# include "Host/AutoScreenshot.h"
# include "Host/NativeRenderer.h"
# include <XCEngine/Input/InputTypes.h>
# include <XCEngine/UI/DrawData.h>
# include <windows.h>
# include <windowsx.h>
# include <algorithm>
# include <filesystem>
# include <string>
# include <vector>
# ifndef XCENGINE_EDITOR_UI_TESTS_REPO_ROOT
# define XCENGINE_EDITOR_UI_TESTS_REPO_ROOT "."
# endif
namespace {
using XCEngine : : Input : : KeyCode ;
using XCEngine : : UI : : UIDrawData ;
using XCEngine : : UI : : UIDrawList ;
using XCEngine : : UI : : UIInputEvent ;
using XCEngine : : UI : : UIInputEventType ;
using XCEngine : : UI : : UIPoint ;
using XCEngine : : UI : : UIPointerButton ;
using XCEngine : : UI : : UIRect ;
using XCEngine : : UI : : Editor : : Host : : AutoScreenshotController ;
using XCEngine : : UI : : Editor : : Host : : NativeRenderer ;
using XCEngine : : UI : : Editor : : UIEditorVector4FieldInteractionFrame ;
using XCEngine : : UI : : Editor : : UIEditorVector4FieldInteractionResult ;
using XCEngine : : UI : : Editor : : UIEditorVector4FieldInteractionState ;
using XCEngine : : UI : : Editor : : UpdateUIEditorVector4FieldInteraction ;
using XCEngine : : UI : : Editor : : Widgets : : AppendUIEditorVector4Field ;
using XCEngine : : UI : : Editor : : Widgets : : FormatUIEditorVector4FieldComponentValue ;
using XCEngine : : UI : : Editor : : Widgets : : HitTestUIEditorVector4Field ;
using XCEngine : : UI : : Editor : : Widgets : : UIEditorVector4FieldHitTarget ;
using XCEngine : : UI : : Editor : : Widgets : : UIEditorVector4FieldHitTargetKind ;
using XCEngine : : UI : : Editor : : Widgets : : UIEditorVector4FieldSpec ;
namespace Style = XCEngine : : UI : : Style ;
constexpr const wchar_t * kWindowClassName = L " XCUIEditorVector4FieldBasicValidation " ;
constexpr const wchar_t * kWindowTitle = L " XCUI Editor | Vector4Field Basic " ;
struct ScenarioLayout {
UIRect introRect = { } ;
UIRect stateRect = { } ;
UIRect previewRect = { } ;
UIRect inspectorRect = { } ;
UIRect inspectorHeaderRect = { } ;
UIRect sectionRect = { } ;
UIRect fieldRect = { } ;
} ;
std : : filesystem : : path ResolveRepoRootPath ( ) {
std : : string root = XCENGINE_EDITOR_UI_TESTS_REPO_ROOT ;
if ( root . size ( ) > = 2u & & root . front ( ) = = ' " ' & & root . back ( ) = = ' " ' ) {
root = root . substr ( 1u , root . size ( ) - 2u ) ;
}
return std : : filesystem : : path ( root ) . lexically_normal ( ) ;
}
std : : filesystem : : path ResolveValidationThemePath ( ) {
return ( ResolveRepoRootPath ( ) / " tests/UI/Editor/integration/shared/themes/editor_validation.xctheme " )
. lexically_normal ( ) ;
}
std : : int32_t MapVectorKey ( 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_TAB : return static_cast < std : : int32_t > ( KeyCode : : Tab ) ;
case VK_RETURN : return static_cast < std : : int32_t > ( KeyCode : : Enter ) ;
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 ,
const XCEngine : : Tests : : EditorUI : : EditorValidationShellMetrics & shellMetrics ) {
const float margin = shellMetrics . margin ;
constexpr float leftWidth = 470.0f ;
const float gap = shellMetrics . gap ;
ScenarioLayout layout = { } ;
layout . introRect = UIRect ( margin , margin , leftWidth , 230.0f ) ;
layout . stateRect = UIRect (
margin ,
layout . introRect . y + layout . introRect . height + gap ,
leftWidth ,
( std : : max ) ( 280.0f , height - ( layout . introRect . y + layout . introRect . height + gap ) - margin ) ) ;
layout . previewRect = UIRect (
leftWidth + margin * 2.0f ,
margin ,
( std : : max ) ( 480.0f , width - leftWidth - margin * 3.0f ) ,
height - margin * 2.0f ) ;
layout . inspectorRect = UIRect ( layout . previewRect . x + 18.0f , layout . previewRect . y + 54.0f , 460.0f , 174.0f ) ;
layout . inspectorHeaderRect = UIRect ( layout . inspectorRect . x , layout . inspectorRect . y , layout . inspectorRect . width , 24.0f ) ;
layout . sectionRect = UIRect ( layout . inspectorRect . x , layout . inspectorRect . y + 24.0f , layout . inspectorRect . width , 24.0f ) ;
layout . fieldRect = UIRect ( layout . inspectorRect . x , layout . sectionRect . y + 26.0f , layout . inspectorRect . width , 22.0f ) ;
return layout ;
}
UIInputEvent MakePointerEvent (
UIInputEventType type ,
const UIPoint & position ,
UIPointerButton button = UIPointerButton : : None ) {
UIInputEvent event = { } ;
event . type = type ;
event . position = position ;
event . pointerButton = button ;
return event ;
}
UIInputEvent MakeKeyEvent ( std : : int32_t keyCode , bool shift = false ) {
UIInputEvent event = { } ;
event . type = UIInputEventType : : KeyDown ;
event . keyCode = keyCode ;
event . modifiers . shift = shift ;
return event ;
}
UIInputEvent MakeCharacterEvent ( wchar_t character ) {
UIInputEvent event = { } ;
event . type = UIInputEventType : : Character ;
event . character = static_cast < std : : uint32_t > ( character ) ;
return event ;
}
std : : string DescribeHitTarget ( const UIEditorVector4FieldHitTarget & hitTarget ) {
if ( hitTarget . kind = = UIEditorVector4FieldHitTargetKind : : Component ) {
return std : : string ( " component_ " ) + std : : to_string ( hitTarget . componentIndex ) ;
}
if ( hitTarget . kind = = UIEditorVector4FieldHitTargetKind : : Row ) {
return " row " ;
}
return " none " ;
}
std : : string DescribeSelectedComponent ( std : : size_t componentIndex ) {
switch ( componentIndex ) {
case 0u : return " X " ;
case 1u : return " Y " ;
case 2u : return " Z " ;
case 3u : return " W " ;
default : return " none " ;
}
}
class ScenarioApp {
public :
int Run ( HINSTANCE hInstance , int nCmdShow ) {
if ( ! Initialize ( hInstance , nCmdShow ) ) {
Shutdown ( ) ;
return 1 ;
}
MSG message = { } ;
while ( message . message ! = WM_QUIT ) {
if ( PeekMessageW ( & message , nullptr , 0U , 0U , PM_REMOVE ) ) {
TranslateMessage ( & message ) ;
DispatchMessageW ( & message ) ;
continue ;
}
RenderFrame ( ) ;
Sleep ( 8 ) ;
}
Shutdown ( ) ;
return static_cast < int > ( message . wParam ) ;
}
private :
static LRESULT CALLBACK WndProc ( HWND hwnd , UINT message , WPARAM wParam , LPARAM lParam ) {
if ( message = = WM_NCCREATE ) {
const auto * createStruct = reinterpret_cast < CREATESTRUCTW * > ( lParam ) ;
auto * app = reinterpret_cast < ScenarioApp * > ( createStruct - > lpCreateParams ) ;
SetWindowLongPtrW ( hwnd , GWLP_USERDATA , reinterpret_cast < LONG_PTR > ( app ) ) ;
return TRUE ;
}
auto * app = reinterpret_cast < ScenarioApp * > ( GetWindowLongPtrW ( hwnd , GWLP_USERDATA ) ) ;
switch ( message ) {
case WM_SIZE :
if ( app ! = nullptr & & wParam ! = SIZE_MINIMIZED ) {
app - > m_renderer . Resize ( static_cast < UINT > ( LOWORD ( lParam ) ) , static_cast < UINT > ( HIWORD ( lParam ) ) ) ;
}
return 0 ;
case WM_MOUSEMOVE :
if ( app ! = nullptr ) {
app - > m_mousePosition = UIPoint ( static_cast < float > ( GET_X_LPARAM ( lParam ) ) , static_cast < float > ( GET_Y_LPARAM ( lParam ) ) ) ;
TRACKMOUSEEVENT trackEvent = { sizeof ( trackEvent ) , TME_LEAVE , hwnd , 0 } ;
TrackMouseEvent ( & trackEvent ) ;
app - > PumpEvents ( { MakePointerEvent ( UIInputEventType : : PointerMove , app - > m_mousePosition ) } ) ;
InvalidateRect ( hwnd , nullptr , FALSE ) ;
return 0 ;
}
break ;
case WM_MOUSELEAVE :
if ( app ! = nullptr ) {
app - > m_mousePosition = UIPoint ( - 1000.0f , - 1000.0f ) ;
app - > PumpEvents ( { MakePointerEvent ( UIInputEventType : : PointerLeave , app - > m_mousePosition ) } ) ;
InvalidateRect ( hwnd , nullptr , FALSE ) ;
return 0 ;
}
break ;
case WM_LBUTTONDOWN :
case WM_LBUTTONUP :
if ( app ! = nullptr ) {
app - > m_mousePosition = UIPoint ( static_cast < float > ( GET_X_LPARAM ( lParam ) ) , static_cast < float > ( GET_Y_LPARAM ( lParam ) ) ) ;
const UIInputEventType type =
message = = WM_LBUTTONDOWN ? UIInputEventType : : PointerButtonDown : UIInputEventType : : PointerButtonUp ;
app - > UpdateResultText ( app - > PumpEvents ( { MakePointerEvent ( type , app - > m_mousePosition , UIPointerButton : : Left ) } ) ) ;
InvalidateRect ( hwnd , nullptr , FALSE ) ;
return 0 ;
}
break ;
case WM_KEYDOWN :
case WM_SYSKEYDOWN :
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 ;
}
if ( wParam = = ' R ' ) {
app - > ResetScenario ( ) ;
InvalidateRect ( hwnd , nullptr , FALSE ) ;
return 0 ;
}
if ( wParam = = VK_F6 ) {
app - > UpdateResultText ( app - > PumpEvents ( { MakePointerEvent ( UIInputEventType : : FocusLost , app - > m_mousePosition ) } ) ) ;
InvalidateRect ( hwnd , nullptr , FALSE ) ;
return 0 ;
}
const std : : int32_t keyCode = MapVectorKey ( static_cast < UINT > ( wParam ) ) ;
if ( keyCode ! = static_cast < std : : int32_t > ( KeyCode : : None ) ) {
app - > UpdateResultText ( app - > PumpEvents ( { MakeKeyEvent ( keyCode , ( GetKeyState ( VK_SHIFT ) & 0x8000 ) ! = 0 ) } ) ) ;
InvalidateRect ( hwnd , nullptr , FALSE ) ;
return 0 ;
}
}
break ;
case WM_CHAR :
if ( app ! = nullptr & & wParam > = 32 ) {
app - > UpdateResultText ( app - > PumpEvents ( { MakeCharacterEvent ( static_cast < wchar_t > ( wParam ) ) } ) ) ;
InvalidateRect ( hwnd , nullptr , FALSE ) ;
return 0 ;
}
break ;
case WM_PAINT :
if ( app ! = nullptr ) {
PAINTSTRUCT paintStruct = { } ;
BeginPaint ( hwnd , & paintStruct ) ;
app - > RenderFrame ( ) ;
EndPaint ( hwnd , & paintStruct ) ;
return 0 ;
}
break ;
case WM_ERASEBKGND :
return 1 ;
case WM_DESTROY :
if ( app ! = nullptr ) {
app - > m_hwnd = nullptr ;
}
PostQuitMessage ( 0 ) ;
return 0 ;
default :
break ;
}
return DefWindowProcW ( hwnd , message , wParam , lParam ) ;
}
bool Initialize ( HINSTANCE hInstance , int nCmdShow ) {
WNDCLASSEXW windowClass = { } ;
windowClass . cbSize = sizeof ( windowClass ) ;
windowClass . style = CS_HREDRAW | CS_VREDRAW ;
windowClass . lpfnWndProc = & ScenarioApp : : WndProc ;
windowClass . hInstance = hInstance ;
windowClass . hCursor = LoadCursorW ( nullptr , IDC_ARROW ) ;
windowClass . lpszClassName = kWindowClassName ;
m_windowClassAtom = RegisterClassExW ( & windowClass ) ;
if ( m_windowClassAtom = = 0 ) {
return false ;
}
m_hwnd = CreateWindowExW ( 0 , kWindowClassName , kWindowTitle , WS_OVERLAPPEDWINDOW | WS_VISIBLE , CW_USEDEFAULT , CW_USEDEFAULT , 1560 , 920 , nullptr , nullptr , hInstance , this ) ;
if ( m_hwnd = = nullptr | | ! m_renderer . Initialize ( m_hwnd ) ) {
return false ;
}
ShowWindow ( m_hwnd , nCmdShow ) ;
UpdateWindow ( m_hwnd ) ;
m_captureRoot = ResolveRepoRootPath ( ) / " tests/UI/Editor/integration/shell/vector4_field_basic/captures " ;
m_autoScreenshot . Initialize ( m_captureRoot ) ;
const auto themeLoad = XCEngine : : Tests : : EditorUI : : LoadEditorValidationTheme ( ResolveValidationThemePath ( ) ) ;
m_theme = themeLoad . theme ;
m_themeStatus = themeLoad . succeeded ? " loaded " : ( themeLoad . error . empty ( ) ? " fallback " : themeLoad . error ) ;
ResetScenario ( ) ;
return true ;
}
void Shutdown ( ) {
m_autoScreenshot . Shutdown ( ) ;
m_renderer . Shutdown ( ) ;
if ( m_hwnd ! = nullptr & & IsWindow ( m_hwnd ) ) {
DestroyWindow ( m_hwnd ) ;
}
if ( m_windowClassAtom ! = 0 ) {
UnregisterClassW ( kWindowClassName , GetModuleHandleW ( nullptr ) ) ;
}
}
void ResetScenario ( ) {
m_spec = { } ;
m_spec . fieldId = " rotation " ;
m_spec . label = " Rotation " ;
m_spec . values = { 1.25 , - 2.5 , 4.75 , 0.5 } ;
m_spec . step = 0.25 ;
m_spec . minValue = - 10.0 ;
m_spec . maxValue = 10.0 ;
m_interactionState = { } ;
m_interactionState . vector4FieldState . focused = true ;
m_interactionState . vector4FieldState . selectedComponentIndex = 0u ;
m_mousePosition = UIPoint ( - 1000.0f , - 1000.0f ) ;
m_lastResult = " 已重置到默认 Vector4Field 状态 " ;
PumpEvents ( { } ) ;
}
UIEditorVector4FieldInteractionResult PumpEvents ( std : : vector < UIInputEvent > events ) {
RECT clientRect = { } ;
GetClientRect ( m_hwnd , & clientRect ) ;
const auto layout = BuildScenarioLayout (
static_cast < float > ( ( std : : max ) ( 1L , clientRect . right - clientRect . left ) ) ,
static_cast < float > ( ( std : : max ) ( 1L , clientRect . bottom - clientRect . top ) ) ,
XCEngine : : Tests : : EditorUI : : ResolveEditorValidationShellMetrics ( m_theme ) ) ;
const auto metrics = XCEngine : : UI : : Editor : : ResolveUIEditorVector4FieldMetrics ( m_theme ) ;
m_frame = UpdateUIEditorVector4FieldInteraction (
m_interactionState ,
m_spec ,
layout . fieldRect ,
std : : move ( events ) ,
metrics ) ;
return m_frame . result ;
}
void UpdateResultText ( const UIEditorVector4FieldInteractionResult & result ) {
if ( result . editCommitRejected ) {
m_lastResult = " 提交失败,当前文本不是合法数字 " ;
} else if ( result . editCommitted ) {
m_lastResult = " 已提交 " + DescribeSelectedComponent ( result . changedComponentIndex ) + " = " + result . committedText ;
} else if ( result . editCanceled ) {
m_lastResult = " 已取消编辑 " ;
} else if ( result . editStarted ) {
m_lastResult = " 开始编辑 component " + DescribeSelectedComponent ( result . selectedComponentIndex ) ;
} else if ( result . stepApplied | | result . valueChanged ) {
m_lastResult = " 数值已更新,当前 component = " + DescribeSelectedComponent ( result . changedComponentIndex ) ;
} else if ( result . selectionChanged ) {
m_lastResult = " 已切换选中 component: " + DescribeSelectedComponent ( result . selectedComponentIndex ) ;
} else if ( result . focusChanged ) {
m_lastResult = std : : string ( " 焦点变化: " ) + ( m_interactionState . vector4FieldState . focused ? " focused " : " lost " ) ;
} else if ( result . consumed ) {
m_lastResult = " 控件已消费输入 " ;
}
}
void RenderFrame ( ) {
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 auto shellMetrics = XCEngine : : Tests : : EditorUI : : ResolveEditorValidationShellMetrics ( m_theme ) ;
const auto shellPalette = XCEngine : : Tests : : EditorUI : : ResolveEditorValidationShellPalette ( m_theme ) ;
const auto layout = BuildScenarioLayout ( width , height , shellMetrics ) ;
PumpEvents ( { } ) ;
const auto vectorMetrics = XCEngine : : UI : : Editor : : ResolveUIEditorVector4FieldMetrics ( m_theme ) ;
const auto vectorPalette = XCEngine : : UI : : Editor : : ResolveUIEditorVector4FieldPalette ( m_theme ) ;
const auto propertyPalette = XCEngine : : UI : : Editor : : ResolveUIEditorPropertyGridPalette ( m_theme ) ;
const auto currentHit = HitTestUIEditorVector4Field ( m_frame . layout , m_mousePosition ) ;
UIDrawData drawData = { } ;
UIDrawList & drawList = drawData . EmplaceDrawList ( " EditorVector4FieldBasic " ) ;
drawList . AddFilledRect ( UIRect ( 0.0f , 0.0f , width , height ) , shellPalette . windowBackground ) ;
drawList . AddFilledRect ( layout . introRect , shellPalette . cardBackground , shellMetrics . cardRadius ) ;
drawList . AddRectOutline ( layout . introRect , shellPalette . cardBorder , 1.0f , shellMetrics . cardRadius ) ;
drawList . AddText ( UIPoint ( layout . introRect . x + 16.0f , layout . introRect . y + 14.0f ) , " 这个测试验证什么功能? " , shellPalette . textPrimary , shellMetrics . titleFontSize ) ;
drawList . AddText ( UIPoint ( layout . introRect . x + 16.0f , layout . introRect . y + 40.0f ) , " 只验证 UIEditorVector4Field 的四通道编辑契约。 " , shellPalette . textMuted , shellMetrics . bodyFontSize ) ;
drawList . AddText ( UIPoint ( layout . introRect . x + 16.0f , layout . introRect . y + 72.0f ) , " 1. 点击 X/Y/Z/W 的 value box, 检查 selected component 和 editing。 " , shellPalette . textPrimary , shellMetrics . bodyFontSize ) ;
drawList . AddText ( UIPoint ( layout . introRect . x + 16.0f , layout . introRect . y + 94.0f ) , " 2. 按 Tab/Shift+Tab 切换 component; Up/Down/Home/End 检查 step 与边界。 " , shellPalette . textPrimary , shellMetrics . bodyFontSize ) ;
drawList . AddText ( UIPoint ( layout . introRect . x + 16.0f , layout . introRect . y + 116.0f ) , " 3. Enter 开始编辑; 直接输入字符也应开始编辑; Enter commit, Escape cancel。 " , shellPalette . textPrimary , shellMetrics . bodyFontSize ) ;
drawList . AddText ( UIPoint ( layout . introRect . x + 16.0f , layout . introRect . y + 138.0f ) , " 4. F6 模拟 FocusLost; F12 截图; R 重置当前测试。 " , shellPalette . textPrimary , shellMetrics . bodyFontSize ) ;
drawList . AddText ( UIPoint ( layout . introRect . x + 16.0f , layout . introRect . y + 160.0f ) , " 5. 重点检查 Hover / Selected / Editing / Values / Result 是否同步。 " , shellPalette . textPrimary , shellMetrics . bodyFontSize ) ;
drawList . AddFilledRect ( layout . stateRect , shellPalette . cardBackground , shellMetrics . cardRadius ) ;
drawList . AddRectOutline ( layout . stateRect , shellPalette . cardBorder , 1.0f , shellMetrics . cardRadius ) ;
drawList . AddText ( UIPoint ( layout . stateRect . x + 16.0f , layout . stateRect . y + 14.0f ) , " 状态摘要 " , shellPalette . textPrimary , shellMetrics . titleFontSize ) ;
drawList . AddText ( UIPoint ( layout . stateRect . x + 16.0f , layout . stateRect . y + 46.0f ) , " Hover: " + DescribeHitTarget ( currentHit ) , shellPalette . textPrimary , shellMetrics . bodyFontSize ) ;
drawList . AddText ( UIPoint ( layout . stateRect . x + 16.0f , layout . stateRect . y + 70.0f ) , " Selected: " + DescribeSelectedComponent ( m_interactionState . vector4FieldState . selectedComponentIndex ) , shellPalette . textPrimary , shellMetrics . bodyFontSize ) ;
drawList . AddText ( UIPoint ( layout . stateRect . x + 16.0f , layout . stateRect . y + 94.0f ) , std : : string ( " Focused: " ) + ( m_interactionState . vector4FieldState . focused ? " 是 " : " 否 " ) , shellPalette . textPrimary , shellMetrics . bodyFontSize ) ;
drawList . AddText ( UIPoint ( layout . stateRect . x + 16.0f , layout . stateRect . y + 118.0f ) , std : : string ( " Editing: " ) + ( m_interactionState . vector4FieldState . editing ? " 是 " : " 否 " ) , shellPalette . textPrimary , shellMetrics . bodyFontSize ) ;
drawList . AddText ( UIPoint ( layout . stateRect . x + 16.0f , layout . stateRect . y + 142.0f ) , " Values: X= " + FormatUIEditorVector4FieldComponentValue ( m_spec , 0u ) + " Y= " + FormatUIEditorVector4FieldComponentValue ( m_spec , 1u ) + " Z= " + FormatUIEditorVector4FieldComponentValue ( m_spec , 2u ) + " W= " + FormatUIEditorVector4FieldComponentValue ( m_spec , 3u ) , shellPalette . textPrimary , shellMetrics . bodyFontSize ) ;
drawList . AddText ( UIPoint ( layout . stateRect . x + 16.0f , layout . stateRect . y + 166.0f ) , " Display: X= " + m_interactionState . vector4FieldState . displayTexts [ 0 ] + " Y= " + m_interactionState . vector4FieldState . displayTexts [ 1 ] + " Z= " + m_interactionState . vector4FieldState . displayTexts [ 2 ] + " W= " + m_interactionState . vector4FieldState . displayTexts [ 3 ] , shellPalette . textPrimary , shellMetrics . bodyFontSize ) ;
drawList . AddText ( UIPoint ( layout . stateRect . x + 16.0f , layout . stateRect . y + 190.0f ) , " Result: " + m_lastResult , shellPalette . textPrimary , shellMetrics . bodyFontSize ) ;
drawList . AddText ( UIPoint ( layout . stateRect . x + 16.0f , layout . stateRect . y + 214.0f ) , " Capture: " + ( m_autoScreenshot . GetLastCaptureSummary ( ) . empty ( ) ? std : : string ( " F12 -> captures/ " ) : m_autoScreenshot . GetLastCaptureSummary ( ) ) , shellPalette . textWeak , shellMetrics . bodyFontSize ) ;
drawList . AddText ( UIPoint ( layout . stateRect . x + 16.0f , layout . stateRect . y + 238.0f ) , " Theme: " + m_themeStatus , shellPalette . textWeak , shellMetrics . bodyFontSize ) ;
drawList . AddFilledRect ( layout . previewRect , shellPalette . cardBackground , shellMetrics . cardRadius ) ;
drawList . AddRectOutline ( layout . previewRect , shellPalette . cardBorder , 1.0f , shellMetrics . cardRadius ) ;
drawList . AddText ( UIPoint ( layout . previewRect . x + 16.0f , layout . previewRect . y + 14.0f ) , " Vector4Field 预览 " , shellPalette . textPrimary , shellMetrics . titleFontSize ) ;
drawList . AddText ( UIPoint ( layout . previewRect . x + 16.0f , layout . previewRect . y + 40.0f ) , " 这里只放一个 Unity 风格的四通道字段。 " , shellPalette . textMuted , shellMetrics . bodyFontSize ) ;
drawList . AddFilledRect ( layout . inspectorRect , propertyPalette . surfaceColor ) ;
drawList . AddRectOutline ( layout . inspectorRect , propertyPalette . borderColor , 1.0f ) ;
drawList . AddFilledRect ( layout . inspectorHeaderRect , shellPalette . cardBackground ) ;
drawList . AddRectOutline ( layout . inspectorHeaderRect , propertyPalette . borderColor , 1.0f ) ;
drawList . AddText ( UIPoint ( layout . inspectorHeaderRect . x + 10.0f , layout . inspectorHeaderRect . y + 5.0f ) , " Inspector " , shellPalette . textPrimary , shellMetrics . bodyFontSize ) ;
drawList . AddFilledRect ( layout . sectionRect , propertyPalette . sectionHeaderColor ) ;
drawList . AddRectOutline ( layout . sectionRect , propertyPalette . borderColor , 1.0f ) ;
drawList . AddText ( UIPoint ( layout . sectionRect . x + 10.0f , layout . sectionRect . y + 5.0f ) , " v Transform " , propertyPalette . sectionTextColor , shellMetrics . bodyFontSize ) ;
AppendUIEditorVector4Field ( drawList , layout . fieldRect , m_spec , m_interactionState . vector4FieldState , vectorPalette , vectorMetrics ) ;
const bool framePresented = m_renderer . Render ( drawData ) ;
m_autoScreenshot . CaptureIfRequested ( m_renderer , drawData , static_cast < unsigned int > ( width ) , static_cast < unsigned int > ( height ) , framePresented ) ;
}
HWND m_hwnd = nullptr ;
ATOM m_windowClassAtom = 0 ;
NativeRenderer m_renderer = { } ;
AutoScreenshotController m_autoScreenshot = { } ;
std : : filesystem : : path m_captureRoot = { } ;
UIEditorVector4FieldSpec m_spec = { } ;
UIEditorVector4FieldInteractionState m_interactionState = { } ;
UIEditorVector4FieldInteractionFrame m_frame = { } ;
Style : : UITheme m_theme = { } ;
UIPoint m_mousePosition = UIPoint ( - 1000.0f , - 1000.0f ) ;
std : : string m_lastResult = " 等待交互 " ;
std : : string m_themeStatus = " fallback " ;
} ;
} // namespace
int WINAPI wWinMain ( HINSTANCE hInstance , HINSTANCE , PWSTR , int nCmdShow ) {
return ScenarioApp ( ) . Run ( hInstance , nCmdShow ) ;
}