/* === S Y N F I G ========================================================= */ /*! \file duck.cpp ** \brief Template File ** ** $Id$ ** ** \legal ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley ** Copyright (c) 2007, 2008 Chris Moore ** Copyright (c) 2009 Nikita Kitaev ** Copyright (c) 2011 Carlos López ** ** This package is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License as ** published by the Free Software Foundation; either version 2 of ** the License, or (at your option) any later version. ** ** This package is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** General Public License for more details. ** \endlegal */ /* ========================================================================= */ /* === H E A D E R S ======================================================= */ #ifdef USING_PCH # include "pch.h" #else #ifdef HAVE_CONFIG_H # include #endif #include "duck.h" #include #include #include #include #include #include #include #include "general.h" #endif /* === U S I N G =========================================================== */ using namespace std; using namespace etl; using namespace synfig; using namespace studio; /* === M A C R O S ========================================================= */ /* === G L O B A L S ======================================================= */ int studio::Duck::duck_count(0); struct _DuckCounter { static int counter; ~_DuckCounter() { if(counter) synfig::error("%d ducks not yet deleted!",counter); } } _duck_counter; int _DuckCounter::counter(0); /* === P R O C E D U R E S ================================================= */ /* === M E T H O D S ======================================================= */ Duck::Duck(): guid_(0), type_(TYPE_NONE), editable_(false), alternative_editable_(false), edit_immediatelly_(false), radius_(false), tangent_(false), hover_(false), ignore_(false), exponential_(false), track_axes_(false), lock_aspect_(false), scalar_(1), origin_(0,0), axis_x_angle_(Angle::deg(0)), axis_x_mag_(1), axis_y_angle_(Angle::deg(90)), axis_y_mag_(1), rotations_(synfig::Angle::deg(0)), aspect_point_(1,1) { duck_count++; _DuckCounter::counter++; } Duck::Duck(const synfig::Point &point): guid_(0), type_(TYPE_POSITION), editable_(false), alternative_editable_(false), edit_immediatelly_(false), radius_(false), tangent_(false), hover_(false), ignore_(false), exponential_(false), track_axes_(false), lock_aspect_(false), scalar_(1), origin_(0,0), axis_x_angle_(Angle::deg(0)), axis_x_mag_(1), axis_y_angle_(Angle::deg(90)), axis_y_mag_(1), point_(point), rotations_(synfig::Angle::deg(0)), aspect_point_(1,1) { duck_count++; _DuckCounter::counter++;} Duck::Duck(const synfig::Point &point,const synfig::Point &origin): guid_(0), type_(TYPE_NONE), editable_(false), alternative_editable_(false), edit_immediatelly_(false), radius_(true), tangent_(false), hover_(false), ignore_(false), exponential_(false), track_axes_(false), lock_aspect_(false), scalar_(1), origin_(origin), axis_x_angle_(Angle::deg(0)), axis_x_mag_(1), axis_y_angle_(Angle::deg(90)), axis_y_mag_(1), point_(point), rotations_(synfig::Angle::deg(0)), aspect_point_(1,1) { duck_count++; _DuckCounter::counter++;} Duck::~Duck() { duck_count--; _DuckCounter::counter--;} synfig::GUID Duck::get_data_guid()const { synfig::GUID type_guid = synfig::GUID::hasher(get_type()); if(value_desc_.is_value_node()) return type_guid ^ value_desc_.get_value_node()->get_guid(); return type_guid ^ synfig::GUID::hasher(get_name()); } void Duck::set_name(const synfig::String &x) { name=x; if(guid_==synfig::GUID::zero()) { guid_=synfig::GUID::hasher(name); } } bool Duck::operator==(const Duck &rhs)const { if(this==&rhs) return true; return name==rhs.name && scalar_==rhs.scalar_ && type_==rhs.type_ && transform_stack_.size()==rhs.transform_stack_.size(); //true; //(origin_duck?*origin_duck==*rhs.origin_duck:origin==rhs.origin) && //(shared_point?*shared_point==*rhs.shared_point:point==rhs.point) ; } //! Sets the location of the duck with respect to the origin void Duck::set_point(const synfig::Point &x) { if (is_aspect_locked()) point_ = aspect_point_ * (x * aspect_point_); else point_ = x; if (shared_point_) *shared_point_ = point_; if (shared_angle_) *shared_angle_ = point_.angle(); if (shared_mag_) *shared_mag_ = point_.mag(); } //! Returns the location of the duck synfig::Point Duck::get_point()const { synfig::Point p; if (!shared_point_ && !shared_angle_ && !shared_mag_) p = point_; else if (shared_point_) p = *shared_point_; else p = synfig::Point( shared_mag_ ? *shared_mag_ : point_.mag(), shared_angle_ ? *shared_angle_ : point_.angle() ); if (is_aspect_locked()) p = aspect_point_ * (p * aspect_point_); return p; } synfig::Point Duck::get_trans_point()const { return transform_stack_.perform(get_sub_trans_point()); } void Duck::set_trans_point(const synfig::Point &x) { set_sub_trans_point(transform_stack_.unperform(x)); } void Duck::set_trans_point(const synfig::Point &x, const synfig::Time &time) { set_sub_trans_point(transform_stack_.unperform(x), time); } //! Retrieves the origin location synfig::Point Duck::get_trans_origin()const { return transform_stack_.perform(get_sub_trans_origin()); } synfig::Point Duck::get_sub_trans_point_without_offset(const synfig::Point &x)const { Point p(x*get_scalar()); return get_axis_x()*p[0] + get_axis_y()*p[1]; } synfig::Point Duck::get_sub_trans_point(const synfig::Point &x)const { Point p(x*get_scalar()); return get_axis_x()*p[0] + get_axis_y()*p[1] + get_sub_trans_origin(); } synfig::Point Duck::get_sub_trans_point()const { return get_sub_trans_point(get_point()); } synfig::Point Duck::get_sub_trans_point_without_offset()const { return get_sub_trans_point_without_offset(get_point()); } void Duck::set_sub_trans_point(const synfig::Point &x) { Matrix m(get_axis_x(), get_axis_y(), get_sub_trans_origin()); m.invert(); Angle old_angle = get_point().angle(); set_point(m.get_transformed(x)/get_scalar()); Angle change = get_point().angle() - old_angle; while (change < Angle::deg(-180)) change += Angle::deg(360); while (change > Angle::deg(180)) change -= Angle::deg(360); rotations_ += change; } void Duck::set_sub_trans_point(const synfig::Point &x, const synfig::Time &time) { set_sub_trans_point(x); if(get_type() == Duck::TYPE_VERTEX || get_type() == Duck::TYPE_POSITION || get_type() == Duck::TYPE_WIDTHPOINT_POSITION) { ValueNode_BLineCalcVertex::Handle bline_vertex; ValueNode_Composite::Handle composite; if ((bline_vertex = ValueNode_BLineCalcVertex::Handle::cast_dynamic(get_value_desc().get_value_node())) || ((composite = ValueNode_Composite::Handle::cast_dynamic(get_value_desc().get_value_node())) && composite->get_type() == type_bline_point && (bline_vertex = ValueNode_BLineCalcVertex::Handle::cast_dynamic(composite->get_link("point"))))) { synfig::Point closest_point = get_point(); synfig::Real radius = 0.0; ValueNode_BLine::Handle bline = ValueNode_BLine::Handle::cast_dynamic(bline_vertex->get_link("bline")); synfig::find_closest_point( (*bline)(time), get_point(), radius, bline->get_loop(), &closest_point); set_point(closest_point); } ValueNode_Composite::Handle wpoint_composite; ValueNode_WPList::Handle wplist; wpoint_composite=ValueNode_Composite::Handle::cast_dynamic(get_value_desc().get_value_node()); if(wpoint_composite && wpoint_composite->get_type() == type_width_point) if(get_value_desc().parent_is_value_node()) { wplist=ValueNode_WPList::Handle::cast_dynamic(get_value_desc().get_parent_value_node()); if(wplist) { ValueNode_BLine::Handle bline(ValueNode_BLine::Handle::cast_dynamic(wplist->get_bline())); synfig::Point closest_point = get_point(); synfig::Real radius = 0.0; synfig::find_closest_point( (*bline)(time), get_point(), radius, bline->get_loop(), &closest_point); set_point(closest_point); } } } } synfig::Point Duck::get_sub_trans_point(const Handle &duck, const Point &def, bool translate)const { // The origin needs to have the same transform stack as this duck return !duck ? def : translate ? transform_stack_.unperform(duck->get_trans_point()) : transform_stack_.unperform(duck->get_trans_point()) - transform_stack_.unperform(duck->get_trans_origin()); } synfig::Point Duck::get_sub_trans_origin()const { return get_sub_trans_point(origin_duck_,origin_); } #ifdef _DEBUG synfig::String Duck::type_name(Type id) { String ret; if (id & TYPE_POSITION) { if (!ret.empty()) ret += ", "; ret += "position"; } if (id & TYPE_TANGENT ) { if (!ret.empty()) ret += ", "; ret += "tangent" ; } if (id & TYPE_RADIUS ) { if (!ret.empty()) ret += ", "; ret += "radius" ; } if (id & TYPE_WIDTH ) { if (!ret.empty()) ret += ", "; ret += "width" ; } if (id & TYPE_ANGLE ) { if (!ret.empty()) ret += ", "; ret += "angle" ; } if (id & TYPE_VERTEX ) { if (!ret.empty()) ret += ", "; ret += "vertex" ; } if (id & TYPE_WIDTHPOINT_POSITION) { if (!ret.empty()) ret += ", "; ret += "widthpoint position" ; } if (id & TYPE_SCALE ) { if (!ret.empty()) ret += ", "; ret += "scale" ; } if (id & TYPE_SCALE_X ) { if (!ret.empty()) ret += ", "; ret += "scale-x" ; } if (id & TYPE_SCALE_Y ) { if (!ret.empty()) ret += ", "; ret += "scale-y" ; } if (id & TYPE_SKEW ) { if (!ret.empty()) ret += ", "; ret += "skew" ; } if (ret.empty()) ret = "none"; return ret; } #endif // _DEBUG