From 77a4a003111bd5cfb771d4849801c898aeb889b0 Mon Sep 17 00:00:00 2001 From: cilix42 Date: Thu, 12 Jun 2008 13:23:17 +0000 Subject: [PATCH] Infrastructure in class LivePathEffect::Effect to put Inkscape into 'wait for parameter path' mode; make LPEMirrorReflect use this to let the user specify the mirroring line --- src/live_effects/effect.cpp | 47 ++++++++++++++++++++++++- src/live_effects/effect.h | 9 ++++- src/live_effects/lpe-mirror_reflect.cpp | 22 ++++++------ src/live_effects/lpe-mirror_reflect.h | 3 +- src/pen-context.cpp | 6 ++-- src/pen-context.h | 7 ++++ src/sp-lpe-item.cpp | 27 ++++++++++---- 7 files changed, 97 insertions(+), 24 deletions(-) diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 0aaedab0a..18d05fe67 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -19,6 +19,10 @@ #include "document-private.h" #include "xml/document.h" #include +#include "pen-context.h" +#include "tools-switch.h" +#include "message-stack.h" +#include "desktop.h" #include "live_effects/lpeobject.h" #include "live_effects/parameter/parameter.h" @@ -183,6 +187,7 @@ Effect::createAndApply(EffectType type, SPDocument *doc, SPItem *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), lpeobj(lpeobject), concatenate_before_pwd2(false) { @@ -207,18 +212,48 @@ Effect::effectType() { return lpeobj->effecttype; } +/** + * Is performed a single time when the effect is freshly applied to a path + */ void Effect::doOnApply (SPLPEItem */*lpeitem*/) { - // This is performed once when the effect is freshly applied to a path } +/** + * Is performed each time before the effect is updated. + */ void Effect::doBeforeEffect (SPLPEItem */*lpeitem*/) { //Do nothing for simple effects } +/** + * Effects 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 set the number of expected mouse clicks. + */ +void +Effect::doAcceptPathPreparations(SPLPEItem *lpeitem) +{ + // 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); + } + + 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; + + 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())); +} void Effect::writeParamsToSVG() { @@ -228,6 +263,16 @@ Effect::writeParamsToSVG() { } } +/** + * 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; +} + /* * Here be the doEffect function chain: */ diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h index 665509fd1..f1241c54b 100644 --- a/src/live_effects/effect.h +++ b/src/live_effects/effect.h @@ -95,10 +95,16 @@ public: EffectType effectType (); virtual void doOnApply (SPLPEItem *lpeitem); - virtual void doBeforeEffect (SPLPEItem *lpeitem); + void writeParamsToSVG(); + virtual void acceptParamPath (SPPath *param_path); + virtual int acceptsNumParams() { return 0; } + void doAcceptPathPreparations(SPLPEItem *lpeitem); + + inline bool pathParamAccepted() { return done_pathparam_set; } + virtual void doEffect (SPCurve * curve); virtual Gtk::Widget * newWidget(Gtk::Tooltips * tooltips); @@ -148,6 +154,7 @@ protected: std::vector > kh_entity_vector; int oncanvasedit_it; BoolParam is_visible; + bool done_pathparam_set; Inkscape::UI::Widget::Registry wr; diff --git a/src/live_effects/lpe-mirror_reflect.cpp b/src/live_effects/lpe-mirror_reflect.cpp index 438d012db..093841c8d 100644 --- a/src/live_effects/lpe-mirror_reflect.cpp +++ b/src/live_effects/lpe-mirror_reflect.cpp @@ -38,22 +38,20 @@ LPEMirrorReflect::~LPEMirrorReflect() } void -LPEMirrorReflect::doOnApply (SPLPEItem *lpeitem) -{ +LPEMirrorReflect::acceptParamPath (SPPath *param_path) { using namespace Geom; - SPCurve *curve = sp_path_get_curve_for_edit (SP_PATH(lpeitem)); - Point A(curve->first_point().to_2geom()); - Point B(curve->last_point().to_2geom()); - - Point M = (2*A + B)/3; // some point between A and B (a bit closer to A) - Point perp_dir = unit_vector((B - A).ccw()); + SPCurve* curve = sp_path_get_curve_for_edit (param_path); + Geom::Point A(curve->first_point().to_2geom()); + Geom::Point B(curve->last_point().to_2geom()); - Point C(M[X], M[Y] + 150); - Point D(M[X], M[Y] - 150); - - Piecewise > rline = Piecewise >(D2(Linear(C[X], D[X]), Linear(C[Y], D[Y]))); + Piecewise > rline = Piecewise >(D2(Linear(A[X], B[X]), Linear(A[Y], B[Y]))); reflection_line.param_set_and_write_new_value(rline); + + SP_OBJECT(param_path)->deleteObject(true); + + // don't remove this; needed for cleanup tasks + Effect::acceptParamPath(param_path); } std::vector diff --git a/src/live_effects/lpe-mirror_reflect.h b/src/live_effects/lpe-mirror_reflect.h index 79b1854f8..a19aafb89 100644 --- a/src/live_effects/lpe-mirror_reflect.h +++ b/src/live_effects/lpe-mirror_reflect.h @@ -28,7 +28,8 @@ public: LPEMirrorReflect(LivePathEffectObject *lpeobject); virtual ~LPEMirrorReflect(); - virtual void doOnApply (SPLPEItem *lpeitem); + virtual void acceptParamPath (SPPath *param_path); + virtual int acceptsNumParams() { return 2; } virtual LPEPathFlashType pathFlashType() { return PERMANENT_FLASH; } diff --git a/src/pen-context.cpp b/src/pen-context.cpp index dd9688f02..4616c04ae 100644 --- a/src/pen-context.cpp +++ b/src/pen-context.cpp @@ -181,7 +181,7 @@ sp_pen_context_dispose(GObject *object) pc->polylines_only = false; if (pc->expecting_clicks_for_LPE > 0) { // we received too few clicks to sanely set the parameter path so we remove the LPE from the item - //sp_lpe_item_remove_current_path_effect(SP_LPE_ITEM(pc->waiting_item), false); + sp_lpe_item_remove_current_path_effect(pc->waiting_item, false); } } @@ -785,8 +785,8 @@ pen_handle_button_release(SPPenContext *const pc, GdkEventButton const &revent) SPEventContext *ec = SP_EVENT_CONTEXT(pc); Inkscape::Selection *selection = sp_desktop_selection (ec->desktop); - //pc->waiting_LPE->acceptParamPath(SP_PATH(selection->singleItem())); - //selection->add(SP_OBJECT(pc->waiting_item)); + pc->waiting_LPE->acceptParamPath(SP_PATH(selection->singleItem())); + selection->add(SP_OBJECT(pc->waiting_item)); } } diff --git a/src/pen-context.h b/src/pen-context.h index 49e77e389..3e4e90924 100644 --- a/src/pen-context.h +++ b/src/pen-context.h @@ -7,6 +7,11 @@ #include "draw-context.h" +namespace Inkscape { +namespace LivePathEffect { +class Effect; +} +} #define SP_TYPE_PEN_CONTEXT (sp_pen_context_get_type()) #define SP_PEN_CONTEXT(o) (G_TYPE_CHECK_INSTANCE_CAST((o), SP_TYPE_PEN_CONTEXT, SPPenContext)) @@ -41,6 +46,8 @@ struct SPPenContext : public SPDrawContext { bool polylines_only; unsigned int expecting_clicks_for_LPE; // if positive, finish the path after this many clicks + Inkscape::LivePathEffect::Effect *waiting_LPE; + SPLPEItem *waiting_item; SPCanvasItem *c0, *c1, *cl0, *cl1; diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp index 3bf5a28ee..9013eb863 100644 --- a/src/sp-lpe-item.cpp +++ b/src/sp-lpe-item.cpp @@ -286,13 +286,20 @@ void sp_lpe_item_perform_path_effect(SPLPEItem *lpeitem, SPCurve *curve) { return; } - if (lpeobj->lpe->isVisible()) { + Inkscape::LivePathEffect::Effect *lpe = lpeobj->lpe; + if (lpe->isVisible()) { + if (lpe->acceptsNumParams() > 0 && !lpe->pathParamAccepted()) { + // if the effect expects mouse input before being applied and the input is not finished + // yet, we don't alter the path + return; + } + // Groups have their doBeforeEffect called elsewhere if (!SP_IS_GROUP(lpeitem)) { - lpeobj->lpe->doBeforeEffect(lpeitem); + lpe->doBeforeEffect(lpeitem); } - lpeobj->lpe->doEffect(curve); + lpe->doEffect(curve); } } } @@ -430,13 +437,21 @@ void sp_lpe_item_add_path_effect(SPLPEItem *lpeitem, gchar *value, bool reset) LivePathEffectObject *lpeobj = lpeitem->path_effect_list->back()->lpeobject; if (lpeobj && lpeobj->lpe) { + Inkscape::LivePathEffect::Effect *lpe = lpeobj->lpe; // Ask the path effect to reset itself if it doesn't have parameters yet if (reset) { // has to be called when all the subitems have their lpes applied - lpeobj->lpe->resetDefaults(lpeitem); + lpe->resetDefaults(lpeitem); + } + + // perform this once when the effect is applied + lpe->doOnApply(SP_LPE_ITEM(lpeitem)); + + // if the effect expects a number of mouse clicks to set a parameter path, perform the + // necessary preparations + if (lpe->acceptsNumParams() > 0) { + lpe->doAcceptPathPreparations(lpeitem); } - /* perform this once when the effect is applied */ - lpeobj->lpe->doOnApply(SP_LPE_ITEM(lpeitem)); } //Enable the path effects now that everything is ready to apply the new path effect -- 2.30.2