diff --git a/.gitmodules b/.gitmodules index e39b749c..d9187dcb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "src/Library/ImGuiFileDialog"] path = src/Library/ImGuiFileDialog url = https://github.com/aiekick/ImGuiFileDialog.git +[submodule "src/Library/ImGuiColorTextEdit"] + path = src/Library/ImGuiColorTextEdit + url = https://github.com/BalazsJako/ImGuiColorTextEdit.git diff --git a/src/Application/Core/Controller.cc b/src/Application/Core/Controller.cc index 9c6b3aa1..d2c0d8dc 100644 --- a/src/Application/Core/Controller.cc +++ b/src/Application/Core/Controller.cc @@ -9,62 +9,68 @@ bool Controller::isActive() const { return active; } void Controller::onEntry() noexcept(false) { window.Create(); renderer.Create(window.Get()); + ImGuiIO &io = ImGui::GetIO(); + + io.KeyMap[ImGuiKey_Backspace] = SDL_GetScancodeFromKey(SDLK_BACKSPACE); + io.KeyMap[ImGuiKey_Enter] = SDL_GetScancodeFromKey(SDLK_RETURN); + io.KeyMap[ImGuiKey_UpArrow] = SDL_GetScancodeFromKey(SDLK_UP); + io.KeyMap[ImGuiKey_DownArrow] = SDL_GetScancodeFromKey(SDLK_DOWN); + io.KeyMap[ImGuiKey_Tab] = SDL_GetScancodeFromKey(SDLK_TAB); active = true; } void Controller::onInput() { int wheel = 0; SDL_Event event; - ImGuiIO& io = ImGui::GetIO(); + ImGuiIO &io = ImGui::GetIO(); while (SDL_PollEvent(&event)) { switch (event.type) { - case SDL_KEYDOWN: - switch (event.key.keysym.sym) { - case SDLK_UP: - case SDLK_DOWN: - case SDLK_RETURN: - case SDLK_BACKSPACE: - case SDLK_TAB: - io.KeysDown[event.key.keysym.scancode] = - (event.type == SDL_KEYDOWN); - break; - default: - break; - } - break; - - case SDL_KEYUP: { - int key = event.key.keysym.scancode; - IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown)); - io.KeysDown[key] = (event.type == SDL_KEYDOWN); - io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0); - io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0); - io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0); - io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0); - break; - } - case SDL_WINDOWEVENT: - switch (event.window.event) { - case SDL_WINDOWEVENT_CLOSE: - active = false; - break; - case SDL_WINDOWEVENT_SIZE_CHANGED: - io.DisplaySize.x = static_cast(event.window.data1); - io.DisplaySize.y = static_cast(event.window.data2); - break; - default: - break; - } - break; - case SDL_TEXTINPUT: - io.AddInputCharactersUTF8(event.text.text); - break; - case SDL_MOUSEWHEEL: - wheel = event.wheel.y; + case SDL_KEYDOWN: + switch (event.key.keysym.sym) { + case SDLK_UP: + case SDLK_DOWN: + case SDLK_RETURN: + case SDLK_BACKSPACE: + case SDLK_TAB: + io.KeysDown[event.key.keysym.scancode] = (event.type == SDL_KEYDOWN); break; default: break; + } + break; + + case SDL_KEYUP: { + int key = event.key.keysym.scancode; + IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown)); + io.KeysDown[key] = (event.type == SDL_KEYDOWN); + io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0); + io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0); + io.KeyAlt = ((SDL_GetModState() & KMOD_ALT) != 0); + io.KeySuper = ((SDL_GetModState() & KMOD_GUI) != 0); + break; + } + case SDL_WINDOWEVENT: + switch (event.window.event) { + case SDL_WINDOWEVENT_CLOSE: + active = false; + break; + case SDL_WINDOWEVENT_SIZE_CHANGED: + io.DisplaySize.x = static_cast(event.window.data1); + io.DisplaySize.y = static_cast(event.window.data2); + break; + default: + break; + } + break; + case SDL_TEXTINPUT: + io.AddInputCharactersUTF8(event.text.text); + break; + case SDL_MOUSEWHEEL: + wheel = event.wheel.y; + break; + default: + break; } } @@ -78,13 +84,9 @@ void Controller::onInput() { io.MouseWheel = static_cast(wheel); } -void Controller::onLoad() { - editor.UpdateScreen(); -} +void Controller::onLoad() { editor.UpdateScreen(); } -void Controller::doRender() { - renderer.Render(); -} +void Controller::doRender() { renderer.Render(); } void Controller::onExit() { ImGui_ImplSDLRenderer_Shutdown(); @@ -95,6 +97,6 @@ void Controller::onExit() { SDL_Quit(); } -} // namespace Core -} // namespace Application -} // namespace yaze \ No newline at end of file +} // namespace Core +} // namespace Application +} // namespace yaze \ No newline at end of file diff --git a/src/Application/Editor/Editor.cc b/src/Application/Editor/Editor.cc index e4dda25c..fa00e2f8 100644 --- a/src/Application/Editor/Editor.cc +++ b/src/Application/Editor/Editor.cc @@ -4,6 +4,87 @@ namespace yaze { namespace Application { namespace Editor { +Editor::Editor() { + static bool inited = false; + if (!inited) { + static const char *const keywords[] = { + "ADC", "AND", "ASL", "BCC", "BCS", "BEQ", "BIT", "BMI", "BNE", + "BPL", "BRA", "BRL", "BVC", "BVS", "CLC", "CLD", "CLI", "CLV", + "CMP", "CPX", "CPY", "DEC", "DEX", "DEY", "EOR", "INC", "INX", + "INY", "JMP", "JSR", "JSL", "LDA", "LDX", "LDY", "LSR", "MVN", "NOP", + "ORA", "PEA", "PER", "PHA", "PHB", "PHD", "PHP", "PHX", "PHY", + "PLA", "PLB", "PLD", "PLP", "PLX", "PLY", "REP", "ROL", "ROR", + "RTI", "RTL", "RTS", "SBC", "SEC", "SEI", "SEP", "STA", "STP", + "STX", "STY", "STZ", "TAX", "TAY", "TCD", "TCS", "TDC", "TRB", + "TSB", "TSC", "TSX", "TXA", "TXS", "TXY", "TYA", "TYX", "WAI", + "WDM", "XBA", "XCE", "ORG", "LOROM", "HIROM", "NAMESPACE", "DB" }; + for (auto &k : keywords) + language65816Def.mKeywords.insert(k); + + static const char *const identifiers[] = { + "abort", "abs", "acos", "asin", "atan", "atexit", + "atof", "atoi", "atol", "ceil", "clock", "cosh", + "ctime", "div", "exit", "fabs", "floor", "fmod", + "getchar", "getenv", "isalnum", "isalpha", "isdigit", "isgraph", + "ispunct", "isspace", "isupper", "kbhit", "log10", "log2", + "log", "memcmp", "modf", "pow", "putchar", "putenv", + "puts", "rand", "remove", "rename", "sinh", "sqrt", + "srand", "strcat", "strcmp", "strerror", "time", "tolower", + "toupper" }; + for (auto &k : identifiers) { + TextEditor::Identifier id; + id.mDeclaration = "Built-in function"; + language65816Def.mIdentifiers.insert(std::make_pair(std::string(k), id)); + } + + language65816Def.mTokenRegexStrings.push_back( + std::make_pair( + "[ \\t]*#[ \\t]*[a-zA-Z_]+", + TextEditor::PaletteIndex::Preprocessor)); + language65816Def.mTokenRegexStrings.push_back( + std::make_pair( + "L?\\\"(\\\\.|[^\\\"])*\\\"", TextEditor::PaletteIndex::String)); + language65816Def.mTokenRegexStrings.push_back( + std::make_pair( + "\\'\\\\?[^\\']\\'", TextEditor::PaletteIndex::CharLiteral)); + language65816Def.mTokenRegexStrings.push_back( + std::make_pair( + "[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)([eE][+-]?[0-9]+)?[fF]?", + TextEditor::PaletteIndex::Number)); + language65816Def.mTokenRegexStrings.push_back( + std::make_pair( + "[+-]?[0-9]+[Uu]?[lL]?[lL]?", TextEditor::PaletteIndex::Number)); + language65816Def.mTokenRegexStrings.push_back( + std::make_pair( + "0[0-7]+[Uu]?[lL]?[lL]?", TextEditor::PaletteIndex::Number)); + language65816Def.mTokenRegexStrings.push_back( + std::make_pair( + "0[xX][0-9a-fA-F]+[uU]?[lL]?[lL]?", + TextEditor::PaletteIndex::Number)); + language65816Def.mTokenRegexStrings.push_back( + std::make_pair( + "[a-zA-Z_][a-zA-Z0-9_]*", TextEditor::PaletteIndex::Identifier)); + language65816Def.mTokenRegexStrings.push_back( + std::make_pair( + "[\\[\\]\\{\\}\\!\\%\\^\\&\\*\\(\\)\\-\\+\\=\\~\\|\\<\\>\\?\\/" + "\\;\\,\\.]", + TextEditor::PaletteIndex::Punctuation)); + + language65816Def.mCommentStart = "/*"; + language65816Def.mCommentEnd = "*/"; + language65816Def.mSingleLineComment = ";"; + + language65816Def.mCaseSensitive = false; + language65816Def.mAutoIndentation = true; + + language65816Def.mName = "65816"; + + inited = true; + } + asm_editor_.SetLanguageDefinition(language65816Def); + asm_editor_.SetPalette(TextEditor::GetDarkPalette()); +} + void Editor::UpdateScreen() { const ImGuiIO &io = ImGui::GetIO(); ImGui::NewFrame(); @@ -51,7 +132,7 @@ void Editor::DrawYazeMenu() { std::string filePathName = ImGuiFileDialog::Instance()->GetFilePathName(); std::string filePath = ImGuiFileDialog::Instance()->GetCurrentPath(); rom.LoadFromFile(filePathName); - owEditor.SetRom(rom); + overworld_editor_.SetRom(rom); rom_data_ = (void *)rom.GetRawData(); } @@ -126,10 +207,12 @@ void Editor::DrawEditMenu() const { } } -void Editor::DrawViewMenu() const { +void Editor::DrawViewMenu() { static bool show_imgui_metrics = false; static bool show_imgui_style_editor = false; static bool show_memory_editor = false; + static bool show_asm_editor = false; + if (show_imgui_metrics) { ImGui::ShowMetricsWindow(&show_imgui_metrics); } @@ -139,6 +222,31 @@ void Editor::DrawViewMenu() const { mem_edit.DrawWindow("Memory Editor", rom_data_, rom.getSize()); } + if (show_asm_editor) { + static bool asm_is_loaded = false; + auto cpos = asm_editor_.GetCursorPosition(); + static const char *fileToEdit = "assets/bunnyhood.asm"; + if (!asm_is_loaded) { + std::ifstream t(fileToEdit); + if (t.good()) { + std::string str((std::istreambuf_iterator(t)), + std::istreambuf_iterator()); + asm_editor_.SetText(str); + } + asm_is_loaded = true; + } + + ImGui::Begin("ASM Editor", &show_asm_editor); + ImGui::Text("%6d/%-6d %6d lines | %s | %s | %s | %s", cpos.mLine + 1, + cpos.mColumn + 1, asm_editor_.GetTotalLines(), + asm_editor_.IsOverwrite() ? "Ovr" : "Ins", + asm_editor_.CanUndo() ? "*" : " ", + asm_editor_.GetLanguageDefinition().mName.c_str(), fileToEdit); + + asm_editor_.Render(fileToEdit); + ImGui::End(); + } + if (show_imgui_style_editor) { ImGui::Begin("Style Editor (ImGui)", &show_imgui_style_editor); ImGui::ShowStyleEditor(); @@ -153,6 +261,7 @@ void Editor::DrawViewMenu() const { } ImGui::MenuItem("HEX Editor", nullptr, &show_memory_editor); + ImGui::MenuItem("ASM Editor", nullptr, &show_asm_editor); ImGui::Separator(); if (ImGui::BeginMenu("GUI Tools")) { @@ -193,7 +302,7 @@ void Editor::DrawHelpMenu() const { // understand the data quickly void Editor::DrawOverworldEditor() { if (ImGui::BeginTabItem("Overworld")) { - owEditor.Update(); + overworld_editor_.Update(); ImGui::EndTabItem(); } } diff --git a/src/Application/Editor/Editor.h b/src/Application/Editor/Editor.h index 9067f5cd..21008a88 100644 --- a/src/Application/Editor/Editor.h +++ b/src/Application/Editor/Editor.h @@ -4,29 +4,31 @@ #include #include "Core/Icons.h" -#include "OverworldEditor.h" +#include "ImGuiColorTextEdit/TextEditor.h" #include "ImGuiFileDialog/ImGuiFileDialog.h" +#include "OverworldEditor.h" #include "Utils/ROM.h" #include "imgui/backends/imgui_impl_sdl.h" #include "imgui/backends/imgui_impl_sdlrenderer.h" #include "imgui/imgui.h" #include "imgui/imgui_internal.h" -#include "imgui/misc/cpp/imgui_stdlib.h" #include "imgui/imgui_memory_editor.h" +#include "imgui/misc/cpp/imgui_stdlib.h" namespace yaze { namespace Application { namespace Editor { class Editor { - public: +public: + Editor(); void UpdateScreen(); - private: +private: void DrawYazeMenu(); void DrawFileMenu() const; void DrawEditMenu() const; - void DrawViewMenu() const; + void DrawViewMenu(); void DrawHelpMenu() const; void DrawOverworldEditor(); @@ -34,18 +36,20 @@ class Editor { void DrawSpriteEditor(); void DrawScreenEditor(); void DrawROMInfo(); - - OverworldEditor owEditor; + + void *rom_data_; + bool isLoaded = true; + Utils::ROM rom; + TextEditor asm_editor_; + TextEditor::LanguageDefinition language65816Def; + OverworldEditor overworld_editor_; - void* rom_data_; - - bool isLoaded = true; ImGuiTableFlags toolset_table_flags = ImGuiTableFlags_SizingFixedFit; }; -} // namespace View -} // namespace Application -} // namespace yaze +} // namespace Editor +} // namespace Application +} // namespace yaze -#endif // YAZE_APPLICATION_VIEW_EDITOR_H \ No newline at end of file +#endif // YAZE_APPLICATION_VIEW_EDITOR_H \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6ad631d1..0ffefb96 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,6 +20,13 @@ target_include_directories(ImGuiFileDialog PUBLIC ${IMGUI_PATH}) target_include_directories(ImGuiFileDialog PUBLIC ${SDL2_INCLUDE_DIR}) target_compile_definitions(ImGuiFileDialog PUBLIC IMGUI_IMPL_OPENGL_LOADER_CUSTOM= GL_GLEXT_PROTOTYPES=1) +set(IMGUI_COLOR_TEXT_EDIT_PATH "Library/ImGuiColorTextEdit") +file(GLOB IMGUI_COLOR_TEXT_EDIT_SOURCES ${IMGUI_COLOR_TEXT_EDIT_PATH}/*.cpp) +add_library("ImGuiColorTextEdit" STATIC ${IMGUI_COLOR_TEXT_EDIT_SOURCES}) +target_include_directories(ImGuiColorTextEdit PUBLIC ${IMGUI_PATH}) +target_include_directories(ImGuiColorTextEdit PUBLIC ${SDL2_INCLUDE_DIR}) +target_compile_definitions(ImGuiColorTextEdit PUBLIC IMGUI_IMPL_OPENGL_LOADER_CUSTOM= GL_GLEXT_PROTOTYPES=1) + # Executable Linkage -------------------------------------------------------------------------------------- add_executable( yaze @@ -45,6 +52,7 @@ add_executable( ${IMGUI_PATH}/backends/imgui_impl_sdlrenderer.cpp ${IMGUI_PATH}/misc/cpp/imgui_stdlib.cpp ${IMGUI_FILE_DLG_PATH}/ImGuiFileDialog.cpp + ${IMGUI_COLOR_TEXT_EDIT_PATH}/TextEditor.cpp ) target_include_directories( diff --git a/src/Library/ImGuiColorTextEdit b/src/Library/ImGuiColorTextEdit new file mode 160000 index 00000000..0a88824f --- /dev/null +++ b/src/Library/ImGuiColorTextEdit @@ -0,0 +1 @@ +Subproject commit 0a88824f7de8d0bd11d8419066caa7d3469395c4