diff options
| author | Jabiertxof <jtx@jtx> | 2017-01-24 14:16:06 +0000 |
|---|---|---|
| committer | Jabiertxof <jtx@jtx> | 2017-01-24 14:16:06 +0000 |
| commit | b25ebda10578c5d697db9716e3c2b70950d33e45 (patch) | |
| tree | 4635b8b3f65600cfd54b5465b906ae42165b0674 /src/ui/tools | |
| parent | Fix some bugs (diff) | |
| parent | fix nodes reverting back during editing (diff) | |
| download | inkscape-b25ebda10578c5d697db9716e3c2b70950d33e45.tar.gz inkscape-b25ebda10578c5d697db9716e3c2b70950d33e45.zip | |
fixing to new trunk
(bzr r15142.1.38)
Diffstat (limited to 'src/ui/tools')
| -rw-r--r-- | src/ui/tools/calligraphic-tool.cpp | 4 | ||||
| -rw-r--r-- | src/ui/tools/eraser-tool.cpp | 12 | ||||
| -rw-r--r-- | src/ui/tools/flood-tool.cpp | 10 | ||||
| -rw-r--r-- | src/ui/tools/gradient-tool.cpp | 18 | ||||
| -rw-r--r-- | src/ui/tools/mesh-tool.cpp | 412 | ||||
| -rw-r--r-- | src/ui/tools/mesh-tool.h | 27 | ||||
| -rw-r--r-- | src/ui/tools/node-tool.cpp | 34 | ||||
| -rw-r--r-- | src/ui/tools/node-tool.h | 9 | ||||
| -rw-r--r-- | src/ui/tools/spray-tool.cpp | 4 | ||||
| -rw-r--r-- | src/ui/tools/tweak-tool.cpp | 185 |
10 files changed, 450 insertions, 265 deletions
diff --git a/src/ui/tools/calligraphic-tool.cpp b/src/ui/tools/calligraphic-tool.cpp index 9b4dbb1a2..c2b86b538 100644 --- a/src/ui/tools/calligraphic-tool.cpp +++ b/src/ui/tools/calligraphic-tool.cpp @@ -921,10 +921,10 @@ void CalligraphicTool::set_to_accumulated(bool unionize, bool subtract) { if (unionize) { desktop->getSelection()->add(this->repr); - sp_selected_path_union_skip_undo(desktop->getSelection()); + desktop->getSelection()->pathUnion(true); } else if (subtract) { desktop->getSelection()->add(this->repr); - sp_selected_path_diff_skip_undo(desktop->getSelection()); + desktop->getSelection()->pathDiff(true); } else { if (this->keep_selected) { desktop->getSelection()->set(this->repr); diff --git a/src/ui/tools/eraser-tool.cpp b/src/ui/tools/eraser-tool.cpp index 4f941e534..ae312e054 100644 --- a/src/ui/tools/eraser-tool.cpp +++ b/src/ui/tools/eraser-tool.cpp @@ -714,7 +714,7 @@ void EraserTool::set_to_accumulated() { Inkscape::GC::release(dup); // parent takes over selection->set(dup); if (!this->nowidth) { - sp_selected_path_union_skip_undo(selection); + selection->pathUnion(true); } selection->add(item); if(item->style->fill_rule.value == SP_WIND_RULE_EVENODD){ @@ -725,9 +725,9 @@ void EraserTool::set_to_accumulated() { css = 0; } if (this->nowidth) { - sp_selected_path_cut_skip_undo(selection); + selection->pathCut(true); } else { - sp_selected_path_diff_skip_undo(selection); + selection->pathDiff(true); } workDone = true; // TODO set this only if something was cut. bool break_apart = prefs->getBool("/tools/eraser/break_apart", false); @@ -762,7 +762,7 @@ void EraserTool::set_to_accumulated() { this->repr->parent()->appendChild(dup); Inkscape::GC::release(dup); // parent takes over selection->set(dup); - sp_selected_path_union_skip_undo(selection); + selection->pathUnion(true); if (bbox && bbox->intersects(*eraserBbox)) { SPClipPath *clip_path = item->clip_ref->getObject(); if (clip_path) { @@ -786,7 +786,7 @@ void EraserTool::set_to_accumulated() { sp_object_unref(clip_path); selection->raiseToTop(true); selection->add(dup_clip); - sp_selected_path_diff_skip_undo(selection); + selection->pathDiff(true); SPItem * clip = SP_ITEM(*(selection->items().begin())); } } @@ -802,7 +802,7 @@ void EraserTool::set_to_accumulated() { rect->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); selection->raiseToTop(true); selection->add(rect); - sp_selected_path_diff_skip_undo(selection); + selection->pathDiff(true); } selection->raiseToTop(true); selection->add(item); diff --git a/src/ui/tools/flood-tool.cpp b/src/ui/tools/flood-tool.cpp index 0b893a7ba..1801a0ea0 100644 --- a/src/ui/tools/flood-tool.cpp +++ b/src/ui/tools/flood-tool.cpp @@ -89,10 +89,10 @@ Glib::ustring ch_init[8] = { const std::vector<Glib::ustring> FloodTool::channel_list( ch_init, ch_init+8 ); Glib::ustring gap_init[4] = { - C_("Flood autogap", "None"), - C_("Flood autogap", "Small"), - C_("Flood autogap", "Medium"), - C_("Flood autogap", "Large") + NC_("Flood autogap", "None"), + NC_("Flood autogap", "Small"), + NC_("Flood autogap", "Medium"), + NC_("Flood autogap", "Large") }; const std::vector<Glib::ustring> FloodTool::gap_list( gap_init, gap_init+4 ); @@ -446,7 +446,7 @@ static void do_trace(bitmap_coords_info bci, guchar *trace_px, SPDesktop *deskto ngettext("Area filled, path with <b>%d</b> node created and unioned with selection.","Area filled, path with <b>%d</b> nodes created and unioned with selection.", SP_PATH(reprobj)->nodesInPath()), SP_PATH(reprobj)->nodesInPath() ); selection->add(reprobj); - sp_selected_path_union_skip_undo(desktop->getSelection()); + selection->pathUnion(true); } else { desktop->messageStack()->flashF( Inkscape::WARNING_MESSAGE, ngettext("Area filled, path with <b>%d</b> node created.","Area filled, path with <b>%d</b> nodes created.", diff --git a/src/ui/tools/gradient-tool.cpp b/src/ui/tools/gradient-tool.cpp index 16df225e0..750596808 100644 --- a/src/ui/tools/gradient-tool.cpp +++ b/src/ui/tools/gradient-tool.cpp @@ -79,6 +79,9 @@ GradientTool::~GradientTool() { 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 <glibmm/i18n.h> which messes up "N_" in extensions... argh!). const gchar *gr_handle_descr [] = { N_("Linear gradient <b>start</b>"), //POINT_LG_BEGIN N_("Linear gradient <b>end</b>"), @@ -88,7 +91,10 @@ const gchar *gr_handle_descr [] = { N_("Radial gradient <b>radius</b>"), N_("Radial gradient <b>focus</b>"), // POINT_RG_FOCUS N_("Radial gradient <b>mid stop</b>"), - N_("Radial gradient <b>mid stop</b>") + N_("Radial gradient <b>mid stop</b>"), + N_("Mesh gradient <b>corner</b>"), + N_("Mesh gradient <b>handle</b>"), + N_("Mesh gradient <b>tensor</b>") }; void GradientTool::selection_changed(Inkscape::Selection*) { @@ -831,6 +837,16 @@ bool GradientTool::root_handler(GdkEvent* event) { ret = TRUE; break; + case GDK_KEY_i: + case GDK_KEY_I: + if (MOD__SHIFT_ONLY(event)) { + // Shift+I - insert stops (alternate keybinding for keyboards + // that don't have the Insert key) + sp_gradient_context_add_stops_between_selected_stops (this); + ret = TRUE; + } + break; + case GDK_KEY_Delete: case GDK_KEY_KP_Delete: case GDK_KEY_BackSpace: diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index c6983b94a..e628094d9 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" @@ -74,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) @@ -92,7 +96,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 <glibmm/i18n.h> which messes up "N_" in extensions... argh!). const gchar *ms_handle_descr [] = { + N_("Linear gradient <b>start</b>"), //POINT_LG_BEGIN + N_("Linear gradient <b>end</b>"), + N_("Linear gradient <b>mid stop</b>"), + N_("Radial gradient <b>center</b>"), + N_("Radial gradient <b>radius</b>"), + N_("Radial gradient <b>radius</b>"), + N_("Radial gradient <b>focus</b>"), // POINT_RG_FOCUS + N_("Radial gradient <b>mid stop</b>"), + N_("Radial gradient <b>mid stop</b>"), N_("Mesh gradient <b>corner</b>"), N_("Mesh gradient <b>handle</b>"), N_("Mesh gradient <b>tensor</b>") @@ -240,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 @@ -266,32 +300,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<SPCtrlCurve *> +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; + + GrDrag *drag = rc->_grdrag; - double dist_screen = Geom::L2 (rc->mousepoint_doc - nearest) * desktop->current_zoom(); + std::vector<SPCtrlCurve *> selected; - double tolerance = (double) SP_EVENT_CONTEXT(rc)->tolerance; + for (std::vector<SPCtrlLine *>::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(curve); + if (first) { + break; + } + } + } + return selected; } @@ -336,12 +377,13 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) std::map<SPMeshGradient*, std::vector<guint> > points; std::map<SPMeshGradient*, SPItem*> items; - + std::map<SPMeshGradient*, Inkscape::PaintTarget> 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<GrDragger *>::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<GrDraggable *>::const_iterator j = dragger->draggables.begin(); j != dragger->draggables.end() ; ++j) { GrDraggable *d = *j; @@ -354,6 +396,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; } } @@ -389,6 +432,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; } @@ -402,22 +450,31 @@ 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: 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: 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; // 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; // Don't create new draggers. + break; + + case MG_CORNER_INSERT: + DocumentUndo::done(doc, SP_VERB_CONTEXT_MESH, _("Inserted new row or column.")); break; default: @@ -426,7 +483,9 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) } } } - drag->updateDraggers(); + + // Not needed. Update is done via gr_drag_sel_modified(). + // drag->updateDraggers(); } @@ -456,38 +515,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, @@ -523,42 +577,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<SPCtrlLine *>::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<SPCtrlCurve *> 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 { - 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")); + + // 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; @@ -570,10 +624,36 @@ 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 ) { + + // Are we over a mesh line? + std::vector<SPCtrlCurve *> over_line = + sp_mesh_context_over_line(this, Geom::Point(event->motion.x, event->motion.y), false); + + if (!over_line.empty()) { + for (std::vector<SPCtrlCurve *>::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 @@ -584,25 +664,43 @@ bool MeshTool::root_handler(GdkEvent* event) { dragging = true; Geom::Point button_dt = desktop->w2d(button_w); - if (event->button.state & GDK_SHIFT_MASK) { - 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); + // 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 (!selection->isEmpty()) { - SnapManager &m = desktop->namedview->snap_manager; - m.setup(desktop); - m.freeSnapReturnByRef(button_dt, Inkscape::SNAPSOURCE_NODE_HANDLE); - m.unSetup(); - } + if (has_mesh) { + Inkscape::Rubberband::get(desktop)->start(desktop, button_dt); + } - this->origin = button_dt; + // 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(); + } + + this->origin = button_dt; + ret = TRUE; } break; @@ -663,19 +761,14 @@ bool MeshTool::root_handler(GdkEvent* event) { } // Change cursor shape if over line - bool over_line = false; + std::vector<SPCtrlCurve *> over_line = + sp_mesh_context_over_line(this, Geom::Point(event->motion.x, event->motion.y)); - if (!drag->lines.empty()) { - for (std::vector<SPCtrlLine *>::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; @@ -692,23 +785,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<SPCtrlLine *>::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<SPCtrlCurve *> 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 { @@ -721,22 +806,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 { @@ -744,15 +854,21 @@ 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); } } } 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(); + } } } @@ -780,10 +896,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, - _("FIXME<b>Ctrl</b>: snap mesh angle"), - _("FIXME<b>Shift</b>: draw mesh around the starting point"), - NULL); + + // sp_event_show_modifier_tip (this->defaultMessageContext(), event, + // _("FIXME<b>Ctrl</b>: snap mesh angle"), + // _("FIXME<b>Shift</b>: draw mesh around the starting point"), + // NULL); break; case GDK_KEY_A: @@ -901,25 +1018,33 @@ 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; + 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: if ( !drag->selected.empty() ) { - std::cout << "Deleting mesh stops not implemented yet" << std::endl; ret = TRUE; } 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()) { @@ -1011,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"); @@ -1065,7 +1200,6 @@ static void sp_mesh_new_default(MeshTool &rc) { } } - } } } diff --git a/src/ui/tools/mesh-tool.h b/src/ui/tools/mesh-tool.h index f142bfd9c..1f012dc53 100644 --- a/src/ui/tools/mesh-tool.h +++ b/src/ui/tools/mesh-tool.h @@ -31,29 +31,34 @@ namespace Tools { class MeshTool : public ToolBase { public: - MeshTool(); - virtual ~MeshTool(); + MeshTool(); + virtual ~MeshTool(); Geom::Point origin; - bool cursor_addnode; - - bool node_added; - Geom::Point mousepoint_doc; // stores mousepoint when over_line in doc coords sigc::connection *selcon; sigc::connection *subselcon; - static const std::string prefsPath; + static const std::string prefsPath; - virtual void setup(); - virtual bool root_handler(GdkEvent* event); + virtual void setup(); + virtual void set(const Inkscape::Preferences::Entry& val); + virtual bool root_handler(GdkEvent* event); - virtual const std::string& getPrefsPath(); + virtual const std::string& getPrefsPath(); private: - void selection_changed(Inkscape::Selection* sel); + void selection_changed(Inkscape::Selection* sel); + + bool cursor_addnode; + bool node_added; + bool show_handles; + bool edit_fill; + bool edit_stroke; + + }; void sp_mesh_context_select_next(ToolBase *event_context); diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp index f3679b40f..0c948c91c 100644 --- a/src/ui/tools/node-tool.cpp +++ b/src/ui/tools/node-tool.cpp @@ -32,6 +32,8 @@ #include "sp-text.h" #include "ui/control-manager.h" #include "ui/tools/node-tool.h" +#include "ui/tools-switch.h" +#include "ui/tools/tool-base.h" #include "ui/tool/control-point-selection.h" #include "ui/tool/event-utils.h" #include "ui/tool/multi-path-manipulator.h" @@ -209,7 +211,7 @@ void NodeTool::setup() { this->_sizeUpdatedConn = ControlManager::getManager().connectCtrlSizeChanged( sigc::mem_fun(this, &NodeTool::handleControlUiStyleChange) ); - + this->helperpath_tmpitem = NULL; this->_selected_nodes = new Inkscape::UI::ControlPointSelection(this->desktop, this->_transform_handle_group); data.node_data.selection = this->_selected_nodes; @@ -237,7 +239,6 @@ void NodeTool::setup() { ))) ); - this->helperpath_tmpitem = NULL; this->cursor_drag = false; this->show_transform_handles = true; this->single_node_transform_handles = false; @@ -270,29 +271,34 @@ void NodeTool::setup() { } this->desktop->emitToolSubselectionChanged(NULL); // sets the coord entry fields to inactive - this->update_helperpath(); + sp_update_helperpath(); } // show helper paths of the applied LPE, if any -void NodeTool::update_helperpath () { - Inkscape::Selection *selection = this->desktop->getSelection(); - - if (this->helperpath_tmpitem) { - this->desktop->remove_temporary_canvasitem(this->helperpath_tmpitem); - this->helperpath_tmpitem = NULL; +void sp_update_helperpath() { + SPDesktop * desktop = SP_ACTIVE_DESKTOP; + if (!desktop || !tools_isactive(desktop, TOOLS_NODES)) { + return; + } + Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>(desktop->event_context); + Inkscape::Selection *selection = desktop->getSelection(); + if (nt->helperpath_tmpitem) { + desktop->remove_temporary_canvasitem(nt->helperpath_tmpitem); + nt->helperpath_tmpitem = NULL; } if (SP_IS_LPE_ITEM(selection->singleItem())) { Inkscape::LivePathEffect::Effect *lpe = SP_LPE_ITEM(selection->singleItem())->getCurrentLPE(); if (lpe && lpe->isVisible()/* && lpe->showOrigPath()*/) { - Inkscape::UI::ControlPointSelection *selectionNodes = _selected_nodes; + + Inkscape::UI::ControlPointSelection *selectionNodes = nt->_selected_nodes; std::vector<Geom::Point> selectedNodesPositions; for (Inkscape::UI::ControlPointSelection::iterator i = selectionNodes->begin(); i != selectionNodes->end(); ++i) { Inkscape::UI::Node *n = dynamic_cast<Inkscape::UI::Node *>(*i); selectedNodesPositions.push_back(n->position()); } lpe->setSelectedNodePoints(selectedNodesPositions); - lpe->setCurrentZoom(this->desktop->current_zoom()); + lpe->setCurrentZoom(desktop->current_zoom()); SPCurve *c = new SPCurve(); SPCurve *cc = new SPCurve(); std::vector<Geom::PathVector> cs = lpe->getCanvasIndicators(SP_LPE_ITEM(selection->singleItem())); @@ -302,11 +308,11 @@ void NodeTool::update_helperpath () { cc->reset(); } if (!c->is_empty()) { - SPCanvasItem *helperpath = sp_canvas_bpath_new(this->desktop->getTempGroup(), c, true); + SPCanvasItem *helperpath = sp_canvas_bpath_new(desktop->getTempGroup(), c, true); sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(helperpath), 0x0000ff9A, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(helperpath), 0, SP_WIND_RULE_NONZERO); sp_canvas_item_affine_absolute(helperpath, selection->singleItem()->i2dt_affine()); - this->helperpath_tmpitem = this->desktop->add_temporary_canvasitem(helperpath, 0); + nt->helperpath_tmpitem = desktop->add_temporary_canvasitem(helperpath, 0); } c->unref(); cc->unref(); @@ -468,7 +474,7 @@ bool NodeTool::root_handler(GdkEvent* event) { switch (event->type) { case GDK_MOTION_NOTIFY: { - update_helperpath(); + sp_update_helperpath(); combine_motion_events(desktop->canvas, event->motion, 0); SPItem *over_item = sp_event_context_find_item (desktop, event_point(event->button), FALSE, TRUE); diff --git a/src/ui/tools/node-tool.h b/src/ui/tools/node-tool.h index 8342d66a6..983ba6cee 100644 --- a/src/ui/tools/node-tool.h +++ b/src/ui/tools/node-tool.h @@ -49,14 +49,14 @@ public: Inkscape::UI::ControlPointSelection* _selected_nodes; Inkscape::UI::MultiPathManipulator* _multipath; - + Inkscape::Display::TemporaryItem *helperpath_tmpitem; + bool edit_clipping_paths; bool edit_masks; static const std::string prefsPath; virtual void setup(); - virtual void update_helperpath(); virtual void set(const Inkscape::Preferences::Entry& val); virtual bool root_handler(GdkEvent* event); @@ -68,7 +68,7 @@ private: sigc::connection _sizeUpdatedConn; SPItem *flashed_item; - Inkscape::Display::TemporaryItem *helperpath_tmpitem; + Inkscape::Display::TemporaryItem *flash_tempitem; Inkscape::UI::Selector* _selector; Inkscape::UI::PathSharedData* _path_data; @@ -96,8 +96,9 @@ private: void update_tip(GdkEvent *event); void handleControlUiStyleChange(); }; - + void sp_update_helperpath(); } + } } diff --git a/src/ui/tools/spray-tool.cpp b/src/ui/tools/spray-tool.cpp index 3649008ff..ad006627c 100644 --- a/src/ui/tools/spray-tool.cpp +++ b/src/ui/tools/spray-tool.cpp @@ -1026,7 +1026,7 @@ static bool sp_spray_recursive(SPDesktop *desktop, if (unionResult) { // No need to add the very first item (initialized with NULL). set->add(unionResult); } - sp_selected_path_union_skip_undo(set); + set->pathUnion(true); set->add(parent_item); Inkscape::GC::release(copy); did = true; @@ -1364,7 +1364,7 @@ bool SprayTool::root_handler(GdkEvent* event) { SP_VERB_CONTEXT_SPRAY, _("Spray with clones")); break; case SPRAY_MODE_SINGLE_PATH: - sp_selected_path_union_skip_undo(objectSet()); + objectSet()->pathUnion(true); desktop->getSelection()->add(object_set.objects().begin(), object_set.objects().end()); DocumentUndo::done(this->desktop->getDocument(), SP_VERB_CONTEXT_SPRAY, _("Spray in single path")); diff --git a/src/ui/tools/tweak-tool.cpp b/src/ui/tools/tweak-tool.cpp index a0394ecd4..ff5d623c2 100644 --- a/src/ui/tools/tweak-tool.cpp +++ b/src/ui/tools/tweak-tool.cpp @@ -56,6 +56,8 @@ #include "sp-gradient-reference.h" #include "sp-linear-gradient.h" #include "sp-radial-gradient.h" +#include "sp-mesh-gradient.h" +#include "sp-mesh-array.h" #include "gradient-chemistry.h" #include "sp-text.h" #include "sp-flowtext.h" @@ -761,112 +763,132 @@ static void tweak_colors_in_gradient(SPItem *item, Inkscape::PaintTarget fill_or p *= (gradient->gradientTransform).inverse(); // now p is in gradient's original coordinates - double pos = 0; - double r = 0; - SPLinearGradient *lg = dynamic_cast<SPLinearGradient *>(gradient); - if (lg) { - Geom::Point p1(lg->x1.computed, lg->y1.computed); - Geom::Point p2(lg->x2.computed, lg->y2.computed); - Geom::Point pdiff(p2 - p1); - double vl = Geom::L2(pdiff); + SPRadialGradient *rg = dynamic_cast<SPRadialGradient *>(gradient); + if (lg || rg) { - // This is the matrix which moves and rotates the gradient line - // so it's oriented along the X axis: - Geom::Affine norm = Geom::Affine(Geom::Translate(-p1)) * Geom::Affine(Geom::Rotate(-atan2(pdiff[Geom::Y], pdiff[Geom::X]))); + double pos = 0; + double r = 0; - // Transform the mouse point by it to find out its projection onto the gradient line: - Geom::Point pnorm = p * norm; + if (lg) { + Geom::Point p1(lg->x1.computed, lg->y1.computed); + Geom::Point p2(lg->x2.computed, lg->y2.computed); + Geom::Point pdiff(p2 - p1); + double vl = Geom::L2(pdiff); - // Scale its X coordinate to match the length of the gradient line: - pos = pnorm[Geom::X] / vl; - // Calculate radius in lenfth-of-gradient-line units - r = radius / vl; + // This is the matrix which moves and rotates the gradient line + // so it's oriented along the X axis: + Geom::Affine norm = Geom::Affine(Geom::Translate(-p1)) * + Geom::Affine(Geom::Rotate(-atan2(pdiff[Geom::Y], pdiff[Geom::X]))); - } else { - SPRadialGradient *rg = dynamic_cast<SPRadialGradient *>(gradient); + // Transform the mouse point by it to find out its projection onto the gradient line: + Geom::Point pnorm = p * norm; + + // Scale its X coordinate to match the length of the gradient line: + pos = pnorm[Geom::X] / vl; + // Calculate radius in lenfth-of-gradient-line units + r = radius / vl; + + } if (rg) { Geom::Point c (rg->cx.computed, rg->cy.computed); pos = Geom::L2(p - c) / rg->r.computed; r = radius / rg->r.computed; } - } - // Normalize pos to 0..1, taking into accound gradient spread: - double pos_e = pos; - if (gradient->getSpread() == SP_GRADIENT_SPREAD_PAD) { - if (pos > 1) { - pos_e = 1; - } - if (pos < 0) { - pos_e = 0; - } - } else if (gradient->getSpread() == SP_GRADIENT_SPREAD_REPEAT) { - if (pos > 1 || pos < 0) { - pos_e = pos - floor(pos); - } - } else if (gradient->getSpread() == SP_GRADIENT_SPREAD_REFLECT) { - if (pos > 1 || pos < 0) { - bool odd = ((int)(floor(pos)) % 2 == 1); - pos_e = pos - floor(pos); - if (odd) { - pos_e = 1 - pos_e; + // Normalize pos to 0..1, taking into accound gradient spread: + double pos_e = pos; + if (gradient->getSpread() == SP_GRADIENT_SPREAD_PAD) { + if (pos > 1) { + pos_e = 1; + } + if (pos < 0) { + pos_e = 0; + } + } else if (gradient->getSpread() == SP_GRADIENT_SPREAD_REPEAT) { + if (pos > 1 || pos < 0) { + pos_e = pos - floor(pos); + } + } else if (gradient->getSpread() == SP_GRADIENT_SPREAD_REFLECT) { + if (pos > 1 || pos < 0) { + bool odd = ((int)(floor(pos)) % 2 == 1); + pos_e = pos - floor(pos); + if (odd) { + pos_e = 1 - pos_e; + } } } - } - SPGradient *vector = sp_gradient_get_forked_vector_if_necessary(gradient, false); + SPGradient *vector = sp_gradient_get_forked_vector_if_necessary(gradient, false); - double offset_l = 0; - double offset_h = 0; - SPObject *child_prev = NULL; - for (auto& child: vector->children) { - SPStop *stop = dynamic_cast<SPStop *>(&child); - if (!stop) { - continue; - } + double offset_l = 0; + double offset_h = 0; + SPObject *child_prev = NULL; + for (auto& child: vector->children) { + SPStop *stop = dynamic_cast<SPStop *>(&child); + if (!stop) { + continue; + } - offset_h = stop->offset; - - if (child_prev) { - SPStop *prevStop = dynamic_cast<SPStop *>(child_prev); - g_assert(prevStop != NULL); - - if (offset_h - offset_l > r && pos_e >= offset_l && pos_e <= offset_h) { - // the summit falls in this interstop, and the radius is small, - // so it only affects the ends of this interstop; - // distribute the force between the two endstops so that they - // get all the painting even if they are not touched by the brush - tweak_color (mode, stop->specified_color.v.c, rgb_goal, - force * (pos_e - offset_l) / (offset_h - offset_l), - do_h, do_s, do_l); - tweak_color(mode, prevStop->specified_color.v.c, rgb_goal, - force * (offset_h - pos_e) / (offset_h - offset_l), - do_h, do_s, do_l); - stop->updateRepr(); - child_prev->updateRepr(); - break; - } else { - // wide brush, may affect more than 2 stops, - // paint each stop by the force from the profile curve - if (offset_l <= pos_e && offset_l > pos_e - r) { + offset_h = stop->offset; + + if (child_prev) { + SPStop *prevStop = dynamic_cast<SPStop *>(child_prev); + g_assert(prevStop != NULL); + + if (offset_h - offset_l > r && pos_e >= offset_l && pos_e <= offset_h) { + // the summit falls in this interstop, and the radius is small, + // so it only affects the ends of this interstop; + // distribute the force between the two endstops so that they + // get all the painting even if they are not touched by the brush + tweak_color (mode, stop->specified_color.v.c, rgb_goal, + force * (pos_e - offset_l) / (offset_h - offset_l), + do_h, do_s, do_l); tweak_color(mode, prevStop->specified_color.v.c, rgb_goal, - force * tweak_profile (fabs (pos_e - offset_l), r), + force * (offset_h - pos_e) / (offset_h - offset_l), do_h, do_s, do_l); + stop->updateRepr(); child_prev->updateRepr(); + break; + } else { + // wide brush, may affect more than 2 stops, + // paint each stop by the force from the profile curve + if (offset_l <= pos_e && offset_l > pos_e - r) { + tweak_color(mode, prevStop->specified_color.v.c, rgb_goal, + force * tweak_profile (fabs (pos_e - offset_l), r), + do_h, do_s, do_l); + child_prev->updateRepr(); + } + + if (offset_h >= pos_e && offset_h < pos_e + r) { + tweak_color (mode, stop->specified_color.v.c, rgb_goal, + force * tweak_profile (fabs (pos_e - offset_h), r), + do_h, do_s, do_l); + stop->updateRepr(); + } } + } - if (offset_h >= pos_e && offset_h < pos_e + r) { + offset_l = offset_h; + child_prev = &child; + } + } else { + // Mesh + SPMeshGradient *mg = dynamic_cast<SPMeshGradient *>(gradient); + if (mg) { + SPMeshGradient *mg_array = dynamic_cast<SPMeshGradient *>(mg->getArray()); + SPMeshNodeArray *array = &(mg_array->array); + // Every third node is a corner node + for( unsigned i=0; i < array->nodes.size(); i+=3 ) { + for( unsigned j=0; j < array->nodes[i].size(); j+=3 ) { + SPStop *stop = array->nodes[i][j]->stop; + double distance = Geom::L2(Geom::Point(p - array->nodes[i][j]->p)); tweak_color (mode, stop->specified_color.v.c, rgb_goal, - force * tweak_profile (fabs (pos_e - offset_h), r), - do_h, do_s, do_l); + force * tweak_profile (distance, radius), do_h, do_s, do_l); stop->updateRepr(); } } } - - offset_l = offset_h; - child_prev = &child; } } @@ -1062,7 +1084,8 @@ sp_tweak_dilate (TweakTool *tc, Geom::Point event_p, Geom::Point p, Geom::Point double move_force = get_move_force(tc); double color_force = MIN(sqrt(path_force)/20.0, 1); - auto items= selection->items(); +// auto items= selection->items(); + std::vector<SPItem*> items(selection->items().begin(), selection->items().end()); for(auto i=items.begin();i!=items.end(); ++i){ SPItem *item = *i; |
