1 /* === S Y N F I G ========================================================= */
3 ** \brief Template File
8 ** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 ** Copyright (c) 2007, 2008 Chris Moore
11 ** This package is free software; you can redistribute it and/or
12 ** modify it under the terms of the GNU General Public License as
13 ** published by the Free Software Foundation; either version 2 of
14 ** the License, or (at your option) any later version.
16 ** This package is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 ** General Public License for more details.
22 /* ========================================================================= */
24 /* === H E A D E R S ======================================================= */
36 #include <synfig/valuenode_bline.h>
37 #include <synfig/valuenode_blinecalctangent.h>
38 #include <synfig/valuenode_blinecalcvertex.h>
39 #include <synfig/valuenode_blinecalcwidth.h>
40 #include <synfig/valuenode_composite.h>
45 /* === U S I N G =========================================================== */
49 using namespace synfig;
50 using namespace studio;
52 /* === M A C R O S ========================================================= */
54 /* === G L O B A L S ======================================================= */
56 int studio::Duck::duck_count(0);
64 synfig::error("%d ducks not yet deleted!",counter);
68 int _DuckCounter::counter(0);
71 /* === P R O C E D U R E S ================================================= */
73 /* === M E T H O D S ======================================================= */
76 rotations(synfig::Angle::deg(0)),
84 { duck_count++; _DuckCounter::counter++; }
86 Duck::Duck(const synfig::Point &point):
89 rotations(synfig::Angle::deg(0)),
98 { duck_count++; _DuckCounter::counter++;}
100 Duck::Duck(const synfig::Point &point,const synfig::Point &origin):
102 rotations(synfig::Angle::deg(0)),
111 { duck_count++; _DuckCounter::counter++;}
113 Duck::~Duck() { duck_count--; _DuckCounter::counter--;}
116 Duck::get_data_guid()const
118 if(value_desc_.is_value_node())
119 return value_desc_.get_value_node()->get_guid();
120 return synfig::GUID::hasher(get_name());
124 Duck::set_name(const synfig::String &x)
127 if(guid_==synfig::GUID::zero())
129 guid_=synfig::GUID::hasher(name);
135 Duck::operator==(const Duck &rhs)const
141 scalar==rhs.scalar &&
143 transform_stack_.size()==rhs.transform_stack_.size();
145 //(origin_duck?*origin_duck==*rhs.origin_duck:origin==rhs.origin) &&
146 //(shared_point?*shared_point==*rhs.shared_point:point==rhs.point) ;
150 Duck::get_trans_point()const
152 return transform_stack_.perform(get_sub_trans_point());
156 Duck::set_trans_point(const synfig::Point &x)
158 set_sub_trans_point(transform_stack_.unperform(x));
162 Duck::set_trans_point(const synfig::Point &x, const synfig::Time &time)
164 set_sub_trans_point(transform_stack_.unperform(x), time);
167 //! Sets the origin point.
169 Duck::set_origin(const synfig::Point &x)
171 origin=x; origin_duck=0;
174 //! Sets the origin point as another duck
176 Duck::set_origin(const etl::handle<Duck> &x)
181 //! Retrieves the origin location
183 Duck::get_origin()const
185 return origin_duck?origin_duck->get_point():origin;
188 //! Retrieves the origin duck
189 const etl::handle<Duck> &
190 Duck::get_origin_duck() const
195 //! Retrieves the origin location
197 Duck::get_trans_origin()const
199 return transform_stack_.perform(get_sub_trans_origin());
203 Duck::get_sub_trans_point()const
205 return get_point()*get_scalar()+get_sub_trans_origin();
209 Duck::set_sub_trans_point(const synfig::Point &x, const synfig::Time &time)
211 if (get_type() == Duck::TYPE_TANGENT ||
212 get_type() == Duck::TYPE_ANGLE)
214 Angle old_angle = get_point().angle();
215 set_point((x-get_sub_trans_origin())/get_scalar());
216 Angle change = get_point().angle() - old_angle;
217 while (change < Angle::deg(-180)) change += Angle::deg(360);
218 while (change > Angle::deg(180)) change -= Angle::deg(360);
219 int old_halves = round_to_int(Angle::deg(rotations).get()/180);
221 int new_halves = round_to_int(Angle::deg(rotations).get()/180);
222 if (old_halves != new_halves &&
223 (new_halves > 1 || new_halves < -1 ||
224 old_halves > 1 || old_halves < -1))
225 synfig::info("rotation: %.2f turns", new_halves/2.0);
226 } else if(get_type() == Duck::TYPE_VERTEX || get_type() == Duck::TYPE_POSITION)
228 set_point((x-get_sub_trans_origin())/get_scalar());
230 ValueNode_BLineCalcVertex::Handle bline_vertex;
231 ValueNode_Composite::Handle composite;
233 if ((bline_vertex = ValueNode_BLineCalcVertex::Handle::cast_dynamic(get_value_desc().get_value_node())) ||
234 ((composite = ValueNode_Composite::Handle::cast_dynamic(get_value_desc().get_value_node())) &&
235 composite->get_type() == ValueBase::TYPE_BLINEPOINT &&
236 (bline_vertex = ValueNode_BLineCalcVertex::Handle::cast_dynamic(composite->get_link("point")))))
238 synfig::Point closest_point = get_point();
239 synfig::Real radius = 0.0;
240 ValueNode_BLine::Handle bline = ValueNode_BLine::Handle::cast_dynamic(bline_vertex->get_link(bline_vertex->get_link_index_from_name("bline")));
241 synfig::find_closest_point(
247 set_point(closest_point);
250 else set_point((x-get_sub_trans_origin())/get_scalar());
253 //! Updates width and tangent ducks that change when the origin moves
255 Duck::update(const synfig::Time &time)
257 if((get_type() == Duck::TYPE_TANGENT || get_type() == Duck::TYPE_WIDTH) && origin_duck)
259 ValueNode_BLineCalcVertex::Handle bline_vertex;
260 ValueNode_Composite::Handle composite;
261 if ((bline_vertex = ValueNode_BLineCalcVertex::Handle::cast_dynamic(origin_duck->get_value_desc().get_value_node())) ||
262 ((composite = ValueNode_Composite::Handle::cast_dynamic(origin_duck->get_value_desc().get_value_node())) &&
263 composite->get_type() == ValueBase::TYPE_BLINEPOINT &&
264 (bline_vertex = ValueNode_BLineCalcVertex::Handle::cast_dynamic(composite->get_link("point")))))
266 synfig::Real radius = 0.0;
267 ValueNode_BLine::Handle bline(ValueNode_BLine::Handle::cast_dynamic(bline_vertex->get_link(bline_vertex->get_link_index_from_name("bline"))));
268 Real amount = synfig::find_closest_point((*bline)(time), origin_duck->get_point(), radius, bline->get_loop());
270 int vertex_amount_index(bline_vertex->get_link_index_from_name("amount"));
271 ValueNode::Handle vertex_amount_value_node(bline_vertex->get_link(vertex_amount_index));
274 if (ValueNode_BLineCalcTangent::Handle bline_tangent = ValueNode_BLineCalcTangent::Handle::cast_dynamic(get_value_desc().get_value_node()))
276 switch (bline_tangent->get_type())
278 case ValueBase::TYPE_ANGLE:
280 Angle angle((*bline_tangent)(time, amount).get(Angle()));
281 set_point(Point(Angle::cos(angle).get(), Angle::sin(angle).get()));
284 case ValueBase::TYPE_REAL:
285 set_point(Point((*bline_tangent)(time, amount).get(Real()), 0));
287 case ValueBase::TYPE_VECTOR:
288 set_point((*bline_tangent)(time, amount).get(Vector()));
294 else if (ValueNode_BLineCalcWidth::Handle bline_width = ValueNode_BLineCalcWidth::Handle::cast_dynamic(get_value_desc().get_value_node()))
295 set_point(Point((*bline_width)(time, amount).get(Real()), 0));
303 Duck::set_sub_trans_point(const synfig::Point &x)
305 if (get_type() == Duck::TYPE_TANGENT ||
306 get_type() == Duck::TYPE_ANGLE)
308 Angle old_angle = get_point().angle();
309 set_point((x-get_sub_trans_origin())/get_scalar());
310 Angle change = get_point().angle() - old_angle;
311 while (change < Angle::deg(-180)) change += Angle::deg(360);
312 while (change > Angle::deg(180)) change -= Angle::deg(360);
313 int old_halves = round_to_int(Angle::deg(rotations).get()/180);
315 int new_halves = round_to_int(Angle::deg(rotations).get()/180);
316 if (old_halves != new_halves &&
317 (new_halves > 1 || new_halves < -1 ||
318 old_halves > 1 || old_halves < -1))
319 synfig::info("rotation: %.2f turns", new_halves/2.0);
321 else set_point((x-get_sub_trans_origin())/get_scalar());
325 Duck::get_sub_trans_origin()const
327 return origin_duck?origin_duck->get_sub_trans_point():origin;
332 Duck::type_name(Type id)
336 if (id & TYPE_POSITION) { if (!ret.empty()) ret += ", "; ret += "position"; }
337 if (id & TYPE_TANGENT ) { if (!ret.empty()) ret += ", "; ret += "tangent" ; }
338 if (id & TYPE_RADIUS ) { if (!ret.empty()) ret += ", "; ret += "radius" ; }
339 if (id & TYPE_WIDTH ) { if (!ret.empty()) ret += ", "; ret += "width" ; }
340 if (id & TYPE_ANGLE ) { if (!ret.empty()) ret += ", "; ret += "angle" ; }
341 if (id & TYPE_VERTEX ) { if (!ret.empty()) ret += ", "; ret += "vertex" ; }