From 1636c1dd1651780d01759676b194312529f211f7 Mon Sep 17 00:00:00 2001 From: Adrian Boguszewski Date: Sat, 25 Jun 2016 22:24:26 +0200 Subject: Moved next functions, added namespace, renamed range functions (bzr r14954.1.10) --- src/ui/tools/mesh-tool.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 47927667c..9aaa0c14e 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -103,7 +103,7 @@ void MeshTool::selection_changed(Inkscape::Selection* /*sel*/) { return; } - guint n_obj = selection->itemList().size(); + guint n_obj = selection->items().size(); if (!drag->isNonEmpty() || selection->isEmpty()) { return; @@ -467,10 +467,10 @@ bool MeshTool::root_handler(GdkEvent* event) { if (over_line) { // We take the first item in selection, because with doubleclick, the first click // always resets selection to the single object under cursor - sp_mesh_context_split_near_point(this, selection->itemList()[0], this->mousepoint_doc, event->button.time); + sp_mesh_context_split_near_point(this, selection->items()[0], this->mousepoint_doc, event->button.time); } else { // Create a new gradient with default coordinates. - std::vector items=selection->itemList(); + std::vector items= selection->items(); for(std::vector::const_iterator i=items.begin();i!=items.end();++i){ SPItem *item = *i; SPGradientType new_type = SP_GRADIENT_TYPE_MESH; @@ -945,7 +945,7 @@ static void sp_mesh_end_drag(MeshTool &rc) { } else { // Starting from empty space: // Sort items so that the topmost comes last - std::vector items(selection->itemList()); + std::vector items(selection->items()); sort(items.begin(),items.end(),sp_item_repr_compare_position); // take topmost vector = sp_gradient_vector_for_object(document, desktop, SP_ITEM(items.back()), fill_or_stroke); @@ -955,7 +955,7 @@ static void sp_mesh_end_drag(MeshTool &rc) { SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property(css, "fill-opacity", "1.0"); - std::vector items=selection->itemList(); + std::vector items= selection->items(); for(std::vector::const_iterator i=items.begin();i!=items.end();++i){ //FIXME: see above @@ -972,7 +972,7 @@ static void sp_mesh_end_drag(MeshTool &rc) { // status text; we do not track coords because this branch is run once, not all the time // during drag - int n_objects = selection->itemList().size(); + int n_objects = selection->items().size(); rc.message_context->setF(Inkscape::NORMAL_MESSAGE, ngettext("Gradient for %d object; with Ctrl to snap angle", "Gradient for %d objects; with Ctrl to snap angle", n_objects), -- cgit v1.2.3 From f35bb1f74a0ffeb5c6477a25e3c4cde87a97bcf1 Mon Sep 17 00:00:00 2001 From: Adrian Boguszewski Date: Thu, 28 Jul 2016 12:06:06 +0200 Subject: Removed unused includes, decrease compilation time (bzr r15025) --- src/ui/tools/mesh-tool.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 47927667c..32e70bc19 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -15,7 +15,7 @@ */ #ifdef HAVE_CONFIG_H -# include "config.h" +#include #endif //#define DEBUG_MESH @@ -33,7 +33,6 @@ #include "macros.h" #include "message-context.h" #include "message-stack.h" -#include "preferences.h" #include "rubberband.h" #include "selection.h" #include "snap.h" -- cgit v1.2.3 From 43b49e325db73cc19b1731db6c69545664ee8fbe Mon Sep 17 00:00:00 2001 From: Adrian Boguszewski Date: Thu, 28 Jul 2016 13:26:17 +0200 Subject: Reverted changes to r15024 after many building problems (bzr r15027) --- src/ui/tools/mesh-tool.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 32e70bc19..47927667c 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -15,7 +15,7 @@ */ #ifdef HAVE_CONFIG_H -#include +# include "config.h" #endif //#define DEBUG_MESH @@ -33,6 +33,7 @@ #include "macros.h" #include "message-context.h" #include "message-stack.h" +#include "preferences.h" #include "rubberband.h" #include "selection.h" #include "snap.h" -- cgit v1.2.3 From 35830f456cadaecf8b8e3944e3031a1a93f6cb41 Mon Sep 17 00:00:00 2001 From: Adrian Boguszewski Date: Wed, 3 Aug 2016 15:29:38 +0200 Subject: Removed unused includes, decreased compilation time. Once again (bzr r15034) --- src/ui/tools/mesh-tool.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 47927667c..32e70bc19 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -15,7 +15,7 @@ */ #ifdef HAVE_CONFIG_H -# include "config.h" +#include #endif //#define DEBUG_MESH @@ -33,7 +33,6 @@ #include "macros.h" #include "message-context.h" #include "message-stack.h" -#include "preferences.h" #include "rubberband.h" #include "selection.h" #include "snap.h" -- cgit v1.2.3 From 7d4ed3c86099e3326c33f6202efec74b3e109756 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 26 Sep 2016 12:18:39 +0200 Subject: Fix Gtk type error, code cleanup, and documentation. (bzr r15133) --- src/ui/tools/mesh-tool.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index f2cf8c4a2..168e26b4c 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -265,14 +265,18 @@ sp_mesh_context_select_prev (ToolBase *event_context) Returns true if mouse cursor over mesh edge. */ static bool -sp_mesh_context_is_over_line (MeshTool *rc, SPItem *item, Geom::Point event_p) +sp_mesh_context_is_over_line (MeshTool *rc, SPCtrlLine *line, Geom::Point event_p) { + if (!SP_IS_CTRLCURVE(line) ) { + return false; + } + SPDesktop *desktop = SP_EVENT_CONTEXT (rc)->desktop; //Translate mouse point into proper coord system rc->mousepoint_doc = desktop->w2d(event_p); - SPCtrlCurve *curve = SP_CTRLCURVE(item); + SPCtrlCurve *curve = SP_CTRLCURVE(line); Geom::BezierCurveN<3> b( curve->p0, curve->p1, curve->p2, curve->p3 ); Geom::Coord coord = b.nearestTime( rc->mousepoint_doc ); // Coord == double Geom::Point nearest = b( coord ); @@ -425,6 +429,7 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) /** Handles all keyboard and mouse input for meshs. +Note: node/handle events are take care of elsewhere. */ bool MeshTool::root_handler(GdkEvent* event) { static bool dragging; @@ -458,8 +463,7 @@ bool MeshTool::root_handler(GdkEvent* event) { if (! drag->lines.empty()) { for (std::vector::const_iterator l = drag->lines.begin(); l != drag->lines.end() && (!over_line); ++l) { - line = (SPCtrlCurve*) (*l); - over_line |= sp_mesh_context_is_over_line (this, (SPItem*) line, Geom::Point(event->motion.x, event->motion.y)); + over_line |= sp_mesh_context_is_over_line (this, *l, Geom::Point(event->motion.x, event->motion.y)); } } @@ -594,7 +598,7 @@ bool MeshTool::root_handler(GdkEvent* event) { if (!drag->lines.empty()) { for (std::vector::const_iterator l = drag->lines.begin(); l != drag->lines.end() ; ++l) { - over_line |= sp_mesh_context_is_over_line (this, (SPItem*)(*l), Geom::Point(event->motion.x, event->motion.y)); + over_line |= sp_mesh_context_is_over_line (this, *l, Geom::Point(event->motion.x, event->motion.y)); } } @@ -625,8 +629,7 @@ bool MeshTool::root_handler(GdkEvent* event) { if (!drag->lines.empty()) { for (std::vector::const_iterator l = drag->lines.begin(); l != drag->lines.end() && (!over_line); ++l) { - line = (SPCtrlLine*)(*l); - over_line = sp_mesh_context_is_over_line (this, (SPItem*) line, Geom::Point(event->motion.x, event->motion.y)); + over_line = sp_mesh_context_is_over_line (this, *l, Geom::Point(event->motion.x, event->motion.y)); if (over_line) { break; @@ -925,6 +928,7 @@ bool MeshTool::root_handler(GdkEvent* event) { return ret; } +// Creates a new mesh gradient. static void sp_mesh_end_drag(MeshTool &rc) { SPDesktop *desktop = SP_EVENT_CONTEXT(&rc)->desktop; Inkscape::Selection *selection = desktop->getSelection(); -- cgit v1.2.3 From f2dd0550fc1a2d4deac985d28055f305b3ad7f64 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 26 Sep 2016 14:21:26 +0200 Subject: Remove unused variable. (bzr r15136) --- src/ui/tools/mesh-tool.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 168e26b4c..763685a0c 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -459,7 +459,6 @@ bool MeshTool::root_handler(GdkEvent* event) { if ( event->button.button == 1 ) { // Are we over a mesh line? bool over_line = false; - SPCtrlCurve *line = NULL; if (! drag->lines.empty()) { for (std::vector::const_iterator l = drag->lines.begin(); l != drag->lines.end() && (!over_line); ++l) { -- cgit v1.2.3 From f9ec83dbb254701f39d3b7a30c0bacb5eaae9ee9 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 27 Sep 2016 10:51:26 +0200 Subject: Rename to per SVG 2 CR specificiation. Note: has been repurposed to be a special shape that tightly wraps a mesh gradient. (bzr r15137) --- src/ui/tools/mesh-tool.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 763685a0c..aac8239f3 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -47,7 +47,7 @@ // Mesh specific #include "ui/tools/mesh-tool.h" -#include "sp-mesh.h" +#include "sp-mesh-gradient.h" #include "display/sp-ctrlcurve.h" using Inkscape::DocumentUndo; @@ -161,9 +161,9 @@ void MeshTool::selection_changed(Inkscape::Selection* /*sel*/) { // if (style && (style->fill.isPaintserver())) { // SPPaintServer *server = item->style->getFillPaintServer(); - // if ( SP_IS_MESH(server) ) { + // if ( SP_IS_MESHGRADIENT(server) ) { - // SPMesh *mg = SP_MESH(server); + // SPMeshGradient *mg = SP_MESHGRADIENT(server); // guint rows = 0;//mg->array.patches.size(); // for ( guint i = 0; i < rows; ++i ) { @@ -330,8 +330,8 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) SPDocument *doc = NULL; GrDrag *drag = rc->_grdrag; - std::map > points; - std::map items; + std::map > points; + std::map items; // Get list of selected draggers for each mesh. // For all selected draggers @@ -345,7 +345,7 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) if( d->point_type != POINT_MG_CORNER ) continue; // Find the gradient - SPMesh *gradient = SP_MESH( getGradient (d->item, d->fill_or_stroke) ); + SPMeshGradient *gradient = SP_MESHGRADIENT( getGradient (d->item, d->fill_or_stroke) ); // Collect points together for same gradient points[gradient].push_back( d->point_i ); @@ -354,8 +354,8 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) } // Loop over meshes. - for( std::map >::const_iterator iter = points.begin(); iter != points.end(); ++iter) { - SPMesh *mg = SP_MESH( iter->first ); + for( std::map >::const_iterator iter = points.begin(); iter != points.end(); ++iter) { + SPMeshGradient *mg = SP_MESHGRADIENT( iter->first ); if( iter->second.size() > 0 ) { guint noperation = 0; switch (operation) { -- cgit v1.2.3 From 2715ea15f1574bf2efc00610ac3c930dcfb30621 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Fri, 14 Oct 2016 10:39:17 +0200 Subject: Do not create unused "vector" gradient when creating mesh gradient. (bzr r15168) --- src/ui/tools/mesh-tool.cpp | 48 +++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index aac8239f3..5e88e26b3 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -38,6 +38,9 @@ #include "snap.h" #include "sp-namedview.h" #include "verbs.h" +#include "sp-text.h" +#include "sp-defs.h" +#include "style.h" // Gradient specific #include "gradient-drag.h" @@ -937,37 +940,42 @@ static void sp_mesh_end_drag(MeshTool &rc) { if (!selection->isEmpty()) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - int type = SP_GRADIENT_TYPE_MESH; - Inkscape::PaintTarget fill_or_stroke = (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE; + Inkscape::PaintTarget fill_or_stroke = + (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? + Inkscape::FOR_FILL : Inkscape::FOR_STROKE; - SPGradient *vector; - if (ec->item_to_select) { - // pick color from the object where drag started - vector = sp_gradient_vector_for_object(document, desktop, ec->item_to_select, fill_or_stroke); - } else { - // Starting from empty space: - // Sort items so that the topmost comes last - std::vector items(selection->items().begin(), selection->items().end()); - sort(items.begin(),items.end(),sp_item_repr_compare_position); - // take topmost - vector = sp_gradient_vector_for_object(document, desktop, SP_ITEM(items.back()), fill_or_stroke); - } - - // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs +// HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property(css, "fill-opacity", "1.0"); + Inkscape::XML::Document *xml_doc = document->getReprDoc(); + SPDefs *defs = document->getDefs(); + auto items= selection->items(); for(auto i=items.begin();i!=items.end();++i){ //FIXME: see above sp_repr_css_change_recursive((*i)->getRepr(), css, "style"); - sp_item_set_gradient(*i, vector, (SPGradientType) type, fill_or_stroke); + // Create mesh element + Inkscape::XML::Node *repr = xml_doc->createElement("svg:meshgradient"); - // We don't need to do anything. Mesh is already sized appropriately. - - (*i)->requestModified(SP_OBJECT_MODIFIED_FLAG); + // privates are garbage-collectable + repr->setAttribute("inkscape:collect", "always"); + + // Attach to document + defs->getRepr()->appendChild(repr); + Inkscape::GC::release(repr); + + // Get corresponding object + SPMeshGradient *mg = static_cast(document->getObjectByRepr(repr)); + mg->array.create(mg, *i, (*i)->visualBounds()); + + bool isText = SP_IS_TEXT(*i); + sp_style_set_property_url (*i, ((fill_or_stroke == Inkscape::FOR_FILL) ? "fill":"stroke"), + mg, isText); + + (*i)->requestModified(SP_OBJECT_MODIFIED_FLAG|SP_OBJECT_STYLE_MODIFIED_FLAG); } DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MESH, _("Create mesh")); -- cgit v1.2.3 From 32442aec84cc13f0a22fa1f07f3de701c6938e5d Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Fri, 14 Oct 2016 22:01:57 +0200 Subject: Implement copying of objects with mesh gradients. (bzr r15171) --- src/ui/tools/mesh-tool.cpp | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 5e88e26b3..33cdc3bda 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -59,7 +59,7 @@ namespace Inkscape { namespace UI { namespace Tools { -static void sp_mesh_end_drag(MeshTool &rc); +static void sp_mesh_new_default(MeshTool &rc); const std::string& MeshTool::getPrefsPath() { return MeshTool::prefsPath; @@ -474,24 +474,25 @@ bool MeshTool::root_handler(GdkEvent* event) { // always resets selection to the single object under cursor sp_mesh_context_split_near_point(this, selection->items().front(), this->mousepoint_doc, event->button.time); } else { + sp_mesh_new_default(*this); // Create a new gradient with default coordinates. - auto items= selection->items(); - for(auto i=items.begin();i!=items.end();++i){ - SPItem *item = *i; - SPGradientType new_type = SP_GRADIENT_TYPE_MESH; - Inkscape::PaintTarget fsmode = (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE; - -#ifdef DEBUG_MESH - std::cout << "sp_mesh_context_root_handler: creating new mesh on: " << (fsmode == Inkscape::FOR_FILL ? "Fill" : "Stroke") << std::endl; -#endif - SPGradient *vector = sp_gradient_vector_for_object(desktop->getDocument(), desktop, item, fsmode); - - SPGradient *priv = sp_item_set_gradient(item, vector, new_type, fsmode); - sp_gradient_reset_to_userspace(priv, item); - } - - DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MESH, - _("Create default mesh")); +// auto items= selection->items(); +// for(auto i=items.begin();i!=items.end();++i){ +// SPItem *item = *i; +// SPGradientType new_type = SP_GRADIENT_TYPE_MESH; +// Inkscape::PaintTarget fsmode = (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE; + +// #ifdef DEBUG_MESH +// std::cout << "sp_mesh_context_root_handler: creating new mesh on: " << (fsmode == Inkscape::FOR_FILL ? "Fill" : "Stroke") << std::endl; +// #endif +// SPGradient *vector = sp_gradient_vector_for_object(desktop->getDocument(), desktop, item, fsmode); + +// SPGradient *priv = sp_item_set_gradient(item, vector, new_type, fsmode); +// sp_gradient_reset_to_userspace(priv, item); +// } + +// DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MESH, +// _("Create default mesh")); } ret = TRUE; @@ -666,7 +667,7 @@ bool MeshTool::root_handler(GdkEvent* event) { } } else { // Create a new mesh gradient - sp_mesh_end_drag(*this); + sp_mesh_new_default(*this); } } else if (this->item_to_select) { if (over_line && line) { @@ -931,7 +932,7 @@ bool MeshTool::root_handler(GdkEvent* event) { } // Creates a new mesh gradient. -static void sp_mesh_end_drag(MeshTool &rc) { +static void sp_mesh_new_default(MeshTool &rc) { SPDesktop *desktop = SP_EVENT_CONTEXT(&rc)->desktop; Inkscape::Selection *selection = desktop->getSelection(); SPDocument *document = desktop->getDocument(); -- cgit v1.2.3 From 619f8b5d9173f2bcc9d9aefccee832d686724e79 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 17 Oct 2016 15:04:09 +0200 Subject: Add option to scale mesh to fit in bounding box. (bzr r15173) --- src/ui/tools/mesh-tool.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 33cdc3bda..cea508782 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -52,6 +52,7 @@ #include "ui/tools/mesh-tool.h" #include "sp-mesh-gradient.h" #include "display/sp-ctrlcurve.h" +#include "display/curve.h" using Inkscape::DocumentUndo; @@ -430,6 +431,71 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) } +/** + * Scale mesh to just fit into bbox of selected items. + */ +void +sp_mesh_context_fit_mesh_in_bbox (MeshTool *rc) +{ + +#ifdef DEBUG_MESH + std::cout << "sp_mesh_context_fit_mesh_in_bbox: entrance: Entrance"<< std::endl; +#endif + + SPDesktop *desktop = SP_EVENT_CONTEXT (rc)->desktop; + + Inkscape::Selection *selection = desktop->getSelection(); + if (selection == NULL) { + return; + } + + bool changed = false; + auto itemlist = selection->items(); + for (auto i=itemlist.begin(); i!=itemlist.end(); ++i) { + + SPItem *item = *i; + SPStyle *style = item->style; + + if (style && (style->fill.isPaintserver())) { + SPPaintServer *server = item->style->getFillPaintServer(); + if ( SP_IS_MESHGRADIENT(server) ) { + + SPMeshGradient *gradient = SP_MESHGRADIENT(server); + SPCurve * outline = gradient->array.outline_path(); + Geom::OptRect mesh_bbox = outline->get_pathvector().boundsExact(); + outline->unref(); + Geom::OptRect item_bbox = item->geometricBounds(); + + if ((*mesh_bbox).width() == 0) { + continue; + } + if ((*mesh_bbox).height() == 0) { + continue; + } + double scale_x = (*item_bbox).width() /(*mesh_bbox).width() ; + double scale_y = (*item_bbox).height()/(*mesh_bbox).height(); + + Geom::Translate t1(-(*mesh_bbox).min()); + Geom::Scale scale(scale_x,scale_y); + Geom::Translate t2((*item_bbox).min()); + Geom::Affine transform = t1 * scale * t2; + if (!transform.isIdentity() ) { + gradient->array.transform(transform); + gradient->array.write( gradient ); + gradient->requestModified(SP_OBJECT_MODIFIED_FLAG); + changed = true; + } + } + } + + } + if (changed) { + DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MESH, + _("Fit mesh inside bounding box.")); + } +} + + /** Handles all keyboard and mouse input for meshs. Note: node/handle events are take care of elsewhere. -- cgit v1.2.3 From 5a528acc28fee968aee4d79373625ed7d0fa553d Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 18 Oct 2016 19:07:20 +0200 Subject: Use geometric bounding box for fill, visual for stroke in creating mesh. (bzr r15175) --- src/ui/tools/mesh-tool.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index cea508782..c6983b94a 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -1036,7 +1036,8 @@ static void sp_mesh_new_default(MeshTool &rc) { // Get corresponding object SPMeshGradient *mg = static_cast(document->getObjectByRepr(repr)); - mg->array.create(mg, *i, (*i)->visualBounds()); + mg->array.create(mg, *i, (fill_or_stroke == Inkscape::FOR_FILL) ? + (*i)->geometricBounds() : (*i)->visualBounds()); bool isText = SP_IS_TEXT(*i); sp_style_set_property_url (*i, ((fill_or_stroke == Inkscape::FOR_FILL) ? "fill":"stroke"), @@ -1045,6 +1046,11 @@ static void sp_mesh_new_default(MeshTool &rc) { (*i)->requestModified(SP_OBJECT_MODIFIED_FLAG|SP_OBJECT_STYLE_MODIFIED_FLAG); } + if (css) { + sp_repr_css_attr_unref(css); + css = 0; + } + DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MESH, _("Create mesh")); // status text; we do not track coords because this branch is run once, not all the time -- cgit v1.2.3 From 430533b9a259eb3dac44755306dfb0fddb34951d Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 8 Nov 2016 15:05:30 +0100 Subject: Improve mesh handling in Fill and Stroke dialog. Create new meshes with alternating color/white pattern (makes it more obvious a mesh has been created). (bzr r15229) --- src/ui/tools/mesh-tool.cpp | 70 ++++++++++++++++------------------------------ 1 file changed, 24 insertions(+), 46 deletions(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index c6983b94a..87cbeef16 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -456,38 +456,33 @@ sp_mesh_context_fit_mesh_in_bbox (MeshTool *rc) SPItem *item = *i; SPStyle *style = item->style; - if (style && (style->fill.isPaintserver())) { - SPPaintServer *server = item->style->getFillPaintServer(); - if ( SP_IS_MESHGRADIENT(server) ) { - - SPMeshGradient *gradient = SP_MESHGRADIENT(server); - SPCurve * outline = gradient->array.outline_path(); - Geom::OptRect mesh_bbox = outline->get_pathvector().boundsExact(); - outline->unref(); - Geom::OptRect item_bbox = item->geometricBounds(); - - if ((*mesh_bbox).width() == 0) { - continue; - } - if ((*mesh_bbox).height() == 0) { - continue; + if (style) { + + if (style->fill.isPaintserver()) { + SPPaintServer *server = item->style->getFillPaintServer(); + if ( SP_IS_MESHGRADIENT(server) ) { + + Geom::OptRect item_bbox = item->geometricBounds(); + SPMeshGradient *gradient = SP_MESHGRADIENT(server); + if (gradient->array.fill_box( item_bbox )) { + changed = true; + } } - double scale_x = (*item_bbox).width() /(*mesh_bbox).width() ; - double scale_y = (*item_bbox).height()/(*mesh_bbox).height(); - - Geom::Translate t1(-(*mesh_bbox).min()); - Geom::Scale scale(scale_x,scale_y); - Geom::Translate t2((*item_bbox).min()); - Geom::Affine transform = t1 * scale * t2; - if (!transform.isIdentity() ) { - gradient->array.transform(transform); - gradient->array.write( gradient ); - gradient->requestModified(SP_OBJECT_MODIFIED_FLAG); - changed = true; + } + + if (style->stroke.isPaintserver()) { + SPPaintServer *server = item->style->getStrokePaintServer(); + if ( SP_IS_MESHGRADIENT(server) ) { + + Geom::OptRect item_bbox = item->visualBounds(); + SPMeshGradient *gradient = SP_MESHGRADIENT(server); + if (gradient->array.fill_box( item_bbox )) { + changed = true; + } } } + } - } if (changed) { DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MESH, @@ -540,25 +535,8 @@ bool MeshTool::root_handler(GdkEvent* event) { // always resets selection to the single object under cursor sp_mesh_context_split_near_point(this, selection->items().front(), this->mousepoint_doc, event->button.time); } else { - sp_mesh_new_default(*this); // Create a new gradient with default coordinates. -// auto items= selection->items(); -// for(auto i=items.begin();i!=items.end();++i){ -// SPItem *item = *i; -// SPGradientType new_type = SP_GRADIENT_TYPE_MESH; -// Inkscape::PaintTarget fsmode = (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE; - -// #ifdef DEBUG_MESH -// std::cout << "sp_mesh_context_root_handler: creating new mesh on: " << (fsmode == Inkscape::FOR_FILL ? "Fill" : "Stroke") << std::endl; -// #endif -// SPGradient *vector = sp_gradient_vector_for_object(desktop->getDocument(), desktop, item, fsmode); - -// SPGradient *priv = sp_item_set_gradient(item, vector, new_type, fsmode); -// sp_gradient_reset_to_userspace(priv, item); -// } - -// DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MESH, -// _("Create default mesh")); + sp_mesh_new_default(*this); } ret = TRUE; -- cgit v1.2.3 From 40c68a138368ffa620e91d7b3908e2593e424a8f Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 9 Nov 2016 10:17:03 +0100 Subject: Click-drag selects nodes rather than creates new mesh if mesh already exists. (bzr r15231) --- src/ui/tools/mesh-tool.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 87cbeef16..61793b8b3 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -561,8 +561,25 @@ bool MeshTool::root_handler(GdkEvent* event) { dragging = true; + // Check if object already has mesh... if it does, don't create new mesh with click-drag. + bool has_mesh = false; + if (!selection->isEmpty()) { + SPStyle *style = selection->items().front()->style; + if (style) { + Inkscape::PaintTarget fill_or_stroke = + (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? + Inkscape::FOR_FILL : Inkscape::FOR_STROKE; + SPPaintServer *server = + (fill_or_stroke == Inkscape::FOR_FILL) ? + style->getFillPaintServer(): + style->getStrokePaintServer(); + if (server && SP_IS_MESHGRADIENT(server)) + has_mesh = true; + } + } + Geom::Point button_dt = desktop->w2d(button_w); - if (event->button.state & GDK_SHIFT_MASK) { + if (event->button.state & GDK_SHIFT_MASK || has_mesh) { Inkscape::Rubberband::get(desktop)->start(desktop, button_dt); } else { // remember clicked item, disregarding groups, honoring Alt; do nothing with Crtl to -- cgit v1.2.3 From 09d3ef953448a73c20dc1a70c2f96e0ac5019f45 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 16 Nov 2016 16:22:39 +0100 Subject: Split selected rows/columns in half using Insert key. (bzr r15251) --- src/ui/tools/mesh-tool.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 61793b8b3..1f6e6ed87 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -389,6 +389,11 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) noperation += mg->array.color_pick( iter->second, items[iter->first] ); break; + case MG_CORNER_INSERT: + // std::cout << "INSERT" << std::endl; + noperation += mg->array.insert( iter->second ); + break; + default: std::cout << "sp_mesh_corner_operation: unknown operation" << std::endl; } @@ -420,6 +425,10 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) DocumentUndo::done(doc, SP_VERB_CONTEXT_MESH, _("Picked mesh corner color.")); break; + case MG_CORNER_INSERT: + DocumentUndo::done(doc, SP_VERB_CONTEXT_MESH, _("Inserted new row or column.")); + break; + default: std::cout << "sp_mesh_corner_operation: unknown operation" << std::endl; } @@ -896,11 +905,12 @@ bool MeshTool::root_handler(GdkEvent* event) { } break; + // Mesh Operations -------------------------------------------- + case GDK_KEY_Insert: case GDK_KEY_KP_Insert: // with any modifiers: - //sp_gradient_context_add_stops_between_selected_stops (rc); - std::cout << "Inserting stops between selected stops not implemented yet" << std::endl; + sp_mesh_context_corner_operation ( this, MG_CORNER_INSERT ); ret = TRUE; break; @@ -913,8 +923,6 @@ bool MeshTool::root_handler(GdkEvent* event) { } break; - // Mesh Operations -------------------------------------------- - case GDK_KEY_b: // Toggle mesh side between lineto and curveto. case GDK_KEY_B: if (MOD__ALT(event) && drag->isNonEmpty() && drag->hasSelection()) { -- cgit v1.2.3 From 776e4475404033912ed3b9d93d4ce2aeda62336c Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 17 Nov 2016 15:30:21 +0100 Subject: Fix status bar messages for meshes and gradients. (bzr r15256) --- src/ui/tools/mesh-tool.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 1f6e6ed87..6b1bfb88f 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -92,7 +92,19 @@ MeshTool::~MeshTool() { delete this->subselcon; } +// This must match GrPointType enum sp-gradient.h +// We should move this to a shared header (can't simply move to gradient.h since that would require +// including which messes up "N_" in extensions... argh!). const gchar *ms_handle_descr [] = { + N_("Linear gradient start"), //POINT_LG_BEGIN + N_("Linear gradient end"), + N_("Linear gradient mid stop"), + N_("Radial gradient center"), + N_("Radial gradient radius"), + N_("Radial gradient radius"), + N_("Radial gradient focus"), // POINT_RG_FOCUS + N_("Radial gradient mid stop"), + N_("Radial gradient mid stop"), N_("Mesh gradient corner"), N_("Mesh gradient handle"), N_("Mesh gradient tensor") @@ -124,6 +136,7 @@ void MeshTool::selection_changed(Inkscape::Selection* /*sel*/) { //TRANSLATORS: Mind the space in front. This is part of a compound message ngettext(" out of %d mesh handle"," out of %d mesh handles",n_tot), ngettext(" on %d selected object"," on %d selected objects",n_obj),NULL); + std::cout << " type: " << drag->singleSelectedDraggerSingleDraggableType() << std::endl; this->message_context->setF(Inkscape::NORMAL_MESSAGE, message,_(ms_handle_descr[drag->singleSelectedDraggerSingleDraggableType()]), n_tot, n_obj); } else { @@ -784,10 +797,11 @@ bool MeshTool::root_handler(GdkEvent* event) { case GDK_KEY_Shift_R: case GDK_KEY_Meta_L: // Meta is when you press Shift+Alt (at least on my machine) case GDK_KEY_Meta_R: - sp_event_show_modifier_tip (this->defaultMessageContext(), event, - _("FIXMECtrl: snap mesh angle"), - _("FIXMEShift: draw mesh around the starting point"), - NULL); + + // sp_event_show_modifier_tip (this->defaultMessageContext(), event, + // _("FIXMECtrl: snap mesh angle"), + // _("FIXMEShift: draw mesh around the starting point"), + // NULL); break; case GDK_KEY_A: -- cgit v1.2.3 From b6b5dbc76fe07238f1bbd259a8d8934c3c757eb7 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 17 Nov 2016 15:33:25 +0100 Subject: Remove debug line from last commit. (bzr r15257) --- src/ui/tools/mesh-tool.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 6b1bfb88f..0d2aafafc 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -136,7 +136,6 @@ void MeshTool::selection_changed(Inkscape::Selection* /*sel*/) { //TRANSLATORS: Mind the space in front. This is part of a compound message ngettext(" out of %d mesh handle"," out of %d mesh handles",n_tot), ngettext(" on %d selected object"," on %d selected objects",n_obj),NULL); - std::cout << " type: " << drag->singleSelectedDraggerSingleDraggableType() << std::endl; this->message_context->setF(Inkscape::NORMAL_MESSAGE, message,_(ms_handle_descr[drag->singleSelectedDraggerSingleDraggableType()]), n_tot, n_obj); } else { -- cgit v1.2.3 From 7aa5bd6f04cbc26d79239b07c6a91fbabf3015d1 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Fri, 18 Nov 2016 20:29:57 +0100 Subject: Improve mouse handling for mesh: * Double clicking an object will create a new mesh if one does not exist, otherwise clicking a line should now reliably divide the row/column. * Click-dragging will create a new mesh if one does not exist, otherwise it will do a rubberband selection of corner nodes. With Shift will add nodes, without will replace selected nodes. (bzr r15260) --- src/ui/tools/mesh-tool.cpp | 196 +++++++++++++++++++++++++++------------------ 1 file changed, 117 insertions(+), 79 deletions(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 0d2aafafc..fbde37856 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -278,32 +278,39 @@ sp_mesh_context_select_prev (ToolBase *event_context) } /** -Returns true if mouse cursor over mesh edge. +Returns vector of control lines mouse is over. Returns only first if 'first' is true. */ -static bool -sp_mesh_context_is_over_line (MeshTool *rc, SPCtrlLine *line, Geom::Point event_p) +static std::vector +sp_mesh_context_over_line (MeshTool *rc, Geom::Point event_p, bool first = true) { - if (!SP_IS_CTRLCURVE(line) ) { - return false; - } - SPDesktop *desktop = SP_EVENT_CONTEXT (rc)->desktop; //Translate mouse point into proper coord system rc->mousepoint_doc = desktop->w2d(event_p); - SPCtrlCurve *curve = SP_CTRLCURVE(line); - Geom::BezierCurveN<3> b( curve->p0, curve->p1, curve->p2, curve->p3 ); - Geom::Coord coord = b.nearestTime( rc->mousepoint_doc ); // Coord == double - Geom::Point nearest = b( coord ); + double tolerance = (double) SP_EVENT_CONTEXT(rc)->tolerance; - double dist_screen = Geom::L2 (rc->mousepoint_doc - nearest) * desktop->current_zoom(); + GrDrag *drag = rc->_grdrag; - double tolerance = (double) SP_EVENT_CONTEXT(rc)->tolerance; + std::vector selected; + + for (std::vector::const_iterator l = drag->lines.begin(); l != drag->lines.end(); ++l) { + if (!SP_IS_CTRLCURVE(*l)) continue; - bool close = (dist_screen < tolerance); + SPCtrlCurve *curve = SP_CTRLCURVE(*l); + Geom::BezierCurveN<3> b( curve->p0, curve->p1, curve->p2, curve->p3 ); + Geom::Coord coord = b.nearestTime( rc->mousepoint_doc ); // Coord == double + Geom::Point nearest = b( coord ); - return close; + double dist_screen = Geom::L2 (rc->mousepoint_doc - nearest) * desktop->current_zoom(); + if (dist_screen < tolerance) { + selected.push_back(*l); + if (first) { + break; + } + } + } + return selected; } @@ -539,25 +546,42 @@ bool MeshTool::root_handler(GdkEvent* event) { // Double click: // If over a mesh line, divide mesh row/column - // If not over a line, create new gradients for selected objects. + // If not over a line and no mesh, create new mesh for top selected object. if ( event->button.button == 1 ) { - // Are we over a mesh line? - bool over_line = false; - if (! drag->lines.empty()) { - for (std::vector::const_iterator l = drag->lines.begin(); l != drag->lines.end() && (!over_line); ++l) { - over_line |= sp_mesh_context_is_over_line (this, *l, Geom::Point(event->motion.x, event->motion.y)); - } - } + // Are we over a mesh line? + std::vector over_line = + sp_mesh_context_over_line(this, Geom::Point(event->motion.x, event->motion.y)); - if (over_line) { + if (!over_line.empty()) { // We take the first item in selection, because with doubleclick, the first click // always resets selection to the single object under cursor sp_mesh_context_split_near_point(this, selection->items().front(), this->mousepoint_doc, event->button.time); } else { // Create a new gradient with default coordinates. - sp_mesh_new_default(*this); + + // Check if object already has mesh... if it does, + // don't create new mesh with click-drag. + bool has_mesh = false; + if (!selection->isEmpty()) { + SPStyle *style = selection->items().front()->style; + if (style) { + Inkscape::PaintTarget fill_or_stroke = + (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? + Inkscape::FOR_FILL : Inkscape::FOR_STROKE; + SPPaintServer *server = + (fill_or_stroke == Inkscape::FOR_FILL) ? + style->getFillPaintServer(): + style->getStrokePaintServer(); + if (server && SP_IS_MESHGRADIENT(server)) + has_mesh = true; + } + } + + if (!has_mesh) { + sp_mesh_new_default(*this); + } } ret = TRUE; @@ -569,9 +593,10 @@ bool MeshTool::root_handler(GdkEvent* event) { #ifdef DEBUG_MESH std::cout << "sp_mesh_context_root_handler: GDK_BUTTON_PRESS" << std::endl; #endif + // Button down - // If Shift key down: do rubber band selection - // Else set origin for drag. A drag creates a new gradient if one does not exist + // If mesh already exists, do rubber band selection. + // Else set origin for drag which will create a new gradient. if ( event->button.button == 1 && !this->space_panning ) { Geom::Point button_w(event->button.x, event->button.y); @@ -582,7 +607,9 @@ bool MeshTool::root_handler(GdkEvent* event) { dragging = true; - // Check if object already has mesh... if it does, don't create new mesh with click-drag. + Geom::Point button_dt = desktop->w2d(button_w); + // Check if object already has mesh... if it does, + // don't create new mesh with click-drag. bool has_mesh = false; if (!selection->isEmpty()) { SPStyle *style = selection->items().front()->style; @@ -599,26 +626,25 @@ bool MeshTool::root_handler(GdkEvent* event) { } } - Geom::Point button_dt = desktop->w2d(button_w); - if (event->button.state & GDK_SHIFT_MASK || has_mesh) { + if (has_mesh) { Inkscape::Rubberband::get(desktop)->start(desktop, button_dt); - } else { - // remember clicked item, disregarding groups, honoring Alt; do nothing with Crtl to - // enable Ctrl+doubleclick of exactly the selected item(s) - if (!(event->button.state & GDK_CONTROL_MASK)) { - this->item_to_select = sp_event_context_find_item (desktop, button_w, event->button.state & GDK_MOD1_MASK, TRUE); - } + } - if (!selection->isEmpty()) { - SnapManager &m = desktop->namedview->snap_manager; - m.setup(desktop); - m.freeSnapReturnByRef(button_dt, Inkscape::SNAPSOURCE_NODE_HANDLE); - m.unSetup(); - } + // remember clicked item, disregarding groups, honoring Alt; do nothing with Crtl to + // enable Ctrl+doubleclick of exactly the selected item(s) + if (!(event->button.state & GDK_CONTROL_MASK)) { + this->item_to_select = sp_event_context_find_item (desktop, button_w, event->button.state & GDK_MOD1_MASK, TRUE); + } - this->origin = button_dt; + if (!selection->isEmpty()) { + SnapManager &m = desktop->namedview->snap_manager; + m.setup(desktop); + m.freeSnapReturnByRef(button_dt, Inkscape::SNAPSOURCE_NODE_HANDLE); + m.unSetup(); } + this->origin = button_dt; + ret = TRUE; } break; @@ -679,19 +705,14 @@ bool MeshTool::root_handler(GdkEvent* event) { } // Change cursor shape if over line - bool over_line = false; + std::vector over_line = + sp_mesh_context_over_line(this, Geom::Point(event->motion.x, event->motion.y)); - if (!drag->lines.empty()) { - for (std::vector::const_iterator l = drag->lines.begin(); l != drag->lines.end() ; ++l) { - over_line |= sp_mesh_context_is_over_line (this, *l, Geom::Point(event->motion.x, event->motion.y)); - } - } - - if (this->cursor_addnode && !over_line) { + if (this->cursor_addnode && over_line.empty()) { this->cursor_shape = cursor_gradient_xpm; this->sp_event_context_update_cursor(); this->cursor_addnode = false; - } else if (!this->cursor_addnode && over_line) { + } else if (!this->cursor_addnode && !over_line.empty()) { this->cursor_shape = cursor_gradient_add_xpm; this->sp_event_context_update_cursor(); this->cursor_addnode = true; @@ -708,23 +729,15 @@ bool MeshTool::root_handler(GdkEvent* event) { this->xp = this->yp = 0; if ( event->button.button == 1 && !this->space_panning ) { - // Check if over line - bool over_line = false; - SPCtrlLine *line = NULL; - - if (!drag->lines.empty()) { - for (std::vector::const_iterator l = drag->lines.begin(); l != drag->lines.end() && (!over_line); ++l) { - over_line = sp_mesh_context_is_over_line (this, *l, Geom::Point(event->motion.x, event->motion.y)); - if (over_line) { - break; - } - } - } + // Check if over line + std::vector over_line = + sp_mesh_context_over_line(this, Geom::Point(event->motion.x, event->motion.y)); if ( (event->button.state & GDK_CONTROL_MASK) && (event->button.state & GDK_MOD1_MASK ) ) { - if (over_line && line) { - sp_mesh_context_split_near_point(this, line->item, this->mousepoint_doc, 0); + if (!over_line.empty()) { + sp_mesh_context_split_near_point(this, over_line[0]->item, + this->mousepoint_doc, 0); ret = TRUE; } } else { @@ -737,22 +750,47 @@ bool MeshTool::root_handler(GdkEvent* event) { } if (!this->within_tolerance) { - // we've been dragging, either create a new gradient - // or rubberband-select if we have rubberband - Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop); - - if (r->is_started() && !this->within_tolerance) { - // this was a rubberband drag - if (r->getMode() == RUBBERBAND_MODE_RECT) { - Geom::OptRect const b = r->getRectangle(); - drag->selectRect(*b); + + // Check if object already has mesh... if it does, + // don't create new mesh with click-drag. + bool has_mesh = false; + if (!selection->isEmpty()) { + SPStyle *style = selection->items().front()->style; + if (style) { + Inkscape::PaintTarget fill_or_stroke = + (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? + Inkscape::FOR_FILL : Inkscape::FOR_STROKE; + SPPaintServer *server = + (fill_or_stroke == Inkscape::FOR_FILL) ? + style->getFillPaintServer(): + style->getStrokePaintServer(); + if (server && SP_IS_MESHGRADIENT(server)) + has_mesh = true; } - } else { - // Create a new mesh gradient + } + + if (!has_mesh) { sp_mesh_new_default(*this); + } else { + + // we've been dragging, either create a new gradient + // or rubberband-select if we have rubberband + Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop); + + if (r->is_started() && !this->within_tolerance) { + // this was a rubberband drag + if (r->getMode() == RUBBERBAND_MODE_RECT) { + Geom::OptRect const b = r->getRectangle(); + if (!(event->button.state & GDK_SHIFT_MASK)) { + drag->deselectAll(); + } + drag->selectRect(*b); + } + } } + } else if (this->item_to_select) { - if (over_line && line) { + if (!over_line.empty()) { // Clicked on an existing mesh line, don't change selection. This stops // possible change in selection during a double click with overlapping objects } else { @@ -760,6 +798,7 @@ bool MeshTool::root_handler(GdkEvent* event) { if (event->button.state & GDK_SHIFT_MASK) { selection->toggle(this->item_to_select); } else { + drag->deselectAll(); selection->set(this->item_to_select); } } @@ -1081,7 +1120,6 @@ static void sp_mesh_new_default(MeshTool &rc) { } } - } } } -- cgit v1.2.3 From e0e832245260d040f12bcebdf5b5e58763448e73 Mon Sep 17 00:00:00 2001 From: su_v <> Date: Sat, 19 Nov 2016 11:47:09 +0100 Subject: Add Shift-I shortcut for insert node. (bzr r15261) --- src/ui/tools/mesh-tool.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index fbde37856..0bcbd8572 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -966,6 +966,16 @@ bool MeshTool::root_handler(GdkEvent* event) { ret = TRUE; break; + case GDK_KEY_i: + case GDK_KEY_I: + if (MOD__SHIFT_ONLY(event)) { + // Shift+I - insert corners (alternate keybinding for keyboards + // that don't have the Insert key) + sp_mesh_context_corner_operation ( this, MG_CORNER_INSERT ); + ret = TRUE; + } + break; + case GDK_KEY_Delete: case GDK_KEY_KP_Delete: case GDK_KEY_BackSpace: -- cgit v1.2.3 From 03eabec553f7938b674a28ef8abe9b39e149fdb9 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sun, 20 Nov 2016 11:36:40 +0100 Subject: Preserve selection of corner nodes for some corner operations. (bzr r15262) --- src/ui/tools/mesh-tool.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 0bcbd8572..d01837c49 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -430,6 +430,7 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) case MG_CORNER_SIDE_ARC: DocumentUndo::done(doc, SP_VERB_CONTEXT_MESH, _("Approximated arc for mesh side.")); + drag->local_change = true; // Don't create new draggers. break; case MG_CORNER_TENSOR_TOGGLE: @@ -438,10 +439,12 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) case MG_CORNER_COLOR_SMOOTH: DocumentUndo::done(doc, SP_VERB_CONTEXT_MESH, _("Smoothed mesh corner color.")); + drag->local_change = true; break; case MG_CORNER_COLOR_PICK: DocumentUndo::done(doc, SP_VERB_CONTEXT_MESH, _("Picked mesh corner color.")); + drag->local_change = true; break; case MG_CORNER_INSERT: @@ -454,7 +457,9 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) } } } - drag->updateDraggers(); + + // Not needed. Update is done via gr_drag_sel_modified(). + // drag->updateDraggers(); } -- cgit v1.2.3 From b045203981fee53df04a760039ed2730d854f8fd Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 21 Nov 2016 12:34:27 +0100 Subject: Keep corner nodes selected when possible for corner operations. (bzr r15264) --- src/ui/tools/mesh-tool.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index d01837c49..7f05906f4 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -355,12 +355,13 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) std::map > points; std::map items; - + std::map fill_or_stroke; + // Get list of selected draggers for each mesh. - // For all selected draggers + // For all selected draggers (a dragger may include draggerables from different meshes). for (std::set::const_iterator i = drag->selected.begin(); i != drag->selected.end(); ++i) { GrDragger *dragger = *i; - // For all draggables of dragger + // For all draggables of dragger (a draggable corresponds to a unique mesh). for (std::vector::const_iterator j = dragger->draggables.begin(); j != dragger->draggables.end() ; ++j) { GrDraggable *d = *j; @@ -373,6 +374,7 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) // Collect points together for same gradient points[gradient].push_back( d->point_i ); items[gradient] = d->item; + fill_or_stroke[gradient] = d->fill_or_stroke ? Inkscape::FOR_FILL: Inkscape::FOR_STROKE; } } @@ -426,6 +428,7 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) case MG_CORNER_SIDE_TOGGLE: DocumentUndo::done(doc, SP_VERB_CONTEXT_MESH, _("Toggled mesh path type.")); + drag->local_change = true; // Don't create new draggers. break; case MG_CORNER_SIDE_ARC: @@ -435,16 +438,17 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) case MG_CORNER_TENSOR_TOGGLE: DocumentUndo::done(doc, SP_VERB_CONTEXT_MESH, _("Toggled mesh tensors.")); + drag->local_change = true; // Don't create new draggers. break; case MG_CORNER_COLOR_SMOOTH: DocumentUndo::done(doc, SP_VERB_CONTEXT_MESH, _("Smoothed mesh corner color.")); - drag->local_change = true; + drag->local_change = true; // Don't create new draggers. break; case MG_CORNER_COLOR_PICK: DocumentUndo::done(doc, SP_VERB_CONTEXT_MESH, _("Picked mesh corner color.")); - drag->local_change = true; + drag->local_change = true; // Don't create new draggers. break; case MG_CORNER_INSERT: -- cgit v1.2.3 From c4922f5c1b54802623bc43f04191495e2338fc24 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 23 Nov 2016 10:23:22 +0100 Subject: Select mesh nodes by clicking on control lines. (bzr r15267) --- src/ui/tools/mesh-tool.cpp | 52 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 11 deletions(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 7f05906f4..61232fb2c 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -41,6 +41,7 @@ #include "sp-text.h" #include "sp-defs.h" #include "style.h" +#include "ui/control-manager.h" // Gradient specific #include "gradient-drag.h" @@ -280,7 +281,7 @@ sp_mesh_context_select_prev (ToolBase *event_context) /** Returns vector of control lines mouse is over. Returns only first if 'first' is true. */ -static std::vector +static std::vector sp_mesh_context_over_line (MeshTool *rc, Geom::Point event_p, bool first = true) { SPDesktop *desktop = SP_EVENT_CONTEXT (rc)->desktop; @@ -292,7 +293,7 @@ sp_mesh_context_over_line (MeshTool *rc, Geom::Point event_p, bool first = true) GrDrag *drag = rc->_grdrag; - std::vector selected; + std::vector selected; for (std::vector::const_iterator l = drag->lines.begin(); l != drag->lines.end(); ++l) { if (!SP_IS_CTRLCURVE(*l)) continue; @@ -304,7 +305,7 @@ sp_mesh_context_over_line (MeshTool *rc, Geom::Point event_p, bool first = true) double dist_screen = Geom::L2 (rc->mousepoint_doc - nearest) * desktop->current_zoom(); if (dist_screen < tolerance) { - selected.push_back(*l); + selected.push_back(curve); if (first) { break; } @@ -560,7 +561,7 @@ bool MeshTool::root_handler(GdkEvent* event) { if ( event->button.button == 1 ) { // Are we over a mesh line? - std::vector over_line = + std::vector over_line = sp_mesh_context_over_line(this, Geom::Point(event->motion.x, event->motion.y)); if (!over_line.empty()) { @@ -607,6 +608,31 @@ bool MeshTool::root_handler(GdkEvent* event) { // If mesh already exists, do rubber band selection. // Else set origin for drag which will create a new gradient. if ( event->button.button == 1 && !this->space_panning ) { + + // Are we over a mesh line? + std::vector over_line = + sp_mesh_context_over_line(this, Geom::Point(event->motion.x, event->motion.y), false); + + if (!over_line.empty()) { + for (std::vector::const_iterator it = over_line.begin(); + it != over_line.end(); ++it ) { + SPItem *item = (*it)->item; + Inkscape::PaintTarget fill_or_stroke = + (*it)->is_fill ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE; + GrDragger* dragger0 = drag->getDraggerFor(item, POINT_MG_CORNER, (*it)->corner0, fill_or_stroke); + GrDragger* dragger1 = drag->getDraggerFor(item, POINT_MG_CORNER, (*it)->corner1, fill_or_stroke); + bool add = (event->button.state & GDK_SHIFT_MASK); + bool toggle = (event->button.state & GDK_CONTROL_MASK); + if ( !add && !toggle ) { + drag->deselectAll(); + } + drag->setSelected( dragger0, true, !toggle ); + drag->setSelected( dragger1, true, !toggle ); + } + ret = true; + break; // To avoid putting the following code in an else block. + } + Geom::Point button_w(event->button.x, event->button.y); // save drag origin @@ -714,7 +740,7 @@ bool MeshTool::root_handler(GdkEvent* event) { } // Change cursor shape if over line - std::vector over_line = + std::vector over_line = sp_mesh_context_over_line(this, Geom::Point(event->motion.x, event->motion.y)); if (this->cursor_addnode && over_line.empty()) { @@ -740,7 +766,7 @@ bool MeshTool::root_handler(GdkEvent* event) { if ( event->button.button == 1 && !this->space_panning ) { // Check if over line - std::vector over_line = + std::vector over_line = sp_mesh_context_over_line(this, Geom::Point(event->motion.x, event->motion.y)); if ( (event->button.state & GDK_CONTROL_MASK) && (event->button.state & GDK_MOD1_MASK ) ) { @@ -812,11 +838,16 @@ bool MeshTool::root_handler(GdkEvent* event) { } } } else { - // click in an empty space; do the same as Esc - if (!drag->selected.empty()) { - drag->deselectAll(); + if (!over_line.empty()) { + // Clicked on an existing mesh line, don't change selection. This stops + // possible change in selection during a double click with overlapping objects } else { - selection->clear(); + // click in an empty space; do the same as Esc + if (!drag->selected.empty()) { + drag->deselectAll(); + } else { + selection->clear(); + } } } @@ -989,7 +1020,6 @@ bool MeshTool::root_handler(GdkEvent* event) { case GDK_KEY_KP_Delete: case GDK_KEY_BackSpace: if ( !drag->selected.empty() ) { - std::cout << "Deleting mesh stops not implemented yet" << std::endl; ret = TRUE; } break; -- cgit v1.2.3 From d87cfa4971963dfb8118ce31e169854fce85bccd Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 1 Dec 2016 14:05:02 +0100 Subject: Add toggles for handle visibility, editing fill, and editing stroke. (bzr r15289) --- src/ui/tools/mesh-tool.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 61232fb2c..b05caf43a 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -75,6 +75,9 @@ MeshTool::MeshTool() : ToolBase(cursor_gradient_xpm, 4, 4) , cursor_addnode(false) , node_added(false) + , show_handles(true) + , edit_fill(true) + , edit_stroke(true) // TODO: Why are these connections stored as pointers? , selcon(NULL) , subselcon(NULL) @@ -253,7 +256,25 @@ void MeshTool::setup() { ) )); + sp_event_context_read(this, "show_handles"); + sp_event_context_read(this, "edit_fill"); + sp_event_context_read(this, "edit_stroke"); + this->selection_changed(selection); + +} + +void MeshTool::set(const Inkscape::Preferences::Entry& value) { + Glib::ustring entry_name = value.getEntryName(); + if (entry_name == "show_handles") { + this->show_handles = value.getBool(true); + } else if (entry_name == "edit_fill") { + this->edit_fill = value.getBool(true); + } else if (entry_name == "edit_stroke") { + this->edit_stroke = value.getBool(true); + } else { + ToolBase::set(value); + } } void -- cgit v1.2.3 From c0895d809dfa89df7242e9bdc838755ed63c9218 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Fri, 2 Dec 2016 10:15:24 +0100 Subject: Ensure new mesh is immediately editable. (bzr r15290) --- src/ui/tools/mesh-tool.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index b05caf43a..e628094d9 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -1136,6 +1136,16 @@ static void sp_mesh_new_default(MeshTool &rc) { (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE; + // Ensure mesh is immediately editable. + // Editting both fill and stroke at same time doesn't work well so avoid. + if (fill_or_stroke == Inkscape::FOR_FILL) { + prefs->setBool("/tools/mesh/edit_fill", true ); + prefs->setBool("/tools/mesh/edit_stroke", false); + } else { + prefs->setBool("/tools/mesh/edit_fill", false); + prefs->setBool("/tools/mesh/edit_stroke", true ); + } + // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider for all tabs SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property(css, "fill-opacity", "1.0"); -- cgit v1.2.3 From 09f59f6114bb5d31bdc8bf0768cd55a111a35349 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 1 Feb 2017 21:19:06 +0100 Subject: Fix typo. (bzr r15463) --- src/ui/tools/mesh-tool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/ui/tools/mesh-tool.cpp') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index e628094d9..ac43b6c9d 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -1137,7 +1137,7 @@ static void sp_mesh_new_default(MeshTool &rc) { Inkscape::FOR_FILL : Inkscape::FOR_STROKE; // Ensure mesh is immediately editable. - // Editting both fill and stroke at same time doesn't work well so avoid. + // Editing both fill and stroke at same time doesn't work well so avoid. if (fill_or_stroke == Inkscape::FOR_FILL) { prefs->setBool("/tools/mesh/edit_fill", true ); prefs->setBool("/tools/mesh/edit_stroke", false); -- cgit v1.2.3