summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: c635a68)
raw | patch | inline | side by side (parent: c635a68)
author | Krzysztof Kosiński <tweenk.pl@gmail.com> | |
Tue, 8 Dec 2009 02:21:08 +0000 (03:21 +0100) | ||
committer | Krzysztof Kosiński <tweenk.pl@gmail.com> | |
Tue, 8 Dec 2009 02:21:08 +0000 (03:21 +0100) |
16 files changed:
index 9232792f68426f4ba15a6b4f69d63051769ae3dd..dfa9fe6b2b0e2d80c9902f1ea7c6ca361767869b 100644 (file)
}
}
-void
-Effect::setup_nodepath(Inkscape::NodePath::Path *np)
-{
- np->helperpath_rgba = 0xff0000ff;
- np->helperpath_width = 1.0;
-}
-
void
Effect::transform_multiply(Geom::Matrix const& postmul, bool set)
{
index 5d67ed0167f01c89e68257096e5256e96ddc120d..a8d34a2338a864ffd514ea996b63e4a742e12786 100644 (file)
*/
virtual void resetDefaults(SPItem * item);
- virtual void setup_nodepath(Inkscape::NodePath::Path *np);
-
/// /todo: is this method really necessary? it causes UI inconsistensies... (johan)
virtual void transform_multiply(Geom::Matrix const& postmul, bool set);
index 144f4720d92d7d7970ee51967712f951f86b02e9..d83529957986788f76ea107e48dffd63a8f4db60 100644 (file)
}
}
-void
-LPEConstructGrid::setup_nodepath(Inkscape::NodePath::Path *np)
-{
- Effect::setup_nodepath(np);
- sp_nodepath_make_straight_path(np);
-}
-
} //namespace LivePathEffect
} /* namespace Inkscape */
index 716960d32d8e0489318abc29e9b597ff1817fb4c..c7e6957941d1fc61dbfff73aaacbdb43467bb1d5 100644 (file)
virtual std::vector<Geom::Path> doEffect_path (std::vector<Geom::Path> const & path_in);
- virtual void setup_nodepath(Inkscape::NodePath::Path *np);
-
private:
ScalarParam nr_x;
ScalarParam nr_y;
index e211483c629c8ac619da054a33688d1421c84f18..bd1ce79989fba16c112df5bf2c41a94c2c149ffc 100644 (file)
return path_out;
}
-void
-LPEGears::setup_nodepath(Inkscape::NodePath::Path *np)
-{
- Effect::setup_nodepath(np);
- sp_nodepath_make_straight_path(np);
-}
-
} // namespace LivePathEffect
} /* namespace Inkscape */
index 4c3a9938bd4385f52111a9f36f17838801f3d24d..bd5e4c4f9728c465e81bc97c3be255054ce0dccb 100644 (file)
virtual std::vector<Geom::Path> doEffect_path (std::vector<Geom::Path> const & path_in);
- virtual void setup_nodepath(Inkscape::NodePath::Path *np);
-
private:
ScalarParam teeth;
ScalarParam phi;
index 794fd980e8b1ad06aeef83b3b8914dc343d53555..087b883515a3c27924d001c836239e6597e5a91d 100644 (file)
{
}
-void
-LPESpiro::setup_nodepath(Inkscape::NodePath::Path *np)
-{
- Effect::setup_nodepath(np);
- sp_nodepath_show_handles(np, false);
-// sp_nodepath_show_helperpath(np, false);
-}
-
void
LPESpiro::doEffect(SPCurve * curve)
{
index 7256665a2ea3254ea465bf89c9093c26ef2dbb9f..4fcd9eaaaad081699d8bc48b2bf121d5bbee0c3e 100644 (file)
virtual LPEPathFlashType pathFlashType() { return SUPPRESS_FLASH; }
- virtual void setup_nodepath(Inkscape::NodePath::Path *np);
virtual void doEffect(SPCurve * curve);
private:
index 7fd0ac0b493c1ee4258747f7dc005af6829a55f0..b2a5d56fa1184defd1c861f56f06dfe798b94f95 100644 (file)
VonKochPathParam::param_setup_nodepath(Inkscape::NodePath::Path *np)
{
PathParam::param_setup_nodepath(np);
- sp_nodepath_make_straight_path(np);
+ //sp_nodepath_make_straight_path(np);
}
//FIXME: a path is used here instead of 2 points to work around path/point param incompatibility bug.
VonKochRefPathParam::param_setup_nodepath(Inkscape::NodePath::Path *np)
{
PathParam::param_setup_nodepath(np);
- sp_nodepath_make_straight_path(np);
+ //sp_nodepath_make_straight_path(np);
}
bool
VonKochRefPathParam::param_readSVGValue(const gchar * strvalue)
{
- std::vector<Geom::Path> old = _pathvector;
+ Geom::PathVector old = _pathvector;
bool res = PathParam::param_readSVGValue(strvalue);
if (res && _pathvector.size()==1 && _pathvector.front().size()==1){
return true;
index 93dfd2667a68da7ed3311b9f8a87217317918781..3a03de51cf6f0735651b0bf155784ab8f4d2d904 100644 (file)
#include "sp-text.h"
#include "display/curve.h"
+#include "ui/tool/node-tool.h"
+#include "ui/tool/multi-path-manipulator.h"
+#include "ui/tool/shape-record.h"
+
namespace Inkscape {
void
PathParam::param_editOncanvas(SPItem * item, SPDesktop * dt)
{
- // TODO this whole method is broken!
+ using namespace Inkscape::UI;
+
+ // TODO remove the tools_switch atrocity.
+ if (!tools_isactive(dt, TOOLS_NODES)) {
+ tools_switch(dt, TOOLS_NODES);
+ }
+
+ InkNodeTool *nt = static_cast<InkNodeTool*>(dt->event_context);
+ std::set<ShapeRecord> shapes;
+ ShapeRecord r;
+
+ r.role = SHAPE_ROLE_LPE_PARAM;
+ r.edit_transform = Geom::identity(); // TODO this is almost certainly wrong
+ if (!href) {
+ r.item = reinterpret_cast<SPItem*>(param_effect->getLPEObj());
+ r.lpe_key = param_key;
+ } else {
+ r.item = ref.getObject();
+ }
+ shapes.insert(r);
+ nt->_multipath->setItems(shapes);
}
void
-PathParam::param_setup_nodepath(Inkscape::NodePath::Path *np)
+PathParam::param_setup_nodepath(Inkscape::NodePath::Path *)
{
- // TODO this too!
- np->show_helperpath = true;
- np->helperpath_rgba = 0x009000ff;
- np->helperpath_width = 1.0;
+ // TODO this method should not exist at all!
}
void
diff --git a/src/nodepath.cpp b/src/nodepath.cpp
index 8f17ae0133122477bd60f9583553eed265fa15fb..36e4e0d8c5dd6d3e6c44cdfed84c0c4dcc80a8ec 100644 (file)
--- a/src/nodepath.cpp
+++ b/src/nodepath.cpp
Inkscape::LivePathEffect::Effect* lpe = sp_lpe_item_get_current_lpe(SP_LPE_ITEM(np->object));
if (lpe) {
- lpe->setup_nodepath(np);
+ //lpe->setup_nodepath(np);
}
} else {
np->repr_key = g_strdup("d");
index 7c539f6b90850e5140d63337a24bb1a4b4966a0e..aaf7e413cdfd303805a7ec4002502cbca9f6eb7d 100644 (file)
#include "desktop.h"
#include "desktop-handles.h"
#include "document.h"
+#include "live_effects/lpeobject.h"
#include "message-stack.h"
#include "preferences.h"
#include "sp-path.h"
}
}
+/** @brief Change the set of items to edit.
+ *
+ * This method attempts to preserve as much of the state as possible. */
void MultiPathManipulator::setItems(std::set<ShapeRecord> const &s)
{
std::set<ShapeRecord> shapes(s);
// add newly selected items
for (std::set<ShapeRecord>::iterator i = shapes.begin(); i != shapes.end(); ++i) {
ShapeRecord const &r = *i;
- if (!SP_IS_PATH(r.item)) continue;
+ if (!SP_IS_PATH(r.item) && !IS_LIVEPATHEFFECT(r.item)) continue;
boost::shared_ptr<PathManipulator> newpm(new PathManipulator(_path_data, (SPPath*) r.item,
- r.edit_transform, _getOutlineColor(r.role)));
+ r.edit_transform, _getOutlineColor(r.role), r.lpe_key));
newpm->showHandles(_show_handles);
// always show outlines for clips and masks
newpm->showOutline(_show_outline || r.role != SHAPE_ROLE_NORMAL);
void MultiPathManipulator::joinNodes()
{
+ invokeForAll(&PathManipulator::hideDragPoint);
// Node join has two parts. In the first one we join two subpaths by fusing endpoints
// into one. In the second we fuse nodes in each subpath.
IterPairList joins;
case SHAPE_ROLE_MASK:
return prefs->getColor("/tools/nodes/mask_color", 0x0000ffff);
case SHAPE_ROLE_LPE_PARAM:
- return prefs->getColor("/tools/nodes/lpe_param_color", 0xb700ffff);
+ return prefs->getColor("/tools/nodes/lpe_param_color", 0x009000ff);
case SHAPE_ROLE_NORMAL:
default:
return prefs->getColor("/tools/nodes/outline_color", 0xff0000ff);
index 31c7227447226d9ba83d3b4b945fdb9aa32ab95e..9103f066f9bc4e65ea7e6733652a6c1a6389ae9c 100644 (file)
#include "display/curve.h"
#include "display/sp-canvas.h"
#include "document.h"
+#include "live_effects/lpeobject.h"
#include "message-context.h"
#include "selection.h"
#include "shape-editor.h" // temporary!
sigc::bind<0>(
sigc::ptr_fun(&ink_node_tool_selection_changed),
nt));
- nt->_selection_modified_connection.disconnect();
+ /*nt->_selection_modified_connection.disconnect();
nt->_selection_modified_connection =
selection->connectModified(
sigc::hide(sigc::bind<0>(
- sigc::ptr_fun(&ink_node_tool_selection_changed),
- nt)));
+ sigc::ptr_fun(&ink_node_tool_selection_modified),
+ nt)));*/
nt->_mouseover_changed_connection.disconnect();
nt->_mouseover_changed_connection =
Inkscape::UI::ControlPoint::signal_mouseover_change.connect(
@@ -293,28 +294,20 @@ void ink_node_tool_set(SPEventContext *ec, Inkscape::Preferences::Entry *value)
}
}
-void store_clip_mask_items(SPItem *clipped, SPObject *obj, std::map<SPItem*,
- std::pair<Geom::Matrix, guint32> > &s, Geom::Matrix const &postm, guint32 color)
-{
- if (!obj) return;
- if (SP_IS_GROUP(obj) || SP_IS_OBJECTGROUP(obj)) {
- //TODO is checking for obj->children != NULL above better?
- for (SPObject *c = obj->children; c; c = c->next) {
- store_clip_mask_items(clipped, c, s, postm, color);
- }
- } else if (SP_IS_ITEM(obj)) {
- s.insert(std::make_pair(SP_ITEM(obj),
- std::make_pair(sp_item_i2d_affine(clipped) * postm, color)));
- }
-}
-
/** Recursively collect ShapeRecords */
void gather_items(InkNodeTool *nt, SPItem *base, SPObject *obj, Inkscape::UI::ShapeRole role,
std::set<Inkscape::UI::ShapeRecord> &s)
{
using namespace Inkscape::UI;
if (!obj) return;
- if (role != SHAPE_ROLE_NORMAL && (SP_IS_GROUP(obj) || SP_IS_OBJECTGROUP(obj))) {
+
+ if (SP_IS_PATH(obj) && obj->repr->attribute("inkscape:original-d") != NULL) {
+ ShapeRecord r;
+ r.item = static_cast<SPItem*>(obj);
+ r.edit_transform = Geom::identity(); // TODO wrong?
+ r.role = SHAPE_ROLE_LPE_PARAM;
+ s.insert(r);
+ } else if (role != SHAPE_ROLE_NORMAL && (SP_IS_GROUP(obj) || SP_IS_OBJECTGROUP(obj))) {
for (SPObject *c = obj->children; c; c = c->next) {
gather_items(nt, base, c, role, s);
}
@@ -325,7 +318,6 @@ void gather_items(InkNodeTool *nt, SPItem *base, SPObject *obj, Inkscape::UI::Sh
// TODO add support for objectBoundingBox
r.edit_transform = base ? sp_item_i2doc_affine(base) : Geom::identity();
r.role = role;
- r.edit_original = false;
if (s.insert(r).second) {
// this item was encountered the first time
if (nt->edit_clipping_paths && item->clip_ref) {
index e9ec78b2e08a51d6e892d7d4ec90421c7207a35c..0ad509a9b473ab06586834a3245c968dd3a967e1 100644 (file)
#include "display/curve.h"
#include "display/canvas-bpath.h"
#include "document.h"
+#include "live_effects/effect.h"
+#include "live_effects/lpeobject.h"
+#include "live_effects/parameter/path.h"
#include "sp-path.h"
#include "helper/geom.h"
#include "preferences.h"
virtual void notifyAttributeChanged(Inkscape::XML::Node &, GQuark attr,
Util::ptr_shared<char>, Util::ptr_shared<char>)
{
- GQuark path_d = g_quark_from_static_string("d");
- GQuark path_transform = g_quark_from_static_string("transform");
// do nothing if blocked
if (_blocked) return;
+ GQuark path_d = g_quark_from_static_string("d");
+ GQuark path_transform = g_quark_from_static_string("transform");
+ GQuark lpe_quark = _pm->_lpe_key.empty() ? 0 : g_quark_from_string(_pm->_lpe_key.data());
+
// only react to "d" (path data) and "transform" attribute changes
- if (attr == path_d) {
+ if (attr == lpe_quark || attr == path_d) {
_pm->_externalChange(PATH_CHANGE_D);
} else if (attr == path_transform) {
_pm->_externalChange(PATH_CHANGE_TRANSFORM);
void build_segment(Geom::PathBuilder &, Node *, Node *);
PathManipulator::PathManipulator(PathSharedData const &data, SPPath *path,
- Geom::Matrix const &et, guint32 outline_color)
+ Geom::Matrix const &et, guint32 outline_color, Glib::ustring lpe_key)
: PointManipulator(data.node_data.desktop, *data.node_data.selection)
, _path_data(data)
, _path(path)
- , _spcurve(sp_path_get_curve_for_edit(path))
+ , _spcurve(NULL)
, _dragpoint(new CurveDragPoint(*this))
, _observer(new PathManipulatorObserver(this))
, _edit_transform(et)
, _show_handles(true)
, _show_outline(false)
+ , _lpe_key(lpe_key)
{
/* Because curve drag point is always created first, it does not cover nodes */
- _i2d_transform = sp_item_i2d_affine(SP_ITEM(path));
+ if (_lpe_key.empty()) {
+ _i2d_transform = sp_item_i2d_affine(SP_ITEM(path));
+ } else {
+ _i2d_transform = Geom::identity();
+ }
_d2i_transform = _i2d_transform.inverse();
_dragpoint->setVisible(false);
+ _getGeometry();
+
_outline = sp_canvas_bpath_new(_path_data.outline_group, NULL);
sp_canvas_item_hide(_outline);
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(_outline), outline_color, 1.0,
if (_path) _path->repr->removeObserver(*_observer);
delete _observer;
gtk_object_destroy(_outline);
- _spcurve->unref();
+ if (_spcurve) _spcurve->unref();
clear();
}
if (!_path) return;
_observer->block();
if (!empty()) {
- _path->updateRepr();
- _path->repr->setAttribute("sodipodi:nodetypes", _createTypeString().data());
+ SP_OBJECT(_path)->updateRepr();
+ _getXMLNode()->setAttribute(_nodetypesKey().data(), _createTypeString().data());
} else {
// this manipulator will have to be destroyed right after this call
- _path->repr->removeObserver(*_observer);
+ _getXMLNode()->removeObserver(*_observer);
sp_object_ref(_path);
_path->deleteObject(true, true);
sp_object_unref(_path);
/** Replace contiguous selections of nodes in each subpath with one node. */
void PathManipulator::weldNodes(NodeList::iterator const &preserve_pos)
{
+ if (!_num_selected) return;
+ _dragpoint->setVisible(false);
+
bool pos_valid = preserve_pos;
for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) {
SubpathPtr sp = *i;
void PathManipulator::deleteNodes(bool keep_shape)
{
if (!_num_selected) return;
-
+ hideDragPoint();
+
unsigned const samples_per_segment = 10;
double const t_step = 1.0 / samples_per_segment;
if (j->selected()) ++num_selected;
else ++num_unselected;
}
- if (num_selected == 0) continue;
+ if (num_selected == 0) {
+ ++i;
+ continue;
+ }
if (sp->closed() ? (num_unselected < 1) : (num_unselected < 2)) {
_subpaths.erase(i++);
continue;
// 2. we are deleting at the end or beginning of an open path
// if !sel_end then sel_beg.prev() must be valid, otherwise the entire subpath
// would be deleted before we get here
- if (keep_shape || !sel_end) sel_beg.prev()->setType(NODE_CUSP, false);
- if (keep_shape || !sel_beg.prev()) sel_end->setType(NODE_CUSP, false);
+ if ((keep_shape || !sel_end) && sel_beg.prev()) sel_beg.prev()->setType(NODE_CUSP, false);
+ if ((keep_shape || !sel_beg.prev()) && sel_end) sel_end->setType(NODE_CUSP, false);
if (keep_shape && sel_beg.prev() && sel_end) {
// Fill fit data
// Fill last point
bezier_data[num_samples - 1] = sel_end->position();
// Compute replacement bezier curve
- // TODO find out optimal error value
+ // TODO the fitting algorithm sucks - rewrite it to be awesome
bezier_fit_cubic(result, bezier_data, num_samples, 0.5);
delete[] bezier_data;
void PathManipulator::deleteSegments()
{
if (_num_selected == 0) return;
+ hideDragPoint();
+
for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end();) {
SubpathPtr sp = *i;
bool has_unselected = false;
_createGeometryFromControlPoints();
}
+void PathManipulator::hideDragPoint()
+{
+ _dragpoint->setVisible(false);
+ _dragpoint->setIterator(NodeList::iterator());
+}
+
/** Insert a node in the segment beginning with the supplied iterator,
* at the given time value */
NodeList::iterator PathManipulator::subdivideSegment(NodeList::iterator first, double t)
{
switch (type) {
case PATH_CHANGE_D: {
- _spcurve->unref();
- _spcurve = sp_path_get_curve_for_edit(_path);
+ _getGeometry();
// ugly: stored offsets of selected nodes in a vector
// vector<bool> should be specialized so that it takes only 1 bit per value
// we need to set the nodetypes after all the handles are in place,
// so that pickBestType works correctly
// TODO maybe migrate to inkscape:node-types?
- gchar const *nts_raw = _path ? _path->repr->attribute("sodipodi:nodetypes") : 0;
+ gchar const *nts_raw = _path ? _path->repr->attribute(_nodetypesKey().data()) : 0;
std::string nodetype_string = nts_raw ? nts_raw : "";
/* Calculate the needed length of the nodetype string.
* For closed paths, the entry is duplicated for the starting node,
builder.finish();
_spcurve->set_pathvector(builder.peek() * (_edit_transform * _i2d_transform).inverse());
_updateOutline();
- if (!empty()) sp_shape_set_curve(SP_SHAPE(_path), _spcurve, false);
+ _setGeometry();
}
/** Build one segment of the geometric representation.
_hc->unref();
}
+/** Retrieve the geometry of the edited object from the object tree */
+void PathManipulator::_getGeometry()
+{
+ using namespace Inkscape::LivePathEffect;
+ if (!_lpe_key.empty()) {
+ Effect *lpe = LIVEPATHEFFECT(_path)->get_lpe();
+ if (lpe) {
+ PathParam *pathparam = dynamic_cast<PathParam *>(lpe->getParameter(_lpe_key.data()));
+ if (!_spcurve)
+ _spcurve = new SPCurve(pathparam->get_pathvector());
+ else
+ _spcurve->set_pathvector(pathparam->get_pathvector());
+ }
+ } else {
+ if (_spcurve) _spcurve->unref();
+ _spcurve = sp_path_get_curve_for_edit(_path);
+ }
+}
+
+/** Set the geometry of the edited object in the object tree, but do not commit to XML */
+void PathManipulator::_setGeometry()
+{
+ using namespace Inkscape::LivePathEffect;
+ if (empty()) return;
+
+ if (!_lpe_key.empty()) {
+ // LPE brain damage follows - copied from nodepath.cpp
+ // NOTE: if we are editing an LPE param, _path is not actually an SPPath, it is
+ // a LivePathEffectObject.
+ Effect *lpe = LIVEPATHEFFECT(_path)->get_lpe();
+ if (lpe) {
+ PathParam *pathparam = dynamic_cast<PathParam *>(lpe->getParameter(_lpe_key.data()));
+ pathparam->set_new_value(_spcurve->get_pathvector(), false);
+ LIVEPATHEFFECT(_path)->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ }
+ } else {
+ if (_path->repr->attribute("inkscape:original-d"))
+ sp_path_set_original_curve(_path, _spcurve, true, false);
+ else
+ sp_shape_set_curve(SP_SHAPE(_path), _spcurve, false);
+ }
+}
+
+/** LPE brain damage */
+Glib::ustring PathManipulator::_nodetypesKey()
+{
+ if (_lpe_key.empty()) return "sodipodi:nodetypes";
+ return _lpe_key + "-nodetypes";
+}
+
+/** LPE brain damage */
+Inkscape::XML::Node *PathManipulator::_getXMLNode()
+{
+ if (_lpe_key.empty()) return _path->repr;
+ return LIVEPATHEFFECT(_path)->repr;
+}
+
void PathManipulator::_attachNodeHandlers(Node *node)
{
Handle *handles[2] = { node->front(), node->back() };
index 01a2b6cbf5bbc3c756c7d812252e044d69f0508d..e0d8c68ca9490e9668f5dcf280c536f9b42b793d 100644 (file)
struct SPCanvasItem;
namespace Inkscape {
+namespace XML { class Node; }
namespace UI {
class PathManipulator;
public:
typedef SPPath *ItemType;
- PathManipulator(PathSharedData const &data, SPPath *path,
- Geom::Matrix const &edit_trans, guint32 outline_color);
+ PathManipulator(PathSharedData const &data, SPPath *path, Geom::Matrix const &edit_trans,
+ guint32 outline_color, Glib::ustring lpe_key);
~PathManipulator();
virtual bool event(GdkEvent *);
void showHandles(bool show);
void showPathDirection(bool show);
void setControlsTransform(Geom::Matrix const &);
+ void hideDragPoint();
NodeList::iterator subdivideSegment(NodeList::iterator after, double t);
std::string _createTypeString();
void _updateOutline();
//void _setOutline(Geom::PathVector const &);
+ void _getGeometry();
+ void _setGeometry();
+ Glib::ustring _nodetypesKey();
+ Inkscape::XML::Node *_getXMLNode();
void _attachNodeHandlers(Node *n);
void _removeNodeHandlers(Node *n);
bool _show_handles;
bool _show_outline;
bool _show_path_direction;
+ Glib::ustring _lpe_key;
friend class PathManipulatorObserver;
friend class CurveDragPoint;
index cc2f8be4073c6c48e64dbee4b1a23f7ce798f220..96c1551f6473b99476f4f9ae78750a58beef67b6 100644 (file)
#ifndef SEEN_UI_TOOL_SHAPE_RECORD_H
#define SEEN_UI_TOOL_SHAPE_RECORD_H
+#include <glibmm/ustring.h>
#include <boost/operators.hpp>
#include <2geom/matrix.h>
SPItem *item; // SP node for the edited shape
Geom::Matrix edit_transform; // how to transform controls - used for clipping paths and masks
ShapeRole role;
- bool edit_original; // whether to use original-d instead of d for editing
+ Glib::ustring lpe_key; // This is LPE brain damage that I do not want to speak of
inline bool operator==(ShapeRecord const &o) const { return item == o.item; }
inline bool operator<(ShapeRecord const &o) const { return item < o.item; }