1
2
3 #include "toonz/txshlevelcolumn.h"
4 #include "toonz/txshsimplelevel.h"
5 #include "toonz/txshcell.h"
6 #include "toonz/tcolumnfxset.h"
7 #include "toonz/tcolumnfx.h"
8 #include "toonz/txshleveltypes.h"
9
10 #include "tstream.h"
11
12 //-----------------------------------------------------------------------------
13
14 namespace {
qstringToFrameId(QString str)15 TFrameId qstringToFrameId(QString str) {
16 if (str.isEmpty() || str == "-1")
17 return TFrameId::EMPTY_FRAME;
18 else if (str == "-" || str == "-2")
19 return TFrameId::NO_FRAME;
20 TFrameId fid;
21 int s = 0;
22 QString number;
23 char letter(0);
24 for (s = 0; s < str.size(); s++) {
25 QChar c = str.at(s);
26 if (c.isNumber()) number.append(c);
27 #if QT_VERSION >= 0x050500
28 else
29 letter = c.toLatin1();
30 #else
31 else
32 letter = c.toAscii();
33 #endif
34 }
35 return TFrameId(number.toInt(), letter);
36 }
37 }
38
39 //-----------------------------------------------------------------------------
40
41 //=============================================================================
42 // TXshLevelColumn
43
TXshLevelColumn()44 TXshLevelColumn::TXshLevelColumn()
45 : m_fx(new TLevelColumnFx())
46 //, m_iconId("")
47 , m_iconVisible(false) {
48 // updateIcon();
49 m_fx->addRef();
50 m_fx->setColumn(this);
51 }
52
53 //-----------------------------------------------------------------------------
54
~TXshLevelColumn()55 TXshLevelColumn::~TXshLevelColumn() {
56 m_fx->setColumn(0);
57 m_fx->release();
58 m_fx = 0;
59 }
60
61 //-----------------------------------------------------------------------------
62
getColumnType() const63 TXshColumn::ColumnType TXshLevelColumn::getColumnType() const {
64 return eLevelType;
65 }
66
67 //----------------------------------------------------------------------------
68
canSetCell(const TXshCell & cell) const69 bool TXshLevelColumn::canSetCell(const TXshCell &cell) const {
70 if (cell.isEmpty()) return true;
71
72 TXshSimpleLevel *sl = cell.getSimpleLevel();
73 if (sl) return (sl->getType() & LEVELCOLUMN_XSHLEVEL);
74
75 return cell.getChildLevel();
76 }
77
78 //-----------------------------------------------------------------------------
79
getLevelColumnFx() const80 TLevelColumnFx *TXshLevelColumn::getLevelColumnFx() const { return m_fx; }
81
82 //-----------------------------------------------------------------------------
83
getFx() const84 TFx *TXshLevelColumn::getFx() const { return m_fx; }
85
86 //-----------------------------------------------------------------------------
87
clone() const88 TXshColumn *TXshLevelColumn::clone() const {
89 TXshLevelColumn *column = new TXshLevelColumn;
90 column->setStatusWord(getStatusWord());
91 column->setOpacity(getOpacity());
92 column->m_cells = m_cells;
93 column->m_first = m_first;
94 column->setColorTag(getColorTag());
95 column->setFilterColorId(getFilterColorId());
96
97 // column->updateIcon();
98 return column;
99 }
100
101 //-----------------------------------------------------------------------------
102
loadData(TIStream & is)103 void TXshLevelColumn::loadData(TIStream &is) {
104 std::string tagName;
105 while (is.openChild(tagName)) {
106 if (tagName == "status") {
107 int status;
108 is >> status;
109 setStatusWord(status);
110 if (status & eCamstandTransparent43) {
111 setOpacity(128);
112 status = status & ~eCamstandTransparent43;
113 }
114 } else if (tagName == "camerastand_opacity") {
115 int opacity;
116 is >> opacity;
117 setOpacity((UCHAR)opacity);
118 } else if (tagName == "filter_color_id") {
119 int id;
120 is >> id;
121 setFilterColorId((TXshColumn::FilterColor)id);
122 } else if (tagName == "cells") {
123 while (is.openChild(tagName)) {
124 if (tagName == "cell") {
125 TPersist *p = 0;
126 QString str;
127 int row = 1, rowCount = 1, increment = 0;
128 TFilePath path;
129 is >> row >> rowCount >> p >> str >> increment;
130 TFrameId fid = qstringToFrameId(str);
131 assert((fid.getLetter() == 0 && rowCount >= 0) ||
132 (fid.getLetter() != 0 && rowCount == 1));
133 TXshLevel *xshLevel = dynamic_cast<TXshLevel *>(p);
134 if (xshLevel) {
135 int fidNumber = fid.getNumber();
136 for (int i = 0; i < rowCount; i++) {
137 TXshCell cell(xshLevel, fid);
138 setCell(row++, cell);
139 // rowCount>1 => fid has not letter.
140 fidNumber += increment;
141 fid = TFrameId(fidNumber);
142 }
143 }
144 } else
145 throw TException("TXshLevelColumn, unknown tag(2): " + tagName);
146 is.closeChild();
147 }
148 } else if (tagName == "fx") {
149 TPersist *p = 0;
150 is >> p;
151 if (TLevelColumnFx *lcf = dynamic_cast<TLevelColumnFx *>(p)) {
152 lcf->addRef();
153 if (m_fx) m_fx->release();
154 m_fx = lcf;
155 lcf->setColumn(this);
156 }
157 } else if (tagName == "fxnodes") // per compatibilita' con 1.x e precedenti
158 {
159 TFxSet fxSet;
160 fxSet.loadData(is);
161 } else {
162 throw TException("TXshLevelColumn, unknown tag: " + tagName);
163 }
164 is.closeChild();
165 }
166 }
167
168 //-----------------------------------------------------------------------------
169
saveData(TOStream & os)170 void TXshLevelColumn::saveData(TOStream &os) {
171 os.child("status") << getStatusWord();
172 if (getOpacity() < 255) os.child("camerastand_opacity") << (int)getOpacity();
173 if (getFilterColorId() != 0)
174 os.child("filter_color_id") << (int)getFilterColorId();
175 int r0, r1;
176 if (getRange(r0, r1)) {
177 os.openChild("cells");
178 for (int r = r0; r <= r1; r++) {
179 TXshCell cell = getCell(r);
180 if (cell.isEmpty()) continue;
181 TFrameId fid = cell.m_frameId;
182 int n = 1, inc = 0, dr = fid.getNumber();
183 // If fid has not letter save more than one cell and its incrementation;
184 // otherwise save one cell.
185 if (r < r1 && fid.getLetter() == 0) {
186 TXshCell cell2 = getCell(r + 1);
187 TFrameId fid2 = cell2.m_frameId;
188 if (cell2.m_level.getPointer() == cell.m_level.getPointer() &&
189 fid2.getLetter() == 0) {
190 inc = cell2.m_frameId.getNumber() - dr;
191 n++;
192 for (;;) {
193 if (r + n > r1) break;
194 cell2 = getCell(r + n);
195 TFrameId fid2 = cell2.m_frameId;
196 if (cell2.m_level.getPointer() != cell.m_level.getPointer() ||
197 fid2.getLetter() != 0)
198 break;
199 if (fid2.getNumber() != dr + n * inc) break;
200 n++;
201 }
202 }
203 }
204 os.child("cell") << r << n << cell.m_level.getPointer() << fid.expand()
205 << inc;
206 r += n - 1;
207 }
208 os.closeChild();
209 }
210 os.child("fx") << m_fx;
211 }
212
213 //-----------------------------------------------------------------------------
214 // Used in TCellData::getNumbers
setNumbers(int row,int rowCount,const TXshCell cells[])215 bool TXshLevelColumn::setNumbers(int row, int rowCount,
216 const TXshCell cells[]) {
217 if (m_cells.empty()) return false;
218 // Check availability.
219 // - if source cells are all empty, do nothing
220 // - also, if source or target cells contain NO_FRAME, do nothing
221 bool isSrcAllEmpty = true;
222 for (int i = 0; i < rowCount; i++) {
223 // checking target cells
224 int currentTgtIndex = row + i - m_first;
225 if (currentTgtIndex < m_cells.size()) {
226 TXshCell tgtCell = m_cells[currentTgtIndex];
227 if (!tgtCell.isEmpty() && tgtCell.m_frameId == TFrameId::NO_FRAME)
228 return false;
229 }
230 // checking source cells
231 TXshCell srcCell = cells[i];
232 if (!srcCell.isEmpty()) {
233 if (srcCell.m_frameId == TFrameId::NO_FRAME) return false;
234 isSrcAllEmpty = false;
235 }
236 }
237 if (isSrcAllEmpty) return false;
238
239 // Find a level to input.
240 // If the first target cell is empty, search the upper cells, and lower cells
241 // and use a level of firsty-found occupied neighbor cell.
242 TXshLevelP currentLevel;
243 int tmpIndex = std::min(row - m_first, (int)m_cells.size() - 1);
244 // search upper cells
245 while (tmpIndex >= 0) {
246 TXshCell tmpCell = m_cells[tmpIndex];
247 if (!tmpCell.isEmpty() && tmpCell.m_frameId != TFrameId::NO_FRAME) {
248 currentLevel = tmpCell.m_level;
249 break;
250 }
251 tmpIndex--;
252 }
253 // if not found any level in upper cells, then search the lower cells
254 if (!currentLevel) {
255 tmpIndex = std::max(row - m_first, 0);
256 while (tmpIndex < (int)m_cells.size()) {
257 TXshCell tmpCell = m_cells[tmpIndex];
258 if (!tmpCell.isEmpty() && tmpCell.m_frameId != TFrameId::NO_FRAME) {
259 currentLevel = tmpCell.m_level;
260 break;
261 }
262 tmpIndex++;
263 }
264 // in the case any level for input could not be found
265 if (!currentLevel) return false;
266 }
267
268 // Resize the cell container
269 int ra = row;
270 int rb = row + rowCount - 1;
271 int c_rb = m_first + m_cells.size() - 1;
272 if (row > c_rb) {
273 int newCellCount = row - m_first + rowCount;
274 m_cells.resize(newCellCount);
275 } else if (row < m_first) {
276 int delta = m_first - row;
277 m_cells.insert(m_cells.begin(), delta, TXshCell());
278 m_first = row;
279 }
280 if (rb > c_rb) {
281 for (int i = 0; i < rb - c_rb; ++i) m_cells.push_back(TXshCell());
282 }
283
284 // Paste numbers.
285 for (int i = 0; i < rowCount; i++) {
286 int dstIndex = row - m_first + i;
287 TXshCell dstCell = m_cells[dstIndex];
288 TXshCell srcCell = cells[i];
289 if (srcCell.isEmpty()) {
290 m_cells[dstIndex] = TXshCell();
291 } else {
292 if (!dstCell.isEmpty()) currentLevel = dstCell.m_level;
293 m_cells[dstIndex] = TXshCell(currentLevel, srcCell.m_frameId);
294 }
295 }
296
297 // Update the cell container.
298 while (!m_cells.empty() && m_cells.back().isEmpty()) {
299 m_cells.pop_back();
300 }
301 while (!m_cells.empty() && m_cells.front().isEmpty()) {
302 m_cells.erase(m_cells.begin());
303 m_first++;
304 }
305 if (m_cells.empty()) {
306 m_first = 0;
307 }
308 return true;
309 }
310
311 //-----------------------------------------------------------------------------
312
313 PERSIST_IDENTIFIER(TXshLevelColumn, "levelColumn")
314