Editor: Fix InspectorPanel AddComponent popup crash

- Remove SeparatorText which causes PopStyleVar mismatch in ImGui
- Add stderr redirection for better error capture
- Add debug logging to InspectorPanel
- Fix EditorLayer commented out undefined functions
This commit is contained in:
2026-03-25 12:56:51 +08:00
parent 0834ccb7aa
commit cad6f586fb
6 changed files with 70 additions and 88 deletions

View File

@@ -7,9 +7,28 @@
#include <imgui_impl_dx12.h> #include <imgui_impl_dx12.h>
#include <imgui_internal.h> #include <imgui_internal.h>
#include <stdio.h> #include <stdio.h>
#include <windows.h>
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
static LONG WINAPI GlobalExceptionFilter(EXCEPTION_POINTERS* exceptionPointers) {
const char* logPath = "D:\\Xuanchi\\Main\\XCEngine\\editor\\bin\\Release\\crash.log";
FILE* f = fopen(logPath, "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 XCEngine {
namespace Editor { namespace Editor {
@@ -19,6 +38,31 @@ Application& Application::Get() {
} }
bool Application::Initialize(HWND hwnd) { 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
{
wchar_t exePath[MAX_PATH];
GetModuleFileNameW(nullptr, exePath, MAX_PATH);
std::wstring exeDirW(exePath);
size_t pos = exeDirW.find_last_of(L"\\/");
if (pos != std::wstring::npos) {
exeDirW = exeDirW.substr(0, pos);
}
std::string exeDir;
int len = WideCharToMultiByte(CP_UTF8, 0, exeDirW.c_str(), -1, nullptr, 0, nullptr, nullptr);
if (len > 0) {
exeDir.resize(len - 1);
WideCharToMultiByte(CP_UTF8, 0, exeDirW.c_str(), -1, &exeDir[0], len, nullptr, nullptr);
}
std::string stderrPath = exeDir + "\\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 // Initialize logging first
Debug::Logger::Get().AddSink(std::make_unique<Debug::ConsoleLogSink>()); Debug::Logger::Get().AddSink(std::make_unique<Debug::ConsoleLogSink>());

View File

@@ -10,6 +10,7 @@ namespace Editor {
struct LogEntry { struct LogEntry {
::XCEngine::Debug::LogLevel level; ::XCEngine::Debug::LogLevel level;
std::string message; std::string message;
std::string timestamp;
}; };
} }

View File

@@ -41,15 +41,16 @@ void EditorLayer::onUpdate(float dt) {
void EditorLayer::onEvent(void* event) { void EditorLayer::onEvent(void* event) {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
if (ImGui::IsKeyPressed(ImGuiKey_F5)) { // TODO: These functions don't exist - need to implement them
TogglePlay(); // if (ImGui::IsKeyPressed(ImGuiKey_F5)) {
} // TogglePlay();
// }
if (ImGui::IsKeyPressed(ImGuiKey_F6)) { //
if (GetEditorMode() != EditorMode::Edit) { // if (ImGui::IsKeyPressed(ImGuiKey_F6)) {
TogglePause(); // if (GetEditorMode() != EditorMode::Edit) {
} // TogglePause();
} // }
// }
} }
void EditorLayer::onImGuiRender() { void EditorLayer::onImGuiRender() {

View File

@@ -22,7 +22,9 @@ void ConsolePanel::Render() {
} }
ImGui::SameLine(); ImGui::SameLine();
ImGui::SeparatorText("Filter"); ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Filter:");
ImGui::SameLine();
ImGui::Separator();
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
@@ -117,53 +119,6 @@ void ConsolePanel::Render() {
ImGui::EndChild(); ImGui::EndChild();
ImGui::End(); ImGui::End();
} }
ImGui::SameLine();
if (ImGui::Button("Info")) {
LogSystem::Get().AddLog(::XCEngine::Debug::LogLevel::Info, "Test info message");
}
ImGui::SameLine();
if (ImGui::Button("Warn")) {
LogSystem::Get().AddLog(::XCEngine::Debug::LogLevel::Warning, "Test warning message");
}
ImGui::SameLine();
if (ImGui::Button("Error")) {
LogSystem::Get().AddLog(::XCEngine::Debug::LogLevel::Error, "Test error message");
}
ImGui::Separator();
ImGui::BeginChild("LogScroll", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
for (const auto& log : LogSystem::Get().GetLogs()) {
ImVec4 color;
const char* prefix;
switch (log.level) {
case ::XCEngine::Debug::LogLevel::Info:
color = ImVec4(0.7f, 0.7f, 0.7f, 1.0f);
prefix = "[Info] ";
break;
case ::XCEngine::Debug::LogLevel::Warning:
color = ImVec4(1.0f, 0.8f, 0.0f, 1.0f);
prefix = "[Warn] ";
break;
case ::XCEngine::Debug::LogLevel::Error:
color = ImVec4(1.0f, 0.3f, 0.3f, 1.0f);
prefix = "[Error]";
break;
}
ImGui::TextColored(color, "%s%s", prefix, log.message.c_str());
}
if (m_scrollToBottom) {
ImGui::SetScrollHereY(1.0f);
m_scrollToBottom = false;
}
ImGui::EndChild();
ImGui::End();
}
} }
} }

View File

@@ -5,24 +5,6 @@
#include <XCEngine/Debug/Logger.h> #include <XCEngine/Debug/Logger.h>
#include <imgui.h> #include <imgui.h>
#include <string> #include <string>
#include <windows.h>
#include <excpt.h>
static LONG WINAPI CrashExceptionFilter(EXCEPTION_POINTERS* exceptionPointers) {
char buffer[1024];
std::snprintf(buffer, sizeof(buffer),
"[CRASH] ExceptionCode=0x%08X, Address=0x%p",
exceptionPointers->ExceptionRecord->ExceptionCode,
exceptionPointers->ExceptionRecord->ExceptionAddress);
FILE* f = fopen("D:\\Xuanchi\\Main\\XCEngine\\editor\\bin\\Release\\crash.log", "a");
if (f) {
fprintf(f, "%s\n", buffer);
fclose(f);
}
fprintf(stderr, "%s\n", buffer);
return EXCEPTION_EXECUTE_HANDLER;
}
namespace XCEngine { namespace XCEngine {
namespace Editor { namespace Editor {
@@ -93,9 +75,9 @@ void InspectorPanel::RenderAddComponentPopup(::XCEngine::Components::GameObject*
} }
Debug::Logger::Get().Debug(Debug::LogCategory::General, "BeginPopup succeeded"); Debug::Logger::Get().Debug(Debug::LogCategory::General, "BeginPopup succeeded");
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(12.0f, 10.0f));
ImGui::SeparatorText("Components"); ImGui::Text("Components");
ImGui::Separator();
bool hasTransform = gameObject->GetComponent<::XCEngine::Components::TransformComponent>() != nullptr; bool hasTransform = gameObject->GetComponent<::XCEngine::Components::TransformComponent>() != nullptr;
Debug::Logger::Get().Debug(Debug::LogCategory::General, hasTransform ? "Has Transform: yes" : "Has Transform: no"); Debug::Logger::Get().Debug(Debug::LogCategory::General, hasTransform ? "Has Transform: yes" : "Has Transform: no");
@@ -104,26 +86,19 @@ void InspectorPanel::RenderAddComponentPopup(::XCEngine::Components::GameObject*
if (ImGui::MenuItem("Transform", nullptr, false, !hasTransform)) { if (ImGui::MenuItem("Transform", nullptr, false, !hasTransform)) {
Debug::Logger::Get().Debug(Debug::LogCategory::General, "MenuItem CLICKED! Before AddComponent"); Debug::Logger::Get().Debug(Debug::LogCategory::General, "MenuItem CLICKED! Before AddComponent");
void* newComp = nullptr; auto* newComp = gameObject->AddComponent<::XCEngine::Components::TransformComponent>();
__try { Debug::Logger::Get().Debug(Debug::LogCategory::General, newComp ? "AddComponent SUCCEEDED" : "AddComponent FAILED");
newComp = gameObject->AddComponent<::XCEngine::Components::TransformComponent>();
Debug::Logger::Get().Debug(Debug::LogCategory::General, newComp ? "AddComponent SUCCEEDED" : "AddComponent FAILED");
}
__except(CrashExceptionFilter(GetExceptionInformation())) {
Debug::Logger::Get().Error(Debug::LogCategory::General, "AddComponent CRASHED!");
}
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} else { } else {
Debug::Logger::Get().Debug(Debug::LogCategory::General, "MenuItem not clicked (disabled or condition false)"); Debug::Logger::Get().Debug(Debug::LogCategory::General, "MenuItem not clicked (disabled or condition false)");
} }
ImGui::SeparatorText("Other"); ImGui::Separator();
ImGui::TextDisabled("No more components available"); ImGui::TextDisabled("No more components available");
Debug::Logger::Get().Debug(Debug::LogCategory::General, "About to EndPopup"); Debug::Logger::Get().Debug(Debug::LogCategory::General, "About to EndPopup - calling EndPopup");
ImGui::EndPopup(); ImGui::EndPopup();
ImGui::PopStyleVar();
Debug::Logger::Get().Debug(Debug::LogCategory::General, "Popup closed"); Debug::Logger::Get().Debug(Debug::LogCategory::General, "Popup closed");
} }

View File

@@ -111,6 +111,8 @@ add_library(XCEngine STATIC
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12Screenshot.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12Screenshot.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12ResourceView.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12ResourceView.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12QueryHeap.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12QueryHeap.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12RenderPass.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/D3D12/D3D12Framebuffer.h
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12Device.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12Device.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12CommandQueue.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12CommandQueue.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12CommandAllocator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12CommandAllocator.cpp
@@ -129,6 +131,8 @@ add_library(XCEngine STATIC
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12Screenshot.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12Screenshot.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12ResourceView.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12ResourceView.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12QueryHeap.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12QueryHeap.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12RenderPass.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/D3D12/D3D12Framebuffer.cpp
# OpenGL RHI # OpenGL RHI
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLBuffer.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLBuffer.h
@@ -147,6 +151,7 @@ add_library(XCEngine STATIC
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLTextureUnitAllocator.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLTextureUnitAllocator.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLUniformBufferManager.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLUniformBufferManager.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLFramebuffer.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLFramebuffer.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLRenderPass.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLResourceView.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLResourceView.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLDescriptorPool.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLDescriptorPool.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h ${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/RHI/OpenGL/OpenGLDescriptorSet.h
@@ -167,6 +172,7 @@ add_library(XCEngine STATIC
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLTextureUnitAllocator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLTextureUnitAllocator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLUniformBufferManager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLUniformBufferManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLFramebuffer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLFramebuffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLRenderPass.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLResourceView.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLResourceView.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLDescriptorPool.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLDescriptorPool.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLDescriptorSet.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/RHI/OpenGL/OpenGLDescriptorSet.cpp