refactor(editor): streamline ImGui card management across various editors
- Refactored multiple editor classes to ensure that ImGui::End() is always called after ImGui::Begin(), enhancing state management and preventing potential rendering issues. - Updated the DungeonEditor, GraphicsEditor, ScreenEditor, MessageEditor, MusicEditor, and SpriteEditor to follow this pattern, improving code consistency and reliability. Benefits: - Improves the stability of the editor UI by ensuring proper handling of ImGui state. - Enhances code readability and maintainability by standardizing the usage of ImGui functions across different editor components.
This commit is contained in:
@@ -443,10 +443,7 @@ void DungeonEditorV2::DrawRoomsListCard() {
|
||||
if (selector_card.Begin()) {
|
||||
if (!rom_ || !rom_->is_loaded()) {
|
||||
ImGui::Text("ROM not loaded");
|
||||
selector_card.End();
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Add text filter
|
||||
static char room_filter[256] = "";
|
||||
ImGui::SetNextItemWidth(-1);
|
||||
@@ -497,6 +494,7 @@ void DungeonEditorV2::DrawRoomsListCard() {
|
||||
ImGui::EndChild();
|
||||
}
|
||||
}
|
||||
}
|
||||
selector_card.End();
|
||||
}
|
||||
|
||||
@@ -510,10 +508,7 @@ void DungeonEditorV2::DrawEntrancesListCard() {
|
||||
if (entrances_card.Begin()) {
|
||||
if (!rom_ || !rom_->is_loaded()) {
|
||||
ImGui::Text("ROM not loaded");
|
||||
entrances_card.End();
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Full entrance configuration UI (matching dungeon_room_selector layout)
|
||||
auto& current_entrance = entrances_[current_entrance_id_];
|
||||
|
||||
@@ -598,6 +593,7 @@ void DungeonEditorV2::DrawEntrancesListCard() {
|
||||
ImGui::EndChild();
|
||||
}
|
||||
}
|
||||
}
|
||||
entrances_card.End();
|
||||
}
|
||||
|
||||
@@ -757,12 +753,8 @@ void DungeonEditorV2::DrawRoomGraphicsCard() {
|
||||
if (graphics_card.Begin()) {
|
||||
if (!rom_ || !rom_->is_loaded()) {
|
||||
ImGui::Text("ROM not loaded");
|
||||
graphics_card.End();
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (current_room_id_ >= 0 && current_room_id_ < static_cast<int>(rooms_.size())) {
|
||||
// Show graphics for current room
|
||||
if (current_room_id_ >= 0 && current_room_id_ < static_cast<int>(rooms_.size())) {
|
||||
auto& room = rooms_[current_room_id_];
|
||||
|
||||
ImGui::Text("Room %03X Graphics", current_room_id_);
|
||||
|
||||
@@ -112,28 +112,29 @@ absl::Status GraphicsEditor::Update() {
|
||||
prototype_card.SetDefaultSize(600, 500);
|
||||
|
||||
// Get visibility flags from card manager and pass to Begin()
|
||||
// Always call End() after Begin() - End() handles ImGui state safely
|
||||
if (sheet_editor_card.Begin(card_manager.GetVisibilityFlag("graphics.sheet_editor"))) {
|
||||
status_ = UpdateGfxEdit();
|
||||
sheet_editor_card.End();
|
||||
}
|
||||
sheet_editor_card.End();
|
||||
|
||||
if (sheet_browser_card.Begin(card_manager.GetVisibilityFlag("graphics.sheet_browser"))) {
|
||||
if (asset_browser_.Initialized == false) {
|
||||
asset_browser_.Initialize(gfx::Arena::Get().gfx_sheets());
|
||||
}
|
||||
asset_browser_.Draw(gfx::Arena::Get().gfx_sheets());
|
||||
sheet_browser_card.End();
|
||||
}
|
||||
sheet_browser_card.End();
|
||||
|
||||
if (player_anims_card.Begin(card_manager.GetVisibilityFlag("graphics.player_animations"))) {
|
||||
status_ = UpdateLinkGfxView();
|
||||
player_anims_card.End();
|
||||
}
|
||||
player_anims_card.End();
|
||||
|
||||
if (prototype_card.Begin(card_manager.GetVisibilityFlag("graphics.prototype_viewer"))) {
|
||||
status_ = UpdateScadView();
|
||||
prototype_card.End();
|
||||
}
|
||||
prototype_card.End();
|
||||
|
||||
CLEAR_AND_RETURN_STATUS(status_)
|
||||
return absl::OkStatus();
|
||||
|
||||
@@ -109,6 +109,7 @@ absl::Status ScreenEditor::Update() {
|
||||
naming_screen_card.SetDefaultSize(500, 400);
|
||||
|
||||
// Get visibility flags from card manager and pass to Begin()
|
||||
// Always call End() after Begin() - End() handles ImGui state safely
|
||||
if (dungeon_maps_card.Begin(card_manager.GetVisibilityFlag("screen.dungeon_maps"))) {
|
||||
DrawDungeonMapsEditor();
|
||||
}
|
||||
@@ -116,7 +117,6 @@ absl::Status ScreenEditor::Update() {
|
||||
|
||||
if (inventory_menu_card.Begin(card_manager.GetVisibilityFlag("screen.inventory_menu"))) {
|
||||
DrawInventoryMenuEditor();
|
||||
|
||||
}
|
||||
inventory_menu_card.End();
|
||||
|
||||
@@ -127,7 +127,6 @@ absl::Status ScreenEditor::Update() {
|
||||
|
||||
if (title_screen_card.Begin(card_manager.GetVisibilityFlag("screen.title_screen"))) {
|
||||
DrawTitleScreenEditor();
|
||||
|
||||
}
|
||||
title_screen_card.End();
|
||||
|
||||
|
||||
@@ -151,8 +151,8 @@ absl::Status MessageEditor::Update() {
|
||||
list_card.SetDefaultSize(400, 600);
|
||||
if (list_card.Begin()) {
|
||||
DrawMessageList();
|
||||
list_card.End();
|
||||
}
|
||||
list_card.End();
|
||||
}
|
||||
|
||||
// Message Editor Card
|
||||
@@ -161,8 +161,8 @@ absl::Status MessageEditor::Update() {
|
||||
editor_card.SetDefaultSize(500, 600);
|
||||
if (editor_card.Begin()) {
|
||||
DrawCurrentMessage();
|
||||
editor_card.End();
|
||||
}
|
||||
editor_card.End();
|
||||
}
|
||||
|
||||
// Font Atlas Card
|
||||
@@ -172,8 +172,8 @@ absl::Status MessageEditor::Update() {
|
||||
if (font_card.Begin()) {
|
||||
DrawFontAtlas();
|
||||
DrawExpandedMessageSettings();
|
||||
font_card.End();
|
||||
}
|
||||
font_card.End();
|
||||
}
|
||||
|
||||
// Dictionary Card
|
||||
@@ -184,8 +184,8 @@ absl::Status MessageEditor::Update() {
|
||||
DrawTextCommands();
|
||||
DrawSpecialCharacters();
|
||||
DrawDictionary();
|
||||
dict_card.End();
|
||||
}
|
||||
dict_card.End();
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
|
||||
@@ -48,20 +48,20 @@ absl::Status MusicEditor::Update() {
|
||||
// Music Tracker Card
|
||||
if (tracker_card.Begin(card_manager.GetVisibilityFlag("music.tracker"))) {
|
||||
DrawTrackerView();
|
||||
tracker_card.End();
|
||||
}
|
||||
tracker_card.End();
|
||||
|
||||
// Instrument Editor Card
|
||||
if (instrument_card.Begin(card_manager.GetVisibilityFlag("music.instrument_editor"))) {
|
||||
DrawInstrumentEditor();
|
||||
instrument_card.End();
|
||||
}
|
||||
instrument_card.End();
|
||||
|
||||
// Assembly View Card
|
||||
if (assembly_card.Begin(card_manager.GetVisibilityFlag("music.assembly"))) {
|
||||
assembly_editor_.InlineUpdate();
|
||||
assembly_card.End();
|
||||
}
|
||||
assembly_card.End();
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
@@ -57,15 +57,16 @@ absl::Status SpriteEditor::Update() {
|
||||
custom_card.SetDefaultSize(800, 600);
|
||||
|
||||
// Get visibility flags from card manager and pass to Begin()
|
||||
// Always call End() after Begin() - End() handles ImGui state safely
|
||||
if (vanilla_card.Begin(card_manager.GetVisibilityFlag("sprite.vanilla_editor"))) {
|
||||
DrawVanillaSpriteEditor();
|
||||
vanilla_card.End();
|
||||
}
|
||||
vanilla_card.End();
|
||||
|
||||
if (custom_card.Begin(card_manager.GetVisibilityFlag("sprite.custom_editor"))) {
|
||||
DrawCustomSprites();
|
||||
custom_card.End();
|
||||
}
|
||||
custom_card.End();
|
||||
|
||||
return status_.ok() ? absl::OkStatus() : status_;
|
||||
}
|
||||
|
||||
@@ -250,12 +250,14 @@ void EditorCard::SetPosition(Position pos) {
|
||||
bool EditorCard::Begin(bool* p_open) {
|
||||
// Check visibility flag first - if provided and false, don't show the card
|
||||
if (p_open && !*p_open) {
|
||||
imgui_begun_ = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle icon-collapsed state
|
||||
if (icon_collapsible_ && collapsed_to_icon_) {
|
||||
DrawFloatingIconButton();
|
||||
imgui_begun_ = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -320,6 +322,9 @@ bool EditorCard::Begin(bool* p_open) {
|
||||
closable_ ? actual_p_open : nullptr,
|
||||
flags);
|
||||
|
||||
// Mark that ImGui::Begin() was called - End() must always be called now
|
||||
imgui_begun_ = true;
|
||||
|
||||
// Register card window for test automation
|
||||
if (ImGui::GetCurrentWindow() && ImGui::GetCurrentWindow()->ID != 0) {
|
||||
std::string card_path = absl::StrFormat("EditorCard:%s", title_.c_str());
|
||||
@@ -332,12 +337,16 @@ bool EditorCard::Begin(bool* p_open) {
|
||||
}
|
||||
|
||||
void EditorCard::End() {
|
||||
// Only call ImGui::End() and pop styles if ImGui::Begin() was called
|
||||
if (imgui_begun_) {
|
||||
// Check if window was focused this frame
|
||||
focused_ = ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows);
|
||||
|
||||
ImGui::End();
|
||||
ImGui::PopStyleColor(2);
|
||||
ImGui::PopStyleVar(2);
|
||||
imgui_begun_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorCard::Focus() {
|
||||
|
||||
@@ -98,9 +98,9 @@ class Toolset {
|
||||
* tile_card.SetPosition(CardPosition::Right);
|
||||
*
|
||||
* if (tile_card.Begin()) {
|
||||
* // Draw tile selector content
|
||||
* tile_card.End();
|
||||
* // Draw tile selector content when visible
|
||||
* }
|
||||
* tile_card.End(); // Always call End() after Begin()
|
||||
* ```
|
||||
*/
|
||||
class EditorCard {
|
||||
@@ -154,6 +154,7 @@ class EditorCard {
|
||||
bool first_draw_ = true;
|
||||
bool focused_ = false;
|
||||
bool* p_open_ = nullptr;
|
||||
bool imgui_begun_ = false; // Track if ImGui::Begin() was called
|
||||
|
||||
// UX enhancements
|
||||
bool headless_ = false; // Minimal chrome, no title bar
|
||||
|
||||
Reference in New Issue
Block a user