Code

Node tool: implement sculpting
authorKrzysztof Kosiński <tweenk.pl@gmail.com>
Wed, 3 Mar 2010 00:10:54 +0000 (01:10 +0100)
committerKrzysztof Kosiński <tweenk.pl@gmail.com>
Wed, 3 Mar 2010 00:10:54 +0000 (01:10 +0100)
src/ui/tool/control-point-selection.cpp
src/ui/tool/control-point-selection.h
src/ui/tool/selectable-control-point.cpp

index df27c2a72ad1929b3654d042e235493919d85e51..f880d2ddfe2c9faf604f3add7c9588b7d1257951 100644 (file)
@@ -266,28 +266,51 @@ void ControlPointSelection::toggleTransformHandlesMode()
     }
 }
 
-void ControlPointSelection::_pointGrabbed()
+void ControlPointSelection::_pointGrabbed(SelectableControlPoint *point)
 {
     hideTransformHandles();
     _dragging = true;
+    _grabbed_point = point;
+    _farthest_point = point;
+    double maxdist = 0;
+    for (iterator i = _points.begin(); i != _points.end(); ++i) {
+        _original_positions.insert(std::make_pair(*i, (*i)->position()));
+        double dist = Geom::distance(*_grabbed_point, **i);
+        if (dist > maxdist) {
+            maxdist = dist;
+            _farthest_point = *i;
+        }
+    }
 }
 
-void ControlPointSelection::_pointDragged(Geom::Point const &old_pos, Geom::Point &new_pos,
-                                          GdkEventMotion */*event*/)
+void ControlPointSelection::_pointDragged(Geom::Point &new_pos, GdkEventMotion *event)
 {
-    Geom::Point delta = new_pos - old_pos;
-    for (iterator i = _points.begin(); i != _points.end(); ++i) {
-        SelectableControlPoint *cur = (*i);
-        cur->move(cur->position() + delta);
+    Geom::Point abs_delta = new_pos - _original_positions[_grabbed_point];
+    double fdist = Geom::distance(_original_positions[_grabbed_point], _original_positions[_farthest_point]);
+    if (held_alt(*event) && fdist > 0) {
+        // sculpting
+        for (iterator i = _points.begin(); i != _points.end(); ++i) {
+            SelectableControlPoint *cur = (*i);
+            double dist = Geom::distance(_original_positions[cur], _original_positions[_grabbed_point]);
+            double deltafrac = 0.5 + 0.5 * cos(M_PI * dist/fdist);
+            cur->move(_original_positions[cur] + abs_delta * deltafrac);
+        }
+    } else {
+        Geom::Point delta = new_pos - _grabbed_point->position();
+        for (iterator i = _points.begin(); i != _points.end(); ++i) {
+            SelectableControlPoint *cur = (*i);
+            cur->move(_original_positions[cur] + abs_delta);
+        }
+        _handles->rotationCenter().move(_handles->rotationCenter().position() + delta);
     }
-    _handles->rotationCenter().move(_handles->rotationCenter().position() + delta);
     signal_update.emit();
 }
 
 void ControlPointSelection::_pointUngrabbed()
 {
+    _original_positions.clear();
     _dragging = false;
-    _grabbed_point = NULL;
+    _grabbed_point = _farthest_point = NULL;
     _updateBounds();
     restoreTransformHandles();
     signal_commit.emit(COMMIT_MOUSE_MOVE);
index dde9ef218aefadb9bd467c70fbaa342a2a6aeaab..b3c2f422bd5a12256a4e7d6ebef0ef19fb926538 100644 (file)
@@ -15,6 +15,7 @@
 #include <memory>
 #include <boost/optional.hpp>
 #include <boost/unordered_set.hpp>
+#include <boost/unordered_map.hpp>
 #include <sigc++/sigc++.h>
 #include <2geom/forward.h>
 #include <2geom/point.h>
@@ -110,8 +111,8 @@ private:
     // The functions below are invoked from SelectableControlPoint.
     // Previously they were connected to handlers when selecting, but this
     // creates problems when dragging a point that was not selected.
-    void _pointGrabbed();
-    void _pointDragged(Geom::Point const &, Geom::Point &, GdkEventMotion *);
+    void _pointGrabbed(SelectableControlPoint *);
+    void _pointDragged(Geom::Point &, GdkEventMotion *);
     void _pointUngrabbed();
     bool _pointClicked(SelectableControlPoint *, GdkEventButton *);
     void _pointChanged(SelectableControlPoint *, bool);
@@ -129,11 +130,12 @@ private:
 
     set_type _points;
     set_type _all_points;
+    boost::unordered_map<SelectableControlPoint *, Geom::Point> _original_positions;
     boost::optional<double> _rot_radius;
     boost::optional<double> _mouseover_rot_radius;
     Geom::OptRect _bounds;
     TransformHandleSet *_handles;
-    SelectableControlPoint *_grabbed_point;
+    SelectableControlPoint *_grabbed_point, *_farthest_point;
     unsigned _dragging         : 1;
     unsigned _handles_visible  : 1;
     unsigned _one_node_handles : 1;
index 1835f0008594cb9e4615ea662c8d9d10f68e14a0..76028dd82d3ee0204344800dd7681b8c3dec3bd6 100644 (file)
@@ -59,13 +59,13 @@ bool SelectableControlPoint::grabbed(GdkEventMotion *)
     if (!selected()) {
         _takeSelection();
     }
-    _selection._pointGrabbed();
+    _selection._pointGrabbed(this);
     return false;
 }
 
 void SelectableControlPoint::dragged(Geom::Point &new_pos, GdkEventMotion *event)
 {
-    _selection._pointDragged(position(), new_pos, event);
+    _selection._pointDragged(new_pos, event);
 }
 
 void SelectableControlPoint::ungrabbed(GdkEventButton *)