From 911b7bc91d9105b1600b5837c44ae228a17fb457 Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Wed, 4 Mar 2026 12:15:24 +0300 Subject: [PATCH] GUI now collects events on its own --- src/DrawingProgram/DrawingProgram.cpp | 1 + .../DrawingProgramSelection.cpp | 26 +-- src/DrawingProgram/Tools/LassoSelectTool.cpp | 1 - src/DrawingProgram/Tools/RectSelectTool.cpp | 1 - src/InputManager.cpp | 56 ++++--- src/InputManager.hpp | 8 +- src/MainProgram.cpp | 7 +- src/Toolbar.cpp | 151 +++++++++++++----- src/Toolbar.hpp | 7 +- src/main.cpp | 2 +- 10 files changed, 184 insertions(+), 76 deletions(-) diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index f5821f2..af9ab5a 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -223,6 +223,7 @@ void DrawingProgram::input_key_callback(const InputManager::KeyCallbackArgs& key break; } } + selection.input_key_callback_display_selection(key); drawTool->input_key_callback(key); } diff --git a/src/DrawingProgram/DrawingProgramSelection.cpp b/src/DrawingProgram/DrawingProgramSelection.cpp index 270ec41..a514599 100644 --- a/src/DrawingProgram/DrawingProgramSelection.cpp +++ b/src/DrawingProgram/DrawingProgramSelection.cpp @@ -356,20 +356,20 @@ void DrawingProgramSelection::update() { void DrawingProgramSelection::input_key_callback_modify_selection(const InputManager::KeyCallbackArgs& key) { switch(key.key) { - case InputManager::KEY_TEXT_UP: { - translate_key(InputManager::KEY_TEXT_UP, key.down); + case InputManager::KEY_GENERIC_UP: { + translate_key(InputManager::KEY_GENERIC_UP, key.down); break; } - case InputManager::KEY_TEXT_DOWN: { - translate_key(InputManager::KEY_TEXT_DOWN, key.down); + case InputManager::KEY_GENERIC_DOWN: { + translate_key(InputManager::KEY_GENERIC_DOWN, key.down); break; } - case InputManager::KEY_TEXT_LEFT: { - translate_key(InputManager::KEY_TEXT_LEFT, key.down); + case InputManager::KEY_GENERIC_LEFT: { + translate_key(InputManager::KEY_GENERIC_LEFT, key.down); break; } - case InputManager::KEY_TEXT_RIGHT: { - translate_key(InputManager::KEY_TEXT_RIGHT, key.down); + case InputManager::KEY_GENERIC_RIGHT: { + translate_key(InputManager::KEY_GENERIC_RIGHT, key.down); break; } } @@ -515,16 +515,16 @@ void DrawingProgramSelection::translate_key(unsigned keyPressed, bool pressed) { constexpr float KEY_TRANSLATE_MAGNITUDE = 5.0f; Vector2f moveVec; switch(keyPressed) { - case InputManager::KEY_TEXT_UP: + case InputManager::KEY_GENERIC_UP: moveVec = {0.0f, -1.0f}; break; - case InputManager::KEY_TEXT_DOWN: + case InputManager::KEY_GENERIC_DOWN: moveVec = {0.0f, 1.0f}; break; - case InputManager::KEY_TEXT_RIGHT: + case InputManager::KEY_GENERIC_RIGHT: moveVec = {1.0f, 0.0f}; break; - case InputManager::KEY_TEXT_LEFT: + case InputManager::KEY_GENERIC_LEFT: moveVec = {-1.0f, 0.0f}; break; } @@ -542,7 +542,7 @@ void DrawingProgramSelection::translate_key(unsigned keyPressed, bool pressed) { selectionTransformCoords = CoordSpaceHelperTransform(translateData.startPos); } else if(transformOpHappening == TransformOperation::TRANSLATE && translateData.translateWithKeys) { - bool anyKeyHeld = drawP.world.main.input.key(InputManager::KEY_TEXT_LEFT).held || drawP.world.main.input.key(InputManager::KEY_TEXT_RIGHT).held || drawP.world.main.input.key(InputManager::KEY_TEXT_DOWN).held || drawP.world.main.input.key(InputManager::KEY_TEXT_UP).held; + bool anyKeyHeld = drawP.world.main.input.key(InputManager::KEY_GENERIC_LEFT).held || drawP.world.main.input.key(InputManager::KEY_GENERIC_RIGHT).held || drawP.world.main.input.key(InputManager::KEY_GENERIC_DOWN).held || drawP.world.main.input.key(InputManager::KEY_GENERIC_UP).held; if(!anyKeyHeld) { commit_transform_selection(); return; diff --git a/src/DrawingProgram/Tools/LassoSelectTool.cpp b/src/DrawingProgram/Tools/LassoSelectTool.cpp index 4d16c65..f0462c3 100644 --- a/src/DrawingProgram/Tools/LassoSelectTool.cpp +++ b/src/DrawingProgram/Tools/LassoSelectTool.cpp @@ -51,7 +51,6 @@ bool LassoSelectTool::right_click_popup_gui(Vector2f popupPos) { } void LassoSelectTool::input_key_callback(const InputManager::KeyCallbackArgs& key) { - drawP.selection.input_key_callback_display_selection(key); drawP.selection.input_key_callback_modify_selection(key); } diff --git a/src/DrawingProgram/Tools/RectSelectTool.cpp b/src/DrawingProgram/Tools/RectSelectTool.cpp index 3b3d54e..de46eb9 100644 --- a/src/DrawingProgram/Tools/RectSelectTool.cpp +++ b/src/DrawingProgram/Tools/RectSelectTool.cpp @@ -25,7 +25,6 @@ void RectSelectTool::gui_toolbox() { } void RectSelectTool::input_key_callback(const InputManager::KeyCallbackArgs& key) { - drawP.selection.input_key_callback_display_selection(key); drawP.selection.input_key_callback_modify_selection(key); } diff --git a/src/InputManager.cpp b/src/InputManager.cpp index 5361fc0..f2c844e 100644 --- a/src/InputManager.cpp +++ b/src/InputManager.cpp @@ -86,14 +86,6 @@ InputManager::InputManager(MainProgram& initMain): keyAssignments = defaultKeyAssignments; } -void InputManager::text_input_silence_everything() { - for(auto& p : keys) { - p.pressed = false; - p.repeat = false; - // Not silencing p.held, as that causes double presses on some keyboards - } -} - void InputManager::set_rich_text_box_input_front(const std::shared_ptr& nTextBox, const std::shared_ptr& nCursor, bool isRichTextBox, const std::optional& nModMap) { text.set_accepting_input(main.window.sdlWindow, true); Text::TextBoxInfo textBoxInfo; @@ -741,6 +733,7 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) { text.do_textbox_operation_with_undo([&]() { textBox->process_key_input(*cursor, RichText::TextBox::InputKey::ENTER, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap); }); + main.input_key_callback(KeyCallbackArgs{.key = KEY_TEXT_ENTER, .down = e.down, .repeat = e.repeat}); break; } case SDLK_TAB: { @@ -752,7 +745,8 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) { break; } case SDLK_ESCAPE: - set_key_down(e, KEY_GENERIC_ESCAPE); + set_key_down(e, KEY_TEXT_ESCAPE); + main.input_key_callback(KeyCallbackArgs{.key = KEY_TEXT_ESCAPE, .down = e.down, .repeat = e.repeat}); break; default: break; @@ -768,16 +762,28 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) { } switch(kPress) { case SDLK_UP: - main.input_key_callback(KeyCallbackArgs{.key = KEY_TEXT_UP, .down = e.down, .repeat = e.repeat}); + set_key_down(e, KEY_GENERIC_UP); + main.input_key_callback(KeyCallbackArgs{.key = KEY_GENERIC_UP, .down = e.down, .repeat = e.repeat}); break; case SDLK_DOWN: - main.input_key_callback(KeyCallbackArgs{.key = KEY_TEXT_DOWN, .down = e.down, .repeat = e.repeat}); + set_key_down(e, KEY_GENERIC_DOWN); + main.input_key_callback(KeyCallbackArgs{.key = KEY_GENERIC_DOWN, .down = e.down, .repeat = e.repeat}); break; case SDLK_LEFT: - main.input_key_callback(KeyCallbackArgs{.key = KEY_TEXT_LEFT, .down = e.down, .repeat = e.repeat}); + set_key_down(e, KEY_GENERIC_LEFT); + main.input_key_callback(KeyCallbackArgs{.key = KEY_GENERIC_LEFT, .down = e.down, .repeat = e.repeat}); break; case SDLK_RIGHT: - main.input_key_callback(KeyCallbackArgs{.key = KEY_TEXT_RIGHT, .down = e.down, .repeat = e.repeat}); + set_key_down(e, KEY_GENERIC_RIGHT); + main.input_key_callback(KeyCallbackArgs{.key = KEY_GENERIC_RIGHT, .down = e.down, .repeat = e.repeat}); + break; + case SDLK_RETURN: + set_key_down(e, KEY_GENERIC_ENTER); + main.input_key_callback(KeyCallbackArgs{.key = KEY_GENERIC_ENTER, .down = e.down, .repeat = e.repeat}); + break; + case SDLK_ESCAPE: + set_key_down(e, KEY_GENERIC_ESCAPE); + main.input_key_callback(KeyCallbackArgs{.key = KEY_GENERIC_ESCAPE, .down = e.down, .repeat = e.repeat}); break; } } @@ -873,12 +879,14 @@ void InputManager::backend_key_up_update(const SDL_KeyboardEvent& e) { break; case SDLK_RETURN: set_key_up(e, KEY_TEXT_ENTER); + main.input_key_callback(KeyCallbackArgs{.key = KEY_TEXT_ENTER, .down = e.down, .repeat = e.repeat}); break; case SDLK_TAB: set_key_up(e, KEY_TEXT_TAB); break; case SDLK_ESCAPE: - set_key_up(e, KEY_GENERIC_ESCAPE); + set_key_up(e, KEY_TEXT_ESCAPE); + main.input_key_callback(KeyCallbackArgs{.key = KEY_TEXT_ESCAPE, .down = e.down, .repeat = e.repeat}); break; default: break; @@ -893,16 +901,28 @@ void InputManager::backend_key_up_update(const SDL_KeyboardEvent& e) { switch(kPress) { case SDLK_UP: - main.input_key_callback(KeyCallbackArgs{.key = KEY_TEXT_UP, .down = e.down, .repeat = e.repeat}); + set_key_up(e, KEY_GENERIC_UP); + main.input_key_callback(KeyCallbackArgs{.key = KEY_GENERIC_UP, .down = e.down, .repeat = e.repeat}); break; case SDLK_DOWN: - main.input_key_callback(KeyCallbackArgs{.key = KEY_TEXT_DOWN, .down = e.down, .repeat = e.repeat}); + set_key_up(e, KEY_GENERIC_DOWN); + main.input_key_callback(KeyCallbackArgs{.key = KEY_GENERIC_DOWN, .down = e.down, .repeat = e.repeat}); break; case SDLK_LEFT: - main.input_key_callback(KeyCallbackArgs{.key = KEY_TEXT_LEFT, .down = e.down, .repeat = e.repeat}); + set_key_up(e, KEY_GENERIC_LEFT); + main.input_key_callback(KeyCallbackArgs{.key = KEY_GENERIC_LEFT, .down = e.down, .repeat = e.repeat}); break; case SDLK_RIGHT: - main.input_key_callback(KeyCallbackArgs{.key = KEY_TEXT_RIGHT, .down = e.down, .repeat = e.repeat}); + set_key_up(e, KEY_GENERIC_RIGHT); + main.input_key_callback(KeyCallbackArgs{.key = KEY_GENERIC_RIGHT, .down = e.down, .repeat = e.repeat}); + break; + case SDLK_RETURN: + set_key_up(e, KEY_GENERIC_ENTER); + main.input_key_callback(KeyCallbackArgs{.key = KEY_GENERIC_ENTER, .down = e.down, .repeat = e.repeat}); + break; + case SDLK_ESCAPE: + set_key_up(e, KEY_GENERIC_ESCAPE); + main.input_key_callback(KeyCallbackArgs{.key = KEY_GENERIC_ESCAPE, .down = e.down, .repeat = e.repeat}); break; } } diff --git a/src/InputManager.hpp b/src/InputManager.hpp index 15cc826..9b47c1e 100644 --- a/src/InputManager.hpp +++ b/src/InputManager.hpp @@ -131,8 +131,6 @@ struct InputManager { int stopKeyInput = 0; std::optional lastPressedKeybind; - void text_input_silence_everything(); - enum KeyCodeEnum : unsigned { // Assignable KEY_CAMERA_ROTATE_CLOCKWISE = 0, @@ -189,6 +187,12 @@ struct InputManager { KEY_TEXT_SELECTALL, KEY_TEXT_UNDO, KEY_TEXT_REDO, + KEY_TEXT_ESCAPE, + KEY_GENERIC_UP, + KEY_GENERIC_DOWN, + KEY_GENERIC_LEFT, + KEY_GENERIC_RIGHT, + KEY_GENERIC_ENTER, KEY_GENERIC_ESCAPE, KEY_GENERIC_LSHIFT, KEY_GENERIC_LALT, diff --git a/src/MainProgram.cpp b/src/MainProgram.cpp index d9c20f6..daaf406 100755 --- a/src/MainProgram.cpp +++ b/src/MainProgram.cpp @@ -92,8 +92,6 @@ void MainProgram::update() { deltaTime.update_time_since(); deltaTime.update_time_point(); - toolbar.initialize_io_before_update(); - for(auto& w : worlds) { if(w == world) w->focus_update(); @@ -103,7 +101,6 @@ void MainProgram::update() { toolbar.update(); // GUI should be setup after the world data has been fully updated for this frame, so that the GUI reflects the current state of the world data - NetLibrary::update(); if(tabSetToOpen) { @@ -328,21 +325,25 @@ void MainProgram::input_key_callback(const InputManager::KeyCallbackArgs& key) { drawGui = !drawGui; } } + toolbar.input_key_callback(key); if(world) world->input_key_callback(key); } void MainProgram::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) { + toolbar.input_mouse_button_callback(button); if(world) world->input_mouse_button_callback(button); } void MainProgram::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) { + toolbar.input_mouse_motion_callback(motion); if(world) world->input_mouse_motion_callback(motion); } void MainProgram::input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel) { + toolbar.input_mouse_wheel_callback(wheel); if(world) world->input_mouse_wheel_callback(wheel); } diff --git a/src/Toolbar.cpp b/src/Toolbar.cpp index d2c97b1..615528e 100644 --- a/src/Toolbar.cpp +++ b/src/Toolbar.cpp @@ -393,17 +393,6 @@ void Toolbar::update() { update_notification_check(); #endif - if(main.input.key(InputManager::KEY_SAVE).pressed && !optionsMenuOpen && !filePicker.isOpen) - save_func(); - if(main.input.key(InputManager::KEY_SAVE_AS).pressed && !optionsMenuOpen && !filePicker.isOpen) - save_as_func(); - if(main.input.key(InputManager::KEY_SHOW_METRICS).pressed) - showPerformance = !showPerformance; - if(main.input.key(InputManager::KEY_OPEN_CHAT).pressed && chatBoxState == CHATBOXSTATE_CLOSE) - chatBoxState = CHATBOXSTATE_JUSTOPEN; - if(main.input.key(InputManager::KEY_SHOW_PLAYER_LIST).pressed) - playerMenuOpen = !playerMenuOpen; - start_gui(); if(main.drawGui) { @@ -2259,30 +2248,126 @@ void Toolbar::file_picker_gui() { } -void Toolbar::initialize_io_before_update() { - io->mouse.leftClick = main.input.mouse.leftClicks; - io->mouse.rightClick = main.input.mouse.rightClicks; - io->mouse.leftHeld = main.input.mouse.leftDown; - io->mouse.rightHeld = main.input.mouse.rightDown; - io->mouse.globalPos = main.input.mouse.pos / final_gui_scale(); - io->mouse.scroll = main.input.mouse.scrollAmount; +void Toolbar::initialize_io() { io->deltaTime = main.deltaTime; - - io->key.left = main.input.key(InputManager::KEY_TEXT_LEFT).repeat; - io->key.right = main.input.key(InputManager::KEY_TEXT_RIGHT).repeat; - io->key.up = main.input.key(InputManager::KEY_TEXT_UP).repeat; - io->key.down = main.input.key(InputManager::KEY_TEXT_DOWN).repeat; io->key.leftShift = main.input.key(InputManager::KEY_TEXT_SHIFT).held; io->key.leftCtrl = main.input.key(InputManager::KEY_TEXT_CTRL).held; - io->key.enter = main.input.key(InputManager::KEY_TEXT_ENTER).repeat; - io->key.escape = main.input.key(InputManager::KEY_GENERIC_ESCAPE).repeat; io->previousRichTextBoxToEdit = io->richTextBoxToEdit; io->richTextBoxToEditCursor = nullptr; io->richTextBoxToEdit = nullptr; +} - if(io->acceptingTextInput) - main.input.text_input_silence_everything(); - io->acceptingTextInput = false; +void Toolbar::end_io() { + if(io->clipboard.textOut) + main.input.set_clipboard_str(*io->clipboard.textOut); + if(io->richTextBoxToEdit != io->previousRichTextBoxToEdit) { + if(io->richTextBoxToEdit) + main.input.set_rich_text_box_input_front(io->richTextBoxToEdit, io->richTextBoxToEditCursor, false); + if(io->previousRichTextBoxToEdit) + main.input.remove_rich_text_box_input(io->previousRichTextBoxToEdit); + } + io->key.left = false; + io->key.right = false; + io->key.up = false; + io->key.down = false; + io->key.enter = false; + io->key.escape = false; + io->mouse.leftClick = 0; + io->mouse.rightClick = 0; + io->mouse.scroll = {0, 0}; +} + +void Toolbar::input_key_callback(const InputManager::KeyCallbackArgs& key) { + if(key.down) { + switch(key.key) { + case InputManager::KEY_TEXT_LEFT: { + io->key.left = true; + break; + } + case InputManager::KEY_TEXT_RIGHT: { + io->key.right = true; + break; + } + case InputManager::KEY_TEXT_UP: { + io->key.up = true; + break; + } + case InputManager::KEY_TEXT_DOWN: { + io->key.down = true; + break; + } + case InputManager::KEY_TEXT_ENTER: { + io->key.enter = true; + break; + } + case InputManager::KEY_TEXT_ESCAPE: { + io->key.escape = true; + break; + } + case InputManager::KEY_SAVE: { + save_func(); + break; + } + case InputManager::KEY_SAVE_AS: { + save_as_func(); + break; + } + case InputManager::KEY_SHOW_METRICS: { + showPerformance = !showPerformance; + break; + } + case InputManager::KEY_OPEN_CHAT: { + if(chatBoxState == CHATBOXSTATE_CLOSE) + chatBoxState = CHATBOXSTATE_JUSTOPEN; + break; + } + case InputManager::KEY_SHOW_PLAYER_LIST: { + playerMenuOpen = !playerMenuOpen; + break; + } + } + } +} + +void Toolbar::input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button) { + if(button.down) { + switch(button.button) { + case InputManager::MouseButton::LEFT: { + io->mouse.leftClick = std::max(io->mouse.leftClick, button.clicks); + io->mouse.leftHeld = true; + break; + } + case InputManager::MouseButton::RIGHT: { + io->mouse.rightClick = std::max(io->mouse.rightClick, button.clicks); + io->mouse.rightHeld = true; + break; + } + default: + break; + } + } + else { + switch(button.button) { + case InputManager::MouseButton::LEFT: { + io->mouse.leftHeld = false; + break; + } + case InputManager::MouseButton::RIGHT: { + io->mouse.rightHeld = false; + break; + } + default: + break; + } + } +} + +void Toolbar::input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) { + io->mouse.globalPos = motion.pos / final_gui_scale(); +} + +void Toolbar::input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel) { + io->mouse.scroll = wheel.amount; } void Toolbar::start_gui() { @@ -2295,6 +2380,7 @@ void Toolbar::start_gui() { gui.windowPos = Vector2f{0.0f, 0.0f}; gui.windowSize = main.window.size.cast() / final_gui_scale(); } + initialize_io(); gui.io = io; io->hoverObstructed = false; io->hoverObstructingAABBs.clear(); @@ -2328,14 +2414,7 @@ float Toolbar::final_gui_scale_not_fit() { void Toolbar::end_gui() { gui.end(); - if(io->clipboard.textOut) - main.input.set_clipboard_str(*io->clipboard.textOut); - if(io->richTextBoxToEdit != io->previousRichTextBoxToEdit) { - if(io->richTextBoxToEdit) - main.input.set_rich_text_box_input_front(io->richTextBoxToEdit, io->richTextBoxToEditCursor, false); - if(io->previousRichTextBoxToEdit) - main.input.remove_rich_text_box_input(io->previousRichTextBoxToEdit); - } + end_io(); } void Toolbar::draw(SkCanvas* canvas) { diff --git a/src/Toolbar.hpp b/src/Toolbar.hpp index 805523a..807ca93 100644 --- a/src/Toolbar.hpp +++ b/src/Toolbar.hpp @@ -40,7 +40,10 @@ class Toolbar { std::string chatMessageInput; Toolbar(MainProgram& initMain); - void initialize_io_before_update(); + void input_key_callback(const InputManager::KeyCallbackArgs& key); + void input_mouse_button_callback(const InputManager::MouseButtonCallbackArgs& button); + void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion); + void input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel); void update(); void draw(SkCanvas* canvas); void color_selector_left(Vector4f* color); @@ -94,6 +97,8 @@ class Toolbar { bool app_close_requested(); private: + void end_io(); + void initialize_io(); void calculate_final_gui_scale(); float final_gui_scale_not_fit(); diff --git a/src/main.cpp b/src/main.cpp index 795e76f..9c0294a 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -210,7 +210,7 @@ void initialize_sdl(MainStruct& mS, int wWidth, int wHeight) { SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); SDL_SetHint(SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT, "#canvas"); // Ensures that SDL only grabs input when browser is focused on canvas - if(!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) + if(!SDL_Init(SDL_INIT_VIDEO)) throw std::runtime_error("[SDL_Init] " + std::string(SDL_GetError())); Uint32 window_flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY;