From b6bed9e92e6b566bc100b6d395371729ba7d8ec2 Mon Sep 17 00:00:00 2001 From: scawful Date: Fri, 11 Apr 2025 02:56:33 -0400 Subject: [PATCH] Refactor EditorManager and integrate PopupManager for improved popup handling --- src/app/editor/editor_manager.cc | 221 +---------------------- src/app/editor/editor_manager.h | 16 +- src/app/editor/system/popup_manager.cc | 238 ++++++++++++++++++++++++- src/app/editor/system/popup_manager.h | 62 ++++++- 4 files changed, 301 insertions(+), 236 deletions(-) diff --git a/src/app/editor/editor_manager.cc b/src/app/editor/editor_manager.cc index 5c85c310..bae10735 100644 --- a/src/app/editor/editor_manager.cc +++ b/src/app/editor/editor_manager.cc @@ -279,169 +279,6 @@ absl::Status EditorManager::Update() { return absl::OkStatus(); } -void EditorManager::ManageActiveEditors() { - // Show popup pane to select an editor to add - static bool show_add_editor = false; - if (show_add_editor) OpenPopup("AddEditor"); - - if (BeginPopup("AddEditor", ImGuiWindowFlags_AlwaysAutoResize)) { - if (MenuItem("Overworld", nullptr, false, - !IsEditorActive(&overworld_editor_, active_editors_))) { - active_editors_.push_back(&overworld_editor_); - CloseCurrentPopup(); - } - if (MenuItem("Dungeon", nullptr, false, - !IsEditorActive(&dungeon_editor_, active_editors_))) { - active_editors_.push_back(&dungeon_editor_); - CloseCurrentPopup(); - } - if (MenuItem("Graphics", nullptr, false, - !IsEditorActive(&graphics_editor_, active_editors_))) { - active_editors_.push_back(&graphics_editor_); - CloseCurrentPopup(); - } - if (MenuItem("Music", nullptr, false, - !IsEditorActive(&music_editor_, active_editors_))) { - active_editors_.push_back(&music_editor_); - CloseCurrentPopup(); - } - if (MenuItem("Palette", nullptr, false, - !IsEditorActive(&palette_editor_, active_editors_))) { - active_editors_.push_back(&palette_editor_); - CloseCurrentPopup(); - } - if (MenuItem("Screen", nullptr, false, - !IsEditorActive(&screen_editor_, active_editors_))) { - active_editors_.push_back(&screen_editor_); - CloseCurrentPopup(); - } - if (MenuItem("Sprite", nullptr, false, - !IsEditorActive(&sprite_editor_, active_editors_))) { - active_editors_.push_back(&sprite_editor_); - CloseCurrentPopup(); - } - if (MenuItem("Code", nullptr, false, - !IsEditorActive(&assembly_editor_, active_editors_))) { - active_editors_.push_back(&assembly_editor_); - CloseCurrentPopup(); - } - if (MenuItem("Message", nullptr, false, - !IsEditorActive(&message_editor_, active_editors_))) { - active_editors_.push_back(&message_editor_); - CloseCurrentPopup(); - } - if (MenuItem("Settings", nullptr, false, - !IsEditorActive(&settings_editor_, active_editors_))) { - active_editors_.push_back(&settings_editor_); - CloseCurrentPopup(); - } - EndPopup(); - } - - if (!IsPopupOpen("AddEditor")) { - show_add_editor = false; - } - - if (BeginTabBar("##TabBar", ImGuiTabBarFlags_Reorderable | - ImGuiTabBarFlags_AutoSelectNewTabs)) { - for (auto editor : active_editors_) { - bool open = true; - switch (editor->type()) { - case EditorType::kOverworld: - if (overworld_editor_.jump_to_tab() == -1) { - if (BeginTabItem("Overworld", &open)) { - current_editor_ = &overworld_editor_; - status_ = overworld_editor_.Update(); - EndTabItem(); - } - } - break; - case EditorType::kDungeon: - if (BeginTabItem("Dungeon", &open)) { - current_editor_ = &dungeon_editor_; - status_ = dungeon_editor_.Update(); - if (overworld_editor_.jump_to_tab() != -1) { - dungeon_editor_.add_room(overworld_editor_.jump_to_tab()); - overworld_editor_.jump_to_tab_ = -1; - } - EndTabItem(); - } - break; - case EditorType::kGraphics: - if (BeginTabItem("Graphics", &open)) { - current_editor_ = &graphics_editor_; - status_ = graphics_editor_.Update(); - EndTabItem(); - } - break; - case EditorType::kMusic: - if (BeginTabItem("Music", &open)) { - current_editor_ = &music_editor_; - - status_ = music_editor_.Update(); - EndTabItem(); - } - break; - case EditorType::kPalette: - if (BeginTabItem("Palette", &open)) { - current_editor_ = &palette_editor_; - status_ = palette_editor_.Update(); - EndTabItem(); - } - break; - case EditorType::kScreen: - if (BeginTabItem("Screen", &open)) { - current_editor_ = &screen_editor_; - status_ = screen_editor_.Update(); - EndTabItem(); - } - break; - case EditorType::kSprite: - if (BeginTabItem("Sprite", &open)) { - current_editor_ = &sprite_editor_; - status_ = sprite_editor_.Update(); - EndTabItem(); - } - break; - case EditorType::kAssembly: - if (BeginTabItem("Code", &open)) { - current_editor_ = &assembly_editor_; - assembly_editor_.UpdateCodeView(); - EndTabItem(); - } - break; - case EditorType::kSettings: - if (BeginTabItem("Settings", &open)) { - current_editor_ = &settings_editor_; - status_ = settings_editor_.Update(); - EndTabItem(); - } - break; - case EditorType::kMessage: - if (BeginTabItem("Message", &open)) { - current_editor_ = &message_editor_; - status_ = message_editor_.Update(); - EndTabItem(); - } - break; - default: - break; - } - if (!open) { - active_editors_.erase( - std::remove(active_editors_.begin(), active_editors_.end(), editor), - active_editors_.end()); - } - } - - if (TabItemButton(ICON_MD_ADD, ImGuiTabItemFlags_Trailing)) { - show_add_editor = true; - } - - EndTabBar(); - } -} - void EditorManager::DrawHomepage() { TextWrapped("Welcome to the Yet Another Zelda3 Editor (yaze)!"); TextWrapped( @@ -457,61 +294,9 @@ void EditorManager::DrawHomepage() { } void EditorManager::DrawPopups() { - static bool show_status_ = false; - static absl::Status prev_status; - if (!status_.ok()) { - show_status_ = true; - prev_status = status_; - } - - if (show_status_ && (BeginCentered("StatusWindow"))) { - Text("%s", ICON_MD_ERROR); - Text("%s", prev_status.ToString().c_str()); - Spacing(); - NextColumn(); - Columns(1); - Separator(); - NewLine(); - SameLine(128); - if (Button("OK", gui::kDefaultModalSize) || IsKeyPressed(ImGuiKey_Space)) { - show_status_ = false; - status_ = absl::OkStatus(); - } - SameLine(); - if (Button(ICON_MD_CONTENT_COPY, ImVec2(50, 0))) { - SetClipboardText(prev_status.ToString().c_str()); - } - End(); - } - - if (about_) OpenPopup("About"); - if (BeginPopupModal("About", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { - Text("Yet Another Zelda3 Editor - v%s", version_.c_str()); - Text("Written by: scawful"); - Spacing(); - Text("Special Thanks: Zarby89, JaredBrian"); - Separator(); - - if (Button("Close", gui::kDefaultModalSize)) { - about_ = false; - CloseCurrentPopup(); - } - EndPopup(); - } - - if (rom_info_) OpenPopup("ROM Information"); - if (BeginPopupModal("ROM Information", nullptr, - ImGuiWindowFlags_AlwaysAutoResize)) { - Text("Title: %s", rom()->title().c_str()); - Text("ROM Size: %s", util::HexLongLong(rom()->size()).c_str()); - - if (Button("Close", gui::kDefaultModalSize) || - IsKeyPressed(ImGuiKey_Escape)) { - rom_info_ = false; - CloseCurrentPopup(); - } - EndPopup(); - } + // This function is now handled by the PopupManager + // We'll keep it as a placeholder in case we need to add more popup-related + // functionality } void EditorManager::DrawMenuBar() { diff --git a/src/app/editor/editor_manager.h b/src/app/editor/editor_manager.h index f3152ae6..04bf34ce 100644 --- a/src/app/editor/editor_manager.h +++ b/src/app/editor/editor_manager.h @@ -15,6 +15,7 @@ #include "app/editor/music/music_editor.h" #include "app/editor/overworld/overworld_editor.h" #include "app/editor/sprite/sprite_editor.h" +#include "app/editor/system/popup_manager.h" #include "app/editor/system/settings_editor.h" #include "app/emu/emulator.h" #include "app/gui/input.h" @@ -50,6 +51,7 @@ class EditorManager : public SharedRom { ss << YAZE_VERSION_MAJOR << "." << YAZE_VERSION_MINOR << "." << YAZE_VERSION_PATCH; ss >> version_; + context_.popup_manager = popup_manager_.get(); } void Initialize(const std::string &filename = ""); @@ -101,19 +103,7 @@ class EditorManager : public SharedRom { Project current_project_; EditorContext context_; - - Editor *current_editor_ = nullptr; - AssemblyEditor assembly_editor_; - DungeonEditor dungeon_editor_; - GraphicsEditor graphics_editor_; - MusicEditor music_editor_; - OverworldEditor overworld_editor_{*rom()}; - PaletteEditor palette_editor_; - ScreenEditor screen_editor_; - SpriteEditor sprite_editor_; - SettingsEditor settings_editor_; - MessageEditor message_editor_; - MemoryEditorWithDiffChecker memory_editor_; + std::unique_ptr popup_manager_; }; } // namespace editor diff --git a/src/app/editor/system/popup_manager.cc b/src/app/editor/system/popup_manager.cc index b73175b5..841393b1 100644 --- a/src/app/editor/system/popup_manager.cc +++ b/src/app/editor/system/popup_manager.cc @@ -1,13 +1,243 @@ #include "popup_manager.h" +#include "app/editor/editor_manager.h" +#include "app/gui/style.h" +#include "app/gui/icons.h" +#include "util/hex.h" +#include "imgui/misc/cpp/imgui_stdlib.h" + namespace yaze { namespace editor { -PopupManager::PopupManager() { +using namespace ImGui; + +PopupManager::PopupManager(EditorManager* editor_manager) + : editor_manager_(editor_manager), status_(absl::OkStatus()) {} + +void PopupManager::Initialize() { + // Register all popups + popups_["About"] = {"About", false, [this]() { DrawAboutPopup(); }}; + popups_["ROM Information"] = {"ROM Information", false, [this]() { DrawRomInfoPopup(); }}; + popups_["Save As.."] = {"Save As..", false, [this]() { DrawSaveAsPopup(); }}; + popups_["New Project"] = {"New Project", false, [this]() { DrawNewProjectPopup(); }}; + popups_["Supported Features"] = {"Supported Features", false, [this]() { DrawSupportedFeaturesPopup(); }}; + popups_["Open a ROM"] = {"Open a ROM", false, [this]() { DrawOpenRomHelpPopup(); }}; + popups_["Manage Project"] = {"Manage Project", false, [this]() { DrawManageProjectPopup(); }}; } -PopupManager::~PopupManager() { +void PopupManager::DrawPopups() { + // Draw status popup if needed + DrawStatusPopup(); + + // Draw all registered popups + for (auto& [name, params] : popups_) { + if (params.is_visible) { + OpenPopup(name.c_str()); + if (BeginPopupModal(name.c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { + params.draw_function(); + EndPopup(); + } + } + } } -} // namespace editor -} // namespace yaze +void PopupManager::Show(const char* name) { + auto it = popups_.find(name); + if (it != popups_.end()) { + it->second.is_visible = true; + } +} + +void PopupManager::Hide(const char* name) { + auto it = popups_.find(name); + if (it != popups_.end()) { + it->second.is_visible = false; + CloseCurrentPopup(); + } +} + +bool PopupManager::IsVisible(const char* name) const { + auto it = popups_.find(name); + if (it != popups_.end()) { + return it->second.is_visible; + } + return false; +} + +void PopupManager::SetStatus(const absl::Status& status) { + if (!status.ok()) { + show_status_ = true; + prev_status_ = status; + status_ = status; + } +} + +bool PopupManager::BeginCentered(const char* name) { + ImGuiIO const& io = GetIO(); + ImVec2 pos(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f); + SetNextWindowPos(pos, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); + ImGuiWindowFlags flags = + ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | + ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings; + return Begin(name, nullptr, flags); +} + +void PopupManager::DrawStatusPopup() { + if (show_status_ && BeginCentered("StatusWindow")) { + Text("%s", ICON_MD_ERROR); + Text("%s", prev_status_.ToString().c_str()); + Spacing(); + NextColumn(); + Columns(1); + Separator(); + NewLine(); + SameLine(128); + if (Button("OK", gui::kDefaultModalSize) || IsKeyPressed(ImGuiKey_Space)) { + show_status_ = false; + status_ = absl::OkStatus(); + } + SameLine(); + if (Button(ICON_MD_CONTENT_COPY, ImVec2(50, 0))) { + SetClipboardText(prev_status_.ToString().c_str()); + } + End(); + } +} + +void PopupManager::DrawAboutPopup() { + Text("Yet Another Zelda3 Editor - v%s", editor_manager_->version().c_str()); + Text("Written by: scawful"); + Spacing(); + Text("Special Thanks: Zarby89, JaredBrian"); + Separator(); + + if (Button("Close", gui::kDefaultModalSize)) { + Hide("About"); + } +} + +void PopupManager::DrawRomInfoPopup() { + auto* current_rom = editor_manager_->GetCurrentRom(); + if (!current_rom) return; + + Text("Title: %s", current_rom->title().c_str()); + Text("ROM Size: %s", util::HexLongLong(current_rom->size()).c_str()); + + if (Button("Close", gui::kDefaultModalSize) || IsKeyPressed(ImGuiKey_Escape)) { + Hide("ROM Information"); + } +} + +void PopupManager::DrawSaveAsPopup() { + static std::string save_as_filename = ""; + InputText("Filename", &save_as_filename); + if (Button("Save", gui::kDefaultModalSize)) { + // Call the save function from editor manager + // This will need to be implemented in the editor manager + Hide("Save As.."); + } + SameLine(); + if (Button("Cancel", gui::kDefaultModalSize)) { + Hide("Save As.."); + } +} + +void PopupManager::DrawNewProjectPopup() { + static std::string save_as_filename = ""; + InputText("Project Name", &save_as_filename); + + // These would need to be implemented in the editor manager + if (Button("Destination Filepath", gui::kDefaultModalSize)) { + // Call file dialog + } + SameLine(); + Text("%s", "filepath"); // This would be from the editor manager + + if (Button("ROM File", gui::kDefaultModalSize)) { + // Call file dialog + } + SameLine(); + Text("%s", "rom_filename"); // This would be from the editor manager + + if (Button("Labels File", gui::kDefaultModalSize)) { + // Call file dialog + } + SameLine(); + Text("%s", "labels_filename"); // This would be from the editor manager + + if (Button("Code Folder", gui::kDefaultModalSize)) { + // Call file dialog + } + SameLine(); + Text("%s", "code_folder"); // This would be from the editor manager + + Separator(); + if (Button("Create", gui::kDefaultModalSize)) { + // Create project + Hide("New Project"); + } + SameLine(); + if (Button("Cancel", gui::kDefaultModalSize)) { + Hide("New Project"); + } +} + +void PopupManager::DrawSupportedFeaturesPopup() { + Text("Overworld"); + BulletText("LW/DW/SW Tilemap Editing"); + BulletText("LW/DW/SW Map Properties"); + BulletText("Create/Delete/Update Entrances"); + BulletText("Create/Delete/Update Exits"); + BulletText("Create/Delete/Update Sprites"); + BulletText("Create/Delete/Update Items"); + + Text("Dungeon"); + BulletText("View Room Header Properties"); + BulletText("View Entrance Properties"); + + Text("Graphics"); + BulletText("View Decompressed Graphics Sheets"); + BulletText("View/Update Graphics Groups"); + + Text("Palettes"); + BulletText("View Palette Groups"); + + Text("Saveable"); + BulletText("All Listed Overworld Features"); + BulletText("Hex Editor Changes"); + + if (Button("Close", gui::kDefaultModalSize)) { + Hide("Supported Features"); + } +} + +void PopupManager::DrawOpenRomHelpPopup() { + Text("File -> Open"); + Text("Select a ROM file to open"); + Text("Supported ROMs (headered or unheadered):"); + Text("The Legend of Zelda: A Link to the Past"); + Text("US Version 1.0"); + Text("JP Version 1.0"); + + if (Button("Close", gui::kDefaultModalSize)) { + Hide("Open a ROM"); + } +} + +void PopupManager::DrawManageProjectPopup() { + Text("Project Menu"); + Text("Create a new project or open an existing one."); + Text("Save the project to save the current state of the project."); + TextWrapped( + "To save a project, you need to first open a ROM and initialize your " + "code path and labels file. Label resource manager can be found in " + "the View menu. Code path is set in the Code editor after opening a " + "folder."); + + if (Button("Close", gui::kDefaultModalSize)) { + Hide("Manage Project"); + } +} + +} // namespace editor +} // namespace yaze diff --git a/src/app/editor/system/popup_manager.h b/src/app/editor/system/popup_manager.h index 7d37e8f7..b0891d36 100644 --- a/src/app/editor/system/popup_manager.h +++ b/src/app/editor/system/popup_manager.h @@ -1,23 +1,83 @@ #ifndef YAZE_APP_EDITOR_POPUP_MANAGER_H #define YAZE_APP_EDITOR_POPUP_MANAGER_H +#include #include +#include + +#include "absl/status/status.h" namespace yaze { namespace editor { +// Forward declaration +class EditorManager; + struct PopupParams { std::string name; + bool is_visible = false; + std::function draw_function; }; // ImGui popup manager. class PopupManager { public: + PopupManager(EditorManager* editor_manager); + // Initialize popups + void Initialize(); + + // Draw all popups + void DrawPopups(); + + // Show a specific popup void Show(const char* name); + // Hide a specific popup + void Hide(const char* name); + + // Check if a popup is visible + bool IsVisible(const char* name) const; + + // Set the status for status popup + void SetStatus(const absl::Status& status); + + // Get the current status + absl::Status GetStatus() const { return status_; } + private: - std::vector popups_; + // Helper function to begin a centered popup + bool BeginCentered(const char* name); + + // Draw the about popup + void DrawAboutPopup(); + + // Draw the ROM info popup + void DrawRomInfoPopup(); + + // Draw the status popup + void DrawStatusPopup(); + + // Draw the save as popup + void DrawSaveAsPopup(); + + // Draw the new project popup + void DrawNewProjectPopup(); + + // Draw the supported features popup + void DrawSupportedFeaturesPopup(); + + // Draw the open ROM help popup + void DrawOpenRomHelpPopup(); + + // Draw the manage project popup + void DrawManageProjectPopup(); + + EditorManager* editor_manager_; + std::unordered_map popups_; + absl::Status status_; + bool show_status_ = false; + absl::Status prev_status_; }; } // namespace editor