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 &center);
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 &center, TPointD &offset) const;
308   void setCenterAndOffset(const TPointD &center, 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