diff --git a/new_editor/CMakeLists.txt b/new_editor/CMakeLists.txt index 3e623972..96a96853 100644 --- a/new_editor/CMakeLists.txt +++ b/new_editor/CMakeLists.txt @@ -158,6 +158,7 @@ target_link_libraries(XCUIEditorHost PUBLIC if(XCENGINE_BUILD_XCUI_EDITOR_APP) add_executable(XCUIEditorApp WIN32 + app/EditorApp.rc app/main.cpp app/Application.cpp app/Commands/ProductEditorHostCommandBridge.cpp diff --git a/new_editor/app/Application.cpp b/new_editor/app/Application.cpp index 0b4d833d..90c02361 100644 --- a/new_editor/app/Application.cpp +++ b/new_editor/app/Application.cpp @@ -1,4 +1,5 @@ #include "Application.h" +#include "EditorResources.h" #include @@ -42,7 +43,7 @@ constexpr float kBaseDpiScale = 96.0f; constexpr float kBorderlessTitleBarHeightDips = 28.0f; constexpr float kBorderlessTitleBarFontSize = 12.0f; constexpr DWORD kBorderlessWindowStyle = - WS_POPUP | WS_THICKFRAME | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; + WS_POPUP | WS_THICKFRAME; bool ResolveVerboseRuntimeTraceEnabled() { wchar_t buffer[8] = {}; @@ -53,6 +54,64 @@ bool ResolveVerboseRuntimeTraceEnabled() { return length > 0u && buffer[0] != L'0'; } +bool LoadEmbeddedPngBytes( + UINT resourceId, + const std::uint8_t*& outData, + std::size_t& outSize, + std::string& outError) { + outData = nullptr; + outSize = 0u; + outError.clear(); + + HMODULE module = GetModuleHandleW(nullptr); + if (module == nullptr) { + outError = "GetModuleHandleW(nullptr) returned null."; + return false; + } + + HRSRC resource = FindResourceW(module, MAKEINTRESOURCEW(resourceId), L"PNG"); + if (resource == nullptr) { + outError = "FindResourceW failed."; + return false; + } + + HGLOBAL resourceData = LoadResource(module, resource); + if (resourceData == nullptr) { + outError = "LoadResource failed."; + return false; + } + + const DWORD resourceSize = SizeofResource(module, resource); + if (resourceSize == 0u) { + outError = "SizeofResource returned zero."; + return false; + } + + const void* lockedBytes = LockResource(resourceData); + if (lockedBytes == nullptr) { + outError = "LockResource failed."; + return false; + } + + outData = reinterpret_cast(lockedBytes); + outSize = static_cast(resourceSize); + return true; +} + +bool LoadEmbeddedPngTexture( + Host::NativeRenderer& renderer, + UINT resourceId, + ::XCEngine::UI::UITextureHandle& outTexture, + std::string& outError) { + const std::uint8_t* bytes = nullptr; + std::size_t byteCount = 0u; + if (!LoadEmbeddedPngBytes(resourceId, bytes, byteCount, outError)) { + return false; + } + + return renderer.LoadTextureFromMemory(bytes, byteCount, outTexture, outError); +} + UINT QuerySystemDpi() { HDC screenDc = GetDC(nullptr); if (screenDc == nullptr) { @@ -415,6 +474,22 @@ bool Application::Initialize(HINSTANCE hInstance, int nCmdShow) { windowClass.lpfnWndProc = &Application::WndProc; windowClass.hInstance = hInstance; windowClass.hCursor = LoadCursorW(nullptr, IDC_ARROW); + windowClass.hIcon = static_cast( + LoadImageW( + hInstance, + MAKEINTRESOURCEW(IDI_APP_ICON), + IMAGE_ICON, + 0, + 0, + LR_DEFAULTSIZE)); + windowClass.hIconSm = static_cast( + LoadImageW( + hInstance, + MAKEINTRESOURCEW(IDI_APP_ICON_SMALL), + IMAGE_ICON, + GetSystemMetrics(SM_CXSMICON), + GetSystemMetrics(SM_CYSMICON), + LR_DEFAULTCOLOR)); windowClass.lpszClassName = kWindowClassName; m_windowClassAtom = RegisterClassExW(&windowClass); if (m_windowClassAtom == 0) { @@ -439,6 +514,12 @@ bool Application::Initialize(HINSTANCE hInstance, int nCmdShow) { LogRuntimeTrace("app", "window creation failed"); return false; } + if (windowClass.hIcon != nullptr) { + SendMessageW(m_hwnd, WM_SETICON, ICON_BIG, reinterpret_cast(windowClass.hIcon)); + } + if (windowClass.hIconSm != nullptr) { + SendMessageW(m_hwnd, WM_SETICON, ICON_SMALL, reinterpret_cast(windowClass.hIconSm)); + } Host::RefreshBorderlessWindowDwmDecorations(m_hwnd); m_hostRuntime.Reset(); m_hostRuntime.SetWindowDpi(QueryWindowDpi(m_hwnd)); @@ -477,6 +558,10 @@ bool Application::Initialize(HINSTANCE hInstance, int nCmdShow) { m_editorWorkspace.AttachViewportWindowRenderer(m_windowRenderer); m_editorWorkspace.SetViewportSurfacePresentationEnabled( attachResult.hasViewportSurfacePresentation); + std::string titleBarLogoError = {}; + if (!LoadEmbeddedPngTexture(m_renderer, IDR_PNG_LOGO_ICON, m_titleBarLogoIcon, titleBarLogoError)) { + LogRuntimeTrace("icons", "titlebar logo_icon.png: " + titleBarLogoError); + } if (!m_editorWorkspace.GetBuiltInIconError().empty()) { LogRuntimeTrace("icons", m_editorWorkspace.GetBuiltInIconError()); } @@ -507,6 +592,7 @@ void Application::Shutdown() { m_autoScreenshot.Shutdown(); m_editorWorkspace.Shutdown(); + m_renderer.ReleaseTexture(m_titleBarLogoIcon); m_windowRenderLoop.Detach(); m_windowRenderer.Shutdown(); m_renderer.Shutdown(); @@ -1114,23 +1200,36 @@ void Application::AppendBorderlessWindowChrome( const Host::BorderlessWindowChromeLayout layout = ResolveBorderlessWindowChromeLayout(clientWidthDips); + const float iconExtent = 16.0f; + const float iconInsetLeft = 8.0f; + const float iconTextGap = 8.0f; + const float iconX = layout.titleBarRect.x + iconInsetLeft; + const float iconY = + layout.titleBarRect.y + + (std::max)(0.0f, (layout.titleBarRect.height - iconExtent) * 0.5f); drawList.AddFilledRect( layout.titleBarRect, - UIColor(0.97f, 0.97f, 0.97f, 1.0f)); + UIColor(0.10f, 0.10f, 0.10f, 1.0f)); drawList.AddLine( UIPoint(layout.titleBarRect.x, layout.titleBarRect.y + layout.titleBarRect.height), UIPoint( layout.titleBarRect.x + layout.titleBarRect.width, layout.titleBarRect.y + layout.titleBarRect.height), - UIColor(0.78f, 0.78f, 0.78f, 1.0f), + UIColor(0.14f, 0.14f, 0.14f, 1.0f), 1.0f); + if (m_titleBarLogoIcon.IsValid()) { + drawList.AddImage( + UIRect(iconX, iconY, iconExtent, iconExtent), + m_titleBarLogoIcon, + UIColor(1.0f, 1.0f, 1.0f, 1.0f)); + } drawList.AddText( UIPoint( - 12.0f, + iconX + (m_titleBarLogoIcon.IsValid() ? (iconExtent + iconTextGap) : 4.0f), layout.titleBarRect.y + (std::max)(0.0f, (layout.titleBarRect.height - kBorderlessTitleBarFontSize) * 0.5f - 1.0f)), kWindowTitleText, - UIColor(0.12f, 0.12f, 0.12f, 1.0f), + UIColor(0.92f, 0.92f, 0.92f, 1.0f), kBorderlessTitleBarFontSize); Host::AppendBorderlessWindowChrome( drawList, @@ -1306,11 +1405,23 @@ std::string Application::DescribeInputEvents( } void Application::OnResize(UINT width, UINT height) { + bool matchesPredictedClientSize = false; + UINT predictedWidth = 0u; + UINT predictedHeight = 0u; + if (m_hostRuntime.TryGetPredictedClientPixelSize(predictedWidth, predictedHeight)) { + matchesPredictedClientSize = + predictedWidth == width && + predictedHeight == height; + } + m_hostRuntime.ClearPredictedClientPixelSize(); if (IsBorderlessWindowEnabled() && m_hwnd != nullptr) { Host::RefreshBorderlessWindowDwmDecorations(m_hwnd); } - ApplyWindowResize(width, height); + + if (!matchesPredictedClientSize) { + ApplyWindowResize(width, height); + } } void Application::OnEnterSizeMove() { diff --git a/new_editor/app/Application.h b/new_editor/app/Application.h index e0ae6451..ee89df51 100644 --- a/new_editor/app/Application.h +++ b/new_editor/app/Application.h @@ -130,6 +130,7 @@ private: std::vector<::XCEngine::UI::UIInputEvent> m_pendingInputEvents = {}; bool m_trackingMouseLeave = false; bool m_renderReady = false; + ::XCEngine::UI::UITextureHandle m_titleBarLogoIcon = {}; ::XCEngine::UI::Editor::Host::BorderlessWindowChromeState m_borderlessWindowChromeState = {}; ::XCEngine::UI::Editor::Host::HostRuntimeState m_hostRuntime = {}; }; diff --git a/new_editor/app/EditorApp.rc b/new_editor/app/EditorApp.rc new file mode 100644 index 00000000..4fda63c9 --- /dev/null +++ b/new_editor/app/EditorApp.rc @@ -0,0 +1,9 @@ +#include "EditorResources.h" + +IDI_APP_ICON ICON "../resources/Icons/logo.ico" +IDI_APP_ICON_SMALL ICON "../resources/Icons/logo_icon.ico" +IDR_PNG_FOLDER_ICON PNG "../resources/Icons/folder_icon.png" +IDR_PNG_GAMEOBJECT_ICON PNG "../resources/Icons/gameobject_icon.png" +IDR_PNG_SCENE_ICON PNG "../resources/Icons/scene_icon.png" +IDR_PNG_LOGO PNG "../resources/Icons/logo.png" +IDR_PNG_LOGO_ICON PNG "../resources/Icons/logo_icon.png" diff --git a/new_editor/app/EditorResources.h b/new_editor/app/EditorResources.h new file mode 100644 index 00000000..46e81b2b --- /dev/null +++ b/new_editor/app/EditorResources.h @@ -0,0 +1,9 @@ +#pragma once + +#define IDI_APP_ICON 101 +#define IDI_APP_ICON_SMALL 102 +#define IDR_PNG_FOLDER_ICON 201 +#define IDR_PNG_GAMEOBJECT_ICON 202 +#define IDR_PNG_SCENE_ICON 203 +#define IDR_PNG_LOGO 204 +#define IDR_PNG_LOGO_ICON 205 diff --git a/new_editor/app/Host/BorderlessWindowChrome.cpp b/new_editor/app/Host/BorderlessWindowChrome.cpp index 2aa317f7..961f7710 100644 --- a/new_editor/app/Host/BorderlessWindowChrome.cpp +++ b/new_editor/app/Host/BorderlessWindowChrome.cpp @@ -1,6 +1,7 @@ #include "BorderlessWindowChrome.h" #include +#include #include namespace XCEngine::UI::Editor::Host { @@ -12,6 +13,12 @@ using ::XCEngine::UI::UIDrawList; using ::XCEngine::UI::UIPoint; using ::XCEngine::UI::UIRect; +constexpr UIColor kTransparentColor(0.0f, 0.0f, 0.0f, 0.0f); + +float ResolveGlyphBoxSize(const UIRect& rect, float ratio, float minSize) { + return (std::max)(minSize, static_cast(std::round(rect.height * ratio))); +} + bool IsPointInsideRect(const UIRect& rect, const UIPoint& point) { return rect.width > 0.0f && rect.height > 0.0f && @@ -28,8 +35,8 @@ void AppendMinimizeGlyph( float thickness) { const float centerX = rect.x + rect.width * 0.5f; const float centerY = rect.y + rect.height * 0.5f; - const float halfWidth = (std::max)(4.0f, rect.height * 0.22f); - const float y = centerY + rect.height * 0.12f; + const float halfWidth = ResolveGlyphBoxSize(rect, 0.38f, 10.0f) * 0.5f; + const float y = centerY; drawList.AddLine( UIPoint(centerX - halfWidth, y), UIPoint(centerX + halfWidth, y), @@ -44,15 +51,16 @@ void AppendMaximizeGlyph( float thickness) { const float centerX = rect.x + rect.width * 0.5f; const float centerY = rect.y + rect.height * 0.5f; - const float halfExtent = (std::max)(4.0f, rect.height * 0.20f); - drawList.AddRectOutline( - UIRect( - centerX - halfExtent, - centerY - halfExtent, - halfExtent * 2.0f, - halfExtent * 2.0f), - color, - thickness); + const float boxSize = ResolveGlyphBoxSize(rect, 0.32f, 9.0f); + const float halfExtent = boxSize * 0.5f; + const float left = centerX - halfExtent; + const float top = centerY - halfExtent; + const float right = left + boxSize; + const float bottom = top + boxSize; + drawList.AddLine(UIPoint(left, top), UIPoint(right, top), color, thickness); + drawList.AddLine(UIPoint(left, top), UIPoint(left, bottom), color, thickness); + drawList.AddLine(UIPoint(right, top), UIPoint(right, bottom), color, thickness); + drawList.AddLine(UIPoint(left, bottom), UIPoint(right, bottom), color, thickness); } void AppendRestoreGlyph( @@ -62,24 +70,30 @@ void AppendRestoreGlyph( float thickness) { const float centerX = rect.x + rect.width * 0.5f; const float centerY = rect.y + rect.height * 0.5f; - const float halfExtent = (std::max)(4.0f, rect.height * 0.18f); - const float offset = 2.0f; - drawList.AddRectOutline( - UIRect( - centerX - halfExtent + offset, - centerY - halfExtent - offset, - halfExtent * 2.0f, - halfExtent * 2.0f), - color, - thickness); - drawList.AddRectOutline( - UIRect( - centerX - halfExtent - offset, - centerY - halfExtent + offset, - halfExtent * 2.0f, - halfExtent * 2.0f), - color, - thickness); + const float boxSize = ResolveGlyphBoxSize(rect, 0.29f, 8.0f); + const float halfExtent = boxSize * 0.5f; + const float offset = 1.0f; + + const float backLeft = centerX - halfExtent + offset; + const float backTop = centerY - halfExtent - offset; + const float backRight = backLeft + boxSize; + const float backBottom = backTop + boxSize; + + const float frontLeft = centerX - halfExtent - offset; + const float frontTop = centerY - halfExtent + offset; + const float frontRight = frontLeft + boxSize; + const float frontBottom = frontTop + boxSize; + + // Only draw the exposed segments of the back window. + drawList.AddLine(UIPoint(backLeft, backTop), UIPoint(backRight, backTop), color, thickness); + drawList.AddLine(UIPoint(backLeft, backTop), UIPoint(backLeft, frontTop), color, thickness); + drawList.AddLine(UIPoint(backRight, backTop), UIPoint(backRight, backBottom), color, thickness); + drawList.AddLine(UIPoint(frontRight, backBottom), UIPoint(backRight, backBottom), color, thickness); + + drawList.AddLine(UIPoint(frontLeft, frontTop), UIPoint(frontRight, frontTop), color, thickness); + drawList.AddLine(UIPoint(frontLeft, frontTop), UIPoint(frontLeft, frontBottom), color, thickness); + drawList.AddLine(UIPoint(frontRight, frontTop), UIPoint(frontRight, frontBottom), color, thickness); + drawList.AddLine(UIPoint(frontLeft, frontBottom), UIPoint(frontRight, frontBottom), color, thickness); } void AppendCloseGlyph( @@ -89,7 +103,7 @@ void AppendCloseGlyph( float thickness) { const float centerX = rect.x + rect.width * 0.5f; const float centerY = rect.y + rect.height * 0.5f; - const float halfWidth = (std::max)(4.0f, rect.height * 0.20f); + const float halfWidth = ResolveGlyphBoxSize(rect, 0.29f, 8.0f) * 0.5f; const float halfHeight = halfWidth; drawList.AddLine( UIPoint(centerX - halfWidth, centerY - halfHeight), @@ -116,7 +130,7 @@ void AppendCloseGlyph( if (hovered) { return palette.closeButtonHoverColor; } - return {}; + return kTransparentColor; } if (pressed) { @@ -125,7 +139,7 @@ void AppendCloseGlyph( if (hovered) { return palette.buttonHoverColor; } - return {}; + return kTransparentColor; } ::XCEngine::UI::UIColor ResolveIconColor( @@ -207,6 +221,54 @@ void ApplyDwmBoolWindowAttribute(HWND hwnd, DWORD attribute, BOOL value) { } } +void ApplyDwmColorWindowAttribute(HWND hwnd, DWORD attribute, COLORREF value) { + if (hwnd == nullptr) { + return; + } + + using DwmSetWindowAttributeFn = HRESULT(WINAPI*)(HWND, DWORD, LPCVOID, DWORD); + static const auto setWindowAttribute = []() -> DwmSetWindowAttributeFn { + HMODULE dwmapi = GetModuleHandleW(L"dwmapi.dll"); + if (dwmapi == nullptr) { + dwmapi = LoadLibraryW(L"dwmapi.dll"); + } + if (dwmapi == nullptr) { + return nullptr; + } + + return reinterpret_cast( + GetProcAddress(dwmapi, "DwmSetWindowAttribute")); + }(); + + if (setWindowAttribute != nullptr) { + setWindowAttribute(hwnd, attribute, &value, sizeof(value)); + } +} + +void ApplyDwmIntWindowAttribute(HWND hwnd, DWORD attribute, int value) { + if (hwnd == nullptr) { + return; + } + + using DwmSetWindowAttributeFn = HRESULT(WINAPI*)(HWND, DWORD, LPCVOID, DWORD); + static const auto setWindowAttribute = []() -> DwmSetWindowAttributeFn { + HMODULE dwmapi = GetModuleHandleW(L"dwmapi.dll"); + if (dwmapi == nullptr) { + dwmapi = LoadLibraryW(L"dwmapi.dll"); + } + if (dwmapi == nullptr) { + return nullptr; + } + + return reinterpret_cast( + GetProcAddress(dwmapi, "DwmSetWindowAttribute")); + }(); + + if (setWindowAttribute != nullptr) { + setWindowAttribute(hwnd, attribute, &value, sizeof(value)); + } +} + } // namespace BorderlessWindowChromeLayout BuildBorderlessWindowChromeLayout( @@ -353,7 +415,13 @@ void RefreshBorderlessWindowDwmDecorations(HWND hwnd) { // Borderless host cannot participate in compositor-driven minimize/maximize // transitions without Windows stretching the last presented client frame. // Disable those transitions for this window, then refresh the shadow state. + ApplyDwmIntWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, DWMNCRP_DISABLED); + ApplyDwmBoolWindowAttribute(hwnd, DWMWA_ALLOW_NCPAINT, FALSE); ApplyDwmBoolWindowAttribute(hwnd, DWMWA_TRANSITIONS_FORCEDISABLED, TRUE); + ApplyDwmBoolWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, TRUE); + ApplyDwmColorWindowAttribute(hwnd, DWMWA_CAPTION_COLOR, RGB(26, 26, 26)); + ApplyDwmColorWindowAttribute(hwnd, DWMWA_TEXT_COLOR, RGB(235, 235, 235)); + ApplyDwmColorWindowAttribute(hwnd, DWMWA_BORDER_COLOR, RGB(26, 26, 26)); EnableBorderlessWindowShadow(hwnd); } diff --git a/new_editor/app/Host/BorderlessWindowChrome.h b/new_editor/app/Host/BorderlessWindowChrome.h index ef3d5959..59404c93 100644 --- a/new_editor/app/Host/BorderlessWindowChrome.h +++ b/new_editor/app/Host/BorderlessWindowChrome.h @@ -28,15 +28,15 @@ struct BorderlessWindowChromeMetrics { struct BorderlessWindowChromePalette { ::XCEngine::UI::UIColor buttonHoverColor = - ::XCEngine::UI::UIColor(0.88f, 0.88f, 0.88f, 1.0f); + ::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f); ::XCEngine::UI::UIColor buttonPressedColor = - ::XCEngine::UI::UIColor(0.78f, 0.78f, 0.78f, 1.0f); + ::XCEngine::UI::UIColor(0.17f, 0.17f, 0.17f, 1.0f); ::XCEngine::UI::UIColor closeButtonHoverColor = ::XCEngine::UI::UIColor(0.91f, 0.31f, 0.24f, 1.0f); ::XCEngine::UI::UIColor closeButtonPressedColor = ::XCEngine::UI::UIColor(0.78f, 0.22f, 0.18f, 1.0f); ::XCEngine::UI::UIColor iconColor = - ::XCEngine::UI::UIColor(0.10f, 0.10f, 0.10f, 1.0f); + ::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f); ::XCEngine::UI::UIColor closeIconHoverColor = ::XCEngine::UI::UIColor(1.0f, 1.0f, 1.0f, 1.0f); }; diff --git a/new_editor/app/Host/NativeRenderer.cpp b/new_editor/app/Host/NativeRenderer.cpp index 32a3dea1..3d7a3c57 100644 --- a/new_editor/app/Host/NativeRenderer.cpp +++ b/new_editor/app/Host/NativeRenderer.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include namespace XCEngine::UI::Editor::Host { @@ -380,6 +381,29 @@ bool NativeRenderer::LoadTextureFromFile( return true; } +bool NativeRenderer::LoadTextureFromMemory( + const std::uint8_t* data, + std::size_t size, + ::XCEngine::UI::UITextureHandle& outTexture, + std::string& outError) { + outError.clear(); + ReleaseTexture(outTexture); + + auto texture = std::make_unique(); + if (!DecodeTextureMemory(data, size, *texture, outError)) { + outTexture = {}; + return false; + } + + outTexture.nativeHandle = reinterpret_cast(texture.get()); + outTexture.width = texture->width; + outTexture.height = texture->height; + outTexture.kind = ::XCEngine::UI::UITextureHandleKind::DescriptorHandle; + m_liveTextures.insert(texture.get()); + texture.release(); + return true; +} + void NativeRenderer::ReleaseTexture(::XCEngine::UI::UITextureHandle& texture) { if (!texture.IsValid()) { texture = {}; @@ -742,15 +766,80 @@ bool NativeRenderer::DecodeTextureFile( return false; } + return DecodeTextureFrame(*frame.Get(), outTexture, outError); +} + +bool NativeRenderer::DecodeTextureMemory( + const std::uint8_t* data, + std::size_t size, + NativeTextureResource& outTexture, + std::string& outError) { + outError.clear(); + if (data == nullptr || size == 0u) { + outError = "DecodeTextureMemory rejected an empty image payload."; + return false; + } + + if (size > static_cast((std::numeric_limits::max)())) { + outError = "DecodeTextureMemory payload exceeds WIC stream limits."; + return false; + } + + if (!EnsureWicFactory(outError)) { + return false; + } + + Microsoft::WRL::ComPtr stream; + HRESULT hr = m_wicFactory->CreateStream(stream.ReleaseAndGetAddressOf()); + if (FAILED(hr) || !stream) { + outError = HrToString("IWICImagingFactory::CreateStream", hr); + return false; + } + + hr = stream->InitializeFromMemory( + const_cast(reinterpret_cast(data)), + static_cast(size)); + if (FAILED(hr)) { + outError = HrToString("IWICStream::InitializeFromMemory", hr); + return false; + } + + Microsoft::WRL::ComPtr decoder; + hr = m_wicFactory->CreateDecoderFromStream( + stream.Get(), + nullptr, + WICDecodeMetadataCacheOnLoad, + decoder.ReleaseAndGetAddressOf()); + if (FAILED(hr) || !decoder) { + outError = HrToString("IWICImagingFactory::CreateDecoderFromStream", hr); + return false; + } + + Microsoft::WRL::ComPtr frame; + hr = decoder->GetFrame(0u, frame.ReleaseAndGetAddressOf()); + if (FAILED(hr) || !frame) { + outError = HrToString("IWICBitmapDecoder::GetFrame", hr); + return false; + } + + return DecodeTextureFrame(*frame.Get(), outTexture, outError); +} + +bool NativeRenderer::DecodeTextureFrame( + IWICBitmapSource& source, + NativeTextureResource& outTexture, + std::string& outError) { + outError.clear(); + Microsoft::WRL::ComPtr converter; - hr = m_wicFactory->CreateFormatConverter(converter.ReleaseAndGetAddressOf()); + HRESULT hr = m_wicFactory->CreateFormatConverter(converter.ReleaseAndGetAddressOf()); if (FAILED(hr) || !converter) { outError = HrToString("IWICImagingFactory::CreateFormatConverter", hr); return false; } hr = converter->Initialize( - frame.Get(), + &source, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, diff --git a/new_editor/app/Host/NativeRenderer.h b/new_editor/app/Host/NativeRenderer.h index 80edd1a8..cfa89214 100644 --- a/new_editor/app/Host/NativeRenderer.h +++ b/new_editor/app/Host/NativeRenderer.h @@ -48,6 +48,11 @@ public: const std::filesystem::path& path, ::XCEngine::UI::UITextureHandle& outTexture, std::string& outError); + bool LoadTextureFromMemory( + const std::uint8_t* data, + std::size_t size, + ::XCEngine::UI::UITextureHandle& outTexture, + std::string& outError); void ReleaseTexture(::XCEngine::UI::UITextureHandle& texture); float MeasureTextWidth( const ::XCEngine::UI::Editor::UIEditorTextMeasureRequest& request) const override; @@ -82,6 +87,15 @@ private: const std::filesystem::path& path, NativeTextureResource& outTexture, std::string& outError); + bool DecodeTextureMemory( + const std::uint8_t* data, + std::size_t size, + NativeTextureResource& outTexture, + std::string& outError); + bool DecodeTextureFrame( + IWICBitmapSource& source, + NativeTextureResource& outTexture, + std::string& outError); bool ResolveTextureBitmap( ID2D1RenderTarget& renderTarget, NativeTextureResource& texture, diff --git a/new_editor/app/Host/WindowMessageDispatcher.cpp b/new_editor/app/Host/WindowMessageDispatcher.cpp index 8379edfb..068f3b02 100644 --- a/new_editor/app/Host/WindowMessageDispatcher.cpp +++ b/new_editor/app/Host/WindowMessageDispatcher.cpp @@ -4,6 +4,13 @@ namespace XCEngine::UI::Editor::Host { +namespace { + +constexpr UINT kMessageNcUaDrawCaption = 0x00AEu; +constexpr UINT kMessageNcUaDrawFrame = 0x00AFu; + +} // namespace + void TryEnableNonClientDpiScaling(HWND hwnd) { if (hwnd == nullptr) { return; @@ -82,6 +89,20 @@ bool WindowMessageDispatcher::TryDispatch( return true; } return false; + case WM_NCHITTEST: + if (application.IsBorderlessWindowEnabled()) { + outResult = HTCLIENT; + return true; + } + return false; + case WM_NCPAINT: + case kMessageNcUaDrawCaption: + case kMessageNcUaDrawFrame: + if (application.IsBorderlessWindowEnabled()) { + outResult = 0; + return true; + } + return false; case WM_SYSCOMMAND: if (application.HandleBorderlessWindowSystemCommand(wParam)) { outResult = 0; diff --git a/new_editor/app/Icons/ProductBuiltInIcons.cpp b/new_editor/app/Icons/ProductBuiltInIcons.cpp index cb94ed69..2974d844 100644 --- a/new_editor/app/Icons/ProductBuiltInIcons.cpp +++ b/new_editor/app/Icons/ProductBuiltInIcons.cpp @@ -1,4 +1,5 @@ #include "ProductBuiltInIcons.h" +#include "EditorResources.h" #include @@ -20,31 +21,96 @@ void AppendLoadError( stream << label << ": " << error; } +bool LoadEmbeddedPngBytes( + UINT resourceId, + const std::uint8_t*& outData, + std::size_t& outSize, + std::string& outError) { + outData = nullptr; + outSize = 0u; + outError.clear(); + + HMODULE module = GetModuleHandleW(nullptr); + if (module == nullptr) { + outError = "GetModuleHandleW(nullptr) returned null."; + return false; + } + + HRSRC resource = FindResourceW(module, MAKEINTRESOURCEW(resourceId), L"PNG"); + if (resource == nullptr) { + outError = "FindResourceW failed."; + return false; + } + + HGLOBAL resourceData = LoadResource(module, resource); + if (resourceData == nullptr) { + outError = "LoadResource failed."; + return false; + } + + const DWORD resourceSize = SizeofResource(module, resource); + if (resourceSize == 0u) { + outError = "SizeofResource returned zero."; + return false; + } + + const void* lockedBytes = LockResource(resourceData); + if (lockedBytes == nullptr) { + outError = "LockResource failed."; + return false; + } + + outData = reinterpret_cast(lockedBytes); + outSize = static_cast(resourceSize); + return true; +} + +void LoadEmbeddedPngTexture( + Host::NativeRenderer& renderer, + UINT resourceId, + std::string_view label, + ::XCEngine::UI::UITextureHandle& outTexture, + std::ostringstream& errorStream) { + const std::uint8_t* bytes = nullptr; + std::size_t byteCount = 0u; + std::string error = {}; + if (!LoadEmbeddedPngBytes(resourceId, bytes, byteCount, error)) { + AppendLoadError(errorStream, label, error); + return; + } + + error.clear(); + if (!renderer.LoadTextureFromMemory(bytes, byteCount, outTexture, error)) { + AppendLoadError(errorStream, label, error); + } +} + } // namespace -void ProductBuiltInIcons::Initialize( - Host::NativeRenderer& renderer, - const std::filesystem::path& repoRoot) { +void ProductBuiltInIcons::Initialize(Host::NativeRenderer& renderer) { Shutdown(); m_renderer = &renderer; - m_repoRoot = repoRoot.lexically_normal(); std::ostringstream errorStream = {}; - std::string error = {}; - if (!m_renderer->LoadTextureFromFile(ResolveFolderIconPath(), m_folderIcon, error)) { - AppendLoadError(errorStream, "folder_icon.png", error); - } - - error.clear(); - if (!m_renderer->LoadTextureFromFile(ResolveGameObjectIconPath(), m_gameObjectIcon, error)) { - AppendLoadError(errorStream, "gameobject_icon.png", error); - } - - error.clear(); - if (!m_renderer->LoadTextureFromFile(ResolveSceneIconPath(), m_sceneIcon, error)) { - AppendLoadError(errorStream, "scene_icon.png", error); - } + LoadEmbeddedPngTexture( + renderer, + IDR_PNG_FOLDER_ICON, + "folder_icon.png", + m_folderIcon, + errorStream); + LoadEmbeddedPngTexture( + renderer, + IDR_PNG_GAMEOBJECT_ICON, + "gameobject_icon.png", + m_gameObjectIcon, + errorStream); + LoadEmbeddedPngTexture( + renderer, + IDR_PNG_SCENE_ICON, + "scene_icon.png", + m_sceneIcon, + errorStream); m_lastError = errorStream.str(); } @@ -57,7 +123,6 @@ void ProductBuiltInIcons::Shutdown() { } m_renderer = nullptr; - m_repoRoot.clear(); m_lastError.clear(); } @@ -79,16 +144,4 @@ const std::string& ProductBuiltInIcons::GetLastError() const { return m_lastError; } -std::filesystem::path ProductBuiltInIcons::ResolveFolderIconPath() const { - return (m_repoRoot / "editor/resources/Icons/folder_icon.png").lexically_normal(); -} - -std::filesystem::path ProductBuiltInIcons::ResolveGameObjectIconPath() const { - return (m_repoRoot / "editor/resources/Icons/gameobject_icon.png").lexically_normal(); -} - -std::filesystem::path ProductBuiltInIcons::ResolveSceneIconPath() const { - return (m_repoRoot / "editor/resources/Icons/scene_icon.png").lexically_normal(); -} - } // namespace XCEngine::UI::Editor::App diff --git a/new_editor/app/Icons/ProductBuiltInIcons.h b/new_editor/app/Icons/ProductBuiltInIcons.h index a63b427c..121b6caf 100644 --- a/new_editor/app/Icons/ProductBuiltInIcons.h +++ b/new_editor/app/Icons/ProductBuiltInIcons.h @@ -5,7 +5,6 @@ #include #include -#include #include namespace XCEngine::UI::Editor::App { @@ -18,21 +17,14 @@ enum class ProductBuiltInIconKind : std::uint8_t { class ProductBuiltInIcons { public: - void Initialize( - Host::NativeRenderer& renderer, - const std::filesystem::path& repoRoot); + void Initialize(Host::NativeRenderer& renderer); void Shutdown(); const ::XCEngine::UI::UITextureHandle& Resolve(ProductBuiltInIconKind kind) const; const std::string& GetLastError() const; private: - std::filesystem::path ResolveFolderIconPath() const; - std::filesystem::path ResolveGameObjectIconPath() const; - std::filesystem::path ResolveSceneIconPath() const; - Host::NativeRenderer* m_renderer = nullptr; - std::filesystem::path m_repoRoot = {}; ::XCEngine::UI::UITextureHandle m_folderIcon = {}; ::XCEngine::UI::UITextureHandle m_gameObjectIcon = {}; ::XCEngine::UI::UITextureHandle m_sceneIcon = {}; diff --git a/new_editor/app/Panels/ProductConsolePanel.cpp b/new_editor/app/Panels/ProductConsolePanel.cpp index 39dd7145..899c1043 100644 --- a/new_editor/app/Panels/ProductConsolePanel.cpp +++ b/new_editor/app/Panels/ProductConsolePanel.cpp @@ -19,9 +19,9 @@ constexpr float kPadding = 8.0f; constexpr float kLineHeight = 18.0f; constexpr float kFontSize = 11.0f; -constexpr UIColor kSurfaceColor(0.205f, 0.205f, 0.205f, 1.0f); -constexpr UIColor kTextColor(0.840f, 0.840f, 0.840f, 1.0f); -constexpr UIColor kChannelColor(0.640f, 0.640f, 0.640f, 1.0f); +constexpr UIColor kSurfaceColor(0.10f, 0.10f, 0.10f, 1.0f); +constexpr UIColor kTextColor(0.860f, 0.860f, 0.860f, 1.0f); +constexpr UIColor kChannelColor(0.660f, 0.660f, 0.660f, 1.0f); constexpr UIColor kEmptyColor(0.580f, 0.580f, 0.580f, 1.0f); float ResolveTextTop(float rectY, float rectHeight, float fontSize) { diff --git a/new_editor/app/Panels/ProductInspectorPanel.cpp b/new_editor/app/Panels/ProductInspectorPanel.cpp index 51320c12..ae6baa46 100644 --- a/new_editor/app/Panels/ProductInspectorPanel.cpp +++ b/new_editor/app/Panels/ProductInspectorPanel.cpp @@ -24,13 +24,13 @@ constexpr float kSubtitleFontSize = 11.0f; constexpr float kSectionTitleFontSize = 11.0f; constexpr float kRowFontSize = 11.0f; -constexpr UIColor kSurfaceColor(0.205f, 0.205f, 0.205f, 1.0f); -constexpr UIColor kSectionHeaderColor(0.225f, 0.225f, 0.225f, 1.0f); -constexpr UIColor kSectionBodyColor(0.215f, 0.215f, 0.215f, 1.0f); -constexpr UIColor kTitleColor(0.910f, 0.910f, 0.910f, 1.0f); -constexpr UIColor kSubtitleColor(0.650f, 0.650f, 0.650f, 1.0f); -constexpr UIColor kLabelColor(0.700f, 0.700f, 0.700f, 1.0f); -constexpr UIColor kValueColor(0.860f, 0.860f, 0.860f, 1.0f); +constexpr UIColor kSurfaceColor(0.10f, 0.10f, 0.10f, 1.0f); +constexpr UIColor kSectionHeaderColor(0.12f, 0.12f, 0.12f, 1.0f); +constexpr UIColor kSectionBodyColor(0.11f, 0.11f, 0.11f, 1.0f); +constexpr UIColor kTitleColor(0.930f, 0.930f, 0.930f, 1.0f); +constexpr UIColor kSubtitleColor(0.640f, 0.640f, 0.640f, 1.0f); +constexpr UIColor kLabelColor(0.720f, 0.720f, 0.720f, 1.0f); +constexpr UIColor kValueColor(0.880f, 0.880f, 0.880f, 1.0f); float ResolveTextTop(float rectY, float rectHeight, float fontSize) { const float lineHeight = fontSize * 1.6f; diff --git a/new_editor/app/Panels/ProductProjectPanel.cpp b/new_editor/app/Panels/ProductProjectPanel.cpp index 8df33e4e..6b1e79bf 100644 --- a/new_editor/app/Panels/ProductProjectPanel.cpp +++ b/new_editor/app/Panels/ProductProjectPanel.cpp @@ -52,17 +52,17 @@ constexpr float kGridPreviewHeight = 54.0f; constexpr float kHeaderFontSize = 12.0f; constexpr float kTileLabelFontSize = 11.0f; -constexpr UIColor kSurfaceColor(0.200f, 0.200f, 0.200f, 1.0f); -constexpr UIColor kPaneColor(0.205f, 0.205f, 0.205f, 1.0f); -constexpr UIColor kHeaderColor(0.215f, 0.215f, 0.215f, 1.0f); -constexpr UIColor kTextPrimary(0.830f, 0.830f, 0.830f, 1.0f); -constexpr UIColor kTextStrong(0.910f, 0.910f, 0.910f, 1.0f); -constexpr UIColor kTextMuted(0.560f, 0.560f, 0.560f, 1.0f); -constexpr UIColor kTileHoverColor(0.245f, 0.245f, 0.245f, 1.0f); -constexpr UIColor kTileSelectedColor(0.300f, 0.300f, 0.300f, 1.0f); -constexpr UIColor kTilePreviewFillColor(0.700f, 0.700f, 0.700f, 1.0f); -constexpr UIColor kTilePreviewShadeColor(0.610f, 0.610f, 0.610f, 1.0f); -constexpr UIColor kTilePreviewOutlineColor(0.860f, 0.860f, 0.860f, 0.35f); +constexpr UIColor kSurfaceColor(0.10f, 0.10f, 0.10f, 1.0f); +constexpr UIColor kPaneColor(0.11f, 0.11f, 0.11f, 1.0f); +constexpr UIColor kHeaderColor(0.12f, 0.12f, 0.12f, 1.0f); +constexpr UIColor kTextPrimary(0.840f, 0.840f, 0.840f, 1.0f); +constexpr UIColor kTextStrong(0.930f, 0.930f, 0.930f, 1.0f); +constexpr UIColor kTextMuted(0.580f, 0.580f, 0.580f, 1.0f); +constexpr UIColor kTileHoverColor(0.14f, 0.14f, 0.14f, 1.0f); +constexpr UIColor kTileSelectedColor(0.17f, 0.17f, 0.17f, 1.0f); +constexpr UIColor kTilePreviewFillColor(0.20f, 0.20f, 0.20f, 1.0f); +constexpr UIColor kTilePreviewShadeColor(0.15f, 0.15f, 0.15f, 1.0f); +constexpr UIColor kTilePreviewOutlineColor(0.920f, 0.920f, 0.920f, 0.25f); bool ContainsPoint(const UIRect& rect, const UIPoint& point) { return point.x >= rect.x && diff --git a/new_editor/app/Panels/ProductTreeViewStyle.h b/new_editor/app/Panels/ProductTreeViewStyle.h index 0e2a6d20..bff7c4b4 100644 --- a/new_editor/app/Panels/ProductTreeViewStyle.h +++ b/new_editor/app/Panels/ProductTreeViewStyle.h @@ -4,11 +4,11 @@ namespace XCEngine::UI::Editor::App { -inline constexpr ::XCEngine::UI::UIColor kProductTreeSurfaceColor(0.205f, 0.205f, 0.205f, 1.0f); -inline constexpr ::XCEngine::UI::UIColor kProductTreeHoverColor(0.245f, 0.245f, 0.245f, 1.0f); -inline constexpr ::XCEngine::UI::UIColor kProductTreeSelectedColor(0.300f, 0.300f, 0.300f, 1.0f); -inline constexpr ::XCEngine::UI::UIColor kProductTreeDisclosureColor(0.560f, 0.560f, 0.560f, 1.0f); -inline constexpr ::XCEngine::UI::UIColor kProductTreeTextColor(0.830f, 0.830f, 0.830f, 1.0f); +inline constexpr ::XCEngine::UI::UIColor kProductTreeSurfaceColor(0.10f, 0.10f, 0.10f, 1.0f); +inline constexpr ::XCEngine::UI::UIColor kProductTreeHoverColor(0.13f, 0.13f, 0.13f, 1.0f); +inline constexpr ::XCEngine::UI::UIColor kProductTreeSelectedColor(0.16f, 0.16f, 0.16f, 1.0f); +inline constexpr ::XCEngine::UI::UIColor kProductTreeDisclosureColor(0.620f, 0.620f, 0.620f, 1.0f); +inline constexpr ::XCEngine::UI::UIColor kProductTreeTextColor(0.900f, 0.900f, 0.900f, 1.0f); inline Widgets::UIEditorTreeViewMetrics BuildProductTreeViewMetrics() { Widgets::UIEditorTreeViewMetrics metrics = {}; diff --git a/new_editor/app/Workspace/ProductEditorWorkspace.cpp b/new_editor/app/Workspace/ProductEditorWorkspace.cpp index 55f3a1a7..03b4a13c 100644 --- a/new_editor/app/Workspace/ProductEditorWorkspace.cpp +++ b/new_editor/app/Workspace/ProductEditorWorkspace.cpp @@ -220,7 +220,7 @@ std::vector FilterHostedContentInputEventsForShellOwnership( void ProductEditorWorkspace::Initialize( const std::filesystem::path& repoRoot, Host::NativeRenderer& renderer) { - m_builtInIcons.Initialize(renderer, repoRoot); + m_builtInIcons.Initialize(renderer); m_hierarchyPanel.SetBuiltInIcons(&m_builtInIcons); m_projectPanel.SetBuiltInIcons(&m_builtInIcons); m_projectPanel.SetTextMeasurer(&renderer); diff --git a/new_editor/include/XCEditor/Shell/UIEditorMenuBar.h b/new_editor/include/XCEditor/Shell/UIEditorMenuBar.h index 145c243a..20982c32 100644 --- a/new_editor/include/XCEditor/Shell/UIEditorMenuBar.h +++ b/new_editor/include/XCEditor/Shell/UIEditorMenuBar.h @@ -30,7 +30,7 @@ struct UIEditorMenuBarMetrics { float horizontalInset = 0.0f; float verticalInset = 2.0f; float buttonGap = 1.0f; - float buttonPaddingX = 4.0f; + float buttonPaddingX = 7.0f; float labelFontSize = 13.0f; float estimatedGlyphWidth = 6.5f; float labelInsetY = -1.5f; diff --git a/new_editor/resources/Icons/folder_icon.png b/new_editor/resources/Icons/folder_icon.png new file mode 100644 index 00000000..55d061ce Binary files /dev/null and b/new_editor/resources/Icons/folder_icon.png differ diff --git a/new_editor/resources/Icons/gameobject_icon.png b/new_editor/resources/Icons/gameobject_icon.png new file mode 100644 index 00000000..39f08e89 Binary files /dev/null and b/new_editor/resources/Icons/gameobject_icon.png differ diff --git a/new_editor/resources/Icons/logo.ico b/new_editor/resources/Icons/logo.ico new file mode 100644 index 00000000..b2b11b88 Binary files /dev/null and b/new_editor/resources/Icons/logo.ico differ diff --git a/new_editor/resources/Icons/logo.png b/new_editor/resources/Icons/logo.png new file mode 100644 index 00000000..f3612e3e Binary files /dev/null and b/new_editor/resources/Icons/logo.png differ diff --git a/new_editor/resources/Icons/logo_icon.ico b/new_editor/resources/Icons/logo_icon.ico new file mode 100644 index 00000000..a079ab6a Binary files /dev/null and b/new_editor/resources/Icons/logo_icon.ico differ diff --git a/new_editor/resources/Icons/logo_icon.png b/new_editor/resources/Icons/logo_icon.png new file mode 100644 index 00000000..b9760f6d Binary files /dev/null and b/new_editor/resources/Icons/logo_icon.png differ diff --git a/new_editor/resources/Icons/scene_icon.png b/new_editor/resources/Icons/scene_icon.png new file mode 100644 index 00000000..b9760f6d Binary files /dev/null and b/new_editor/resources/Icons/scene_icon.png differ diff --git a/new_editor/src/Foundation/UIEditorTheme.cpp b/new_editor/src/Foundation/UIEditorTheme.cpp index 1b5e467e..f438553d 100644 --- a/new_editor/src/Foundation/UIEditorTheme.cpp +++ b/new_editor/src/Foundation/UIEditorTheme.cpp @@ -4,12 +4,208 @@ namespace XCEngine::UI::Editor { namespace { +using ::XCEngine::UI::UIColor; + template const TValue& GetDefaultValue() { static const TValue value = {}; return value; } +Widgets::UIEditorMenuBarPalette BuildMenuBarPalette() { + Widgets::UIEditorMenuBarPalette palette = {}; + palette.barColor = UIColor(0.10f, 0.10f, 0.10f, 1.0f); + palette.buttonColor = UIColor(0.0f, 0.0f, 0.0f, 0.0f); + palette.buttonHoveredColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.buttonOpenColor = UIColor(0.17f, 0.17f, 0.17f, 1.0f); + palette.borderColor = UIColor(0.0f, 0.0f, 0.0f, 0.0f); + palette.focusedBorderColor = UIColor(0.0f, 0.0f, 0.0f, 0.0f); + palette.openBorderColor = UIColor(0.0f, 0.0f, 0.0f, 0.0f); + palette.textPrimary = UIColor(0.93f, 0.93f, 0.93f, 1.0f); + palette.textMuted = UIColor(0.72f, 0.72f, 0.72f, 1.0f); + palette.textDisabled = UIColor(0.45f, 0.45f, 0.45f, 1.0f); + return palette; +} + +Widgets::UIEditorMenuPopupPalette BuildMenuPopupPalette() { + Widgets::UIEditorMenuPopupPalette palette = {}; + palette.popupColor = UIColor(0.10f, 0.10f, 0.10f, 1.0f); + palette.borderColor = UIColor(0.16f, 0.16f, 0.16f, 1.0f); + palette.itemHoverColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.itemOpenColor = UIColor(0.17f, 0.17f, 0.17f, 1.0f); + palette.separatorColor = UIColor(0.10f, 0.10f, 0.10f, 1.0f); + palette.textPrimary = UIColor(0.93f, 0.93f, 0.93f, 1.0f); + palette.textMuted = UIColor(0.68f, 0.68f, 0.68f, 1.0f); + palette.textDisabled = UIColor(0.45f, 0.45f, 0.45f, 1.0f); + palette.glyphColor = UIColor(0.90f, 0.90f, 0.90f, 1.0f); + return palette; +} + +Widgets::UIEditorListViewPalette BuildListViewPalette() { + Widgets::UIEditorListViewPalette palette = {}; + palette.surfaceColor = UIColor(0.10f, 0.10f, 0.10f, 1.0f); + palette.borderColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.focusedBorderColor = UIColor(0.18f, 0.18f, 0.18f, 1.0f); + palette.rowHoverColor = UIColor(0.13f, 0.13f, 0.13f, 1.0f); + palette.rowSelectedColor = UIColor(0.16f, 0.16f, 0.16f, 1.0f); + palette.rowSelectedFocusedColor = UIColor(0.18f, 0.18f, 0.18f, 1.0f); + palette.primaryTextColor = UIColor(0.93f, 0.93f, 0.93f, 1.0f); + palette.secondaryTextColor = UIColor(0.67f, 0.67f, 0.67f, 1.0f); + return palette; +} + +Widgets::UIEditorTreeViewPalette BuildTreeViewPalette() { + Widgets::UIEditorTreeViewPalette palette = {}; + palette.surfaceColor = UIColor(0.10f, 0.10f, 0.10f, 1.0f); + palette.borderColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.focusedBorderColor = UIColor(0.18f, 0.18f, 0.18f, 1.0f); + palette.rowHoverColor = UIColor(0.13f, 0.13f, 0.13f, 1.0f); + palette.rowSelectedColor = UIColor(0.16f, 0.16f, 0.16f, 1.0f); + palette.rowSelectedFocusedColor = UIColor(0.18f, 0.18f, 0.18f, 1.0f); + palette.disclosureColor = UIColor(0.62f, 0.62f, 0.62f, 1.0f); + palette.textColor = UIColor(0.92f, 0.92f, 0.92f, 1.0f); + return palette; +} + +Widgets::UIEditorScrollViewPalette BuildScrollViewPalette() { + Widgets::UIEditorScrollViewPalette palette = {}; + palette.surfaceColor = UIColor(0.10f, 0.10f, 0.10f, 1.0f); + palette.borderColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.focusedBorderColor = UIColor(0.18f, 0.18f, 0.18f, 1.0f); + palette.scrollbarTrackColor = UIColor(0.08f, 0.08f, 0.08f, 1.0f); + palette.scrollbarThumbColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.scrollbarThumbHoverColor = UIColor(0.17f, 0.17f, 0.17f, 1.0f); + palette.scrollbarThumbActiveColor = UIColor(0.20f, 0.20f, 0.20f, 1.0f); + return palette; +} + +Widgets::UIEditorTabStripPalette BuildTabStripPalette() { + Widgets::UIEditorTabStripPalette palette = {}; + palette.stripBackgroundColor = UIColor(0.10f, 0.10f, 0.10f, 1.0f); + palette.headerBackgroundColor = UIColor(0.11f, 0.11f, 0.11f, 1.0f); + palette.contentBackgroundColor = UIColor(0.12f, 0.12f, 0.12f, 1.0f); + palette.stripBorderColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.headerContentSeparatorColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.focusedBorderColor = UIColor(0.16f, 0.16f, 0.16f, 1.0f); + palette.tabColor = UIColor(0.12f, 0.12f, 0.12f, 1.0f); + palette.tabHoveredColor = UIColor(0.15f, 0.15f, 0.15f, 1.0f); + palette.tabSelectedColor = UIColor(0.12f, 0.12f, 0.12f, 1.0f); + palette.tabBorderColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.tabHoveredBorderColor = UIColor(0.16f, 0.16f, 0.16f, 1.0f); + palette.tabSelectedBorderColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.textPrimary = UIColor(0.92f, 0.92f, 0.92f, 1.0f); + palette.textSecondary = UIColor(0.72f, 0.72f, 0.72f, 1.0f); + palette.textMuted = UIColor(0.58f, 0.58f, 0.58f, 1.0f); + palette.closeButtonColor = UIColor(0.12f, 0.12f, 0.12f, 1.0f); + palette.closeButtonHoveredColor = UIColor(0.15f, 0.15f, 0.15f, 1.0f); + palette.closeButtonBorderColor = UIColor(0.16f, 0.16f, 0.16f, 1.0f); + palette.closeGlyphColor = UIColor(0.85f, 0.85f, 0.85f, 1.0f); + palette.reorderPreviewColor = UIColor(0.92f, 0.92f, 0.92f, 0.90f); + return palette; +} + +Widgets::UIEditorStatusBarPalette BuildStatusBarPalette() { + Widgets::UIEditorStatusBarPalette palette = {}; + palette.surfaceColor = UIColor(0.10f, 0.10f, 0.10f, 1.0f); + palette.borderColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.focusedBorderColor = UIColor(0.16f, 0.16f, 0.16f, 1.0f); + palette.segmentColor = UIColor(0.12f, 0.12f, 0.12f, 1.0f); + palette.segmentHoveredColor = UIColor(0.15f, 0.15f, 0.15f, 1.0f); + palette.segmentActiveColor = UIColor(0.18f, 0.18f, 0.18f, 1.0f); + palette.segmentBorderColor = UIColor(0.16f, 0.16f, 0.16f, 1.0f); + palette.separatorColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.textPrimary = UIColor(0.90f, 0.90f, 0.90f, 1.0f); + palette.textMuted = UIColor(0.64f, 0.64f, 0.64f, 1.0f); + palette.textAccent = UIColor(0.94f, 0.94f, 0.94f, 1.0f); + return palette; +} + +Widgets::UIEditorPanelFramePalette BuildPanelFramePalette() { + Widgets::UIEditorPanelFramePalette palette = {}; + palette.surfaceColor = UIColor(0.10f, 0.10f, 0.10f, 1.0f); + palette.headerColor = UIColor(0.11f, 0.11f, 0.11f, 1.0f); + palette.footerColor = UIColor(0.10f, 0.10f, 0.10f, 1.0f); + palette.borderColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.hoveredBorderColor = UIColor(0.16f, 0.16f, 0.16f, 1.0f); + palette.activeBorderColor = UIColor(0.18f, 0.18f, 0.18f, 1.0f); + palette.focusedBorderColor = UIColor(0.16f, 0.16f, 0.16f, 1.0f); + palette.textPrimary = UIColor(0.92f, 0.92f, 0.92f, 1.0f); + palette.textSecondary = UIColor(0.68f, 0.68f, 0.68f, 1.0f); + palette.textMuted = UIColor(0.58f, 0.58f, 0.58f, 1.0f); + palette.actionButtonColor = UIColor(0.12f, 0.12f, 0.12f, 1.0f); + palette.actionButtonHoveredColor = UIColor(0.15f, 0.15f, 0.15f, 1.0f); + palette.actionButtonSelectedColor = UIColor(0.18f, 0.18f, 0.18f, 1.0f); + palette.actionButtonBorderColor = UIColor(0.16f, 0.16f, 0.16f, 1.0f); + palette.actionGlyphColor = UIColor(0.84f, 0.84f, 0.84f, 1.0f); + return palette; +} + +Widgets::UIEditorDockHostPalette BuildDockHostPalette() { + Widgets::UIEditorDockHostPalette palette = {}; + palette.tabStripPalette = BuildTabStripPalette(); + palette.panelFramePalette = BuildPanelFramePalette(); + palette.splitterColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.splitterHoveredColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.splitterActiveColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.placeholderTitleColor = UIColor(0.92f, 0.92f, 0.92f, 1.0f); + palette.placeholderTextColor = UIColor(0.70f, 0.70f, 0.70f, 1.0f); + palette.placeholderMutedColor = UIColor(0.58f, 0.58f, 0.58f, 1.0f); + palette.dropPreviewFillColor = UIColor(0.92f, 0.92f, 0.92f, 0.08f); + palette.dropPreviewBorderColor = UIColor(0.96f, 0.96f, 0.96f, 0.70f); + return palette; +} + +Widgets::UIEditorViewportSlotPalette BuildViewportSlotPalette() { + Widgets::UIEditorViewportSlotPalette palette = {}; + palette.frameColor = UIColor(0.09f, 0.09f, 0.09f, 1.0f); + palette.topBarColor = UIColor(0.10f, 0.10f, 0.10f, 1.0f); + palette.surfaceColor = UIColor(0.08f, 0.08f, 0.08f, 1.0f); + palette.surfaceHoverOverlayColor = UIColor(0.18f, 0.18f, 0.18f, 0.12f); + palette.surfaceActiveOverlayColor = UIColor(0.22f, 0.22f, 0.22f, 0.10f); + palette.captureOverlayColor = UIColor(0.92f, 0.92f, 0.92f, 0.06f); + palette.borderColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.focusedBorderColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.surfaceBorderColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.surfaceHoveredBorderColor = UIColor(0.16f, 0.16f, 0.16f, 1.0f); + palette.surfaceActiveBorderColor = UIColor(0.18f, 0.18f, 0.18f, 1.0f); + palette.surfaceCapturedBorderColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.toolColor = UIColor(0.12f, 0.12f, 0.12f, 1.0f); + palette.toolHoveredColor = UIColor(0.15f, 0.15f, 0.15f, 1.0f); + palette.toolSelectedColor = UIColor(0.18f, 0.18f, 0.18f, 1.0f); + palette.toolDisabledColor = UIColor(0.10f, 0.10f, 0.10f, 1.0f); + palette.toolBorderColor = UIColor(0.16f, 0.16f, 0.16f, 1.0f); + palette.textPrimary = UIColor(0.92f, 0.92f, 0.92f, 1.0f); + palette.textSecondary = UIColor(0.68f, 0.68f, 0.68f, 1.0f); + palette.textMuted = UIColor(0.58f, 0.58f, 0.58f, 1.0f); + palette.imageTint = UIColor(1.0f, 1.0f, 1.0f, 1.0f); + palette.statusBarPalette = BuildStatusBarPalette(); + return palette; +} + +UIEditorShellComposePalette BuildShellComposePalette() { + UIEditorShellComposePalette palette = {}; + palette.surfaceColor = UIColor(0.10f, 0.10f, 0.10f, 1.0f); + palette.surfaceBorderColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.menuBarPalette = BuildMenuBarPalette(); + palette.toolbarPalette.barColor = UIColor(0.10f, 0.10f, 0.10f, 1.0f); + palette.toolbarPalette.groupColor = UIColor(0.11f, 0.11f, 0.11f, 1.0f); + palette.toolbarPalette.groupBorderColor = UIColor(0.14f, 0.14f, 0.14f, 1.0f); + palette.toolbarPalette.buttonColor = UIColor(0.12f, 0.12f, 0.12f, 1.0f); + palette.toolbarPalette.buttonBorderColor = UIColor(0.16f, 0.16f, 0.16f, 1.0f); + palette.toolbarPalette.iconColor = UIColor(0.88f, 0.88f, 0.88f, 1.0f); + palette.dockHostPalette = BuildDockHostPalette(); + palette.viewportPalette = BuildViewportSlotPalette(); + palette.statusBarPalette = BuildStatusBarPalette(); + return palette; +} + +UIEditorShellInteractionPalette BuildShellInteractionPalette() { + UIEditorShellInteractionPalette palette = {}; + palette.shellPalette = BuildShellComposePalette(); + palette.popupPalette = BuildMenuPopupPalette(); + return palette; +} + #define XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(Name, Type) \ const Type& ResolveUIEditor##Name() { \ return GetDefaultValue(); \ @@ -38,32 +234,80 @@ XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(ObjectFieldPalette, Widgets::UIEditorObjectF XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(AssetFieldMetrics, Widgets::UIEditorAssetFieldMetrics) XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(AssetFieldPalette, Widgets::UIEditorAssetFieldPalette) XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(MenuPopupMetrics, Widgets::UIEditorMenuPopupMetrics) -XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(MenuPopupPalette, Widgets::UIEditorMenuPopupPalette) XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(ListViewMetrics, Widgets::UIEditorListViewMetrics) -XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(ListViewPalette, Widgets::UIEditorListViewPalette) XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(TreeViewMetrics, Widgets::UIEditorTreeViewMetrics) -XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(TreeViewPalette, Widgets::UIEditorTreeViewPalette) XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(ScrollViewMetrics, Widgets::UIEditorScrollViewMetrics) -XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(ScrollViewPalette, Widgets::UIEditorScrollViewPalette) XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(TabStripMetrics, Widgets::UIEditorTabStripMetrics) -XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(TabStripPalette, Widgets::UIEditorTabStripPalette) XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(MenuBarMetrics, Widgets::UIEditorMenuBarMetrics) -XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(MenuBarPalette, Widgets::UIEditorMenuBarPalette) XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(StatusBarMetrics, Widgets::UIEditorStatusBarMetrics) -XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(StatusBarPalette, Widgets::UIEditorStatusBarPalette) XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(PanelFrameMetrics, Widgets::UIEditorPanelFrameMetrics) -XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(PanelFramePalette, Widgets::UIEditorPanelFramePalette) XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(DockHostMetrics, Widgets::UIEditorDockHostMetrics) -XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(DockHostPalette, Widgets::UIEditorDockHostPalette) XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(ViewportSlotMetrics, Widgets::UIEditorViewportSlotMetrics) -XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(ViewportSlotPalette, Widgets::UIEditorViewportSlotPalette) XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(ShellComposeMetrics, UIEditorShellComposeMetrics) -XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(ShellComposePalette, UIEditorShellComposePalette) XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(ShellInteractionMetrics, UIEditorShellInteractionMetrics) -XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(ShellInteractionPalette, UIEditorShellInteractionPalette) XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(PropertyGridMetrics, Widgets::UIEditorPropertyGridMetrics) XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS(PropertyGridPalette, Widgets::UIEditorPropertyGridPalette) +const Widgets::UIEditorMenuPopupPalette& ResolveUIEditorMenuPopupPalette() { + static const Widgets::UIEditorMenuPopupPalette palette = BuildMenuPopupPalette(); + return palette; +} + +const Widgets::UIEditorListViewPalette& ResolveUIEditorListViewPalette() { + static const Widgets::UIEditorListViewPalette palette = BuildListViewPalette(); + return palette; +} + +const Widgets::UIEditorTreeViewPalette& ResolveUIEditorTreeViewPalette() { + static const Widgets::UIEditorTreeViewPalette palette = BuildTreeViewPalette(); + return palette; +} + +const Widgets::UIEditorScrollViewPalette& ResolveUIEditorScrollViewPalette() { + static const Widgets::UIEditorScrollViewPalette palette = BuildScrollViewPalette(); + return palette; +} + +const Widgets::UIEditorTabStripPalette& ResolveUIEditorTabStripPalette() { + static const Widgets::UIEditorTabStripPalette palette = BuildTabStripPalette(); + return palette; +} + +const Widgets::UIEditorMenuBarPalette& ResolveUIEditorMenuBarPalette() { + static const Widgets::UIEditorMenuBarPalette palette = BuildMenuBarPalette(); + return palette; +} + +const Widgets::UIEditorStatusBarPalette& ResolveUIEditorStatusBarPalette() { + static const Widgets::UIEditorStatusBarPalette palette = BuildStatusBarPalette(); + return palette; +} + +const Widgets::UIEditorPanelFramePalette& ResolveUIEditorPanelFramePalette() { + static const Widgets::UIEditorPanelFramePalette palette = BuildPanelFramePalette(); + return palette; +} + +const Widgets::UIEditorDockHostPalette& ResolveUIEditorDockHostPalette() { + static const Widgets::UIEditorDockHostPalette palette = BuildDockHostPalette(); + return palette; +} + +const Widgets::UIEditorViewportSlotPalette& ResolveUIEditorViewportSlotPalette() { + static const Widgets::UIEditorViewportSlotPalette palette = BuildViewportSlotPalette(); + return palette; +} + +const UIEditorShellComposePalette& ResolveUIEditorShellComposePalette() { + static const UIEditorShellComposePalette palette = BuildShellComposePalette(); + return palette; +} + +const UIEditorShellInteractionPalette& ResolveUIEditorShellInteractionPalette() { + static const UIEditorShellInteractionPalette palette = BuildShellInteractionPalette(); + return palette; +} + #undef XCUIEDITOR_DEFINE_DEFAULT_ACCESSORS } // namespace XCEngine::UI::Editor diff --git a/new_editor/src/Widgets/UIEditorFieldRowLayout.cpp b/new_editor/src/Widgets/UIEditorFieldRowLayout.cpp index c4e59319..cdf4e6b5 100644 --- a/new_editor/src/Widgets/UIEditorFieldRowLayout.cpp +++ b/new_editor/src/Widgets/UIEditorFieldRowLayout.cpp @@ -18,7 +18,39 @@ bool AreEqual(float lhs, float rhs) { } // namespace const UIEditorInspectorFieldStyleTokens& GetUIEditorInspectorFieldStyleTokens() { - static const UIEditorInspectorFieldStyleTokens kTokens = {}; + static const UIEditorInspectorFieldStyleTokens kTokens = [] { + UIEditorInspectorFieldStyleTokens tokens = {}; + tokens.rowHoverColor = ::XCEngine::UI::UIColor(0.12f, 0.12f, 0.12f, 1.0f); + tokens.rowActiveColor = ::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f); + tokens.labelColor = ::XCEngine::UI::UIColor(0.78f, 0.78f, 0.78f, 1.0f); + tokens.valueColor = ::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f); + tokens.readOnlyValueColor = ::XCEngine::UI::UIColor(0.60f, 0.60f, 0.60f, 1.0f); + tokens.controlColor = ::XCEngine::UI::UIColor(0.12f, 0.12f, 0.12f, 1.0f); + tokens.controlHoverColor = ::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f); + tokens.controlEditingColor = ::XCEngine::UI::UIColor(0.18f, 0.18f, 0.18f, 1.0f); + tokens.controlReadOnlyColor = ::XCEngine::UI::UIColor(0.10f, 0.10f, 0.10f, 1.0f); + tokens.controlBorderColor = ::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f); + tokens.controlFocusedBorderColor = ::XCEngine::UI::UIColor(0.18f, 0.18f, 0.18f, 1.0f); + tokens.prefixColor = ::XCEngine::UI::UIColor(0.12f, 0.12f, 0.12f, 1.0f); + tokens.prefixBorderColor = ::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f); + tokens.popupColor = ::XCEngine::UI::UIColor(0.10f, 0.10f, 0.10f, 1.0f); + tokens.popupBorderColor = ::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f); + tokens.popupHeaderColor = ::XCEngine::UI::UIColor(0.11f, 0.11f, 0.11f, 1.0f); + tokens.popupTitleColor = ::XCEngine::UI::UIColor(0.93f, 0.93f, 0.93f, 1.0f); + tokens.popupTextColor = ::XCEngine::UI::UIColor(0.86f, 0.86f, 0.86f, 1.0f); + tokens.popupTextMutedColor = ::XCEngine::UI::UIColor(0.68f, 0.68f, 0.68f, 1.0f); + tokens.previewBorderColor = ::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f); + tokens.previewBaseColor = ::XCEngine::UI::UIColor(0.12f, 0.12f, 0.12f, 1.0f); + tokens.checkerLightColor = ::XCEngine::UI::UIColor(0.26f, 0.26f, 0.26f, 1.0f); + tokens.checkerDarkColor = ::XCEngine::UI::UIColor(0.16f, 0.16f, 0.16f, 1.0f); + tokens.sliderBorderColor = ::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f); + tokens.numericBoxColor = ::XCEngine::UI::UIColor(0.12f, 0.12f, 0.12f, 1.0f); + tokens.numericBoxBorderColor = ::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f); + tokens.numericBoxTextColor = ::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f); + tokens.closeButtonHoverColor = ::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f); + tokens.closeGlyphColor = ::XCEngine::UI::UIColor(0.85f, 0.85f, 0.85f, 1.0f); + return tokens; + }(); return kTokens; }