feat: Implement Custom ImGui Assertion Handler to Enhance Stability

- Added a custom assertion handler for ImGui to log assertion failures instead of crashing the application.
- Implemented a mechanism to back up and reset ImGui workspace settings after multiple assertion failures.
- Updated the window creation process to set the custom assertion handler conditionally based on build configuration.
- Enhanced the welcome screen to truncate project names for better display in the UI.
This commit is contained in:
scawful
2025-10-07 13:43:44 -04:00
parent c4384a6d08
commit 6a439f7255
3 changed files with 53 additions and 2 deletions

View File

@@ -1,15 +1,53 @@
#include "app/core/window.h"
#include <filesystem>
#include "absl/status/status.h"
#include "absl/strings/str_format.h"
#include "app/core/platform/font_loader.h"
#include "util/sdl_deleter.h"
#include "util/log.h"
#include "app/gfx/arena.h"
#include "app/gui/style.h"
#include "imgui/backends/imgui_impl_sdl2.h"
#include "imgui/backends/imgui_impl_sdlrenderer2.h"
#include "imgui/imgui.h"
namespace {
// Custom ImGui assertion handler to prevent crashes
void ImGuiAssertionHandler(const char* expr, const char* file, int line,
const char* msg) {
// Log the assertion instead of crashing
LOG_ERROR("ImGui", "Assertion failed: %s\nFile: %s:%d\nMessage: %s",
expr, file, line, msg ? msg : "");
// Try to recover by resetting ImGui state
static int error_count = 0;
error_count++;
if (error_count > 5) {
LOG_ERROR("ImGui", "Too many assertions, resetting workspace settings...");
// Backup and reset imgui.ini
try {
if (std::filesystem::exists("imgui.ini")) {
std::filesystem::copy("imgui.ini", "imgui.ini.backup",
std::filesystem::copy_options::overwrite_existing);
std::filesystem::remove("imgui.ini");
LOG_INFO("ImGui", "Workspace settings reset. Backup saved to imgui.ini.backup");
}
} catch (const std::exception& e) {
LOG_ERROR("ImGui", "Failed to reset workspace: %s", e.what());
}
error_count = 0; // Reset counter
}
// Don't abort - let the program continue
// The assertion is logged and workspace can be reset if needed
}
} // namespace
namespace yaze {
namespace core {
@@ -41,6 +79,14 @@ absl::Status CreateWindow(Window& window, int flags) {
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
// Set custom assertion handler to prevent crashes
#ifdef IMGUI_DISABLE_DEFAULT_ASSERT_HANDLER
ImGui::SetAssertHandler(ImGuiAssertionHandler);
#else
// For release builds, assertions are already disabled
LOG_INFO("Window", "ImGui assertions are disabled in this build");
#endif
// Initialize ImGuiTestEngine after ImGui context is created
#if defined(YAZE_ENABLE_IMGUI_TEST_ENGINE) && YAZE_ENABLE_IMGUI_TEST_ENGINE

View File

@@ -17,6 +17,7 @@ set(
app/editor/dungeon/dungeon_renderer.cc
app/editor/dungeon/dungeon_room_loader.cc
app/editor/dungeon/dungeon_usage_tracker.cc
app/editor/dungeon/object_editor_card.cc
app/editor/overworld/overworld_editor.cc
app/editor/overworld/scratch_space.cc
app/editor/sprite/sprite_editor.cc

View File

@@ -634,11 +634,15 @@ void WelcomeScreen::DrawProjectCard(const RecentProject& project, int index) {
ImGui::Text(ICON_MD_VIDEOGAME_ASSET);
ImGui::PopStyleColor();
// Project name (compact)
// Project name (compact, shorten if too long)
ImGui::SetCursorScreenPos(ImVec2(content_pos.x + 32, content_pos.y + 8));
ImGui::PushTextWrapPos(cursor_pos.x + card_size.x - 8);
ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[0]); // Default font
ImGui::TextColored(kTriforceGold, "%s", project.name.c_str());
std::string short_name = project.name;
if (short_name.length() > 22) {
short_name = short_name.substr(0, 19) + "...";
}
ImGui::TextColored(kTriforceGold, "%s", short_name.c_str());
ImGui::PopFont();
ImGui::PopTextWrapPos();