editor manager refactor
This commit is contained in:
@@ -9,9 +9,6 @@
|
|||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
#include "app/editor/system/command_manager.h"
|
|
||||||
#include "app/editor/system/extension_manager.h"
|
|
||||||
#include "app/editor/system/history_manager.h"
|
|
||||||
#include "app/editor/system/popup_manager.h"
|
#include "app/editor/system/popup_manager.h"
|
||||||
#include "app/editor/system/shortcut_manager.h"
|
#include "app/editor/system/shortcut_manager.h"
|
||||||
|
|
||||||
@@ -65,36 +62,11 @@ class UserSettings;
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
struct EditorDependencies {
|
struct EditorDependencies {
|
||||||
Rom* rom = nullptr;
|
|
||||||
EditorCardRegistry* card_registry = nullptr;
|
|
||||||
ToastManager* toast_manager = nullptr;
|
|
||||||
PopupManager* popup_manager = nullptr;
|
|
||||||
ShortcutManager* shortcut_manager = nullptr;
|
|
||||||
UserSettings* user_settings = nullptr;
|
|
||||||
size_t session_id = 0;
|
|
||||||
|
|
||||||
gfx::IRenderer* renderer = nullptr;
|
|
||||||
void* custom_data = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct EditorContext {
|
|
||||||
CommandManager command_manager;
|
|
||||||
ExtensionManager extension_manager;
|
|
||||||
HistoryManager history_manager;
|
|
||||||
PopupManager* popup_manager = nullptr;
|
|
||||||
ShortcutManager shortcut_manager;
|
|
||||||
|
|
||||||
// Session identification for multi-session support
|
|
||||||
// Used by child panels to create unique ImGui IDs
|
|
||||||
size_t session_id = 0;
|
|
||||||
|
|
||||||
// Cross-session shared clipboard for editor data transfers
|
|
||||||
struct SharedClipboard {
|
struct SharedClipboard {
|
||||||
// Overworld tile16 selection payload
|
|
||||||
bool has_overworld_tile16 = false;
|
bool has_overworld_tile16 = false;
|
||||||
std::vector<int> overworld_tile16_ids;
|
std::vector<int> overworld_tile16_ids;
|
||||||
int overworld_width = 0; // in tile16 units
|
int overworld_width = 0;
|
||||||
int overworld_height = 0; // in tile16 units
|
int overworld_height = 0;
|
||||||
|
|
||||||
void Clear() {
|
void Clear() {
|
||||||
has_overworld_tile16 = false;
|
has_overworld_tile16 = false;
|
||||||
@@ -102,7 +74,20 @@ struct EditorContext {
|
|||||||
overworld_width = 0;
|
overworld_width = 0;
|
||||||
overworld_height = 0;
|
overworld_height = 0;
|
||||||
}
|
}
|
||||||
} shared_clipboard;
|
};
|
||||||
|
|
||||||
|
Rom* rom = nullptr;
|
||||||
|
EditorCardRegistry* card_registry = nullptr;
|
||||||
|
ToastManager* toast_manager = nullptr;
|
||||||
|
PopupManager* popup_manager = nullptr;
|
||||||
|
ShortcutManager* shortcut_manager = nullptr;
|
||||||
|
SharedClipboard* shared_clipboard = nullptr;
|
||||||
|
UserSettings* user_settings = nullptr;
|
||||||
|
size_t session_id = 0;
|
||||||
|
|
||||||
|
gfx::IRenderer* renderer = nullptr;
|
||||||
|
|
||||||
|
void* custom_data = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class EditorType {
|
enum class EditorType {
|
||||||
@@ -139,6 +124,8 @@ class Editor {
|
|||||||
Editor() = default;
|
Editor() = default;
|
||||||
virtual ~Editor() = default;
|
virtual ~Editor() = default;
|
||||||
|
|
||||||
|
void SetDependencies(const EditorDependencies& deps) { dependencies_ = deps; }
|
||||||
|
|
||||||
// Initialization of the editor, no ROM assets.
|
// Initialization of the editor, no ROM assets.
|
||||||
virtual void Initialize() = 0;
|
virtual void Initialize() = 0;
|
||||||
|
|
||||||
@@ -164,8 +151,6 @@ class Editor {
|
|||||||
|
|
||||||
EditorType type() const { return type_; }
|
EditorType type() const { return type_; }
|
||||||
|
|
||||||
void set_context(EditorContext* context) { context_ = context; }
|
|
||||||
|
|
||||||
bool* active() { return &active_; }
|
bool* active() { return &active_; }
|
||||||
void set_active(bool active) { active_ = active; }
|
void set_active(bool active) { active_ = active; }
|
||||||
void toggle_active() { active_ = !active_; }
|
void toggle_active() { active_ = !active_; }
|
||||||
@@ -177,20 +162,20 @@ class Editor {
|
|||||||
protected:
|
protected:
|
||||||
bool active_ = false;
|
bool active_ = false;
|
||||||
EditorType type_;
|
EditorType type_;
|
||||||
EditorContext* context_ = nullptr;
|
EditorDependencies dependencies_;
|
||||||
|
|
||||||
// Helper method to create session-aware card titles for multi-session support
|
// Helper method to create session-aware card titles for multi-session support
|
||||||
std::string MakeCardTitle(const std::string& base_title) const {
|
std::string MakeCardTitle(const std::string& base_title) const {
|
||||||
if (context_ && context_->session_id > 0) {
|
if (dependencies_.session_id > 0) {
|
||||||
return absl::StrFormat("%s [S%zu]", base_title, context_->session_id);
|
return absl::StrFormat("%s [S%zu]", base_title, dependencies_.session_id);
|
||||||
}
|
}
|
||||||
return base_title;
|
return base_title;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper method to create session-aware card IDs for multi-session support
|
// Helper method to create session-aware card IDs for multi-session support
|
||||||
std::string MakeCardId(const std::string& base_id) const {
|
std::string MakeCardId(const std::string& base_id) const {
|
||||||
if (context_ && context_->session_id > 0) {
|
if (dependencies_.session_id > 0) {
|
||||||
return absl::StrFormat("s%zu.%s", context_->session_id, base_id);
|
return absl::StrFormat("s%zu.%s", dependencies_.session_id, base_id);
|
||||||
}
|
}
|
||||||
return base_id;
|
return base_id;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ set(
|
|||||||
app/editor/system/session_coordinator.cc
|
app/editor/system/session_coordinator.cc
|
||||||
app/editor/system/user_settings.cc
|
app/editor/system/user_settings.cc
|
||||||
app/editor/system/window_delegate.cc
|
app/editor/system/window_delegate.cc
|
||||||
|
app/editor/system/shortcut_configurator.cc
|
||||||
app/editor/ui/editor_selection_dialog.cc
|
app/editor/ui/editor_selection_dialog.cc
|
||||||
app/editor/ui/menu_builder.cc
|
app/editor/ui/menu_builder.cc
|
||||||
app/editor/ui/ui_coordinator.cc
|
app/editor/ui/ui_coordinator.cc
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3,54 +3,55 @@
|
|||||||
|
|
||||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||||
|
|
||||||
|
#include "app/editor/editor.h"
|
||||||
#include "app/editor/system/user_settings.h"
|
#include "app/editor/system/user_settings.h"
|
||||||
#include "app/editor/ui/workspace_manager.h"
|
#include "app/editor/ui/workspace_manager.h"
|
||||||
|
|
||||||
#include "imgui/imgui.h"
|
#include "imgui/imgui.h"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
#include "app/core/features.h"
|
#include "app/core/features.h"
|
||||||
#include "app/core/project.h"
|
#include "app/core/project.h"
|
||||||
|
#include "app/editor/agent/agent_chat_history_popup.h"
|
||||||
#include "app/editor/code/assembly_editor.h"
|
#include "app/editor/code/assembly_editor.h"
|
||||||
#include "app/editor/code/memory_editor.h"
|
#include "app/editor/code/memory_editor.h"
|
||||||
#include "app/editor/ui/menu_builder.h"
|
|
||||||
#include "app/editor/code/project_file_editor.h"
|
#include "app/editor/code/project_file_editor.h"
|
||||||
#include "app/editor/dungeon/dungeon_editor_v2.h"
|
#include "app/editor/dungeon/dungeon_editor_v2.h"
|
||||||
#include "app/editor/graphics/graphics_editor.h"
|
#include "app/editor/graphics/graphics_editor.h"
|
||||||
#include "app/editor/palette/palette_editor.h"
|
|
||||||
#include "app/editor/graphics/screen_editor.h"
|
#include "app/editor/graphics/screen_editor.h"
|
||||||
#include "app/editor/message/message_editor.h"
|
#include "app/editor/message/message_editor.h"
|
||||||
#include "app/editor/music/music_editor.h"
|
#include "app/editor/music/music_editor.h"
|
||||||
#include "app/editor/overworld/overworld_editor.h"
|
#include "app/editor/overworld/overworld_editor.h"
|
||||||
|
#include "app/editor/palette/palette_editor.h"
|
||||||
#include "app/editor/sprite/sprite_editor.h"
|
#include "app/editor/sprite/sprite_editor.h"
|
||||||
#include "app/editor/system/popup_manager.h"
|
#include "app/editor/system/editor_card_registry.h"
|
||||||
#include "app/editor/system/proposal_drawer.h"
|
|
||||||
#include "app/editor/agent/agent_chat_history_popup.h"
|
|
||||||
#ifdef YAZE_WITH_GRPC
|
|
||||||
#include "app/editor/agent/agent_editor.h"
|
|
||||||
#include "app/editor/agent/automation_bridge.h"
|
|
||||||
#endif
|
|
||||||
#include "app/editor/system/settings_editor.h"
|
|
||||||
#include "app/editor/system/toast_manager.h"
|
|
||||||
#include "app/rom.h"
|
|
||||||
#include "app/editor/system/editor_registry.h"
|
#include "app/editor/system/editor_registry.h"
|
||||||
#include "app/editor/system/menu_orchestrator.h"
|
#include "app/editor/system/menu_orchestrator.h"
|
||||||
|
#include "app/editor/system/popup_manager.h"
|
||||||
#include "app/editor/system/project_manager.h"
|
#include "app/editor/system/project_manager.h"
|
||||||
|
#include "app/editor/system/proposal_drawer.h"
|
||||||
#include "app/editor/system/rom_file_manager.h"
|
#include "app/editor/system/rom_file_manager.h"
|
||||||
#include "app/editor/system/editor_card_registry.h"
|
|
||||||
#include "app/editor/system/session_coordinator.h"
|
#include "app/editor/system/session_coordinator.h"
|
||||||
|
#include "app/editor/system/settings_editor.h"
|
||||||
|
#include "app/editor/system/toast_manager.h"
|
||||||
#include "app/editor/system/window_delegate.h"
|
#include "app/editor/system/window_delegate.h"
|
||||||
#include "app/editor/ui/editor_selection_dialog.h"
|
#include "app/editor/ui/editor_selection_dialog.h"
|
||||||
|
#include "app/editor/ui/menu_builder.h"
|
||||||
#include "app/editor/ui/ui_coordinator.h"
|
#include "app/editor/ui/ui_coordinator.h"
|
||||||
#include "app/editor/ui/welcome_screen.h"
|
#include "app/editor/ui/welcome_screen.h"
|
||||||
#include "app/emu/emulator.h"
|
#include "app/emu/emulator.h"
|
||||||
#include "app/gfx/debug/performance/performance_dashboard.h"
|
#include "zelda3/overworld/overworld.h"
|
||||||
|
#include "app/rom.h"
|
||||||
#include "yaze_config.h"
|
#include "yaze_config.h"
|
||||||
|
|
||||||
#ifdef YAZE_WITH_GRPC
|
#ifdef YAZE_WITH_GRPC
|
||||||
|
#include "app/editor/agent/agent_editor.h"
|
||||||
|
#include "app/editor/agent/automation_bridge.h"
|
||||||
|
|
||||||
// Forward declarations for gRPC-dependent types
|
// Forward declarations for gRPC-dependent types
|
||||||
namespace yaze::agent {
|
namespace yaze::agent {
|
||||||
class AgentControlServer;
|
class AgentControlServer;
|
||||||
@@ -66,7 +67,8 @@ namespace editor {
|
|||||||
*/
|
*/
|
||||||
class EditorSet {
|
class EditorSet {
|
||||||
public:
|
public:
|
||||||
explicit EditorSet(Rom* rom = nullptr, UserSettings* user_settings = nullptr, size_t session_id = 0)
|
explicit EditorSet(Rom* rom = nullptr, UserSettings* user_settings = nullptr,
|
||||||
|
size_t session_id = 0)
|
||||||
: session_id_(session_id),
|
: session_id_(session_id),
|
||||||
assembly_editor_(rom),
|
assembly_editor_(rom),
|
||||||
dungeon_editor_(rom),
|
dungeon_editor_(rom),
|
||||||
@@ -89,6 +91,8 @@ class EditorSet {
|
|||||||
settings_editor_.set_user_settings(settings);
|
settings_editor_.set_user_settings(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApplyDependencies(const EditorDependencies& dependencies);
|
||||||
|
|
||||||
size_t session_id() const { return session_id_; }
|
size_t session_id() const { return session_id_; }
|
||||||
|
|
||||||
AssemblyEditor assembly_editor_;
|
AssemblyEditor assembly_editor_;
|
||||||
@@ -130,24 +134,25 @@ class EditorManager {
|
|||||||
|
|
||||||
// Processes startup flags to open a specific editor and cards.
|
// Processes startup flags to open a specific editor and cards.
|
||||||
void OpenEditorAndCardsFromFlags(const std::string& editor_name,
|
void OpenEditorAndCardsFromFlags(const std::string& editor_name,
|
||||||
const std::string& cards_str);
|
const std::string& cards_str);
|
||||||
absl::Status Update();
|
absl::Status Update();
|
||||||
void DrawMenuBar();
|
void DrawMenuBar();
|
||||||
|
|
||||||
auto emulator() -> emu::Emulator& { return emulator_; }
|
auto emulator() -> emu::Emulator& { return emulator_; }
|
||||||
auto quit() const { return quit_; }
|
auto quit() const { return quit_; }
|
||||||
auto version() const { return version_; }
|
auto version() const { return version_; }
|
||||||
void DrawMenuBarExtras();
|
|
||||||
MenuBuilder& menu_builder() { return menu_builder_; }
|
MenuBuilder& menu_builder() { return menu_builder_; }
|
||||||
void ShowSessionSwitcher();
|
|
||||||
void ShowEditorSelection();
|
|
||||||
void ShowDisplaySettings();
|
|
||||||
|
|
||||||
absl::Status SetCurrentRom(Rom* rom);
|
absl::Status SetCurrentRom(Rom* rom);
|
||||||
auto GetCurrentRom() -> Rom* { return current_rom_; }
|
auto GetCurrentRom() -> Rom* { return current_rom_; }
|
||||||
auto GetCurrentEditorSet() -> EditorSet* { return current_editor_set_; }
|
auto GetCurrentEditorSet() -> EditorSet* { return current_editor_set_; }
|
||||||
auto GetCurrentEditor() -> Editor* { return current_editor_; }
|
auto GetCurrentEditor() -> Editor* { return current_editor_; }
|
||||||
auto overworld() -> yaze::zelda3::Overworld* { return ¤t_editor_set_->overworld_editor_.overworld(); }
|
size_t GetCurrentSessionId() const { return current_session_id_; }
|
||||||
|
UICoordinator* ui_coordinator() { return ui_coordinator_.get(); }
|
||||||
|
auto overworld() -> yaze::zelda3::Overworld* {
|
||||||
|
return ¤t_editor_set_->overworld_editor_.overworld();
|
||||||
|
}
|
||||||
|
|
||||||
// Session management helpers
|
// Session management helpers
|
||||||
size_t GetCurrentSessionIndex() const;
|
size_t GetCurrentSessionIndex() const;
|
||||||
@@ -164,19 +169,21 @@ class EditorManager {
|
|||||||
void SetFontGlobalScale(float scale) {
|
void SetFontGlobalScale(float scale) {
|
||||||
user_settings_.prefs().font_global_scale = scale;
|
user_settings_.prefs().font_global_scale = scale;
|
||||||
ImGui::GetIO().FontGlobalScale = scale;
|
ImGui::GetIO().FontGlobalScale = scale;
|
||||||
SaveUserSettings();
|
auto status = user_settings_.Save();
|
||||||
|
if (!status.ok()) {
|
||||||
|
LOG_WARN("EditorManager", "Failed to save user settings: %s",
|
||||||
|
status.ToString().c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildModernMenu();
|
|
||||||
|
|
||||||
// User settings helpers
|
|
||||||
void LoadUserSettings();
|
|
||||||
void SaveUserSettings();
|
|
||||||
|
|
||||||
// Workspace management (delegates to WorkspaceManager)
|
// Workspace management (delegates to WorkspaceManager)
|
||||||
void RefreshWorkspacePresets() { workspace_manager_.RefreshPresets(); }
|
void RefreshWorkspacePresets() { workspace_manager_.RefreshPresets(); }
|
||||||
void SaveWorkspacePreset(const std::string& name) { workspace_manager_.SaveWorkspacePreset(name); }
|
void SaveWorkspacePreset(const std::string& name) {
|
||||||
void LoadWorkspacePreset(const std::string& name) { workspace_manager_.LoadWorkspacePreset(name); }
|
workspace_manager_.SaveWorkspacePreset(name);
|
||||||
|
}
|
||||||
|
void LoadWorkspacePreset(const std::string& name) {
|
||||||
|
workspace_manager_.LoadWorkspacePreset(name);
|
||||||
|
}
|
||||||
|
|
||||||
// Jump-to functionality for cross-editor navigation
|
// Jump-to functionality for cross-editor navigation
|
||||||
void JumpToDungeonRoom(int room_id);
|
void JumpToDungeonRoom(int room_id);
|
||||||
@@ -185,8 +192,6 @@ class EditorManager {
|
|||||||
|
|
||||||
// Card-based editor registry
|
// Card-based editor registry
|
||||||
static bool IsCardBasedEditor(EditorType type);
|
static bool IsCardBasedEditor(EditorType type);
|
||||||
static std::string GetEditorCategory(EditorType type);
|
|
||||||
static EditorType GetEditorTypeFromCategory(const std::string& category);
|
|
||||||
bool IsSidebarVisible() const {
|
bool IsSidebarVisible() const {
|
||||||
return ui_coordinator_ ? ui_coordinator_->IsCardSidebarVisible() : false;
|
return ui_coordinator_ ? ui_coordinator_->IsCardSidebarVisible() : false;
|
||||||
}
|
}
|
||||||
@@ -212,8 +217,14 @@ class EditorManager {
|
|||||||
void SaveWorkspaceLayout() { window_delegate_.SaveWorkspaceLayout(); }
|
void SaveWorkspaceLayout() { window_delegate_.SaveWorkspaceLayout(); }
|
||||||
void LoadWorkspaceLayout() { window_delegate_.LoadWorkspaceLayout(); }
|
void LoadWorkspaceLayout() { window_delegate_.LoadWorkspaceLayout(); }
|
||||||
void ResetWorkspaceLayout() { window_delegate_.ResetWorkspaceLayout(); }
|
void ResetWorkspaceLayout() { window_delegate_.ResetWorkspaceLayout(); }
|
||||||
void ShowAllWindows() { if (ui_coordinator_) ui_coordinator_->ShowAllWindows(); }
|
void ShowAllWindows() {
|
||||||
void HideAllWindows() { if (ui_coordinator_) ui_coordinator_->HideAllWindows(); }
|
if (ui_coordinator_)
|
||||||
|
ui_coordinator_->ShowAllWindows();
|
||||||
|
}
|
||||||
|
void HideAllWindows() {
|
||||||
|
if (ui_coordinator_)
|
||||||
|
ui_coordinator_->HideAllWindows();
|
||||||
|
}
|
||||||
|
|
||||||
// Layout presets (inline delegation)
|
// Layout presets (inline delegation)
|
||||||
void LoadDeveloperLayout() { window_delegate_.LoadDeveloperLayout(); }
|
void LoadDeveloperLayout() { window_delegate_.LoadDeveloperLayout(); }
|
||||||
@@ -221,24 +232,46 @@ class EditorManager {
|
|||||||
void LoadModderLayout() { window_delegate_.LoadModderLayout(); }
|
void LoadModderLayout() { window_delegate_.LoadModderLayout(); }
|
||||||
|
|
||||||
// Helper methods
|
// Helper methods
|
||||||
std::string GenerateUniqueEditorTitle(EditorType type, size_t session_index) const;
|
std::string GenerateUniqueEditorTitle(EditorType type,
|
||||||
|
size_t session_index) const;
|
||||||
bool HasDuplicateSession(const std::string& filepath);
|
bool HasDuplicateSession(const std::string& filepath);
|
||||||
void RenameSession(size_t index, const std::string& new_name);
|
void RenameSession(size_t index, const std::string& new_name);
|
||||||
void Quit() { quit_ = true; }
|
void Quit() { quit_ = true; }
|
||||||
|
|
||||||
// UI visibility controls (public for MenuOrchestrator)
|
// UI visibility controls (public for MenuOrchestrator)
|
||||||
// UI visibility controls - inline for performance (single-line wrappers delegating to UICoordinator)
|
// UI visibility controls - inline for performance (single-line wrappers delegating to UICoordinator)
|
||||||
void ShowGlobalSearch() { if (ui_coordinator_) ui_coordinator_->ShowGlobalSearch(); }
|
void ShowGlobalSearch() {
|
||||||
void ShowCommandPalette() { if (ui_coordinator_) ui_coordinator_->ShowCommandPalette(); }
|
if (ui_coordinator_)
|
||||||
void ShowPerformanceDashboard() { if (ui_coordinator_) ui_coordinator_->SetPerformanceDashboardVisible(true); }
|
ui_coordinator_->ShowGlobalSearch();
|
||||||
void ShowImGuiDemo() { if (ui_coordinator_) ui_coordinator_->SetImGuiDemoVisible(true); }
|
}
|
||||||
void ShowImGuiMetrics() { if (ui_coordinator_) ui_coordinator_->SetImGuiMetricsVisible(true); }
|
void ShowCommandPalette() {
|
||||||
|
if (ui_coordinator_)
|
||||||
|
ui_coordinator_->ShowCommandPalette();
|
||||||
|
}
|
||||||
|
void ShowPerformanceDashboard() {
|
||||||
|
if (ui_coordinator_)
|
||||||
|
ui_coordinator_->SetPerformanceDashboardVisible(true);
|
||||||
|
}
|
||||||
|
void ShowImGuiDemo() {
|
||||||
|
if (ui_coordinator_)
|
||||||
|
ui_coordinator_->SetImGuiDemoVisible(true);
|
||||||
|
}
|
||||||
|
void ShowImGuiMetrics() {
|
||||||
|
if (ui_coordinator_)
|
||||||
|
ui_coordinator_->SetImGuiMetricsVisible(true);
|
||||||
|
}
|
||||||
void ShowHexEditor();
|
void ShowHexEditor();
|
||||||
void ShowEmulator() { show_emulator_ = true; }
|
void ShowEmulator() { show_emulator_ = true; }
|
||||||
void ShowMemoryEditor() { show_memory_editor_ = true; }
|
void ShowMemoryEditor() { show_memory_editor_ = true; }
|
||||||
void ShowResourceLabelManager() { show_resource_label_manager = true; }
|
void ShowResourceLabelManager() { show_resource_label_manager = true; }
|
||||||
void ShowCardBrowser() { if (ui_coordinator_) ui_coordinator_->ShowCardBrowser(); }
|
void ShowCardBrowser() {
|
||||||
void ShowWelcomeScreen() { if (ui_coordinator_) ui_coordinator_->SetWelcomeScreenVisible(true); }
|
if (ui_coordinator_)
|
||||||
|
ui_coordinator_->ShowCardBrowser();
|
||||||
|
}
|
||||||
|
void ShowWelcomeScreen() {
|
||||||
|
if (ui_coordinator_)
|
||||||
|
ui_coordinator_->SetWelcomeScreenVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef YAZE_ENABLE_TESTING
|
#ifdef YAZE_ENABLE_TESTING
|
||||||
void ShowTestDashboard() { show_test_dashboard_ = true; }
|
void ShowTestDashboard() { show_test_dashboard_ = true; }
|
||||||
@@ -255,22 +288,17 @@ class EditorManager {
|
|||||||
absl::Status SaveRom();
|
absl::Status SaveRom();
|
||||||
absl::Status SaveRomAs(const std::string& filename);
|
absl::Status SaveRomAs(const std::string& filename);
|
||||||
absl::Status OpenRomOrProject(const std::string& filename);
|
absl::Status OpenRomOrProject(const std::string& filename);
|
||||||
absl::Status CreateNewProject(const std::string& template_name = "Basic ROM Hack");
|
absl::Status CreateNewProject(
|
||||||
|
const std::string& template_name = "Basic ROM Hack");
|
||||||
absl::Status OpenProject();
|
absl::Status OpenProject();
|
||||||
absl::Status SaveProject();
|
absl::Status SaveProject();
|
||||||
absl::Status SaveProjectAs();
|
absl::Status SaveProjectAs();
|
||||||
absl::Status ImportProject(const std::string& project_path);
|
absl::Status ImportProject(const std::string& project_path);
|
||||||
absl::Status RepairCurrentProject();
|
absl::Status RepairCurrentProject();
|
||||||
void ShowProjectHelp();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DrawWelcomeScreen();
|
|
||||||
absl::Status DrawRomSelector();
|
absl::Status DrawRomSelector();
|
||||||
void DrawContextSensitiveCardControl(); // Card control for current editor
|
void DrawContextSensitiveCardControl(); // Card control for current editor
|
||||||
void DrawSessionSwitcher();
|
|
||||||
void DrawSessionManager();
|
|
||||||
void DrawLayoutPresets();
|
|
||||||
void DrawSessionRenameDialog();
|
|
||||||
|
|
||||||
absl::Status LoadAssets();
|
absl::Status LoadAssets();
|
||||||
|
|
||||||
@@ -336,7 +364,8 @@ class EditorManager {
|
|||||||
core::FeatureFlags::Flags feature_flags; // Per-session feature flags
|
core::FeatureFlags::Flags feature_flags; // Per-session feature flags
|
||||||
|
|
||||||
RomSession() = default;
|
RomSession() = default;
|
||||||
explicit RomSession(Rom&& r, UserSettings* user_settings = nullptr, size_t session_id = 0)
|
explicit RomSession(Rom&& r, UserSettings* user_settings = nullptr,
|
||||||
|
size_t session_id = 0)
|
||||||
: rom(std::move(r)), editors(&rom, user_settings, session_id) {
|
: rom(std::move(r)), editors(&rom, user_settings, session_id) {
|
||||||
filepath = rom.filename();
|
filepath = rom.filename();
|
||||||
// Initialize with default feature flags
|
// Initialize with default feature flags
|
||||||
@@ -353,20 +382,23 @@ class EditorManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::deque<RomSession> sessions_;
|
std::deque<RomSession> sessions_;
|
||||||
Rom* current_rom_ = nullptr;
|
Rom* current_rom_ = nullptr;
|
||||||
EditorSet* current_editor_set_ = nullptr;
|
EditorSet* current_editor_set_ = nullptr;
|
||||||
Editor* current_editor_ = nullptr;
|
Editor* current_editor_ = nullptr;
|
||||||
EditorSet blank_editor_set_{};
|
EditorSet blank_editor_set_{};
|
||||||
|
// Tracks which session is currently active so delegators (menus, popups,
|
||||||
|
// shortcuts) stay in sync without relying on per-editor context.
|
||||||
|
size_t current_session_id_ = 0;
|
||||||
|
|
||||||
gfx::IRenderer* renderer_ = nullptr;
|
gfx::IRenderer* renderer_ = nullptr;
|
||||||
|
|
||||||
core::YazeProject current_project_;
|
core::YazeProject current_project_;
|
||||||
EditorContext context_;
|
EditorDependencies::SharedClipboard shared_clipboard_;
|
||||||
std::unique_ptr<PopupManager> popup_manager_;
|
std::unique_ptr<PopupManager> popup_manager_;
|
||||||
ToastManager toast_manager_;
|
ToastManager toast_manager_;
|
||||||
MenuBuilder menu_builder_;
|
MenuBuilder menu_builder_;
|
||||||
|
ShortcutManager shortcut_manager_;
|
||||||
UserSettings user_settings_;
|
UserSettings user_settings_;
|
||||||
WorkspaceManager workspace_manager_{&toast_manager_};
|
WorkspaceManager workspace_manager_{&toast_manager_};
|
||||||
|
|
||||||
@@ -394,6 +426,9 @@ class EditorManager {
|
|||||||
EditorSet* prev_editor_set_;
|
EditorSet* prev_editor_set_;
|
||||||
size_t prev_session_id_;
|
size_t prev_session_id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ConfigureEditorDependencies(EditorSet* editor_set, Rom* rom,
|
||||||
|
size_t session_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace editor
|
} // namespace editor
|
||||||
|
|||||||
@@ -315,7 +315,9 @@ void MessageEditor::DrawExpandedMessageSettings() {
|
|||||||
expanded_messages_,
|
expanded_messages_,
|
||||||
message_preview_.all_dictionaries_)
|
message_preview_.all_dictionaries_)
|
||||||
.ok()) {
|
.ok()) {
|
||||||
context_->popup_manager->Show("Error");
|
if (auto* popup_manager = dependencies_.popup_manager) {
|
||||||
|
popup_manager->Show("Error");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ class MessageEditor : public Editor {
|
|||||||
type_ = EditorType::kMessage;
|
type_ = EditorType::kMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit MessageEditor(Rom* rom, const EditorDependencies& deps)
|
||||||
|
: MessageEditor(rom) {
|
||||||
|
dependencies_ = deps;
|
||||||
|
}
|
||||||
|
|
||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
absl::Status Load() override;
|
absl::Status Load() override;
|
||||||
absl::Status Update() override;
|
absl::Status Update() override;
|
||||||
|
|||||||
@@ -1032,8 +1032,9 @@ void OverworldEditor::CheckForSelectRectangle() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
absl::Status OverworldEditor::Copy() {
|
absl::Status OverworldEditor::Copy() {
|
||||||
if (!context_)
|
if (!dependencies_.shared_clipboard) {
|
||||||
return absl::FailedPreconditionError("No editor context");
|
return absl::FailedPreconditionError("Clipboard unavailable");
|
||||||
|
}
|
||||||
// If a rectangle selection exists, copy its tile16 IDs into shared clipboard
|
// If a rectangle selection exists, copy its tile16 IDs into shared clipboard
|
||||||
if (ow_map_canvas_.select_rect_active() &&
|
if (ow_map_canvas_.select_rect_active() &&
|
||||||
!ow_map_canvas_.selected_points().empty()) {
|
!ow_map_canvas_.selected_points().empty()) {
|
||||||
@@ -1059,27 +1060,28 @@ absl::Status OverworldEditor::Copy() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context_->shared_clipboard.overworld_tile16_ids = std::move(ids);
|
dependencies_.shared_clipboard->overworld_tile16_ids = std::move(ids);
|
||||||
context_->shared_clipboard.overworld_width = width;
|
dependencies_.shared_clipboard->overworld_width = width;
|
||||||
context_->shared_clipboard.overworld_height = height;
|
dependencies_.shared_clipboard->overworld_height = height;
|
||||||
context_->shared_clipboard.has_overworld_tile16 = true;
|
dependencies_.shared_clipboard->has_overworld_tile16 = true;
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
// Single tile copy fallback
|
// Single tile copy fallback
|
||||||
if (current_tile16_ >= 0) {
|
if (current_tile16_ >= 0) {
|
||||||
context_->shared_clipboard.overworld_tile16_ids = {current_tile16_};
|
dependencies_.shared_clipboard->overworld_tile16_ids = {current_tile16_};
|
||||||
context_->shared_clipboard.overworld_width = 1;
|
dependencies_.shared_clipboard->overworld_width = 1;
|
||||||
context_->shared_clipboard.overworld_height = 1;
|
dependencies_.shared_clipboard->overworld_height = 1;
|
||||||
context_->shared_clipboard.has_overworld_tile16 = true;
|
dependencies_.shared_clipboard->has_overworld_tile16 = true;
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
return absl::FailedPreconditionError("Nothing selected to copy");
|
return absl::FailedPreconditionError("Nothing selected to copy");
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::Status OverworldEditor::Paste() {
|
absl::Status OverworldEditor::Paste() {
|
||||||
if (!context_)
|
if (!dependencies_.shared_clipboard) {
|
||||||
return absl::FailedPreconditionError("No editor context");
|
return absl::FailedPreconditionError("Clipboard unavailable");
|
||||||
if (!context_->shared_clipboard.has_overworld_tile16) {
|
}
|
||||||
|
if (!dependencies_.shared_clipboard->has_overworld_tile16) {
|
||||||
return absl::FailedPreconditionError("Clipboard empty");
|
return absl::FailedPreconditionError("Clipboard empty");
|
||||||
}
|
}
|
||||||
if (ow_map_canvas_.points().empty() &&
|
if (ow_map_canvas_.points().empty() &&
|
||||||
@@ -1105,9 +1107,9 @@ absl::Status OverworldEditor::Paste() {
|
|||||||
const int superX = current_map_ % 8;
|
const int superX = current_map_ % 8;
|
||||||
const int tiles_per_local_map = 512 / kTile16Size;
|
const int tiles_per_local_map = 512 / kTile16Size;
|
||||||
|
|
||||||
const int width = context_->shared_clipboard.overworld_width;
|
const int width = dependencies_.shared_clipboard->overworld_width;
|
||||||
const int height = context_->shared_clipboard.overworld_height;
|
const int height = dependencies_.shared_clipboard->overworld_height;
|
||||||
const auto& ids = context_->shared_clipboard.overworld_tile16_ids;
|
const auto& ids = dependencies_.shared_clipboard->overworld_tile16_ids;
|
||||||
|
|
||||||
// Guard
|
// Guard
|
||||||
if (width * height != static_cast<int>(ids.size())) {
|
if (width * height != static_cast<int>(ids.size())) {
|
||||||
|
|||||||
@@ -69,6 +69,11 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
|
|||||||
// MapPropertiesSystem will be initialized after maps_bmp_ and canvas are ready
|
// MapPropertiesSystem will be initialized after maps_bmp_ and canvas are ready
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit OverworldEditor(Rom* rom, const EditorDependencies& deps)
|
||||||
|
: OverworldEditor(rom) {
|
||||||
|
dependencies_ = deps;
|
||||||
|
}
|
||||||
|
|
||||||
void Initialize(gfx::IRenderer* renderer, Rom* rom);
|
void Initialize(gfx::IRenderer* renderer, Rom* rom);
|
||||||
void Initialize() override;
|
void Initialize() override;
|
||||||
absl::Status Load() override;
|
absl::Status Load() override;
|
||||||
@@ -104,6 +109,8 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
|
|||||||
return absl::StrFormat("ROM loaded: %s", rom_->title());
|
return absl::StrFormat("ROM loaded: %s", rom_->title());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rom* rom() const { return rom_; }
|
||||||
|
|
||||||
// Jump-to functionality
|
// Jump-to functionality
|
||||||
void set_current_map(int map_id) {
|
void set_current_map(int map_id) {
|
||||||
if (map_id >= 0 && map_id < zelda3::kNumOverworldMaps) {
|
if (map_id >= 0 && map_id < zelda3::kNumOverworldMaps) {
|
||||||
|
|||||||
@@ -96,23 +96,24 @@ absl::Status OverworldEditor::DrawScratchSpace() {
|
|||||||
scratch_spaces_[current_scratch_slot_].tile_data[tile_x][tile_y]);
|
scratch_spaces_[current_scratch_slot_].tile_data[tile_x][tile_y]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!scratch_tile_ids.empty() && context_) {
|
if (!scratch_tile_ids.empty() && dependencies_.shared_clipboard) {
|
||||||
const auto& points = scratch_canvas_.selected_points();
|
const auto& points = scratch_canvas_.selected_points();
|
||||||
int width =
|
int width =
|
||||||
std::abs(static_cast<int>((points[1].x - points[0].x) / 32)) + 1;
|
std::abs(static_cast<int>((points[1].x - points[0].x) / 32)) + 1;
|
||||||
int height =
|
int height =
|
||||||
std::abs(static_cast<int>((points[1].y - points[0].y) / 32)) + 1;
|
std::abs(static_cast<int>((points[1].y - points[0].y) / 32)) + 1;
|
||||||
context_->shared_clipboard.overworld_tile16_ids =
|
dependencies_.shared_clipboard->overworld_tile16_ids =
|
||||||
std::move(scratch_tile_ids);
|
std::move(scratch_tile_ids);
|
||||||
context_->shared_clipboard.overworld_width = width;
|
dependencies_.shared_clipboard->overworld_width = width;
|
||||||
context_->shared_clipboard.overworld_height = height;
|
dependencies_.shared_clipboard->overworld_height = height;
|
||||||
context_->shared_clipboard.has_overworld_tile16 = true;
|
dependencies_.shared_clipboard->has_overworld_tile16 = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HOVER_HINT("Copy scratch selection to clipboard for pasting in overworld");
|
HOVER_HINT("Copy scratch selection to clipboard for pasting in overworld");
|
||||||
|
|
||||||
if (context_ && context_->shared_clipboard.has_overworld_tile16) {
|
if (dependencies_.shared_clipboard &&
|
||||||
|
dependencies_.shared_clipboard->has_overworld_tile16) {
|
||||||
Text(ICON_MD_CONTENT_PASTE
|
Text(ICON_MD_CONTENT_PASTE
|
||||||
" Pattern ready! Use Shift+Click to stamp, or paste in overworld");
|
" Pattern ready! Use Shift+Click to stamp, or paste in overworld");
|
||||||
}
|
}
|
||||||
@@ -223,13 +224,15 @@ void OverworldEditor::DrawScratchSpacePattern() {
|
|||||||
int start_tile_y = static_cast<int>(mouse_position.y) / 32;
|
int start_tile_y = static_cast<int>(mouse_position.y) / 32;
|
||||||
|
|
||||||
// Get the selected tiles from overworld via clipboard
|
// Get the selected tiles from overworld via clipboard
|
||||||
if (!context_ || !context_->shared_clipboard.has_overworld_tile16) {
|
if (!dependencies_.shared_clipboard ||
|
||||||
|
!dependencies_.shared_clipboard->has_overworld_tile16) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& tile_ids = context_->shared_clipboard.overworld_tile16_ids;
|
const auto& tile_ids =
|
||||||
int pattern_width = context_->shared_clipboard.overworld_width;
|
dependencies_.shared_clipboard->overworld_tile16_ids;
|
||||||
int pattern_height = context_->shared_clipboard.overworld_height;
|
int pattern_width = dependencies_.shared_clipboard->overworld_width;
|
||||||
|
int pattern_height = dependencies_.shared_clipboard->overworld_height;
|
||||||
|
|
||||||
if (tile_ids.empty())
|
if (tile_ids.empty())
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -549,15 +549,21 @@ void MenuOrchestrator::OnSwitchToEditor(EditorType editor_type) {
|
|||||||
|
|
||||||
void MenuOrchestrator::OnShowEditorSelection() {
|
void MenuOrchestrator::OnShowEditorSelection() {
|
||||||
// Delegate to EditorManager
|
// Delegate to EditorManager
|
||||||
|
// TODO: Draw editor selection via UICoordinator
|
||||||
if (editor_manager_) {
|
if (editor_manager_) {
|
||||||
editor_manager_->ShowEditorSelection();
|
if (auto* ui = editor_manager_->ui_coordinator()) {
|
||||||
|
ui->ShowEditorSelection();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuOrchestrator::OnShowDisplaySettings() {
|
void MenuOrchestrator::OnShowDisplaySettings() {
|
||||||
// Delegate to EditorManager
|
// Delegate to EditorManager
|
||||||
|
// TODO: Draw display settings via UICoordinator
|
||||||
if (editor_manager_) {
|
if (editor_manager_) {
|
||||||
editor_manager_->ShowDisplaySettings();
|
if (auto* ui = editor_manager_->ui_coordinator()) {
|
||||||
|
ui->ShowDisplaySettings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -624,8 +630,11 @@ void MenuOrchestrator::OnSwitchToSession(size_t session_index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MenuOrchestrator::OnShowSessionSwitcher() {
|
void MenuOrchestrator::OnShowSessionSwitcher() {
|
||||||
|
// TODO: Draw session switcher via UICoordinator
|
||||||
if (editor_manager_) {
|
if (editor_manager_) {
|
||||||
editor_manager_->ShowSessionSwitcher();
|
if (auto* ui = editor_manager_->ui_coordinator()) {
|
||||||
|
ui->ShowSessionSwitcher();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -879,7 +888,8 @@ void MenuOrchestrator::OnQuit() {
|
|||||||
|
|
||||||
// Menu item validation helpers
|
// Menu item validation helpers
|
||||||
bool MenuOrchestrator::CanSaveRom() const {
|
bool MenuOrchestrator::CanSaveRom() const {
|
||||||
return rom_manager_.IsRomLoaded();
|
auto* rom = editor_manager_->GetCurrentRom();
|
||||||
|
return rom ? rom_manager_.IsRomLoaded(rom) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MenuOrchestrator::CanSaveProject() const {
|
bool MenuOrchestrator::CanSaveProject() const {
|
||||||
@@ -887,7 +897,8 @@ bool MenuOrchestrator::CanSaveProject() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MenuOrchestrator::HasActiveRom() const {
|
bool MenuOrchestrator::HasActiveRom() const {
|
||||||
return rom_manager_.IsRomLoaded();
|
auto* rom = editor_manager_->GetCurrentRom();
|
||||||
|
return rom ? rom_manager_.IsRomLoaded(rom) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MenuOrchestrator::HasActiveProject() const {
|
bool MenuOrchestrator::HasActiveProject() const {
|
||||||
@@ -904,7 +915,8 @@ bool MenuOrchestrator::HasMultipleSessions() const {
|
|||||||
|
|
||||||
// Menu item text generation
|
// Menu item text generation
|
||||||
std::string MenuOrchestrator::GetRomFilename() const {
|
std::string MenuOrchestrator::GetRomFilename() const {
|
||||||
return rom_manager_.GetRomFilename();
|
auto* rom = editor_manager_->GetCurrentRom();
|
||||||
|
return rom ? rom_manager_.GetRomFilename(rom) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MenuOrchestrator::GetProjectName() const {
|
std::string MenuOrchestrator::GetProjectName() const {
|
||||||
|
|||||||
@@ -2,37 +2,162 @@
|
|||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
#include "app/editor/system/toast_manager.h"
|
#include "app/editor/system/toast_manager.h"
|
||||||
#include "app/rom.h"
|
#include "app/rom.h"
|
||||||
#include "util/file_util.h"
|
#include "util/file_util.h"
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze::editor {
|
||||||
namespace editor {
|
|
||||||
|
|
||||||
RomFileManager::RomFileManager(ToastManager* toast_manager)
|
RomFileManager::RomFileManager(ToastManager* toast_manager)
|
||||||
: toast_manager_(toast_manager) {
|
: toast_manager_(toast_manager) {}
|
||||||
|
|
||||||
|
absl::Status RomFileManager::LoadRom(Rom* rom, const std::string& filename) {
|
||||||
|
if (!rom) {
|
||||||
|
return absl::InvalidArgumentError("ROM pointer cannot be null");
|
||||||
|
}
|
||||||
|
if (filename.empty()) {
|
||||||
|
return absl::InvalidArgumentError("No filename provided");
|
||||||
|
}
|
||||||
|
return LoadRomFromFile(rom, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::Status RomFileManager::LoadRom(const std::string& filename) {
|
absl::Status RomFileManager::SaveRom(Rom* rom) {
|
||||||
|
if (!IsRomLoaded(rom)) {
|
||||||
|
return absl::FailedPreconditionError("No ROM loaded to save");
|
||||||
|
}
|
||||||
|
|
||||||
|
Rom::SaveSettings settings;
|
||||||
|
settings.backup = true;
|
||||||
|
settings.save_new = false;
|
||||||
|
settings.z3_save = true;
|
||||||
|
|
||||||
|
auto status = rom->SaveToFile(settings);
|
||||||
|
if (!status.ok() && toast_manager_) {
|
||||||
|
toast_manager_->Show(
|
||||||
|
absl::StrFormat("Failed to save ROM: %s", status.message()),
|
||||||
|
ToastType::kError);
|
||||||
|
} else if (toast_manager_) {
|
||||||
|
toast_manager_->Show("ROM saved successfully", ToastType::kSuccess);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status RomFileManager::SaveRomAs(Rom* rom, const std::string& filename) {
|
||||||
|
if (!IsRomLoaded(rom)) {
|
||||||
|
return absl::FailedPreconditionError("No ROM loaded to save");
|
||||||
|
}
|
||||||
|
if (filename.empty()) {
|
||||||
|
return absl::InvalidArgumentError(
|
||||||
|
"No filename provided for save as");
|
||||||
|
}
|
||||||
|
|
||||||
|
Rom::SaveSettings settings;
|
||||||
|
settings.backup = false;
|
||||||
|
settings.save_new = true;
|
||||||
|
settings.filename = filename;
|
||||||
|
settings.z3_save = true;
|
||||||
|
|
||||||
|
auto status = rom->SaveToFile(settings);
|
||||||
|
if (!status.ok() && toast_manager_) {
|
||||||
|
toast_manager_->Show(
|
||||||
|
absl::StrFormat("Failed to save ROM as: %s", status.message()),
|
||||||
|
ToastType::kError);
|
||||||
|
} else if (toast_manager_) {
|
||||||
|
toast_manager_->Show(
|
||||||
|
absl::StrFormat("ROM saved as: %s", filename),
|
||||||
|
ToastType::kSuccess);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status RomFileManager::OpenRomOrProject(Rom* rom,
|
||||||
|
const std::string& filename) {
|
||||||
|
if (!rom) {
|
||||||
|
return absl::InvalidArgumentError("ROM pointer cannot be null");
|
||||||
|
}
|
||||||
if (filename.empty()) {
|
if (filename.empty()) {
|
||||||
// TODO: Show file dialog
|
|
||||||
return absl::InvalidArgumentError("No filename provided");
|
return absl::InvalidArgumentError("No filename provided");
|
||||||
}
|
}
|
||||||
|
|
||||||
return LoadRomFromFile(filename);
|
std::string extension =
|
||||||
|
std::filesystem::path(filename).extension().string();
|
||||||
|
|
||||||
|
if (extension == ".yaze" || extension == ".json") {
|
||||||
|
return absl::UnimplementedError(
|
||||||
|
"Project file loading not yet implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
return LoadRom(rom, filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::Status RomFileManager::LoadRomFromFile(const std::string& filename) {
|
absl::Status RomFileManager::CreateBackup(Rom* rom) {
|
||||||
|
if (!IsRomLoaded(rom)) {
|
||||||
|
return absl::FailedPreconditionError("No ROM loaded to backup");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string backup_filename = GenerateBackupFilename(rom->filename());
|
||||||
|
|
||||||
|
Rom::SaveSettings settings;
|
||||||
|
settings.backup = true;
|
||||||
|
settings.filename = backup_filename;
|
||||||
|
settings.z3_save = true;
|
||||||
|
|
||||||
|
auto status = rom->SaveToFile(settings);
|
||||||
|
if (!status.ok() && toast_manager_) {
|
||||||
|
toast_manager_->Show(
|
||||||
|
absl::StrFormat("Failed to create backup: %s", status.message()),
|
||||||
|
ToastType::kError);
|
||||||
|
} else if (toast_manager_) {
|
||||||
|
toast_manager_->Show(
|
||||||
|
absl::StrFormat("Backup created: %s", backup_filename),
|
||||||
|
ToastType::kSuccess);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status RomFileManager::ValidateRom(Rom* rom) {
|
||||||
|
if (!IsRomLoaded(rom)) {
|
||||||
|
return absl::FailedPreconditionError("No valid ROM to validate");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rom->size() < 512 * 1024 || rom->size() > 8 * 1024 * 1024) {
|
||||||
|
return absl::InvalidArgumentError("ROM size is outside expected range");
|
||||||
|
}
|
||||||
|
if (rom->title().empty()) {
|
||||||
|
return absl::InvalidArgumentError("ROM title is empty or invalid");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toast_manager_) {
|
||||||
|
toast_manager_->Show("ROM validation passed", ToastType::kSuccess);
|
||||||
|
}
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RomFileManager::IsRomLoaded(Rom* rom) const {
|
||||||
|
return rom && rom->is_loaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string RomFileManager::GetRomFilename(Rom* rom) const {
|
||||||
|
if (!IsRomLoaded(rom)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return rom->filename();
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status RomFileManager::LoadRomFromFile(
|
||||||
|
Rom* rom, const std::string& filename) {
|
||||||
|
if (!rom) {
|
||||||
|
return absl::InvalidArgumentError("ROM pointer cannot be null");
|
||||||
|
}
|
||||||
if (!IsValidRomFile(filename)) {
|
if (!IsValidRomFile(filename)) {
|
||||||
return absl::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
absl::StrFormat("Invalid ROM file: %s", filename));
|
absl::StrFormat("Invalid ROM file: %s", filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new ROM instance
|
auto status = rom->LoadFromFile(filename);
|
||||||
Rom new_rom;
|
|
||||||
auto status = new_rom.LoadFromFile(filename);
|
|
||||||
if (!status.ok()) {
|
if (!status.ok()) {
|
||||||
if (toast_manager_) {
|
if (toast_manager_) {
|
||||||
toast_manager_->Show(
|
toast_manager_->Show(
|
||||||
@@ -42,200 +167,19 @@ absl::Status RomFileManager::LoadRomFromFile(const std::string& filename) {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set as current ROM
|
|
||||||
current_rom_ = &new_rom;
|
|
||||||
|
|
||||||
if (toast_manager_) {
|
if (toast_manager_) {
|
||||||
toast_manager_->Show(
|
toast_manager_->Show(absl::StrFormat("ROM loaded: %s", rom->title()),
|
||||||
absl::StrFormat("ROM loaded: %s", new_rom.title()),
|
ToastType::kSuccess);
|
||||||
ToastType::kSuccess);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::Status RomFileManager::SaveRom() {
|
std::string RomFileManager::GenerateBackupFilename(
|
||||||
if (!IsRomLoaded()) {
|
const std::string& original_filename) const {
|
||||||
return absl::FailedPreconditionError("No ROM loaded to save");
|
|
||||||
}
|
|
||||||
|
|
||||||
Rom::SaveSettings settings;
|
|
||||||
settings.backup = true;
|
|
||||||
settings.save_new = false;
|
|
||||||
settings.z3_save = true;
|
|
||||||
|
|
||||||
auto status = current_rom_->SaveToFile(settings);
|
|
||||||
if (!status.ok()) {
|
|
||||||
if (toast_manager_) {
|
|
||||||
toast_manager_->Show(
|
|
||||||
absl::StrFormat("Failed to save ROM: %s", status.message()),
|
|
||||||
ToastType::kError);
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toast_manager_) {
|
|
||||||
toast_manager_->Show("ROM saved successfully", ToastType::kSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
return absl::OkStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::Status RomFileManager::SaveRomAs(const std::string& filename) {
|
|
||||||
if (!IsRomLoaded()) {
|
|
||||||
return absl::FailedPreconditionError("No ROM loaded to save");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filename.empty()) {
|
|
||||||
return absl::InvalidArgumentError("No filename provided for save as");
|
|
||||||
}
|
|
||||||
|
|
||||||
Rom::SaveSettings settings;
|
|
||||||
settings.backup = false;
|
|
||||||
settings.save_new = true;
|
|
||||||
settings.filename = filename;
|
|
||||||
settings.z3_save = true;
|
|
||||||
|
|
||||||
auto status = current_rom_->SaveToFile(settings);
|
|
||||||
if (!status.ok()) {
|
|
||||||
if (toast_manager_) {
|
|
||||||
toast_manager_->Show(
|
|
||||||
absl::StrFormat("Failed to save ROM as: %s", status.message()),
|
|
||||||
ToastType::kError);
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toast_manager_) {
|
|
||||||
toast_manager_->Show(
|
|
||||||
absl::StrFormat("ROM saved as: %s", filename),
|
|
||||||
ToastType::kSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
return absl::OkStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::Status RomFileManager::OpenRomOrProject(const std::string& filename) {
|
|
||||||
if (filename.empty()) {
|
|
||||||
return absl::InvalidArgumentError("No filename provided");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if it's a project file or ROM file
|
|
||||||
std::string extension = std::filesystem::path(filename).extension().string();
|
|
||||||
|
|
||||||
if (extension == ".yaze" || extension == ".json") {
|
|
||||||
// TODO: Handle project files
|
|
||||||
return absl::UnimplementedError("Project file loading not yet implemented");
|
|
||||||
} else {
|
|
||||||
// Assume it's a ROM file
|
|
||||||
return LoadRom(filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::Status RomFileManager::LoadAssets() {
|
|
||||||
if (!IsRomLoaded()) {
|
|
||||||
return absl::FailedPreconditionError("No ROM loaded to load assets from");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Implement asset loading logic
|
|
||||||
// This would typically load graphics, music, etc. from the ROM
|
|
||||||
|
|
||||||
if (toast_manager_) {
|
|
||||||
toast_manager_->Show("Assets loaded", ToastType::kInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return absl::OkStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::Status RomFileManager::SetCurrentRom(Rom* rom) {
|
|
||||||
if (!rom) {
|
|
||||||
return absl::InvalidArgumentError("ROM pointer cannot be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
current_rom_ = rom;
|
|
||||||
return absl::OkStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string RomFileManager::GetRomFilename() const {
|
|
||||||
if (!IsRomLoaded()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return current_rom_->filename();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string RomFileManager::GetRomTitle() const {
|
|
||||||
if (!IsRomLoaded()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return current_rom_->title();
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::Status RomFileManager::ValidateRom() {
|
|
||||||
return ValidateRom(current_rom_);
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::Status RomFileManager::ValidateRom(Rom* rom) {
|
|
||||||
if (!rom || !rom->is_loaded()) {
|
|
||||||
return absl::FailedPreconditionError("No valid ROM to validate");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Implement ROM validation logic
|
|
||||||
// This would check ROM integrity, checksums, expected data structures, etc.
|
|
||||||
|
|
||||||
// Basic validation: check if ROM size is reasonable
|
|
||||||
if (rom->size() < 512 * 1024 || rom->size() > 8 * 1024 * 1024) {
|
|
||||||
return absl::InvalidArgumentError("ROM size is outside expected range");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if ROM title is readable
|
|
||||||
if (rom->title().empty()) {
|
|
||||||
return absl::InvalidArgumentError("ROM title is empty or invalid");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toast_manager_) {
|
|
||||||
toast_manager_->Show("ROM validation passed", ToastType::kSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
return absl::OkStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::Status RomFileManager::CreateBackup() {
|
|
||||||
if (!IsRomLoaded()) {
|
|
||||||
return absl::FailedPreconditionError("No ROM loaded to backup");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string backup_filename = GenerateBackupFilename(GetRomFilename());
|
|
||||||
|
|
||||||
Rom::SaveSettings settings;
|
|
||||||
settings.backup = true;
|
|
||||||
settings.filename = backup_filename;
|
|
||||||
settings.z3_save = true;
|
|
||||||
|
|
||||||
auto status = current_rom_->SaveToFile(settings);
|
|
||||||
if (!status.ok()) {
|
|
||||||
if (toast_manager_) {
|
|
||||||
toast_manager_->Show(
|
|
||||||
absl::StrFormat("Failed to create backup: %s", status.message()),
|
|
||||||
ToastType::kError);
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toast_manager_) {
|
|
||||||
toast_manager_->Show(
|
|
||||||
absl::StrFormat("Backup created: %s", backup_filename),
|
|
||||||
ToastType::kSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
return absl::OkStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string RomFileManager::GenerateBackupFilename(const std::string& original_filename) const {
|
|
||||||
std::filesystem::path path(original_filename);
|
std::filesystem::path path(original_filename);
|
||||||
std::string stem = path.stem().string();
|
std::string stem = path.stem().string();
|
||||||
std::string extension = path.extension().string();
|
std::string extension = path.extension().string();
|
||||||
|
|
||||||
// Add timestamp to make it unique
|
|
||||||
auto now = std::chrono::system_clock::now();
|
auto now = std::chrono::system_clock::now();
|
||||||
auto time_t = std::chrono::system_clock::to_time_t(now);
|
auto time_t = std::chrono::system_clock::to_time_t(now);
|
||||||
|
|
||||||
@@ -251,16 +195,12 @@ bool RomFileManager::IsValidRomFile(const std::string& filename) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check file size (SNES ROMs are typically 2MB, 3MB, 4MB, 6MB, etc.)
|
|
||||||
auto file_size = std::filesystem::file_size(filename);
|
auto file_size = std::filesystem::file_size(filename);
|
||||||
if (file_size < 1024 * 1024 || file_size > 8 * 1024 * 1024) {
|
if (file_size < 1024 * 1024 || file_size > 8 * 1024 * 1024) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add more ROM validation (header checks, etc.)
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace editor
|
} // namespace yaze::editor
|
||||||
} // namespace yaze
|
|
||||||
|
|||||||
@@ -27,34 +27,21 @@ class RomFileManager {
|
|||||||
~RomFileManager() = default;
|
~RomFileManager() = default;
|
||||||
|
|
||||||
// ROM file operations
|
// ROM file operations
|
||||||
absl::Status LoadRom(const std::string& filename = "");
|
absl::Status LoadRom(Rom* rom, const std::string& filename);
|
||||||
absl::Status SaveRom();
|
absl::Status SaveRom(Rom* rom);
|
||||||
absl::Status SaveRomAs(const std::string& filename);
|
absl::Status SaveRomAs(Rom* rom, const std::string& filename);
|
||||||
absl::Status OpenRomOrProject(const std::string& filename);
|
absl::Status OpenRomOrProject(Rom* rom, const std::string& filename);
|
||||||
|
absl::Status CreateBackup(Rom* rom);
|
||||||
|
absl::Status ValidateRom(Rom* rom);
|
||||||
|
|
||||||
// Asset operations
|
// Utility helpers
|
||||||
absl::Status LoadAssets();
|
bool IsRomLoaded(Rom* rom) const;
|
||||||
|
std::string GetRomFilename(Rom* rom) const;
|
||||||
// ROM state management
|
|
||||||
absl::Status SetCurrentRom(Rom* rom);
|
|
||||||
Rom* GetCurrentRom() const { return current_rom_; }
|
|
||||||
|
|
||||||
// ROM information
|
|
||||||
bool IsRomLoaded() const { return current_rom_ && current_rom_->is_loaded(); }
|
|
||||||
std::string GetRomFilename() const;
|
|
||||||
std::string GetRomTitle() const;
|
|
||||||
|
|
||||||
// Validation and backup
|
|
||||||
absl::Status ValidateRom();
|
|
||||||
absl::Status ValidateRom(Rom* rom); // Validate a specific ROM
|
|
||||||
absl::Status CreateBackup();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Rom* current_rom_ = nullptr;
|
|
||||||
ToastManager* toast_manager_ = nullptr;
|
ToastManager* toast_manager_ = nullptr;
|
||||||
|
|
||||||
// Helper methods
|
absl::Status LoadRomFromFile(Rom* rom, const std::string& filename);
|
||||||
absl::Status LoadRomFromFile(const std::string& filename);
|
|
||||||
std::string GenerateBackupFilename(const std::string& original_filename) const;
|
std::string GenerateBackupFilename(const std::string& original_filename) const;
|
||||||
bool IsValidRomFile(const std::string& filename) const;
|
bool IsValidRomFile(const std::string& filename) const;
|
||||||
};
|
};
|
||||||
|
|||||||
350
src/app/editor/system/shortcut_configurator.cc
Normal file
350
src/app/editor/system/shortcut_configurator.cc
Normal file
@@ -0,0 +1,350 @@
|
|||||||
|
#include "app/editor/system/shortcut_configurator.h"
|
||||||
|
|
||||||
|
#include "absl/functional/bind_front.h"
|
||||||
|
#include "absl/strings/str_format.h"
|
||||||
|
#include "app/editor/editor_manager.h"
|
||||||
|
#include "app/editor/system/editor_card_registry.h"
|
||||||
|
#include "app/editor/system/menu_orchestrator.h"
|
||||||
|
#include "app/editor/system/proposal_drawer.h"
|
||||||
|
#include "app/editor/system/rom_file_manager.h"
|
||||||
|
#include "app/editor/system/session_coordinator.h"
|
||||||
|
#include "app/editor/system/toast_manager.h"
|
||||||
|
#include "app/editor/ui/ui_coordinator.h"
|
||||||
|
#include "app/editor/ui/workspace_manager.h"
|
||||||
|
#include "app/editor/system/popup_manager.h"
|
||||||
|
#include "app/core/project.h"
|
||||||
|
|
||||||
|
namespace yaze::editor {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void RegisterIfValid(ShortcutManager* shortcut_manager,
|
||||||
|
const std::string& name,
|
||||||
|
const std::vector<ImGuiKey>& keys,
|
||||||
|
std::function<void()> callback) {
|
||||||
|
if (!shortcut_manager || !callback) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
shortcut_manager->RegisterShortcut(name, keys, std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterIfValid(ShortcutManager* shortcut_manager,
|
||||||
|
const std::string& name,
|
||||||
|
ImGuiKey key,
|
||||||
|
std::function<void()> callback) {
|
||||||
|
if (!shortcut_manager || !callback) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
shortcut_manager->RegisterShortcut(name, key, std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void ConfigureEditorShortcuts(const ShortcutDependencies& deps,
|
||||||
|
ShortcutManager* shortcut_manager) {
|
||||||
|
if (!shortcut_manager) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* editor_manager = deps.editor_manager;
|
||||||
|
auto* ui_coordinator = deps.ui_coordinator;
|
||||||
|
auto* popup_manager = deps.popup_manager;
|
||||||
|
auto* card_registry = deps.card_registry;
|
||||||
|
|
||||||
|
RegisterIfValid(
|
||||||
|
shortcut_manager, "global.toggle_sidebar",
|
||||||
|
{ImGuiKey_LeftCtrl, ImGuiKey_B},
|
||||||
|
[ui_coordinator]() {
|
||||||
|
if (ui_coordinator) {
|
||||||
|
ui_coordinator->ToggleCardSidebar();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Open", {ImGuiMod_Ctrl, ImGuiKey_O},
|
||||||
|
[editor_manager]() {
|
||||||
|
if (editor_manager) {
|
||||||
|
editor_manager->LoadRom();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Save", {ImGuiMod_Ctrl, ImGuiKey_S},
|
||||||
|
[editor_manager]() {
|
||||||
|
if (editor_manager) {
|
||||||
|
editor_manager->SaveRom();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Save As",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_S},
|
||||||
|
[editor_manager]() {
|
||||||
|
if (editor_manager) {
|
||||||
|
// Use project-aware default filename when possible
|
||||||
|
std::string filename = editor_manager->GetCurrentRom()
|
||||||
|
? editor_manager->GetCurrentRom()->filename()
|
||||||
|
: "";
|
||||||
|
editor_manager->SaveRomAs(filename);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Close ROM", {ImGuiMod_Ctrl, ImGuiKey_W},
|
||||||
|
[editor_manager]() {
|
||||||
|
if (editor_manager && editor_manager->GetCurrentRom()) {
|
||||||
|
editor_manager->GetCurrentRom()->Close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Quit", {ImGuiMod_Ctrl, ImGuiKey_Q},
|
||||||
|
[editor_manager]() {
|
||||||
|
if (editor_manager) {
|
||||||
|
editor_manager->Quit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Undo", {ImGuiMod_Ctrl, ImGuiKey_Z},
|
||||||
|
[editor_manager]() {
|
||||||
|
if (editor_manager && editor_manager->GetCurrentEditor()) {
|
||||||
|
editor_manager->GetCurrentEditor()->Undo();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Redo",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_Z},
|
||||||
|
[editor_manager]() {
|
||||||
|
if (editor_manager && editor_manager->GetCurrentEditor()) {
|
||||||
|
editor_manager->GetCurrentEditor()->Redo();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Cut", {ImGuiMod_Ctrl, ImGuiKey_X},
|
||||||
|
[editor_manager]() {
|
||||||
|
if (editor_manager && editor_manager->GetCurrentEditor()) {
|
||||||
|
editor_manager->GetCurrentEditor()->Cut();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Copy", {ImGuiMod_Ctrl, ImGuiKey_C},
|
||||||
|
[editor_manager]() {
|
||||||
|
if (editor_manager && editor_manager->GetCurrentEditor()) {
|
||||||
|
editor_manager->GetCurrentEditor()->Copy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Paste", {ImGuiMod_Ctrl, ImGuiKey_V},
|
||||||
|
[editor_manager]() {
|
||||||
|
if (editor_manager && editor_manager->GetCurrentEditor()) {
|
||||||
|
editor_manager->GetCurrentEditor()->Paste();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Find", {ImGuiMod_Ctrl, ImGuiKey_F},
|
||||||
|
[editor_manager]() {
|
||||||
|
if (editor_manager && editor_manager->GetCurrentEditor()) {
|
||||||
|
editor_manager->GetCurrentEditor()->Find();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(
|
||||||
|
shortcut_manager, "Command Palette",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_P},
|
||||||
|
[ui_coordinator]() {
|
||||||
|
if (ui_coordinator) {
|
||||||
|
ui_coordinator->ShowCommandPalette();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(
|
||||||
|
shortcut_manager, "Global Search",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_K},
|
||||||
|
[ui_coordinator]() {
|
||||||
|
if (ui_coordinator) {
|
||||||
|
ui_coordinator->ShowGlobalSearch();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Load Last ROM",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiKey_R},
|
||||||
|
[editor_manager]() {
|
||||||
|
auto& recent = core::RecentFilesManager::GetInstance();
|
||||||
|
if (!recent.GetRecentFiles().empty() && editor_manager) {
|
||||||
|
editor_manager->OpenRomOrProject(
|
||||||
|
recent.GetRecentFiles().front());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Show About", ImGuiKey_F1,
|
||||||
|
[popup_manager]() {
|
||||||
|
if (popup_manager) {
|
||||||
|
popup_manager->Show("About");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
auto register_editor_shortcut = [&](EditorType type, ImGuiKey key) {
|
||||||
|
RegisterIfValid(shortcut_manager,
|
||||||
|
absl::StrFormat("switch.%d", static_cast<int>(type)),
|
||||||
|
{ImGuiMod_Ctrl, key},
|
||||||
|
[editor_manager, type]() {
|
||||||
|
if (editor_manager) {
|
||||||
|
editor_manager->SwitchToEditor(type);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
register_editor_shortcut(EditorType::kOverworld, ImGuiKey_1);
|
||||||
|
register_editor_shortcut(EditorType::kDungeon, ImGuiKey_2);
|
||||||
|
register_editor_shortcut(EditorType::kGraphics, ImGuiKey_3);
|
||||||
|
register_editor_shortcut(EditorType::kSprite, ImGuiKey_4);
|
||||||
|
register_editor_shortcut(EditorType::kMessage, ImGuiKey_5);
|
||||||
|
register_editor_shortcut(EditorType::kMusic, ImGuiKey_6);
|
||||||
|
register_editor_shortcut(EditorType::kPalette, ImGuiKey_7);
|
||||||
|
register_editor_shortcut(EditorType::kScreen, ImGuiKey_8);
|
||||||
|
register_editor_shortcut(EditorType::kAssembly, ImGuiKey_9);
|
||||||
|
register_editor_shortcut(EditorType::kSettings, ImGuiKey_0);
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Editor Selection",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiKey_E},
|
||||||
|
[ui_coordinator]() {
|
||||||
|
if (ui_coordinator) {
|
||||||
|
ui_coordinator->ShowEditorSelection();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(
|
||||||
|
shortcut_manager, "Card Browser",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_B},
|
||||||
|
[ui_coordinator]() {
|
||||||
|
if (ui_coordinator) {
|
||||||
|
ui_coordinator->ShowCardBrowser();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (card_registry) {
|
||||||
|
RegisterIfValid(shortcut_manager, "Show Dungeon Cards",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_D},
|
||||||
|
[card_registry]() {
|
||||||
|
card_registry->ShowAllCardsInCategory("Dungeon");
|
||||||
|
});
|
||||||
|
RegisterIfValid(shortcut_manager, "Show Graphics Cards",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_G},
|
||||||
|
[card_registry]() {
|
||||||
|
card_registry->ShowAllCardsInCategory("Graphics");
|
||||||
|
});
|
||||||
|
RegisterIfValid(shortcut_manager, "Show Screen Cards",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_S},
|
||||||
|
[card_registry]() {
|
||||||
|
card_registry->ShowAllCardsInCategory("Screen");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef YAZE_WITH_GRPC
|
||||||
|
RegisterIfValid(shortcut_manager, "Agent Editor",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_A},
|
||||||
|
[editor_manager]() {
|
||||||
|
if (editor_manager) {
|
||||||
|
editor_manager->ShowAIAgent();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Agent Chat History",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiKey_H},
|
||||||
|
[editor_manager]() {
|
||||||
|
if (editor_manager) {
|
||||||
|
editor_manager->ShowChatHistory();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Proposal Drawer",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiKey_P},
|
||||||
|
[editor_manager]() {
|
||||||
|
if (editor_manager) {
|
||||||
|
editor_manager->ShowProposalDrawer();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureMenuShortcuts(const ShortcutDependencies& deps,
|
||||||
|
ShortcutManager* shortcut_manager) {
|
||||||
|
if (!shortcut_manager) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* menu_orchestrator = deps.menu_orchestrator;
|
||||||
|
auto* session_coordinator = deps.session_coordinator;
|
||||||
|
auto* workspace_manager = deps.workspace_manager;
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "New Session",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_N},
|
||||||
|
[session_coordinator]() {
|
||||||
|
if (session_coordinator) {
|
||||||
|
session_coordinator->CreateNewSession();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Duplicate Session",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_D},
|
||||||
|
[session_coordinator]() {
|
||||||
|
if (session_coordinator) {
|
||||||
|
session_coordinator->DuplicateCurrentSession();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Close Session",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_W},
|
||||||
|
[session_coordinator]() {
|
||||||
|
if (session_coordinator) {
|
||||||
|
session_coordinator->CloseCurrentSession();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Session Switcher",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiKey_Tab},
|
||||||
|
[session_coordinator]() {
|
||||||
|
if (session_coordinator) {
|
||||||
|
session_coordinator->ShowSessionSwitcher();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Save Layout",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_L},
|
||||||
|
[workspace_manager]() {
|
||||||
|
if (workspace_manager) {
|
||||||
|
workspace_manager->SaveWorkspaceLayout();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Load Layout",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_O},
|
||||||
|
[workspace_manager]() {
|
||||||
|
if (workspace_manager) {
|
||||||
|
workspace_manager->LoadWorkspaceLayout();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Reset Layout",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiMod_Shift, ImGuiKey_R},
|
||||||
|
[workspace_manager]() {
|
||||||
|
if (workspace_manager) {
|
||||||
|
workspace_manager->ResetWorkspaceLayout();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterIfValid(shortcut_manager, "Maximize Window", ImGuiKey_F11,
|
||||||
|
[workspace_manager]() {
|
||||||
|
if (workspace_manager) {
|
||||||
|
workspace_manager->MaximizeCurrentWindow();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
#ifdef YAZE_ENABLE_TESTING
|
||||||
|
RegisterIfValid(shortcut_manager, "Test Dashboard",
|
||||||
|
{ImGuiMod_Ctrl, ImGuiKey_T},
|
||||||
|
[menu_orchestrator]() {
|
||||||
|
if (menu_orchestrator) {
|
||||||
|
menu_orchestrator->OnShowTestDashboard();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace yaze::editor
|
||||||
|
|
||||||
48
src/app/editor/system/shortcut_configurator.h
Normal file
48
src/app/editor/system/shortcut_configurator.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#ifndef YAZE_APP_EDITOR_SYSTEM_SHORTCUT_CONFIGURATOR_H_
|
||||||
|
#define YAZE_APP_EDITOR_SYSTEM_SHORTCUT_CONFIGURATOR_H_
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "app/editor/editor.h"
|
||||||
|
#include "app/editor/system/shortcut_manager.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace editor {
|
||||||
|
|
||||||
|
class EditorManager;
|
||||||
|
class EditorRegistry;
|
||||||
|
class MenuOrchestrator;
|
||||||
|
class RomFileManager;
|
||||||
|
class ProjectManager;
|
||||||
|
class SessionCoordinator;
|
||||||
|
class UICoordinator;
|
||||||
|
class WorkspaceManager;
|
||||||
|
class PopupManager;
|
||||||
|
class ToastManager;
|
||||||
|
class EditorCardRegistry;
|
||||||
|
|
||||||
|
struct ShortcutDependencies {
|
||||||
|
EditorManager* editor_manager = nullptr;
|
||||||
|
EditorRegistry* editor_registry = nullptr;
|
||||||
|
MenuOrchestrator* menu_orchestrator = nullptr;
|
||||||
|
RomFileManager* rom_file_manager = nullptr;
|
||||||
|
ProjectManager* project_manager = nullptr;
|
||||||
|
SessionCoordinator* session_coordinator = nullptr;
|
||||||
|
UICoordinator* ui_coordinator = nullptr;
|
||||||
|
WorkspaceManager* workspace_manager = nullptr;
|
||||||
|
PopupManager* popup_manager = nullptr;
|
||||||
|
ToastManager* toast_manager = nullptr;
|
||||||
|
EditorCardRegistry* card_registry = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ConfigureEditorShortcuts(const ShortcutDependencies& deps,
|
||||||
|
ShortcutManager* shortcut_manager);
|
||||||
|
|
||||||
|
void ConfigureMenuShortcuts(const ShortcutDependencies& deps,
|
||||||
|
ShortcutManager* shortcut_manager);
|
||||||
|
|
||||||
|
} // namespace editor
|
||||||
|
} // namespace yaze
|
||||||
|
|
||||||
|
#endif // YAZE_APP_EDITOR_SYSTEM_SHORTCUT_CONFIGURATOR_H_
|
||||||
|
|
||||||
@@ -111,7 +111,8 @@ void UICoordinator::DrawAllUI() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UICoordinator::DrawMenuBarExtras() {
|
void UICoordinator::DrawMenuBarExtras() {
|
||||||
auto* current_rom = rom_manager_.GetCurrentRom();
|
// Get current ROM from EditorManager (RomFileManager doesn't track "current")
|
||||||
|
auto* current_rom = editor_manager_->GetCurrentRom();
|
||||||
std::string version_text = absl::StrFormat("v%s", editor_manager_->version().c_str());
|
std::string version_text = absl::StrFormat("v%s", editor_manager_->version().c_str());
|
||||||
float version_width = ImGui::CalcTextSize(version_text.c_str()).x;
|
float version_width = ImGui::CalcTextSize(version_text.c_str()).x;
|
||||||
float session_rom_area_width = 280.0f;
|
float session_rom_area_width = 280.0f;
|
||||||
|
|||||||
Reference in New Issue
Block a user