1 
2 
3 #include "toonz/columnfan.h"
4 #include "toonz/preferences.h"
5 
6 // TnzCore includes
7 #include "tstream.h"
8 
9 // STD includss
10 #include <assert.h>
11 
12 //=============================================================================
13 // ColumnFan
14 
ColumnFan()15 ColumnFan::ColumnFan()
16     : m_firstFreePos(0)
17     , m_unfolded(74)
18     , m_folded(9)
19     , m_cameraActive(true)
20     , m_cameraColumnDim(22) {}
21 
22 //-----------------------------------------------------------------------------
23 
setDimensions(int unfolded,int cameraColumn)24 void ColumnFan::setDimensions(int unfolded, int cameraColumn) {
25   m_unfolded        = unfolded;
26   m_cameraColumnDim = cameraColumn;
27   // folded always 9
28   update();
29 }
30 
31 //-----------------------------------------------------------------------------
32 
update()33 void ColumnFan::update() {
34   int lastPos     = -m_unfolded;
35   bool lastActive = true;
36   int m           = m_columns.size();
37   int i;
38   for (i = 0; i < m; i++) {
39     bool active = m_columns[i].m_active;
40     if (lastActive)
41       lastPos += m_unfolded;
42     else if (active)
43       lastPos += m_folded;
44     m_columns[i].m_pos = lastPos;
45     lastActive         = active;
46   }
47   m_firstFreePos = lastPos + (lastActive ? m_unfolded : m_folded);
48   m_table.clear();
49   for (i = 0; i < m; i++)
50     if (m_columns[i].m_active)
51       m_table[m_columns[i].m_pos + m_unfolded - 1] = i;
52     else if (i + 1 < m && m_columns[i + 1].m_active)
53       m_table[m_columns[i + 1].m_pos - 1] = i;
54     else if (i + 1 == m)
55       m_table[m_firstFreePos - 1] = i;
56 }
57 
58 //-----------------------------------------------------------------------------
59 
layerAxisToCol(int coord) const60 int ColumnFan::layerAxisToCol(int coord) const {
61   if (Preferences::instance()->isXsheetCameraColumnVisible()) {
62     int firstCol =
63         m_cameraActive
64             ? m_cameraColumnDim
65             : ((m_columns.size() > 0 && !m_columns[0].m_active) ? 0 : m_folded);
66     if (coord < firstCol) return -1;
67     coord -= firstCol;
68   }
69   if (coord < m_firstFreePos) {
70     std::map<int, int>::const_iterator it = m_table.lower_bound(coord);
71     if (it == m_table.end()) return -3;
72     assert(it != m_table.end());
73     return it->second;
74   } else
75     return m_columns.size() + (coord - m_firstFreePos) / m_unfolded;
76 }
77 
78 //-----------------------------------------------------------------------------
79 
colToLayerAxis(int col) const80 int ColumnFan::colToLayerAxis(int col) const {
81   int m        = m_columns.size();
82   int firstCol = 0;
83   if (Preferences::instance()->isXsheetCameraColumnVisible()) {
84     if (col < -1) return -m_cameraColumnDim;
85     if (col < 0) return 0;
86     firstCol =
87         m_cameraActive
88             ? m_cameraColumnDim
89             : ((m_columns.size() > 0 && !m_columns[0].m_active) ? 0 : m_folded);
90   }
91   if (col >= 0 && col < m)
92     return firstCol + m_columns[col].m_pos;
93   else
94     return firstCol + m_firstFreePos + (col - m) * m_unfolded;
95 }
96 
97 //-----------------------------------------------------------------------------
98 
activate(int col)99 void ColumnFan::activate(int col) {
100   int m = m_columns.size();
101   if (col < 0) {
102     m_cameraActive = true;
103     return;
104   }
105   if (col < m) {
106     m_columns[col].m_active = true;
107     int i;
108     for (i = m - 1; i >= 0 && m_columns[i].m_active; i--) {
109     }
110     i++;
111     if (i < m) {
112       m = i;
113       m_columns.erase(m_columns.begin() + i, m_columns.end());
114     }
115   }
116   update();
117 }
118 
119 //-----------------------------------------------------------------------------
120 
deactivate(int col)121 void ColumnFan::deactivate(int col) {
122   if (col < 0) {
123     m_cameraActive = false;
124     return;
125   }
126   while ((int)m_columns.size() <= col) m_columns.push_back(Column());
127   m_columns[col].m_active = false;
128   update();
129 }
130 
131 //-----------------------------------------------------------------------------
132 
isActive(int col) const133 bool ColumnFan::isActive(int col) const {
134   return 0 <= col && col < (int)m_columns.size()
135              ? m_columns[col].m_active
136              : col < 0 ? m_cameraActive : true;
137 }
138 
139 //-----------------------------------------------------------------------------
140 
isEmpty() const141 bool ColumnFan::isEmpty() const { return m_columns.empty(); }
142 
143 //-----------------------------------------------------------------------------
144 
copyFoldedStateFrom(const ColumnFan & from)145 void ColumnFan::copyFoldedStateFrom(const ColumnFan &from) {
146   m_cameraActive = from.m_cameraActive;
147   for (int i = 0, n = (int)from.m_columns.size(); i < n; i++)
148     if (!from.isActive(i)) deactivate(i);
149 }
150 
151 //-----------------------------------------------------------------------------
152 
saveData(TOStream & os)153 void ColumnFan::saveData(
154     TOStream &os) {  // only saves indices of folded columns
155   int index, n = (int)m_columns.size();
156   for (index = 0; index < n;) {
157     while (index < n && m_columns[index].m_active) index++;
158     if (index < n) {
159       int firstIndex = index;
160       os << index;
161       index++;
162       while (index < n && !m_columns[index].m_active) index++;
163       os << index - firstIndex;
164     }
165   }
166 }
167 
168 //-----------------------------------------------------------------------------
169 
loadData(TIStream & is)170 void ColumnFan::loadData(TIStream &is) {
171   m_columns.clear();
172   m_table.clear();
173   m_firstFreePos = 0;
174   while (!is.eos()) {
175     int index = 0, count = 0;
176     is >> index >> count;
177     int j;
178     for (j = 0; j < count; j++) deactivate(index + j);
179   }
180 }
181 
182 //-----------------------------------------------------------------------------
183 
rollLeftFoldedState(int index,int count)184 void ColumnFan::rollLeftFoldedState(int index, int count) {
185   assert(index >= 0);
186   int columnCount = m_columns.size();
187   if (columnCount <= index) return;
188   if (index + count - 1 > columnCount) count = columnCount - index + 1;
189   if (count < 2) return;
190 
191   int i = index, j = index + count - 1;
192   bool tmp = isActive(i);
193 
194   for (int k = i; k < j; ++k) {
195     if (isActive(k) && !isActive(k + 1))
196       deactivate(k);
197     else if (!isActive(k) && isActive(k + 1))
198       activate(k);
199   }
200   if (isActive(j) && !tmp)
201     deactivate(j);
202   else if (!isActive(j) && tmp)
203     activate(j);
204 
205   update();
206 }
207 
208 //-----------------------------------------------------------------------------
209 
rollRightFoldedState(int index,int count)210 void ColumnFan::rollRightFoldedState(int index, int count) {
211   assert(index >= 0);
212 
213   int columnCount = m_columns.size();
214   if (columnCount <= index) return;
215   if (index + count - 1 > columnCount) count = columnCount - index + 1;
216   if (count < 2) return;
217 
218   int i = index, j = index + count - 1;
219   bool tmp = isActive(j);
220 
221   for (int k = j; k > i; --k) {
222     if (isActive(k) && !isActive(k - 1))
223       deactivate(k);
224     else if (!isActive(k) && isActive(k - 1))
225       activate(k);
226   }
227   if (isActive(i) && !tmp)
228     deactivate(i);
229   else if (!isActive(i) && tmp)
230     activate(i);
231 
232   update();
233 }
234