1 #pragma once 2 3 #ifndef T_STAGE_OBJECT_INCLUDED 4 #define T_STAGE_OBJECT_INCLUDED 5 6 // TnzCore includes 7 #include "tgeometry.h" 8 9 // TnzBase includes 10 #include "tdoubleparam.h" 11 12 // TnzExt includes 13 #include "ext/plasticskeletondeformation.h" 14 15 // TnzLib includes 16 #include "tstageobjectid.h" 17 18 // tcg includes 19 #include "tcg/tcg_controlled_access.h" 20 21 // Qt includes 22 #include <QStack> 23 24 #undef DVAPI 25 #undef DVVAR 26 #ifdef TOONZLIB_EXPORTS 27 #define DVAPI DV_EXPORT_API 28 #define DVVAR DV_EXPORT_VAR 29 #else 30 #define DVAPI DV_IMPORT_API 31 #define DVVAR DV_IMPORT_VAR 32 #endif 33 34 //==================================================== 35 36 // Forward declarations 37 38 class TPinnedRangeSet; 39 class TStroke; 40 class TStageObjectParams; 41 class TStageObjectSpline; 42 class TCamera; 43 class TStageObjectTree; 44 class PlasticSkeletonDeformation; 45 46 //==================================================== 47 48 //******************************************************************************************** 49 // TStageObject declaration 50 //******************************************************************************************** 51 52 /*! 53 TStageObject is the Toonz class representing animatable scene objects like 54 columns, pegbars, 55 tables and cameras (pretty much every object in Toonz's stage schematic). 56 57 \par Description 58 59 A TStageObject contains a common set of editable parameters (coordinates, 60 angles and more) 61 that define the object's state along an xsheet timeline. These parameters are 62 in the form of 63 animatable TDoubleParam instances and can be accessed directly through the 64 getParam() method. 65 \n\n 66 A notable responsibility of the TStageObject class is that of building the 67 keyframes data that 68 will be shown in xsheet viewes (the key icons). The object's keyframes are 69 built and cached 70 each time one of its associated parameters is changed. 71 \n\n 72 Furthermore, a TStageObject instance is typically a node in a tree-like 73 hierarchycal structure 74 of class TStageObjectTree which is used to define relative object placement 75 between objects. 76 77 \par Creation 78 79 Client code should access TStageObject instances through its TXsheet owner, 80 like: 81 82 \code 83 84 TStageObjectId objectId = TApp::instance()->getCurrentObject()->getObjectId(); 85 TStageObject* stageObject = TApp::instance()->getCurrentXsheet() 86 ->getXsheet()->getStageObject(objectId); 87 88 \endcode 89 90 The actual creation of new TStageObject instances is currently a 91 responsibility of the 92 TStageObjectTree class. 93 */ 94 95 class DVAPI TStageObject final : public TSmartObject, public TParamObserver { 96 DECLARE_CLASS_CODE 97 98 public: 99 /*! 100 Used to describe the object status - ie how the object can move. 101 The default value is XY. 102 */ 103 enum Status { 104 XY, //!< The object can move freely on a plane 105 PATH = 1, //!< The movement take place on a spline 106 PATH_AIM = 2, //!< The movement take place on a spline with the orientation 107 //! of the object 108 //!< defined by the user through \b TStageObject::T_Angle and the total 109 //! angle is 110 //!< the sum of the user angle plus the angle formed by 111 //!< the tangent at the curve in the actual point 112 IK = 3, //!< The object is translated according to inverse kinematics 113 PATH_UPPK = 5, //!< PATH + UPPK (Update Pos Path Keyframe, when the spline 114 //! is changed; see TStageObjectSpline) 115 PATH_AIM_UPPK = 6, //!< PATH_AIM + UPPK 116 UPPK_MASK = 4, //!< (status&UPPK_MASK)!=0 <==> UPPK enabled 117 STATUS_MASK = 3 //!< (status&STATUS_MASK) => old status 118 }; 119 120 //! Used to describe object parameters. 121 enum Channel { 122 T_Angle, //!< Object's angle (rotation) 123 T_X, //!< Local x coordinate in inches 124 T_Y, //!< Local y coordinate in inches 125 T_Z, //!< Layer depth 126 T_SO, //!< Stacking Order 127 T_ScaleX, //!< X-axis scale factor 128 T_ScaleY, //!< Y-axis scale factor 129 T_Scale, 130 T_Path, //!< point position along the spline, as a percentage of the length 131 //! of the spline 132 T_ShearX, //!< Shear along x-axis 133 T_ShearY, //!< Shear along y-axis 134 T_ChannelCount 135 }; 136 137 /*! 138 The Keyframe struct define a keyframe. 139 A keyframe allows to define object values in a specific frame. 140 Keyframes are the starting and ending points of a transition in a scene. 141 Its parameters are taken as references to make changes on the paramters of 142 other frames, 143 as: 144 145 \li interpolation of parameters between two keyframes in the timeline, 146 \li extrapolation of parameters after or before a single keyframe. 147 */ 148 struct Keyframe; 149 150 /*! 151 Define a map of int and keyframe necessary to know object keyframe; 152 Its purpose is the indexing of the object's keyframes. 153 */ 154 typedef std::map<int, Keyframe> KeyframeMap; 155 156 public: 157 /*! Initializes a stage object in his \e tree with an unique id. 158 \n The constructor is called by \b TStageObjectTree to create a new column in 159 the tree or 160 in general a new node in the tree. 161 */ 162 TStageObject(TStageObjectTree *tree, TStageObjectId id); 163 /*! 164 This is the destructor. 165 */ 166 ~TStageObject(); 167 168 //! Retrieves the stage object's id. 169 TStageObjectId getId() const; 170 171 //! Sets the object's id. setId(const TStageObjectId & id)172 void setId(const TStageObjectId &id) { 173 if (id != TStageObjectId::NoneId) m_id = id; 174 } 175 176 void setName(const std::string &name); 177 std::string getName() const; 178 179 //! Returns the id's full name, ie the name of the object with its id 180 //! appended. 181 std::string getFullName() const; 182 183 //! Returns whether this object is already in use. isOpened()184 bool isOpened() const { return m_isOpened; } 185 186 //! Sets the usage status of the object. setIsOpened(bool value)187 void setIsOpened(bool value) { m_isOpened = value; } 188 189 //! Returns whether the object has been locked (can't move). isLocked()190 bool isLocked() const { return m_locked; } 191 192 //! Locks the object. lock(bool on)193 void lock(bool on) { m_locked = on; } 194 195 // used by Inverse Kinematics getPinnedRangeSet()196 TPinnedRangeSet *getPinnedRangeSet() const { return m_pinnedRangeSet; } 197 198 //! Sets the object's parent. 199 void setParent(const TStageObjectId &parentId); 200 201 //! Returns the \a id of the object's parent. Use the owner xsheet to access 202 //! the parent object. 203 TStageObjectId getParent() const; 204 205 //! Returns the motion path associated to the object 206 TStageObjectSpline *getSpline() const; 207 208 /*! 209 Sets the motion path of the object. 210 A \e null pointer argument make \e this an object without a path and set the 211 object status to TStageObject::XY, 212 that is it can move on a palne. 213 \e this gets ownership of \e spline. 214 \note does NOT take spline ownership 215 */ 216 void setSpline(TStageObjectSpline *spline); 217 218 /*! 219 As setSpline(), but doesn't notify; 220 actually setSpline() calls doSetSpline() and then notifies 221 \note does NOT take spline ownership 222 */ 223 void doSetSpline(TStageObjectSpline *spline); 224 225 //! Returns whether stageObject is ancestor of this. 226 bool isAncestor(TStageObject *stageObject) const; 227 228 //! Sets the object's status. 229 void setStatus(Status status); 230 231 //! Returns the object's status. getStatus()232 Status getStatus() const { return m_status; } 233 234 //! helper functions to manipulate status isAimEnabled()235 inline bool isAimEnabled() const { 236 return (m_status & STATUS_MASK) == PATH_AIM; 237 } isPathEnabled()238 inline bool isPathEnabled() const { 239 return (m_status & STATUS_MASK) == PATH_AIM || 240 (m_status & STATUS_MASK) == PATH; 241 } isUppkEnabled()242 inline bool isUppkEnabled() const { return (m_status & UPPK_MASK) != 0; } 243 void enableAim(bool enabled); 244 void enablePath(bool enabled); 245 void enableUppk(bool enabled); 246 247 //! Returns object's position in the schematic view. getDagNodePos()248 TPointD getDagNodePos() const { return m_dagNodePos; } 249 250 /*! 251 Sets the position of the object node object in the widget work area. 252 This function is provided for status saving purpose of the interface that 253 manages the schematic's view. 254 */ setDagNodePos(const TPointD & p)255 void setDagNodePos(const TPointD &p) { m_dagNodePos = p; } 256 257 /*! 258 Returns string containing pegbar handle name like A,B...Z, or H1,H2...H8. 259 \n It refers to the handle of the actual pegbar, ie the offset center of the 260 pegbar. 261 The default value is B that centers the pegbar and corresponds to an hook with 262 index equal to 0. 263 Hooks are column references (0 is the center) in the sheet and are data 264 structures defined in the file hook.h. 265 \n H1 has an index equal to 1, H2 => 2 and so on. 266 \sa setHandle() and getParentHandle() 267 */ getHandle()268 const std::string &getHandle() const { return m_handle; } 269 270 /*! 271 Return string containing pegbar parent handle name. Es.: A,B...Z, or H1,H2...H8. 272 \sa setParentHandle() and getHandle() 273 */ getParentHandle()274 const std::string &getParentHandle() const { return m_parentHandle; } 275 276 /*! 277 Sets the name of the pegbar handle name. 278 An empty or an H1,...,H8 string sets the offset to the actual center of the 279 object. 280 \sa getHandle() 281 */ 282 void setHandle(const std::string &s); 283 284 //! Sets the name of the pegbar parent handle name. 285 void setParentHandle(const std::string &s); 286 287 //! Sets the channel \e type to the value \e val 288 void setParam(Channel type, double frame, double val); 289 290 //! Returns the \b TStageObject::Channel value associated with the \e frame. 291 double getParam(Channel type, double frame) const; 292 293 //! Sets the center of the \e frame to \e center. 294 void setCenter(double frame, const TPointD ¢er); 295 296 //! Returns the center of the \e frame. 297 TPointD getCenter(double frame) const; 298 299 //! Returns the offset of the object. \sa setOffset(). 300 TPointD getOffset() const; 301 302 //! Sets the offset of the object. \sa getOffset(). 303 void setOffset(const TPointD &off); 304 305 // n.b. accesso diretto alla variabili interne center e offset. serve per 306 // undo/redo 307 void getCenterAndOffset(TPointD ¢er, TPointD &offset) const; 308 void setCenterAndOffset(const TPointD ¢er, const TPointD &offset); 309 310 //! Returns true if \e frame is a keyframe. \sa TStageObject::Keyframe 311 bool isKeyframe(int frame) const; 312 313 //! Returns true if \e frame is a keyframe for all channels. 314 bool isFullKeyframe(int frame) const; 315 316 //! Returns true if \e frame is a keyframe for all channels with exeption of 317 //! global scale channel. 318 bool is52FullKeyframe(int frame) const; 319 320 /*! 321 Retrieves from the list of the keyframes a keyframe object 322 (TStageObject::Keyframe) associated 323 with the frame. 324 */ 325 Keyframe getKeyframe(int frame) const; 326 327 void setKeyframeWithoutUndo(int frame, const Keyframe &); 328 void setKeyframeWithoutUndo(int frame); 329 void removeKeyframeWithoutUndo(int frame); 330 331 /*! 332 Moves Keyframe \e src to \e dst. All the Channels associated are copied and 333 the reference to \e src is deleted. 334 Returns \e true on success. 335 */ 336 bool moveKeyframe(int dst, int src); 337 338 /* 339 This function checks if a list of keyframes can be moved without deleting an 340 existing keyframe. 341 */ 342 bool canMoveKeyframes(std::set<int> &frames, int delta); 343 344 /* 345 Translates the list \e frames of \e delta frames. Returns \e true on success. 346 */ 347 bool moveKeyframes(std::set<int> &frames, int delta); 348 349 /** Gets a range of keyframes */ 350 void getKeyframes(KeyframeMap &keyframes) const; 351 bool getKeyframeRange(int &r0, int &r1) const; 352 353 bool getKeyframeSpan(int row, int &r0, double &ease0, int &r1, 354 double &ease1) const; 355 356 TAffine getPlacement(double t); 357 TAffine getParentPlacement(double t) const; 358 359 /*! 360 Returns the object's depth at specified frame. 361 \sa Methods getGlobalNoScaleZ() and getNoScaleZ(). 362 */ 363 double getZ(double frame); 364 365 //! Returns the object's stacking order at specified frame. 366 double getSO(double frame); 367 368 //! Returns the absolute depth with no scale factor. 369 double getGlobalNoScaleZ() const; 370 371 //! This method returns the original depth of the pegbar. 372 double getNoScaleZ() const; 373 374 /*! 375 Returns the depth with no scale factor. 376 Movig along Z axis results in a scale factor on the plane XY. 377 This method sets the original depth of the pegbar. 378 \n \sa getGlobalNoScaleZ(). 379 */ 380 void setNoScaleZ(double noScaleZ); 381 382 //! Returns the stored skeleton deformation, if any 383 PlasticSkeletonDeformationP getPlasticSkeletonDeformation() const; 384 385 //! Stores the specified skeleton deformation 386 void setPlasticSkeletonDeformation(const PlasticSkeletonDeformationP &sd); 387 388 //! Returns whether the object has children. hasChildren()389 bool hasChildren() const { return !m_children.empty(); } getChildren()390 const std::list<TStageObject *> &getChildren() const { return m_children; } 391 392 /*! 393 Returns \e true if the objects cycle is enabled, 394 i.e. if a finite sequence is a cycle. 395 */ 396 bool isCycleEnabled() const; 397 398 /*! 399 Enables cycle of the object, this method is provided to take care 400 of the position of the viewer in the sequence. 401 \sa isCycleEnabled() 402 */ 403 void enableCycle(bool on); 404 405 /*! 406 Gets local placement of the object taking care of translation, rotation, shear 407 and scale 408 of the \e frame 409 */ getLocalPlacement(double frame)410 TAffine getLocalPlacement(double frame) { 411 return computeLocalPlacement(frame); 412 } 413 414 //! Returns the \e channel's value of the object. 415 TDoubleParam *getParam(Channel channel) const; 416 417 //! Copies the data of the object in a new object with a new id and adds it to 418 //! the tree. 419 TStageObject *clone(); 420 421 //! Returns a new data-structure filled with the actual data of the object. 422 TStageObjectParams *getParams() const; 423 424 //! Sets the object's values to \e src values and update the object. 425 void assignParams(const TStageObjectParams *src, 426 bool doParametersClone = true); 427 428 //! Returns a pointer to the actual camera. getCamera()429 TCamera *getCamera() { return m_camera; } getCamera()430 const TCamera *getCamera() const { return m_camera; } 431 432 /*! 433 Removes this object from the list of children of his actual parent. 434 Doesn't delete \e this. 435 */ 436 void detachFromParent(); 437 438 //! Makes all children of \e this childern of \e parentId. 439 void attachChildrenToParent(const TStageObjectId &parentId); 440 441 //! Resets the area position setting internal time of the object and of all 442 //! his children to -1. 443 void invalidate(); 444 445 /*! 446 Return true if current object is visible, if object position in z-axis is 447 less than 1000; othrwise return false. 448 \n Set \b TAffine \b aff to current object trasformation matrix computed 449 using camera and object trasformation matrix, 450 \b cameraAff, \b objectAff, and using camera and object position in z-axis, 451 \b cameraZ, \b objectZ. 452 \n \b objectZ default value is zero, big value describe the nearest camera 453 object; 454 original distance between table and camera is 1000. 455 \n \b cameraZ default value is zero, negative value suggest that camera is near 456 to 457 the table, camera is in the table for cameraZ = -1000. 458 */ 459 static bool perspective(TAffine &aff, const TAffine &cameraAff, 460 double cameraZ, const TAffine &objectAff, 461 double objectZ, double objectNoScaleZ); 462 463 void loadData(TIStream &is); 464 void saveData(TOStream &os); 465 466 // Group management 467 int setGroupId(int value); 468 void setGroupId(int value, int position); 469 int getGroupId(); 470 QStack<int> getGroupIdStack(); 471 void removeGroupId(int position); 472 int removeGroupId(); 473 474 bool isGrouped(); 475 bool isContainedInGroup(int groupId); 476 477 void setGroupName(const std::wstring &name, int position = -1); 478 std::wstring getGroupName(bool fromEditor); 479 QStack<std::wstring> getGroupNameStack(); 480 int removeGroupName(bool fromEditor); 481 void removeGroupName(int position = -1); 482 483 void removeFromAllGroup(); 484 485 void editGroup(); 486 bool isGroupEditing(); 487 void closeEditingGroup(int groupId); 488 int getEditingGroupId(); 489 std::wstring getEditingGroupName(); 490 491 void updateKeyframes(); //!< Rebuilds the internal keyframes table. 492 493 double paramsTime( 494 double t) const; //!< Traduces the xsheet-time into the one suitable 495 //!< for param values extraction (dealing with repeat/cycling) 496 497 private: 498 // Lazily updated data 499 500 struct LazyData { 501 KeyframeMap m_keyframes; 502 double m_time; 503 504 LazyData(); 505 }; 506 507 private: 508 tcg::invalidable<LazyData> m_lazyData; 509 510 TStageObjectId m_id; 511 TStageObjectTree *m_tree; 512 TStageObject *m_parent; 513 std::list<TStageObject *> m_children; 514 515 bool m_cycleEnabled; 516 517 TAffine m_localPlacement; 518 TAffine m_absPlacement; 519 520 TStageObjectSpline *m_spline; 521 Status m_status; 522 523 TDoubleParamP m_x, m_y, m_z, m_so, m_rot, m_scalex, m_scaley, m_scale, 524 m_posPath, m_shearx, m_sheary; 525 526 PlasticSkeletonDeformationP 527 m_skeletonDeformation; //!< Deformation curves for a plastic skeleton 528 529 TPointD m_center; 530 TPointD m_offset; 531 532 // ----For Inverse Kinematics interpolation 533 TPinnedRangeSet *m_pinnedRangeSet; 534 535 TAffine computeIkRootOffset(int t); 536 int m_ikflag; 537 // ---- 538 539 double m_noScaleZ; 540 541 std::string m_name; 542 TPointD m_dagNodePos; 543 bool m_isOpened; 544 std::string m_handle, m_parentHandle; 545 TCamera *m_camera; 546 QStack<int> m_groupId; 547 QStack<std::wstring> m_groupName; 548 int m_groupSelector; 549 550 bool m_locked; 551 552 private: 553 // Not copyable 554 TStageObject(const TStageObject &); 555 TStageObject &operator=(const TStageObject &); 556 557 TPointD getHandlePos(std::string handle, int row) const; 558 TAffine computeLocalPlacement(double frame); 559 TStageObject *findRoot(double frame) const; 560 TStageObject *getPinnedDescendant(int frame); 561 562 private: 563 // Lazy data-related functions 564 565 LazyData &lazyData(); 566 const LazyData &lazyData() const; 567 568 void update(LazyData &ld) const; 569 570 void invalidate(LazyData &ld) const; 571 void updateKeyframes(LazyData &ld) const; 572 573 void onChange(const class TParamChange &c) override; 574 }; 575 576 //----------------------------------------------------------------------------- 577 578 #ifdef _WIN32 579 template class DVAPI TSmartPointerT<TStageObject>; 580 #endif 581 582 typedef TSmartPointerT<TStageObject> TStageObjectP; 583 584 //============================================================================= 585 586 // TODO: togliere questo include da qui. 587 // Bisogna: includere qui il contenuto del file e eliminare 588 // tstageobjectkeyframe.h 589 // oppure creare un altro file con la dichiarazione di TStageObjectParams 590 #include "tstageobjectkeyframe.h" 591 592 //============================================================================= 593 // 594 // TStageObjectParams 595 // 596 //============================================================================= 597 class DVAPI TStageObjectParams { 598 public: 599 TStageObjectId m_id, m_parentId; 600 std::vector<TStageObjectId> m_children; 601 std::map<int, TStageObject::Keyframe> m_keyframes; 602 bool m_cycleEnabled, m_isOpened; 603 TStageObjectSpline *m_spline; 604 TStageObject::Status m_status; 605 std::string m_handle, m_parentHandle; 606 TPinnedRangeSet *m_pinnedRangeSet; 607 TDoubleParamP m_x, m_y, m_z, m_so, m_rot, m_scalex, m_scaley, m_scale, 608 m_posPath, m_shearx, m_sheary; 609 PlasticSkeletonDeformationP 610 m_skeletonDeformation; //!< Deformation curves for a plastic skeleton 611 double m_noScaleZ; 612 TPointD m_center, m_offset; 613 std::string m_name; 614 615 TStageObjectParams(); 616 TStageObjectParams(TStageObjectParams *data); 617 ~TStageObjectParams(); 618 TStageObjectParams *clone(); 619 }; 620 621 #endif 622