summaryrefslogtreecommitdiffstats
path: root/src/ui/tool
diff options
context:
space:
mode:
authorLiam P. White <inkscapebronyat-signgmaildotcom>2014-05-09 00:26:27 +0000
committerLiam P. White <inkscapebronyat-signgmaildotcom>2014-05-09 00:26:27 +0000
commit3d1cf059b042d213642e74cef82ec372e79281e4 (patch)
tree8a5d0f69c4c7372e87bd2a88bffc405e0a02258f /src/ui/tool
parentUpdate to trunk (diff)
parentMerging Jabier's spirolive+bspline branch (diff)
downloadinkscape-3d1cf059b042d213642e74cef82ec372e79281e4.tar.gz
inkscape-3d1cf059b042d213642e74cef82ec372e79281e4.zip
Update to trunk/integrate BSpline
(bzr r13090.1.73)
Diffstat (limited to 'src/ui/tool')
-rw-r--r--src/ui/tool/curve-drag-point.cpp17
-rw-r--r--src/ui/tool/multi-path-manipulator.cpp13
-rw-r--r--src/ui/tool/node.cpp201
-rw-r--r--src/ui/tool/node.h12
-rw-r--r--src/ui/tool/path-manipulator.cpp101
-rw-r--r--src/ui/tool/path-manipulator.h9
6 files changed, 326 insertions, 27 deletions
diff --git a/src/ui/tool/curve-drag-point.cpp b/src/ui/tool/curve-drag-point.cpp
index 4ca736f80..013553410 100644
--- a/src/ui/tool/curve-drag-point.cpp
+++ b/src/ui/tool/curve-drag-point.cpp
@@ -53,9 +53,11 @@ bool CurveDragPoint::grabbed(GdkEventMotion */*event*/)
// delta is a vector equal 1/3 of distance from first to second
Geom::Point delta = (second->position() - first->position()) / 3.0;
- first->front()->move(first->front()->position() + delta);
- second->back()->move(second->back()->position() - delta);
-
+ // only update the nodes if the mode is bspline
+ if(!_pm.isBSpline(false)){
+ first->front()->move(first->front()->position() + delta);
+ second->back()->move(second->back()->position() - delta);
+ }
_pm.update();
} else {
_segment_was_degenerate = false;
@@ -88,9 +90,12 @@ void CurveDragPoint::dragged(Geom::Point &new_pos, GdkEventMotion *event)
Geom::Point offset0 = ((1-weight)/(3*t*(1-t)*(1-t))) * delta;
Geom::Point offset1 = (weight/(3*t*t*(1-t))) * delta;
- first->front()->move(first->front()->position() + offset0);
- second->back()->move(second->back()->position() + offset1);
-
+ //modified so that, if the trace is bspline, it only acts if the SHIFT key is pressed
+ if(!_pm.isBSpline(false)){
+ first->front()->move(first->front()->position() + offset0);
+ second->back()->move(second->back()->position() + offset1);
+ }else if(weight>=0.8 && held_shift(*event))second->back()->move(new_pos);
+ else if(weight<=0.2 && held_shift(*event))first->front()->move(new_pos);
_pm.update();
}
diff --git a/src/ui/tool/multi-path-manipulator.cpp b/src/ui/tool/multi-path-manipulator.cpp
index b54b5ad07..bdcd70e00 100644
--- a/src/ui/tool/multi-path-manipulator.cpp
+++ b/src/ui/tool/multi-path-manipulator.cpp
@@ -670,7 +670,18 @@ bool MultiPathManipulator::event(Inkscape::UI::Tools::ToolBase *event_context, G
// a) del preserves shape, and control is not pressed
// b) ctrl+del preserves shape (del_preserves_shape is false), and control is pressed
// Hence xor
- deleteNodes(del_preserves_shape ^ held_control(event->key));
+ guint mode = prefs->getInt("/tools/freehand/pen/freehand-mode", 0);
+
+ //if the trace is bspline ( mode 2)
+ if(mode==2){
+ // is this correct ?
+ if(del_preserves_shape ^ held_control(event->key))
+ deleteNodes(false);
+ else
+ deleteNodes(true);
+ }
+ else
+ deleteNodes(del_preserves_shape ^ held_control(event->key));
// Delete any selected gradient nodes as well
event_context->deleteSelectedDrag(held_control(event->key));
diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp
index fbbc4be64..1434a5c5b 100644
--- a/src/ui/tool/node.cpp
+++ b/src/ui/tool/node.cpp
@@ -13,7 +13,6 @@
#include <glib/gi18n.h>
#include <2geom/bezier-utils.h>
#include <2geom/transforms.h>
-
#include "display/sp-ctrlline.h"
#include "display/sp-canvas.h"
#include "display/sp-canvas-util.h"
@@ -29,6 +28,8 @@
#include "ui/tool/node.h"
#include "ui/tool/path-manipulator.h"
#include <gdk/gdkkeysyms.h>
+#include <cmath>
+
namespace {
@@ -166,6 +167,12 @@ void Handle::move(Geom::Point const &new_pos)
}
}
setPosition(new_pos);
+
+ //move the handler and its oposite the same proportion
+ if(_pm().isBSpline()){
+ setPosition(_pm().BSplineHandleReposition(this,this));
+ this->other()->setPosition(_pm().BSplineHandleReposition(this->other(),this));
+ }
return;
}
@@ -177,6 +184,13 @@ void Handle::move(Geom::Point const &new_pos)
Geom::Point new_delta = (Geom::dot(delta, direction)
/ Geom::L2sq(direction)) * direction;
setRelativePos(new_delta);
+
+ //move the handler and its oposite the same proportion
+ if(_pm().isBSpline()){
+ setPosition(_pm().BSplineHandleReposition(this,this));
+ this->other()->setPosition(_pm().BSplineHandleReposition(this->other(),this));
+ }
+
return;
}
@@ -195,8 +209,14 @@ void Handle::move(Geom::Point const &new_pos)
break;
default: break;
}
-
setPosition(new_pos);
+
+ // moves the handler and its oposite the same proportion
+ if(_pm().isBSpline()){
+ setPosition(_pm().BSplineHandleReposition(this,this));
+ this->other()->setPosition(_pm().BSplineHandleReposition(this->other(),this));
+ }
+
}
void Handle::setPosition(Geom::Point const &p)
@@ -273,12 +293,26 @@ bool Handle::_eventHandler(Inkscape::UI::Tools::ToolBase *event_context, GdkEven
break;
default: break;
}
+ // new double click event to set the handlers of a node to the default proportion, 0.3334%
+ case GDK_2BUTTON_PRESS:
+ handle_2button_press();
+ break;
+
default: break;
}
return ControlPoint::_eventHandler(event_context, event);
}
+//this function moves the handler and its oposite to the default proportion of 0.3334
+void Handle::handle_2button_press(){
+ if(_pm().isBSpline()){
+ setPosition(_pm().BSplineHandleReposition(this,0.3334));
+ this->other()->setPosition(_pm().BSplineHandleReposition(this->other(),0.3334));
+ _pm().update();
+ }
+}
+
bool Handle::grabbed(GdkEventMotion *)
{
_saved_other_pos = other()->position();
@@ -326,10 +360,18 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event)
ctrl_constraint = Inkscape::Snapper::SnapConstraint(parent_pos, parent_pos - perp_pos);
}
new_pos = result;
+ // moves the handler and its oposite in X fixed positions depending on parameter "steps with control"
+ // by default in live BSpline
+ if(_pm().isBSpline()){
+ setPosition(new_pos);
+ int steps = _pm().BSplineGetSteps();
+ new_pos=_pm().BSplineHandleReposition(this,ceilf(_pm().BSplineHandlePosition(this,this)*steps)/steps);
+ }
}
std::vector<Inkscape::SnapCandidatePoint> unselected;
- if (snap) {
+ //if the snap adjustment is activated and it is not bspline
+ if (snap && !_pm().isBSpline()) {
ControlPointSelection::Set &nodes = _parent->_selection.allPoints();
for (ControlPointSelection::Set::iterator i = nodes.begin(); i != nodes.end(); ++i) {
Node *n = static_cast<Node*>(*i);
@@ -369,6 +411,10 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event)
other()->setPosition(_saved_other_pos);
}
}
+ //if it is bspline but SHIFT or CONTROL are not pressed it fixes it in the original position
+ if(_pm().isBSpline() && !held_shift(*event) && !held_control(*event)){
+ new_pos=_last_drag_origin();
+ }
move(new_pos); // needed for correct update, even though it's redundant
_pm().update();
}
@@ -427,13 +473,19 @@ static double snap_increment_degrees() {
Glib::ustring Handle::_getTip(unsigned state) const
{
char const *more;
+ // a trick to mark as bspline if the node has no strength, we are going to use it later
+ // to show the appropiate messages. We cannot do it in any different way becasue the function is constant
+
+ bool isBSpline = _pm().isBSpline();
bool can_shift_rotate = _parent->type() == NODE_CUSP && !other()->isDegenerate();
- if (can_shift_rotate) {
+ if (can_shift_rotate && !isBSpline) {
more = C_("Path handle tip", "more: Shift, Ctrl, Alt");
- } else {
+ } else if(isBSpline){
+ more = C_("Path handle tip", "more: Ctrl");
+ }else {
more = C_("Path handle tip", "more: Ctrl, Alt");
}
- if (state_held_alt(state)) {
+ if (state_held_alt(state) && !isBSpline) {
if (state_held_control(state)) {
if (state_held_shift(state) && can_shift_rotate) {
return format_tip(C_("Path handle tip",
@@ -456,18 +508,24 @@ Glib::ustring Handle::_getTip(unsigned state) const
}
} else {
if (state_held_control(state)) {
- if (state_held_shift(state) && can_shift_rotate) {
+ if (state_held_shift(state) && can_shift_rotate && !isBSpline) {
return format_tip(C_("Path handle tip",
"<b>Shift+Ctrl</b>: snap rotation angle to %g° increments and rotate both handles"),
snap_increment_degrees());
- } else {
+ } else if(isBSpline){
+ return format_tip(C_("Path handle tip",
+ "<b>Ctrl</b>: Move handle by his actual steps in BSpline Live Effect"));
+ }else{
return format_tip(C_("Path handle tip",
"<b>Ctrl</b>: snap rotation angle to %g° increments, click to retract"),
snap_increment_degrees());
}
- } else if (state_held_shift(state) && can_shift_rotate) {
+ } else if (state_held_shift(state) && can_shift_rotate && !isBSpline) {
return C_("Path hande tip",
"<b>Shift</b>: rotate both handles by the same angle");
+ } else if(state_held_shift(state) && isBSpline){
+ return C_("Path hande tip",
+ "<b>Shift</b>: move handle");
}
}
@@ -476,9 +534,13 @@ Glib::ustring Handle::_getTip(unsigned state) const
return format_tip(C_("Path handle tip",
"<b>Auto node handle</b>: drag to convert to smooth node (%s)"), more);
default:
- return format_tip(C_("Path handle tip",
- "<b>%s</b>: drag to shape the segment (%s)"),
- handle_type_to_localized_string(_parent->type()), more);
+ if(!isBSpline){
+ return format_tip(C_("Path handle tip",
+ "<b>Auto node handle</b>: drag to convert to smooth node (%s)"), more);
+ }else{
+ return format_tip(C_("Path handle tip",
+ "<b>BSpline node handle</b>: Shift to drag, double click to reset (%s)"), more);
+ }
}
}
@@ -553,18 +615,80 @@ void Node::move(Geom::Point const &new_pos)
// move handles when the node moves.
Geom::Point old_pos = position();
Geom::Point delta = new_pos - position();
+
+ // save the previous nodes strength to apply it again once the node is moved
+ double nodeWeight = 0.0000;
+ double nextNodeWeight = 0.0000;
+ double prevNodeWeight = 0.0000;
+ Node *n = this;
+ Node * nextNode = n->nodeToward(n->front());
+ Node * prevNode = n->nodeToward(n->back());
+ nodeWeight = _pm().BSplineHandlePosition(n->front());
+ if(prevNode){
+ if(prevNode->isEndNode()){
+ prevNodeWeight = _pm().BSplineHandlePosition(prevNode->front(),prevNode->front());
+ }
+ }
+ if(nextNode){
+ if(nextNode->isEndNode()){
+ nextNodeWeight = _pm().BSplineHandlePosition(nextNode->back(),nextNode->back());
+ }
+ }
+
setPosition(new_pos);
+
_front.setPosition(_front.position() + delta);
_back.setPosition(_back.position() + delta);
// if the node has a smooth handle after a line segment, it should be kept colinear
// with the segment
_fixNeighbors(old_pos, new_pos);
+
+ // move the affected handlers. First the node ones, later the adjoining ones.
+ if(_pm().isBSpline()){
+ _front.setPosition(_pm().BSplineHandleReposition(this->front(),nodeWeight));
+ _back.setPosition(_pm().BSplineHandleReposition(this->back(),nodeWeight));
+ if(prevNode){
+ if(prevNode->isEndNode()){
+ prevNode->front()->setPosition(_pm().BSplineHandleReposition(prevNode->front(),prevNodeWeight));
+ }else{
+ prevNode->front()->setPosition(_pm().BSplineHandleReposition(prevNode->front(),prevNode->back()));
+ }
+ }
+ if(nextNode){
+ if(nextNode->isEndNode()){
+ nextNode->back()->setPosition(_pm().BSplineHandleReposition(nextNode->back(),nextNodeWeight));
+ }else{
+ nextNode->back()->setPosition(_pm().BSplineHandleReposition(nextNode->back(),nextNode->back()));
+ }
+ }
+ }
}
void Node::transform(Geom::Affine const &m)
{
+
Geom::Point old_pos = position();
+
+ // save the previous nodes strength to apply it again once the node is moved
+ double nodeWeight = 0.0000;
+ double nextNodeWeight = 0.0000;
+ double prevNodeWeight = 0.0000;
+ Node *n = this;
+ Node * nextNode = n->nodeToward(n->front());
+ Node * prevNode = n->nodeToward(n->back());
+ nodeWeight = _pm().BSplineHandlePosition(n->front());
+ if(prevNode){
+ if(prevNode->isEndNode()){
+ prevNodeWeight = _pm().BSplineHandlePosition(prevNode->front(),prevNode->front());
+ }
+ }
+ if(nextNode){
+ if(nextNode->isEndNode()){
+ nextNodeWeight = _pm().BSplineHandlePosition(nextNode->back(),nextNode->back());
+ }
+ }
+
setPosition(position() * m);
_front.setPosition(_front.position() * m);
_back.setPosition(_back.position() * m);
@@ -572,6 +696,26 @@ void Node::transform(Geom::Affine const &m)
/* Affine transforms keep handle invariants for smooth and symmetric nodes,
* but smooth nodes at ends of linear segments and auto nodes need special treatment */
_fixNeighbors(old_pos, position());
+
+ // move the involved handlers, first the node ones, later the adjoining ones
+ if(_pm().isBSpline()){
+ _front.setPosition(_pm().BSplineHandleReposition(this->front(),nodeWeight));
+ _back.setPosition(_pm().BSplineHandleReposition(this->back(),nodeWeight));
+ if(prevNode){
+ if(prevNode->isEndNode()){
+ prevNode->front()->setPosition(_pm().BSplineHandleReposition(prevNode->front(),prevNodeWeight));
+ }else{
+ prevNode->front()->setPosition(_pm().BSplineHandleReposition(prevNode->front(),prevNode->back()));
+ }
+ }
+ if(nextNode){
+ if(nextNode->isEndNode()){
+ nextNode->back()->setPosition(_pm().BSplineHandleReposition(nextNode->back(),nextNodeWeight));
+ }else{
+ nextNode->back()->setPosition(_pm().BSplineHandleReposition(nextNode->back(),nextNode->front()));
+ }
+ }
+ }
}
Geom::Rect Node::bounds() const
@@ -657,6 +801,7 @@ void Node::showHandles(bool v)
if (!_back.isDegenerate()) {
_back.setVisible(v);
}
+
}
void Node::updateHandles()
@@ -758,6 +903,16 @@ void Node::setType(NodeType type, bool update_handles)
break;
default: break;
}
+ /* in node type changes, about bspline traces, we can mantain them with 0.0000 power in border mode,
+ or we give them the default power in curve mode */
+ if(_pm().isBSpline()){
+ double weight = 0.0000;
+ if(_pm().BSplineHandlePosition(this->front()) != 0.0000 ){
+ weight = 0.3334;
+ }
+ _front.setPosition(_pm().BSplineHandleReposition(this->front(),weight));
+ _back.setPosition(_pm().BSplineHandleReposition(this->back(),weight));
+ }
}
_type = type;
_setControlType(nodeTypeToCtrlType(_type));
@@ -870,6 +1025,7 @@ bool Node::_eventHandler(Inkscape::UI::Tools::ToolBase *event_context, GdkEvent
_selection.spatialGrow(this, dir);
}
return true;
+
default:
break;
}
@@ -1004,6 +1160,11 @@ void Node::_setState(State state)
case STATE_CLICKED:
mgr.setActive(_canvas_item, true);
mgr.setPrelight(_canvas_item, false);
+ //this shows the handlers when selecting the nodes
+ if(_pm().isBSpline()){
+ this->front()->setPosition(_pm().BSplineHandleReposition(this->front()));
+ this->back()->setPosition(_pm().BSplineHandleReposition(this->back()));
+ }
break;
}
SelectableControlPoint::_setState(state);
@@ -1258,6 +1419,7 @@ Node *Node::nodeAwayFrom(Handle *h)
Glib::ustring Node::_getTip(unsigned state) const
{
+ bool isBSpline = _pm().isBSpline();
if (state_held_shift(state)) {
bool can_drag_out = (_next() && _front.isDegenerate()) || (_prev() && _back.isDegenerate());
if (can_drag_out) {
@@ -1287,15 +1449,24 @@ Glib::ustring Node::_getTip(unsigned state) const
// No modifiers: assemble tip from node type
char const *nodetype = node_type_to_localized_string(_type);
if (_selection.transformHandlesEnabled() && selected()) {
- if (_selection.size() == 1) {
+ if (_selection.size() == 1 && !isBSpline) {
return format_tip(C_("Path node tip",
"<b>%s</b>: drag to shape the path (more: Shift, Ctrl, Alt)"), nodetype);
+ }else if(_selection.size() == 1){
+ return format_tip(C_("Path node tip",
+ "<b>BSpline node</b>: %g weight, drag to shape the path (more: Shift, Ctrl, Alt)"),0.0000/*this->bsplineWeight*/);
}
return format_tip(C_("Path node tip",
"<b>%s</b>: drag to shape the path, click to toggle scale/rotation handles (more: Shift, Ctrl, Alt)"), nodetype);
}
- return format_tip(C_("Path node tip",
- "<b>%s</b>: drag to shape the path, click to select only this node (more: Shift, Ctrl, Alt)"), nodetype);
+ if (!isBSpline) {
+ return format_tip(C_("Path node tip",
+ "<b>%s</b>: drag to shape the path, click to select only this node (more: Shift, Ctrl, Alt)"), nodetype);
+ }else{
+ return format_tip(C_("Path node tip",
+ "<b>BSpline node</b>: drag to shape the path, click to select only this node (more: Shift, Ctrl, Alt)"));
+
+ }
}
Glib::ustring Node::_getDragTip(GdkEventMotion */*event*/) const
diff --git a/src/ui/tool/node.h b/src/ui/tool/node.h
index 4582d998a..5971956e1 100644
--- a/src/ui/tool/node.h
+++ b/src/ui/tool/node.h
@@ -117,7 +117,7 @@ public:
protected:
Handle(NodeSharedData const &data, Geom::Point const &initial_pos, Node *parent);
-
+ virtual void handle_2button_press();
virtual bool _eventHandler(Inkscape::UI::Tools::ToolBase *event_context, GdkEvent *event);
virtual void dragged(Geom::Point &new_pos, GdkEventMotion *event);
virtual bool grabbed(GdkEventMotion *event);
@@ -131,6 +131,7 @@ protected:
private:
inline PathManipulator &_pm();
+ inline PathManipulator &_pm() const;
Node *_parent; // the handle's lifetime does not extend beyond that of the parent node,
// so a naked pointer is OK and allows setting it during Node's construction
SPCtrlLine *_handle_line;
@@ -217,6 +218,7 @@ public:
Node *nodeAwayFrom(Handle *h);
NodeList &nodeList() { return *(static_cast<ListNode*>(this)->ln_list); }
+ NodeList &nodeList() const { return *(static_cast<ListNode const*>(this)->ln_list); }
/**
* Move the node to the bottom of its canvas group.
@@ -263,6 +265,7 @@ private:
Inkscape::SnapSourceType _snapSourceType() const;
Inkscape::SnapTargetType _snapTargetType() const;
inline PathManipulator &_pm();
+ inline PathManipulator &_pm() const;
/** Determine whether two nodes are joined by a linear segment. */
static bool _is_line_segment(Node *first, Node *second);
@@ -490,10 +493,17 @@ inline double Handle::length() const {
inline PathManipulator &Handle::_pm() {
return _parent->_pm();
}
+inline PathManipulator &Handle::_pm() const {
+ return _parent->_pm();
+}
inline PathManipulator &Node::_pm() {
return nodeList().subpathList().pm();
}
+inline PathManipulator &Node::_pm() const {
+ return nodeList().subpathList().pm();
+}
+
// definitions for node iterator
template <typename N>
NodeIterator<N>::operator bool() const {
diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp
index 338499672..3beeed049 100644
--- a/src/ui/tool/path-manipulator.cpp
+++ b/src/ui/tool/path-manipulator.cpp
@@ -42,6 +42,7 @@
#include "ui/tool/multi-path-manipulator.h"
#include "xml/node.h"
#include "xml/node-observer.h"
+#include "live_effects/lpe-bspline.h"
namespace Inkscape {
namespace UI {
@@ -102,7 +103,6 @@ private:
};
void build_segment(Geom::PathBuilder &, Node *, Node *);
-
PathManipulator::PathManipulator(MultiPathManipulator &mpm, SPPath *path,
Geom::Affine const &et, guint32 outline_color, Glib::ustring lpe_key)
: PointManipulator(mpm._path_data.node_data.desktop, *mpm._path_data.node_data.selection)
@@ -145,6 +145,8 @@ PathManipulator::PathManipulator(MultiPathManipulator &mpm, SPPath *path,
sigc::hide( sigc::mem_fun(*this, &PathManipulator::_updateOutlineOnZoomChange)));
_createControlPointsFromGeometry();
+ //Define if the path is BSpline on construction
+ isBSpline(true);
}
PathManipulator::~PathManipulator()
@@ -662,6 +664,15 @@ unsigned PathManipulator::_deleteStretch(NodeList::iterator start, NodeList::ite
nl.erase(start);
start = next;
}
+ // if we are removing, we readjust the handlers
+ if(isBSpline()){
+ if(start.prev()){
+ start.prev()->front()->setPosition(BSplineHandleReposition(start.prev()->front(),start.prev()->back()));
+ }
+ if(end){
+ end->back()->setPosition(BSplineHandleReposition(end->back(),end->front()));
+ }
+ }
return del_len;
}
@@ -816,7 +827,6 @@ void PathManipulator::scaleHandle(Node *n, int which, int dir, bool pixel)
}
h->setRelativePos(relpos);
update();
-
gchar const *key = which < 0 ? "handle:scale:left" : "handle:scale:right";
_commit(_("Scale handle"), key);
}
@@ -1104,7 +1114,6 @@ void PathManipulator::_createControlPointsFromGeometry()
Geom::Curve const &cseg = pit->back_closed();
bool fuse_ends = pit->closed()
&& Geom::are_near(cseg.initialPoint(), cseg.finalPoint());
-
for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit) {
Geom::Point pos = cit->finalPoint();
Node *current_node;
@@ -1171,6 +1180,89 @@ void PathManipulator::_createControlPointsFromGeometry()
}
}
+//determines if the trace has a bspline effect and the number of steps that it takes
+int PathManipulator::BSplineGetSteps() const {
+
+ LivePathEffect::LPEBSpline const *lpe_bsp = NULL;
+
+ if (SP_IS_LPE_ITEM(_path) && _path->hasPathEffect()){
+ Inkscape::LivePathEffect::Effect const *thisEffect = SP_LPE_ITEM(_path)->getPathEffectOfType(Inkscape::LivePathEffect::BSPLINE);
+ if(thisEffect){
+ lpe_bsp = dynamic_cast<LivePathEffect::LPEBSpline const*>(thisEffect->getLPEObj()->get_lpe());
+ }
+ }
+ int steps = 0;
+ if(lpe_bsp){
+ steps = lpe_bsp->steps+1;
+ }
+ return steps;
+}
+
+// determines if the trace has bspline effect
+bool PathManipulator::isBSpline(bool recalculate){
+ if(recalculate){
+ _is_bspline = this->BSplineGetSteps() > 0;
+ }
+ return _is_bspline;
+}
+
+bool PathManipulator::isBSpline() const {
+ return BSplineGetSteps() > 0;
+}
+
+// returns the corresponding strength to the position of the handlers
+double PathManipulator::BSplineHandlePosition(Handle *h, Handle *h2){
+ using Geom::X;
+ using Geom::Y;
+ if(h2){
+ h = h2;
+ }
+ double pos = 0.0000;
+ Node *n = h->parent();
+ Node * nextNode = NULL;
+ nextNode = n->nodeToward(h);
+ if(nextNode){
+ SPCurve *lineInsideNodes = new SPCurve();
+ lineInsideNodes->moveto(n->position());
+ lineInsideNodes->lineto(nextNode->position());
+ pos = Geom::nearest_point(h->position(),*lineInsideNodes->first_segment());
+ }
+ if (pos == 0.0000 && !h2){
+ return BSplineHandlePosition(h, h->other());
+ }
+ return pos;
+}
+
+// give the location for the handler in the corresponding position
+Geom::Point PathManipulator::BSplineHandleReposition(Handle *h, Handle *h2){
+ double pos = this->BSplineHandlePosition(h, h2);
+ return BSplineHandleReposition(h,pos);
+}
+
+// give the location for the handler to the specified position
+Geom::Point PathManipulator::BSplineHandleReposition(Handle *h,double pos){
+ using Geom::X;
+ using Geom::Y;
+ Geom::Point ret = h->position();
+ Node *n = h->parent();
+ Geom::D2< Geom::SBasis > SBasisInsideNodes;
+ SPCurve *lineInsideNodes = new SPCurve();
+ Node * nextNode = NULL;
+ nextNode = n->nodeToward(h);
+ if(nextNode && pos != 0.0000){
+ lineInsideNodes->moveto(n->position());
+ lineInsideNodes->lineto(nextNode->position());
+ SBasisInsideNodes = lineInsideNodes->first_segment()->toSBasis();
+ ret = SBasisInsideNodes.valueAt(pos);
+ ret = Geom::Point(ret[X] + 0.005,ret[Y] + 0.005);
+ }else{
+ if(pos == 0.0000){
+ ret = n->position();
+ }
+ }
+ return ret;
+}
+
/** Construct the geometric representation of nodes and handles, update the outline
* and display
* \param alert_LPE if true, first the LPE is warned what the new path is going to be before updating it
@@ -1178,6 +1270,8 @@ void PathManipulator::_createControlPointsFromGeometry()
void PathManipulator::_createGeometryFromControlPoints(bool alert_LPE)
{
Geom::PathBuilder builder;
+ //Refresh if is bspline some times -think on path change selection, this value get lost
+ isBSpline(true);
for (std::list<SubpathPtr>::iterator spi = _subpaths.begin(); spi != _subpaths.end(); ) {
SubpathPtr subpath = *spi;
if (subpath->empty()) {
@@ -1186,7 +1280,6 @@ void PathManipulator::_createGeometryFromControlPoints(bool alert_LPE)
}
NodeList::iterator prev = subpath->begin();
builder.moveTo(prev->position());
-
for (NodeList::iterator i = ++subpath->begin(); i != subpath->end(); ++i) {
build_segment(builder, prev.ptr(), i.ptr());
prev = i;
diff --git a/src/ui/tool/path-manipulator.h b/src/ui/tool/path-manipulator.h
index 7a13ce723..151805c83 100644
--- a/src/ui/tool/path-manipulator.h
+++ b/src/ui/tool/path-manipulator.h
@@ -19,6 +19,7 @@
#include <boost/weak_ptr.hpp>
#include "ui/tool/node.h"
#include "ui/tool/manipulator.h"
+#include "live_effects/lpe-bspline.h"
struct SPCanvasItem;
class SPCurve;
@@ -95,6 +96,7 @@ public:
NodeList::iterator extremeNode(NodeList::iterator origin, bool search_selected,
bool search_unselected, bool closest);
+ int BSplineGetSteps() const;
// this is necessary for Tab-selection in MultiPathManipulator
SubpathList &subpathList() { return _subpaths; }
@@ -104,6 +106,12 @@ private:
typedef boost::shared_ptr<NodeList> SubpathPtr;
void _createControlPointsFromGeometry();
+
+ bool isBSpline(bool recalculate = false);
+ bool isBSpline() const;
+ double BSplineHandlePosition(Handle *h, Handle *h2 = NULL);
+ Geom::Point BSplineHandleReposition(Handle *h, Handle *h2 = NULL);
+ Geom::Point BSplineHandleReposition(Handle *h, double pos);
void _createGeometryFromControlPoints(bool alert_LPE = false);
unsigned _deleteStretch(NodeList::iterator first, NodeList::iterator last, bool keep_shape);
std::string _createTypeString();
@@ -145,6 +153,7 @@ private:
bool _show_path_direction;
bool _live_outline;
bool _live_objects;
+ bool _is_bspline;
Glib::ustring _lpe_key;
friend class PathManipulatorObserver;