diff options
Diffstat (limited to 'src/live_effects/lpe-copy_rotate.cpp')
| -rw-r--r-- | src/live_effects/lpe-copy_rotate.cpp | 156 |
1 files changed, 104 insertions, 52 deletions
diff --git a/src/live_effects/lpe-copy_rotate.cpp b/src/live_effects/lpe-copy_rotate.cpp index 5b94e9083..1133e083a 100644 --- a/src/live_effects/lpe-copy_rotate.cpp +++ b/src/live_effects/lpe-copy_rotate.cpp @@ -11,17 +11,36 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <gtkmm.h> #include <gdk/gdk.h> #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 <glibmm/i18n.h> 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) { @@ -40,7 +59,6 @@ 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), @@ -56,7 +74,6 @@ 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); @@ -70,41 +87,6 @@ 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<Parameter *>::iterator it = param_vector.begin(); - while (it != param_vector.end()) { - if ((*it)->widget_is_visible) { - Parameter *param = *it; - Gtk::Widget *widg = dynamic_cast<Gtk::Widget *>(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<Gtk::Widget *>(vbox); -} - - void LPECopyRotate::doOnApply(SPLPEItem const* lpeitem) { @@ -122,6 +104,11 @@ 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<Parameter *>::iterator it = param_vector.begin(); it != param_vector.end(); ++it) { @@ -159,25 +146,11 @@ 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<SPLPEItem*>(lpeitem); item->apply_to_clippath(item); item->apply_to_mask(item); @@ -445,6 +418,85 @@ 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<LPECopyRotate *>(_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<LPECopyRotate *>(_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<LPECopyRotate const*>(_effect); + return lpe->start_pos; +} + +Geom::Point +KnotHolderEntityRotationAngle::knot_get() const +{ + LPECopyRotate const *lpe = dynamic_cast<LPECopyRotate const*>(_effect); + return lpe->rot_pos; +} + +} // namespace CR + +/* ######################## */ + } //namespace LivePathEffect } /* namespace Inkscape */ |
