2026-03-20 17:08:06 +08:00
|
|
|
#include "Application.h"
|
2026-03-26 23:52:05 +08:00
|
|
|
#include "Core/EditorWindowTitle.h"
|
2026-03-25 01:23:08 +08:00
|
|
|
#include "Layers/EditorLayer.h"
|
2026-03-25 16:20:21 +08:00
|
|
|
#include "Core/EditorContext.h"
|
2026-03-25 16:13:02 +08:00
|
|
|
#include "Core/EditorConsoleSink.h"
|
2026-03-26 21:18:33 +08:00
|
|
|
#include "Core/EditorEvents.h"
|
|
|
|
|
#include "Core/EventBus.h"
|
2026-03-26 23:52:05 +08:00
|
|
|
#include "Platform/Win32Utf8.h"
|
2026-03-25 12:30:05 +08:00
|
|
|
#include <XCEngine/Debug/Logger.h>
|
|
|
|
|
#include <XCEngine/Debug/FileLogSink.h>
|
|
|
|
|
#include <XCEngine/Debug/ConsoleLogSink.h>
|
2026-03-20 17:08:06 +08:00
|
|
|
#include <stdio.h>
|
2026-03-25 12:56:51 +08:00
|
|
|
#include <windows.h>
|
2026-03-20 17:08:06 +08:00
|
|
|
|
2026-03-26 01:26:26 +08:00
|
|
|
namespace {
|
|
|
|
|
std::string GetExecutableLogPath(const char* fileName) {
|
2026-03-26 23:52:05 +08:00
|
|
|
return XCEngine::Editor::Platform::GetExecutableDirectoryUtf8() + "\\" + fileName;
|
2026-03-26 01:26:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
2026-03-25 12:56:51 +08:00
|
|
|
static LONG WINAPI GlobalExceptionFilter(EXCEPTION_POINTERS* exceptionPointers) {
|
2026-03-26 01:26:26 +08:00
|
|
|
const std::string logPath = GetExecutableLogPath("crash.log");
|
|
|
|
|
|
|
|
|
|
FILE* f = nullptr;
|
|
|
|
|
fopen_s(&f, logPath.c_str(), "a");
|
2026-03-25 12:56:51 +08:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-24 20:02:38 +08:00
|
|
|
namespace XCEngine {
|
|
|
|
|
namespace Editor {
|
2026-03-20 17:08:06 +08:00
|
|
|
|
|
|
|
|
Application& Application::Get() {
|
|
|
|
|
static Application instance;
|
|
|
|
|
return instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Application::Initialize(HWND hwnd) {
|
2026-03-25 12:56:51 +08:00
|
|
|
SetUnhandledExceptionFilter(GlobalExceptionFilter);
|
2026-03-26 23:52:05 +08:00
|
|
|
|
2026-03-25 12:56:51 +08:00
|
|
|
{
|
2026-03-26 01:26:26 +08:00
|
|
|
const std::string stderrPath = GetExecutableLogPath("stderr.log");
|
2026-03-25 12:56:51 +08:00
|
|
|
freopen(stderrPath.c_str(), "w", stderr);
|
|
|
|
|
}
|
2026-03-26 23:52:05 +08:00
|
|
|
|
2026-03-25 12:30:05 +08:00
|
|
|
Debug::Logger::Get().AddSink(std::make_unique<Debug::ConsoleLogSink>());
|
2026-03-25 16:13:02 +08:00
|
|
|
Debug::Logger::Get().AddSink(std::make_unique<Debug::EditorConsoleSink>());
|
2026-03-26 23:52:05 +08:00
|
|
|
|
|
|
|
|
const std::string exeDir = Platform::GetExecutableDirectoryUtf8();
|
2026-03-25 12:30:05 +08:00
|
|
|
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...");
|
|
|
|
|
Debug::Logger::Get().Info(Debug::LogCategory::General, ("Log file: " + logPath).c_str());
|
|
|
|
|
|
2026-03-20 17:08:06 +08:00
|
|
|
m_hwnd = hwnd;
|
|
|
|
|
|
2026-03-26 23:52:05 +08:00
|
|
|
if (!m_windowRenderer.Initialize(hwnd, 1280, 720)) {
|
2026-03-20 17:08:06 +08:00
|
|
|
MessageBoxW(hwnd, L"Failed to create D3D12 device", L"Error", MB_OK | MB_ICONERROR);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-26 21:18:33 +08:00
|
|
|
m_editorContext = std::make_shared<EditorContext>();
|
|
|
|
|
m_editorContext->SetProjectPath(exeDir);
|
|
|
|
|
m_exitRequestedHandlerId = m_editorContext->GetEventBus().Subscribe<EditorExitRequestedEvent>(
|
|
|
|
|
[this](const EditorExitRequestedEvent&) {
|
|
|
|
|
if (m_hwnd) {
|
|
|
|
|
PostMessageW(m_hwnd, WM_CLOSE, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
});
|
2026-03-26 22:10:43 +08:00
|
|
|
m_imguiSession.Initialize(m_editorContext->GetProjectPath());
|
2026-03-26 21:18:33 +08:00
|
|
|
|
2026-03-26 23:52:05 +08:00
|
|
|
m_imguiBackend.Initialize(hwnd, m_windowRenderer.GetDevice(), m_windowRenderer.GetSrvHeap());
|
2026-03-20 17:08:06 +08:00
|
|
|
|
2026-03-25 01:23:08 +08:00
|
|
|
m_editorLayer = new EditorLayer();
|
2026-03-25 15:35:00 +08:00
|
|
|
m_editorLayer->SetContext(m_editorContext);
|
2026-03-25 01:23:08 +08:00
|
|
|
m_layerStack.pushLayer(std::unique_ptr<Core::Layer>(m_editorLayer));
|
|
|
|
|
m_layerStack.onAttach();
|
2026-03-20 17:08:06 +08:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Application::Shutdown() {
|
2026-03-25 01:23:08 +08:00
|
|
|
m_layerStack.onDetach();
|
2026-03-26 21:18:33 +08:00
|
|
|
|
|
|
|
|
if (m_editorContext && m_exitRequestedHandlerId) {
|
|
|
|
|
m_editorContext->GetEventBus().Unsubscribe<EditorExitRequestedEvent>(m_exitRequestedHandlerId);
|
|
|
|
|
m_exitRequestedHandlerId = 0;
|
|
|
|
|
}
|
2026-03-25 01:23:08 +08:00
|
|
|
|
2026-03-26 22:10:43 +08:00
|
|
|
m_imguiBackend.Shutdown();
|
|
|
|
|
m_imguiSession.Shutdown();
|
2026-03-26 23:52:05 +08:00
|
|
|
m_windowRenderer.Shutdown();
|
2026-03-20 17:08:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Application::Render() {
|
2026-03-26 22:10:43 +08:00
|
|
|
m_imguiBackend.BeginFrame();
|
2026-03-20 17:08:06 +08:00
|
|
|
|
2026-03-25 01:23:08 +08:00
|
|
|
m_layerStack.onImGuiRender();
|
2026-03-26 01:26:26 +08:00
|
|
|
UpdateWindowTitle();
|
2026-03-20 17:08:06 +08:00
|
|
|
|
|
|
|
|
ImGui::Render();
|
2026-03-26 23:52:05 +08:00
|
|
|
|
2026-03-26 21:18:33 +08:00
|
|
|
float clearColor[4] = { 0.22f, 0.22f, 0.22f, 1.0f };
|
2026-03-26 23:52:05 +08:00
|
|
|
m_windowRenderer.Render(m_imguiBackend, clearColor);
|
2026-03-20 17:08:06 +08:00
|
|
|
}
|
|
|
|
|
|
2026-03-26 01:26:26 +08:00
|
|
|
void Application::UpdateWindowTitle() {
|
|
|
|
|
if (!m_hwnd || !m_editorContext) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-26 23:52:05 +08:00
|
|
|
const std::wstring title = Platform::Utf8ToWide(BuildEditorWindowTitle(*m_editorContext));
|
2026-03-26 01:26:26 +08:00
|
|
|
if (title != m_lastWindowTitle) {
|
|
|
|
|
SetWindowTextW(m_hwnd, title.c_str());
|
|
|
|
|
m_lastWindowTitle = title;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-20 17:08:06 +08:00
|
|
|
void Application::OnResize(int width, int height) {
|
2026-03-26 23:52:05 +08:00
|
|
|
m_windowRenderer.Resize(width, height);
|
2026-03-20 17:08:06 +08:00
|
|
|
}
|
|
|
|
|
|
2026-03-24 20:02:38 +08:00
|
|
|
}
|
2026-03-26 01:26:26 +08:00
|
|
|
}
|