summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDiederik van Lierop <mailat-signdiedenrezidotnl>2010-12-27 21:18:34 +0000
committerDiederik van Lierop <mailat-signdiedenrezidotnl>2010-12-27 21:18:34 +0000
commitc210fd393e9423898f9c745fe081da3d90e9b605 (patch)
tree09058ccadaff96bb3d031c76d7f78bfc05ffc1a2
parentExtensions. Add option to choose dxf output units (diff)
downloadinkscape-c210fd393e9423898f9c745fe081da3d90e9b605.tar.gz
inkscape-c210fd393e9423898f9c745fe081da3d90e9b605.zip
Node tool: snap while scaling a selection of nodes. Consider this as experimental; needs cleanup!
(bzr r9985)
-rw-r--r--src/seltrans.cpp28
-rw-r--r--src/seltrans.h1
-rw-r--r--src/snap.cpp56
-rw-r--r--src/snap.h17
-rw-r--r--src/ui/tool/control-point-selection.cpp18
-rw-r--r--src/ui/tool/control-point-selection.h5
-rw-r--r--src/ui/tool/transform-handle-set.cpp66
7 files changed, 148 insertions, 43 deletions
diff --git a/src/seltrans.cpp b/src/seltrans.cpp
index b0e19e60c..b1d184986 100644
--- a/src/seltrans.cpp
+++ b/src/seltrans.cpp
@@ -299,7 +299,7 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s
An average user would rarely ever try to snap such a large number of nodes anyway, because
(s)he could hardly discern which node would be snapping */
if (prefs->getBool("/options/snapclosestonly/value", false)) {
- _keepClosestPointOnly(_snap_points, p);
+ m.keepClosestPointOnly(_snap_points, p);
} else {
_snap_points = snap_points_hull;
}
@@ -360,14 +360,14 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s
if (prefs->getBool("/options/snapclosestonly/value", false)) {
if (m.snapprefs.getSnapModeNode()) {
- _keepClosestPointOnly(_snap_points, p);
+ m.keepClosestPointOnly(_snap_points, p);
} else {
_snap_points.clear(); // don't keep any point
}
if (m.snapprefs.getSnapModeBBox()) {
- _keepClosestPointOnly(_bbox_points, p);
- _keepClosestPointOnly(_bbox_points_for_translating, p);
+ m.keepClosestPointOnly(_bbox_points, p);
+ m.keepClosestPointOnly(_bbox_points_for_translating, p);
} else {
_bbox_points.clear(); // don't keep any point
_bbox_points_for_translating.clear();
@@ -1632,26 +1632,6 @@ Geom::Point Inkscape::SelTrans::_calcAbsAffineGeom(Geom::Scale const geom_scale)
return _calcAbsAffineDefault(geom_scale); // this is bogus, but we must return _something_
}
-void Inkscape::SelTrans::_keepClosestPointOnly(std::vector<Inkscape::SnapCandidatePoint> &points, const Geom::Point &reference)
-{
- if (points.size() < 2) return;
-
- Inkscape::SnapCandidatePoint closest_point = Inkscape::SnapCandidatePoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, SNAPTARGET_UNDEFINED);
- Geom::Coord closest_dist = NR_HUGE;
-
- for(std::vector<Inkscape::SnapCandidatePoint>::const_iterator i = points.begin(); i != points.end(); i++) {
- Geom::Coord dist = Geom::L2((*i).getPoint() - reference);
- if (i == points.begin() || dist < closest_dist) {
- closest_point = *i;
- closest_dist = dist;
- }
- }
-
- closest_point.setSourceNum(-1);
- points.clear();
- points.push_back(closest_point);
-}
-
/*
Local Variables:
mode:c++
diff --git a/src/seltrans.h b/src/seltrans.h
index 0183683ff..bb26aa2cb 100644
--- a/src/seltrans.h
+++ b/src/seltrans.h
@@ -103,7 +103,6 @@ private:
Geom::Point _getGeomHandlePos(Geom::Point const &visual_handle_pos);
Geom::Point _calcAbsAffineDefault(Geom::Scale const default_scale);
Geom::Point _calcAbsAffineGeom(Geom::Scale const geom_scale);
- void _keepClosestPointOnly(std::vector<Inkscape::SnapCandidatePoint> &points, const Geom::Point &reference);
void _display_snapsource();
enum State {
diff --git a/src/snap.cpp b/src/snap.cpp
index 79f398cc5..85d2fd5af 100644
--- a/src/snap.cpp
+++ b/src/snap.cpp
@@ -22,6 +22,7 @@
#include "sp-namedview.h"
#include "snap.h"
+#include "snap-enums.h"
#include "snapped-line.h"
#include "snapped-curve.h"
@@ -682,7 +683,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
Geom::Point const &transformation,
Geom::Point const &origin,
Geom::Dim2 dim,
- bool uniform) const
+ bool uniform)
{
/* We have a list of points, which we are proposing to transform in some way. We need to see
** if any of these points, when transformed, snap to anything. If they do, we return the
@@ -734,6 +735,12 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
g_warning("Unconstrained rotation is not supported!");
}
+ // We will try to snap a set of points, but we don't want to have a snap indicator displayed
+ // for each of them. That's why it's temporarily disabled here, and re-enabled again after we
+ // have finished calling the freeSnap() and constrainedSnap() methods
+ bool _orig_snapindicator_status = _snapindicator;
+ _snapindicator = false;
+
std::vector<Inkscape::SnapCandidatePoint>::iterator j = transformed_points.begin();
// std::cout << std::endl;
@@ -802,6 +809,9 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
// std::cout << "dist = " << snapped_point.getSnapDistance() << std::endl;
snapped_point.setPointerDistance(Geom::L2(pointer - (*i).getPoint()));
+ // Allow the snapindicator to be displayed again
+ _snapindicator = _orig_snapindicator_status;
+
Geom::Point result;
/*Find the transformation that describes where the snapped point has
@@ -891,6 +901,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
if (snapped_point.getSnapped()) {
// We snapped; keep track of the best snap
+ // TODO: Compare the transformations instead of the snap points; we should be looking for the closest transformation
if (best_snapped_point.isOtherSnapBetter(snapped_point, true)) {
best_transformation = result;
best_snapped_point = snapped_point;
@@ -932,6 +943,15 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
// Using " < 1e6" instead of " < NR_HUGE" for catching some rounding errors
// These rounding errors might be caused by NRRects, see bug #1584301
best_snapped_point.setSnapDistance(best_metric < 1e6 ? best_metric : NR_HUGE);
+
+ if (_snapindicator) {
+ if (best_snapped_point.getSnapped()) {
+ _desktop->snapindicator->set_new_snaptarget(best_snapped_point);
+ } else {
+ _desktop->snapindicator->remove_snaptarget();
+ }
+ }
+
return best_snapped_point;
}
@@ -947,7 +967,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed(
Inkscape::SnappedPoint SnapManager::freeSnapTranslate(std::vector<Inkscape::SnapCandidatePoint> const &p,
Geom::Point const &pointer,
- Geom::Point const &tr) const
+ Geom::Point const &tr)
{
Inkscape::SnappedPoint result = _snapTransformed(p, pointer, false, Geom::Point(0,0), TRANSLATE, tr, Geom::Point(0,0), Geom::X, false);
@@ -971,7 +991,7 @@ Inkscape::SnappedPoint SnapManager::freeSnapTranslate(std::vector<Inkscape::Snap
Inkscape::SnappedPoint SnapManager::constrainedSnapTranslate(std::vector<Inkscape::SnapCandidatePoint> const &p,
Geom::Point const &pointer,
Inkscape::Snapper::SnapConstraint const &constraint,
- Geom::Point const &tr) const
+ Geom::Point const &tr)
{
Inkscape::SnappedPoint result = _snapTransformed(p, pointer, true, constraint, TRANSLATE, tr, Geom::Point(0,0), Geom::X, false);
@@ -996,7 +1016,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapTranslate(std::vector<Inkscap
Inkscape::SnappedPoint SnapManager::freeSnapScale(std::vector<Inkscape::SnapCandidatePoint> const &p,
Geom::Point const &pointer,
Geom::Scale const &s,
- Geom::Point const &o) const
+ Geom::Point const &o)
{
Inkscape::SnappedPoint result = _snapTransformed(p, pointer, false, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, false);
@@ -1021,7 +1041,7 @@ Inkscape::SnappedPoint SnapManager::freeSnapScale(std::vector<Inkscape::SnapCand
Inkscape::SnappedPoint SnapManager::constrainedSnapScale(std::vector<Inkscape::SnapCandidatePoint> const &p,
Geom::Point const &pointer,
Geom::Scale const &s,
- Geom::Point const &o) const
+ Geom::Point const &o)
{
// When constrained scaling, only uniform scaling is supported.
Inkscape::SnappedPoint result = _snapTransformed(p, pointer, true, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, true);
@@ -1050,7 +1070,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(std::vector<Inkscape:
Geom::Coord const &s,
Geom::Point const &o,
Geom::Dim2 d,
- bool u) const
+ bool u)
{
Inkscape::SnappedPoint result = _snapTransformed(p, pointer, true, Geom::Point(0,0), STRETCH, Geom::Point(s, s), o, d, u);
@@ -1078,7 +1098,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(std::vector<Inkscape::Sn
Inkscape::Snapper::SnapConstraint const &constraint,
Geom::Point const &s,
Geom::Point const &o,
- Geom::Dim2 d) const
+ Geom::Dim2 d)
{
// "s" contains skew factor in s[0], and scale factor in s[1]
@@ -1113,7 +1133,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(std::vector<Inkscape::Sn
Inkscape::SnappedPoint SnapManager::constrainedSnapRotate(std::vector<Inkscape::SnapCandidatePoint> const &p,
Geom::Point const &pointer,
Geom::Coord const &angle,
- Geom::Point const &o) const
+ Geom::Point const &o)
{
// Snapping the nodes of the bounding box of a selection that is being transformed, will only work if
// the transformation of the bounding box is equal to the transformation of the individual nodes. This is
@@ -1429,6 +1449,26 @@ void SnapManager::_displaySnapsource(Inkscape::SnapCandidatePoint const &p) cons
}
}
+void SnapManager::keepClosestPointOnly(std::vector<Inkscape::SnapCandidatePoint> &points, const Geom::Point &reference) const
+{
+ if (points.size() < 2) return;
+
+ Inkscape::SnapCandidatePoint closest_point = Inkscape::SnapCandidatePoint(Geom::Point(NR_HUGE, NR_HUGE), Inkscape::SNAPSOURCE_UNDEFINED, Inkscape::SNAPTARGET_UNDEFINED);
+ Geom::Coord closest_dist = NR_HUGE;
+
+ for(std::vector<Inkscape::SnapCandidatePoint>::const_iterator i = points.begin(); i != points.end(); i++) {
+ Geom::Coord dist = Geom::L2((*i).getPoint() - reference);
+ if (i == points.begin() || dist < closest_dist) {
+ closest_point = *i;
+ closest_dist = dist;
+ }
+ }
+
+ closest_point.setSourceNum(-1);
+ points.clear();
+ points.push_back(closest_point);
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/snap.h b/src/snap.h
index c79bd308a..8f8416ee5 100644
--- a/src/snap.h
+++ b/src/snap.h
@@ -149,41 +149,41 @@ public:
Inkscape::SnappedPoint freeSnapTranslate(std::vector<Inkscape::SnapCandidatePoint> const &p,
Geom::Point const &pointer,
- Geom::Point const &tr) const;
+ Geom::Point const &tr);
Inkscape::SnappedPoint constrainedSnapTranslate(std::vector<Inkscape::SnapCandidatePoint> const &p,
Geom::Point const &pointer,
Inkscape::Snapper::SnapConstraint const &constraint,
- Geom::Point const &tr) const;
+ Geom::Point const &tr);
Inkscape::SnappedPoint freeSnapScale(std::vector<Inkscape::SnapCandidatePoint> const &p,
Geom::Point const &pointer,
Geom::Scale const &s,
- Geom::Point const &o) const;
+ Geom::Point const &o);
Inkscape::SnappedPoint constrainedSnapScale(std::vector<Inkscape::SnapCandidatePoint> const &p,
Geom::Point const &pointer,
Geom::Scale const &s,
- Geom::Point const &o) const;
+ Geom::Point const &o);
Inkscape::SnappedPoint constrainedSnapStretch(std::vector<Inkscape::SnapCandidatePoint> const &p,
Geom::Point const &pointer,
Geom::Coord const &s,
Geom::Point const &o,
Geom::Dim2 d,
- bool uniform) const;
+ bool uniform);
Inkscape::SnappedPoint constrainedSnapSkew(std::vector<Inkscape::SnapCandidatePoint> const &p,
Geom::Point const &pointer,
Inkscape::Snapper::SnapConstraint const &constraint,
Geom::Point const &s, // s[0] = skew factor, s[1] = scale factor
Geom::Point const &o,
- Geom::Dim2 d) const;
+ Geom::Dim2 d);
Inkscape::SnappedPoint constrainedSnapRotate(std::vector<Inkscape::SnapCandidatePoint> const &p,
Geom::Point const &pointer,
Geom::Coord const &angle,
- Geom::Point const &o) const;
+ Geom::Point const &o);
Inkscape::GuideSnapper guide; ///< guide snapper
Inkscape::ObjectSnapper object; ///< snapper to other objects
@@ -200,6 +200,7 @@ public:
bool getSnapIndicator() const {return _snapindicator;}
Inkscape::SnappedPoint findBestSnap(Inkscape::SnapCandidatePoint const &p, SnappedConstraints const &sc, bool constrained, bool noCurves = false, bool allowOffScreen = false) const;
+ void keepClosestPointOnly(std::vector<Inkscape::SnapCandidatePoint> &points, const Geom::Point &reference) const;
protected:
SPNamedView const *_named_view;
@@ -220,7 +221,7 @@ private:
Geom::Point const &transformation,
Geom::Point const &origin,
Geom::Dim2 dim,
- bool uniform) const;
+ bool uniform);
Geom::Point _transformPoint(Inkscape::SnapCandidatePoint const &p,
Transformation const transformation_type,
diff --git a/src/ui/tool/control-point-selection.cpp b/src/ui/tool/control-point-selection.cpp
index baa53f76e..517e90da2 100644
--- a/src/ui/tool/control-point-selection.cpp
+++ b/src/ui/tool/control-point-selection.cpp
@@ -642,6 +642,24 @@ bool ControlPointSelection::event(GdkEvent *event)
return false;
}
+std::vector<Inkscape::SnapCandidatePoint> ControlPointSelection::getOriginalPoints()
+{
+ std::vector<Inkscape::SnapCandidatePoint> points;
+ for (iterator i = _points.begin(); i != _points.end(); ++i) {
+ points.push_back(Inkscape::SnapCandidatePoint(_original_positions[*i], SNAPSOURCE_NODE_HANDLE));
+ }
+ return points;
+}
+
+void ControlPointSelection::setOriginalPoints()
+{
+ _original_positions.clear();
+ for (iterator i = _points.begin(); i != _points.end(); ++i) {
+ _original_positions.insert(std::make_pair(*i, (*i)->position()));
+ }
+}
+
+
} // namespace UI
} // namespace Inkscape
diff --git a/src/ui/tool/control-point-selection.h b/src/ui/tool/control-point-selection.h
index 6a5b05e85..0e5acf6c5 100644
--- a/src/ui/tool/control-point-selection.h
+++ b/src/ui/tool/control-point-selection.h
@@ -22,6 +22,7 @@
#include "util/unordered-containers.h"
#include "ui/tool/commit-events.h"
#include "ui/tool/manipulator.h"
+#include "snap-candidate.h"
class SPDesktop;
struct SPCanvasGroup;
@@ -108,6 +109,10 @@ public:
sigc::signal<void> signal_update;
sigc::signal<void, SelectableControlPoint *, bool> signal_point_changed;
sigc::signal<void, CommitEvent> signal_commit;
+
+ std::vector<Inkscape::SnapCandidatePoint> getOriginalPoints();
+ void setOriginalPoints();
+
private:
// The functions below are invoked from SelectableControlPoint.
// Previously they were connected to handlers when selecting, but this
diff --git a/src/ui/tool/transform-handle-set.cpp b/src/ui/tool/transform-handle-set.cpp
index cafd592a3..209b7fe98 100644
--- a/src/ui/tool/transform-handle-set.cpp
+++ b/src/ui/tool/transform-handle-set.cpp
@@ -19,11 +19,15 @@
#include "display/sodipodi-ctrlrect.h"
#include "preferences.h"
#include "snap.h"
+#include "snap-candidate.h"
#include "sp-namedview.h"
#include "ui/tool/commit-events.h"
#include "ui/tool/control-point.h"
+#include "ui/tool/control-point-selection.h"
+#include "ui/tool/selectable-control-point.h"
#include "ui/tool/event-utils.h"
#include "ui/tool/transform-handle-set.h"
+#include "ui/tool/node-tool.h"
// FIXME BRAIN DAMAGE WARNING: this is a global variable in select-context.cpp
// It should be moved to a header
@@ -96,6 +100,8 @@ protected:
Geom::Matrix _last_transform;
Geom::Point _origin;
TransformHandleSet &_th;
+ std::vector<Inkscape::SnapCandidatePoint> _snap_points;
+
private:
virtual bool grabbed(GdkEventMotion *) {
_origin = position();
@@ -105,6 +111,20 @@ private:
_th._setActiveHandle(this);
_cset = &invisible_cset;
_setState(_state);
+
+ // Collect the snap-candidates, one for each selected node. These will be stored in the _snap_points vector.
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SnapManager &m = desktop->namedview->snap_manager;
+ InkNodeTool *nt = INK_NODE_TOOL(_desktop->event_context);
+ ControlPointSelection *selection = nt->_selected_nodes.get();
+
+ _snap_points = selection->getOriginalPoints();
+
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ if (prefs->getBool("/options/snapclosestonly/value", false)) {
+ m.keepClosestPointOnly(_snap_points, _origin);
+ }
+
return false;
}
virtual void dragged(Geom::Point &new_pos, GdkEventMotion *event)
@@ -118,6 +138,7 @@ private:
_last_transform = t;
}
virtual void ungrabbed(GdkEventButton *) {
+ _snap_points.clear();
_th._clearActiveHandle();
_cset = &thandle_cset;
_setState(_state);
@@ -177,23 +198,64 @@ protected:
_sc_center = _th.rotationCenter();
_sc_opposite = _th.bounds().corner(_corner + 2);
_last_scale_x = _last_scale_y = 1.0;
+ InkNodeTool *nt = INK_NODE_TOOL(_desktop->event_context);
+ ControlPointSelection *selection = nt->_selected_nodes.get();
+ std::cout << "startTransform()" << std::endl;
+ selection->setOriginalPoints();
}
virtual Geom::Matrix computeTransform(Geom::Point const &new_pos, GdkEventMotion *event) {
Geom::Point scc = held_shift(*event) ? _sc_center : _sc_opposite;
Geom::Point vold = _origin - scc, vnew = new_pos - scc;
+
// avoid exploding the selection
if (Geom::are_near(vold[Geom::X], 0) || Geom::are_near(vold[Geom::Y], 0))
return Geom::identity();
double scale[2] = { vnew[Geom::X] / vold[Geom::X], vnew[Geom::Y] / vold[Geom::Y] };
+
if (held_alt(*event)) {
for (unsigned i = 0; i < 2; ++i) {
if (scale[i] >= 1.0) scale[i] = round(scale[i]);
else scale[i] = 1.0 / round(1.0 / scale[i]);
}
- } else if (held_control(*event)) {
- scale[0] = scale[1] = std::min(scale[0], scale[1]);
+ } else {
+ //SPDesktop *desktop = _th._desktop; // Won't work as _desktop is protected
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SnapManager &m = desktop->namedview->snap_manager;
+
+ // The lines below have been copied from Handle::dragged() in node.cpp, and need to be
+ // activated if we want to snap to unselected (i.e. stationary) nodes and stationary pieces of paths of the
+ // path that's currently being edited
+ /*
+ std::vector<Inkscape::SnapCandidatePoint> unselected;
+ typedef ControlPointSelection::Set Set;
+ Set &nodes = _parent->_selection.allPoints();
+ for (Set::iterator i = nodes.begin(); i != nodes.end(); ++i) {
+ Node *n = static_cast<Node*>(*i);
+ Inkscape::SnapCandidatePoint p(n->position(), n->_snapSourceType(), n->_snapTargetType());
+ unselected.push_back(p);
+ }
+ m.setupIgnoreSelection(_desktop, true, &unselected);
+ */
+
+ m.setupIgnoreSelection(_desktop);
+
+ Inkscape::SnappedPoint sp;
+ if (held_control(*event)) {
+ scale[0] = scale[1] = std::min(scale[0], scale[1]);
+ sp = m.constrainedSnapScale(_snap_points, _origin, Geom::Scale(scale[0], scale[1]), scc);
+ } else {
+ sp = m.freeSnapScale(_snap_points, _origin, Geom::Scale(scale[0], scale[1]), scc);
+ }
+ m.unSetup();
+
+ if (sp.getSnapped()) {
+ Geom::Point result = sp.getTransformation();
+ scale[0] = result[0];
+ scale[1] = result[1];
+ }
}
+
_last_scale_x = scale[0];
_last_scale_y = scale[1];
Geom::Matrix t = Geom::Translate(-scc)