From 4363fe9f9d161c5f8d1ec9235ffce46fd12e33b0 Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Fri, 29 May 2026 19:45:28 +0300 Subject: [PATCH] Fixed undo problem with eraser --- .../CanvasComponentContainer.cpp | 3 +- .../EditCanvasComponentWorldUndoAction.cpp | 38 +++++++++++++++++++ .../EditCanvasComponentWorldUndoAction.hpp | 14 +++++++ src/DrawingProgram/Tools/EraserTool.cpp | 14 +++---- src/DrawingProgram/Tools/EraserTool.hpp | 2 +- 5 files changed, 62 insertions(+), 9 deletions(-) diff --git a/src/CanvasComponents/CanvasComponentContainer.cpp b/src/CanvasComponents/CanvasComponentContainer.cpp index 078609c..30feb16 100644 --- a/src/CanvasComponents/CanvasComponentContainer.cpp +++ b/src/CanvasComponents/CanvasComponentContainer.cpp @@ -151,11 +151,12 @@ void CanvasComponentContainer::commit_transform_dont_invalidate_cache() { // camCoordsScaleToCheckAgainst is different from camCoords.inverseScale if we locked the eraser's scale. CanvasComponentEraseDetailResult CanvasComponentContainer::collides_with_erase_detail(const CoordSpaceHelper& camCoords, const WorldScalar& camCoordsScaleToCheckAgainst, const SkPath& checkAgainstCam) const { constexpr static int COMP_MAX_SHIFT_BEFORE_STOP_ERASE = 3; + constexpr static int COMP_COMPLETE_ERASE_SHIFT = 13; if(!worldAABB.has_value()) return CanvasComponentEraseDetailResult::NO_CHANGE; if((camCoordsScaleToCheckAgainst << COMP_MAX_SHIFT_BEFORE_STOP_ERASE) < coords.inverseScale) // Object is too large, just dismiss the collision return CanvasComponentEraseDetailResult::NO_CHANGE; - else if(coords.inverseScale < (camCoordsScaleToCheckAgainst >> COMP_COLLIDE_MIN_SHIFT_TINY)) { + else if(coords.inverseScale < (camCoordsScaleToCheckAgainst >> COMP_COMPLETE_ERASE_SHIFT)) { if(checkAgainstCam.contains(convert_vec2(camCoords.to_space(worldAABB.value().min)))) return CanvasComponentEraseDetailResult::REMOVED; return CanvasComponentEraseDetailResult::NO_CHANGE; diff --git a/src/DrawingProgram/EditCanvasComponentWorldUndoAction.cpp b/src/DrawingProgram/EditCanvasComponentWorldUndoAction.cpp index a73f490..3b287f1 100644 --- a/src/DrawingProgram/EditCanvasComponentWorldUndoAction.cpp +++ b/src/DrawingProgram/EditCanvasComponentWorldUndoAction.cpp @@ -51,3 +51,41 @@ bool EditCanvasComponentWorldUndoAction::undo_redo(WorldUndoManager& undoMan) { } EditCanvasComponentWorldUndoAction::~EditCanvasComponentWorldUndoAction() {} + + + + +EditTransformCanvasComponentWorldUndoAction::EditTransformCanvasComponentWorldUndoAction(std::unique_ptr initData, const CoordSpaceHelper& initCoords, WorldUndoManager::UndoObjectID initUndoID): + data(std::move(initData)), + coords(initCoords), + undoID(initUndoID) +{} + +std::string EditTransformCanvasComponentWorldUndoAction::get_name() const { + return "Edit Canvas Component With Transform"; +} + +bool EditTransformCanvasComponentWorldUndoAction::undo(WorldUndoManager& undoMan) { + return undo_redo(undoMan); +} + +bool EditTransformCanvasComponentWorldUndoAction::redo(WorldUndoManager& undoMan) { + return undo_redo(undoMan); +} + +bool EditTransformCanvasComponentWorldUndoAction::undo_redo(WorldUndoManager& undoMan) { + std::optional toEditID = undoMan.get_netid_from_undoid(undoID); + if(!toEditID.has_value()) + return false; + auto objPtr = undoMan.world.netObjMan.get_obj_temporary_ref_from_id(toEditID.value()); + std::unique_ptr newData = objPtr->get_comp().get_data_copy(); + objPtr->get_comp().set_data_from(*data); + data = std::move(newData); + std::swap(coords, objPtr->coords); + undoMan.world.drawProg.send_transforms_for({&(*objPtr->objInfo)}); + objPtr->commit_update(undoMan.world.drawProg); + objPtr->send_comp_update(undoMan.world.drawProg, true); + return true; +} + +EditTransformCanvasComponentWorldUndoAction::~EditTransformCanvasComponentWorldUndoAction() {} diff --git a/src/DrawingProgram/EditCanvasComponentWorldUndoAction.hpp b/src/DrawingProgram/EditCanvasComponentWorldUndoAction.hpp index d1abbfe..a764a79 100644 --- a/src/DrawingProgram/EditCanvasComponentWorldUndoAction.hpp +++ b/src/DrawingProgram/EditCanvasComponentWorldUndoAction.hpp @@ -31,3 +31,17 @@ class EditCanvasComponentWorldUndoAction : public WorldUndoAction { std::unique_ptr data; WorldUndoManager::UndoObjectID undoID; }; + +class EditTransformCanvasComponentWorldUndoAction : public WorldUndoAction { + public: + EditTransformCanvasComponentWorldUndoAction(std::unique_ptr initData, const CoordSpaceHelper& initCoords, WorldUndoManager::UndoObjectID initUndoID); + std::string get_name() const override; + bool undo(WorldUndoManager& undoMan) override; + bool redo(WorldUndoManager& undoMan) override; + bool undo_redo(WorldUndoManager& undoMan); + ~EditTransformCanvasComponentWorldUndoAction(); + + std::unique_ptr data; + CoordSpaceHelper coords; + WorldUndoManager::UndoObjectID undoID; +}; diff --git a/src/DrawingProgram/Tools/EraserTool.cpp b/src/DrawingProgram/Tools/EraserTool.cpp index e577ca0..d49ff7f 100644 --- a/src/DrawingProgram/Tools/EraserTool.cpp +++ b/src/DrawingProgram/Tools/EraserTool.cpp @@ -139,7 +139,7 @@ void EraserTool::erase_on_path() { if(drawP.layerMan.component_passes_layer_selector(c, drawP.controls.layerSelector)) { auto it = updatedComponents.find(c); if(it != updatedComponents.end()) { - c->obj->get_comp().set_data_from(*(it->second)); + c->obj->get_comp().set_data_from(*it->second->obj); updatedComponents.erase(it); } erasedComponents.emplace(c); @@ -154,7 +154,7 @@ void EraserTool::erase_on_path() { drawP.drawCache.node_loop_erase_if_components(bvhNode, [&](auto c) { if(drawP.world.main.toolConfig.eraser.eraseDetail) { if(drawP.layerMan.component_passes_layer_selector(c, drawP.controls.layerSelector)) { - auto dataCopy = c->obj->get_comp().get_data_copy(); + auto dataCopy = c->obj->get_data_copy(); CanvasComponentEraseDetailResult result = c->obj->collides_with_erase_detail(genData.coords, eraseScaleToCheckAgainst, erasePath); switch(result) { case CanvasComponentEraseDetailResult::NO_CHANGE: @@ -173,11 +173,11 @@ void EraserTool::erase_on_path() { case CanvasComponentEraseDetailResult::REMOVED: auto it = updatedComponents.find(c); if(it != updatedComponents.end()) { - c->obj->get_comp().set_data_from(*(it->second)); + c->obj->get_comp().set_data_from(*it->second->obj); updatedComponents.erase(it); } else - c->obj->get_comp().set_data_from(*dataCopy); + c->obj->get_comp().set_data_from(*dataCopy->obj); erasedComponents.emplace(c); drawP.drawCache.invalidate_cache_at_optional_aabb(c->obj->get_world_bounds()); return true; @@ -223,7 +223,7 @@ void EraserTool::commit_erase() { newObjectsToPlace[comp->obj->parentLayer].emplace_back(std::next(comp->obj->objInfo), c); placedNewObject = true; erasedComponents.emplace(comp); - comp->obj->get_comp().set_data_from(*oldData); + comp->obj->get_comp().set_data_from(*oldData->obj); return true; } return false; @@ -248,10 +248,10 @@ void EraserTool::commit_erase() { comp->obj->send_comp_update(drawP, true); if(first) { first = false; - drawP.world.undo.push(std::make_unique(std::move(oldData), drawP.world.undo.get_undoid_from_netid(comp->obj.get_net_id()))); + drawP.world.undo.push(std::make_unique(std::move(oldData->obj), oldData->coords, drawP.world.undo.get_undoid_from_netid(comp->obj.get_net_id()))); } else - drawP.world.undo.push_on_last(std::make_unique(std::move(oldData), drawP.world.undo.get_undoid_from_netid(comp->obj.get_net_id()))); + drawP.world.undo.push_on_last(std::make_unique(std::move(oldData->obj), oldData->coords, drawP.world.undo.get_undoid_from_netid(comp->obj.get_net_id()))); } }, NetworkingObjects::NetObjManager::SendUpdateType::SEND_TO_ALL, nullptr); erasedComponents.clear(); diff --git a/src/DrawingProgram/Tools/EraserTool.hpp b/src/DrawingProgram/Tools/EraserTool.hpp index dbb7499..3c21ec6 100644 --- a/src/DrawingProgram/Tools/EraserTool.hpp +++ b/src/DrawingProgram/Tools/EraserTool.hpp @@ -40,7 +40,7 @@ class EraserTool : public DrawingProgramToolBase { virtual void input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion) override; virtual void input_pen_axis_callback(const InputManager::PenAxisCallbackArgs& axis) override; - std::unordered_map> updatedComponents; + std::unordered_map> updatedComponents; std::unordered_set erasedComponents; // Pointers will be erased from this set if theyre erased in the main list (done by callback) private: SkPath erasePath;