1 
2 
3 // TnzLib includes
4 #include "toonz/txsheet.h"
5 #include "toonz/txshcell.h"
6 #include "toonz/hook.h"
7 #include "toonz/dpiscale.h"
8 #include "toonz/txshsimplelevel.h"
9 #include "toonz/stage.h"
10 
11 #include "xshhandlemanager.h"
12 
13 //*******************************************************************************
14 //    Local namespace
15 //*******************************************************************************
16 
17 namespace {
18 
19 // Returns the sum of each pass hook between fid and precFid.
forwardPass(const TFrameId & fid,const TFrameId & precFid,TXshSimpleLevel * sl,Hook * hook)20 TPointD forwardPass(const TFrameId &fid, const TFrameId &precFid,
21                     TXshSimpleLevel *sl, Hook *hook) {
22   TPointD delta;
23   std::vector<TFrameId> levelFids;
24   sl->getFids(levelFids);
25 
26   int f, fCount = levelFids.size();
27   for (f = 0; f != fCount; ++f) {
28     const TFrameId &levelFid = levelFids[f];
29 
30     if (levelFid < precFid) continue;
31 
32     if (levelFid >= fid) break;
33 
34     if (hook->isKeyframe(levelFid))
35       delta += hook->getAPos(levelFid) - hook->getBPos(levelFid);
36   }
37 
38   return delta;
39 }
40 
41 //-----------------------------------------------------------------------------
42 // Returns subtraction of each pass hook between fid and precFid.
backwardPass(const TFrameId & fid,const TFrameId & precFid,TXshSimpleLevel * sl,Hook * hook)43 TPointD backwardPass(const TFrameId &fid, const TFrameId &precFid,
44                      TXshSimpleLevel *sl, Hook *hook) {
45   TPointD delta;
46   std::vector<TFrameId> levelFids;
47   sl->getFids(levelFids);
48 
49   int f, fCount = levelFids.size();
50   for (f = 0; f != fCount; ++f) {
51     const TFrameId &levelFid = levelFids[f];
52 
53     if (levelFid < fid) continue;
54 
55     if (levelFid >= precFid) break;
56 
57     if (hook->isKeyframe(levelFid))
58       delta -= hook->getAPos(levelFid) - hook->getBPos(levelFid);
59   }
60 
61   return delta;
62 }
63 
64 //-----------------------------------------------------------------------------
65 // Compute pass hook between fid and precFid
computePassHook(const TFrameId & fid,const TFrameId & precFid,TXshSimpleLevel * sl,Hook * hook)66 TPointD computePassHook(const TFrameId &fid, const TFrameId &precFid,
67                         TXshSimpleLevel *sl, Hook *hook) {
68   if (fid < precFid && (precFid.getNumber() - fid.getNumber()) <= 2)
69     return backwardPass(fid, precFid, sl, hook);
70 
71   return forwardPass(fid, precFid, sl, hook);
72 }
73 
74 }  // namespace
75 
76 //*******************************************************************************
77 //    XshHandleManager  implementation
78 //*******************************************************************************
79 
getHandlePos(const TStageObjectId & id,const std::string & handle,int row) const80 TPointD XshHandleManager::getHandlePos(const TStageObjectId &id,
81                                        const std::string &handle,
82                                        int row) const {
83   static const double unit = 8.0;
84 
85   assert(m_xsh->getScene());
86 
87   if (handle == "")
88     return TPointD();
89 
90   else if (handle[0] == 'H' && handle.length() > 1) {
91     // Hook port case
92 
93     if (!id.isColumn()) return TPointD();
94 
95     int hookIndex = 0;
96     {
97       int h, hLength = handle.length();
98       for (h = 1; h != hLength; ++h)
99         hookIndex = hookIndex * 10 + (handle[h] - '0');
100     }
101 
102     TStageObject *obj = m_xsh->getStageObject(id);
103     if (const PlasticSkeletonDeformationP &def =
104             obj->getPlasticSkeletonDeformation()) {
105       int skelId = def->skeletonId(row);
106 
107       PlasticSkeleton skel;
108       def->storeDeformedSkeleton(skelId, row, skel);
109 
110       int v = def->vertexIndex(hookIndex, skelId);
111       return (v >= 0) ? TScale(1.0 / Stage::inch) * skel.vertex(v).P()
112                       : TPointD();
113     }
114 
115     --hookIndex;
116 
117     int col = id.getIndex();
118     TXshCell cell(m_xsh->getCell(row, col));
119 
120     TXshLevel *xl = cell.m_level.getPointer();
121     if (!xl) return TPointD();
122 
123     TXshSimpleLevel *sl = xl->getSimpleLevel();
124     if (!sl) return TPointD();
125 
126     Hook *hook = sl->getHookSet()->getHook(hookIndex);
127     if (!hook) return TPointD();
128 
129     TFrameId fid(cell.m_frameId);
130 
131     TPointD pos = hook->getAPos(fid) * (1.0 / Stage::inch);
132     TPointD delta;
133 
134     for (int r = row - 1; r >= 0; --r) {
135       cell = m_xsh->getCell(r, col);
136       if (cell.m_level.getPointer() != xl) break;
137 
138       const TFrameId &precFid = cell.m_frameId;
139       delta += computePassHook(fid, precFid, sl, hook);
140       fid = precFid;
141     }
142 
143     pos += delta * (1.0 / Stage::inch);
144     pos = getDpiAffine(sl, cell.m_frameId, true) * pos;
145 
146     return pos;
147   } else if ('A' <= handle[0] && handle[0] <= 'Z')
148     return TPointD(unit * (handle[0] - 'B'), 0);
149   else if ('a' <= handle[0] && handle[0] <= 'z')
150     return TPointD(0.5 * unit * (handle[0] - 'b'), 0);
151   else
152     return TPointD();
153 }
154