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