summaryrefslogtreecommitdiffstats
path: root/src/ui/tool/node.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/tool/node.cpp')
-rw-r--r--src/ui/tool/node.cpp180
1 files changed, 165 insertions, 15 deletions
diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp
index e246bf997..73460a313 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,7 @@
#include "ui/tool/node.h"
#include "ui/tool/path-manipulator.h"
#include <gdk/gdkkeysyms.h>
+#include <math.h>
namespace {
@@ -166,6 +166,12 @@ void Handle::move(Geom::Point const &new_pos)
}
}
setPosition(new_pos);
+
+ //move the handler and its oposite the same proportion
+ if(_pm().isBSpline(false)){
+ setPosition(_pm().BSplineHandleReposition(this));
+ this->other()->setPosition(_pm().BSplineHandleReposition(this->other(),_parent->bsplineWeight));
+ }
return;
}
@@ -177,6 +183,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(false)){
+ setPosition(_pm().BSplineHandleReposition(this));
+ this->other()->setPosition(_pm().BSplineHandleReposition(this->other(),_parent->bsplineWeight));
+ }
+
return;
}
@@ -195,8 +208,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(false)){
+ setPosition(_pm().BSplineHandleReposition(this));
+ this->other()->setPosition(_pm().BSplineHandleReposition(this->other(),_parent->bsplineWeight));
+ }
+
}
void Handle::setPosition(Geom::Point const &p)
@@ -273,12 +292,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(false)){
+ setPosition(_pm().BSplineHandleReposition(this,0.3334));
+ this->other()->setPosition(_pm().BSplineHandleReposition(this->other(),_parent->bsplineWeight));
+ _pm().update();
+ }
+}
+
bool Handle::grabbed(GdkEventMotion *)
{
_saved_other_pos = other()->position();
@@ -326,10 +359,19 @@ 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(false)){
+ setPosition(new_pos);
+ int steps = _pm().BSplineGetSteps();
+ _parent->bsplineWeight = ceilf(_pm().BSplineHandlePosition(this)*steps)/steps;
+ new_pos=_pm().BSplineHandleReposition(this,_parent->bsplineWeight);
+ }
}
std::vector<Inkscape::SnapCandidatePoint> unselected;
- if (snap) {
+ //if the snap adjustment is activated and it is not bspline
+ if (snap && !_pm().isBSpline(false)) {
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(false) && !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();
}
@@ -385,6 +431,10 @@ void Handle::ungrabbed(GdkEventButton *event)
Geom::Point dist = _desktop->d2w(_parent->position()) - _desktop->d2w(position());
if (dist.length() <= drag_tolerance) {
move(_parent->position());
+ //sets the bspline strength to 0.0000
+ if(_pm().isBSpline(false)){
+ _parent->bsplineWeight = 0.0000;
+ }
}
}
@@ -427,13 +477,21 @@ 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 = false;
+ if( _parent->bsplineWeight != 0.0000)
+ isBSpline = true;
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 +514,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 +540,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,17 +621,38 @@ 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 node strength to apply it again once the node is moved
+ double oldPos = 0.0000;
+ Node *n = this;
+ if(_pm().isBSpline(false)){
+ oldPos = n->bsplineWeight;
+ }
+
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(false)){
+ _front.setPosition(_pm().BSplineHandleReposition(this->front(),oldPos));
+ _back.setPosition(_pm().BSplineHandleReposition(this->back(),oldPos));
+ _pm().BSplineNodeHandlesReposition(this);
+ }
}
void Node::transform(Geom::Affine const &m)
{
+ // save the previous node strength to apply it again later when the node is moved
+ double oldPos = 0.0000;
+ if(_pm().isBSpline(false)){
+ oldPos = this->bsplineWeight;
+ }
Geom::Point old_pos = position();
setPosition(position() * m);
_front.setPosition(_front.position() * m);
@@ -572,6 +661,13 @@ 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(false)){
+ _front.setPosition(_pm().BSplineHandleReposition(this->front(),oldPos));
+ _back.setPosition(_pm().BSplineHandleReposition(this->back(),oldPos));
+ _pm().BSplineNodeHandlesReposition(this);
+ }
}
Geom::Rect Node::bounds() const
@@ -657,6 +753,20 @@ void Node::showHandles(bool v)
if (!_back.isDegenerate()) {
_back.setVisible(v);
}
+
+ // define the node strength, depending on being or not bspline traced.
+ // every time we operate over these handlers in a trace bspline
+ // that strength needs to be updated.
+
+ this->bsplineWeight = 0.0000;
+ if(_pm().isBSpline(false) && (!_front.isDegenerate() || !_back.isDegenerate())){
+ if (!_front.isDegenerate()) {
+ _pm().BSplineHandlePosition(&_front);
+ }
+ if (!_back.isDegenerate()) {
+ _pm().BSplineHandlePosition(&_back);
+ }
+ }
}
void Node::updateHandles()
@@ -758,6 +868,13 @@ 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(false)){
+ if(this->bsplineWeight !=0.0000) this->bsplineWeight = 0.3334;
+ _front.setPosition(_pm().BSplineHandleReposition(this->front(),this->bsplineWeight));
+ _back.setPosition(_pm().BSplineHandleReposition(this->back(),this->bsplineWeight));
+ }
}
_type = type;
_setControlType(nodeTypeToCtrlType(_type));
@@ -870,6 +987,7 @@ bool Node::_eventHandler(Inkscape::UI::Tools::ToolBase *event_context, GdkEvent
_selection.spatialGrow(this, dir);
}
return true;
+
default:
break;
}
@@ -1004,6 +1122,22 @@ 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(false)){
+ if(!this->back()->isDegenerate()){
+ _pm().BSplineHandlePosition(this->back());
+ }else if (!this->front()->isDegenerate()){
+ _pm().BSplineHandlePosition(this->front());
+ }else{
+ this->bsplineWeight = 0.0000;
+ }
+ if(!this->front()->isDegenerate()){
+ this->front()->setPosition(_pm().BSplineHandleReposition(this->front(),this->bsplineWeight));
+ }
+ if(!this->back()->isDegenerate()){
+ this->back()->setPosition(_pm().BSplineHandleReposition(this->back(),this->bsplineWeight));
+ }
+ }
break;
}
SelectableControlPoint::_setState(state);
@@ -1254,6 +1388,13 @@ Node *Node::nodeAwayFrom(Handle *h)
Glib::ustring Node::_getTip(unsigned state) const
{
+
+ /* if the node doesnt have strength, it marks it as bspline, we'll use it later
+ to show the appropiate messages. We cannot do it in any other way, because the
+ function is constant */
+ bool isBSpline = false;
+ if( this->bsplineWeight != 0.0000)
+ isBSpline = true;
if (state_held_shift(state)) {
bool can_drag_out = (_next() && _front.isDegenerate()) || (_prev() && _back.isDegenerate());
if (can_drag_out) {
@@ -1283,15 +1424,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)"),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