1 /* === S Y N F I G ========================================================= */
2 /*!	\file duck.h
3 **	\brief Template Header
4 **
5 **	$Id$
6 **
7 **	\legal
8 **	Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9 **	Copyright (c) 2007, 2008 Chris Moore
10 **	Copyright (c) 2009 Nikita Kitaev
11 **
12 **	This package is free software; you can redistribute it and/or
13 **	modify it under the terms of the GNU General Public License as
14 **	published by the Free Software Foundation; either version 2 of
15 **	the License, or (at your option) any later version.
16 **
17 **	This package is distributed in the hope that it will be useful,
18 **	but WITHOUT ANY WARRANTY; without even the implied warranty of
19 **	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 **	General Public License for more details.
21 **	\endlegal
22 */
23 /* ========================================================================= */
24 
25 /* === S T A R T =========================================================== */
26 
27 #ifndef __SYNFIG_DUCKMATIC_DUCK_H
28 #define __SYNFIG_DUCKMATIC_DUCK_H
29 
30 /* === H E A D E R S ======================================================= */
31 
32 #include <list>
33 
34 #include <ETL/smart_ptr>
35 #include <ETL/handle>
36 
37 #include <synfig/vector.h>
38 #include <synfig/string.h>
39 #include <synfig/real.h>
40 #include <sigc++/sigc++.h>
41 #include <synfig/time.h>
42 #include <ETL/smart_ptr>
43 #include <synfigapp/value_desc.h>
44 #include <synfig/transform.h>
45 
46 /* === M A C R O S ========================================================= */
47 
48 #ifdef HASH_MAP_H
49 #include HASH_MAP_H
50 #include FUNCTIONAL_H
51 
52 #ifndef __STRING_HASH__
53 #define __STRING_HASH__
54 class StringHash
55 {
56 # ifdef FUNCTIONAL_HASH_ON_STRING
57 	HASH_MAP_NAMESPACE::hash<synfig::String> hasher_;
58 # else  // FUNCTIONAL_HASH_ON_STRING
59 	HASH_MAP_NAMESPACE::hash<const char*> hasher_;
60 # endif  // FUNCTIONAL_HASH_ON_STRING
61 public:
operator()62 	size_t operator()(const synfig::String& x)const
63 	{
64 # ifdef FUNCTIONAL_HASH_ON_STRING
65 		return hasher_(x);
66 # else  // FUNCTIONAL_HASH_ON_STRING
67 		return hasher_(x.c_str());
68 # endif  // FUNCTIONAL_HASH_ON_STRING
69 	}
70 };
71 #endif
72 #else
73 #include <map>
74 #endif
75 
76 #include <set>
77 
78 /* === T Y P E D E F S ===================================================== */
79 
80 /* === C L A S S E S & S T R U C T S ======================================= */
81 
82 namespace studio {
83 class Duckmatic;
84 
85 /*! \class Duck
86 **	\writeme */
87 class Duck : public etl::shared_object
88 {
89 	friend class Duckmatic;
90 
91 public:
92 	enum Type
93 	{
94 		TYPE_NONE					=	(0),		//    0
95 		TYPE_POSITION				=	(1 <<  0),	//    1
96 		TYPE_TANGENT				=	(1 <<  1),	//    2
97 		TYPE_RADIUS					=	(1 <<  2),	//    4
98 		TYPE_WIDTH					=	(1 <<  3),	//    8
99 		TYPE_ANGLE					=	(1 <<  4),	//   16
100 		TYPE_VERTEX					=	(1 <<  5),	//   32
101 		TYPE_BONE_RECURSIVE			=	(1 <<  6),	//   64
102 		TYPE_WIDTHPOINT_POSITION	=	(1 <<  7),	//  128
103 		TYPE_SCALE					=	(1 <<  8),	//  256
104 		TYPE_SCALE_X				=	(1 <<  9),	//  512
105 		TYPE_SCALE_Y				=	(1 << 10),	// 1024
106 		TYPE_SKEW					=	(1 << 11),	// 2048
107 
108 		TYPE_ALL					=	(~0),
109 
110 		TYPE_DEFAULT				=	0xdefadefa
111 	};
112 	//used for preference/interface handle tooltip flag
113 	enum Structure
114 	{
115 		STRUCT_NONE					=	(0),		//    0
116 		STRUCT_BLINEPOINT			=	(1 <<  0),	//    1
117 		STRUCT_TRANSFORMATION		=	(1 <<  1),	//    2
118 		STRUCT_WIDTHPOINT			=	(1 <<  2),	//    4
119 		STRUCT_BONE					=	(1 <<  3),	//    8
120 		STRUCT_GRADIENT				=	(1 <<  4),	//   16
121 		STRUCT_TEXT					=	(1 <<  5),	//   32
122 		STRUCT_RADIUS				=	(1 <<  6),	//   64
123 		STRUCT_TRANSFO_BY_VALUE		=	(1 <<  7),	//  128
124 
125 		STRUCT_ALL					=	(~0),
126 
127 		STRUCT_DEFAULT				=	0x44 //STRUCT_RADIUS+STRUCT_WIDTHPOINT
128 	};
129 	typedef etl::handle<Duck> Handle;
130 	typedef etl::loose_handle<Duck> LooseHandle;
131 
132 private:
133 
134 	sigc::signal<bool,const Duck &> signal_edited_;
135 	sigc::signal<void> signal_user_click_[5];
136 
137 
138 	// information about represented value
139 
140 	synfig::GUID guid_;
141 	synfig::String name;
142 	Type type_;
143 	synfigapp::ValueDesc value_desc_;
144 	synfigapp::ValueDesc alternative_value_desc_;
145 
146 
147 	// Flags
148 
149 	bool editable_;
150 	bool alternative_editable_;
151 	bool edit_immediatelly_;
152 	bool radius_;
153 	bool tangent_;
154 	bool hover_;
155 	bool ignore_;
156 	bool exponential_;
157 	bool track_axes_;
158 	bool lock_aspect_;
159 
160 	// positioning
161 
162 	synfig::TransformStack transform_stack_;
163 
164 	synfig::Real scalar_;
165 
166 	synfig::Point origin_;
167 	Handle origin_duck_;
168 
169 	Handle axis_x_angle_duck_;
170 	synfig::Angle axis_x_angle_;
171 
172 	Handle axis_x_mag_duck_;
173 	synfig::Real axis_x_mag_;
174 
175 	Handle axis_y_angle_duck_;
176 	synfig::Angle axis_y_angle_;
177 
178 	Handle axis_y_mag_duck_;
179 	synfig::Real axis_y_mag_;
180 
181 	Handle connect_duck_;
182 	Handle box_duck_;
183 
184 	// value
185 
186 	synfig::Point point_;
187 	etl::smart_ptr<synfig::Point> shared_point_;
188 	etl::smart_ptr<synfig::Angle> shared_angle_;
189 	etl::smart_ptr<synfig::Real> shared_mag_;
190 	synfig::Angle rotations_;
191 	synfig::Point aspect_point_;
192 
193 	static int duck_count;
194 public:
195 
196 	// constructors
197 
198 	Duck();
199 	explicit Duck(const synfig::Point &point);
200 	Duck(const synfig::Point &point,const synfig::Point &origin);
201 	~Duck();
202 
203 
204 	// signals
205 
signal_edited()206 	sigc::signal<bool,const Duck &> &signal_edited()
207 		{ return signal_edited_; }
208 	sigc::signal<void> &signal_user_click(int i=0)
209 		{ assert(i>=0); assert(i<5); return signal_user_click_[i]; }
210 
211 
212 	// information about represented value
213 
set_guid(const synfig::GUID & x)214 	void set_guid(const synfig::GUID& x) { guid_=x; }
get_guid()215 	const synfig::GUID& get_guid()const { return guid_; }
216 	synfig::GUID get_data_guid()const;
217 
218 	//! Sets the name of the duck
219 	void set_name(const synfig::String &x);
220 	//! Retrieves the name of the duck
get_name()221 	synfig::String get_name()const { return name; }
222 
set_type(Type x)223 	void set_type(Type x) { type_=x; }
get_type()224 	Type get_type()const { return type_; }
225 
226 #ifdef _DEBUG
227 	//!	Returns a string containing the name of the given Type
228 	static synfig::String type_name(Type id);
229 	//!	Returns a string containing the name of the type
type_name()230 	synfig::String type_name()const { return type_name(get_type()); }
231 #endif	// _DEBUG
232 
set_value_desc(const synfigapp::ValueDesc & x)233 	void set_value_desc(const synfigapp::ValueDesc &x)
234 		{ value_desc_=x; }
get_value_desc()235 	const synfigapp::ValueDesc& get_value_desc() const
236 		{ return value_desc_; }
set_alternative_value_desc(const synfigapp::ValueDesc & x)237 	void set_alternative_value_desc(const synfigapp::ValueDesc &x)
238 		{ alternative_value_desc_=x; }
get_alternative_value_desc()239 	const synfigapp::ValueDesc& get_alternative_value_desc() const
240 		{ return alternative_value_desc_; }
241 
242 
243 	// flags
244 
get_editable(bool is_alternative_mode)245 	bool get_editable(bool is_alternative_mode)const
246 	{
247 		if (alternative_value_desc_.is_valid())
248 			return is_alternative_mode ? alternative_editable_ : editable_;
249 		return editable_;
250 	}
251 	//! Changes the editable flag.
set_editable(bool x)252 	void set_editable(bool x)
253 		{ editable_=x; }
254 	//! Retrieves the status of the editable flag
get_editable()255 	bool get_editable()const
256 		{ return editable_; }
257 	//! Changes the editable_alternative flag.
set_alternative_editable(bool x)258 	void set_alternative_editable(bool x)
259 		{ alternative_editable_=x; }
260 	//! Retrieves the status of the editable_alternative flag
get_alternative_editable()261 	bool get_alternative_editable()const
262 		{ return alternative_editable_; }
263 
is_radius()264 	bool is_radius()const
265 		{ return radius_; }
set_radius(bool r)266 	void set_radius(bool r)
267 		{ radius_=r; }
268 
269 	//! If set, the duck will send signal_edited while moving.
270 	//! If not set, the duck will send signal_edited when button released.
set_edit_immediatelly(bool x)271 	void set_edit_immediatelly(bool x)
272 		{ edit_immediatelly_=x; }
get_edit_immediatelly()273 	bool get_edit_immediatelly()const
274 		{ return edit_immediatelly_; }
275 
set_tangent(bool x)276 	void set_tangent(bool x)
277 		{ tangent_=x; if (x) type_=TYPE_TANGENT; }
get_tangent()278 	bool get_tangent()const
279 		{ return tangent_; }
280 
281 	//! Sets whether to show the duck as if it is being hovered over
set_hover(bool h)282 	void set_hover(bool h)
283 		{ hover_=h; }
284 	//! Retrieves whether to show the duck as if it is being hovered over
get_hover()285 	bool get_hover()const
286 		{ return hover_; }
287 
288 	//! Sets whether to ignore the duck when checking for user interaction
set_ignore(bool i)289 	void set_ignore(bool i)
290 		{ ignore_=i; }
291 	//! Retrieves whether to ignore the duck when checking for user interaction
get_ignore()292 	bool get_ignore()const
293 		{ return ignore_; }
294 
295 	//! Sets if the duck is using the exponential function
296 	/*!	Such representation allows to set the Real values in the range from \c -inf to \c inf . */
set_exponential(bool n)297 	void set_exponential(bool n)
298 		{ exponential_=n; }
299 	//! Retrieves the exponential value
get_exponential()300 	bool get_exponential()const
301 		{ return exponential_; }
302 
303 	//! draw projection lines onto axes
is_axes_tracks()304 	bool is_axes_tracks()const
305 		{ return track_axes_; }
set_track_axes(bool r)306 	void set_track_axes(bool r)
307 		{ track_axes_=r; }
308 
is_aspect_locked()309 	bool is_aspect_locked()const
310 		{ return lock_aspect_; }
set_lock_aspect(bool r)311 	void set_lock_aspect(bool r)
312 		{ if (!lock_aspect_ && r) aspect_point_=point_.norm(); lock_aspect_=r; }
313 
314 	// positioning
315 
set_transform_stack(const synfig::TransformStack & x)316 	void set_transform_stack(const synfig::TransformStack& x)
317 		{ transform_stack_=x; }
get_transform_stack()318 	const synfig::TransformStack& get_transform_stack()const
319 		{ return transform_stack_; }
320 
321 	//! Sets the scalar multiplier for the duck with respect to the origin
set_scalar(synfig::Vector::value_type n)322 	void set_scalar(synfig::Vector::value_type n)
323 		{ scalar_=n; }
324 	//! Retrieves the scalar value
get_scalar()325 	synfig::Vector::value_type get_scalar()const
326 		{ return scalar_; }
327 
328 	//! Sets the origin point.
set_origin(const synfig::Point & x)329 	void set_origin(const synfig::Point &x)
330 		{ origin_=x; origin_duck_=NULL; }
331 	//! Sets the origin point as another duck
set_origin(const Handle & x)332 	void set_origin(const Handle &x)
333 		{ origin_duck_=x; }
334 	//! Retrieves the origin location
get_origin()335 	synfig::Point get_origin()const
336 		{ return origin_duck_?origin_duck_->get_point():origin_; }
337 	//! Retrieves the origin duck
get_origin_duck()338 	const Handle& get_origin_duck() const
339 		{ return origin_duck_; }
340 
set_axis_x_angle(const synfig::Angle & a)341 	void set_axis_x_angle(const synfig::Angle &a)
342 		{ axis_x_angle_=a; axis_x_angle_duck_=NULL; }
343 	void set_axis_x_angle(const Handle &duck, const synfig::Angle angle = synfig::Angle::zero())
344 		{ axis_x_angle_duck_=duck; axis_x_angle_=angle; }
get_axis_x_angle()345 	synfig::Angle get_axis_x_angle()const
346 		{ return axis_x_angle_duck_?get_sub_trans_point(axis_x_angle_duck_,false).angle()+axis_x_angle_:axis_x_angle_; }
get_axis_x_angle_duck()347 	const Handle& get_axis_x_angle_duck()const
348 		{ return axis_x_angle_duck_; }
349 
set_axis_x_mag(const synfig::Real & m)350 	void set_axis_x_mag(const synfig::Real &m)
351 		{ axis_x_mag_=m; axis_x_mag_duck_=NULL; }
set_axis_x_mag(const Handle & duck)352 	void set_axis_x_mag(const Handle &duck)
353 		{ axis_x_mag_duck_=duck; }
get_axis_x_mag()354 	synfig::Real get_axis_x_mag()const
355 		{ return axis_x_mag_duck_?get_sub_trans_point(axis_x_mag_duck_,false).mag():axis_x_mag_; }
get_axis_x_mag_duck()356 	const Handle& get_axis_x_mag_duck()const
357 		{ return axis_x_mag_duck_; }
358 
get_axis_x()359 	synfig::Point get_axis_x()const
360 		{ return synfig::Point(get_axis_x_mag(), get_axis_x_angle()); }
361 
set_axis_y_angle(const synfig::Angle & a)362 	void set_axis_y_angle(const synfig::Angle &a)
363 		{ axis_y_angle_=a; axis_y_angle_duck_=NULL; }
364 	void set_axis_y_angle(const Handle &duck, const synfig::Angle angle = synfig::Angle::zero())
365 		{ axis_y_angle_duck_=duck; axis_y_angle_=angle; }
get_axis_y_angle()366 	synfig::Angle get_axis_y_angle()const
367 		{ return axis_y_angle_duck_?get_sub_trans_point(axis_y_angle_duck_,false).angle()+axis_y_angle_:axis_y_angle_; }
get_axis_y_angle_duck()368 	const Handle& get_axis_y_angle_duck()const
369 		{ return axis_y_angle_duck_; }
370 
set_axis_y_mag(const synfig::Real & m)371 	void set_axis_y_mag(const synfig::Real &m)
372 		{ axis_y_mag_=m; axis_y_mag_duck_=NULL; }
set_axis_y_mag(const Handle & duck)373 	void set_axis_y_mag(const Handle &duck)
374 		{ axis_y_mag_duck_=duck; }
get_axis_y_mag()375 	synfig::Real get_axis_y_mag()const
376 		{ return axis_y_mag_duck_?get_sub_trans_point(axis_y_mag_duck_,false).mag():axis_y_mag_; }
get_axis_y_mag_duck()377 	const Handle& get_axis_y_mag_duck()const
378 		{ return axis_y_mag_duck_; }
379 
get_axis_y()380 	synfig::Point get_axis_y()const
381 		{ return synfig::Point(get_axis_y_mag(), get_axis_y_angle()); }
382 
383 	//! linear ducks moves along specified axis only (angle locked)
is_linear()384 	bool is_linear()const
385 		{ return !get_axis_y_mag_duck() && get_axis_y_mag() == 0; }
set_linear(bool r)386 	void set_linear(bool r)
387 		{ if (is_linear() != r) set_axis_y_mag(r?0:1); }
set_linear(bool r,const synfig::Angle & a)388 	void set_linear(bool r, const synfig::Angle &a)
389 		{ set_linear(r); set_axis_x_angle(a); }
set_linear(bool r,const Handle & duck)390 	void set_linear(bool r, const Handle &duck)
391 		{ set_linear(r); set_axis_x_angle(duck); }
get_linear_angle()392 	synfig::Angle get_linear_angle()const
393 		{ return get_axis_x_angle(); }
get_linear_duck()394 	const Handle& get_linear_duck()const
395 		{ return get_axis_x_angle_duck(); }
396 
397 
398 	// guidelines to other ducks
399 
400 	//! draw line from specified duck to this duck
set_connect_duck(const Handle & x)401 	void set_connect_duck(const Handle& x)
402 		{ connect_duck_=x; }
get_connect_duck()403 	const Handle& get_connect_duck()const
404 		{ return connect_duck_; }
405 
406 	//! draw rectangle by two points - from this duck and from specified duck
set_box_duck(const Handle & x)407 	void set_box_duck(const Handle& x)
408 		{ box_duck_=x; }
get_box_duck()409 	const Handle& get_box_duck()const
410 		{ return box_duck_; }
411 
412 
413 	// value
414 
415 	//! Sets the location of the duck with respect to the origin
416 	void set_point(const synfig::Point &x);
417 	//! Returns the location of the duck
418 	synfig::Point get_point()const;
419 
set_shared_point(const etl::smart_ptr<synfig::Point> & x)420 	void set_shared_point(const etl::smart_ptr<synfig::Point>&x)
421 		{ shared_point_=x; }
get_shared_point()422 	const etl::smart_ptr<synfig::Point>& get_shared_point()const
423 		{ return shared_point_; }
424 
set_shared_angle(const etl::smart_ptr<synfig::Angle> & x)425 	void set_shared_angle(const etl::smart_ptr<synfig::Angle>&x)
426 		{ shared_angle_=x; }
get_shared_angle()427 	const etl::smart_ptr<synfig::Angle>& get_shared_angle()const
428 		{ return shared_angle_; }
429 
set_shared_mag(const etl::smart_ptr<synfig::Real> & x)430 	void set_shared_mag(const etl::smart_ptr<synfig::Real>&x)
431 		{ shared_mag_=x; }
get_shared_mag()432 	const etl::smart_ptr<synfig::Real>& get_shared_mag()const
433 		{ return shared_mag_; }
434 
435 	//! Returns the rotations of the duck
436 	//! For angle and tangent ducks, rotations are used instead of the location
437 	//! so that the duck can me rotated more than 180 degrees
get_rotations()438 	synfig::Angle get_rotations()const
439 		{ return rotations_; };
440 	//! Sets the rotations of the duck
set_rotations(const synfig::Angle & x)441 	void set_rotations(const synfig::Angle &x)
442 		{ rotations_=x; };
443 
444 
445 	// calculation of position of duck at workarea
446 
447 	synfig::Point get_trans_point()const;
448 
449 	void set_trans_point(const synfig::Point &x);
450 	void set_trans_point(const synfig::Point &x, const synfig::Time &time);
451 
452 	synfig::Point get_sub_trans_point(const synfig::Point &x)const;
453 	synfig::Point get_sub_trans_point()const;
454 	synfig::Point get_sub_trans_point_without_offset(const synfig::Point &x)const;
455 	synfig::Point get_sub_trans_point_without_offset()const;
456 	void set_sub_trans_point(const synfig::Point &x);
457 	void set_sub_trans_point(const synfig::Point &x, const synfig::Time &time);
458 	synfig::Point get_sub_trans_point(const Handle &duck, const synfig::Point &def, bool translate = true)const;
459 	synfig::Point get_sub_trans_point(const Handle &duck, bool translate = true)const
460 		{ return get_sub_trans_point(duck, synfig::Point(0,0), translate); }
461 	synfig::Point get_sub_trans_origin()const;
462 
463 	//! Retrieves the origin location
464 	synfig::Point get_trans_origin()const;
465 
466 
467 	// operators
468 
469 	bool operator==(const Duck &rhs)const;
470 }; // END of class Duck
471 
472 //! Combine Flags
473 inline Duck::Type
474 operator|(Duck::Type lhs, const Duck::Type rhs)
475 { return static_cast<Duck::Type>(int(lhs)|int(rhs)); }
476 
477 //! Exclude Flags
478 inline Duck::Type
479 operator-(Duck::Type lhs, const Duck::Type rhs)
480 { return static_cast<Duck::Type>(int(lhs)&~int(rhs)); }
481 
482 inline Duck::Type&
483 operator|=(Duck::Type& lhs, const Duck::Type rhs)
484 { *reinterpret_cast<int*>(&lhs)|=int(rhs); return lhs; }
485 
486 inline Duck::Type
487 operator&(const Duck::Type lhs, const Duck::Type rhs)
488 { return static_cast<Duck::Type>(int(lhs)&int(rhs)); }
489 
490 class DuckMap : public
491 #ifdef HASH_MAP_H
492 HASH_MAP_CLASS<synfig::GUID,etl::handle<studio::Duck>,synfig::GUIDHash>
493 {
494 	typedef HASH_MAP_CLASS<synfig::GUID,etl::handle<studio::Duck>,synfig::GUIDHash> PARENT_TYPE;
495 #else
496 std::map<synfig::GUID,etl::handle<studio::Duck> >
497 {
498 	typedef std::map<synfig::GUID,etl::handle<studio::Duck> > PARENT_TYPE;
499 #endif
500 public:
insert(const Duck::Handle & x)501 	void insert(const Duck::Handle& x) { operator[](x->get_guid())=x;  }
502 }; // END of class DuckMap
503 
504 typedef std::list<Duck::Handle> DuckList;
505 
506 }; // END of namespace studio
507 
508 /* === E N D =============================================================== */
509 
510 #endif
511