diff --git a/src/DrawCamera.cpp b/src/DrawCamera.cpp index 90fb47d..61b68a3 100755 --- a/src/DrawCamera.cpp +++ b/src/DrawCamera.cpp @@ -158,10 +158,10 @@ void DrawCamera::update_main(World& w) { } } } - if(w.main.input.key(InputManager::KEY_CAMERA_ROTATE_COUNTERCLOCKWISE).held && !w.main.input.text.get_accepting_input()) { + if(w.main.input.key(InputManager::KEY_CAMERA_ROTATE_COUNTERCLOCKWISE).held && !w.main.input.text.is_accepting_input()) { c.rotate_about(c.from_space(w.main.window.size.cast() * 0.5f), -w.main.deltaTime); } - if(w.main.input.key(InputManager::KEY_CAMERA_ROTATE_CLOCKWISE).held && !w.main.input.text.get_accepting_input()) { + if(w.main.input.key(InputManager::KEY_CAMERA_ROTATE_CLOCKWISE).held && !w.main.input.text.is_accepting_input()) { c.rotate_about(c.from_space(w.main.window.size.cast() * 0.5f), w.main.deltaTime); } } diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index c4dc0d6..12b3eae 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -46,55 +46,55 @@ DrawingProgram::DrawingProgram(World& initWorld): } void DrawingProgram::register_callbacks() { - keyCallbacks[InputManager::KEY_DRAW_TOOL_BRUSH] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_BRUSH].register_callback([&](auto& key) { + world.keyCallbacks[InputManager::KEY_DRAW_TOOL_BRUSH] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_BRUSH].register_callback([&](auto& key) { if(key.down && !key.repeat) switch_to_tool(DrawingProgramToolType::BRUSH); }); - keyCallbacks[InputManager::KEY_DRAW_TOOL_ERASER] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_ERASER].register_callback([&](auto& key) { + world.keyCallbacks[InputManager::KEY_DRAW_TOOL_ERASER] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_ERASER].register_callback([&](auto& key) { if(key.down && !key.repeat) switch_to_tool(DrawingProgramToolType::ERASER); }); - keyCallbacks[InputManager::KEY_DRAW_TOOL_RECTSELECT] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_RECTSELECT].register_callback([&](auto& key) { + world.keyCallbacks[InputManager::KEY_DRAW_TOOL_RECTSELECT] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_RECTSELECT].register_callback([&](auto& key) { if(key.down && !key.repeat) switch_to_tool(DrawingProgramToolType::RECTSELECT); }); - keyCallbacks[InputManager::KEY_DRAW_TOOL_RECTANGLE] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_RECTANGLE].register_callback([&](auto& key) { + world.keyCallbacks[InputManager::KEY_DRAW_TOOL_RECTANGLE] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_RECTANGLE].register_callback([&](auto& key) { if(key.down && !key.repeat) switch_to_tool(DrawingProgramToolType::RECTANGLE); }); - keyCallbacks[InputManager::KEY_DRAW_TOOL_ELLIPSE] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_ELLIPSE].register_callback([&](auto& key) { + world.keyCallbacks[InputManager::KEY_DRAW_TOOL_ELLIPSE] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_ELLIPSE].register_callback([&](auto& key) { if(key.down && !key.repeat) switch_to_tool(DrawingProgramToolType::ELLIPSE); }); - keyCallbacks[InputManager::KEY_DRAW_TOOL_TEXTBOX] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_TEXTBOX].register_callback([&](auto& key) { + world.keyCallbacks[InputManager::KEY_DRAW_TOOL_TEXTBOX] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_TEXTBOX].register_callback([&](auto& key) { if(key.down && !key.repeat) switch_to_tool(DrawingProgramToolType::TEXTBOX); }); - keyCallbacks[InputManager::KEY_DRAW_TOOL_EYEDROPPER] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_EYEDROPPER].register_callback([&](auto& key) { + world.keyCallbacks[InputManager::KEY_DRAW_TOOL_EYEDROPPER] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_EYEDROPPER].register_callback([&](auto& key) { if(key.down && !key.repeat) switch_to_tool(DrawingProgramToolType::EYEDROPPER); }); - keyCallbacks[InputManager::KEY_DRAW_TOOL_SCREENSHOT] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_SCREENSHOT].register_callback([&](auto& key) { + world.keyCallbacks[InputManager::KEY_DRAW_TOOL_SCREENSHOT] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_SCREENSHOT].register_callback([&](auto& key) { if(key.down && !key.repeat) switch_to_tool(DrawingProgramToolType::SCREENSHOT); }); - keyCallbacks[InputManager::KEY_DRAW_TOOL_ZOOM] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_ZOOM].register_callback([&](auto& key) { + world.keyCallbacks[InputManager::KEY_DRAW_TOOL_ZOOM] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_ZOOM].register_callback([&](auto& key) { if(key.down && !key.repeat) switch_to_tool(DrawingProgramToolType::ZOOM); }); - keyCallbacks[InputManager::KEY_DRAW_TOOL_LASSOSELECT] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_LASSOSELECT].register_callback([&](auto& key) { + world.keyCallbacks[InputManager::KEY_DRAW_TOOL_LASSOSELECT] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_LASSOSELECT].register_callback([&](auto& key) { if(key.down && !key.repeat) switch_to_tool(DrawingProgramToolType::LASSOSELECT); }); - keyCallbacks[InputManager::KEY_DRAW_TOOL_PAN] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_PAN].register_callback([&](auto& key) { + world.keyCallbacks[InputManager::KEY_DRAW_TOOL_PAN] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_PAN].register_callback([&](auto& key) { if(key.down && !key.repeat) switch_to_tool(DrawingProgramToolType::PAN); }); - keyCallbacks[InputManager::KEY_DRAW_TOOL_LINE] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_LINE].register_callback([&](auto& key) { + world.keyCallbacks[InputManager::KEY_DRAW_TOOL_LINE] = world.main.input.keyCallbacks[InputManager::KEY_DRAW_TOOL_LINE].register_callback([&](auto& key) { if(key.down && !key.repeat) switch_to_tool(DrawingProgramToolType::LINE); }); - keyCallbacks[InputManager::KEY_HOLD_TO_PAN] = world.main.input.keyCallbacks[InputManager::KEY_HOLD_TO_PAN].register_callback([&](auto& key) { + world.keyCallbacks[InputManager::KEY_HOLD_TO_PAN] = world.main.input.keyCallbacks[InputManager::KEY_HOLD_TO_PAN].register_callback([&](auto& key) { if(key.down && !key.repeat && tempMoveToolSwitch == TemporaryMoveToolSwitch::NONE) { toolTypeAfterTempMove = drawTool->get_type(); switch_to_tool(DrawingProgramToolType::PAN); @@ -105,7 +105,7 @@ void DrawingProgram::register_callbacks() { tempMoveToolSwitch = TemporaryMoveToolSwitch::NONE; } }); - keyCallbacks[InputManager::KEY_HOLD_TO_ZOOM] = world.main.input.keyCallbacks[InputManager::KEY_HOLD_TO_ZOOM].register_callback([&](auto& key) { + world.keyCallbacks[InputManager::KEY_HOLD_TO_ZOOM] = world.main.input.keyCallbacks[InputManager::KEY_HOLD_TO_ZOOM].register_callback([&](auto& key) { if(key.down && !key.repeat && tempMoveToolSwitch == TemporaryMoveToolSwitch::NONE) { toolTypeAfterTempMove = drawTool->get_type(); switch_to_tool(DrawingProgramToolType::ZOOM); @@ -120,10 +120,8 @@ void DrawingProgram::register_callbacks() { } void DrawingProgram::deregister_callbacks() { - for(auto& [key, callback] : keyCallbacks) - world.main.input.keyCallbacks[key].deregister_callback(callback); - keyCallbacks.clear(); tempMoveToolSwitch = TemporaryMoveToolSwitch::NONE; + selection.deselect_all(); } void DrawingProgram::server_init_no_file() { diff --git a/src/DrawingProgram/DrawingProgram.hpp b/src/DrawingProgram/DrawingProgram.hpp index ce994b5..bb05b45 100644 --- a/src/DrawingProgram/DrawingProgram.hpp +++ b/src/DrawingProgram/DrawingProgram.hpp @@ -125,8 +125,6 @@ class DrawingProgram { uint32_t nextID = 0; - std::unordered_map keyCallbacks; - friend class EyeDropperTool; friend class RectDrawTool; friend class EllipseDrawTool; diff --git a/src/DrawingProgram/DrawingProgramSelection.cpp b/src/DrawingProgram/DrawingProgramSelection.cpp index 00e50d7..97434de 100644 --- a/src/DrawingProgram/DrawingProgramSelection.cpp +++ b/src/DrawingProgram/DrawingProgramSelection.cpp @@ -353,19 +353,8 @@ void DrawingProgramSelection::commit_transform_selection() { void DrawingProgramSelection::update() { if(is_something_selected()) { - selectionRectPoints[0] = selectionTransformCoords.from_space_world(initialSelectionAABB.min); - selectionRectPoints[1] = selectionTransformCoords.from_space_world(initialSelectionAABB.bottom_left()); - selectionRectPoints[2] = selectionTransformCoords.from_space_world(initialSelectionAABB.max); - selectionRectPoints[3] = selectionTransformCoords.from_space_world(initialSelectionAABB.top_right()); - - scaleData.handlePoint = drawP.world.drawData.cam.c.to_space(initialSelectionAABB.max); - rotateData.centerHandlePoint = drawP.world.drawData.cam.c.to_space(rotateData.centerPos); - rotateData.handlePoint = get_rotation_point_pos_from_angle(rotateData.rotationAngle); - rebuild_cam_space(); - constexpr float KEY_TRANSLATE_MAGNITUDE = 5.0f; - if(drawP.is_actual_selection_tool(drawP.drawTool->get_type())) { switch(transformOpHappening) { case TransformOperation::NONE: @@ -392,53 +381,9 @@ void DrawingProgramSelection::update() { check_add_stroke_color_change_undo(); } } - else { - Vector2f moveVec = {0, 0}; - if(drawP.world.main.input.key(InputManager::KEY_TEXT_UP).pressed) - moveVec.y() -= 1.0f; - if(drawP.world.main.input.key(InputManager::KEY_TEXT_DOWN).pressed) - moveVec.y() += 1.0f; - if(drawP.world.main.input.key(InputManager::KEY_TEXT_RIGHT).pressed) - moveVec.x() += 1.0f; - if(drawP.world.main.input.key(InputManager::KEY_TEXT_LEFT).pressed) - moveVec.x() -= 1.0f; - if(moveVec != Vector2f{0.0f, 0.0f}) { - moveVec *= KEY_TRANSLATE_MAGNITUDE; - translateData.startPos = drawP.world.drawData.cam.c.dir_from_space(moveVec); - translateData.translateWithKeys = true; - selectionTransformCoords = CoordSpaceHelperTransform(translateData.startPos); - transformOpHappening = TransformOperation::TRANSLATE; - translateData.keyTranslateLastMoveTime = std::chrono::steady_clock::now(); - check_add_stroke_color_change_undo(); - } - } break; case TransformOperation::TRANSLATE: - if(translateData.translateWithKeys) { - Vector2f moveVec = {0, 0}; - constexpr auto TIME_TO_NEXT_MOVE = std::chrono::milliseconds(700); - constexpr auto TIME_TO_SUBTRACT_BETWEEN_REPEATS = std::chrono::milliseconds(650); - if(drawP.world.main.input.key(InputManager::KEY_TEXT_UP).held) - moveVec.y() -= 1.0f; - if(drawP.world.main.input.key(InputManager::KEY_TEXT_DOWN).held) - moveVec.y() += 1.0f; - if(drawP.world.main.input.key(InputManager::KEY_TEXT_RIGHT).held) - moveVec.x() += 1.0f; - if(drawP.world.main.input.key(InputManager::KEY_TEXT_LEFT).held) - moveVec.x() -= 1.0f; - if(moveVec != Vector2f{0.0f, 0.0f} && (std::chrono::steady_clock::now() - translateData.keyTranslateLastMoveTime) >= TIME_TO_NEXT_MOVE) { - moveVec *= KEY_TRANSLATE_MAGNITUDE; - translateData.startPos += drawP.world.drawData.cam.c.dir_from_space(moveVec); - selectionTransformCoords = CoordSpaceHelperTransform(translateData.startPos); - translateData.keyTranslateLastMoveTime = std::chrono::steady_clock::now() - TIME_TO_SUBTRACT_BETWEEN_REPEATS; // Time between repeat moves is shorter than time between first press and first repeat - } - 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; - if(!anyKeyHeld) { - commit_transform_selection(); - return; - } - } - else { + if(!translateData.translateWithKeys) { if(drawP.controls.leftClickHeld) selectionTransformCoords = CoordSpaceHelperTransform(drawP.world.get_mouse_world_pos() - translateData.startPos); else { @@ -498,33 +443,34 @@ void DrawingProgramSelection::update() { } void DrawingProgramSelection::register_key_callbacks() { - drawP.keyCallbacks[InputManager::KEY_DRAW_DELETE] = drawP.world.main.input.keyCallbacks[InputManager::KEY_DRAW_DELETE].register_callback([&](auto& key) { + auto& keyCallbacks = drawP.world.keyCallbacks; + keyCallbacks[InputManager::KEY_DRAW_DELETE] = drawP.world.main.input.keyCallbacks[InputManager::KEY_DRAW_DELETE].register_callback([&](auto& key) { if(key.down && !key.repeat) delete_all(); }); - drawP.keyCallbacks[InputManager::KEY_COPY] = drawP.world.main.input.keyCallbacks[InputManager::KEY_COPY].register_callback([&](auto& key) { + keyCallbacks[InputManager::KEY_COPY] = drawP.world.main.input.keyCallbacks[InputManager::KEY_COPY].register_callback([&](auto& key) { if(key.down && !key.repeat) selection_to_clipboard(); }); - drawP.keyCallbacks[InputManager::KEY_CUT] = drawP.world.main.input.keyCallbacks[InputManager::KEY_CUT].register_callback([&](auto& key) { + keyCallbacks[InputManager::KEY_CUT] = drawP.world.main.input.keyCallbacks[InputManager::KEY_CUT].register_callback([&](auto& key) { if(key.down && !key.repeat) { selection_to_clipboard(); delete_all(); } }); - drawP.keyCallbacks[InputManager::KEY_PASTE] = drawP.world.main.input.keyCallbacks[InputManager::KEY_PASTE].register_callback([&](auto& key) { + keyCallbacks[InputManager::KEY_PASTE] = drawP.world.main.input.keyCallbacks[InputManager::KEY_PASTE].register_callback([&](auto& key) { if(key.down && !key.repeat) { deselect_all(); paste_clipboard(drawP.world.main.input.mouse.pos); } }); - drawP.keyCallbacks[InputManager::KEY_PASTE_IMAGE] = drawP.world.main.input.keyCallbacks[InputManager::KEY_PASTE_IMAGE].register_callback([&](auto& key) { + keyCallbacks[InputManager::KEY_PASTE_IMAGE] = drawP.world.main.input.keyCallbacks[InputManager::KEY_PASTE_IMAGE].register_callback([&](auto& key) { if(key.down && !key.repeat) { deselect_all(); paste_image(drawP.world.main.input.mouse.pos); } }); - drawP.keyCallbacks[InputManager::KEY_DESELECT_AND_EDIT_TOOL] = drawP.world.main.input.keyCallbacks[InputManager::KEY_DESELECT_AND_EDIT_TOOL].register_callback([&](auto& key) { + keyCallbacks[InputManager::KEY_DESELECT_AND_EDIT_TOOL] = drawP.world.main.input.keyCallbacks[InputManager::KEY_DESELECT_AND_EDIT_TOOL].register_callback([&](auto& key) { if(key.down && !key.repeat) { if(is_something_selected()) deselect_all(); @@ -532,6 +478,58 @@ void DrawingProgramSelection::register_key_callbacks() { drawP.switch_to_tool(DrawingProgramToolType::EDIT, true); } }); + keyCallbacks[InputManager::KEY_TEXT_UP] = drawP.world.main.input.keyCallbacks[InputManager::KEY_TEXT_UP].register_callback([&](auto& key) { + translate_key(InputManager::KEY_TEXT_UP, key.down); + }); + keyCallbacks[InputManager::KEY_TEXT_DOWN] = drawP.world.main.input.keyCallbacks[InputManager::KEY_TEXT_DOWN].register_callback([&](auto& key) { + translate_key(InputManager::KEY_TEXT_DOWN, key.down); + }); + keyCallbacks[InputManager::KEY_TEXT_LEFT] = drawP.world.main.input.keyCallbacks[InputManager::KEY_TEXT_LEFT].register_callback([&](auto& key) { + translate_key(InputManager::KEY_TEXT_LEFT, key.down); + }); + keyCallbacks[InputManager::KEY_TEXT_RIGHT] = drawP.world.main.input.keyCallbacks[InputManager::KEY_TEXT_RIGHT].register_callback([&](auto& key) { + translate_key(InputManager::KEY_TEXT_RIGHT, key.down); + }); +} + +void DrawingProgramSelection::translate_key(unsigned keyPressed, bool pressed) { + if(pressed) { + constexpr float KEY_TRANSLATE_MAGNITUDE = 5.0f; + Vector2f moveVec; + switch(keyPressed) { + case InputManager::KEY_TEXT_UP: + moveVec = {0.0f, -1.0f}; + break; + case InputManager::KEY_TEXT_DOWN: + moveVec = {0.0f, 1.0f}; + break; + case InputManager::KEY_TEXT_RIGHT: + moveVec = {1.0f, 0.0f}; + break; + case InputManager::KEY_TEXT_LEFT: + moveVec = {-1.0f, 0.0f}; + break; + } + moveVec *= KEY_TRANSLATE_MAGNITUDE; + if(transformOpHappening == TransformOperation::NONE) { + translateData.startPos = drawP.world.drawData.cam.c.dir_from_space(moveVec); + translateData.translateWithKeys = true; + transformOpHappening = TransformOperation::TRANSLATE; + check_add_stroke_color_change_undo(); + } + else if(transformOpHappening == TransformOperation::TRANSLATE && translateData.translateWithKeys) { + moveVec *= KEY_TRANSLATE_MAGNITUDE; + translateData.startPos += drawP.world.drawData.cam.c.dir_from_space(moveVec); + } + 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; + if(!anyKeyHeld) { + commit_transform_selection(); + return; + } + } } void DrawingProgramSelection::deselect_all() { @@ -700,6 +698,15 @@ std::unordered_set DrawingProgramSelection:: } void DrawingProgramSelection::rebuild_cam_space() { + selectionRectPoints[0] = selectionTransformCoords.from_space_world(initialSelectionAABB.min); + selectionRectPoints[1] = selectionTransformCoords.from_space_world(initialSelectionAABB.bottom_left()); + selectionRectPoints[2] = selectionTransformCoords.from_space_world(initialSelectionAABB.max); + selectionRectPoints[3] = selectionTransformCoords.from_space_world(initialSelectionAABB.top_right()); + + scaleData.handlePoint = drawP.world.drawData.cam.c.to_space(initialSelectionAABB.max); + rotateData.centerHandlePoint = drawP.world.drawData.cam.c.to_space(rotateData.centerPos); + rotateData.handlePoint = get_rotation_point_pos_from_angle(rotateData.rotationAngle); + SCollision::ColliderCollection collideRectWorld; collideRectWorld.triangle.emplace_back(selectionRectPoints[0], selectionRectPoints[1], selectionRectPoints[2]); collideRectWorld.triangle.emplace_back(selectionRectPoints[0], selectionRectPoints[2], selectionRectPoints[3]); @@ -714,15 +721,6 @@ Vector2f DrawingProgramSelection::get_rotation_point_pos_from_angle(double angle void DrawingProgramSelection::draw_components(SkCanvas* canvas, const DrawData& drawData) { if(is_something_selected()) { - selectionRectPoints[0] = selectionTransformCoords.from_space_world(initialSelectionAABB.min); - selectionRectPoints[1] = selectionTransformCoords.from_space_world(initialSelectionAABB.bottom_left()); - selectionRectPoints[2] = selectionTransformCoords.from_space_world(initialSelectionAABB.max); - selectionRectPoints[3] = selectionTransformCoords.from_space_world(initialSelectionAABB.top_right()); - - scaleData.handlePoint = drawP.world.drawData.cam.c.to_space(selectionTransformCoords.from_space_world(initialSelectionAABB.max)); - rotateData.centerHandlePoint = drawP.world.drawData.cam.c.to_space(selectionTransformCoords.from_space_world(rotateData.centerPos)); - rotateData.handlePoint = get_rotation_point_pos_from_angle(rotateData.rotationAngle); - rebuild_cam_space(); DrawData selectionDrawData = drawData; diff --git a/src/DrawingProgram/DrawingProgramSelection.hpp b/src/DrawingProgram/DrawingProgramSelection.hpp index c00a356..00fc278 100644 --- a/src/DrawingProgram/DrawingProgramSelection.hpp +++ b/src/DrawingProgram/DrawingProgramSelection.hpp @@ -30,6 +30,7 @@ class DrawingProgramSelection { CanvasComponentContainer::ObjInfo* get_front_object_colliding_with_in_editing_layer(const SCollision::ColliderCollection& cC); void register_key_callbacks(); private: + void translate_key(unsigned keyPressed, bool pressed); bool mouse_collided_with_selection_aabb(); bool mouse_collided_with_scale_point(); bool mouse_collided_with_rotate_center_handle_point(); @@ -75,7 +76,6 @@ class DrawingProgramSelection { struct TranslationData { WorldVec startPos; bool translateWithKeys; - std::chrono::steady_clock::time_point keyTranslateLastMoveTime; } translateData; struct ScaleData { diff --git a/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.cpp b/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.cpp index 90f6ff4..de99299 100644 --- a/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.cpp +++ b/src/DrawingProgram/Tools/EditTools/TextBoxEditTool.cpp @@ -295,7 +295,7 @@ bool TextBoxEditTool::edit_update(CanvasComponentContainer::ObjInfo* comp) { bool collidesWithBox = comp->obj->collides_with_cam_coords(drawP.world.drawData.cam.c, mousePointCollection); - input.text.set_rich_text_box_input(a.textBox, a.cursor, true, currentMods); + //input.text.set_rich_text_box_input_back(a.textBox, a.cursor, true, currentMods); a.textBox->process_mouse_left_button(*a.cursor, a.get_mouse_pos(drawP), (drawP.controls.leftClick && collidesWithBox) ? drawP.world.main.input.mouse.leftClicks : 0, drawP.controls.leftClickHeld, input.key(InputManager::KEY_GENERIC_LSHIFT).held); return true; diff --git a/src/GUIStuff/Elements/Element.hpp b/src/GUIStuff/Elements/Element.hpp index 5647604..e6fc8e8 100644 --- a/src/GUIStuff/Elements/Element.hpp +++ b/src/GUIStuff/Elements/Element.hpp @@ -94,7 +94,9 @@ struct UpdateInputData { std::optional textOut; } clipboard; - std::function, std::shared_ptr)> richTextBoxEdit; + std::shared_ptr previousRichTextBoxToEdit; + std::shared_ptr richTextBoxToEdit; + std::shared_ptr richTextBoxToEditCursor; SkFont get_font(float fSize) const; diff --git a/src/GUIStuff/Elements/TextBox.hpp b/src/GUIStuff/Elements/TextBox.hpp index e4d52cc..0563868 100644 --- a/src/GUIStuff/Elements/TextBox.hpp +++ b/src/GUIStuff/Elements/TextBox.hpp @@ -31,7 +31,8 @@ template class TextBox : public Element { }) { selection.update(Clay_Hovered(), io.mouse.leftClick, io.mouse.leftHeld); if(data && selection.selected) { - io.richTextBoxEdit(textbox, cur); + io.richTextBoxToEdit = textbox; + io.richTextBoxToEditCursor = cur; textbox->process_mouse_left_button(*cur, io.mouse.pos - bb.min, io.mouse.leftClick, io.mouse.leftHeld, io.key.leftShift); if((updateEveryEdit && textbox->inputChangedTextBox) || io.key.enter) { update_on_edit(); diff --git a/src/InputManager.cpp b/src/InputManager.cpp index e30ba6d..09cb093 100644 --- a/src/InputManager.cpp +++ b/src/InputManager.cpp @@ -1,6 +1,7 @@ #include "InputManager.hpp" #include +#include #include #include @@ -83,47 +84,60 @@ InputManager::InputManager() { } void InputManager::text_input_silence_everything() { - text.set_accepting_input(); for(auto& p : keys) { p.pressed = false; p.repeat = false; // Not silencing p.held, as that causes double presses on some keyboards } - text.newInput.clear(); } -void InputManager::Text::set_rich_text_box_input(const std::shared_ptr& nTextBox, const std::shared_ptr& nCursor, bool isRichTextBox, const std::optional& nModMap) { - set_accepting_input(); - newTextBox = nTextBox; - newCursor = nCursor; - newModMap = nModMap; - newIsRichTextBox = isRichTextBox; +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(sdlWindow, true); + Text::TextBoxInfo textBoxInfo; + textBoxInfo.textBox = nTextBox; + textBoxInfo.cursor = nCursor; + textBoxInfo.modMap = nModMap; + textBoxInfo.isRichTextBox = isRichTextBox; + text.textBoxes.emplace_front(textBoxInfo); +} + +void InputManager::set_rich_text_box_input_back(const std::shared_ptr& nTextBox, const std::shared_ptr& nCursor, bool isRichTextBox, const std::optional& nModMap) { + text.set_accepting_input(sdlWindow, true); + Text::TextBoxInfo textBoxInfo; + textBoxInfo.textBox = nTextBox; + textBoxInfo.cursor = nCursor; + textBoxInfo.modMap = nModMap; + textBoxInfo.isRichTextBox = isRichTextBox; + text.textBoxes.emplace_back(textBoxInfo); +} + +void InputManager::remove_rich_text_box_input(const std::shared_ptr& nTextBox) { + std::erase_if(text.textBoxes, [&nTextBox](Text::TextBoxInfo& info) { + return (info.textBox == nTextBox); + }); + if(text.textBoxes.empty()) + text.set_accepting_input(sdlWindow, false); } void InputManager::Text::add_text_to_textbox(const std::string& inputText) { - if(textBox && !inputText.empty()) + if(!textBoxes.empty() && !inputText.empty()) { + auto& frontTextBox = textBoxes.front(); do_textbox_operation_with_undo([&]() { - textBox->process_text_input(*cursor, inputText, modMap); + frontTextBox.textBox->process_text_input(*frontTextBox.cursor, inputText, frontTextBox.modMap); }); -} - -void InputManager::Text::set_accepting_input() { - acceptingInputNew = true; -} - -bool InputManager::Text::get_accepting_input() { - return acceptingInput; + } } void InputManager::Text::add_textbox_undo(const RichText::TextBox::Cursor& prevCursor, const RichText::TextData& prevRichText) { - if(textBox) { - textboxUndo.push({[textBox = textBox, cursor = cursor, prevCursor = prevCursor, prevRichText = prevRichText]() { + if(!textBoxes.empty()) { + auto& frontTextBox = textBoxes.front(); + frontTextBox.textboxUndo.push({[textBox = frontTextBox.textBox, cursor = frontTextBox.cursor, prevCursor = prevCursor, prevRichText = prevRichText]() { textBox->set_rich_text_data(prevRichText); cursor->selectionBeginPos = cursor->selectionEndPos = cursor->pos = std::max(prevCursor.selectionEndPos, prevCursor.selectionBeginPos); cursor->previousX = std::nullopt; return true; }, - [textBox = textBox, cursor = cursor, currentCursor = *cursor, currentRichText = textBox->get_rich_text_data()]() { + [textBox = frontTextBox.textBox, cursor = frontTextBox.cursor, currentCursor = *frontTextBox.cursor, currentRichText = frontTextBox.textBox->get_rich_text_data()]() { textBox->set_rich_text_data(currentRichText); cursor->selectionBeginPos = cursor->selectionEndPos = cursor->pos = std::max(currentCursor.selectionEndPos, currentCursor.selectionBeginPos); cursor->previousX = std::nullopt; @@ -133,14 +147,30 @@ void InputManager::Text::add_textbox_undo(const RichText::TextBox::Cursor& prevC } void InputManager::Text::do_textbox_operation_with_undo(const std::function& func) { - if(textBox) { - auto prevRichText = textBox->get_rich_text_data(); - auto prevCursor = *cursor; + if(!textBoxes.empty()) { + auto& frontTextBox = textBoxes.front(); + auto prevRichText = frontTextBox.textBox->get_rich_text_data(); + auto prevCursor = *frontTextBox.cursor; func(); add_textbox_undo(prevCursor, prevRichText); } } +bool InputManager::Text::is_accepting_input() { + return acceptingInput; +} + +void InputManager::Text::set_accepting_input(SDL_Window* window, bool newAcceptingInputVal) { + if(!acceptingInput && newAcceptingInputVal) { + SDL_StartTextInput(window); + acceptingInput = true; + } + else if(acceptingInput && !newAcceptingInputVal) { + SDL_StopTextInput(window); + acceptingInput = false; + } +} + std::string InputManager::get_clipboard_str_SDL() { char* data = SDL_GetClipboardText(); std::string toRet(data); @@ -356,55 +386,59 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) { // e.key != SDLK_LMETA && e.key != SDLK_RMETA && - if(stopKeyInput && !e.down) + if(stopKeyInput) return; sdlKeyCallbacks.run_callbacks(e); + std::shared_ptr textBox = text.textBoxes.empty() ? nullptr : text.textBoxes.front().textBox; + std::shared_ptr cursor = text.textBoxes.empty() ? nullptr : text.textBoxes.front().cursor; + std::optional modMap = text.textBoxes.empty() ? std::nullopt : text.textBoxes.front().modMap; + switch(kPress) { case SDLK_UP: set_key_down(e, KEY_TEXT_UP); - if(text.textBox && key(KEY_TEXT_UP).repeat) - text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::UP, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + if(textBox && key(KEY_TEXT_UP).repeat) + textBox->process_key_input(*cursor, RichText::TextBox::InputKey::UP, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap); break; case SDLK_DOWN: set_key_down(e, KEY_TEXT_DOWN); - if(text.textBox && key(KEY_TEXT_DOWN).repeat) - text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::DOWN, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + if(textBox && key(KEY_TEXT_DOWN).repeat) + textBox->process_key_input(*cursor, RichText::TextBox::InputKey::DOWN, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap); break; case SDLK_LEFT: set_key_down(e, KEY_TEXT_LEFT); - if(text.textBox && key(KEY_TEXT_LEFT).repeat) - text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::LEFT, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + if(textBox && key(KEY_TEXT_LEFT).repeat) + textBox->process_key_input(*cursor, RichText::TextBox::InputKey::LEFT, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap); break; case SDLK_RIGHT: set_key_down(e, KEY_TEXT_RIGHT); - if(text.textBox && key(KEY_TEXT_RIGHT).repeat) - text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::RIGHT, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + if(textBox && key(KEY_TEXT_RIGHT).repeat) + textBox->process_key_input(*cursor, RichText::TextBox::InputKey::RIGHT, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap); break; case SDLK_BACKSPACE: set_key_down(e, KEY_TEXT_BACKSPACE); - if(text.textBox && key(KEY_TEXT_BACKSPACE).repeat) + if(textBox && key(KEY_TEXT_BACKSPACE).repeat) text.do_textbox_operation_with_undo([&]() { - text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::BACKSPACE, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + textBox->process_key_input(*cursor, RichText::TextBox::InputKey::BACKSPACE, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap); }); break; case SDLK_DELETE: set_key_down(e, KEY_TEXT_DELETE); - if(text.textBox && key(KEY_TEXT_DELETE).repeat) + if(textBox && key(KEY_TEXT_DELETE).repeat) text.do_textbox_operation_with_undo([&]() { - text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::DEL, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + textBox->process_key_input(*cursor, RichText::TextBox::InputKey::DEL, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap); }); break; case SDLK_HOME: set_key_down(e, KEY_TEXT_HOME); - if(text.textBox && key(KEY_TEXT_HOME).repeat) - text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::HOME, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + if(textBox && key(KEY_TEXT_HOME).repeat) + textBox->process_key_input(*cursor, RichText::TextBox::InputKey::HOME, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap); break; case SDLK_END: set_key_down(e, KEY_TEXT_END); - if(text.textBox && key(KEY_TEXT_END).repeat) - text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::END, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + if(textBox && key(KEY_TEXT_END).repeat) + textBox->process_key_input(*cursor, RichText::TextBox::InputKey::END, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap); break; case SDLK_LSHIFT: set_key_down(e, KEY_TEXT_SHIFT); @@ -425,21 +459,21 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) { // Use either Ctrl or Meta (command for Mac) keys. We do either instead of checking, since checking can get complicated on Emscripten if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL)) set_key_down(e, KEY_TEXT_COPY); - if(text.textBox && key(KEY_TEXT_COPY).repeat) - set_clipboard_plain_and_richtext_pair(text.textBox->process_copy(*text.cursor)); + if(textBox && key(KEY_TEXT_COPY).repeat) + set_clipboard_plain_and_richtext_pair(textBox->process_copy(*cursor)); break; case SDLK_X: if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL)) set_key_down(e, KEY_TEXT_CUT); - if(text.textBox && key(KEY_TEXT_CUT).repeat) + if(textBox && key(KEY_TEXT_CUT).repeat) text.do_textbox_operation_with_undo([&]() { - set_clipboard_plain_and_richtext_pair(text.textBox->process_cut(*text.cursor)); + set_clipboard_plain_and_richtext_pair(textBox->process_cut(*cursor)); }); break; case SDLK_V: if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL)) set_key_down(e, KEY_TEXT_PASTE); - if(text.textBox && key(KEY_TEXT_PASTE).repeat) + if(textBox && key(KEY_TEXT_PASTE).repeat) text.do_textbox_operation_with_undo([&]() { call_text_paste(true); }); @@ -447,34 +481,34 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) { case SDLK_A: if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL)) set_key_down(e, KEY_TEXT_SELECTALL); - if(text.textBox && key(KEY_TEXT_SELECTALL).repeat) - text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::SELECT_ALL, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + if(textBox && key(KEY_TEXT_SELECTALL).repeat) + textBox->process_key_input(*cursor, RichText::TextBox::InputKey::SELECT_ALL, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap); break; case SDLK_Z: if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL)) set_key_down(e, KEY_TEXT_UNDO); - if(text.textBox && key(KEY_TEXT_UNDO).repeat) - text.textboxUndo.undo(); + if(textBox && key(KEY_TEXT_UNDO).repeat) + text.textBoxes.front().textboxUndo.undo(); break; case SDLK_R: if((kMod & SDL_KMOD_GUI) || (kMod & SDL_KMOD_CTRL)) set_key_down(e, KEY_TEXT_REDO); - if(text.textBox && key(KEY_TEXT_REDO).repeat) - text.textboxUndo.redo(); + if(textBox && key(KEY_TEXT_REDO).repeat) + text.textBoxes.front().textboxUndo.redo(); break; case SDLK_RETURN: { set_key_down(e, KEY_TEXT_ENTER); - if(text.textBox && key(KEY_TEXT_ENTER).repeat) + if(textBox && key(KEY_TEXT_ENTER).repeat) text.do_textbox_operation_with_undo([&]() { - text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::ENTER, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + textBox->process_key_input(*cursor, RichText::TextBox::InputKey::ENTER, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap); }); break; } case SDLK_TAB: { set_key_down(e, KEY_TEXT_TAB); - if(text.textBox && key(KEY_TEXT_TAB).repeat) + if(textBox && key(KEY_TEXT_TAB).repeat) text.do_textbox_operation_with_undo([&]() { - text.textBox->process_key_input(*text.cursor, RichText::TextBox::InputKey::TAB, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, text.modMap); + textBox->process_key_input(*cursor, RichText::TextBox::InputKey::TAB, ctrl_or_meta_held(), key(KEY_GENERIC_LSHIFT).held, modMap); }); break; } @@ -485,13 +519,28 @@ void InputManager::backend_key_down_update(const SDL_KeyboardEvent& e) { break; } - if(text.get_accepting_input() && e.down) + if(text.acceptingInput) return; auto f = keyAssignments.find({make_generic_key_mod(kMod), kPress}); + KeyCallbackArgs keyArgs{.down = e.down, .repeat = e.repeat}; if(f != keyAssignments.end()) { set_key_down(e, f->second); - keyCallbacks[f->second].run_callbacks(KeyCallbackArgs{.down = e.down, .repeat = e.repeat}); + keyCallbacks[f->second].run_callbacks(keyArgs); + } + switch(kPress) { + case SDLK_UP: + keyCallbacks[KEY_TEXT_UP].run_callbacks(keyArgs); + break; + case SDLK_DOWN: + keyCallbacks[KEY_TEXT_DOWN].run_callbacks(keyArgs); + break; + case SDLK_LEFT: + keyCallbacks[KEY_TEXT_LEFT].run_callbacks(keyArgs); + break; + case SDLK_RIGHT: + keyCallbacks[KEY_TEXT_RIGHT].run_callbacks(keyArgs); + break; } } @@ -509,16 +558,16 @@ void InputManager::call_text_paste(bool isRichTextPaste) { } void InputManager::process_text_paste(const std::string& plainClipboardStr) { - if(text.textBox) { + if(!text.textBoxes.empty()) { // Workaround for not being able to copy richtext to system clipboard, this should at least work within the application itself - if(text.isRichTextBox && text.isNextPasteRich && lastCopiedRichText.has_value()) { + if(text.textBoxes.front().isRichTextBox && text.isNextPasteRich && lastCopiedRichText.has_value()) { if(lastCopiedRichText.value().get_plain_text() == remove_carriage_returns_from_str(plainClipboardStr)) - text.textBox->process_rich_text_input(*text.cursor, lastCopiedRichText.value()); + text.textBoxes.front().textBox->process_rich_text_input(*text.textBoxes.front().cursor, lastCopiedRichText.value()); else - text.textBox->process_text_input(*text.cursor, plainClipboardStr, text.modMap); + text.textBoxes.front().textBox->process_text_input(*text.textBoxes.front().cursor, plainClipboardStr, text.textBoxes.front().modMap); } else - text.textBox->process_text_input(*text.cursor, plainClipboardStr, text.modMap); + text.textBoxes.front().textBox->process_text_input(*text.textBoxes.front().cursor, plainClipboardStr, text.textBoxes.front().modMap); } } @@ -597,9 +646,27 @@ void InputManager::backend_key_up_update(const SDL_KeyboardEvent& e) { break; } + KeyCallbackArgs keyArgs{.down = e.down, .repeat = e.repeat}; for(auto& p : keyAssignments) { - if(p.first.y() == kPress) // Dont try matching modifiers when setting key to go up + if(p.first.y() == kPress) { // Dont try matching modifiers when setting key to go up set_key_up(e, p.second); + keyCallbacks[p.second].run_callbacks(keyArgs); + } + } + + switch(kPress) { + case SDLK_UP: + keyCallbacks[KEY_TEXT_UP].run_callbacks(keyArgs); + break; + case SDLK_DOWN: + keyCallbacks[KEY_TEXT_DOWN].run_callbacks(keyArgs); + break; + case SDLK_LEFT: + keyCallbacks[KEY_TEXT_LEFT].run_callbacks(keyArgs); + break; + case SDLK_RIGHT: + keyCallbacks[KEY_TEXT_RIGHT].run_callbacks(keyArgs); + break; } } @@ -619,21 +686,7 @@ void InputManager::frame_reset(const Vector2i& windowSize) { mouse.leftClicks = 0; mouse.rightClicks = 0; mouse.middleClicks = 0; - text.acceptingInput = text.acceptingInputNew; - text.acceptingInputNew = false; - if(text.cursor != text.newCursor || text.textBox != text.newTextBox) - text.textboxUndo.clear(); - text.cursor = text.newCursor; - text.textBox = text.newTextBox; - text.modMap = text.newModMap; - text.isRichTextBox = text.newIsRichTextBox; - text.newCursor = nullptr; - text.newTextBox = nullptr; - text.newModMap = std::nullopt; - text.newIsRichTextBox = false; - - text.newInput.clear(); droppedItems.clear(); cursorIcon = SystemCursorType::DEFAULT; diff --git a/src/InputManager.hpp b/src/InputManager.hpp index fa8abd0..f3668b9 100644 --- a/src/InputManager.hpp +++ b/src/InputManager.hpp @@ -89,36 +89,33 @@ struct InputManager { std::array buttons; } pen; + void set_rich_text_box_input_front(const std::shared_ptr& nTextBox, const std::shared_ptr& nCursor, bool isRichTextBox, const std::optional& nModMap = std::nullopt); + void set_rich_text_box_input_back(const std::shared_ptr& nTextBox, const std::shared_ptr& nCursor, bool isRichTextBox, const std::optional& nModMap = std::nullopt); + void remove_rich_text_box_input(const std::shared_ptr& nTextBox); + struct Text { - std::string newInput; - bool lastAcceptingTextInputVal = false; + bool is_accepting_input(); - void set_accepting_input(); - bool get_accepting_input(); - - void set_rich_text_box_input(const std::shared_ptr& nTextBox, const std::shared_ptr& nCursor, bool isRichTextBox, const std::optional& nModMap = std::nullopt); void add_text_to_textbox(const std::string& inputText); void add_textbox_undo(const RichText::TextBox::Cursor& prevCursor, const RichText::TextData& prevRichText); void do_textbox_operation_with_undo(const std::function& func); private: + struct TextBoxInfo { + bool isRichTextBox; + std::shared_ptr textBox; + std::shared_ptr cursor; + std::optional modMap; + UndoManager textboxUndo; + }; + + void set_accepting_input(SDL_Window* window, bool newAcceptingInputVal); + bool isNextPasteRich = false; - - bool isRichTextBox; - std::shared_ptr textBox; - std::shared_ptr cursor; - std::optional modMap; - - bool newIsRichTextBox; - std::shared_ptr newTextBox; - std::shared_ptr newCursor; - std::optional newModMap; - - UndoManager textboxUndo; - bool acceptingInput = false; - bool acceptingInputNew = false; + + std::deque textBoxes; friend struct InputManager; } text; @@ -245,6 +242,8 @@ struct InputManager { std::unordered_map keyAssignments; std::unordered_map defaultKeyAssignments; std::array keys; + + SDL_Window* sdlWindow; }; NLOHMANN_JSON_SERIALIZE_ENUM(InputManager::KeyCodeEnum, { diff --git a/src/Toolbar.cpp b/src/Toolbar.cpp index eeb4dfb..f5eb016 100644 --- a/src/Toolbar.cpp +++ b/src/Toolbar.cpp @@ -2275,9 +2275,9 @@ void Toolbar::initialize_io_before_update() { 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->richTextBoxEdit = [&](std::shared_ptr t, std::shared_ptr c) { - main.input.text.set_rich_text_box_input(t, c, false); - }; + io->previousRichTextBoxToEdit = io->richTextBoxToEdit; + io->richTextBoxToEditCursor = nullptr; + io->richTextBoxToEdit = nullptr; if(io->acceptingTextInput) main.input.text_input_silence_everything(); @@ -2319,6 +2319,12 @@ 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); + } } void Toolbar::draw(SkCanvas* canvas) { diff --git a/src/World.cpp b/src/World.cpp index e76d3e6..d2c6532 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -259,20 +259,21 @@ void World::on_tab_in() { void World::register_callbacks() { drawProg.register_callbacks(); - redoKeyCallback = main.input.keyCallbacks[InputManager::KEY_REDO].register_callback([&](auto& key) { - if(key.down && !key.repeat) + keyCallbacks[InputManager::KEY_REDO] = main.input.keyCallbacks[InputManager::KEY_REDO].register_callback([&](auto& key) { + if(key.down) redo_with_checks(); }); - undoKeyCallback = main.input.keyCallbacks[InputManager::KEY_UNDO].register_callback([&](auto& key) { - if(key.down && !key.repeat) + keyCallbacks[InputManager::KEY_UNDO] = main.input.keyCallbacks[InputManager::KEY_UNDO].register_callback([&](auto& key) { + if(key.down) undo_with_checks(); }); } void World::deregister_callbacks() { drawProg.deregister_callbacks(); - main.input.keyCallbacks[InputManager::KEY_REDO].deregister_callback(redoKeyCallback); - main.input.keyCallbacks[InputManager::KEY_UNDO].deregister_callback(undoKeyCallback); + for(auto& [key, callback] : keyCallbacks) + main.input.keyCallbacks[key].deregister_callback(callback); + keyCallbacks.clear(); } void World::send_chat_message(const std::string& message) { diff --git a/src/World.hpp b/src/World.hpp index 1c5e584..60eae74 100644 --- a/src/World.hpp +++ b/src/World.hpp @@ -101,9 +101,9 @@ class World { std::shared_ptr netServer; std::shared_ptr netClient; + + std::unordered_map keyCallbacks; private: - InputManager::KeyCallbackManager::Callback* undoKeyCallback; - InputManager::KeyCallbackManager::Callback* redoKeyCallback; void register_callbacks(); void deregister_callbacks(); diff --git a/src/main.cpp b/src/main.cpp index 422f2a0..d9dde5c 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #include "Helpers/SCollision.hpp" #include "Helpers/StringHelpers.hpp" #include "Helpers/FileDownloader.hpp" +#include "VersionConstants.hpp" #include "include/gpu/GpuTypes.h" #include #include @@ -195,6 +196,14 @@ void get_refresh_rate(MainStruct& mS) { } void initialize_sdl(MainStruct& mS, int wWidth, int wHeight) { + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING, "InfiniPaint"); + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_VERSION_STRING, VersionConstants::CURRENT_VERSION_STRING.c_str()); + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_IDENTIFIER_STRING, "com.infinipaint.infinipaint"); + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_CREATOR_STRING, "Yousef Khadadeh (ErrorAtLine0)"); + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_COPYRIGHT_STRING, "Copyright (c) 2026 Yousef Khadadeh"); + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_URL_STRING, "https://infinipaint.com/"); + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_TYPE_STRING, "application"); + SDL_SetHint(SDL_HINT_APP_NAME, "InfiniPaint"); SDL_SetHint(SDL_HINT_PEN_MOUSE_EVENTS, "0"); SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0"); @@ -455,6 +464,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) { mS.m->documentsPath = std::filesystem::path(documentsPathSDL); #endif mS.m->window.sdlWindow = mS.window; + mS.m->input.sdlWindow = mS.window; mS.m->update_scale_and_density(); #ifdef __EMSCRIPTEN__ emscripten_set_beforeunload_callback((void*)mSPtr, emscripten_before_unload); @@ -659,12 +669,6 @@ SDL_AppResult SDL_AppIterate(void *appstate) { SDL_SetCursor(mS.systemCursors[static_cast(mS.m->input.cursorIcon)]); } - if(mS.m->input.text.get_accepting_input() && !mS.m->input.text.lastAcceptingTextInputVal) - SDL_StartTextInput(mS.window); - else if(!mS.m->input.text.get_accepting_input() && mS.m->input.text.lastAcceptingTextInputVal) - SDL_StopTextInput(mS.window); - mS.m->input.text.lastAcceptingTextInputVal = mS.m->input.text.get_accepting_input(); - //cpu_save_sleep(mS); //attempt_redraw_and_swap_buffers(mS); regular_draw(mS); @@ -769,7 +773,6 @@ SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) { mS.m->input.backend_key_up_update(event->key); break; case SDL_EVENT_TEXT_INPUT: - mS.m->input.text.newInput += event->text.text; mS.m->input.text.add_text_to_textbox(event->text.text); break; case SDL_EVENT_DROP_FILE: