From 0d071aa7974c52898d4cfd591b0a37a09d120a97 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sun, 24 Mar 2024 13:00:09 +0100 Subject: [PATCH] [Corners LPE 4] Knot fixes --- src/live_effects/effect.cpp | 58 ++++++++++++++----- src/live_effects/effect.h | 2 + src/live_effects/lpe-fillet-chamfer.cpp | 2 +- .../parameter/nodesatellitesarray.cpp | 32 ++-------- .../parameter/nodesatellitesarray.h | 1 - src/ui/knot/knot-holder.cpp | 24 +++----- src/ui/shape-editor.cpp | 21 +++---- src/ui/shape-editor.h | 3 +- src/ui/tools/node-tool.cpp | 11 ++++ src/ui/tools/node-tool.h | 5 +- 10 files changed, 81 insertions(+), 78 deletions(-) diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 38127a421d..b6c021b8fe 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -47,12 +47,11 @@ #include "live_effects/lpe-interpolate_points.h" #include "live_effects/lpe-jointype.h" #include "live_effects/lpe-knot.h" -#include "live_effects/lpe-lattice2.h" #include "live_effects/lpe-lattice.h" +#include "live_effects/lpe-lattice2.h" #include "live_effects/lpe-line_segment.h" #include "live_effects/lpe-measure-segments.h" #include "live_effects/lpe-mirror_symmetry.h" -#include "live_effects/lpeobject.h" #include "live_effects/lpe-offset.h" #include "live_effects/lpe-parallel.h" #include "live_effects/lpe-path_length.h" @@ -64,8 +63,8 @@ #include "live_effects/lpe-powerstroke.h" #include "live_effects/lpe-pts2ellipse.h" #include "live_effects/lpe-recursiveskeleton.h" -#include "live_effects/lpe-roughen.h" #include "live_effects/lpe-rough-hatches.h" +#include "live_effects/lpe-roughen.h" #include "live_effects/lpe-ruler.h" #include "live_effects/lpe-show_handles.h" #include "live_effects/lpe-simplify.h" @@ -79,6 +78,7 @@ #include "live_effects/lpe-tiling.h" #include "live_effects/lpe-transform_2pts.h" #include "live_effects/lpe-vonkoch.h" +#include "live_effects/lpeobject.h" #include "message-stack.h" #include "object/sp-defs.h" #include "object/sp-root.h" @@ -86,6 +86,7 @@ #include "path-chemistry.h" #include "ui/icon-loader.h" #include "ui/pack.h" +#include "ui/shape-editor.h" #include "ui/tools/node-tool.h" #include "ui/tools/pen-tool.h" #include "xml/sp-css-attr.h" @@ -1488,6 +1489,31 @@ void Effect::doAfterEffect_impl(SPLPEItem const *lpeitem, SPCurve *curve) _adjust_path = false; } +void Effect::reloadKnots(SPLPEItem const *lpeitem) +{ + if (!is_current) { + return; + } + if (SPDesktop *desktop = SP_ACTIVE_DESKTOP) { + if (auto nt = dynamic_cast(desktop->getTool())) { + auto lpeitem_mutable = const_cast(lpeitem); + SPItem *item = cast(lpeitem_mutable); + auto lpeitems = getCurrrentLPEItems(); + if (!lpeitems.empty()) { + item = cast(lpeitems.front()); + } + for (auto &_shape_editor : nt->_shape_editors) { + if (item && item == _shape_editor.first) { + auto shape_editor = _shape_editor.second.get(); + shape_editor->unset_item(); + shape_editor->set_item(item); + return; + } + } + } + } +} + void Effect::doOnRemove_impl(SPLPEItem const* lpeitem) { SPDocument *document = getSPDoc(); @@ -1502,6 +1528,7 @@ void Effect::doOnRemove_impl(SPLPEItem const* lpeitem) } doOnRemove(sp_lpe_item); getLPEObj()->deleted = true; + reloadKnots(sp_lpe_item); } /** @@ -1550,6 +1577,9 @@ void Effect::doOnApply_impl(SPLPEItem const* lpeitem) void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem) { sp_lpe_item = const_cast(lpeitem); + is_current = sp_lpe_item->getCurrentLPE() == this; + // enure is not deleted if we we resurrect the item with the LPE + getLPEObj()->deleted = false; if (_provides_path_adjustment) { LPEItemShapesNumbers lpenumbers; // By the moment we not handle LPEItem groups. see here how to add to @@ -1563,6 +1593,7 @@ void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem) //std::cout << _lpenumbers << std::endl; _lpenumbers = lpenumbers; } + doBeforeEffect(lpeitem); if (is_load) { update_satellites(); @@ -1719,7 +1750,14 @@ Effect::registerParameter(Parameter * param) void Effect::addHandles(KnotHolder *knotholder, SPItem *item) { using namespace Inkscape::LivePathEffect; - + if (getLPEObj()->deleted) { + return; + } + if (is_load) { + if (auto lpeitem = cast(item)) { + sp_lpe_item_update_patheffect(lpeitem, false, false); + } + } // add handles provided by the effect itself addKnotHolderEntities(knotholder, item); @@ -1727,12 +1765,6 @@ Effect::addHandles(KnotHolder *knotholder, SPItem *item) { for (auto & p : param_vector) { p->addKnotHolderEntities(knotholder, item); } - if (is_load) { - auto lpeitem = cast(item); - if (lpeitem) { - sp_lpe_item_update_patheffect(lpeitem, false, false); - } - } } /** @@ -1774,10 +1806,8 @@ Effect::addCanvasIndicators(SPLPEItem const*/*lpeitem*/, std::vector(desktop->getTool()); - if (nt) { + if (SPDesktop *desktop = SP_ACTIVE_DESKTOP) { + if (auto const nt = dynamic_cast(desktop->getTool())) { Inkscape::UI::Tools::sp_update_helperpath(desktop); } } diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h index e6501b7b99..2298d61baf 100644 --- a/src/live_effects/effect.h +++ b/src/live_effects/effect.h @@ -162,6 +162,7 @@ public: bool keep_paths; // set this to false allow retain extra generated objects, see measure line LPE bool is_load; bool is_applied; + bool is_current = false; bool on_remove_all; bool refresh_widgets; bool finishiddle = false; @@ -177,6 +178,7 @@ public: // them. SPShape *current_shape; // these get stored in performPathEffects. std::vector param_vector; + void reloadKnots(SPLPEItem const *lpeitem); void setDefaultParameters(); void resetDefaultParameters(); bool hasDefaultParameters(); diff --git a/src/live_effects/lpe-fillet-chamfer.cpp b/src/live_effects/lpe-fillet-chamfer.cpp index 2d1e0d0a04..5cf2462bc4 100644 --- a/src/live_effects/lpe-fillet-chamfer.cpp +++ b/src/live_effects/lpe-fillet-chamfer.cpp @@ -364,7 +364,7 @@ void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem) _pathvector_nodesatellites->setNodeSatellites(nodesatellites); _pathvector_nodesatellites->recalculateForNewPathVector(pathv, nodesatellite); nodesatellites_param.setPathVectorNodeSatellites(_pathvector_nodesatellites, true); - nodesatellites_param.reloadKnots(); + reloadKnots(lpeItem); } else { _pathvector_nodesatellites->setPathVector(pathv); _pathvector_nodesatellites->setNodeSatellites(nodesatellites); diff --git a/src/live_effects/parameter/nodesatellitesarray.cpp b/src/live_effects/parameter/nodesatellitesarray.cpp index 4d181d3cef..74a8c3fc89 100644 --- a/src/live_effects/parameter/nodesatellitesarray.cpp +++ b/src/live_effects/parameter/nodesatellitesarray.cpp @@ -9,24 +9,18 @@ #include "nodesatellitesarray.h" -#include - #include <2geom/path-intersection.h> - -#include "display/control/canvas-item-enums.h" -#include "inkscape.h" -#include "preferences.h" +#include #include "display/control/canvas-item-ctrl.h" +#include "display/control/canvas-item-enums.h" #include "helper/geom.h" +#include "inkscape.h" #include "live_effects/effect.h" #include "live_effects/lpe-fillet-chamfer.h" #include "object/sp-lpe-item.h" +#include "preferences.h" #include "ui/dialog/lpe-fillet-chamfer-properties.h" -#include "ui/knot/knot-holder.h" -#include "ui/shape-editor.h" -#include "ui/tools/node-tool.h" - // TODO due to internal breakage in glibmm headers, // this has to be included last. @@ -60,24 +54,6 @@ void NodeSatelliteArrayParam::setPathVectorNodeSatellites(PathVectorNodeSatellit } } -void NodeSatelliteArrayParam::reloadKnots() -{ - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (desktop && !_global_knot_hide) { - Inkscape::UI::Tools::NodeTool *nt = dynamic_cast(desktop->getTool()); - if (nt) { - for (auto &_shape_editor : nt->_shape_editors) { - Inkscape::UI::ShapeEditor *shape_editor = _shape_editor.second.get(); - if (shape_editor && shape_editor->lpeknotholder) { - SPItem *item = shape_editor->lpeknotholder->item; - delete shape_editor->lpeknotholder; - shape_editor->lpeknotholder = nullptr; - shape_editor->set_item(item); - } - } - } - } -} void NodeSatelliteArrayParam::setUseDistance(bool use_knot_distance) { _use_distance = use_knot_distance; diff --git a/src/live_effects/parameter/nodesatellitesarray.h b/src/live_effects/parameter/nodesatellitesarray.h index 49855db228..230163d0cf 100644 --- a/src/live_effects/parameter/nodesatellitesarray.h +++ b/src/live_effects/parameter/nodesatellitesarray.h @@ -57,7 +57,6 @@ public: void setCurrentZoom(double current_zoom); void setGlobalKnotHide(bool global_knot_hide); void setEffectType(EffectType et); - void reloadKnots(); void updateAmmount(double amount); void setPathVectorNodeSatellites(PathVectorNodeSatellites *pathVectorNodeSatellites, bool write = true); diff --git a/src/ui/knot/knot-holder.cpp b/src/ui/knot/knot-holder.cpp index 5154c02d9c..73a1816954 100644 --- a/src/ui/knot/knot-holder.cpp +++ b/src/ui/knot/knot-holder.cpp @@ -217,22 +217,12 @@ KnotHolder::transform_selected(Geom::Affine transform){ } } -void -KnotHolder::unselect_knots(){ - Inkscape::UI::Tools::NodeTool *nt = dynamic_cast(desktop->getTool()); - if (nt) { - for (auto &_shape_editor : nt->_shape_editors) { - Inkscape::UI::ShapeEditor *shape_editor = _shape_editor.second.get(); - if (shape_editor && shape_editor->has_knotholder()) { - KnotHolder * knotholder = shape_editor->knotholder; - if (knotholder) { - for (auto e : knotholder->entity) { - if (e->knot->is_selected()) { - e->knot->selectKnot(false); - } - } - } - } +void KnotHolder::unselect_knots() +{ + for (auto i : entity) { + SPKnot *knot = i->knot; + if (knot->is_selected()) { + knot->selectKnot(false); } } } @@ -295,7 +285,7 @@ KnotHolder::knot_ungrabbed_handler(SPKnot *knot, guint state) for(auto e : this->entity) { if (e->knot == knot) { e->knot_ungrabbed(e->knot->position(), e->knot->drag_origin * item->i2dt_affine().inverse() * _edit_transform.inverse(), state); - if (e->knot->is_lpe) { + if (knot->is_lpe) { // ungrab can delete the knot return; } break; diff --git a/src/ui/shape-editor.cpp b/src/ui/shape-editor.cpp index fe8e2a745a..60190d2cc9 100644 --- a/src/ui/shape-editor.cpp +++ b/src/ui/shape-editor.cpp @@ -16,6 +16,7 @@ #include "desktop.h" #include "document.h" +#include "inkscape.h" #include "live_effects/effect.h" #include "object/sp-lpe-item.h" #include "ui/knot/knot-holder.h" @@ -124,19 +125,11 @@ void ShapeEditor::set_item(SPItem *item) { if (item) { Inkscape::XML::Node *repr; + _externChangedConn = INKSCAPE.signal_external_change.connect([this]() { this->reset_item(); }); if (!this->knotholder) { // only recreate knotholder if none is present this->knotholder = createKnotHolder(item, desktop, _edit_rotation, _edit_marker_mode); } - auto lpe = cast(item); - if (!(lpe && - lpe->getCurrentLPE() && - lpe->getCurrentLPE()->isVisible() && - lpe->getCurrentLPE()->providesKnotholder())) - { - delete this->lpeknotholder; - this->lpeknotholder = nullptr; - } if (!this->lpeknotholder) { // only recreate knotholder if none is present this->lpeknotholder = createLPEKnotHolder(item, desktop); @@ -172,11 +165,11 @@ void ShapeEditor::set_item(SPItem *item) { Why not make a reload function in KnotHolder? */ void ShapeEditor::reset_item() { - if (knotholder) { - SPObject *obj = desktop->getDocument()->getObjectByRepr(knotholder_listener_attached_for); /// note that it is not certain that this is an SPItem; it could be a LivePathEffectObject. - set_item(cast(obj)); - } else if (lpeknotholder) { - SPObject *obj = desktop->getDocument()->getObjectByRepr(lpeknotholder_listener_attached_for); /// note that it is not certain that this is an SPItem; it could be a LivePathEffectObject. + if (knotholder || lpeknotholder) { + SPObject *obj = desktop->getDocument()->getObjectByRepr(knotholder_listener_attached_for); + if (!obj) { + obj = desktop->getDocument()->getObjectByRepr(lpeknotholder_listener_attached_for); + } set_item(cast(obj)); } } diff --git a/src/ui/shape-editor.h b/src/ui/shape-editor.h index fdaefe9b71..ccafa3d5ee 100644 --- a/src/ui/shape-editor.h +++ b/src/ui/shape-editor.h @@ -15,6 +15,7 @@ #include <2geom/affine.h> +#include "helper/auto-connection.h" #include "xml/node-observer.h" class KnotHolder; @@ -48,7 +49,7 @@ public: private: void reset_item(); static bool _blockSetItem; - + Inkscape::auto_connection _externChangedConn; SPDesktop *desktop; Inkscape::XML::Node *knotholder_listener_attached_for{nullptr}; Inkscape::XML::Node *lpeknotholder_listener_attached_for{nullptr}; diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp index ef4cb7a4a2..6faf4231ef 100644 --- a/src/ui/tools/node-tool.cpp +++ b/src/ui/tools/node-tool.cpp @@ -385,6 +385,17 @@ void NodeTool::selection_changed(Inkscape::Selection *sel) { auto item = cast(r.object); si->set_item(item); this->_shape_editors.insert({item, std::move(si)}); + // delete all knotholders on remove item become recreated later + _releaseConnections[item] = item->connectRelease([this](auto item) { + for (auto i = this->_shape_editors.begin(); i != this->_shape_editors.end();) { + if (item == (*i).first) { + (*i).second->unset_item(); + this->_shape_editors.erase(i++); + } else { + ++i; + } + } + }); } } diff --git a/src/ui/tools/node-tool.h b/src/ui/tools/node-tool.h index aa4c2571ec..aad51d692d 100644 --- a/src/ui/tools/node-tool.h +++ b/src/ui/tools/node-tool.h @@ -14,9 +14,10 @@ #include #include -#include #include +#include +#include "helper/auto-connection.h" #include "ui/tools/tool-base.h" namespace Inkscape { @@ -62,7 +63,7 @@ public: private: Inkscape::Rubberband *get_rubberband() const; - + std::unordered_map _releaseConnections; sigc::connection _selection_changed_connection; sigc::connection _mouseover_changed_connection; -- GitLab