index 4ccfa59524720c04365036bf6ca89a44e4f55726..66d2334e018684ad2ed8b74748c9ab8853dfb012 100644 (file)
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include "live_effects/effect.h"
+
#include "display/display-forward.h"
#include "xml/node-event-vector.h"
#include "sp-object.h"
#include "desktop.h"
#include "inkscape.h"
#include "document.h"
+#include "document-private.h"
+#include "xml/document.h"
#include <glibmm/i18n.h>
+#include "pen-context.h"
+#include "tools-switch.h"
+#include "message-stack.h"
+#include "desktop.h"
+#include "nodepath.h"
-#include "live_effects/effect.h"
#include "live_effects/lpeobject.h"
#include "live_effects/parameter/parameter.h"
#include <glibmm/ustring.h>
-#include "live_effects/n-art-bpath-2geom.h"
+#include "libnr/n-art-bpath-2geom.h"
#include "display/curve.h"
-#include <2geom/sbasis-to-bezier.h>
#include <gtkmm.h>
#include <exception>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/matrix.h>
+
+
// include effects:
-#include "live_effects/lpe-skeletalstrokes.h"
-#include "live_effects/lpe-pathalongpath.h"
-#include "live_effects/lpe-slant.h"
+#include "live_effects/lpe-patternalongpath.h"
+#include "live_effects/lpe-bendpath.h"
+#include "live_effects/lpe-sketch.h"
+#include "live_effects/lpe-vonkoch.h"
+#include "live_effects/lpe-knot.h"
#include "live_effects/lpe-test-doEffect-stack.h"
#include "live_effects/lpe-gears.h"
#include "live_effects/lpe-curvestitch.h"
-
-#include "nodepath.h"
+#include "live_effects/lpe-circle_with_radius.h"
+#include "live_effects/lpe-perspective_path.h"
+#include "live_effects/lpe-spiro.h"
+#include "live_effects/lpe-lattice.h"
+#include "live_effects/lpe-envelope.h"
+#include "live_effects/lpe-constructgrid.h"
+#include "live_effects/lpe-perp_bisector.h"
+#include "live_effects/lpe-tangent_to_curve.h"
+#include "live_effects/lpe-mirror_symmetry.h"
+#include "live_effects/lpe-circle_3pts.h"
+#include "live_effects/lpe-angle_bisector.h"
+#include "live_effects/lpe-parallel.h"
+#include "live_effects/lpe-copy_rotate.h"
+#include "live_effects/lpe-offset.h"
+// end of includes
namespace Inkscape {
const Util::EnumData<EffectType> LPETypeData[INVALID_LPE] = {
// {constant defined in effect.h, N_("name of your effect"), "name of your effect in SVG"}
- {PATH_ALONG_PATH, N_("Path along path"), "path_along_path"},
- {SKELETAL_STROKES, N_("Pattern along path"), "skeletal"},
+ {BEND_PATH, N_("Bend"), "bend_path"},
+ {PATTERN_ALONG_PATH, N_("Pattern Along Path"), "skeletal"}, // for historic reasons, this effect is called skeletal(strokes) in Inkscape:SVG
+ {SKETCH, N_("Sketch"), "sketch"},
+ {VONKOCH, N_("VonKoch"), "vonkoch"},
+ {KNOT, N_("Knot"), "knot"},
#ifdef LPE_ENABLE_TEST_EFFECTS
- {SLANT, N_("Slant"), "slant"},
{DOEFFECTSTACK_TEST, N_("doEffect stack test"), "doeffectstacktest"},
#endif
{GEARS, N_("Gears"), "gears"},
- {CURVE_STITCH, N_("Stitch subcurves"), "curvestitching"},
+ {CURVE_STITCH, N_("Stitch Sub-Paths"), "curvestitching"},
+ {CIRCLE_WITH_RADIUS, N_("Circle (center+radius)"), "circle_with_radius"},
+ {PERSPECTIVE_PATH, N_("Perspective path"), "perspective_path"},
+ {SPIRO, N_("Spiro spline"), "spiro"},
+ {LATTICE, N_("Lattice Deformation"), "lattice"},
+ {ENVELOPE, N_("Envelope Deformation"), "envelope"},
+ {CONSTRUCT_GRID, N_("Construct grid"), "construct_grid"},
+ {PERP_BISECTOR, N_("Perpendicular bisector"), "perp_bisector"},
+ {TANGENT_TO_CURVE, N_("Tangent to curve"), "tangent_to_curve"},
+ {MIRROR_SYMMETRY, N_("Mirror symmetry"), "mirror_symmetry"},
+ {CIRCLE_3PTS, N_("Circle through 3 points"), "circle_3pts"},
+ {ANGLE_BISECTOR, N_("Angle bisector"), "angle_bisector"},
+ {PARALLEL, N_("Parallel"), "parallel"},
+ {COPY_ROTATE, N_("Rotate copies"), "copy_rotate"},
+ {OFFSET, N_("Offset"), "offset"},
};
const Util::EnumDataConverter<EffectType> LPETypeConverter(LPETypeData, INVALID_LPE);
{
Effect* neweffect = NULL;
switch (lpenr) {
- case SKELETAL_STROKES:
- neweffect = (Effect*) new LPESkeletalStrokes(lpeobj);
+ case PATTERN_ALONG_PATH:
+ neweffect = static_cast<Effect*> ( new LPEPatternAlongPath(lpeobj) );
break;
- case PATH_ALONG_PATH:
- neweffect = (Effect*) new LPEPathAlongPath(lpeobj);
+ case BEND_PATH:
+ neweffect = static_cast<Effect*> ( new LPEBendPath(lpeobj) );
break;
-#ifdef LPE_ENABLE_TEST_EFFECTS
- case SLANT:
- neweffect = (Effect*) new LPESlant(lpeobj);
+ case SKETCH:
+ neweffect = static_cast<Effect*> ( new LPESketch(lpeobj) );
break;
+ case VONKOCH:
+ neweffect = static_cast<Effect*> ( new LPEVonKoch(lpeobj) );
+ break;
+ case KNOT:
+ neweffect = static_cast<Effect*> ( new LPEKnot(lpeobj) );
+ break;
+#ifdef LPE_ENABLE_TEST_EFFECTS
case DOEFFECTSTACK_TEST:
- neweffect = (Effect*) new LPEdoEffectStackTest(lpeobj);
+ neweffect = static_cast<Effect*> ( new LPEdoEffectStackTest(lpeobj) );
break;
#endif
case GEARS:
- neweffect = (Effect*) new LPEGears(lpeobj);
+ neweffect = static_cast<Effect*> ( new LPEGears(lpeobj) );
break;
case CURVE_STITCH:
- neweffect = (Effect*) new LPECurveStitch(lpeobj);
+ neweffect = static_cast<Effect*> ( new LPECurveStitch(lpeobj) );
+ break;
+ case LATTICE:
+ neweffect = static_cast<Effect*> ( new LPELattice(lpeobj) );
+ break;
+ case ENVELOPE:
+ neweffect = static_cast<Effect*> ( new LPEEnvelope(lpeobj) );
+ break;
+ case CIRCLE_WITH_RADIUS:
+ neweffect = static_cast<Effect*> ( new LPECircleWithRadius(lpeobj) );
+ break;
+ case PERSPECTIVE_PATH:
+ neweffect = static_cast<Effect*> ( new LPEPerspectivePath(lpeobj) );
+ break;
+ case SPIRO:
+ neweffect = static_cast<Effect*> ( new LPESpiro(lpeobj) );
+ break;
+ case CONSTRUCT_GRID:
+ neweffect = static_cast<Effect*> ( new LPEConstructGrid(lpeobj) );
+ break;
+ case PERP_BISECTOR:
+ neweffect = static_cast<Effect*> ( new LPEPerpBisector(lpeobj) );
+ break;
+ case TANGENT_TO_CURVE:
+ neweffect = static_cast<Effect*> ( new LPETangentToCurve(lpeobj) );
+ break;
+ case MIRROR_SYMMETRY:
+ neweffect = static_cast<Effect*> ( new LPEMirrorSymmetry(lpeobj) );
+ break;
+ case CIRCLE_3PTS:
+ neweffect = static_cast<Effect*> ( new LPECircle3Pts(lpeobj) );
+ break;
+ case ANGLE_BISECTOR:
+ neweffect = static_cast<Effect*> ( new LPEAngleBisector(lpeobj) );
+ break;
+ case PARALLEL:
+ neweffect = static_cast<Effect*> ( new LPEParallel(lpeobj) );
+ break;
+ case COPY_ROTATE:
+ neweffect = static_cast<Effect*> ( new LPECopyRotate(lpeobj) );
+ break;
+ case OFFSET:
+ neweffect = static_cast<Effect*> ( new LPEOffset(lpeobj) );
break;
default:
g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr);
return neweffect;
}
+void
+Effect::createAndApply(const char* name, SPDocument *doc, SPItem *item)
+{
+ // Path effect definition
+ Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
+ Inkscape::XML::Node *repr = xml_doc->createElement("inkscape:path-effect");
+ repr->setAttribute("effect", name);
+
+ SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc))->addChild(repr, NULL); // adds to <defs> and assigns the 'id' attribute
+ const gchar * repr_id = repr->attribute("id");
+ Inkscape::GC::release(repr);
+
+ gchar *href = g_strdup_printf("#%s", repr_id);
+ sp_lpe_item_add_path_effect(SP_LPE_ITEM(item), href, true);
+ g_free(href);
+}
+
+void
+Effect::createAndApply(EffectType type, SPDocument *doc, SPItem *item)
+{
+ createAndApply(LPETypeConverter.get_key(type).c_str(), doc, item);
+}
+
Effect::Effect(LivePathEffectObject *lpeobject)
+ : oncanvasedit_it(0),
+ is_visible(_("Is visible?"), _("If unchecked, the effect remains applied to the object but is temporarily disabled on canvas"), "is_visible", &wr, this, true),
+ done_pathparam_set(false),
+ show_orig_path(false),
+ lpeobj(lpeobject),
+ concatenate_before_pwd2(false),
+ provides_own_flash_paths(true) // is automatically set to false if providesOwnFlashPaths() is not overridden
{
- vbox = NULL;
- tooltips = NULL;
- lpeobj = lpeobject;
- oncanvasedit_it = param_map.begin();
+ registerParameter( dynamic_cast<Parameter *>(&is_visible) );
}
Effect::~Effect()
{
- if (tooltips) {
- delete tooltips;
- }
}
-Glib::ustring
+Glib::ustring
Effect::getName()
{
if (lpeobj->effecttype_set && lpeobj->effecttype < INVALID_LPE)
return Glib::ustring( _("No effect") );
}
-/*
- * Here be the doEffect function chain:
+EffectType
+Effect::effectType() {
+ return lpeobj->effecttype;
+}
+
+/**
+ * Is performed a single time when the effect is freshly applied to a path
*/
void
-Effect::doEffect (SPCurve * curve)
+Effect::doOnApply (SPLPEItem */*lpeitem*/)
{
- NArtBpath *new_bpath = doEffect_nartbpath(SP_CURVE_BPATH(curve));
+}
- if (new_bpath && new_bpath != SP_CURVE_BPATH(curve)) { // FIXME, add function to SPCurve to change bpath? or a copy function?
- if (curve->_bpath) {
- g_free(curve->_bpath); //delete old bpath
- }
- curve->_bpath = new_bpath;
- }
+/**
+ * Is performed each time before the effect is updated.
+ */
+void
+Effect::doBeforeEffect (SPLPEItem */*lpeitem*/)
+{
+ //Do nothing for simple effects
}
-NArtBpath *
-Effect::doEffect_nartbpath (NArtBpath * path_in)
+/**
+ * Effects can have a parameter path set before they are applied by accepting a nonzero number of
+ * mouse clicks. This method activates the pen context, which waits for the specified number of
+ * clicks. Override Effect::acceptsNumParams() to return the number of expected mouse clicks.
+ */
+void
+Effect::doAcceptPathPreparations(SPLPEItem *lpeitem)
{
- try {
- std::vector<Geom::Path> orig_pathv = BPath_to_2GeomPath(path_in);
+ // switch to pen context
+ SPDesktop *desktop = inkscape_active_desktop(); // TODO: Is there a better method to find the item's desktop?
+ if (!tools_isactive(desktop, TOOLS_FREEHAND_PEN)) {
+ tools_switch(desktop, TOOLS_FREEHAND_PEN);
+ }
- std::vector<Geom::Path> result_pathv = doEffect_path(orig_pathv);
+ SPEventContext *ec = desktop->event_context;
+ SPPenContext *pc = SP_PEN_CONTEXT(ec);
+ pc->expecting_clicks_for_LPE = this->acceptsNumParams();
+ pc->waiting_LPE = this;
+ pc->waiting_item = lpeitem;
+ pc->polylines_only = true;
- NArtBpath *new_bpath = BPath_from_2GeomPath(result_pathv);
+ ec->desktop->messageStack()->flash(Inkscape::INFORMATION_MESSAGE,
+ g_strdup_printf(_("Please specify a parameter path for the LPE '%s' with %d mouse clicks"),
+ getName().c_str(), acceptsNumParams()));
+}
- return new_bpath;
+void
+Effect::writeParamsToSVG() {
+ std::vector<Inkscape::LivePathEffect::Parameter *>::iterator p;
+ for (p = param_vector.begin(); p != param_vector.end(); ++p) {
+ (*p)->write_to_SVG();
}
- catch (std::exception e) {
- g_warning("Exception during LPE %s execution. \n %s", getName().c_str(), e.what());
- SP_ACTIVE_DESKTOP->messageStack()->flash( Inkscape::WARNING_MESSAGE,
- _("An exception occurred during execution of the Path Effect.") );
+}
- NArtBpath *path_out;
+/**
+ * If the effect expects a path parameter (specified by a number of mouse clicks) before it is
+ * applied, this is the method that processes the resulting path. Override it to customize it for
+ * your LPE. But don't forget to call the parent method so that done_pathparam_set is set to true!
+ */
+void
+Effect::acceptParamPath (SPPath */*param_path*/) {
+ done_pathparam_set = true;
+}
- unsigned ret = 0;
- while ( path_in[ret].code != NR_END ) {
- ++ret;
- }
- unsigned len = ++ret;
+/*
+ * Here be the doEffect function chain:
+ */
+void
+Effect::doEffect (SPCurve * curve)
+{
+ std::vector<Geom::Path> orig_pathv = curve->get_pathvector();
- path_out = g_new(NArtBpath, len);
- memcpy(path_out, path_in, len * sizeof(NArtBpath));
- return path_out;
- }
+ std::vector<Geom::Path> result_pathv = doEffect_path(orig_pathv);
+
+ curve->set_pathvector(result_pathv);
}
std::vector<Geom::Path>
-Effect::doEffect_path (std::vector<Geom::Path> & path_in)
+Effect::doEffect_path (std::vector<Geom::Path> const & path_in)
{
- Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in;
-
- for (unsigned int i=0; i < path_in.size(); i++) {
- pwd2_in.concat( path_in[i].toPwSb() );
+ std::vector<Geom::Path> path_out;
+
+ if ( !concatenate_before_pwd2 ) {
+ // default behavior
+ for (unsigned int i=0; i < path_in.size(); i++) {
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in = path_in[i].toPwSb();
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_out = doEffect_pwd2(pwd2_in);
+ std::vector<Geom::Path> path = Geom::path_from_piecewise( pwd2_out, LPE_CONVERSION_TOLERANCE);
+ // add the output path vector to the already accumulated vector:
+ for (unsigned int j=0; j < path.size(); j++) {
+ path_out.push_back(path[j]);
+ }
+ }
+ } else {
+ // concatenate the path into possibly discontinuous pwd2
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in;
+ for (unsigned int i=0; i < path_in.size(); i++) {
+ pwd2_in.concat( path_in[i].toPwSb() );
+ }
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_out = doEffect_pwd2(pwd2_in);
+ path_out = Geom::path_from_piecewise( pwd2_out, LPE_CONVERSION_TOLERANCE);
}
- Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_out = doEffect_pwd2(pwd2_in);
-
- std::vector<Geom::Path> path_out = Geom::path_from_piecewise( pwd2_out, LPE_CONVERSION_TOLERANCE);
-
return path_out;
}
Geom::Piecewise<Geom::D2<Geom::SBasis> >
-Effect::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > & pwd2_in)
+Effect::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
{
g_warning("Effect has no doEffect implementation");
return pwd2_in;
void
Effect::readallParameters(Inkscape::XML::Node * repr)
{
- param_map_type::iterator it = param_map.begin();
- while (it != param_map.end()) {
- const gchar * key = (*it).first.c_str();
+ std::vector<Parameter *>::iterator it = param_vector.begin();
+ while (it != param_vector.end()) {
+ Parameter * param = *it;
+ const gchar * key = param->param_key.c_str();
const gchar * value = repr->attribute(key);
- if(value) {
- setParameter(key, value);
+ if (value) {
+ bool accepted = param->param_readSVGValue(value);
+ if (!accepted) {
+ g_warning("Effect::readallParameters - '%s' not accepted for %s", value, key);
+ }
+ } else {
+ // set default value
+ param->param_set_default();
}
+
it++;
}
}
void
Effect::setParameter(const gchar * key, const gchar * new_value)
{
- Glib::ustring stringkey(key);
-
- param_map_type::iterator it = param_map.find(stringkey);
- if (it != param_map.end()) {
+ Parameter * param = getParameter(key);
+ if (param) {
if (new_value) {
- bool accepted = it->second->param_readSVGValue(new_value);
- if (!accepted) {
+ bool accepted = param->param_readSVGValue(new_value);
+ if (!accepted) {
g_warning("Effect::setParameter - '%s' not accepted for %s", new_value, key);
}
} else {
// set default value
- it->second->param_set_default();
+ param->param_set_default();
}
}
}
void
Effect::registerParameter(Parameter * param)
{
- param_map[param->param_key] = param; // inserts or updates
+ param_vector.push_back(param);
+}
+
+// TODO: should we provide a way to alter the handle's appearance?
+void
+Effect::registerKnotHolderHandle(KnotHolderEntity* entity, const char* descr)
+{
+ kh_entity_vector.push_back(std::make_pair(entity, descr));
}
+/**
+ * Add all registered LPE knotholder handles to the knotholder
+ */
+void
+Effect::addHandles(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) {
+ std::vector<std::pair<KnotHolderEntity*, const char*> >::iterator i;
+ for (i = kh_entity_vector.begin(); i != kh_entity_vector.end(); ++i) {
+ KnotHolderEntity *entity = i->first;
+ const char *descr = i->second;
+
+ entity->create(desktop, item, knotholder, descr);
+ knotholder->add(entity);
+ }
+}
+
+void
+Effect::addPointParamHandles(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) {
+ using namespace Inkscape::LivePathEffect;
+ for (std::vector<Parameter *>::iterator p = param_vector.begin(); p != param_vector.end(); ++p) {
+ if ((*p)->paramType() == POINT_PARAM) {
+ PointParam *pparam = static_cast<PointParam *>(*p);
+ KnotHolderEntity *e = dynamic_cast<KnotHolderEntity *>(*p);
+ e->create(desktop, item, knotholder, pparam->handleTip(),
+ pparam->knotShape(), pparam->knotMode(), pparam->knotColor());
+ knotholder->add(e);
+ }
+ }
+}
+
+void
+Effect::addHelperPaths(SPLPEItem *lpeitem, SPDesktop *desktop)
+{
+ g_return_if_fail(desktop);
+ g_return_if_fail(SP_IS_PATH(lpeitem));
+
+ if (providesKnotholder() && showOrigPath()) {
+ // TODO: we assume that if the LPE provides its own knotholder, there is no nodepath so we
+ // must create the helper curve for the original path manually; once we allow nodepaths and
+ // knotholders alongside each other, this needs to be rethought!
+ SPCanvasItem *canvasitem = sp_nodepath_generate_helperpath(desktop, SP_PATH(lpeitem));
+ Inkscape::Display::TemporaryItem* tmpitem = desktop->add_temporary_canvasitem (canvasitem, 0);
+ lpeitem->lpe_helperpaths.push_back(tmpitem);
+ }
+
+ for (std::vector<Parameter *>::iterator p = param_vector.begin(); p != param_vector.end(); ++p) {
+ if ((*p)->paramType() == Inkscape::LivePathEffect::PATH_PARAM) {
+ SPCurve *c = new SPCurve(static_cast<Inkscape::LivePathEffect::PathParam*>(*p)->get_pathvector());
+
+ // TODO: factor this out (also the copied code above); see also lpe-lattice.cpp
+ SPCanvasItem *canvasitem = sp_nodepath_generate_helperpath(desktop, c, SP_ITEM(lpeitem), 0x009000ff);
+ Inkscape::Display::TemporaryItem* tmpitem = desktop->add_temporary_canvasitem (canvasitem, 0);
+ lpeitem->lpe_helperpaths.push_back(tmpitem);
+ }
+ }
+
+ addHelperPathsImpl(lpeitem, desktop);
+}
+
+void
+Effect::addHelperPathsImpl(SPLPEItem */*lpeitem*/, SPDesktop */*desktop*/)
+{
+ // if this method is overloaded in derived classes, provides_own_flash_paths will be true
+ provides_own_flash_paths = false;
+}
+
+/**
+ * This *creates* a new widget, management of deletion should be done by the caller
+ */
Gtk::Widget *
-Effect::getWidget()
+Effect::newWidget(Gtk::Tooltips * tooltips)
{
- if (!vbox) {
- vbox = Gtk::manage( new Gtk::VBox() ); // use manage here, because after deletion of Effect object, others might still be pointing to this widget.
- //if (!tooltips)
- tooltips = new Gtk::Tooltips();
-
- vbox->set_border_width(5);
-
- param_map_type::iterator it = param_map.begin();
- while (it != param_map.end()) {
- Parameter * param = it->second;
- Gtk::Widget * widg = param->param_getWidget();
- Glib::ustring * tip = param->param_getTooltip();
- if (widg) {
- vbox->pack_start(*widg, true, true, 2);
- if (tip != NULL) {
- tooltips->set_tip(*widg, *tip);
- }
+ // use manage here, because after deletion of Effect object, others might still be pointing to this widget.
+ Gtk::VBox * vbox = Gtk::manage( new Gtk::VBox() );
+
+ vbox->set_border_width(5);
+
+ std::vector<Parameter *>::iterator it = param_vector.begin();
+ while (it != param_vector.end()) {
+ Parameter * param = *it;
+ Gtk::Widget * widg = param->param_newWidget(tooltips);
+ Glib::ustring * tip = param->param_getTooltip();
+ if (widg) {
+ vbox->pack_start(*widg, true, true, 2);
+ if (tip != NULL) {
+ tooltips->set_tip(*widg, *tip);
}
-
- it++;
}
+
+ it++;
}
return dynamic_cast<Gtk::Widget *>(vbox);
{
Glib::ustring stringkey(key);
- param_map_type::iterator it = param_map.find(stringkey);
- if (it != param_map.end()) {
- return it->second;
- } else {
- return NULL;
+ std::vector<Parameter *>::iterator it = param_vector.begin();
+ while (it != param_vector.end()) {
+ Parameter * param = *it;
+ if ( param->param_key == key) {
+ return param;
+ }
+
+ it++;
}
+
+ return NULL;
}
Parameter *
Effect::getNextOncanvasEditableParam()
{
+ if (param_vector.size() == 0) // no parameters
+ return NULL;
+
oncanvasedit_it++;
- if (oncanvasedit_it == param_map.end()) {
- oncanvasedit_it = param_map.begin();
+ if (oncanvasedit_it >= static_cast<int>(param_vector.size())) {
+ oncanvasedit_it = 0;
}
- param_map_type::iterator old_it = oncanvasedit_it;
+ int old_it = oncanvasedit_it;
do {
- Parameter * param = oncanvasedit_it->second;
- if(param->oncanvas_editable) {
+ Parameter * param = param_vector[oncanvasedit_it];
+ if(param && param->oncanvas_editable) {
return param;
} else {
oncanvasedit_it++;
- if (oncanvasedit_it == param_map.end()) { // loop round the map
- oncanvasedit_it = param_map.begin();
+ if (oncanvasedit_it == static_cast<int>(param_vector.size())) { // loop round the map
+ oncanvasedit_it = 0;
}
}
} while (oncanvasedit_it != old_it); // iterate until complete loop through map has been made
}
void
-Effect::setup_notepath(Inkscape::NodePath::Path *np)
+Effect::setup_nodepath(Inkscape::NodePath::Path *np)
{
- np->show_helperpath = true;
np->helperpath_rgba = 0xff0000ff;
np->helperpath_width = 1.0;
}
+void
+Effect::transform_multiply(Geom::Matrix const& postmul, bool set)
+{
+ // cycle through all parameters. Most parameters will not need transformation, but path and point params do.
+ for (std::vector<Parameter *>::iterator it = param_vector.begin(); it != param_vector.end(); it++) {
+ Parameter * param = *it;
+ param->param_transform_multiply(postmul, set);
+ }
+}
+
+bool
+Effect::providesKnotholder()
+{
+ // does the effect actively provide any knotholder entities of its own?
+ if (kh_entity_vector.size() > 0)
+ return true;
+
+ // otherwise: are there any PointParams?
+ for (std::vector<Parameter *>::iterator p = param_vector.begin(); p != param_vector.end(); ++p) {
+ if ((*p)->paramType() == Inkscape::LivePathEffect::POINT_PARAM) {
+ return true;
+ }
+ }
+
+ return false;
+}
} /* namespace LivePathEffect */