From 5c9722f0f1e8133300a9146439b1de4b60274488 Mon Sep 17 00:00:00 2001 From: Jabiertxof Date: Thu, 8 Dec 2016 23:21:24 +0100 Subject: 'upport' changes to LPE's rotate copies and mirrot symmetry (bzr r15313) --- src/live_effects/lpe-copy_rotate.cpp | 155 ++++++++++--------------------- src/live_effects/lpe-copy_rotate.h | 16 +--- src/live_effects/lpe-mirror_symmetry.cpp | 144 ++++++++++++---------------- src/live_effects/lpe-mirror_symmetry.h | 11 +-- 4 files changed, 117 insertions(+), 209 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-copy_rotate.cpp b/src/live_effects/lpe-copy_rotate.cpp index 1133e083a..a21d67078 100644 --- a/src/live_effects/lpe-copy_rotate.cpp +++ b/src/live_effects/lpe-copy_rotate.cpp @@ -15,32 +15,12 @@ #include <2geom/path-intersection.h> #include <2geom/sbasis-to-bezier.h> #include "live_effects/lpe-copy_rotate.h" - -#include "knotholder.h" // TODO due to internal breakage in glibmm headers, this must be last: #include namespace Inkscape { namespace LivePathEffect { -namespace CR { - -class KnotHolderEntityStartingAngle : public LPEKnotHolderEntity { -public: - KnotHolderEntityStartingAngle(LPECopyRotate *effect) : LPEKnotHolderEntity(effect) {}; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual Geom::Point knot_get() const; -}; - -class KnotHolderEntityRotationAngle : public LPEKnotHolderEntity { -public: - KnotHolderEntityRotationAngle(LPECopyRotate *effect) : LPEKnotHolderEntity(effect) {}; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual Geom::Point knot_get() const; -}; - -} // namespace CR - bool pointInTriangle(Geom::Point const &p, Geom::Point const &p1, Geom::Point const &p2, Geom::Point const &p3) { @@ -59,6 +39,7 @@ pointInTriangle(Geom::Point const &p, Geom::Point const &p1, Geom::Point const & LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) : Effect(lpeobject), origin(_("Origin"), _("Origin of the rotation"), "origin", &wr, this), + starting_point("hidden", "hidden", "starting_point", &wr, this), starting_angle(_("Starting:"), _("Angle of the first copy"), "starting_angle", &wr, this, 0.0), rotation_angle(_("Rotation angle:"), _("Angle between two successive copies"), "rotation_angle", &wr, this, 60.0), num_copies(_("Number of copies:"), _("Number of copies of the original path"), "num_copies", &wr, this, 6), @@ -74,6 +55,7 @@ LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) : registerParameter(&copies_to_360); registerParameter(&fuse_paths); registerParameter(&starting_angle); + registerParameter(&starting_point); registerParameter(&rotation_angle); registerParameter(&num_copies); registerParameter(&origin); @@ -87,6 +69,41 @@ LPECopyRotate::~LPECopyRotate() } +Gtk::Widget * LPECopyRotate::newWidget() +{ + // 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(Effect::newWidget())); + + vbox->set_border_width(5); + vbox->set_homogeneous(false); + vbox->set_spacing(2); + + std::vector::iterator it = param_vector.begin(); + while (it != param_vector.end()) { + if ((*it)->widget_is_visible) { + Parameter *param = *it; + Gtk::Widget *widg = dynamic_cast(param->param_newWidget()); + Glib::ustring *tip = param->param_getTooltip(); + if (widg) { + if (param->param_key != "starting_point") { + vbox->pack_start(*widg, true, true, 2); + if (tip) { + widg->set_tooltip_text(*tip); + } else { + widg->set_tooltip_text(""); + widg->set_has_tooltip(false); + } + } + } + } + + ++it; + } + return dynamic_cast(vbox); +} + + void LPECopyRotate::doOnApply(SPLPEItem const* lpeitem) { @@ -104,11 +121,6 @@ LPECopyRotate::doOnApply(SPLPEItem const* lpeitem) void LPECopyRotate::transform_multiply(Geom::Affine const& postmul, bool set) { - if(fuse_paths) { - Geom::Coord angle = Geom::deg_from_rad(atan(-postmul[1]/postmul[0])); - angle += starting_angle; - starting_angle.param_set_value(angle); - } // cycle through all parameters. Most parameters will not need transformation, but path and point params do. for (std::vector::iterator it = param_vector.begin(); it != param_vector.end(); ++it) { @@ -146,11 +158,25 @@ LPECopyRotate::doBeforeEffect (SPLPEItem const* lpeitem) dir = unit_vector(B - A); // I first suspected the minus sign to be a bug in 2geom but it is // likely due to SVG's choice of coordinate system orientation (max) + bool near = Geom::are_near(previous_start_point, (Geom::Point)starting_point, 0.01); + if (!near) { + starting_angle.param_set_value(deg_from_rad(-angle_between(dir, starting_point - origin))); + if (GDK_SHIFT_MASK) { + dist_angle_handle = L2(B - A); + } else { + dist_angle_handle = L2(starting_point - origin); + } + } start_pos = origin + dir * Rotate(-rad_from_deg(starting_angle)) * dist_angle_handle; rot_pos = origin + dir * Rotate(-rad_from_deg(rotation_angle+starting_angle)) * dist_angle_handle; + if (near) { + starting_point.param_setValue(start_pos); + } + previous_start_point = (Geom::Point)starting_point; if ( fuse_paths || copies_to_360 ) { rot_pos = origin; } + SPLPEItem * item = const_cast(lpeitem); item->apply_to_clippath(item); item->apply_to_mask(item); @@ -418,85 +444,6 @@ LPECopyRotate::resetDefaults(SPItem const* item) original_bbox(SP_LPE_ITEM(item)); } -void -LPECopyRotate::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) -{ - { - KnotHolderEntity *e = new CR::KnotHolderEntityStartingAngle(this); - e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, - _("Adjust the starting angle")); - knotholder->add(e); - } - { - KnotHolderEntity *e = new CR::KnotHolderEntityRotationAngle(this); - e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, - _("Adjust the rotation angle")); - knotholder->add(e); - } -}; - -namespace CR { - -using namespace Geom; - -void -KnotHolderEntityStartingAngle::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) -{ - LPECopyRotate* lpe = dynamic_cast(_effect); - - Geom::Point const s = snap_knot_position(p, state); - - // I first suspected the minus sign to be a bug in 2geom but it is - // likely due to SVG's choice of coordinate system orientation (max) - lpe->starting_angle.param_set_value(deg_from_rad(-angle_between(lpe->dir, s - lpe->origin))); - if (state & GDK_SHIFT_MASK) { - lpe->dist_angle_handle = L2(lpe->B - lpe->A); - } else { - lpe->dist_angle_handle = L2(p - lpe->origin); - } - - // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. - sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); -} - -void -KnotHolderEntityRotationAngle::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) -{ - LPECopyRotate* lpe = dynamic_cast(_effect); - - Geom::Point const s = snap_knot_position(p, state); - - // I first suspected the minus sign to be a bug in 2geom but it is - // likely due to SVG's choice of coordinate system orientation (max) - lpe->rotation_angle.param_set_value(deg_from_rad(-angle_between(lpe->dir, s - lpe->origin)) - lpe->starting_angle); - if (state & GDK_SHIFT_MASK) { - lpe->dist_angle_handle = L2(lpe->B - lpe->A); - } else { - lpe->dist_angle_handle = L2(p - lpe->origin); - } - - // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. - sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); -} - -Geom::Point -KnotHolderEntityStartingAngle::knot_get() const -{ - LPECopyRotate const *lpe = dynamic_cast(_effect); - return lpe->start_pos; -} - -Geom::Point -KnotHolderEntityRotationAngle::knot_get() const -{ - LPECopyRotate const *lpe = dynamic_cast(_effect); - return lpe->rot_pos; -} - -} // namespace CR - -/* ######################## */ - } //namespace LivePathEffect } /* namespace Inkscape */ diff --git a/src/live_effects/lpe-copy_rotate.h b/src/live_effects/lpe-copy_rotate.h index 87af867df..f189ffa04 100644 --- a/src/live_effects/lpe-copy_rotate.h +++ b/src/live_effects/lpe-copy_rotate.h @@ -13,7 +13,7 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ - +#include #include "live_effects/effect.h" #include "live_effects/parameter/point.h" #include "live_effects/lpegroupbbox.h" @@ -21,12 +21,6 @@ namespace Inkscape { namespace LivePathEffect { -namespace CR { -// we need a separate namespace to avoid clashes with LPEPerpBisector -class KnotHolderEntityStartingAngle; -class KnotHolderEntityRotationAngle; -} - class LPECopyRotate : public Effect, GroupBBoxEffect { public: LPECopyRotate(LivePathEffectObject *lpeobject); @@ -38,16 +32,13 @@ public: virtual void split(Geom::PathVector &path_in, Geom::Path const ÷r); virtual void resetDefaults(SPItem const* item); virtual void transform_multiply(Geom::Affine const& postmul, bool set); - /* the knotholder entity classes must be declared friends */ - friend class CR::KnotHolderEntityStartingAngle; - friend class CR::KnotHolderEntityRotationAngle; - void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item); - + virtual Gtk::Widget * newWidget(); protected: virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector &hp_vec); private: PointParam origin; + PointParam starting_point; ScalarParam starting_angle; ScalarParam rotation_angle; ScalarParam num_copies; @@ -58,6 +49,7 @@ private: Geom::Point dir; Geom::Point start_pos; Geom::Point rot_pos; + Geom::Point previous_start_point; double dist_angle_handle; LPECopyRotate(const LPECopyRotate&); LPECopyRotate& operator=(const LPECopyRotate&); diff --git a/src/live_effects/lpe-mirror_symmetry.cpp b/src/live_effects/lpe-mirror_symmetry.cpp index 4deb29d8f..c5c9b7260 100644 --- a/src/live_effects/lpe-mirror_symmetry.cpp +++ b/src/live_effects/lpe-mirror_symmetry.cpp @@ -18,8 +18,8 @@ #include #include "helper/geom.h" #include <2geom/path-intersection.h> -#include "knotholder.h" // TODO due to internal breakage in glibmm headers, this must be last: +#include namespace Inkscape { namespace LivePathEffect { @@ -34,39 +34,16 @@ static const Util::EnumData ModeTypeData[MT_END] = { static const Util::EnumDataConverter MTConverter(ModeTypeData, MT_END); -namespace MS { - -class KnotHolderEntityCenterMirrorSymmetry : public LPEKnotHolderEntity { -public: - KnotHolderEntityCenterMirrorSymmetry(LPEMirrorSymmetry *effect) : LPEKnotHolderEntity(effect){}; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual Geom::Point knot_get() const; -}; - -class KnotHolderEntityStartMirrorSymmetry : public LPEKnotHolderEntity { -public: - KnotHolderEntityStartMirrorSymmetry(LPEMirrorSymmetry *effect) : LPEKnotHolderEntity(effect){}; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual Geom::Point knot_get() const; -}; - -class KnotHolderEntityEndMirrorSymmetry : public LPEKnotHolderEntity { -public: - KnotHolderEntityEndMirrorSymmetry(LPEMirrorSymmetry *effect) : LPEKnotHolderEntity(effect){}; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual Geom::Point knot_get() const; -}; - -} // namespace MS - LPEMirrorSymmetry::LPEMirrorSymmetry(LivePathEffectObject *lpeobject) : Effect(lpeobject), mode(_("Mode"), _("Symmetry move mode"), "mode", MTConverter, &wr, this, MT_FREE), discard_orig_path(_("Discard original path?"), _("Check this to only keep the mirrored part of the path"), "discard_orig_path", &wr, this, false), fuse_paths(_("Fuse paths"), _("Fuse original and the reflection into a single path"), "fuse_paths", &wr, this, false), oposite_fuse(_("Opposite fuse"), _("Picks the other side of the mirror as the original"), "oposite_fuse", &wr, this, false), + //TODO: Fix htip for multilang start_point(_("Start mirror line"), _("Start mirror line"), "start_point", &wr, this, "Adjust the start of mirroring"), - end_point(_("End mirror line"), _("End mirror line"), "end_point", &wr, this, "Adjust end of mirroring") + end_point(_("End mirror line"), _("End mirror line"), "end_point", &wr, this, "Adjust end of mirroring"), + center_point("hidden","hidden", "center_point", &wr, this, "hidden") { show_orig_path = true; registerParameter(&mode); @@ -75,15 +52,51 @@ LPEMirrorSymmetry::LPEMirrorSymmetry(LivePathEffectObject *lpeobject) : registerParameter( &oposite_fuse); registerParameter( &start_point); registerParameter( &end_point); + registerParameter( ¢er_point); apply_to_clippath_and_mask = true; + previous_center = Geom::Point(0,0); } LPEMirrorSymmetry::~LPEMirrorSymmetry() { } -void +Gtk::Widget * LPEMirrorSymmetry::newWidget() +{ + // 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(Effect::newWidget())); + + vbox->set_border_width(5); + vbox->set_homogeneous(false); + vbox->set_spacing(2); + + std::vector::iterator it = param_vector.begin(); + while (it != param_vector.end()) { + if ((*it)->widget_is_visible) { + Parameter *param = *it; + Gtk::Widget *widg = dynamic_cast(param->param_newWidget()); + Glib::ustring *tip = param->param_getTooltip(); + if (widg) { + if (param->param_key != "center_point") { + vbox->pack_start(*widg, true, true, 2); + if (tip) { + widg->set_tooltip_text(*tip); + } else { + widg->set_tooltip_text(""); + widg->set_has_tooltip(false); + } + } + } + } + + ++it; + } + return dynamic_cast(vbox); +} + +void LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem) { using namespace Geom; @@ -99,19 +112,21 @@ LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem) point_a = Geom::Point(center_point[X],boundingbox_Y.min()); point_b = Geom::Point(center_point[X],boundingbox_Y.max()); } - line_separation.setPoints(point_a, point_b); - if ( mode == MT_X || mode == MT_Y ) { + if (Geom::are_near((Geom::Point)start_point, (Geom::Point)end_point, 0.01)) { start_point.param_setValue(point_a); end_point.param_setValue(point_b); - center_point = Geom::middle_point(point_a, point_b); + } + line_separation.setPoints(point_a, point_b); + if ( mode == MT_X || mode == MT_Y ) { + start_point.param_setValue(point_a, true); + end_point.param_setValue(point_b, true); } else if ( mode == MT_FREE) { if(!are_near(previous_center,center_point, 0.01)) { Geom::Point trans = center_point - previous_center; - start_point.param_setValue(start_point * trans); - end_point.param_setValue(end_point * trans); + start_point.param_setValue(start_point * trans, true); + end_point.param_setValue(end_point * trans, true); line_separation.setPoints(start_point, end_point); } else { - center_point = Geom::middle_point((Geom::Point)start_point, (Geom::Point)end_point); line_separation.setPoints(start_point, end_point); } } else if ( mode == MT_V){ @@ -120,11 +135,10 @@ LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem) Geom::Rect view_box_rect = doc->getViewBox(); Geom::Point sp = Geom::Point(view_box_rect.width()/2.0, 0); sp *= i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(SP_ACTIVE_DESKTOP->currentLayer()->parent)) .inverse(); - start_point.param_setValue(sp); + start_point.param_setValue(sp, true); Geom::Point ep = Geom::Point(view_box_rect.width()/2.0, view_box_rect.height()); ep *= i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(SP_ACTIVE_DESKTOP->currentLayer()->parent)) .inverse(); - end_point.param_setValue(ep); - center_point = Geom::middle_point((Geom::Point)start_point, (Geom::Point)end_point); + end_point.param_setValue(ep, true); line_separation.setPoints(start_point, end_point); } } else { //horizontal page @@ -133,22 +147,22 @@ LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem) Geom::Rect view_box_rect = doc->getViewBox(); Geom::Point sp = Geom::Point(0, view_box_rect.height()/2.0); sp *= i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(SP_ACTIVE_DESKTOP->currentLayer()->parent)) .inverse(); - start_point.param_setValue(sp); + start_point.param_setValue(sp, true); Geom::Point ep = Geom::Point(view_box_rect.width(), view_box_rect.height()/2.0); ep *= i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(SP_ACTIVE_DESKTOP->currentLayer()->parent)) .inverse(); - end_point.param_setValue(ep); - center_point = Geom::middle_point((Geom::Point)start_point, (Geom::Point)end_point); + end_point.param_setValue(ep, true); line_separation.setPoints(start_point, end_point); } } - previous_center = center_point; + previous_center = Geom::middle_point((Geom::Point)start_point, (Geom::Point)end_point); + if (!are_near(previous_center, center_point,0.01)) { + center_point.param_setValue(previous_center); + } } void LPEMirrorSymmetry::transform_multiply(Geom::Affine const& postmul, bool set) { - center_point *= postmul; - previous_center = center_point; // cycle through all parameters. Most parameters will not need transformation, but path and point params do. for (std::vector::iterator it = param_vector.begin(); it != param_vector.end(); ++it) { Parameter * param = *it; @@ -166,11 +180,11 @@ LPEMirrorSymmetry::doOnApply (SPLPEItem const* lpeitem) Point point_a(boundingbox_X.max(), boundingbox_Y.min()); Point point_b(boundingbox_X.max(), boundingbox_Y.max()); Point point_c(boundingbox_X.max(), boundingbox_Y.middle()); - start_point.param_setValue(point_a); + start_point.param_setValue(point_a, true); start_point.param_update_default(point_a); - end_point.param_setValue(point_b); + end_point.param_setValue(point_b, true); end_point.param_update_default(point_b); - center_point = point_c; + center_point.param_setValue(point_c); previous_center = center_point; } @@ -330,44 +344,6 @@ LPEMirrorSymmetry::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector hp_vec.push_back(helper); } -void -LPEMirrorSymmetry::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) -{ - SPKnotShapeType knot_shape = SP_KNOT_SHAPE_CIRCLE; - SPKnotModeType knot_mode = SP_KNOT_MODE_XOR; - guint32 knot_color = 0x0000ff00; - { - KnotHolderEntity *c = new MS::KnotHolderEntityCenterMirrorSymmetry(this); - c->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, - _("Adjust the center"), knot_shape, knot_mode, knot_color ); - knotholder->add(c); - } -}; - -namespace MS { - -using namespace Geom; - -void -KnotHolderEntityCenterMirrorSymmetry::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state) -{ - LPEMirrorSymmetry* lpe = dynamic_cast(_effect); - Geom::Point const s = snap_knot_position(p, state); - lpe->center_point = s; - - // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. - sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); -} - -Geom::Point -KnotHolderEntityCenterMirrorSymmetry::knot_get() const -{ - LPEMirrorSymmetry const *lpe = dynamic_cast(_effect); - return lpe->center_point; -} - -} // namespace CR - } //namespace LivePathEffect } /* namespace Inkscape */ diff --git a/src/live_effects/lpe-mirror_symmetry.h b/src/live_effects/lpe-mirror_symmetry.h index 7ec4029e0..cabd00546 100644 --- a/src/live_effects/lpe-mirror_symmetry.h +++ b/src/live_effects/lpe-mirror_symmetry.h @@ -26,11 +26,6 @@ namespace Inkscape { namespace LivePathEffect { -namespace MS { -// we need a separate namespace to avoid clashes with LPEPerpBisector -class KnotHolderEntityCenterMirrorSymmetry; -} - enum ModeType { MT_V, MT_H, @@ -48,9 +43,7 @@ public: virtual void doBeforeEffect (SPLPEItem const* lpeitem); virtual void transform_multiply(Geom::Affine const& postmul, bool set); virtual Geom::PathVector doEffect_path (Geom::PathVector const & path_in); - /* the knotholder entity classes must be declared friends */ - friend class MS::KnotHolderEntityCenterMirrorSymmetry; - void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item); + virtual Gtk::Widget * newWidget(); protected: virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector &hp_vec); @@ -62,9 +55,9 @@ private: BoolParam oposite_fuse; PointParam start_point; PointParam end_point; + PointParam center_point; Geom::Line line_separation; Geom::Point previous_center; - Geom::Point center_point; LPEMirrorSymmetry(const LPEMirrorSymmetry&); LPEMirrorSymmetry& operator=(const LPEMirrorSymmetry&); -- cgit v1.2.3