#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 #include #include #include #include namespace { std::string GetExecutableLogPath(const char* fileName) { return XCEngine::Editor::Platform::GetExecutableDirectoryUtf8() + "\\" + fileName; } } // namespace static LONG WINAPI GlobalExceptionFilter(EXCEPTION_POINTERS* exceptionPointers) { const std::string logPath = GetExecutableLogPath("crash.log"); FILE* f = nullptr; fopen_s(&f, logPath.c_str(), "a"); if (f) { fprintf(f, "[CRASH] ExceptionCode=0x%08X, Address=0x%p\n", exceptionPointers->ExceptionRecord->ExceptionCode, exceptionPointers->ExceptionRecord->ExceptionAddress); fclose(f); } fprintf(stderr, "[CRASH] ExceptionCode=0x%08X, Address=0x%p\n", exceptionPointers->ExceptionRecord->ExceptionCode, exceptionPointers->ExceptionRecord->ExceptionAddress); return EXCEPTION_EXECUTE_HANDLER; } namespace XCEngine { namespace Editor { Application& Application::Get() { static Application instance; return instance; } bool Application::Initialize(HWND hwnd) { SetUnhandledExceptionFilter(GlobalExceptionFilter); { const std::string stderrPath = GetExecutableLogPath("stderr.log"); freopen(stderrPath.c_str(), "w", stderr); } Debug::Logger::Get().AddSink(std::make_unique()); Debug::Logger::Get().AddSink(std::make_unique()); const std::string exeDir = Platform::GetExecutableDirectoryUtf8(); std::string logPath = exeDir + "\\editor.log"; Debug::Logger::Get().AddSink(std::make_unique(logPath.c_str())); Debug::Logger::Get().Info(Debug::LogCategory::General, "Editor Application starting..."); Debug::Logger::Get().Info(Debug::LogCategory::General, ("Log file: " + logPath).c_str()); m_hwnd = hwnd; if (!m_windowRenderer.Initialize(hwnd, 1280, 720)) { MessageBoxW(hwnd, L"Failed to create D3D12 device", L"Error", MB_OK | MB_ICONERROR); return false; } m_editorContext = std::make_shared(); m_editorContext->SetProjectPath(exeDir); m_exitRequestedHandlerId = m_editorContext->GetEventBus().Subscribe( [this](const EditorExitRequestedEvent&) { if (m_hwnd) { PostMessageW(m_hwnd, WM_CLOSE, 0, 0); } }); m_imguiSession.Initialize(m_editorContext->GetProjectPath()); m_imguiBackend.Initialize(hwnd, m_windowRenderer.GetDevice(), m_windowRenderer.GetSrvHeap()); m_editorLayer = new EditorLayer(); m_editorLayer->SetContext(m_editorContext); m_layerStack.pushLayer(std::unique_ptr(m_editorLayer)); m_layerStack.onAttach(); return true; } void Application::Shutdown() { m_layerStack.onDetach(); if (m_editorContext && m_exitRequestedHandlerId) { m_editorContext->GetEventBus().Unsubscribe(m_exitRequestedHandlerId); m_exitRequestedHandlerId = 0; } m_imguiBackend.Shutdown(); m_imguiSession.Shutdown(); m_windowRenderer.Shutdown(); } void Application::Render() { m_imguiBackend.BeginFrame(); m_layerStack.onImGuiRender(); UpdateWindowTitle(); ImGui::Render(); float clearColor[4] = { 0.22f, 0.22f, 0.22f, 1.0f }; m_windowRenderer.Render(m_imguiBackend, clearColor); } void Application::UpdateWindowTitle() { if (!m_hwnd || !m_editorContext) { return; } const std::wstring title = Platform::Utf8ToWide(BuildEditorWindowTitle(*m_editorContext)); if (title != m_lastWindowTitle) { SetWindowTextW(m_hwnd, title.c_str()); m_lastWindowTitle = title; } } void Application::OnResize(int width, int height) { m_windowRenderer.Resize(width, height); } } }