diff --git a/src/app/core/controller.h b/src/app/core/controller.h index 9e654986..726189d2 100644 --- a/src/app/core/controller.h +++ b/src/app/core/controller.h @@ -9,7 +9,7 @@ #include "app/core/platform/renderer.h" #include "app/core/utils/file_util.h" #include "app/editor/editor_manager.h" -#include "app/editor/utils/editor.h" +#include "app/editor/editor.h" #include "imgui/backends/imgui_impl_sdl2.h" #include "imgui/backends/imgui_impl_sdlrenderer2.h" #include "imgui/imconfig.h" diff --git a/src/app/core/platform/app_delegate.mm b/src/app/core/platform/app_delegate.mm index 7a54f398..e03dec3c 100644 --- a/src/app/core/platform/app_delegate.mm +++ b/src/app/core/platform/app_delegate.mm @@ -2,7 +2,7 @@ #import "app/core/platform/app_delegate.h" #import "app/core/controller.h" #import "app/core/platform/file_dialog.h" -#import "app/editor/utils/editor.h" +#import "app/editor/editor.h" #import "app/rom.h" #if defined(__APPLE__) && defined(__MACH__) @@ -225,6 +225,8 @@ NSLog(@"Open Recent File action triggered"); } +@end + extern "C" void yaze_initialize_cococa() { @autoreleasepool { AppDelegate *delegate = [[AppDelegate alloc] init]; @@ -250,8 +252,6 @@ extern "C" void yaze_run_cocoa_app_delegate(const char *filename) { controller.OnExit(); } -@end - #endif #endif diff --git a/src/app/editor/system/command_manager.cc b/src/app/editor/system/command_manager.cc index 30512971..f8310414 100644 --- a/src/app/editor/system/command_manager.cc +++ b/src/app/editor/system/command_manager.cc @@ -2,15 +2,79 @@ #include +#include "app/editor/editor.h" #include "imgui/imgui.h" namespace yaze { namespace app { namespace editor { +ImGuiKey MapKeyToImGuiKey(char key) { + switch (key) { + case 'A': + return ImGuiKey_A; + case 'B': + return ImGuiKey_B; + case 'C': + return ImGuiKey_C; + case 'D': + return ImGuiKey_D; + case 'E': + return ImGuiKey_E; + case 'F': + return ImGuiKey_F; + case 'G': + return ImGuiKey_G; + case 'H': + return ImGuiKey_H; + case 'I': + return ImGuiKey_I; + case 'J': + return ImGuiKey_J; + case 'K': + return ImGuiKey_K; + case 'L': + return ImGuiKey_L; + case 'M': + return ImGuiKey_M; + case 'N': + return ImGuiKey_N; + case 'O': + return ImGuiKey_O; + case 'P': + return ImGuiKey_P; + case 'Q': + return ImGuiKey_Q; + case 'R': + return ImGuiKey_R; + case 'S': + return ImGuiKey_S; + case 'T': + return ImGuiKey_T; + case 'U': + return ImGuiKey_U; + case 'V': + return ImGuiKey_V; + case 'W': + return ImGuiKey_W; + case 'X': + return ImGuiKey_X; + case 'Y': + return ImGuiKey_Y; + case 'Z': + return ImGuiKey_Z; + case '/': + return ImGuiKey_Slash; + case '-': + return ImGuiKey_Minus; + default: + return ImGuiKey_COUNT; + } +} + // When the player presses Space, a popup will appear fixed to the bottom of the // ImGui window with a list of the available key commands which can be used. -void CommandManager::ShowWhichKey() { +void CommandManager::ShowWhichKey(EditorLayoutParams *editor_layout) { if (commands_.empty()) { InitializeDefaults(); } @@ -42,64 +106,50 @@ void CommandManager::ShowWhichKey() { if (ImGui::BeginTable("CommandsTable", commands_.size(), ImGuiTableFlags_SizingStretchProp)) { - for (const auto& [shortcut, info] : commands_) { + for (const auto &[shortcut, info] : commands_) { ImGui::TableNextColumn(); - ImGui::TextColored(colors[colorIndex], "%c: %s", info.mnemonic, - info.name.c_str()); + ImGui::TextColored(colors[colorIndex], "%c: %s", + info.command_info.mnemonic, + info.command_info.name.c_str()); colorIndex = (colorIndex + 1) % numColors; } ImGui::EndTable(); } ImGui::EndPopup(); } + + // if the user presses the shortcut key, execute the command + // or if it is a subcommand prefix, wait for the next key + // to determine the subcommand + static bool subcommand_section = false; + for (const auto &[shortcut, info] : commands_) { + if (ImGui::IsKeyPressed(MapKeyToImGuiKey(shortcut[0]))) { + info.command_info.command(); + } + } } -void CommandManager::InitializeDefaults() { - commands_ = { - {"O", - {[]() { /* Open ROM logic */ }, 'O', "Open ROM", - "Open a ROM file for editing"}}, - {"S", - {[]() { /* Save ROM logic */ }, 'S', "Save ROM", - "Save the current ROM"}}, - {"I", - {[]() { /* Import Data logic */ }, 'I', "Import Data", - "Import data into the ROM"}}, - {"E", - {[]() { /* Export Data logic */ }, 'E', "Export Data", - "Export data from the ROM"}}, - {"P", - {[]() { /* Patch ROM logic */ }, 'P', "Patch ROM", - "Apply a patch to the ROM"}}, - {"U", {[]() { /* Undo logic */ }, 'U', "Undo", "Undo the last action"}}, - {"R", - {[]() { /* Redo logic */ }, 'R', "Redo", "Redo the last undone action"}}, - {"F", {[]() { /* Find logic */ }, 'F', "Find", "Find data in the ROM"}}, - {"G", - {[]() { /* Goto logic */ }, 'G', "Goto", - "Go to a specific address in the ROM"}}, - {"H", {[]() { /* Help logic */ }, 'H', "Help", "Show help information"}}}; -} +void CommandManager::InitializeDefaults() {} -void CommandManager::SaveKeybindings(const std::string& filepath) { +void CommandManager::SaveKeybindings(const std::string &filepath) { std::ofstream out(filepath); if (out.is_open()) { - for (const auto& [shortcut, info] : commands_) { - out << shortcut << " " << info.mnemonic << " " << info.name << " " - << info.desc << "\n"; + for (const auto &[shortcut, info] : commands_) { + out << shortcut << " " << info.command_info.mnemonic << " " + << info.command_info.name << " " << info.command_info.desc << "\n"; } out.close(); } } -void CommandManager::LoadKeybindings(const std::string& filepath) { +void CommandManager::LoadKeybindings(const std::string &filepath) { std::ifstream in(filepath); if (in.is_open()) { commands_.clear(); std::string shortcut, name, desc; char mnemonic; while (in >> shortcut >> mnemonic >> name >> desc) { - commands_[shortcut] = {nullptr, mnemonic, name, desc}; + commands_[shortcut].command_info = {nullptr, mnemonic, name, desc}; } in.close(); } diff --git a/src/app/editor/system/command_manager.h b/src/app/editor/system/command_manager.h index 543345b8..06319f37 100644 --- a/src/app/editor/system/command_manager.h +++ b/src/app/editor/system/command_manager.h @@ -1,16 +1,21 @@ #ifndef YAZE_APP_EDITOR_SYSTEM_COMMAND_MANAGER_H #define YAZE_APP_EDITOR_SYSTEM_COMMAND_MANAGER_H -#include +#include #include #include +#include "app/editor/editor.h" +#include "imgui/imgui.h" + namespace yaze { namespace app { namespace editor { +ImGuiKey MapKeyToImGuiKey(char key); + class CommandManager { - public: +public: using Command = std::function; struct CommandInfo { @@ -18,40 +23,61 @@ class CommandManager { char mnemonic; std::string name; std::string desc; - CommandInfo(Command command, char mnemonic, const std::string& name, - const std::string& desc) - : command(std::move(command)), - mnemonic(mnemonic), - name(name), + CommandInfo(Command command, char mnemonic, const std::string &name, + const std::string &desc) + : command(std::move(command)), mnemonic(mnemonic), name(name), desc(desc) {} CommandInfo() = default; }; - void RegisterCommand(const std::string& shortcut, Command command, - char mnemonic, const std::string& name, - const std::string& desc) { - commands_[shortcut] = {std::move(command), mnemonic, name, desc}; + // New command info which supports subsections of commands + struct CommandInfoOrPrefix { + CommandInfo command_info; + std::unordered_map subcommands; + CommandInfoOrPrefix(CommandInfo command_info) + : command_info(std::move(command_info)) {} + CommandInfoOrPrefix() = default; + }; + + void RegisterPrefix(const std::string &group_name, const char prefix, + const std::string &name, const std::string &desc) { + commands_[group_name].command_info = {nullptr, prefix, name, desc}; } - void ExecuteCommand(const std::string& shortcut) { + void RegisterSubcommand(const std::string &group_name, + const std::string &shortcut, const char mnemonic, + const std::string &name, const std::string &desc, + Command command) { + commands_[group_name].subcommands[shortcut].command_info = { + command, mnemonic, name, desc}; + } + + void RegisterCommand(const std::string &shortcut, Command command, + char mnemonic, const std::string &name, + const std::string &desc) { + commands_[shortcut].command_info = {std::move(command), mnemonic, name, + desc}; + } + + void ExecuteCommand(const std::string &shortcut) { if (commands_.find(shortcut) != commands_.end()) { - commands_[shortcut].command(); + commands_[shortcut].command_info.command(); } } - void ShowWhichKey(); + void ShowWhichKey(EditorLayoutParams *editor_layout = nullptr); void InitializeDefaults(); - void SaveKeybindings(const std::string& filepath); - void LoadKeybindings(const std::string& filepath); + void SaveKeybindings(const std::string &filepath); + void LoadKeybindings(const std::string &filepath); - private: - std::unordered_map commands_; +private: + std::unordered_map commands_; }; -} // namespace editor -} // namespace app -} // namespace yaze +} // namespace editor +} // namespace app +} // namespace yaze -#endif // YAZE_APP_EDITOR_SYSTEM_COMMAND_MANAGER_H \ No newline at end of file +#endif // YAZE_APP_EDITOR_SYSTEM_COMMAND_MANAGER_H