From 777a5a6d03382480bc8b45d68087e03ad33764ef Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Tue, 6 Jan 2026 19:06:44 +0300 Subject: [PATCH] Added keybind to image paste --- src/DrawingProgram/DrawingProgram.cpp | 33 +++----------- src/DrawingProgram/DrawingProgram.hpp | 2 +- .../DrawingProgramSelection.cpp | 45 ++++++++++++++++++- .../DrawingProgramSelection.hpp | 1 + src/InputManager.cpp | 2 + src/InputManager.hpp | 2 + 6 files changed, 56 insertions(+), 29 deletions(-) diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index c9796f7..62ae541 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -36,10 +36,6 @@ #include "Tools/EraserTool.hpp" -#ifdef __EMSCRIPTEN__ - #include -#endif - DrawingProgram::DrawingProgram(World& initWorld): world(initWorld), drawCache(*this), @@ -171,27 +167,8 @@ bool DrawingProgram::selection_action_menu(Vector2f popupPos) { shouldClose = true; } if(t.gui.text_button_left_transparent("Paste Image", "Paste Image")) { - #ifdef __EMSCRIPTEN__ - struct PasteData { - std::weak_ptr w; - Vector2f screenPos; - }; - static PasteData pasteData; - pasteData.screenPos = popupPos; - pasteData.w = make_weak_ptr(world.main.world); - emscripten_browser_clipboard::paste_async_image([](std::string_view pasteData, void* callbackData){ - PasteData* p = (PasteData*)callbackData; - std::shared_ptr wLock = p->w.lock(); - if(wLock) - wLock->drawProg.add_file_to_canvas_by_data("Image from clipboard", pasteData, p->screenPos); - else - Logger::get().log("INFO", "Loading image to canvas that has been destroyed"); - }, &pasteData); - #else - world.main.input.get_clipboard_image_data_SDL([&](std::string_view pasteData) { - add_file_to_canvas_by_data("Image from clipboard", pasteData, popupPos); - }); - #endif + selection.deselect_all(); + selection.paste_image(popupPos * t.final_gui_scale()); shouldClose = true; } if(selection.is_something_selected()) { @@ -536,7 +513,7 @@ void DrawingProgram::add_file_to_canvas_by_path_execute(const std::filesystem::p } } -void DrawingProgram::add_file_to_canvas_by_data(const std::string& fileName, std::string_view fileBuffer, Vector2f dropPos) { +CanvasComponentContainer::ObjInfo* DrawingProgram::add_file_to_canvas_by_data(const std::string& fileName, std::string_view fileBuffer, Vector2f dropPos) { if(layerMan.is_a_layer_being_edited()) { ResourceData newResource; newResource.data = std::make_shared(fileBuffer); @@ -553,9 +530,11 @@ void DrawingProgram::add_file_to_canvas_by_data(const std::string& fileName, std img.d.p1 = dropPos - imDim; img.d.p2 = dropPos + imDim; img.d.imageID = imageID; - auto newObjInfo = layerMan.add_component_to_layer_being_edited(newContainer); + CanvasComponentContainer::ObjInfo* newObjInfo = layerMan.add_component_to_layer_being_edited(newContainer); layerMan.add_undo_place_component(newObjInfo); + return newObjInfo; } + return nullptr; } float DrawingProgram::drag_point_radius() { diff --git a/src/DrawingProgram/DrawingProgram.hpp b/src/DrawingProgram/DrawingProgram.hpp index 9f4a6ef..9cb0c78 100644 --- a/src/DrawingProgram/DrawingProgram.hpp +++ b/src/DrawingProgram/DrawingProgram.hpp @@ -35,7 +35,7 @@ class DrawingProgram { void init_server_callbacks(); void init_client_callbacks(); void add_file_to_canvas_by_path(const std::filesystem::path& filePath, Vector2f dropPos, bool addInSameThread); - void add_file_to_canvas_by_data(const std::string& fileName, std::string_view fileBuffer, Vector2f dropPos); + CanvasComponentContainer::ObjInfo* add_file_to_canvas_by_data(const std::string& fileName, std::string_view fileBuffer, Vector2f dropPos); void get_used_resources(std::unordered_set& resourceSet); void load_file(cereal::PortableBinaryInputArchive& a, VersionNumber version); diff --git a/src/DrawingProgram/DrawingProgramSelection.cpp b/src/DrawingProgram/DrawingProgramSelection.cpp index f2c125a..62a7c51 100644 --- a/src/DrawingProgram/DrawingProgramSelection.cpp +++ b/src/DrawingProgram/DrawingProgramSelection.cpp @@ -18,6 +18,10 @@ #define ROTATION_POINT_RADIUS_MULTIPLIER 0.7f #define ROTATION_POINTS_DISTANCE 20.0f +#ifdef __EMSCRIPTEN__ + #include +#endif + DrawingProgramSelection::DrawingProgramSelection(DrawingProgram& initDrawP): drawP(initDrawP) {} @@ -343,9 +347,15 @@ void DrawingProgramSelection::update() { deselect_all(); paste_clipboard(drawP.world.main.input.mouse.pos); } + else if(drawP.world.main.input.key(InputManager::KEY_PASTE_IMAGE).pressed) { + deselect_all(); + paste_image(drawP.world.main.input.mouse.pos); + } } else if(drawP.world.main.input.key(InputManager::KEY_PASTE).pressed && !drawP.prevent_undo_or_redo()) paste_clipboard(drawP.world.main.input.mouse.pos); + else if(drawP.world.main.input.key(InputManager::KEY_PASTE_IMAGE).pressed && !drawP.prevent_undo_or_redo()) + paste_image(drawP.world.main.input.mouse.pos); else if(drawP.world.main.input.key(InputManager::KEY_GENERIC_ESCAPE).pressed) drawP.switch_to_tool(DrawingProgramToolType::EDIT, true); } @@ -432,7 +442,40 @@ void DrawingProgramSelection::paste_clipboard(Vector2f pasteScreenPos) { compSetInserted.emplace_back(&(*it)); } set_to_selection(compSetInserted); - //drawP.add_undo_place_components(compSetInserted); + } +} + +void DrawingProgramSelection::paste_image(Vector2f pasteScreenPos) { + if(drawP.layerMan.is_a_layer_being_edited()) { + #ifdef __EMSCRIPTEN__ + struct PasteData { + std::weak_ptr w; + Vector2f screenPos; + }; + static PasteData pasteData; + pasteData.screenPos = pasteScreenPos; + pasteData.w = make_weak_ptr(drawP.world.main.world); + emscripten_browser_clipboard::paste_async_image([](std::string_view pasteData, void* callbackData){ + PasteData* p = (PasteData*)callbackData; + std::shared_ptr wLock = p->w.lock(); + if(wLock) + wLock->drawProg.add_file_to_canvas_by_data("Image from clipboard", pasteData, p->screenPos); + else + Logger::get().log("INFO", "Loading image to canvas that has been destroyed"); + }, &pasteData); + #else + if(!drawP.is_selection_allowing_tool(drawP.drawTool->get_type())) + drawP.switch_to_tool(DrawingProgramToolType::EDIT); + + std::vector compSetInserted; + drawP.world.main.input.get_clipboard_image_data_SDL([&](std::string_view pasteData) { + compSetInserted.emplace_back(drawP.add_file_to_canvas_by_data("Image from clipboard", pasteData, pasteScreenPos)); + }); + if(!compSetInserted.empty() && compSetInserted.back() != nullptr) { + drawP.drawCache.erase_component(compSetInserted.back()); + set_to_selection(compSetInserted); + } + #endif } } diff --git a/src/DrawingProgram/DrawingProgramSelection.hpp b/src/DrawingProgram/DrawingProgramSelection.hpp index 1f6149d..1ae6a94 100644 --- a/src/DrawingProgram/DrawingProgramSelection.hpp +++ b/src/DrawingProgram/DrawingProgramSelection.hpp @@ -19,6 +19,7 @@ class DrawingProgramSelection { void update(); void deselect_all(); void paste_clipboard(Vector2f pasteScreenPos); + void paste_image(Vector2f pasteScreenPos); std::unordered_set get_selection_as_set(); void delete_all(); void selection_to_clipboard(); diff --git a/src/InputManager.cpp b/src/InputManager.cpp index aa09609..5f2ca75 100644 --- a/src/InputManager.cpp +++ b/src/InputManager.cpp @@ -32,6 +32,7 @@ InputManager::InputManager() { defaultKeyAssignments[{CTRL_MOD, SDLK_C}] = KEY_COPY; defaultKeyAssignments[{CTRL_MOD, SDLK_X}] = KEY_CUT; defaultKeyAssignments[{CTRL_MOD, SDLK_V}] = KEY_PASTE; + defaultKeyAssignments[{CTRL_MOD | SDL_KMOD_SHIFT, SDLK_V}] = KEY_PASTE_IMAGE; defaultKeyAssignments[{0, SDLK_B}] = KEY_DRAW_TOOL_BRUSH; defaultKeyAssignments[{0, SDLK_E}] = KEY_DRAW_TOOL_ERASER; defaultKeyAssignments[{0, SDLK_Z}] = KEY_DRAW_TOOL_ZOOM; @@ -155,6 +156,7 @@ void InputManager::get_clipboard_image_data_SDL(const std::function(clipboardData), clipboardDataSize)); SDL_free(clipboardData); + return; } } } diff --git a/src/InputManager.hpp b/src/InputManager.hpp index 50f9fc4..01323dd 100644 --- a/src/InputManager.hpp +++ b/src/InputManager.hpp @@ -149,6 +149,7 @@ struct InputManager { KEY_COPY, KEY_CUT, KEY_PASTE, + KEY_PASTE_IMAGE, KEY_DRAW_TOOL_BRUSH, KEY_DRAW_TOOL_ERASER, KEY_DRAW_TOOL_ZOOM, @@ -240,6 +241,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM(InputManager::KeyCodeEnum, { {InputManager::KEY_COPY, "Copy"}, {InputManager::KEY_CUT, "Cut"}, {InputManager::KEY_PASTE, "Paste"}, + {InputManager::KEY_PASTE_IMAGE, "Paste Image"}, {InputManager::KEY_DRAW_TOOL_BRUSH, "Brush Tool"}, {InputManager::KEY_DRAW_TOOL_ERASER, "Eraser Tool"}, {InputManager::KEY_DRAW_TOOL_ZOOM, "Zoom Tool"},