Checkpoint current new editor host iteration
This commit is contained in:
@@ -141,6 +141,7 @@ xcui_editor_apply_common_target_settings(XCUIEditorHost PUBLIC)
|
|||||||
target_link_libraries(XCUIEditorHost PUBLIC
|
target_link_libraries(XCUIEditorHost PUBLIC
|
||||||
XCEngine
|
XCEngine
|
||||||
d2d1.lib
|
d2d1.lib
|
||||||
|
d3d11.lib
|
||||||
d3d12.lib
|
d3d12.lib
|
||||||
d3dcompiler.lib
|
d3dcompiler.lib
|
||||||
dwrite.lib
|
dwrite.lib
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ constexpr const wchar_t* kWindowClassName = L"XCEditorShellHost";
|
|||||||
constexpr const wchar_t* kWindowTitle = L"Main Scene * - Main.xx - XCEngine Editor";
|
constexpr const wchar_t* kWindowTitle = L"Main Scene * - Main.xx - XCEngine Editor";
|
||||||
constexpr UINT kDefaultDpi = 96u;
|
constexpr UINT kDefaultDpi = 96u;
|
||||||
constexpr float kBaseDpiScale = 96.0f;
|
constexpr float kBaseDpiScale = 96.0f;
|
||||||
|
constexpr UINT kDeferredRenderMessage = WM_APP + 1u;
|
||||||
|
|
||||||
bool ResolveVerboseRuntimeTraceEnabled() {
|
bool ResolveVerboseRuntimeTraceEnabled() {
|
||||||
wchar_t buffer[8] = {};
|
wchar_t buffer[8] = {};
|
||||||
@@ -541,6 +542,8 @@ void Application::RenderFrame() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ApplyPendingWindowResize();
|
||||||
|
|
||||||
RECT clientRect = {};
|
RECT clientRect = {};
|
||||||
GetClientRect(m_hwnd, &clientRect);
|
GetClientRect(m_hwnd, &clientRect);
|
||||||
const unsigned int pixelWidth =
|
const unsigned int pixelWidth =
|
||||||
@@ -607,7 +610,7 @@ void Application::RenderFrame() {
|
|||||||
ApplyHostedContentCaptureRequests();
|
ApplyHostedContentCaptureRequests();
|
||||||
ApplyCurrentCursor();
|
ApplyCurrentCursor();
|
||||||
m_editorWorkspace.Append(drawList);
|
m_editorWorkspace.Append(drawList);
|
||||||
if (d3d12FrameBegun && !m_inInteractiveResize) {
|
if (d3d12FrameBegun) {
|
||||||
m_editorWorkspace.RenderRequestedViewports(m_windowRenderer.GetRenderContext());
|
m_editorWorkspace.RenderRequestedViewports(m_windowRenderer.GetRenderContext());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -760,36 +763,51 @@ std::string Application::DescribeInputEvents(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Application::OnResize() {
|
void Application::OnResize() {
|
||||||
|
QueueCurrentClientResize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::OnEnterSizeMove() {
|
||||||
|
m_inInteractiveResize = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::OnExitSizeMove() {
|
||||||
|
m_inInteractiveResize = false;
|
||||||
|
QueueCurrentClientResize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::QueueWindowResize(UINT width, UINT height) {
|
||||||
|
if (width == 0u || height == 0u) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_pendingWindowResizeWidth = width;
|
||||||
|
m_pendingWindowResizeHeight = height;
|
||||||
|
m_hasPendingWindowResize = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::QueueCurrentClientResize() {
|
||||||
UINT width = 0u;
|
UINT width = 0u;
|
||||||
UINT height = 0u;
|
UINT height = 0u;
|
||||||
if (!QueryCurrentClientPixelSize(width, height)) {
|
if (!QueryCurrentClientPixelSize(width, height)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_renderer.Resize(width, height);
|
QueueWindowResize(width, height);
|
||||||
CommitWindowResize();
|
}
|
||||||
if (m_inInteractiveResize) {
|
|
||||||
m_editorWorkspace.SetViewportSurfacePresentationEnabled(false);
|
bool Application::ApplyPendingWindowResize() {
|
||||||
|
if (!m_hasPendingWindowResize) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void Application::OnEnterSizeMove() {
|
const UINT width = m_pendingWindowResizeWidth;
|
||||||
m_inInteractiveResize = true;
|
const UINT height = m_pendingWindowResizeHeight;
|
||||||
m_editorWorkspace.SetViewportSurfacePresentationEnabled(false);
|
m_hasPendingWindowResize = false;
|
||||||
}
|
if (width == 0u || height == 0u) {
|
||||||
|
|
||||||
void Application::OnExitSizeMove() {
|
|
||||||
m_inInteractiveResize = false;
|
|
||||||
CommitWindowResize();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Application::CommitWindowResize() {
|
|
||||||
UINT width = 0u;
|
|
||||||
UINT height = 0u;
|
|
||||||
if (!QueryCurrentClientPixelSize(width, height)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_renderer.Resize(width, height);
|
||||||
m_renderer.DetachWindowRenderer();
|
m_renderer.DetachWindowRenderer();
|
||||||
const bool resizedWindowRenderer =
|
const bool resizedWindowRenderer =
|
||||||
m_windowRenderer.Resize(static_cast<int>(width), static_cast<int>(height));
|
m_windowRenderer.Resize(static_cast<int>(width), static_cast<int>(height));
|
||||||
@@ -816,6 +834,15 @@ bool Application::CommitWindowResize() {
|
|||||||
return hasHealthyD3D12WindowInterop;
|
return hasHealthyD3D12WindowInterop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::RequestDeferredRenderFrame() {
|
||||||
|
if (m_hwnd == nullptr || !IsWindow(m_hwnd) || m_renderFrameQueued) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_renderFrameQueued = true;
|
||||||
|
PostMessageW(m_hwnd, kDeferredRenderMessage, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
bool Application::QueryCurrentClientPixelSize(UINT& outWidth, UINT& outHeight) const {
|
bool Application::QueryCurrentClientPixelSize(UINT& outWidth, UINT& outHeight) const {
|
||||||
outWidth = 0u;
|
outWidth = 0u;
|
||||||
outHeight = 0u;
|
outHeight = 0u;
|
||||||
@@ -844,16 +871,18 @@ void Application::OnDpiChanged(UINT dpi, const RECT& suggestedRect) {
|
|||||||
m_dpiScale = GetDpiScale();
|
m_dpiScale = GetDpiScale();
|
||||||
m_renderer.SetDpiScale(m_dpiScale);
|
m_renderer.SetDpiScale(m_dpiScale);
|
||||||
if (m_hwnd != nullptr) {
|
if (m_hwnd != nullptr) {
|
||||||
|
const LONG windowWidth = suggestedRect.right - suggestedRect.left;
|
||||||
|
const LONG windowHeight = suggestedRect.bottom - suggestedRect.top;
|
||||||
SetWindowPos(
|
SetWindowPos(
|
||||||
m_hwnd,
|
m_hwnd,
|
||||||
nullptr,
|
nullptr,
|
||||||
suggestedRect.left,
|
suggestedRect.left,
|
||||||
suggestedRect.top,
|
suggestedRect.top,
|
||||||
suggestedRect.right - suggestedRect.left,
|
windowWidth,
|
||||||
suggestedRect.bottom - suggestedRect.top,
|
windowHeight,
|
||||||
SWP_NOZORDER | SWP_NOACTIVATE);
|
SWP_NOZORDER | SWP_NOACTIVATE);
|
||||||
CommitWindowResize();
|
QueueCurrentClientResize();
|
||||||
InvalidateRect(m_hwnd, nullptr, FALSE);
|
RequestDeferredRenderFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostringstream trace = {};
|
std::ostringstream trace = {};
|
||||||
@@ -1011,16 +1040,23 @@ LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LP
|
|||||||
case WM_EXITSIZEMOVE:
|
case WM_EXITSIZEMOVE:
|
||||||
if (application != nullptr) {
|
if (application != nullptr) {
|
||||||
application->OnExitSizeMove();
|
application->OnExitSizeMove();
|
||||||
application->RenderFrame();
|
application->RequestDeferredRenderFrame();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WM_SIZE:
|
case WM_SIZE:
|
||||||
if (application != nullptr && wParam != SIZE_MINIMIZED) {
|
if (application != nullptr && wParam != SIZE_MINIMIZED) {
|
||||||
application->OnResize();
|
application->OnResize();
|
||||||
application->RenderFrame();
|
application->RequestDeferredRenderFrame();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
case kDeferredRenderMessage:
|
||||||
|
if (application != nullptr) {
|
||||||
|
application->m_renderFrameQueued = false;
|
||||||
|
application->RenderFrame();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case WM_PAINT:
|
case WM_PAINT:
|
||||||
if (application != nullptr) {
|
if (application != nullptr) {
|
||||||
PAINTSTRUCT paintStruct = {};
|
PAINTSTRUCT paintStruct = {};
|
||||||
|
|||||||
@@ -37,8 +37,15 @@ private:
|
|||||||
bool Initialize(HINSTANCE hInstance, int nCmdShow);
|
bool Initialize(HINSTANCE hInstance, int nCmdShow);
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
void RenderFrame();
|
void RenderFrame();
|
||||||
void OnResize(UINT width, UINT height);
|
void OnResize();
|
||||||
|
void OnEnterSizeMove();
|
||||||
|
void OnExitSizeMove();
|
||||||
void OnDpiChanged(UINT dpi, const RECT& suggestedRect);
|
void OnDpiChanged(UINT dpi, const RECT& suggestedRect);
|
||||||
|
void QueueWindowResize(UINT width, UINT height);
|
||||||
|
void QueueCurrentClientResize();
|
||||||
|
bool ApplyPendingWindowResize();
|
||||||
|
void RequestDeferredRenderFrame();
|
||||||
|
bool QueryCurrentClientPixelSize(UINT& outWidth, UINT& outHeight) const;
|
||||||
bool IsPointerInsideClientArea() const;
|
bool IsPointerInsideClientArea() const;
|
||||||
bool ApplyCurrentCursor() const;
|
bool ApplyCurrentCursor() const;
|
||||||
LPCWSTR ResolveCurrentCursorResource() const;
|
LPCWSTR ResolveCurrentCursorResource() const;
|
||||||
@@ -64,6 +71,7 @@ private:
|
|||||||
void QueueWindowFocusEvent(::XCEngine::UI::UIInputEventType type);
|
void QueueWindowFocusEvent(::XCEngine::UI::UIInputEventType type);
|
||||||
static std::filesystem::path ResolveRepoRootPath();
|
static std::filesystem::path ResolveRepoRootPath();
|
||||||
static LONG WINAPI HandleUnhandledException(EXCEPTION_POINTERS* exceptionInfo);
|
static LONG WINAPI HandleUnhandledException(EXCEPTION_POINTERS* exceptionInfo);
|
||||||
|
static bool IsVerboseRuntimeTraceEnabled();
|
||||||
|
|
||||||
HWND m_hwnd = nullptr;
|
HWND m_hwnd = nullptr;
|
||||||
HINSTANCE m_hInstance = nullptr;
|
HINSTANCE m_hInstance = nullptr;
|
||||||
@@ -78,6 +86,11 @@ private:
|
|||||||
bool m_trackingMouseLeave = false;
|
bool m_trackingMouseLeave = false;
|
||||||
UINT m_windowDpi = 96u;
|
UINT m_windowDpi = 96u;
|
||||||
float m_dpiScale = 1.0f;
|
float m_dpiScale = 1.0f;
|
||||||
|
bool m_inInteractiveResize = false;
|
||||||
|
bool m_renderFrameQueued = false;
|
||||||
|
bool m_hasPendingWindowResize = false;
|
||||||
|
UINT m_pendingWindowResizeWidth = 0u;
|
||||||
|
UINT m_pendingWindowResizeHeight = 0u;
|
||||||
};
|
};
|
||||||
|
|
||||||
int RunXCUIEditorApp(HINSTANCE hInstance, int nCmdShow);
|
int RunXCUIEditorApp(HINSTANCE hInstance, int nCmdShow);
|
||||||
|
|||||||
@@ -22,7 +22,10 @@
|
|||||||
|
|
||||||
#include <d3d12.h>
|
#include <d3d12.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <wrl/client.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace XCEngine::UI::Editor::Host {
|
namespace XCEngine::UI::Editor::Host {
|
||||||
@@ -34,13 +37,17 @@ public:
|
|||||||
|
|
||||||
bool Initialize(HWND hwnd, int width, int height);
|
bool Initialize(HWND hwnd, int width, int height);
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
void Resize(int width, int height);
|
bool Resize(int width, int height);
|
||||||
bool BeginFrame();
|
bool BeginFrame();
|
||||||
|
bool PreparePresentSurface();
|
||||||
bool SubmitFrame(bool presentSwapChain);
|
bool SubmitFrame(bool presentSwapChain);
|
||||||
|
bool SignalFrameCompletion();
|
||||||
|
bool PresentFrame();
|
||||||
|
|
||||||
ID3D12Device* GetDevice() const;
|
ID3D12Device* GetDevice() const;
|
||||||
ID3D12DescriptorHeap* GetSrvHeap() const;
|
ID3D12DescriptorHeap* GetSrvHeap() const;
|
||||||
ID3D12CommandQueue* GetCommandQueue() const;
|
ID3D12CommandQueue* GetCommandQueue() const;
|
||||||
|
const std::string& GetLastError() const;
|
||||||
void AllocateShaderResourceDescriptor(
|
void AllocateShaderResourceDescriptor(
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
|
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle);
|
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle);
|
||||||
@@ -57,6 +64,9 @@ public:
|
|||||||
::XCEngine::RHI::RHIDevice* GetRHIDevice() const;
|
::XCEngine::RHI::RHIDevice* GetRHIDevice() const;
|
||||||
::XCEngine::RHI::RHISwapChain* GetSwapChain() const;
|
::XCEngine::RHI::RHISwapChain* GetSwapChain() const;
|
||||||
const ::XCEngine::Rendering::RenderSurface* GetCurrentRenderSurface() const;
|
const ::XCEngine::Rendering::RenderSurface* GetCurrentRenderSurface() const;
|
||||||
|
const ::XCEngine::RHI::D3D12Texture* GetCurrentBackBufferTexture() const;
|
||||||
|
const ::XCEngine::RHI::D3D12Texture* GetBackBufferTexture(std::uint32_t index) const;
|
||||||
|
std::uint32_t GetBackBufferCount() const;
|
||||||
::XCEngine::Rendering::RenderContext GetRenderContext() const;
|
::XCEngine::Rendering::RenderContext GetRenderContext() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -64,13 +74,18 @@ private:
|
|||||||
::XCEngine::RHI::D3D12CommandQueue* GetD3D12CommandQueue() const;
|
::XCEngine::RHI::D3D12CommandQueue* GetD3D12CommandQueue() const;
|
||||||
::XCEngine::RHI::D3D12CommandList* GetD3D12CommandList() const;
|
::XCEngine::RHI::D3D12CommandList* GetD3D12CommandList() const;
|
||||||
::XCEngine::RHI::D3D12SwapChain* GetD3D12SwapChain() const;
|
::XCEngine::RHI::D3D12SwapChain* GetD3D12SwapChain() const;
|
||||||
|
::XCEngine::RHI::RHICommandList* GetCurrentCommandList() const;
|
||||||
void AllocateShaderResourceDescriptorInternal(
|
void AllocateShaderResourceDescriptorInternal(
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
|
D3D12_CPU_DESCRIPTOR_HANDLE* outCpuHandle,
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle);
|
D3D12_GPU_DESCRIPTOR_HANDLE* outGpuHandle);
|
||||||
void FreeShaderResourceDescriptorInternal(
|
void FreeShaderResourceDescriptorInternal(
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle,
|
D3D12_CPU_DESCRIPTOR_HANDLE cpuHandle,
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle);
|
D3D12_GPU_DESCRIPTOR_HANDLE gpuHandle);
|
||||||
|
bool InitializeFrameCompletionFence();
|
||||||
|
void ReleaseFrameCompletionFence();
|
||||||
|
void WaitForBackBufferFrame(std::uint32_t backBufferIndex);
|
||||||
void WaitForGpuIdle();
|
void WaitForGpuIdle();
|
||||||
|
void ReleaseBackBufferCommandReferences();
|
||||||
void ReleaseBackBufferViews();
|
void ReleaseBackBufferViews();
|
||||||
bool RecreateBackBufferViews();
|
bool RecreateBackBufferViews();
|
||||||
|
|
||||||
@@ -80,13 +95,19 @@ private:
|
|||||||
|
|
||||||
::XCEngine::RHI::RHIDevice* m_device = nullptr;
|
::XCEngine::RHI::RHIDevice* m_device = nullptr;
|
||||||
::XCEngine::RHI::RHICommandQueue* m_commandQueue = nullptr;
|
::XCEngine::RHI::RHICommandQueue* m_commandQueue = nullptr;
|
||||||
::XCEngine::RHI::RHICommandList* m_commandList = nullptr;
|
std::array<::XCEngine::RHI::RHICommandList*, kSwapChainBufferCount> m_commandLists = {};
|
||||||
::XCEngine::RHI::RHISwapChain* m_swapChain = nullptr;
|
::XCEngine::RHI::RHISwapChain* m_swapChain = nullptr;
|
||||||
::XCEngine::RHI::RHIDescriptorPool* m_srvPool = nullptr;
|
::XCEngine::RHI::RHIDescriptorPool* m_srvPool = nullptr;
|
||||||
::XCEngine::RHI::D3D12DescriptorHeap* m_srvHeap = nullptr;
|
::XCEngine::RHI::D3D12DescriptorHeap* m_srvHeap = nullptr;
|
||||||
std::vector<bool> m_srvUsage = {};
|
std::vector<bool> m_srvUsage = {};
|
||||||
std::vector<::XCEngine::RHI::RHIResourceView*> m_backBufferViews = {};
|
std::vector<::XCEngine::RHI::RHIResourceView*> m_backBufferViews = {};
|
||||||
std::vector<::XCEngine::Rendering::RenderSurface> m_backBufferSurfaces = {};
|
std::vector<::XCEngine::Rendering::RenderSurface> m_backBufferSurfaces = {};
|
||||||
|
Microsoft::WRL::ComPtr<ID3D12Fence> m_frameCompletionFence = {};
|
||||||
|
HANDLE m_frameCompletionEvent = nullptr;
|
||||||
|
std::array<std::uint64_t, kSwapChainBufferCount> m_backBufferFenceValues = {};
|
||||||
|
std::uint32_t m_activeBackBufferIndex = 0u;
|
||||||
|
std::uint64_t m_lastSubmittedFrameValue = 0;
|
||||||
|
std::string m_lastError = {};
|
||||||
UINT m_srvDescriptorSize = 0;
|
UINT m_srvDescriptorSize = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,17 @@
|
|||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "D3D12WindowRenderer.h"
|
||||||
|
|
||||||
#include <XCEditor/Foundation/UIEditorTextMeasurement.h>
|
#include <XCEditor/Foundation/UIEditorTextMeasurement.h>
|
||||||
|
|
||||||
#include <XCEngine/UI/DrawData.h>
|
#include <XCEngine/UI/DrawData.h>
|
||||||
|
|
||||||
#include <d2d1.h>
|
#include <d2d1_1.h>
|
||||||
|
#include <d3d11_4.h>
|
||||||
|
#include <d3d11on12.h>
|
||||||
#include <dwrite.h>
|
#include <dwrite.h>
|
||||||
|
#include <dxgi1_2.h>
|
||||||
#include <wincodec.h>
|
#include <wincodec.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <wrl/client.h>
|
#include <wrl/client.h>
|
||||||
@@ -30,7 +35,13 @@ public:
|
|||||||
void SetDpiScale(float dpiScale);
|
void SetDpiScale(float dpiScale);
|
||||||
float GetDpiScale() const;
|
float GetDpiScale() const;
|
||||||
void Resize(UINT width, UINT height);
|
void Resize(UINT width, UINT height);
|
||||||
|
bool AttachWindowRenderer(D3D12WindowRenderer& windowRenderer);
|
||||||
|
void DetachWindowRenderer();
|
||||||
|
void ReleaseWindowRendererBackBufferTargets();
|
||||||
|
bool RebuildWindowRendererBackBufferTargets();
|
||||||
|
bool HasAttachedWindowRenderer() const;
|
||||||
bool Render(const ::XCEngine::UI::UIDrawData& drawData);
|
bool Render(const ::XCEngine::UI::UIDrawData& drawData);
|
||||||
|
bool RenderToWindowRenderer(const ::XCEngine::UI::UIDrawData& drawData);
|
||||||
const std::string& GetLastRenderError() const;
|
const std::string& GetLastRenderError() const;
|
||||||
bool LoadTextureFromFile(
|
bool LoadTextureFromFile(
|
||||||
const std::filesystem::path& path,
|
const std::filesystem::path& path,
|
||||||
@@ -47,15 +58,6 @@ public:
|
|||||||
std::string& outError);
|
std::string& outError);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool EnsureRenderTarget();
|
|
||||||
bool EnsureWicFactory(std::string& outError);
|
|
||||||
void DiscardRenderTarget();
|
|
||||||
bool CreateDeviceResources();
|
|
||||||
void InvalidateCachedTextureBitmaps(const ID2D1RenderTarget* renderTarget);
|
|
||||||
bool RenderToTarget(
|
|
||||||
ID2D1RenderTarget& renderTarget,
|
|
||||||
ID2D1SolidColorBrush& solidBrush,
|
|
||||||
const ::XCEngine::UI::UIDrawData& drawData);
|
|
||||||
struct NativeTextureResource {
|
struct NativeTextureResource {
|
||||||
std::vector<std::uint8_t> pixels = {};
|
std::vector<std::uint8_t> pixels = {};
|
||||||
Microsoft::WRL::ComPtr<ID2D1Bitmap> cachedBitmap = {};
|
Microsoft::WRL::ComPtr<ID2D1Bitmap> cachedBitmap = {};
|
||||||
@@ -63,6 +65,30 @@ private:
|
|||||||
UINT width = 0u;
|
UINT width = 0u;
|
||||||
UINT height = 0u;
|
UINT height = 0u;
|
||||||
};
|
};
|
||||||
|
struct D3D12BackBufferInteropTarget {
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11Resource> wrappedResource = {};
|
||||||
|
Microsoft::WRL::ComPtr<ID2D1Bitmap1> targetBitmap = {};
|
||||||
|
};
|
||||||
|
struct D3D12SourceTextureInteropResource {
|
||||||
|
std::uintptr_t key = 0u;
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11Resource> wrappedResource = {};
|
||||||
|
Microsoft::WRL::ComPtr<ID2D1Bitmap1> bitmap = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
bool EnsureRenderTarget();
|
||||||
|
bool EnsureWindowRendererInterop();
|
||||||
|
bool EnsureWicFactory(std::string& outError);
|
||||||
|
void DiscardRenderTarget();
|
||||||
|
bool CreateDeviceResources();
|
||||||
|
void ReleaseWindowRendererInterop();
|
||||||
|
bool RebuildBackBufferInteropTargets();
|
||||||
|
void ClearActiveInteropSourceTextures();
|
||||||
|
bool PrepareActiveInteropSourceTextures(const ::XCEngine::UI::UIDrawData& drawData);
|
||||||
|
void InvalidateCachedTextureBitmaps(const ID2D1RenderTarget* renderTarget);
|
||||||
|
bool RenderToTarget(
|
||||||
|
ID2D1RenderTarget& renderTarget,
|
||||||
|
ID2D1SolidColorBrush& solidBrush,
|
||||||
|
const ::XCEngine::UI::UIDrawData& drawData);
|
||||||
bool DecodeTextureFile(
|
bool DecodeTextureFile(
|
||||||
const std::filesystem::path& path,
|
const std::filesystem::path& path,
|
||||||
NativeTextureResource& outTexture,
|
NativeTextureResource& outTexture,
|
||||||
@@ -71,6 +97,9 @@ private:
|
|||||||
ID2D1RenderTarget& renderTarget,
|
ID2D1RenderTarget& renderTarget,
|
||||||
NativeTextureResource& texture,
|
NativeTextureResource& texture,
|
||||||
Microsoft::WRL::ComPtr<ID2D1Bitmap>& outBitmap);
|
Microsoft::WRL::ComPtr<ID2D1Bitmap>& outBitmap);
|
||||||
|
bool ResolveInteropBitmap(
|
||||||
|
const ::XCEngine::UI::UITextureHandle& texture,
|
||||||
|
Microsoft::WRL::ComPtr<ID2D1Bitmap>& outBitmap) const;
|
||||||
void RenderCommand(
|
void RenderCommand(
|
||||||
ID2D1RenderTarget& renderTarget,
|
ID2D1RenderTarget& renderTarget,
|
||||||
ID2D1SolidColorBrush& solidBrush,
|
ID2D1SolidColorBrush& solidBrush,
|
||||||
@@ -82,11 +111,21 @@ private:
|
|||||||
static std::wstring Utf8ToWide(std::string_view text);
|
static std::wstring Utf8ToWide(std::string_view text);
|
||||||
|
|
||||||
HWND m_hwnd = nullptr;
|
HWND m_hwnd = nullptr;
|
||||||
Microsoft::WRL::ComPtr<ID2D1Factory> m_d2dFactory;
|
D3D12WindowRenderer* m_windowRenderer = nullptr;
|
||||||
|
Microsoft::WRL::ComPtr<ID2D1Factory1> m_d2dFactory;
|
||||||
Microsoft::WRL::ComPtr<IDWriteFactory> m_dwriteFactory;
|
Microsoft::WRL::ComPtr<IDWriteFactory> m_dwriteFactory;
|
||||||
Microsoft::WRL::ComPtr<IWICImagingFactory> m_wicFactory;
|
Microsoft::WRL::ComPtr<IWICImagingFactory> m_wicFactory;
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11Device> m_d3d11Device;
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_d3d11DeviceContext;
|
||||||
|
Microsoft::WRL::ComPtr<ID3D11On12Device> m_d3d11On12Device;
|
||||||
|
Microsoft::WRL::ComPtr<ID2D1Device> m_d2dDevice;
|
||||||
|
Microsoft::WRL::ComPtr<ID2D1DeviceContext> m_d2dDeviceContext;
|
||||||
Microsoft::WRL::ComPtr<ID2D1HwndRenderTarget> m_renderTarget;
|
Microsoft::WRL::ComPtr<ID2D1HwndRenderTarget> m_renderTarget;
|
||||||
Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> m_solidBrush;
|
Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> m_solidBrush;
|
||||||
|
Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> m_interopBrush;
|
||||||
|
std::vector<D3D12BackBufferInteropTarget> m_backBufferInteropTargets = {};
|
||||||
|
std::vector<D3D12SourceTextureInteropResource> m_activeInteropSourceTextures = {};
|
||||||
|
std::unordered_map<std::uintptr_t, Microsoft::WRL::ComPtr<ID2D1Bitmap1>> m_activeInteropBitmaps;
|
||||||
mutable std::unordered_map<int, Microsoft::WRL::ComPtr<IDWriteTextFormat>> m_textFormats;
|
mutable std::unordered_map<int, Microsoft::WRL::ComPtr<IDWriteTextFormat>> m_textFormats;
|
||||||
std::unordered_set<NativeTextureResource*> m_liveTextures;
|
std::unordered_set<NativeTextureResource*> m_liveTextures;
|
||||||
std::string m_lastRenderError = {};
|
std::string m_lastRenderError = {};
|
||||||
|
|||||||
@@ -429,11 +429,10 @@ UIEditorWorkspacePanelPresentationModel BuildViewportPresentation(
|
|||||||
presentation.panelId = std::move(panelId);
|
presentation.panelId = std::move(panelId);
|
||||||
presentation.kind = UIEditorPanelPresentationKind::ViewportShell;
|
presentation.kind = UIEditorPanelPresentationKind::ViewportShell;
|
||||||
presentation.viewportShellModel.spec.chrome.title = std::move(title);
|
presentation.viewportShellModel.spec.chrome.title = std::move(title);
|
||||||
presentation.viewportShellModel.spec.chrome.subtitle = std::move(subtitle);
|
presentation.viewportShellModel.spec.chrome.subtitle = {};
|
||||||
presentation.viewportShellModel.spec.chrome.showTopBar = true;
|
presentation.viewportShellModel.spec.chrome.showTopBar = false;
|
||||||
presentation.viewportShellModel.spec.chrome.showBottomBar = true;
|
presentation.viewportShellModel.spec.chrome.showBottomBar = false;
|
||||||
presentation.viewportShellModel.frame.statusText =
|
presentation.viewportShellModel.frame.statusText.clear();
|
||||||
"Viewport request chain is active.";
|
|
||||||
return presentation;
|
return presentation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,8 +447,8 @@ UIEditorShellInteractionDefinition BuildBaseShellDefinition() {
|
|||||||
definition.statusSegments = {};
|
definition.statusSegments = {};
|
||||||
definition.workspacePresentations = {
|
definition.workspacePresentations = {
|
||||||
BuildHostedContentPresentation("hierarchy"),
|
BuildHostedContentPresentation("hierarchy"),
|
||||||
BuildViewportPresentation("scene", "Scene", "New Editor viewport shell"),
|
BuildViewportPresentation("scene", "Scene", {}),
|
||||||
BuildViewportPresentation("game", "Game", "New Editor viewport shell"),
|
BuildViewportPresentation("game", "Game", {}),
|
||||||
BuildHostedContentPresentation("inspector"),
|
BuildHostedContentPresentation("inspector"),
|
||||||
BuildHostedContentPresentation("console"),
|
BuildHostedContentPresentation("console"),
|
||||||
BuildHostedContentPresentation("project")
|
BuildHostedContentPresentation("project")
|
||||||
|
|||||||
@@ -8,24 +8,6 @@ namespace {
|
|||||||
|
|
||||||
using ::XCEngine::RHI::ResourceStates;
|
using ::XCEngine::RHI::ResourceStates;
|
||||||
|
|
||||||
std::string BuildViewportPendingStatus(ProductViewportKind kind) {
|
|
||||||
return kind == ProductViewportKind::Scene
|
|
||||||
? "Scene viewport host pending D3D12 presenter integration."
|
|
||||||
: "Game viewport host pending D3D12 presenter integration.";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string BuildViewportReadyStatus(ProductViewportKind kind) {
|
|
||||||
return kind == ProductViewportKind::Scene
|
|
||||||
? "Scene viewport render target ready; presenter still uses NativeRenderer."
|
|
||||||
: "Game viewport render target ready; presenter still uses NativeRenderer.";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string BuildViewportPresentedStatus(ProductViewportKind kind) {
|
|
||||||
return kind == ProductViewportKind::Scene
|
|
||||||
? "Scene viewport frame ready."
|
|
||||||
: "Game viewport frame ready.";
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void ProductViewportHostService::AttachWindowRenderer(
|
void ProductViewportHostService::AttachWindowRenderer(
|
||||||
@@ -81,23 +63,17 @@ ProductViewportFrame ProductViewportHostService::RequestViewport(
|
|||||||
: 0u;
|
: 0u;
|
||||||
|
|
||||||
if (!entry.requestedThisFrame) {
|
if (!entry.requestedThisFrame) {
|
||||||
entry.statusText = "Viewport is waiting for a visible surface.";
|
|
||||||
return BuildFrame(entry, requestedSize);
|
return BuildFrame(entry, requestedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_windowRenderer == nullptr || m_device == nullptr) {
|
if (m_windowRenderer == nullptr || m_device == nullptr) {
|
||||||
entry.statusText = BuildViewportPendingStatus(kind);
|
|
||||||
return BuildFrame(entry, requestedSize);
|
return BuildFrame(entry, requestedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EnsureViewportResources(entry)) {
|
if (!EnsureViewportResources(entry)) {
|
||||||
entry.statusText = "Failed to create viewport render targets.";
|
|
||||||
return BuildFrame(entry, requestedSize);
|
return BuildFrame(entry, requestedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
entry.statusText = m_surfacePresentationEnabled
|
|
||||||
? BuildViewportPresentedStatus(kind)
|
|
||||||
: BuildViewportReadyStatus(kind);
|
|
||||||
return BuildFrame(entry, requestedSize);
|
return BuildFrame(entry, requestedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,9 +95,6 @@ void ProductViewportHostService::RenderRequestedViewports(
|
|||||||
}
|
}
|
||||||
|
|
||||||
entry.renderedThisFrame = true;
|
entry.renderedThisFrame = true;
|
||||||
entry.statusText = m_surfacePresentationEnabled
|
|
||||||
? BuildViewportPresentedStatus(entry.kind)
|
|
||||||
: BuildViewportReadyStatus(entry.kind);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,33 +36,62 @@ void ApplyViewportFrameToPresentation(
|
|||||||
presentation.viewportShellModel.frame.statusText = viewportFrame.statusText;
|
presentation.viewportShellModel.frame.statusText = viewportFrame.statusText;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<UIEditorWorkspacePanelPresentationModel> BuildWorkspacePresentations(
|
void ApplyViewportFrameToShellModel(
|
||||||
const UIEditorShellInteractionDefinition& definition,
|
const ProductViewportFrame& viewportFrame,
|
||||||
const UIEditorShellInteractionRequest& shellRequest,
|
UIEditorViewportShellModel& shellModel) {
|
||||||
ProductViewportHostService& viewportHostService) {
|
shellModel.frame.texture = viewportFrame.texture;
|
||||||
std::vector<UIEditorWorkspacePanelPresentationModel> presentations =
|
shellModel.frame.requestedSize = viewportFrame.requestedSize;
|
||||||
definition.workspacePresentations;
|
shellModel.frame.presentedSize = viewportFrame.renderSize;
|
||||||
for (UIEditorWorkspacePanelPresentationModel& presentation : presentations) {
|
shellModel.frame.hasTexture = viewportFrame.hasTexture;
|
||||||
if (presentation.kind != UIEditorPanelPresentationKind::ViewportShell ||
|
shellModel.frame.statusText = viewportFrame.statusText;
|
||||||
!IsProductViewportPanel(presentation.panelId)) {
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const UIEditorWorkspaceViewportComposeRequest* viewportRequest =
|
UIEditorWorkspacePanelPresentationModel* FindMutableWorkspacePresentation(
|
||||||
FindUIEditorWorkspaceViewportPresentationRequest(
|
std::vector<UIEditorWorkspacePanelPresentationModel>& presentations,
|
||||||
shellRequest.shellRequest.workspaceRequest,
|
std::string_view panelId) {
|
||||||
presentation.panelId);
|
for (UIEditorWorkspacePanelPresentationModel& presentation : presentations) {
|
||||||
const ::XCEngine::UI::UISize requestedSize =
|
if (presentation.panelId == panelId) {
|
||||||
viewportRequest != nullptr
|
return &presentation;
|
||||||
? viewportRequest->viewportShellRequest.requestedViewportSize
|
}
|
||||||
: ::XCEngine::UI::UISize();
|
|
||||||
ApplyViewportFrameToPresentation(
|
|
||||||
viewportHostService.RequestViewport(
|
|
||||||
ResolveProductViewportKind(presentation.panelId),
|
|
||||||
requestedSize),
|
|
||||||
presentation);
|
|
||||||
}
|
}
|
||||||
return presentations;
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyViewportFramesToShellFrame(
|
||||||
|
UIEditorShellInteractionFrame& shellFrame,
|
||||||
|
ProductViewportHostService& viewportHostService) {
|
||||||
|
auto applyToViewportFrames =
|
||||||
|
[&](std::vector<UIEditorWorkspaceViewportComposeFrame>& viewportFrames) {
|
||||||
|
for (UIEditorWorkspaceViewportComposeFrame& viewportComposeFrame : viewportFrames) {
|
||||||
|
if (!IsProductViewportPanel(viewportComposeFrame.panelId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProductViewportFrame viewportFrame =
|
||||||
|
viewportHostService.RequestViewport(
|
||||||
|
ResolveProductViewportKind(viewportComposeFrame.panelId),
|
||||||
|
viewportComposeFrame.viewportShellFrame.requestedViewportSize);
|
||||||
|
ApplyViewportFrameToShellModel(
|
||||||
|
viewportFrame,
|
||||||
|
viewportComposeFrame.viewportShellModel);
|
||||||
|
if (UIEditorWorkspacePanelPresentationModel* presentation =
|
||||||
|
FindMutableWorkspacePresentation(
|
||||||
|
shellFrame.model.workspacePresentations,
|
||||||
|
viewportComposeFrame.panelId);
|
||||||
|
presentation != nullptr) {
|
||||||
|
ApplyViewportFrameToPresentation(viewportFrame, *presentation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
applyToViewportFrames(shellFrame.workspaceInteractionFrame.composeFrame.viewportFrames);
|
||||||
|
applyToViewportFrames(shellFrame.shellFrame.workspaceFrame.viewportFrames);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<UIEditorWorkspacePanelPresentationModel> BuildWorkspacePresentations(
|
||||||
|
const UIEditorShellInteractionDefinition& definition) {
|
||||||
|
return definition.workspacePresentations;
|
||||||
}
|
}
|
||||||
|
|
||||||
UIEditorShellComposeModel BuildShellComposeModelFromFrame(
|
UIEditorShellComposeModel BuildShellComposeModelFromFrame(
|
||||||
@@ -168,18 +197,7 @@ void ProductEditorWorkspace::Update(
|
|||||||
UIEditorShellInteractionDefinition definition =
|
UIEditorShellInteractionDefinition definition =
|
||||||
context.BuildShellDefinition(captureText);
|
context.BuildShellDefinition(captureText);
|
||||||
m_viewportHostService.BeginFrame();
|
m_viewportHostService.BeginFrame();
|
||||||
const UIEditorShellInteractionRequest shellRequest =
|
definition.workspacePresentations = BuildWorkspacePresentations(definition);
|
||||||
ResolveUIEditorShellInteractionRequest(
|
|
||||||
bounds,
|
|
||||||
context.GetWorkspaceController(),
|
|
||||||
definition,
|
|
||||||
m_shellInteractionState,
|
|
||||||
metrics,
|
|
||||||
context.GetShellServices());
|
|
||||||
definition.workspacePresentations = BuildWorkspacePresentations(
|
|
||||||
definition,
|
|
||||||
shellRequest,
|
|
||||||
m_viewportHostService);
|
|
||||||
const std::vector<UIInputEvent> hostedContentEvents = inputEvents;
|
const std::vector<UIInputEvent> hostedContentEvents = inputEvents;
|
||||||
const std::vector<UIInputEvent> shellEvents =
|
const std::vector<UIInputEvent> shellEvents =
|
||||||
HasHostedContentCapture()
|
HasHostedContentCapture()
|
||||||
@@ -194,6 +212,7 @@ void ProductEditorWorkspace::Update(
|
|||||||
shellEvents,
|
shellEvents,
|
||||||
context.GetShellServices(),
|
context.GetShellServices(),
|
||||||
metrics);
|
metrics);
|
||||||
|
ApplyViewportFramesToShellFrame(m_shellFrame, m_viewportHostService);
|
||||||
context.SyncSessionFromWorkspace();
|
context.SyncSessionFromWorkspace();
|
||||||
context.UpdateStatusFromShellResult(m_shellFrame.result);
|
context.UpdateStatusFromShellResult(m_shellFrame.result);
|
||||||
|
|
||||||
|
|||||||
@@ -19,5 +19,6 @@ void AppendUIEditorCrashTrace(
|
|||||||
|
|
||||||
std::filesystem::path GetUIEditorRuntimeTracePath();
|
std::filesystem::path GetUIEditorRuntimeTracePath();
|
||||||
std::filesystem::path GetUIEditorCrashTracePath();
|
std::filesystem::path GetUIEditorCrashTracePath();
|
||||||
|
bool IsUIEditorRuntimeTraceInitialized();
|
||||||
|
|
||||||
} // namespace XCEngine::UI::Editor
|
} // namespace XCEngine::UI::Editor
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ std::mutex g_traceMutex = {};
|
|||||||
std::filesystem::path g_logRoot = {};
|
std::filesystem::path g_logRoot = {};
|
||||||
std::filesystem::path g_runtimeTracePath = {};
|
std::filesystem::path g_runtimeTracePath = {};
|
||||||
std::filesystem::path g_crashTracePath = {};
|
std::filesystem::path g_crashTracePath = {};
|
||||||
|
std::ofstream g_runtimeTraceStream = {};
|
||||||
|
std::ofstream g_crashTraceStream = {};
|
||||||
bool g_traceInitialized = false;
|
bool g_traceInitialized = false;
|
||||||
|
|
||||||
std::string BuildTimestampString() {
|
std::string BuildTimestampString() {
|
||||||
@@ -40,16 +42,9 @@ std::string BuildTimestampString() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AppendTraceLine(
|
void AppendTraceLine(
|
||||||
const std::filesystem::path& path,
|
std::ofstream& stream,
|
||||||
std::string_view channel,
|
std::string_view channel,
|
||||||
std::string_view message) {
|
std::string_view message) {
|
||||||
if (path.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::error_code errorCode = {};
|
|
||||||
std::filesystem::create_directories(path.parent_path(), errorCode);
|
|
||||||
std::ofstream stream(path, std::ios::out | std::ios::app);
|
|
||||||
if (!stream.is_open()) {
|
if (!stream.is_open()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -70,11 +65,20 @@ void InitializeUIEditorRuntimeTrace(const std::filesystem::path& logRoot) {
|
|||||||
g_logRoot = logRoot.lexically_normal();
|
g_logRoot = logRoot.lexically_normal();
|
||||||
g_runtimeTracePath = (g_logRoot / "runtime.log").lexically_normal();
|
g_runtimeTracePath = (g_logRoot / "runtime.log").lexically_normal();
|
||||||
g_crashTracePath = (g_logRoot / "crash.log").lexically_normal();
|
g_crashTracePath = (g_logRoot / "crash.log").lexically_normal();
|
||||||
g_traceInitialized = true;
|
|
||||||
|
|
||||||
std::error_code errorCode = {};
|
std::error_code errorCode = {};
|
||||||
std::filesystem::create_directories(g_logRoot, errorCode);
|
std::filesystem::create_directories(g_logRoot, errorCode);
|
||||||
AppendTraceLine(g_runtimeTracePath, "trace", "trace session started");
|
g_runtimeTraceStream.close();
|
||||||
|
g_crashTraceStream.close();
|
||||||
|
g_runtimeTraceStream.open(g_runtimeTracePath, std::ios::out | std::ios::app);
|
||||||
|
g_crashTraceStream.open(g_crashTracePath, std::ios::out | std::ios::app);
|
||||||
|
g_traceInitialized = g_runtimeTraceStream.is_open() && g_crashTraceStream.is_open();
|
||||||
|
if (!g_traceInitialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AppendTraceLine(g_runtimeTraceStream, "trace", "trace session started");
|
||||||
|
g_runtimeTraceStream.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShutdownUIEditorRuntimeTrace() {
|
void ShutdownUIEditorRuntimeTrace() {
|
||||||
@@ -83,7 +87,11 @@ void ShutdownUIEditorRuntimeTrace() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AppendTraceLine(g_runtimeTracePath, "trace", "trace session ended");
|
AppendTraceLine(g_runtimeTraceStream, "trace", "trace session ended");
|
||||||
|
g_runtimeTraceStream.flush();
|
||||||
|
g_crashTraceStream.flush();
|
||||||
|
g_runtimeTraceStream.close();
|
||||||
|
g_crashTraceStream.close();
|
||||||
g_traceInitialized = false;
|
g_traceInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +103,7 @@ void AppendUIEditorRuntimeTrace(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AppendTraceLine(g_runtimeTracePath, channel, message);
|
AppendTraceLine(g_runtimeTraceStream, channel, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppendUIEditorCrashTrace(
|
void AppendUIEditorCrashTrace(
|
||||||
@@ -113,8 +121,10 @@ void AppendUIEditorCrashTrace(
|
|||||||
"Unhandled exception code=0x%08X address=%p",
|
"Unhandled exception code=0x%08X address=%p",
|
||||||
exceptionCode,
|
exceptionCode,
|
||||||
exceptionAddress);
|
exceptionAddress);
|
||||||
AppendTraceLine(g_crashTracePath, "crash", buffer);
|
AppendTraceLine(g_crashTraceStream, "crash", buffer);
|
||||||
AppendTraceLine(g_runtimeTracePath, "crash", buffer);
|
AppendTraceLine(g_runtimeTraceStream, "crash", buffer);
|
||||||
|
g_crashTraceStream.flush();
|
||||||
|
g_runtimeTraceStream.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path GetUIEditorRuntimeTracePath() {
|
std::filesystem::path GetUIEditorRuntimeTracePath() {
|
||||||
@@ -127,4 +137,9 @@ std::filesystem::path GetUIEditorCrashTracePath() {
|
|||||||
return g_crashTracePath;
|
return g_crashTracePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsUIEditorRuntimeTraceInitialized() {
|
||||||
|
std::lock_guard lock(g_traceMutex);
|
||||||
|
return g_traceInitialized;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace XCEngine::UI::Editor
|
} // namespace XCEngine::UI::Editor
|
||||||
|
|||||||
@@ -55,34 +55,6 @@ UISize ResolveFrameAspectSize(const UIEditorViewportSlotFrame& frame, const UISi
|
|||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
UIRect FitRectToAspect(const UIRect& container, const UISize& size) {
|
|
||||||
if (!HasArea(container) || size.width <= 0.0f || size.height <= 0.0f) {
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
const float containerAspect = container.width / container.height;
|
|
||||||
const float frameAspect = size.width / size.height;
|
|
||||||
if (frameAspect <= 0.0f) {
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frameAspect >= containerAspect) {
|
|
||||||
const float fittedHeight = container.width / frameAspect;
|
|
||||||
return UIRect(
|
|
||||||
container.x,
|
|
||||||
container.y + (container.height - fittedHeight) * 0.5f,
|
|
||||||
container.width,
|
|
||||||
fittedHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
const float fittedWidth = container.height * frameAspect;
|
|
||||||
return UIRect(
|
|
||||||
container.x + (container.width - fittedWidth) * 0.5f,
|
|
||||||
container.y,
|
|
||||||
fittedWidth,
|
|
||||||
container.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
UIColor ResolveToolFillColor(
|
UIColor ResolveToolFillColor(
|
||||||
const UIEditorViewportSlotToolItem& item,
|
const UIEditorViewportSlotToolItem& item,
|
||||||
bool hovered,
|
bool hovered,
|
||||||
@@ -199,11 +171,7 @@ UIEditorViewportSlotLayout BuildUIEditorViewportSlotLayout(
|
|||||||
layout.inputRect = InsetRect(layout.surfaceRect, metrics.surfaceInset);
|
layout.inputRect = InsetRect(layout.surfaceRect, metrics.surfaceInset);
|
||||||
layout.requestedSurfaceSize =
|
layout.requestedSurfaceSize =
|
||||||
UISize(layout.inputRect.width, layout.inputRect.height);
|
UISize(layout.inputRect.width, layout.inputRect.height);
|
||||||
layout.textureRect = frame.hasTexture
|
layout.textureRect = layout.inputRect;
|
||||||
? FitRectToAspect(
|
|
||||||
layout.inputRect,
|
|
||||||
ResolveFrameAspectSize(frame, layout.requestedSurfaceSize))
|
|
||||||
: layout.inputRect;
|
|
||||||
|
|
||||||
if (!layout.hasTopBar) {
|
if (!layout.hasTopBar) {
|
||||||
return layout;
|
return layout;
|
||||||
@@ -437,34 +405,8 @@ void AppendUIEditorViewportSlotForeground(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const UISize frameSize = ResolveFrameAspectSize(frame, layout.requestedSurfaceSize);
|
|
||||||
if (frame.hasTexture && frame.texture.IsValid()) {
|
if (frame.hasTexture && frame.texture.IsValid()) {
|
||||||
drawList.AddImage(layout.textureRect, frame.texture, palette.imageTint);
|
drawList.AddImage(layout.textureRect, frame.texture, palette.imageTint);
|
||||||
drawList.AddText(
|
|
||||||
UIPoint(layout.inputRect.x + 14.0f, layout.inputRect.y + 14.0f),
|
|
||||||
"Texture " +
|
|
||||||
std::to_string(static_cast<int>(frameSize.width)) +
|
|
||||||
"x" +
|
|
||||||
std::to_string(static_cast<int>(frameSize.height)),
|
|
||||||
palette.textMuted,
|
|
||||||
12.0f);
|
|
||||||
} else {
|
|
||||||
const std::string statusText = frame.statusText.empty()
|
|
||||||
? std::string("Viewport is waiting for frame")
|
|
||||||
: frame.statusText;
|
|
||||||
drawList.AddText(
|
|
||||||
UIPoint(layout.inputRect.x + 16.0f, layout.inputRect.y + 18.0f),
|
|
||||||
statusText,
|
|
||||||
palette.textPrimary,
|
|
||||||
14.0f);
|
|
||||||
drawList.AddText(
|
|
||||||
UIPoint(layout.inputRect.x + 16.0f, layout.inputRect.y + 42.0f),
|
|
||||||
"Requested surface: " +
|
|
||||||
std::to_string(static_cast<int>(layout.requestedSurfaceSize.width)) +
|
|
||||||
"x" +
|
|
||||||
std::to_string(static_cast<int>(layout.requestedSurfaceSize.height)),
|
|
||||||
palette.textMuted,
|
|
||||||
12.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layout.hasBottomBar) {
|
if (layout.hasBottomBar) {
|
||||||
|
|||||||
Reference in New Issue
Block a user