From b926f2f81ee1f888dba3c79f34bc97a9a5dcef20 Mon Sep 17 00:00:00 2001 From: Rodney Date: Oct 15 2020 06:55:31 +0000 Subject: Merge pull request #3526 from shun-iwasawa/xdts_frame_number_with_suffix XDTS I/O enhancement: Enabled to handle frame number with suffix --- diff --git a/toonz/sources/toonz/xdtsio.cpp b/toonz/sources/toonz/xdtsio.cpp index 9e1a1a3..5ccce01 100644 --- a/toonz/sources/toonz/xdtsio.cpp +++ b/toonz/sources/toonz/xdtsio.cpp @@ -58,6 +58,24 @@ void XdtsHeader::write(QJsonObject &json) const { //----------------------------------------------------------------------------- +TFrameId XdtsFrameDataItem::str2Fid(const QString &str) const { + bool ok; + int frame = str.toInt(&ok); + if (ok) return TFrameId(frame); + // separate the last word as suffix + frame = str.left(str.size() - 1).toInt(&ok); + if (!ok) return TFrameId(-1); // EMPTY + if (!str[str.size() - 1].isLetter()) return TFrameId(-1); // EMPTY + char c = str[str.size() - 1].toLatin1(); + + return TFrameId(frame, c); +} + +QString XdtsFrameDataItem::fid2Str(const TFrameId &fid) const { + if (fid.getLetter() == 0) return QString::number(fid.getNumber()); + return QString::number(fid.getNumber()) + QString(fid.getLetter()); +} + void XdtsFrameDataItem::read(const QJsonObject &json) { m_id = DataId(qRound(json["id"].toDouble())); QJsonArray valuesArray = json["values"].toArray(); @@ -73,6 +91,23 @@ void XdtsFrameDataItem::write(QJsonObject &json) const { json["values"] = valuesArray; } +TFrameId XdtsFrameDataItem::getFrameId() const { + // int getCellNumber() const { + if (m_values.isEmpty()) + return TFrameId(-1); // EMPTY + // if (m_values.isEmpty()) return 0; + QString val = m_values.at(0); + if (val == "SYMBOL_NULL_CELL") + return TFrameId(-1); // EMPTY + // ignore sheet symbols for now + else if (val == "SYMBOL_HYPHEN" || val == "SYMBOL_TICK_1" || + val == "SYMBOL_TICK_2") + return TFrameId(-2); // IGNORE + // return -1; + // return cell number + return str2Fid(m_values.at(0)); +} + //----------------------------------------------------------------------------- void XdtsTrackFrameItem::read(const QJsonObject &json) { QJsonArray dataArray = json["data"].toArray(); @@ -99,8 +134,8 @@ void XdtsTrackFrameItem::write(QJsonObject &json) const { //----------------------------------------------------------------------------- -QPair XdtsTrackFrameItem::frameCellNumber() const { - return QPair(m_frame, m_data[0].getCellNumber()); +QPair XdtsTrackFrameItem::frameFid() const { + return QPair(m_frame, m_data[0].getFrameId()); } //----------------------------------------------------------------------------- @@ -128,36 +163,37 @@ void XdtsFieldTrackItem::write(QJsonObject &json) const { } //----------------------------------------------------------------------------- -static bool frameLessThan(const QPair &v1, const QPair &v2) { +static bool frameLessThan(const QPair &v1, + const QPair &v2) { return v1.first < v2.first; } -QVector XdtsFieldTrackItem::getCellNumberTrack() const { - QList> frameCellNumbers; +QVector XdtsFieldTrackItem::getCellFrameIdTrack() const { + QList> frameFids; for (const XdtsTrackFrameItem &frame : m_frames) - frameCellNumbers.append(frame.frameCellNumber()); - std::sort(frameCellNumbers.begin(), frameCellNumbers.end(), frameLessThan); - - QVector cells; - int currentFrame = 0; - int initialNumber = 0; - for (QPair &frameCellNumber : frameCellNumbers) { - while (currentFrame < frameCellNumber.first) { + frameFids.append(frame.frameFid()); + std::sort(frameFids.begin(), frameFids.end(), frameLessThan); + + QVector cells; + int currentFrame = 0; + TFrameId initialNumber = TFrameId(); + for (QPair &frameFid : frameFids) { + while (currentFrame < frameFid.first) { cells.append((cells.isEmpty()) ? initialNumber : cells.last()); currentFrame++; } // CSP may export negative frame data (although it is not allowed in XDTS // format specification) so handle such case. - if (frameCellNumber.first < 0) { - initialNumber = frameCellNumber.second; + if (frameFid.first < 0) { + initialNumber = frameFid.second; continue; } // ignore sheet symbols for now - int cellNumber = frameCellNumber.second; - if (cellNumber == -1) - cells.append((cells.isEmpty()) ? 0 : cells.last()); + TFrameId cellFid = frameFid.second; + if (cellFid.getNumber() == -2) // IGNORE case + cells.append((cells.isEmpty()) ? TFrameId(-1) : cells.last()); else - cells.append(cellNumber); + cells.append(cellFid); currentFrame++; } return cells; @@ -169,7 +205,7 @@ QString XdtsFieldTrackItem::build(TXshCellColumn *column) { TXshCell prevCell; int r0, r1; column->getRange(r0, r1); - if (r0 > 0) addFrame(0, 0); + if (r0 > 0) addFrame(0, TFrameId(-1)); for (int row = r0; row <= r1; row++) { TXshCell cell = column->getCell(row); // try to register the level @@ -181,13 +217,13 @@ QString XdtsFieldTrackItem::build(TXshCellColumn *column) { if (prevCell == cell) continue; if (cell.isEmpty()) - addFrame(row, 0); + addFrame(row, TFrameId(-1)); else - addFrame(row, cell.getFrameId().getNumber()); + addFrame(row, cell.getFrameId()); prevCell = cell; } - addFrame(r1 + 1, 0); + addFrame(r1 + 1, TFrameId(-1)); if (level) return QString::fromStdWString(level->getName()); else { @@ -227,12 +263,12 @@ QList XdtsTimeTableFieldItem::getOccupiedColumns() const { return ret; } -QVector XdtsTimeTableFieldItem::getColumnTrack(int col) const { +QVector XdtsTimeTableFieldItem::getColumnTrack(int col) const { for (const XdtsFieldTrackItem &track : m_tracks) { if (track.getTrackNo() != col) continue; - return track.getCellNumberTrack(); + return track.getCellFrameIdTrack(); } - return QVector(); + return QVector(); } void XdtsTimeTableFieldItem::build(TXsheet *xsheet, QStringList &columnLabels) { @@ -467,22 +503,22 @@ bool XdtsIo::loadXdtsScene(ToonzScene *scene, const TFilePath &scenePath) { QStringList layerNames = cellHeader.getLayerNames(); QList columns = cellField.getOccupiedColumns(); for (int column : columns) { - QString levelName = layerNames.at(column); - TXshLevel *level = levels.value(levelName); - QVector track = cellField.getColumnTrack(column); + QString levelName = layerNames.at(column); + TXshLevel *level = levels.value(levelName); + QVector track = cellField.getColumnTrack(column); int row = 0; std::vector::iterator it; - for (int f : track) { - if (f == 0) // empty cell + for (TFrameId fid : track) { + if (fid.getNumber() == -1) // EMPTY cell case row++; else - xsh->setCell(row++, column, TXshCell(level, TFrameId(f))); + xsh->setCell(row++, column, TXshCell(level, fid)); } // if the last cell is not "SYMBOL_NULL_CELL", continue the cell // to the end of the sheet - int lastFid = track.last(); - if (lastFid != 0) { + TFrameId lastFid = track.last(); + if (lastFid.getNumber() != -1) { for (; row < duration; row++) xsh->setCell(row, column, TXshCell(level, TFrameId(lastFid))); } diff --git a/toonz/sources/toonz/xdtsio.h b/toonz/sources/toonz/xdtsio.h index 1b3702c..d8b1df2 100644 --- a/toonz/sources/toonz/xdtsio.h +++ b/toonz/sources/toonz/xdtsio.h @@ -2,6 +2,8 @@ #ifndef XDTSIO_H #define XDTSIO_H +#include "tfilepath.h" + #include #include #include @@ -77,25 +79,18 @@ class XdtsFrameDataItem { // SYMBOL_HYPHEN Continue previous All fields // field instruction + TFrameId str2Fid(const QString &) const; + QString fid2Str(const TFrameId &) const; + public: XdtsFrameDataItem() : m_id(Default) {} - XdtsFrameDataItem(int cellNumber) : m_id(Default) { - m_values.append((cellNumber == 0) ? QString("SYMBOL_NULL_CELL") - : QString::number(cellNumber)); + XdtsFrameDataItem(TFrameId fId) : m_id(Default) { + m_values.append((fId.getNumber() == -1) ? QString("SYMBOL_NULL_CELL") + : fid2Str(fId)); } void read(const QJsonObject &json); void write(QJsonObject &json) const; - int getCellNumber() const { - if (m_values.isEmpty()) return 0; - QString val = m_values.at(0); - if (val == "SYMBOL_NULL_CELL") return 0; - // ignore sheet symbols for now - else if (val == "SYMBOL_HYPHEN" || val == "SYMBOL_TICK_1" || - val == "SYMBOL_TICK_2") - return -1; - // return cell number - return m_values.at(0).toInt(); - } + TFrameId getFrameId() const; }; //"description": "Individual layer frame information", @@ -111,12 +106,12 @@ class XdtsTrackFrameItem { //"required": ["data", "frame"] public: XdtsTrackFrameItem() = default; - XdtsTrackFrameItem(int frame, int cellNumber) : m_frame(frame) { - m_data.append(XdtsFrameDataItem(cellNumber)); + XdtsTrackFrameItem(int frame, TFrameId fId) : m_frame(frame) { + m_data.append(XdtsFrameDataItem(fId)); } void read(const QJsonObject &json); void write(QJsonObject &json) const; - QPair frameCellNumber() const; + QPair frameFid() const; }; //"description": "Individual field layer info", @@ -137,11 +132,11 @@ public: void write(QJsonObject &json) const; bool isEmpty() const { return m_frames.isEmpty(); } int getTrackNo() const { return m_trackNo; } - QVector getCellNumberTrack() const; + QVector getCellFrameIdTrack() const; QString build(TXshCellColumn *); - void addFrame(int frame, int cellNumber) { - m_frames.append(XdtsTrackFrameItem(frame, cellNumber)); + void addFrame(int frame, TFrameId fId) { + m_frames.append(XdtsTrackFrameItem(frame, fId)); } }; @@ -159,7 +154,7 @@ public: void write(QJsonObject &json) const; bool isCellField() { return m_fieldId == CELL; } QList getOccupiedColumns() const; - QVector getColumnTrack(int col) const; + QVector getColumnTrack(int col) const; void build(TXsheet *, QStringList &); };