Refactor editor shell host layers
This commit is contained in:
@@ -1,65 +1,20 @@
|
||||
#include "Application.h"
|
||||
#include "Core/EditorWindowTitle.h"
|
||||
#include "Layers/EditorLayer.h"
|
||||
#include "Core/EditorContext.h"
|
||||
#include "Core/EditorConsoleSink.h"
|
||||
#include "Core/EditorEvents.h"
|
||||
#include "Core/EventBus.h"
|
||||
#include "Platform/Win32Utf8.h"
|
||||
#include <XCEngine/Debug/Logger.h>
|
||||
#include <XCEngine/Debug/FileLogSink.h>
|
||||
#include <XCEngine/Debug/ConsoleLogSink.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <filesystem>
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <string>
|
||||
|
||||
namespace {
|
||||
|
||||
std::string WideToUtf8(const std::wstring& value) {
|
||||
if (value.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
int len = WideCharToMultiByte(CP_UTF8, 0, value.c_str(), -1, nullptr, 0, nullptr, nullptr);
|
||||
if (len <= 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string result(len - 1, '\0');
|
||||
WideCharToMultiByte(CP_UTF8, 0, value.c_str(), -1, &result[0], len, nullptr, nullptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::wstring Utf8ToWide(const std::string& value) {
|
||||
if (value.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
int len = MultiByteToWideChar(CP_UTF8, 0, value.c_str(), -1, nullptr, 0);
|
||||
if (len <= 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::wstring result(len - 1, L'\0');
|
||||
MultiByteToWideChar(CP_UTF8, 0, value.c_str(), -1, &result[0], len);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string GetExecutableDirectoryUtf8() {
|
||||
wchar_t exePath[MAX_PATH];
|
||||
GetModuleFileNameW(nullptr, exePath, MAX_PATH);
|
||||
|
||||
std::wstring exeDirW(exePath);
|
||||
const size_t pos = exeDirW.find_last_of(L"\\/");
|
||||
if (pos != std::wstring::npos) {
|
||||
exeDirW = exeDirW.substr(0, pos);
|
||||
}
|
||||
|
||||
return WideToUtf8(exeDirW);
|
||||
}
|
||||
|
||||
std::string GetExecutableLogPath(const char* fileName) {
|
||||
return GetExecutableDirectoryUtf8() + "\\" + fileName;
|
||||
return XCEngine::Editor::Platform::GetExecutableDirectoryUtf8() + "\\" + fileName;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -92,24 +47,17 @@ Application& Application::Get() {
|
||||
}
|
||||
|
||||
bool Application::Initialize(HWND hwnd) {
|
||||
// Set global exception filter first to catch any crashes
|
||||
SetUnhandledExceptionFilter(GlobalExceptionFilter);
|
||||
|
||||
// Redirect stderr to log file to capture ImGui errors
|
||||
|
||||
{
|
||||
const std::string stderrPath = GetExecutableLogPath("stderr.log");
|
||||
freopen(stderrPath.c_str(), "w", stderr);
|
||||
|
||||
fprintf(stderr, "[TEST] stderr redirection test - this should appear in stderr.log\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
// Initialize logging first
|
||||
|
||||
Debug::Logger::Get().AddSink(std::make_unique<Debug::ConsoleLogSink>());
|
||||
Debug::Logger::Get().AddSink(std::make_unique<Debug::EditorConsoleSink>());
|
||||
|
||||
// Get exe directory for log file path
|
||||
const std::string exeDir = GetExecutableDirectoryUtf8();
|
||||
|
||||
const std::string exeDir = Platform::GetExecutableDirectoryUtf8();
|
||||
std::string logPath = exeDir + "\\editor.log";
|
||||
Debug::Logger::Get().AddSink(std::make_unique<Debug::FileLogSink>(logPath.c_str()));
|
||||
Debug::Logger::Get().Info(Debug::LogCategory::General, "Editor Application starting...");
|
||||
@@ -117,14 +65,10 @@ bool Application::Initialize(HWND hwnd) {
|
||||
|
||||
m_hwnd = hwnd;
|
||||
|
||||
if (!CreateDevice()) {
|
||||
if (!m_windowRenderer.Initialize(hwnd, 1280, 720)) {
|
||||
MessageBoxW(hwnd, L"Failed to create D3D12 device", L"Error", MB_OK | MB_ICONERROR);
|
||||
return false;
|
||||
}
|
||||
if (!CreateRenderTarget()) {
|
||||
MessageBoxW(hwnd, L"Failed to create render target", L"Error", MB_OK | MB_ICONERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_editorContext = std::make_shared<EditorContext>();
|
||||
m_editorContext->SetProjectPath(exeDir);
|
||||
@@ -136,7 +80,7 @@ bool Application::Initialize(HWND hwnd) {
|
||||
});
|
||||
m_imguiSession.Initialize(m_editorContext->GetProjectPath());
|
||||
|
||||
m_imguiBackend.Initialize(hwnd, m_device, m_srvHeap);
|
||||
m_imguiBackend.Initialize(hwnd, m_windowRenderer.GetDevice(), m_windowRenderer.GetSrvHeap());
|
||||
|
||||
m_editorLayer = new EditorLayer();
|
||||
m_editorLayer->SetContext(m_editorContext);
|
||||
@@ -156,17 +100,7 @@ void Application::Shutdown() {
|
||||
|
||||
m_imguiBackend.Shutdown();
|
||||
m_imguiSession.Shutdown();
|
||||
|
||||
CleanupRenderTarget();
|
||||
|
||||
if (m_fence) m_fence->Release();
|
||||
if (m_commandList) m_commandList->Release();
|
||||
if (m_commandAllocator) m_commandAllocator->Release();
|
||||
if (m_commandQueue) m_commandQueue->Release();
|
||||
if (m_rtvHeap) m_rtvHeap->Release();
|
||||
if (m_srvHeap) m_srvHeap->Release();
|
||||
if (m_swapChain) m_swapChain->Release();
|
||||
if (m_device) m_device->Release();
|
||||
m_windowRenderer.Shutdown();
|
||||
}
|
||||
|
||||
void Application::Render() {
|
||||
@@ -176,46 +110,9 @@ void Application::Render() {
|
||||
UpdateWindowTitle();
|
||||
|
||||
ImGui::Render();
|
||||
|
||||
m_frameIndex = m_swapChain->GetCurrentBackBufferIndex();
|
||||
m_commandAllocator->Reset();
|
||||
m_commandList->Reset(m_commandAllocator, nullptr);
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.pResource = m_renderTargets[m_frameIndex];
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
m_commandList->ResourceBarrier(1, &barrier);
|
||||
|
||||
|
||||
float clearColor[4] = { 0.22f, 0.22f, 0.22f, 1.0f };
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = m_rtvHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
rtvHandle.ptr += m_frameIndex * m_rtvDescriptorSize;
|
||||
m_commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
|
||||
m_commandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr);
|
||||
|
||||
ID3D12DescriptorHeap* heaps[] = { m_srvHeap };
|
||||
m_commandList->SetDescriptorHeaps(1, heaps);
|
||||
|
||||
m_imguiBackend.RenderDrawData(m_commandList);
|
||||
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
|
||||
m_commandList->ResourceBarrier(1, &barrier);
|
||||
|
||||
m_commandList->Close();
|
||||
ID3D12CommandList* cmdLists[] = { m_commandList };
|
||||
m_commandQueue->ExecuteCommandLists(1, cmdLists);
|
||||
|
||||
m_swapChain->Present(1, 0);
|
||||
|
||||
m_fenceValue++;
|
||||
m_commandQueue->Signal(m_fence, m_fenceValue);
|
||||
if (m_fence->GetCompletedValue() < m_fenceValue) {
|
||||
m_fence->SetEventOnCompletion(m_fenceValue, nullptr);
|
||||
}
|
||||
m_windowRenderer.Render(m_imguiBackend, clearColor);
|
||||
}
|
||||
|
||||
void Application::UpdateWindowTitle() {
|
||||
@@ -223,23 +120,7 @@ void Application::UpdateWindowTitle() {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& sceneManager = m_editorContext->GetSceneManager();
|
||||
std::string sceneName = sceneManager.HasActiveScene() ? sceneManager.GetCurrentSceneName() : "No Scene";
|
||||
if (sceneName.empty()) {
|
||||
sceneName = "Untitled Scene";
|
||||
}
|
||||
|
||||
if (sceneManager.IsSceneDirty()) {
|
||||
sceneName += " *";
|
||||
}
|
||||
if (sceneManager.GetCurrentScenePath().empty()) {
|
||||
sceneName += " (Unsaved)";
|
||||
} else {
|
||||
sceneName += " - ";
|
||||
sceneName += std::filesystem::path(sceneManager.GetCurrentScenePath()).filename().string();
|
||||
}
|
||||
|
||||
const std::wstring title = Utf8ToWide(sceneName + " - XCEngine Editor");
|
||||
const std::wstring title = Platform::Utf8ToWide(BuildEditorWindowTitle(*m_editorContext));
|
||||
if (title != m_lastWindowTitle) {
|
||||
SetWindowTextW(m_hwnd, title.c_str());
|
||||
m_lastWindowTitle = title;
|
||||
@@ -247,107 +128,7 @@ void Application::UpdateWindowTitle() {
|
||||
}
|
||||
|
||||
void Application::OnResize(int width, int height) {
|
||||
if (width <= 0 || height <= 0) return;
|
||||
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
|
||||
CleanupRenderTarget();
|
||||
|
||||
if (m_swapChain) {
|
||||
DXGI_SWAP_CHAIN_DESC desc;
|
||||
m_swapChain->GetDesc(&desc);
|
||||
m_swapChain->ResizeBuffers(3, width, height, desc.BufferDesc.Format, desc.Flags);
|
||||
}
|
||||
|
||||
CreateRenderTarget();
|
||||
}
|
||||
|
||||
bool Application::CreateDevice() {
|
||||
HRESULT hr = D3D12CreateDevice(nullptr, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
queueDesc.Priority = 0;
|
||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
queueDesc.NodeMask = 0;
|
||||
hr = m_device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&m_commandQueue));
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
hr = m_device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&m_commandAllocator));
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
hr = m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, m_commandAllocator, nullptr, IID_PPV_ARGS(&m_commandList));
|
||||
if (FAILED(hr)) return false;
|
||||
m_commandList->Close();
|
||||
|
||||
hr = m_device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_fence));
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
IDXGIFactory4* factory = nullptr;
|
||||
hr = CreateDXGIFactory1(IID_PPV_ARGS(&factory));
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
|
||||
swapChainDesc.BufferCount = 3;
|
||||
swapChainDesc.Width = m_width;
|
||||
swapChainDesc.Height = m_height;
|
||||
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
|
||||
IDXGISwapChain1* swapChain1 = nullptr;
|
||||
hr = factory->CreateSwapChainForHwnd(m_commandQueue, m_hwnd, &swapChainDesc, nullptr, nullptr, &swapChain1);
|
||||
factory->Release();
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
hr = swapChain1->QueryInterface(IID_PPV_ARGS(&m_swapChain));
|
||||
swapChain1->Release();
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC rtvDesc = {};
|
||||
rtvDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
rtvDesc.NumDescriptors = 3;
|
||||
rtvDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
hr = m_device->CreateDescriptorHeap(&rtvDesc, IID_PPV_ARGS(&m_rtvHeap));
|
||||
if (FAILED(hr)) return false;
|
||||
m_rtvDescriptorSize = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC srvDesc = {};
|
||||
srvDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
srvDesc.NumDescriptors = 1;
|
||||
srvDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
hr = m_device->CreateDescriptorHeap(&srvDesc, IID_PPV_ARGS(&m_srvHeap));
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Application::CreateRenderTarget() {
|
||||
if (!m_swapChain || !m_device || !m_rtvHeap) return false;
|
||||
|
||||
for (UINT i = 0; i < 3; i++) {
|
||||
HRESULT hr = m_swapChain->GetBuffer(i, IID_PPV_ARGS(&m_renderTargets[i]));
|
||||
if (FAILED(hr)) return false;
|
||||
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = m_rtvHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
rtvHandle.ptr += i * m_rtvDescriptorSize;
|
||||
m_device->CreateRenderTargetView(m_renderTargets[i], nullptr, rtvHandle);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::CleanupRenderTarget() {
|
||||
for (UINT i = 0; i < 3; i++) {
|
||||
if (m_renderTargets[i]) {
|
||||
m_renderTargets[i]->Release();
|
||||
m_renderTargets[i] = nullptr;
|
||||
}
|
||||
}
|
||||
m_windowRenderer.Resize(width, height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user