1 
2 
3 #include "toonz/tstageobject.h"
4 
5 // TnzLib includes
6 #include "toonz/tstageobjecttree.h"
7 #include "toonz/tstageobjectspline.h"
8 #include "toonz/txsheet.h"
9 #include "toonz/observer.h"
10 #include "toonz/txshlevelcolumn.h"
11 #include "toonz/txshcell.h"
12 #include "toonz/stage.h"
13 #include "toonz/tcamera.h"
14 #include "toonz/doubleparamcmd.h"
15 #include "toonz/tpinnedrangeset.h"
16 
17 // TnzExt includes
18 #include "ext/plasticskeleton.h"
19 #include "ext/plasticskeletondeformation.h"
20 #include "ext/plasticdeformerstorage.h"
21 
22 // TnzCore includes
23 #include "tstream.h"
24 #include "tstroke.h"
25 #include "tconvert.h"
26 #include "tundo.h"
27 #include "tconst.h"
28 
29 // Qt includes
30 #include <QMetaObject>
31 
32 // STD includes
33 #include <fstream>
34 #include <set>
35 
36 using namespace std;
37 
38 //
39 // Per un problema su alcune macchine, solo Release.
40 // il problema si verifica ruotando gli oggetti sul camera stand
41 //
42 
43 #ifdef _MSC_VER
44 #pragma optimize("", off)
45 #endif
makeRotation(double ang)46 static TAffine makeRotation(double ang) { return TRotation(ang); }
47 #ifdef _MSC_VER
48 #pragma optimize("", on)
49 #endif
50 
51 DEFINE_CLASS_CODE(TStageObject, 102)
52 
53 //************************************************************************************************
54 //    Local namespace
55 //************************************************************************************************
56 
57 namespace {
58 
59 enum StageObjectType {
60   NONE   = 0,
61   CAMERA = 1,
62   TABLE  = 2,
63   PEGBAR = 5,
64   COLUMN = 6
65 };
66 
67 const int StageObjectTypeShift = 28;
68 const int StageObjectMaxIndex  = ((1 << StageObjectTypeShift) - 1);
69 const int StageObjectIndexMask = ((1 << StageObjectTypeShift) - 1);
70 
71 }  // namespace
72 
73 //************************************************************************************************
74 //    TStageObjectParams  implementation
75 //************************************************************************************************
76 
TStageObjectParams()77 TStageObjectParams::TStageObjectParams() : m_spline(0), m_noScaleZ(0) {}
78 
79 //-----------------------------------------------------------------------------
80 
TStageObjectParams(TStageObjectParams * data)81 TStageObjectParams::TStageObjectParams(TStageObjectParams *data)
82     : m_id(data->m_id)
83     , m_parentId(data->m_parentId)
84     , m_children(data->m_children)
85     , m_keyframes(data->m_keyframes)
86     , m_cycleEnabled(data->m_cycleEnabled)
87     , m_spline(data->m_spline)
88     , m_status(data->m_status)
89     , m_handle(data->m_handle)
90     , m_parentHandle(data->m_parentHandle)
91     , m_x(data->m_x)
92     , m_y(data->m_y)
93     , m_z(data->m_z)
94     , m_so(data->m_so)
95     , m_rot(data->m_rot)
96     , m_scalex(data->m_scalex)
97     , m_scaley(data->m_scaley)
98     , m_scale(data->m_scale)
99     , m_posPath(data->m_posPath)
100     , m_shearx(data->m_shearx)
101     , m_sheary(data->m_sheary)
102     , m_skeletonDeformation(data->m_skeletonDeformation)
103     , m_noScaleZ(data->m_noScaleZ)
104     , m_center(data->m_center)
105     , m_offset(data->m_offset)
106     , m_name(data->m_name)
107     , m_isOpened(data->m_isOpened)
108     , m_pinnedRangeSet(data->m_pinnedRangeSet->clone()) {}
109 
110 //---------------------------------------------------------------------------
111 
~TStageObjectParams()112 TStageObjectParams::~TStageObjectParams() { delete m_pinnedRangeSet; }
113 
114 //---------------------------------------------------------------------------
115 
clone()116 TStageObjectParams *TStageObjectParams::clone() {
117   return new TStageObjectParams(this);
118 }
119 
120 //===========================================================================
121 // Utility Functions
122 //---------------------------------------------------------------------------
123 
toStageObjectId(string s)124 TStageObjectId toStageObjectId(string s) {
125   if (s == "None")
126     return TStageObjectId::NoneId;
127   else if (s == "Table")
128     return TStageObjectId::TableId;
129   else if (isInt(s)) {
130     TStageObjectId id;
131     id.setCode(std::stoi(s));
132     return id;
133   } else if (s.length() > 3) {
134     if (s.substr(0, 3) == "Col")
135       return TStageObjectId::ColumnId(std::stoi(s.substr(3)) - 1);
136     else if (s.substr(0, 3) == "Peg")
137       return TStageObjectId::PegbarId(std::stoi(s.substr(3)) - 1);
138     else if (s.length() > 6 && s.substr(0, 6) == "Camera")
139       return TStageObjectId::CameraId(std::stoi(s.substr(6)) - 1);
140   }
141   return TStageObjectId::NoneId;
142 }
143 
144 //-----------------------------------------------------------------------------
145 
operator <<(ostream & out,const TStageObjectId & id)146 ostream &operator<<(ostream &out, const TStageObjectId &id) {
147   return out << id.toString();
148 }
149 
150 //************************************************************************************************
151 //    TStageObjectId  implementation
152 //************************************************************************************************
153 
TStageObjectId()154 TStageObjectId::TStageObjectId() : m_id(NONE << StageObjectTypeShift) {}
155 
156 //-----------------------------------------------------------------------------
157 
~TStageObjectId()158 TStageObjectId::~TStageObjectId() {}
159 
160 //-----------------------------------------------------------------------------
161 
isCamera() const162 bool TStageObjectId::isCamera() const {
163   return m_id >> StageObjectTypeShift == CAMERA;
164 }
165 
166 //-----------------------------------------------------------------------------
167 
isTable() const168 bool TStageObjectId::isTable() const {
169   return m_id >> StageObjectTypeShift == TABLE;
170 }
171 
172 //-----------------------------------------------------------------------------
173 
isPegbar() const174 bool TStageObjectId::isPegbar() const {
175   return m_id >> StageObjectTypeShift == PEGBAR;
176 }
177 
178 //-----------------------------------------------------------------------------
179 
isColumn() const180 bool TStageObjectId::isColumn() const {
181   return m_id >> StageObjectTypeShift == COLUMN;
182 }
183 
184 //-----------------------------------------------------------------------------
185 
186 const TStageObjectId TStageObjectId::NoneId(NONE << StageObjectTypeShift);
187 
188 //-----------------------------------------------------------------------------
189 
190 const TStageObjectId TStageObjectId::TableId(TABLE << StageObjectTypeShift);
191 
192 //-----------------------------------------------------------------------------
193 
CameraId(int index)194 const TStageObjectId TStageObjectId::CameraId(int index) {
195   assert(0 <= index && index <= StageObjectMaxIndex);
196   return TStageObjectId(CAMERA << StageObjectTypeShift | index);
197 }
198 
199 //-----------------------------------------------------------------------------
200 
PegbarId(int index)201 const TStageObjectId TStageObjectId::PegbarId(int index) {
202   assert(0 <= index && index <= StageObjectMaxIndex);
203   return TStageObjectId(PEGBAR << StageObjectTypeShift | index);
204 }
205 
206 //-----------------------------------------------------------------------------
207 
ColumnId(int index)208 const TStageObjectId TStageObjectId::ColumnId(int index) {
209   assert(0 <= index && index <= StageObjectMaxIndex);
210   return TStageObjectId(COLUMN << StageObjectTypeShift | index);
211 }
212 
213 //-----------------------------------------------------------------------------
214 
toString() const215 string TStageObjectId::toString() const {
216   int index = m_id & StageObjectIndexMask;
217   string shortName;
218   switch (m_id >> StageObjectTypeShift) {
219   case NONE:
220     shortName = "None";
221     break;
222   case CAMERA:
223     shortName = "Camera" + std::to_string(index + 1);
224     break;
225   case TABLE:
226     shortName = "Table";
227     break;
228   case PEGBAR:
229     shortName = "Peg" + std::to_string(index + 1);
230     break;
231   case COLUMN:
232     shortName = "Col" + std::to_string(index + 1);
233     break;
234   default:
235     shortName = "BadPegbar";
236   }
237   return shortName;
238 }
239 
240 //-----------------------------------------------------------------------------
241 
getIndex() const242 int TStageObjectId::getIndex() const { return m_id & StageObjectIndexMask; }
243 
244 //=============================================================================
245 namespace {  // TStageObject Utility
246 //-----------------------------------------------------------------------------
247 
withFrame(TDoubleKeyframe k,double frame)248 TDoubleKeyframe withFrame(TDoubleKeyframe k, double frame) {
249   k.m_frame = frame;
250   return k;
251 }
252 
253 //-----------------------------------------------------------------------------
254 
setKeyframe(const TDoubleParamP & param,const TDoubleKeyframe & kf,int frame,const double & easeIn,const double & easeOut)255 bool setKeyframe(const TDoubleParamP &param, const TDoubleKeyframe &kf,
256                  int frame, const double &easeIn, const double &easeOut) {
257   if (!kf.m_isKeyframe) return false;
258 
259   TDoubleKeyframe kfCopy = kf;
260 
261   kfCopy.m_frame = frame;
262   if (easeIn >= 0.0) kfCopy.m_speedIn = TPointD(-easeIn, kfCopy.m_speedIn.y);
263   if (easeOut >= 0.0) kfCopy.m_speedOut = TPointD(easeOut, kfCopy.m_speedOut.y);
264 
265   param->setKeyframe(kfCopy);
266   return true;
267 }
268 
269 //-----------------------------------------------------------------------------
270 
setkey(const TDoubleParamP & param,int frame)271 void setkey(const TDoubleParamP &param, int frame) {
272   KeyframeSetter setter(param.getPointer(), -1, false);
273   setter.createKeyframe(frame);
274 }
275 
276 //-----------------------------------------------------------------------------
277 
updateUnit(TDoubleParam * param)278 void updateUnit(TDoubleParam *param) {
279   for (int i = 0; i < param->getKeyframeCount(); i++) {
280     TDoubleKeyframe k = param->getKeyframe(i);
281     k.m_value /= Stage::inch;
282     param->setKeyframe(i, k);
283   }
284 }
285 
286 //-----------------------------------------------------------------------------
287 
convertTo4InchCenterUnits(string handle)288 string convertTo4InchCenterUnits(string handle) {
289   // per convenzione un handle del tipo 'a'..'z' utilizza
290   // la vecchia convenzione per i centri (4 inch invece di 8)
291   if (handle.length() == 1 && 'A' <= handle[0] && handle[0] <= 'Z' &&
292       handle[0] != 'B')
293     return string(1, handle[0] + 'a' - 'A');
294   else
295     return handle;
296 }
297 
298 //-----------------------------------------------------------------------------
299 
updateDagPosition(const TPointD & pos,const VersionNumber & tnzVersion)300 TPointD updateDagPosition(const TPointD &pos, const VersionNumber &tnzVersion) {
301   if (tnzVersion < VersionNumber(1, 16)) return TConst::nowhere;
302   return pos;
303 }
304 
305 //-----------------------------------------------------------------------------
306 
307 // Update the passed stage object keyframe and keyframe type specification with
308 // a new keyframe. Returns true if specifications match, false otherwise.
touchEaseAndCompare(const TDoubleKeyframe & kf,TStageObject::Keyframe & stageKf,TDoubleKeyframe::Type & type)309 bool touchEaseAndCompare(const TDoubleKeyframe &kf,
310                          TStageObject::Keyframe &stageKf,
311                          TDoubleKeyframe::Type &type) {
312   bool initialization = (type == TDoubleKeyframe::None);
313 
314   if (initialization) type = kf.m_type;
315 
316   if (kf.m_type != type || (kf.m_type != TDoubleKeyframe::SpeedInOut &&
317                             kf.m_type != TDoubleKeyframe::EaseInOut &&
318                             (kf.m_prevType != TDoubleKeyframe::None &&
319                              kf.m_prevType != TDoubleKeyframe::SpeedInOut &&
320                              kf.m_prevType != TDoubleKeyframe::EaseInOut))) {
321     stageKf.m_easeIn  = -1.0;
322     stageKf.m_easeOut = -1.0;
323 
324     return false;
325   }
326 
327   double easeIn = -kf.m_speedIn.x;
328   if (initialization)
329     stageKf.m_easeIn = easeIn;
330   else if (stageKf.m_easeIn != easeIn)
331     stageKf.m_easeIn = -1.0;
332 
333   double easeOut = kf.m_speedOut.x;
334   if (initialization)
335     stageKf.m_easeOut = easeOut;
336   else if (stageKf.m_easeOut != easeOut)
337     stageKf.m_easeOut = -1.0;
338 
339   return true;
340 }
341 
342 //-----------------------------------------------------------------------------
343 }  // namespace
344 //-----------------------------------------------------------------------------
345 
346 //************************************************************************************************
347 //    TStageObject::LazyData  implementation
348 //************************************************************************************************
349 
LazyData()350 TStageObject::LazyData::LazyData() : m_time(-1.0) {}
351 
352 //************************************************************************************************
353 //    TStageObject  implementation
354 //************************************************************************************************
355 
TStageObject(TStageObjectTree * tree,TStageObjectId id)356 TStageObject::TStageObject(TStageObjectTree *tree, TStageObjectId id)
357     : m_tree(tree)
358     , m_id(id)
359     , m_parent(0)
360     , m_name("")
361     , m_isOpened(false)
362     , m_spline(0)
363     , m_status(XY)
364     , m_x(new TDoubleParam())
365     , m_y(new TDoubleParam())
366     , m_z(new TDoubleParam())
367     , m_so(new TDoubleParam())
368     , m_rot(new TDoubleParam())
369     , m_scalex(new TDoubleParam(1.0))
370     , m_scaley(new TDoubleParam(1.0))
371     , m_scale(new TDoubleParam(1.0))
372     , m_posPath(new TDoubleParam())
373     , m_shearx(new TDoubleParam())
374     , m_sheary(new TDoubleParam())
375     , m_center()
376     , m_offset()
377     , m_cycleEnabled(false)
378     , m_handle("B")
379     , m_parentHandle("B")
380     , m_dagNodePos(TConst::nowhere)
381     , m_camera(0)
382     , m_locked(false)
383     , m_noScaleZ(0)
384     , m_pinnedRangeSet(0)
385     , m_ikflag(0)
386     , m_groupSelector(-1) {
387   // NOTA: per le unita' di misura controlla anche tooloptions.cpp
388   m_x->setName("W_X");
389   m_x->setMeasureName("length.x");
390   m_x->addObserver(this);
391 
392   m_y->setName("W_Y");
393   m_y->setMeasureName("length.y");
394   m_y->addObserver(this);
395 
396   m_z->setName("W_Z");
397   m_z->setMeasureName(id.isCamera() ? "zdepth.cam" : "zdepth");
398   m_z->addObserver(this);
399 
400   m_so->setName("W_SO");
401   m_so->addObserver(this);
402 
403   m_rot->setName("W_Rotation");
404   m_rot->setMeasureName("angle");
405   m_rot->addObserver(this);
406 
407   m_scalex->setName("W_ScaleH");
408   m_scalex->setMeasureName("scale");
409   m_scalex->addObserver(this);
410 
411   m_scaley->setName("W_ScaleV");
412   m_scaley->setMeasureName("scale");
413   m_scaley->addObserver(this);
414 
415   m_scale->setName("W_Scale");
416   m_scale->setMeasureName("scale");
417   m_scale->addObserver(this);
418 
419   m_shearx->setName("W_ShearH");
420   m_shearx->setMeasureName("shear");
421   m_shearx->addObserver(this);
422 
423   m_sheary->setName("W_ShearV");
424   m_sheary->setMeasureName("shear");
425   m_sheary->addObserver(this);
426 
427   m_posPath->setName("posPath");
428   m_posPath->setMeasureName("percentage2");
429   m_posPath->addObserver(this);
430 
431   m_tree->setGrammar(m_x);
432   m_tree->setGrammar(m_y);
433   m_tree->setGrammar(m_z);
434   m_tree->setGrammar(m_so);
435   m_tree->setGrammar(m_rot);
436   m_tree->setGrammar(m_scalex);
437   m_tree->setGrammar(m_scaley);
438   m_tree->setGrammar(m_scale);
439   m_tree->setGrammar(m_shearx);
440   m_tree->setGrammar(m_sheary);
441   m_tree->setGrammar(m_posPath);
442 
443   if (id.isCamera()) m_camera = new TCamera();
444 
445   m_pinnedRangeSet = new TPinnedRangeSet();
446 }
447 
448 //-----------------------------------------------------------------------------
449 
~TStageObject()450 TStageObject::~TStageObject() {
451   if (m_spline) {
452     if (m_posPath) m_spline->removeParam(m_posPath.getPointer());
453     m_spline->release();
454   }
455 
456   if (m_x) m_x->removeObserver(this);
457   if (m_y) m_y->removeObserver(this);
458   if (m_z) m_z->removeObserver(this);
459   if (m_so) m_so->removeObserver(this);
460   if (m_rot) m_rot->removeObserver(this);
461   if (m_scalex) m_scalex->removeObserver(this);
462   if (m_scaley) m_scaley->removeObserver(this);
463   if (m_scale) m_scale->removeObserver(this);
464   if (m_shearx) m_shearx->removeObserver(this);
465   if (m_sheary) m_sheary->removeObserver(this);
466   if (m_posPath) m_posPath->removeObserver(this);
467 
468   if (m_skeletonDeformation) {
469     PlasticDeformerStorage::instance()->releaseDeformationData(
470         m_skeletonDeformation.getPointer());
471     m_skeletonDeformation->removeObserver(this);
472   }
473 
474   delete m_camera;
475   delete m_pinnedRangeSet;
476 }
477 
478 //-----------------------------------------------------------------------------
479 
lazyData() const480 const TStageObject::LazyData &TStageObject::lazyData() const {
481   return m_lazyData([this](LazyData &ld) { this->update(ld); });
482 }
483 
484 //-----------------------------------------------------------------------------
485 
lazyData()486 TStageObject::LazyData &TStageObject::lazyData() {
487   return const_cast<LazyData &>(
488       static_cast<const TStageObject &>(*this).lazyData());
489 }
490 
491 //-----------------------------------------------------------------------------
492 
update(LazyData & ld) const493 void TStageObject::update(LazyData &ld) const {
494   if (ld.m_time >= 0.0) invalidate(ld);
495 
496   updateKeyframes(ld);
497 }
498 
499 //-----------------------------------------------------------------------------
500 
onChange(const class TParamChange & c)501 void TStageObject::onChange(const class TParamChange &c) {
502   // Rationale: Since a stage object holds many parameters (or par references),
503   // it may receive multiple notifications at the same time - but it should
504   // actually refresh its data only ONCE for 'em all.
505 
506   // Even worse, the stage object may be notified for EACH touched key of just
507   // one of its parameters. This means this function gets called A LOT.
508 
509   // Thus, we're just SCHEDULING for a data refresh. The actual refresh happens
510   // whenever the scheduled data is accessed.
511 
512   if (c.m_keyframeChanged)
513     m_lazyData.invalidate();  // Both invalidate placement AND keyframes
514   else
515     invalidate();  // Invalidate placement only
516 }
517 
518 //-----------------------------------------------------------------------------
519 
getId() const520 TStageObjectId TStageObject::getId() const { return m_id; }
521 
522 //-----------------------------------------------------------------------------
523 
paramsTime(double t) const524 double TStageObject::paramsTime(double t) const {
525   const KeyframeMap &keyframes = lazyData().m_keyframes;
526 
527   if (m_cycleEnabled && keyframes.size() > 1) {
528     int firstT = keyframes.begin()->first;
529     if (t <= firstT) return t;
530     int lastT  = keyframes.rbegin()->first;
531     int tRange = lastT - firstT + 1;
532     assert(tRange > 0);
533     int it    = tfloor(t);
534     double ft = t - it;
535     return firstT + ((it - firstT) % tRange) + ft;
536   } else
537     return t;
538 }
539 
540 //-----------------------------------------------------------------------------
541 
setName(const std::string & name)542 void TStageObject::setName(const std::string &name) {
543   m_name = (name == m_id.toString()) ? std::string() : name;
544 }
545 
546 //-----------------------------------------------------------------------------
547 
getName() const548 string TStageObject::getName() const {
549   if (m_name != "") return m_name;
550   if (!m_id.isColumn()) return m_id.toString();
551   return "Col" + std::to_string(m_id.getIndex() + 1);
552 }
553 
554 //-----------------------------------------------------------------------------
555 
getFullName() const556 string TStageObject::getFullName() const {
557   string name = getName();
558   if (m_id.isColumn()) {
559     if (name.find("Col") == 0 && name.length() > 3 &&
560         name.find_first_not_of("0123456789", 3) == string::npos)
561       return name;
562     else
563       return name + " (" + std::to_string(m_id.getIndex() + 1) + ")";
564   } else
565     return name;
566 }
567 
568 //-----------------------------------------------------------------------------
569 
setParent(const TStageObjectId & parentId)570 void TStageObject::setParent(const TStageObjectId &parentId) {
571   assert(m_tree);
572   TStageObject *newParent = 0;
573   if (parentId != TStageObjectId::NoneId) {
574     newParent = m_tree->getStageObject(parentId);
575     assert(newParent);
576 
577     // cerco di evitare i cicli
578     TStageObject *p = newParent;
579     while (p->m_parent) {
580       if (p->m_parent->getId() == getId()) return;
581       p = p->m_parent;
582     }
583   } else {
584     if (!m_id.isCamera() && !m_id.isTable()) {
585       newParent = m_tree->getStageObject(TStageObjectId::TableId);
586       assert(newParent);
587     }
588   }
589 
590   if (m_parent) m_parent->m_children.remove(this);
591 
592   m_parent = newParent;
593   if (m_parent) m_parent->m_children.insert(m_parent->m_children.end(), this);
594   invalidate();
595 
596 #ifndef NDEBUG
597   if (m_id.isCamera()) {
598   } else if (m_id.isTable()) {
599     assert(m_parent == 0);
600   } else if (m_id.isColumn()) {
601     assert(m_parent &&
602            (m_parent->m_id.isTable() || m_parent->m_id.isColumn() ||
603             m_parent->m_id.isPegbar() || m_parent->m_id.isCamera()));
604   } else if (m_id.isPegbar()) {
605     assert(m_parent && (m_parent->m_id.isTable() || m_parent->m_id.isCamera() ||
606                         m_parent->m_id.isPegbar()));
607   } else {
608     assert(0);
609   }
610 #endif
611 }
612 
613 //-----------------------------------------------------------------------------
614 
detachFromParent()615 void TStageObject::detachFromParent() {
616   if (m_parent) m_parent->m_children.remove(this);
617   m_parent = 0;
618   invalidate();
619 }
620 
621 //-----------------------------------------------------------------------------
622 
attachChildrenToParent(const TStageObjectId & parentId)623 void TStageObject::attachChildrenToParent(const TStageObjectId &parentId) {
624   while (!m_children.empty()) {
625     TStageObject *son = *m_children.begin();
626     if (son) son->setParent(parentId);
627   }
628 }
629 
630 //-----------------------------------------------------------------------------
631 
getParent() const632 TStageObjectId TStageObject::getParent() const {
633   return m_parent ? m_parent->m_id : TStageObjectId();
634 }
635 
636 //-----------------------------------------------------------------------------
637 
isAncestor(TStageObject * stageObject) const638 bool TStageObject::isAncestor(TStageObject *stageObject) const {
639   if (!stageObject) return false;
640   if (stageObject == (TStageObject *)m_parent)
641     return true;
642   else if (m_parent == 0)
643     return false;
644   else
645     return m_parent->isAncestor(stageObject);
646 }
647 
648 //-----------------------------------------------------------------------------
649 
getSpline() const650 TStageObjectSpline *TStageObject::getSpline() const { return m_spline; }
651 
652 //-----------------------------------------------------------------------------
653 
doSetSpline(TStageObjectSpline * spline)654 void TStageObject::doSetSpline(TStageObjectSpline *spline) {
655   TDoubleParam *param = m_posPath.getPointer();
656   bool uppkEnabled    = isUppkEnabled();
657   if (!spline) {
658     if (uppkEnabled && m_spline) m_spline->removeParam(param);
659     if (m_spline) m_spline->release();
660     m_spline = 0;
661     enablePath(false);
662   } else {
663     if (m_spline != spline) {
664       if (m_spline && uppkEnabled) m_spline->removeParam(param);
665       if (m_spline) m_spline->release();
666       m_spline = spline;
667       m_spline->addRef();
668       if (m_spline && uppkEnabled) m_spline->addParam(param);
669     }
670     if (!isPathEnabled()) enablePath(true);
671   }
672 }
673 
674 //-----------------------------------------------------------------------------
675 
setSpline(TStageObjectSpline * spline)676 void TStageObject::setSpline(TStageObjectSpline *spline) {
677   doSetSpline(spline);
678   TNotifier::instance()->notify(TXsheetChange());
679   TNotifier::instance()->notify(TStageChange());
680   invalidate();
681 }
682 
683 //-----------------------------------------------------------------------------
684 
setStatus(Status status)685 void TStageObject::setStatus(Status status) {
686   if (m_status == status) return;
687   bool oldPathEnabled = isPathEnabled();
688   bool oldUppkEnabled = isUppkEnabled();
689   m_status            = status;
690   bool pathEnabled    = isPathEnabled();
691   bool uppkEnabled    = isUppkEnabled();
692 
693   if (pathEnabled) {
694     if (!m_spline)
695       doSetSpline(m_tree->createSpline());
696     else if (oldUppkEnabled != uppkEnabled) {
697       TDoubleParam *param = getParam(T_Path);
698       if (uppkEnabled)
699         m_spline->addParam(param);
700       else
701         m_spline->removeParam(param);
702     }
703   } else {
704     doSetSpline(0);
705   }
706   invalidate();
707 }
708 
709 //-----------------------------------------------------------------------------
710 
enableAim(bool enabled)711 void TStageObject::enableAim(bool enabled) {
712   setStatus((Status)((m_status & ~STATUS_MASK) | (enabled ? PATH_AIM : PATH)));
713 }
714 
715 //-----------------------------------------------------------------------------
716 
enablePath(bool enabled)717 void TStageObject::enablePath(bool enabled) {
718   if (isPathEnabled() != enabled) setStatus(enabled ? PATH : XY);
719 }
720 
721 //-----------------------------------------------------------------------------
722 
enableUppk(bool enabled)723 void TStageObject::enableUppk(bool enabled) {
724   assert(isPathEnabled());
725   setStatus((Status)((m_status & ~UPPK_MASK) | (enabled ? UPPK_MASK : 0)));
726 }
727 
728 //-----------------------------------------------------------------------------
729 
setCenter(double frame,const TPointD & center)730 void TStageObject::setCenter(double frame, const TPointD &center) {
731   TPointD c = center - getHandlePos(m_handle, (int)frame);
732 
733   TAffine aff   = computeLocalPlacement(frame);
734   TPointD delta = aff * c - aff * m_center;
735   m_center      = c;
736   m_offset += delta;
737   invalidate();
738 }
739 
740 //-----------------------------------------------------------------------------
741 
getCenter(double frame) const742 TPointD TStageObject::getCenter(double frame) const {
743   return m_center + getHandlePos(m_handle, (int)frame);
744 }
745 
746 //-----------------------------------------------------------------------------
747 
getOffset() const748 TPointD TStageObject::getOffset() const { return m_offset; }
749 
750 //-----------------------------------------------------------------------------
751 
setOffset(const TPointD & off)752 void TStageObject::setOffset(const TPointD &off) {
753   m_offset = off;
754   invalidate();
755 }
756 
757 //-----------------------------------------------------------------------------
758 
getCenterAndOffset(TPointD & center,TPointD & offset) const759 void TStageObject::getCenterAndOffset(TPointD &center, TPointD &offset) const {
760   center = m_center;
761   offset = m_offset;
762 }
763 
764 //-----------------------------------------------------------------------------
765 
setCenterAndOffset(const TPointD & center,const TPointD & offset)766 void TStageObject::setCenterAndOffset(const TPointD &center,
767                                       const TPointD &offset) {
768   m_center = center;
769   m_offset = offset;
770   invalidate();
771 }
772 
773 //-----------------------------------------------------------------------------
774 
setHandle(const std::string & s)775 void TStageObject::setHandle(const std::string &s) {
776   m_handle = s;
777   if (!s.empty() && s[0] == 'H') m_offset = m_center = TPointD();
778 
779   invalidate();
780 }
781 
782 //-----------------------------------------------------------------------------
783 
setParentHandle(const std::string & s)784 void TStageObject::setParentHandle(const std::string &s) {
785   m_parentHandle = s;
786   invalidate();
787 }
788 
789 //-----------------------------------------------------------------------------
790 
getHandlePos(string handle,int row) const791 TPointD TStageObject::getHandlePos(string handle, int row) const {
792   double unit = 8;
793   if (handle == "")
794     return TPointD();
795   else if (handle.length() > 1 && handle[0] == 'H')
796     return m_tree->getHandlePos(m_id, handle, row);
797   else if (handle.length() == 1 && 'A' <= handle[0] && handle[0] <= 'Z')
798     return TPointD(unit * (handle[0] - 'B'), 0);
799   else if (handle.length() == 1 && 'a' <= handle[0] && handle[0] <= 'z')
800     return TPointD(0.5 * unit * (handle[0] - 'b'), 0);
801   else
802     return TPointD(0, 0);
803 }
804 
805 //-----------------------------------------------------------------------------
806 
isKeyframe(int frame) const807 bool TStageObject::isKeyframe(int frame) const {
808   const KeyframeMap &keyframes = lazyData().m_keyframes;
809   return keyframes.find(frame) != keyframes.end();
810 }
811 
812 //-----------------------------------------------------------------------------
813 
is52FullKeyframe(int frame) const814 bool TStageObject::is52FullKeyframe(int frame) const {
815   return m_rot->isKeyframe(frame) && m_x->isKeyframe(frame) &&
816          m_y->isKeyframe(frame) && m_z->isKeyframe(frame) &&
817          m_posPath->isKeyframe(frame) && m_scalex->isKeyframe(frame) &&
818          m_scaley->isKeyframe(frame) && m_shearx->isKeyframe(frame) &&
819          m_sheary->isKeyframe(frame);
820 }
821 
822 //-----------------------------------------------------------------------------
823 
isFullKeyframe(int frame) const824 bool TStageObject::isFullKeyframe(int frame) const {
825   return m_rot->isKeyframe(frame) && m_x->isKeyframe(frame) &&
826          m_y->isKeyframe(frame) && m_z->isKeyframe(frame) &&
827          m_so->isKeyframe(frame) && m_posPath->isKeyframe(frame) &&
828          m_scalex->isKeyframe(frame) && m_scaley->isKeyframe(frame) &&
829          m_scale->isKeyframe(frame) && m_shearx->isKeyframe(frame) &&
830          m_sheary->isKeyframe(frame);
831 }
832 
833 //-----------------------------------------------------------------------------
834 
getKeyframe(int frame) const835 TStageObject::Keyframe TStageObject::getKeyframe(int frame) const {
836   const KeyframeMap &keyframes = lazyData().m_keyframes;
837 
838   std::map<int, TStageObject::Keyframe>::const_iterator it;
839   it = keyframes.find(frame);
840   if (it == keyframes.end()) {
841     TStageObject::Keyframe k;
842     k.m_channels[TStageObject::T_Angle]  = m_rot->getValue(frame);
843     k.m_channels[TStageObject::T_X]      = m_x->getValue(frame);
844     k.m_channels[TStageObject::T_Y]      = m_y->getValue(frame);
845     k.m_channels[TStageObject::T_Z]      = m_z->getValue(frame);
846     k.m_channels[TStageObject::T_SO]     = m_so->getValue(frame);
847     k.m_channels[TStageObject::T_ScaleX] = m_scalex->getValue(frame);
848     k.m_channels[TStageObject::T_ScaleY] = m_scaley->getValue(frame);
849     k.m_channels[TStageObject::T_Scale]  = m_scale->getValue(frame);
850     k.m_channels[TStageObject::T_Path]   = m_posPath->getValue(frame);
851     k.m_channels[TStageObject::T_ShearX] = m_shearx->getValue(frame);
852     k.m_channels[TStageObject::T_ShearY] = m_sheary->getValue(frame);
853 
854     if (m_skeletonDeformation)
855       m_skeletonDeformation->getKeyframeAt(frame, k.m_skeletonKeyframe);
856 
857     k.m_isKeyframe = false;
858     return k;
859   } else
860     return it->second;
861 }
862 
863 //-----------------------------------------------------------------------------
864 
setKeyframeWithoutUndo(int frame,const TStageObject::Keyframe & k)865 void TStageObject::setKeyframeWithoutUndo(int frame,
866                                           const TStageObject::Keyframe &k) {
867   KeyframeMap &keyframes = lazyData().m_keyframes;
868 
869   bool keyWasSet = false;
870   keyWasSet = ::setKeyframe(m_rot, k.m_channels[TStageObject::T_Angle], frame,
871                             k.m_easeIn, k.m_easeOut) ||
872               keyWasSet;
873   keyWasSet = ::setKeyframe(m_x, k.m_channels[TStageObject::T_X], frame,
874                             k.m_easeIn, k.m_easeOut) ||
875               keyWasSet;
876   keyWasSet = ::setKeyframe(m_y, k.m_channels[TStageObject::T_Y], frame,
877                             k.m_easeIn, k.m_easeOut) ||
878               keyWasSet;
879   keyWasSet = ::setKeyframe(m_z, k.m_channels[TStageObject::T_Z], frame,
880                             k.m_easeIn, k.m_easeOut) ||
881               keyWasSet;
882   keyWasSet = ::setKeyframe(m_so, k.m_channels[TStageObject::T_SO], frame,
883                             k.m_easeIn, k.m_easeOut) ||
884               keyWasSet;
885   keyWasSet = ::setKeyframe(m_posPath, k.m_channels[TStageObject::T_Path],
886                             frame, k.m_easeIn, k.m_easeOut) ||
887               keyWasSet;
888   keyWasSet = ::setKeyframe(m_scalex, k.m_channels[TStageObject::T_ScaleX],
889                             frame, k.m_easeIn, k.m_easeOut) ||
890               keyWasSet;
891   keyWasSet = ::setKeyframe(m_scaley, k.m_channels[TStageObject::T_ScaleY],
892                             frame, k.m_easeIn, k.m_easeOut) ||
893               keyWasSet;
894   keyWasSet = ::setKeyframe(m_scale, k.m_channels[TStageObject::T_Scale], frame,
895                             k.m_easeIn, k.m_easeOut) ||
896               keyWasSet;
897   keyWasSet = ::setKeyframe(m_shearx, k.m_channels[TStageObject::T_ShearX],
898                             frame, k.m_easeIn, k.m_easeOut) ||
899               keyWasSet;
900   keyWasSet = ::setKeyframe(m_sheary, k.m_channels[TStageObject::T_ShearY],
901                             frame, k.m_easeIn, k.m_easeOut) ||
902               keyWasSet;
903 
904   if (m_skeletonDeformation)
905     keyWasSet = m_skeletonDeformation->setKeyframe(k.m_skeletonKeyframe, frame,
906                                                    k.m_easeIn, k.m_easeOut) ||
907                 keyWasSet;
908 
909   if (keyWasSet) keyframes[frame] = k;
910 
911   invalidate();
912 }
913 
914 //-----------------------------------------------------------------------------
915 
setKeyframeWithoutUndo(int frame)916 void TStageObject::setKeyframeWithoutUndo(int frame) {
917   if (isFullKeyframe(frame)) return;
918 
919   setkey(m_x, frame);
920   setkey(m_y, frame);
921   setkey(m_z, frame);
922   setkey(m_so, frame);
923   setkey(m_posPath, frame);
924   setkey(m_rot, frame);
925   setkey(m_scalex, frame);
926   setkey(m_scaley, frame);
927   setkey(m_scale, frame);
928   setkey(m_shearx, frame);
929   setkey(m_sheary, frame);
930 
931   // Plastic keys are currently not *created* by xsheet commands.
932 
933   /*if(m_skeletonDeformation)
934 {
935 const PlasticSkeleton* skeleton = m_skeletonDeformation->skeleton();
936 const tcg::list<PlasticSkeleton::vertex_type>& vertices = skeleton->vertices();
937 
938 tcg::list<PlasticSkeleton::vertex_type>::const_iterator vt,
939 vEnd(vertices.end());
940 for(vt = vertices.begin(); vt != vertices.end(); ++vt)
941 {
942 SkVD* vd = m_skeletonDeformation->vertexDeformation(vt->name());
943 assert(vd);
944 
945 for(int p=0; p<SkVD::PARAMS_COUNT; ++p)
946   setkey(vd->m_params[p], frame);
947 }
948 }*/
949 }
950 
951 //-----------------------------------------------------------------------------
952 
removeKeyframeWithoutUndo(int frame)953 void TStageObject::removeKeyframeWithoutUndo(int frame) {
954   KeyframeMap &keyframes = lazyData().m_keyframes;
955   double &time           = lazyData().m_time;
956 
957   if (!isKeyframe(frame)) return;
958 
959   keyframes.erase(frame);
960   m_rot->deleteKeyframe(frame);
961   m_x->deleteKeyframe(frame);
962   m_y->deleteKeyframe(frame);
963   m_z->deleteKeyframe(frame);
964   m_so->deleteKeyframe(frame);
965   m_scalex->deleteKeyframe(frame);
966   m_scaley->deleteKeyframe(frame);
967   m_scale->deleteKeyframe(frame);
968   m_posPath->deleteKeyframe(frame);
969   m_shearx->deleteKeyframe(frame);
970   m_sheary->deleteKeyframe(frame);
971 
972   if (m_skeletonDeformation) m_skeletonDeformation->deleteKeyframe(frame);
973 
974   time = -1;
975   if ((int)keyframes.size() < 2) m_cycleEnabled = false;
976 
977   invalidate();
978 }
979 
980 //-----------------------------------------------------------------------------
981 
moveKeyframe(int dst,int src)982 bool TStageObject::moveKeyframe(int dst, int src) {
983   assert(dst != src);
984   if (isKeyframe(dst) || !isKeyframe(src)) return false;
985   setKeyframeWithoutUndo(dst, getKeyframe(src));
986   removeKeyframeWithoutUndo(src);
987   assert(isKeyframe(dst));
988   assert(!isKeyframe(src));
989   invalidate();
990   return true;
991 }
992 
993 //-----------------------------------------------------------------------------
994 
canMoveKeyframes(std::set<int> & frames,int delta)995 bool TStageObject::canMoveKeyframes(std::set<int> &frames, int delta) {
996   if (delta == 0) return false;
997   std::set<int>::iterator it;
998   for (it = frames.begin(); it != frames.end(); ++it) {
999     int f = *it;
1000     if (!isKeyframe(f)) return false;
1001     f += delta;
1002     if (f < 0) return false;
1003     if (frames.find(f) == frames.end() && isKeyframe(f)) return false;
1004   }
1005   return true;
1006 }
1007 
1008 //-----------------------------------------------------------------------------
1009 
moveKeyframes(std::set<int> & frames,int delta)1010 bool TStageObject::moveKeyframes(std::set<int> &frames, int delta) {
1011   if (!canMoveKeyframes(frames, delta)) return false;
1012   if (delta < 0) {
1013     std::set<int>::iterator it;
1014     for (it = frames.begin(); it != frames.end(); ++it) {
1015       bool ret = moveKeyframe(*it + delta, *it);
1016       assert(ret);
1017     }
1018   } else {
1019     std::set<int>::reverse_iterator ti;
1020     for (ti = frames.rbegin(); ti != frames.rend(); ++ti) {
1021       bool ret = moveKeyframe(*ti + delta, *ti);
1022       assert(ret);
1023     }
1024   }
1025   return true;
1026 }
1027 
1028 //-----------------------------------------------------------------------------
1029 
getKeyframes(KeyframeMap & keyframes) const1030 void TStageObject::getKeyframes(KeyframeMap &keyframes) const {
1031   keyframes = lazyData().m_keyframes;
1032 }
1033 
1034 //-----------------------------------------------------------------------------
1035 
getKeyframeRange(int & r0,int & r1) const1036 bool TStageObject::getKeyframeRange(int &r0, int &r1) const {
1037   const KeyframeMap &keyframes = lazyData().m_keyframes;
1038 
1039   if (keyframes.empty()) {
1040     r0 = 0;
1041     r1 = -1;
1042     return false;
1043   }
1044   r0 = keyframes.begin()->first;
1045   r1 = keyframes.rbegin()->first;
1046 
1047   return true;
1048 }
1049 
1050 //-----------------------------------------------------------------------------
1051 
getKeyframeSpan(int row,int & r0,double & ease0,int & r1,double & ease1) const1052 bool TStageObject::getKeyframeSpan(int row, int &r0, double &ease0, int &r1,
1053                                    double &ease1) const {
1054   const KeyframeMap &keyframes = lazyData().m_keyframes;
1055 
1056   KeyframeMap::const_iterator it = keyframes.lower_bound(row);
1057   if (it == keyframes.end() || it == keyframes.begin() || it->first == row) {
1058     r0    = 0;
1059     r1    = -1;
1060     ease0 = ease1 = 0;
1061     return false;
1062   }
1063   r1    = it->first;
1064   ease1 = it->second.m_easeIn;
1065   --it;
1066   r0    = it->first;
1067   ease0 = it->second.m_easeOut;
1068 
1069   return true;
1070 }
1071 
1072 //-----------------------------------------------------------------------------
1073 
setParam(Channel type,double frame,double val)1074 void TStageObject::setParam(Channel type, double frame, double val) {
1075   assert(0);
1076 }
1077 
1078 //-----------------------------------------------------------------------------
1079 
getParam(Channel type,double frame) const1080 double TStageObject::getParam(Channel type, double frame) const {
1081   switch (type) {
1082   case T_Angle:
1083     return m_rot->getValue(frame);
1084   case T_X:
1085     return m_x->getValue(frame);
1086   case T_Y:
1087     return m_y->getValue(frame);
1088   case T_Z:
1089     return m_z->getValue(frame);
1090   case T_SO:
1091     return m_so->getValue(frame);
1092   case T_ScaleX:
1093     return m_scalex->getValue(frame);
1094   case T_ScaleY:
1095     return m_scaley->getValue(frame);
1096   case T_Scale:
1097     return m_scale->getValue(frame);
1098   case T_Path:
1099     return m_posPath->getValue(frame);
1100   case T_ShearX:
1101     return m_shearx->getValue(frame);
1102   case T_ShearY:
1103     return m_sheary->getValue(frame);
1104 
1105   default:
1106     assert(false);
1107     return 0;
1108   }
1109 }
1110 
1111 //-----------------------------------------------------------------------------
1112 
getParam(Channel channel) const1113 TDoubleParam *TStageObject::getParam(Channel channel) const {
1114   switch (channel) {
1115   case T_X:
1116     return m_x.getPointer();
1117   case T_Y:
1118     return m_y.getPointer();
1119   case T_Z:
1120     return m_z.getPointer();
1121   case T_SO:
1122     return m_so.getPointer();
1123   case T_Angle:
1124     return m_rot.getPointer();
1125   case T_Path:
1126     return m_posPath.getPointer();
1127   case T_ScaleX:
1128     return m_scalex.getPointer();
1129   case T_ScaleY:
1130     return m_scaley.getPointer();
1131   case T_Scale:
1132     return m_scale.getPointer();
1133   case T_ShearX:
1134     return m_shearx.getPointer();
1135   case T_ShearY:
1136     return m_sheary.getPointer();
1137   default:
1138     return 0;
1139   }
1140 }
1141 
1142 //-----------------------------------------------------------------------------
1143 
getPlasticSkeletonDeformation() const1144 PlasticSkeletonDeformationP TStageObject::getPlasticSkeletonDeformation()
1145     const {
1146   return m_skeletonDeformation;
1147 }
1148 
1149 //-----------------------------------------------------------------------------
1150 
setPlasticSkeletonDeformation(const PlasticSkeletonDeformationP & sd)1151 void TStageObject::setPlasticSkeletonDeformation(
1152     const PlasticSkeletonDeformationP &sd) {
1153   if (m_skeletonDeformation == sd) return;
1154 
1155   if (m_skeletonDeformation) {
1156     PlasticDeformerStorage::instance()->releaseDeformationData(
1157         m_skeletonDeformation.getPointer());
1158 
1159     m_skeletonDeformation->setGrammar(0);
1160     m_skeletonDeformation->removeObserver(this);
1161   }
1162 
1163   m_skeletonDeformation = sd;
1164 
1165   if (m_skeletonDeformation) {
1166     m_skeletonDeformation->setGrammar(m_tree->getGrammar());
1167     m_skeletonDeformation->addObserver(this);
1168   }
1169 }
1170 
1171 //-----------------------------------------------------------------------------
1172 
clone()1173 TStageObject *TStageObject::clone() {
1174   assert(m_tree);
1175   TStageObjectId pegId    = getId();
1176   TStageObjectId newPegId = TStageObjectId::NoneId;
1177   int newIndex            = pegId.getIndex();
1178   if (pegId.isCamera()) {
1179     while ((m_tree->getStageObject(TStageObjectId::CameraId(newIndex), false) !=
1180             0L) ||
1181            (pegId.getIndex() == newIndex))
1182       ++newIndex;
1183     newPegId = TStageObjectId::CameraId(newIndex);
1184   } else if (pegId.isColumn()) {
1185     while ((m_tree->getStageObject(TStageObjectId::ColumnId(newIndex), false) !=
1186             0L) ||
1187            (pegId.getIndex() == newIndex))
1188       ++newIndex;
1189     newPegId = TStageObjectId::ColumnId(newIndex);
1190   } else if (pegId.isPegbar()) {
1191     while ((m_tree->getStageObject(TStageObjectId::PegbarId(newIndex), false) !=
1192             0L) ||
1193            (pegId.getIndex() == newIndex))
1194       ++newIndex;
1195     newPegId = TStageObjectId::PegbarId(newIndex);
1196   } else {
1197     assert(!"Unknown stage object type");
1198     return 0L;
1199   }
1200   assert(newPegId != TStageObjectId::NoneId);
1201   assert(newIndex >= 0);
1202   assert(newPegId.getIndex() != pegId.getIndex());
1203 
1204   // aggiunge lo stage object clonato nel stage object tree
1205   TStageObject *clonedPeg = m_tree->getStageObject(newPegId, true);
1206   TStageObject *cloned    = clonedPeg;
1207   assert(cloned);
1208   assert(cloned->m_tree == m_tree);
1209 
1210   KeyframeMap &keyframes       = lazyData().m_keyframes;
1211   KeyframeMap &clonedKeyframes = cloned->lazyData().m_keyframes;
1212 
1213   std::map<int, TStageObject::Keyframe>::iterator itKf = keyframes.begin();
1214   for (; itKf != keyframes.end(); ++itKf) {
1215     clonedKeyframes.insert(make_pair(itKf->first, itKf->second));
1216   }
1217   cloned->m_cycleEnabled    = m_cycleEnabled;
1218   cloned->lazyData().m_time = lazyData().m_time;
1219   cloned->m_localPlacement  = m_localPlacement;
1220   cloned->m_absPlacement    = m_absPlacement;
1221   cloned->m_status          = m_status;
1222   cloned->doSetSpline(m_spline);
1223 
1224   cloned->m_x       = static_cast<TDoubleParam *>(m_x->clone());
1225   cloned->m_y       = static_cast<TDoubleParam *>(m_y->clone());
1226   cloned->m_z       = static_cast<TDoubleParam *>(m_z->clone());
1227   cloned->m_so      = static_cast<TDoubleParam *>(m_so->clone());
1228   cloned->m_rot     = static_cast<TDoubleParam *>(m_rot->clone());
1229   cloned->m_scalex  = static_cast<TDoubleParam *>(m_scalex->clone());
1230   cloned->m_scaley  = static_cast<TDoubleParam *>(m_scaley->clone());
1231   cloned->m_scale   = static_cast<TDoubleParam *>(m_scale->clone());
1232   cloned->m_posPath = static_cast<TDoubleParam *>(m_posPath->clone());
1233   cloned->m_shearx  = static_cast<TDoubleParam *>(m_shearx->clone());
1234   cloned->m_sheary  = static_cast<TDoubleParam *>(m_sheary->clone());
1235 
1236   if (m_skeletonDeformation)
1237     cloned->m_skeletonDeformation =
1238         new PlasticSkeletonDeformation(*m_skeletonDeformation);
1239 
1240   cloned->m_noScaleZ   = m_noScaleZ;
1241   cloned->m_center     = m_center;
1242   cloned->m_offset     = m_offset;
1243   cloned->m_name       = m_name;
1244   cloned->m_dagNodePos = m_dagNodePos;
1245 
1246   return cloned;
1247 }
1248 
1249 //-----------------------------------------------------------------------------
1250 
isCycleEnabled() const1251 bool TStageObject::isCycleEnabled() const { return m_cycleEnabled; }
1252 
1253 //-----------------------------------------------------------------------------
1254 
enableCycle(bool on)1255 void TStageObject::enableCycle(bool on) { m_cycleEnabled = on; }
1256 
1257 //-----------------------------------------------------------------------------
1258 
findRoot(double frame) const1259 TStageObject *TStageObject::findRoot(double frame) const {
1260   if (!m_parent) return NULL;
1261 
1262   TStageObject *parent = m_parent;
1263   while (parent->m_parent && parent->lazyData().m_time != frame)
1264     parent = parent->m_parent;
1265 
1266   return parent;
1267 }
1268 
1269 //-----------------------------------------------------------------------------
1270 
getPinnedDescendant(int frame)1271 TStageObject *TStageObject::getPinnedDescendant(int frame) {
1272   if (getPinnedRangeSet()->isPinned(frame)) return this;
1273   for (list<TStageObject *>::iterator it = m_children.begin();
1274        it != m_children.end(); ++it) {
1275     TStageObject *child = *it;
1276     if (child->getPinnedRangeSet()->isPinned(frame)) return child;
1277     TStageObject *pinned = child->getPinnedDescendant(frame);
1278     if (pinned) return pinned;
1279   }
1280   return 0;
1281 }
1282 
1283 //-----------------------------------------------------------------------------
1284 
computeIkRootOffset(int t)1285 TAffine TStageObject::computeIkRootOffset(int t) {
1286   if (m_ikflag > 0) return TAffine();
1287 
1288   // get normal movement (which will be left-multiplied to the IK-part)
1289   setStatus(XY);
1290   invalidate();
1291   TAffine basePlacement = getPlacement(t);
1292   setStatus(IK);
1293   invalidate();
1294 
1295   TStageObject *foot = getPinnedDescendant(t);
1296   if (foot == 0) {
1297     foot = this;
1298     setStatus(XY);
1299   }
1300 
1301   m_ikflag++;
1302   invalidate();
1303 
1304   TAffine placement                   = foot->getPlacement(t).inv();
1305   int t0                              = 0;
1306   const TPinnedRangeSet::Range *range = foot->getPinnedRangeSet()->getRange(t);
1307   if (range) t0 = range->first;
1308   while (t0 > 0) {
1309     TStageObject *oldFoot = getPinnedDescendant(t0 - 1);
1310     if (oldFoot == 0) break;  // oldFoot = this;
1311     assert(oldFoot != foot);
1312     TAffine changeFootAff =
1313         oldFoot->getPlacement(t0).inv() * foot->getPlacement(t0);
1314     placement = changeFootAff * placement;
1315     foot      = oldFoot;
1316     range     = oldFoot->getPinnedRangeSet()->getRange(t0 - 1);
1317     t0        = 0;
1318     if (range) t0 = range->first;
1319   }
1320   m_ikflag--;
1321   invalidate();
1322 
1323   placement = foot->getPinnedRangeSet()->getPlacement() * placement;
1324 
1325   return basePlacement * placement;
1326 }
1327 
1328 //-----------------------------------------------------------------------------
1329 /*
1330 inline double getPosPathAtCP(const TStroke* path, int cpIndex)
1331 {
1332   int n = path->getControlPointCount();
1333   return path->getLengthAtControlPoint(tcrop(cpIndex*4,0,n-1));
1334 }
1335 
1336 //-----------------------------------------------------------------------------
1337 */
1338 
computeLocalPlacement(double frame)1339 TAffine TStageObject::computeLocalPlacement(double frame) {
1340   frame = paramsTime(frame);
1341 
1342   if (lazyData().m_time != frame) {
1343     double sc  = m_scale->getValue(frame);
1344     double sx  = sc * m_scalex->getValue(frame);
1345     double sy  = sc * m_scaley->getValue(frame);
1346     double ang = m_rot->getValue(frame);
1347     double shx = m_shearx->getValue(frame);
1348     double shy = m_sheary->getValue(frame);
1349 
1350     TPointD position;
1351     double posPath = 0;
1352     switch (m_status & STATUS_MASK) {
1353     case XY:
1354       position.x = m_x->getValue(frame) * Stage::inch;
1355       position.y = m_y->getValue(frame) * Stage::inch;
1356       break;
1357     case PATH:
1358       assert(m_spline);
1359       assert(m_spline->getStroke());
1360       posPath = m_spline->getStroke()->getLength() *
1361                 m_posPath->getValue(frame) * 0.01;
1362       position = m_spline->getStroke()->getPointAtLength(posPath);
1363       break;
1364     case PATH_AIM:
1365       assert(m_spline);
1366       assert(m_spline->getStroke());
1367       posPath = m_spline->getStroke()->getLength() *
1368                 m_posPath->getValue(frame) * 0.01;
1369 
1370       position = m_spline->getStroke()->getPointAtLength(posPath);
1371       if (m_spline->getStroke()->getLength() > 1e-5)
1372         ang +=
1373             rad2degree(atan(m_spline->getStroke()->getSpeedAtLength(posPath)));
1374       break;
1375     case IK:
1376       return computeIkRootOffset(frame);
1377       break;
1378     }
1379 
1380     TAffine shear(1, shx, 0, shy, 1, 0);
1381 
1382     TPointD handlePos = getHandlePos(m_handle, (int)frame);
1383     TPointD center    = (m_center + handlePos) * Stage::inch;
1384 
1385     TPointD pos = m_offset;
1386     if (m_parent) pos += m_parent->getHandlePos(m_parentHandle, (int)frame);
1387     pos = pos * Stage::inch + position;
1388 
1389     m_localPlacement = TTranslation(pos) * makeRotation(ang) * shear *
1390                        TScale(sx, sy) * TTranslation(-center);
1391   }
1392 
1393   return m_localPlacement;
1394 }
1395 
1396 //-----------------------------------------------------------------------------
1397 
getPlacement(double t)1398 TAffine TStageObject::getPlacement(double t) {
1399   double &time = lazyData().m_time;
1400 
1401   if (time == t) return m_absPlacement;
1402   if (time != -1) {
1403     if (!m_parent)
1404       invalidate();
1405     else
1406       findRoot(t)->invalidate();
1407   }
1408 
1409   double tt = paramsTime(t);
1410 
1411   TAffine place;
1412   if (m_parent)
1413     place = m_parent->getPlacement(t) * computeLocalPlacement(tt);
1414   else
1415     place = computeLocalPlacement(tt);
1416   m_absPlacement = place;
1417   time           = t;
1418   return place;
1419 }
1420 
1421 //-----------------------------------------------------------------------------
1422 
getZ(double t)1423 double TStageObject::getZ(double t) {
1424   double tt = paramsTime(t);
1425   if (m_parent)
1426     return m_parent->getZ(t) + m_z->getValue(tt);
1427   else
1428     return m_z->getValue(tt);
1429 }
1430 
1431 //-----------------------------------------------------------------------------
1432 
getSO(double t)1433 double TStageObject::getSO(double t) {
1434   double tt = paramsTime(t);
1435   if (m_parent)
1436     return m_parent->getSO(t) + m_so->getValue(tt);
1437   else
1438     return m_so->getValue(tt);
1439 }
1440 
1441 //-----------------------------------------------------------------------------
1442 
getGlobalNoScaleZ() const1443 double TStageObject::getGlobalNoScaleZ() const {
1444   return m_parent ? m_parent->getGlobalNoScaleZ() + m_noScaleZ : m_noScaleZ;
1445 }
1446 
1447 //-----------------------------------------------------------------------------
1448 
getNoScaleZ() const1449 double TStageObject::getNoScaleZ() const { return m_noScaleZ; }
1450 
1451 //-----------------------------------------------------------------------------
1452 
setNoScaleZ(double noScaleZ)1453 void TStageObject::setNoScaleZ(double noScaleZ) {
1454   if (m_noScaleZ == noScaleZ) return;
1455   m_noScaleZ = noScaleZ;
1456   invalidate();
1457 }
1458 
1459 //-----------------------------------------------------------------------------
1460 
invalidate(LazyData & ld) const1461 void TStageObject::invalidate(LazyData &ld) const {
1462   // Since this is an invalidation function, access to the invalidable data
1463   // should
1464   // not trigger a data update
1465   ld.m_time = -1;
1466 
1467   std::list<TStageObject *>::const_iterator cit = m_children.begin();
1468   for (; cit != m_children.end(); ++cit) (*cit)->invalidate();
1469 }
1470 
1471 //-----------------------------------------------------------------------------
1472 
invalidate()1473 void TStageObject::invalidate() { invalidate(m_lazyData(tcg::direct_access)); }
1474 
1475 //-----------------------------------------------------------------------------
1476 
getParentPlacement(double t) const1477 TAffine TStageObject::getParentPlacement(double t) const {
1478   return m_parent ? m_parent->getPlacement(t) : TAffine();
1479 }
1480 
1481 //-----------------------------------------------------------------------------
1482 
1483 // Rebuild the keyframes map
updateKeyframes(LazyData & ld) const1484 void TStageObject::updateKeyframes(LazyData &ld) const {
1485   KeyframeMap &keyframes = ld.m_keyframes;
1486 
1487   // Clear the map
1488   keyframes.clear();
1489 
1490   // Gather all sensible parameters in a vector
1491   std::vector<TDoubleParam *> params;
1492 
1493   if (m_status == XY) {
1494     params.push_back(m_x.getPointer());
1495     params.push_back(m_y.getPointer());
1496   } else {
1497     params.push_back(m_posPath.getPointer());
1498   }
1499 
1500   params.push_back(m_z.getPointer());
1501   params.push_back(m_so.getPointer());
1502   params.push_back(m_rot.getPointer());
1503   params.push_back(m_scalex.getPointer());
1504   params.push_back(m_scaley.getPointer());
1505   params.push_back(m_scale.getPointer());
1506   params.push_back(m_shearx.getPointer());
1507   params.push_back(m_sheary.getPointer());
1508 
1509   if (m_skeletonDeformation) {
1510     params.push_back(m_skeletonDeformation->skeletonIdsParam().getPointer());
1511 
1512     // Add Plastic Skeleton params too
1513     SkD::vd_iterator vdt, vdEnd;
1514     m_skeletonDeformation->vertexDeformations(vdt, vdEnd);
1515 
1516     for (; vdt != vdEnd; ++vdt) {
1517       const std::pair<const QString *, SkVD *> &vd = *vdt;
1518 
1519       for (int p = 0; p < SkVD::PARAMS_COUNT; ++p)
1520         params.push_back(vd.second->m_params[p].getPointer());
1521     }
1522   }
1523 
1524   // Scan each parameter for a key frame - add each in a set
1525   std::set<int> frames;
1526 
1527   int p, pCount = params.size();
1528   for (p = 0; p < pCount; ++p) {
1529     TDoubleParam *param = params[p];
1530 
1531     int k, kCount = param->getKeyframeCount();
1532     for (k = 0; k < kCount; ++k) {
1533       const TDoubleKeyframe &kf = param->getKeyframe(k);
1534       frames.insert((int)kf.m_frame);
1535     }
1536   }
1537 
1538   // Traverse said set and build a TStageObject keyframe for each found instant
1539 
1540   std::set<int>::iterator ft, fEnd(frames.end());
1541   for (ft = frames.begin(); ft != fEnd; ++ft) {
1542     int f = *ft;
1543 
1544     // Add values
1545     TStageObject::Keyframe stageKf;
1546     stageKf.m_channels[TStageObject::T_Angle]  = m_rot->getKeyframeAt(f);
1547     stageKf.m_channels[TStageObject::T_X]      = m_x->getKeyframeAt(f);
1548     stageKf.m_channels[TStageObject::T_Y]      = m_y->getKeyframeAt(f);
1549     stageKf.m_channels[TStageObject::T_Z]      = m_z->getKeyframeAt(f);
1550     stageKf.m_channels[TStageObject::T_SO]     = m_so->getKeyframeAt(f);
1551     stageKf.m_channels[TStageObject::T_ScaleX] = m_scalex->getKeyframeAt(f);
1552     stageKf.m_channels[TStageObject::T_ScaleY] = m_scaley->getKeyframeAt(f);
1553     stageKf.m_channels[TStageObject::T_Scale]  = m_scale->getKeyframeAt(f);
1554     stageKf.m_channels[TStageObject::T_Path]   = m_posPath->getKeyframeAt(f);
1555     stageKf.m_channels[TStageObject::T_ShearX] = m_shearx->getKeyframeAt(f);
1556     stageKf.m_channels[TStageObject::T_ShearY] = m_sheary->getKeyframeAt(f);
1557 
1558     if (m_skeletonDeformation)
1559       m_skeletonDeformation->getKeyframeAt(f, stageKf.m_skeletonKeyframe);
1560 
1561     stageKf.m_isKeyframe = true;
1562 
1563     // Build the stage keyframe's global ease factors
1564     stageKf.m_easeIn  = -1;
1565     stageKf.m_easeOut = -1;
1566 
1567     TDoubleKeyframe::Type type = TDoubleKeyframe::None;
1568     bool easeOk                = true;
1569 
1570     // Start from analyzing standard channels
1571     for (int c = 0; easeOk && c < T_ChannelCount; ++c) {
1572       const TDoubleKeyframe &kf = stageKf.m_channels[c];
1573       if (!kf.m_isKeyframe) continue;
1574 
1575       easeOk = touchEaseAndCompare(kf, stageKf, type);
1576     }
1577 
1578     // Finally, check the skeleton deformation keyframes
1579     const std::map<QString, SkVD::Keyframe> &vdfs =
1580         stageKf.m_skeletonKeyframe.m_vertexKeyframes;
1581 
1582     std::map<QString, SkVD::Keyframe>::const_iterator vdft, vdfEnd(vdfs.end());
1583     for (vdft = vdfs.begin(); easeOk && vdft != vdfEnd; ++vdft) {
1584       for (int p = 0; p < SkVD::PARAMS_COUNT; ++p) {
1585         const TDoubleKeyframe &kf = vdft->second.m_keyframes[p];
1586         if (!kf.m_isKeyframe) continue;
1587 
1588         easeOk = touchEaseAndCompare(kf, stageKf, type);
1589       }
1590     }
1591 
1592     keyframes[f] = stageKf;
1593   }
1594 }
1595 
1596 //-----------------------------------------------------------------------------
1597 
updateKeyframes()1598 void TStageObject::updateKeyframes() {
1599   return updateKeyframes(m_lazyData(tcg::direct_access));
1600 }
1601 
1602 //-----------------------------------------------------------------------------
1603 
saveData(TOStream & os)1604 void TStageObject::saveData(TOStream &os) {
1605   TStageObjectId parentId = getParent();
1606   std::map<std::string, string> attr;
1607   attr["id"]           = parentId.toString();
1608   attr["handle"]       = m_handle;
1609   attr["parentHandle"] = m_parentHandle;
1610   os.openChild("parent", attr);
1611   os.closeChild();
1612   if (m_name != "") os.child("name") << m_name;
1613   os.child("isOpened") << (int)m_isOpened;
1614   if (isGrouped()) {
1615     os.openChild("groupIds");
1616     int i;
1617     for (i = 0; i < m_groupId.size(); i++) os << m_groupId[i];
1618     os.closeChild();
1619     os.openChild("groupNames");
1620     for (i = 0; i < m_groupName.size(); i++) os << m_groupName[i];
1621     os.closeChild();
1622   }
1623 
1624   m_pinnedRangeSet->saveData(os);
1625 
1626   os.child("center") << m_center.x << m_center.y << -m_offset.x << -m_offset.y;
1627   os.child("status") << (int)m_status;
1628   if (m_noScaleZ != 0) os.child("noScaleZ") << m_noScaleZ;
1629 
1630   if (m_spline) os.child("splinep") << m_spline;
1631 
1632   if (!m_x->isDefault()) os.child("x") << *m_x;
1633   if (!m_y->isDefault()) os.child("y") << *m_y;
1634   if (!m_z->isDefault()) os.child("z") << *m_z;
1635   if (!m_so->isDefault()) os.child("so") << *m_so;
1636   if (!m_scalex->isDefault()) os.child("sx") << *m_scalex;
1637   if (!m_scaley->isDefault()) os.child("sy") << *m_scaley;
1638   if (!m_scale->isDefault()) os.child("sc") << *m_scale;
1639   if (!m_rot->isDefault()) os.child("rot") << *m_rot;
1640   if (!m_posPath->isDefault()) os.child("pos") << *m_posPath;
1641   if (!m_shearx->isDefault()) os.child("shx") << *m_shearx;
1642   if (!m_sheary->isDefault()) os.child("shy") << *m_sheary;
1643   if (m_cycleEnabled) os.child("cycle") << 1;
1644 
1645   if (m_skeletonDeformation) os.child("plasticSD") << *m_skeletonDeformation;
1646 
1647   os.child("nodePos") << m_dagNodePos.x << m_dagNodePos.y;
1648 
1649   if (getId().isCamera()) {
1650     os.openChild("camera");
1651     m_camera->saveData(os);
1652     os.closeChild();
1653 
1654     /*TDimensionD size = m_camera->getSize();
1655 TDimension res = m_camera->getRes();
1656 bool isXPrevalence = m_camera->isXPrevalence();
1657 os.child("cameraSize") << size.lx << size.ly;
1658 os.child("cameraRes") << res.lx << res.ly;
1659 os.child("xPrevalence") << (int)isXPrevalence;*/
1660   }
1661 }
1662 
1663 //-----------------------------------------------------------------------------
1664 
loadData(TIStream & is)1665 void TStageObject::loadData(TIStream &is) {
1666   VersionNumber tnzVersion = is.getVersion();
1667   string tagName;
1668   QList<int> groupIds;
1669   QList<wstring> groupNames;
1670 
1671   KeyframeMap &keyframes = lazyData().m_keyframes;
1672 
1673   while (is.matchTag(tagName)) {
1674     if (tagName == "parent") {
1675       string parentIdStr  = is.getTagAttribute("id");
1676       string handle       = is.getTagAttribute("handle");
1677       string parentHandle = is.getTagAttribute("parentHandle");
1678       if (tnzVersion < VersionNumber(1, 15)) {
1679         handle       = convertTo4InchCenterUnits(handle);
1680         parentHandle = convertTo4InchCenterUnits(parentHandle);
1681       }
1682       if (parentIdStr == "")  // vecchio formato
1683         is >> parentIdStr;
1684       else {
1685       }
1686 
1687       TStageObjectId parentId = toStageObjectId(parentIdStr);
1688       if (m_id != TStageObjectId::NoneId &&
1689           parentId != TStageObjectId::NoneId) {
1690         assert(parentId != m_id);
1691         setParent(parentId);
1692       }
1693       if (handle != "") setHandle(handle);
1694       if (parentHandle != "") setParentHandle(parentHandle);
1695     } else if (tagName == "center") {
1696       is >> m_center.x >> m_center.y >> m_offset.x >> m_offset.y;
1697       m_offset = -m_offset;
1698     } else if (tagName == "name")
1699       is >> m_name;
1700     else if (tagName == "x")
1701       is >> *m_x;
1702     else if (tagName == "y")
1703       is >> *m_y;
1704     else if (tagName == "z")
1705       is >> *m_z;
1706     else if (tagName == "so")
1707       is >> *m_so;
1708     else if (tagName == "rot")
1709       is >> *m_rot;
1710     else if (tagName == "sx")
1711       is >> *m_scalex;
1712     else if (tagName == "sy")
1713       is >> *m_scaley;
1714     else if (tagName == "sc")
1715       is >> *m_scale;
1716     else if (tagName == "shx")
1717       is >> *m_shearx;
1718     else if (tagName == "shy")
1719       is >> *m_sheary;
1720     else if (tagName == "pos")
1721       is >> *m_posPath;
1722     else if (tagName == "posCP") {
1723       TDoubleParam posCP;
1724       is >> posCP;
1725     }  // Ghibli 6.2 release. cfr
1726     else if (tagName == "noScaleZ")
1727       is >> m_noScaleZ;
1728     else if (tagName == "isOpened") {
1729       int v = 0;
1730       is >> v;
1731       m_isOpened = (bool)v;
1732     } else if (tagName == "pinnedStatus") {
1733       m_pinnedRangeSet->loadData(is);
1734     } else if (tagName == "status") {
1735       int v = 0;
1736       is >> v;
1737       m_status = (Status)v;
1738     } else if (tagName == "spline") {
1739       TStageObjectSpline *spline = m_tree->createSpline();
1740       is >> *spline;
1741       m_spline = spline;
1742       m_spline->addRef();
1743     } else if (tagName == "splinep") {
1744       TPersist *p = 0;
1745       is >> p;
1746       m_spline = dynamic_cast<TStageObjectSpline *>(p);
1747       m_tree->insertSpline(m_spline);
1748       m_spline->addRef();
1749     } else if (tagName == "cycle") {
1750       int dummy;
1751       is >> dummy;
1752       m_cycleEnabled = true;
1753     } else if (tagName == "nodePos") {
1754       TPointD pos;
1755       is >> pos.x >> pos.y;
1756       m_dagNodePos = updateDagPosition(pos, tnzVersion);
1757       // is >> m_dagNodePos.x >> m_dagNodePos.y;
1758     }
1759     //***** camera parameters till toonz 6.0 ********
1760     else if (tagName == "cameraSize") {
1761       TDimensionD size(0, 0);
1762       is >> size.lx >> size.ly;
1763       if (m_camera) m_camera->setSize(size);
1764     } else if (tagName == "cameraRes") {
1765       TDimension res(0, 0);
1766       is >> res.lx >> res.ly;
1767       if (m_camera) m_camera->setRes(res);
1768     }
1769     //***** camera parameters toonz 6.1 ******** november 2009
1770     else if (tagName == "camera")
1771       m_camera->loadData(is);
1772     else if (tagName == "groupIds") {
1773       int groupId;
1774       while (!is.eos()) {
1775         is >> groupId;
1776         groupIds.push_back(groupId);
1777       }
1778     } else if (tagName == "groupNames") {
1779       wstring groupName;
1780       while (!is.eos()) {
1781         is >> groupName;
1782         groupNames.push_back(groupName);
1783       }
1784     } else if (tagName == "plasticSD") {
1785       PlasticSkeletonDeformation *sd = new PlasticSkeletonDeformation;
1786       is >> *sd;
1787       setPlasticSkeletonDeformation(sd);
1788     } else
1789       throw TException("TStageObject::loadData. unexpected tag: " + tagName);
1790     is.matchEndTag();
1791   }
1792   if (!groupIds.isEmpty()) {
1793     assert(groupIds.size() == groupNames.size());
1794     int i;
1795     for (i = 0; i < groupIds.size(); i++) {
1796       setGroupId(groupIds[i]);
1797       setGroupName(groupNames[i]);
1798     }
1799   }
1800   if (tnzVersion < VersionNumber(1, 13)) {
1801     updateUnit(m_y.getPointer());
1802     updateUnit(m_x.getPointer());
1803   }
1804   if (tnzVersion < VersionNumber(1, 14)) {
1805     double factor = 1.0 / Stage::inch;
1806     m_center      = m_center * factor;
1807     m_offset      = m_offset * factor;
1808   }
1809   if (tnzVersion < VersionNumber(1, 16) && !keyframes.empty()) {
1810     std::map<int, TStageObject::Keyframe>::iterator itKf = keyframes.begin();
1811     std::set<int> keyframeIndexSet;
1812     for (; itKf != keyframes.end(); itKf++)
1813       if (is52FullKeyframe(itKf->first)) keyframeIndexSet.insert(itKf->first);
1814     std::set<int>::iterator itKfInd = keyframeIndexSet.begin();
1815     for (; itKfInd != keyframeIndexSet.end(); itKfInd++)
1816       setkey(m_scale, *itKfInd);
1817   }
1818   // Calling updateKeyframes() here may cause failure to load expressions
1819   // especially if it refers to a curve which is to be loaded AFTER this
1820   // function while loading scene process. So I will skip it assuming that
1821   // updateKeyframes() will be called when it is actually needed.
1822   // updateKeyframes();
1823   if (m_spline != 0 && isUppkEnabled())
1824     m_spline->addParam(m_posPath.getPointer());
1825   invalidate();
1826 }
1827 
1828 //-----------------------------------------------------------------------------
1829 
getParams() const1830 TStageObjectParams *TStageObject::getParams() const {
1831   TStageObjectParams *data = new TStageObjectParams();
1832   data->m_name             = m_name;
1833   data->m_center           = m_center;
1834   data->m_noScaleZ         = m_noScaleZ;
1835 
1836   data->m_id       = m_id;
1837   data->m_parentId = getParent();
1838   data->m_offset   = m_offset;
1839   data->m_status   = m_status;
1840 
1841   data->m_x       = m_x;
1842   data->m_y       = m_y;
1843   data->m_z       = m_z;
1844   data->m_so      = m_so;
1845   data->m_rot     = m_rot;
1846   data->m_scalex  = m_scalex;
1847   data->m_scaley  = m_scaley;
1848   data->m_scale   = m_scale;
1849   data->m_posPath = m_posPath;
1850   data->m_shearx  = m_shearx;
1851   data->m_sheary  = m_sheary;
1852 
1853   data->m_skeletonDeformation = m_skeletonDeformation;
1854 
1855   data->m_cycleEnabled = m_cycleEnabled;
1856   data->m_spline       = m_spline;
1857 
1858   data->m_handle       = m_handle;
1859   data->m_parentHandle = m_parentHandle;
1860   if (m_pinnedRangeSet) data->m_pinnedRangeSet = m_pinnedRangeSet->clone();
1861 
1862   return data;
1863 }
1864 
1865 //-----------------------------------------------------------------------------
1866 
assignParams(const TStageObjectParams * src,bool doParametersClone)1867 void TStageObject::assignParams(const TStageObjectParams *src,
1868                                 bool doParametersClone) {
1869   m_name     = src->m_name;
1870   m_center   = src->m_center;
1871   m_noScaleZ = src->m_noScaleZ;
1872   m_offset   = src->m_offset;
1873   m_status   = src->m_status;
1874   if (m_spline) m_spline->release();
1875   m_spline = src->m_spline;
1876   if (m_spline) m_spline->addRef();
1877 
1878   if (doParametersClone) {
1879     m_x->copy(src->m_x.getPointer());
1880     m_y->copy(src->m_y.getPointer());
1881     m_z->copy(src->m_z.getPointer());
1882     m_so->copy(src->m_so.getPointer());
1883     m_rot->copy(src->m_rot.getPointer());
1884     m_scalex->copy(src->m_scalex.getPointer());
1885     m_scaley->copy(src->m_scaley.getPointer());
1886     m_scale->copy(src->m_scale.getPointer());
1887     m_posPath->copy(src->m_posPath.getPointer());
1888     m_shearx->copy(src->m_shearx.getPointer());
1889     m_sheary->copy(src->m_sheary.getPointer());
1890 
1891     if (src->m_skeletonDeformation)
1892       setPlasticSkeletonDeformation(
1893           new PlasticSkeletonDeformation(*src->m_skeletonDeformation));
1894   } else {
1895     m_x = src->m_x.getPointer();
1896     m_x->addObserver(this);
1897     m_y = src->m_y.getPointer();
1898     m_y->addObserver(this);
1899     m_z = src->m_z.getPointer();
1900     m_z->addObserver(this);
1901     m_so = src->m_so.getPointer();
1902     m_so->addObserver(this);
1903     m_rot = src->m_rot.getPointer();
1904     m_rot->addObserver(this);
1905     m_scalex = src->m_scalex.getPointer();
1906     m_scalex->addObserver(this);
1907     m_scaley = src->m_scaley.getPointer();
1908     m_scaley->addObserver(this);
1909     m_scale = src->m_scale.getPointer();
1910     m_scale->addObserver(this);
1911     m_posPath = src->m_posPath.getPointer();
1912     m_posPath->addObserver(this);
1913     m_shearx = src->m_shearx.getPointer();
1914     m_shearx->addObserver(this);
1915     m_sheary = src->m_sheary.getPointer();
1916     m_sheary->addObserver(this);
1917 
1918     m_skeletonDeformation = src->m_skeletonDeformation;
1919     if (m_skeletonDeformation) m_skeletonDeformation->addObserver(this);
1920   }
1921 
1922   m_handle       = src->m_handle;
1923   m_parentHandle = src->m_parentHandle;
1924 
1925   m_cycleEnabled = src->m_cycleEnabled;
1926   if (m_pinnedRangeSet) *m_pinnedRangeSet = *src->m_pinnedRangeSet;
1927   updateKeyframes();
1928   if (m_spline && isUppkEnabled()) m_spline->addParam(m_posPath.getPointer());
1929   invalidate();
1930 }
1931 
1932 //-----------------------------------------------------------------------------
1933 //
1934 // objectZ e' la posizione dell'oggetto lungo l'asse Z
1935 //   il default e' 0. valori grandi rappresentano oggetti piu' vicini alla
1936 //   camera
1937 //   la distanza iniziale fra tavolo e camera e' 1000
1938 //
1939 // cameraZ e' la posizione della camera lungo l'asse Z
1940 //   il default e' 0. valori negativi indicano che la camera si avvicina al
1941 //   tavolo
1942 //   (che raggiungerebbe per un valore di -1000)
1943 //
1944 
perspective(TAffine & aff,const TAffine & cameraAff,double cameraZ,const TAffine & objectAff,double objectZ,double objectNoScaleZ)1945 bool TStageObject::perspective(TAffine &aff, const TAffine &cameraAff,
1946                                double cameraZ, const TAffine &objectAff,
1947                                double objectZ, double objectNoScaleZ) {
1948   TPointD cameraPos(cameraAff.a13, cameraAff.a23);
1949   TPointD objectPos(objectAff.a13, objectAff.a23);
1950 
1951   const double focus     = 1000;
1952   const double nearPlane = 1;
1953 
1954   /*--
1955    * dzはカメラとオブジェクトの間の距離、focus(=1000)はPegbarをZ軸方向に動かさなかった場合のデフォルト距離
1956    * --*/
1957   double dz = focus + cameraZ - objectZ;
1958   if (dz < nearPlane) {
1959     aff = TAffine();
1960     return false;
1961   }
1962 
1963   double noScaleSc = 1 - objectNoScaleZ / focus;
1964   aff = cameraAff * TScale((focus + cameraZ) / dz) * cameraAff.inv() *
1965         objectAff * TScale(noScaleSc);
1966 
1967   return true;
1968 }
1969 
1970 //-----------------------------------------------------------------------------
1971 
setGroupId(int value)1972 int TStageObject::setGroupId(int value) {
1973   m_groupSelector++;
1974   m_groupId.insert(m_groupSelector, value);
1975   return m_groupSelector;
1976 }
1977 
1978 //-----------------------------------------------------------------------------
1979 
setGroupId(int value,int position)1980 void TStageObject::setGroupId(int value, int position) {
1981   assert(position >= 0 && position <= m_groupId.size());
1982   m_groupId.insert(position, value);
1983   if (m_groupSelector + 1 >= position) m_groupSelector++;
1984 }
1985 
1986 //-----------------------------------------------------------------------------
1987 
getGroupId()1988 int TStageObject::getGroupId() {
1989   return m_groupId.isEmpty() || m_groupSelector < 0 ||
1990                  m_groupSelector >= m_groupId.size()
1991              ? 0
1992              : m_groupId[m_groupSelector];
1993 }
1994 
1995 //-----------------------------------------------------------------------------
1996 
getGroupIdStack()1997 QStack<int> TStageObject::getGroupIdStack() { return m_groupId; }
1998 
1999 //-----------------------------------------------------------------------------
2000 
removeGroupId(int position)2001 void TStageObject::removeGroupId(int position) {
2002   if (!isGrouped()) return;
2003   assert(position >= 0 && position <= m_groupId.size());
2004   m_groupId.remove(position);
2005   if (m_groupSelector + 1 >= position && m_groupSelector > -1)
2006     m_groupSelector--;
2007 }
2008 
2009 //-----------------------------------------------------------------------------
2010 
removeGroupId()2011 int TStageObject::removeGroupId() {
2012   m_groupId.remove(m_groupSelector);
2013   if (m_groupSelector > -1) m_groupSelector--;
2014   return m_groupSelector + 1;
2015 }
2016 
2017 //-----------------------------------------------------------------------------
2018 
isGrouped()2019 bool TStageObject::isGrouped() { return !m_groupId.isEmpty(); }
2020 
2021 //-----------------------------------------------------------------------------
2022 
isContainedInGroup(int groupId)2023 bool TStageObject::isContainedInGroup(int groupId) {
2024   return m_groupId.contains(groupId);
2025 }
2026 
2027 //-----------------------------------------------------------------------------
2028 
setGroupName(const wstring & name,int position)2029 void TStageObject::setGroupName(const wstring &name, int position) {
2030   int groupSelector = position < 0 ? m_groupSelector : position;
2031   assert(groupSelector >= 0 && groupSelector <= m_groupName.size());
2032   m_groupName.insert(groupSelector, name);
2033 }
2034 
2035 //-----------------------------------------------------------------------------
2036 
getGroupName(bool fromEditor)2037 wstring TStageObject::getGroupName(bool fromEditor) {
2038   int groupSelector = fromEditor ? m_groupSelector + 1 : m_groupSelector;
2039   return m_groupName.isEmpty() || groupSelector < 0 ||
2040                  groupSelector >= m_groupName.size()
2041              ? L""
2042              : m_groupName[groupSelector];
2043 }
2044 
2045 //-----------------------------------------------------------------------------
2046 
getGroupNameStack()2047 QStack<wstring> TStageObject::getGroupNameStack() { return m_groupName; }
2048 
2049 //-----------------------------------------------------------------------------
2050 
removeGroupName(bool fromEditor)2051 int TStageObject::removeGroupName(bool fromEditor) {
2052   int groupSelector = fromEditor ? m_groupSelector + 1 : m_groupSelector;
2053   if (!isGrouped()) return -1;
2054   assert(groupSelector >= 0 && groupSelector <= m_groupName.size());
2055   m_groupName.remove(groupSelector);
2056   return groupSelector;
2057 }
2058 
2059 //-----------------------------------------------------------------------------
2060 
removeGroupName(int position)2061 void TStageObject::removeGroupName(int position) {
2062   int groupSelector = position < 0 ? m_groupSelector : position;
2063   assert(groupSelector >= 0 && groupSelector <= m_groupName.size());
2064   m_groupName.remove(groupSelector);
2065 }
2066 
2067 //-----------------------------------------------------------------------------
2068 
removeFromAllGroup()2069 void TStageObject::removeFromAllGroup() {
2070   m_groupId.clear();
2071   m_groupName.clear();
2072   m_groupSelector = -1;
2073 }
2074 
2075 //-----------------------------------------------------------------------------
2076 
editGroup()2077 void TStageObject::editGroup() { m_groupSelector--; }
2078 
2079 //-----------------------------------------------------------------------------
2080 
isGroupEditing()2081 bool TStageObject::isGroupEditing() {
2082   return isGrouped() && m_groupSelector == -1;
2083 }
2084 
2085 //-----------------------------------------------------------------------------
2086 
closeEditingGroup(int groupId)2087 void TStageObject::closeEditingGroup(int groupId) {
2088   if (!m_groupId.contains(groupId)) return;
2089   m_groupSelector = 0;
2090   while (m_groupId[m_groupSelector] != groupId &&
2091          m_groupSelector < m_groupId.size())
2092     m_groupSelector++;
2093 }
2094 
2095 //-----------------------------------------------------------------------------
2096 
getEditingGroupId()2097 int TStageObject::getEditingGroupId() {
2098   if (!isGrouped() || m_groupSelector + 1 >= m_groupId.size()) return -1;
2099   return m_groupId[m_groupSelector + 1];
2100 }
2101 
2102 //-----------------------------------------------------------------------------
2103 
getEditingGroupName()2104 wstring TStageObject::getEditingGroupName() {
2105   if (!isGrouped() || m_groupSelector + 1 >= m_groupName.size()) return L"";
2106   return m_groupName[m_groupSelector + 1];
2107 }
2108