Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/txshlevelcolumn.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsimplelevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshcell.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnfxset.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnfx.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshleveltypes.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
TFrameId qstringToFrameId(QString str) {
Shinya Kitaoka 120a6e
  if (str.isEmpty() || str == "-1")
Shinya Kitaoka 120a6e
    return TFrameId::EMPTY_FRAME;
Shinya Kitaoka 120a6e
  else if (str == "-" || str == "-2")
Shinya Kitaoka 120a6e
    return TFrameId::NO_FRAME;
shun-iwasawa ef0f8b
shun-iwasawa ef0f8b
  QString regExpStr = QString("^%1$").arg(TFilePath::fidRegExpStr());
shun-iwasawa ef0f8b
  QRegExp rx(regExpStr);
shun-iwasawa ef0f8b
  int pos = rx.indexIn(str);
shun-iwasawa ef0f8b
  if (pos < 0) return TFrameId();
shun-iwasawa ef0f8b
  if (rx.cap(2).isEmpty())
shun-iwasawa ef0f8b
    return TFrameId(rx.cap(1).toInt());
shun-iwasawa ef0f8b
  else
shun-iwasawa ef0f8b
    return TFrameId(rx.cap(1).toInt(), rx.cap(2));
Toshihiro Shimizu 890ddd
}
shun-iwasawa ef0f8b
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================================================
Toshihiro Shimizu 890ddd
// TXshLevelColumn
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TXshLevelColumn::TXshLevelColumn()
Shinya Kitaoka 120a6e
    : m_fx(new TLevelColumnFx())
Shinya Kitaoka 120a6e
    //, m_iconId("")
Shinya Kitaoka 120a6e
    , m_iconVisible(false) {
Shinya Kitaoka 120a6e
  // updateIcon();
Shinya Kitaoka 120a6e
  m_fx->addRef();
Shinya Kitaoka 120a6e
  m_fx->setColumn(this);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TXshLevelColumn::~TXshLevelColumn() {
Shinya Kitaoka 120a6e
  m_fx->setColumn(0);
Shinya Kitaoka 120a6e
  m_fx->release();
Shinya Kitaoka 120a6e
  m_fx = 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TXshColumn::ColumnType TXshLevelColumn::getColumnType() const {
Shinya Kitaoka 120a6e
  return eLevelType;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TXshLevelColumn::canSetCell(const TXshCell &cell) const {
Shinya Kitaoka 120a6e
  if (cell.isEmpty()) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshSimpleLevel *sl = cell.getSimpleLevel();
Shinya Kitaoka 120a6e
  if (sl) return (sl->getType() & LEVELCOLUMN_XSHLEVEL);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return cell.getChildLevel();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TLevelColumnFx *TXshLevelColumn::getLevelColumnFx() const { return m_fx; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFx *TXshLevelColumn::getFx() const { return m_fx; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TXshColumn *TXshLevelColumn::clone() const {
Shinya Kitaoka 120a6e
  TXshLevelColumn *column = new TXshLevelColumn;
Shinya Kitaoka 120a6e
  column->setStatusWord(getStatusWord());
Shinya Kitaoka 120a6e
  column->setOpacity(getOpacity());
Shinya Kitaoka 120a6e
  column->m_cells = m_cells;
Shinya Kitaoka 120a6e
  column->m_first = m_first;
manongjohn 09549b
  column->setColorTag(getColorTag());
shun-iwasawa a266be
  column->setColorFilterId(getColorFilterId());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // column->updateIcon();
Shinya Kitaoka 120a6e
  return column;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshLevelColumn::loadData(TIStream &is) {
Shinya Kitaoka 120a6e
  std::string tagName;
Shinya Kitaoka 120a6e
  while (is.openChild(tagName)) {
Shinya Kitaoka 120a6e
    if (tagName == "status") {
Shinya Kitaoka 120a6e
      int status;
Shinya Kitaoka 120a6e
      is >> status;
Shinya Kitaoka 120a6e
      setStatusWord(status);
Shinya Kitaoka 120a6e
      if (status & eCamstandTransparent43) {
Shinya Kitaoka 120a6e
        setOpacity(128);
Shinya Kitaoka 120a6e
        status = status & ~eCamstandTransparent43;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else if (tagName == "camerastand_opacity") {
Shinya Kitaoka 120a6e
      int opacity;
Shinya Kitaoka 120a6e
      is >> opacity;
Shinya Kitaoka 120a6e
      setOpacity((UCHAR)opacity);
shun_iwasawa a3cdd8
    } else if (tagName == "filter_color_id") {
shun_iwasawa a3cdd8
      int id;
shun_iwasawa a3cdd8
      is >> id;
shun-iwasawa a266be
      setColorFilterId(id);
Shinya Kitaoka 120a6e
    } else if (tagName == "cells") {
Shinya Kitaoka 120a6e
      while (is.openChild(tagName)) {
Shinya Kitaoka 120a6e
        if (tagName == "cell") {
Shinya Kitaoka 120a6e
          TPersist *p = 0;
shun-iwasawa ef0f8b
          std::string str;
Shinya Kitaoka 120a6e
          int row = 1, rowCount = 1, increment = 0;
Shinya Kitaoka 120a6e
          TFilePath path;
Shinya Kitaoka 120a6e
          is >> row >> rowCount >> p >> str >> increment;
shun-iwasawa ef0f8b
          TFrameId fid = qstringToFrameId(QString::fromStdString(str));
shun-iwasawa ef0f8b
          assert((fid.getLetter().isEmpty() && rowCount >= 0) ||
shun-iwasawa ef0f8b
                 (!fid.getLetter().isEmpty() && rowCount == 1));
Shinya Kitaoka 120a6e
          TXshLevel *xshLevel = dynamic_cast<txshlevel *="">(p);</txshlevel>
Shinya Kitaoka 120a6e
          if (xshLevel) {
Shinya Kitaoka 120a6e
            int fidNumber = fid.getNumber();
Shinya Kitaoka 120a6e
            for (int i = 0; i < rowCount; i++) {
Shinya Kitaoka 120a6e
              TXshCell cell(xshLevel, fid);
Shinya Kitaoka 120a6e
              setCell(row++, cell);
Shinya Kitaoka 120a6e
              // rowCount>1 => fid has not letter.
Shinya Kitaoka 120a6e
              fidNumber += increment;
Shinya Kitaoka 120a6e
              fid = TFrameId(fidNumber);
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          throw TException("TXshLevelColumn, unknown tag(2): " + tagName);
Shinya Kitaoka 120a6e
        is.closeChild();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else if (tagName == "fx") {
Shinya Kitaoka 120a6e
      TPersist *p = 0;
Shinya Kitaoka 120a6e
      is >> p;
Shinya Kitaoka 120a6e
      if (TLevelColumnFx *lcf = dynamic_cast<tlevelcolumnfx *="">(p)) {</tlevelcolumnfx>
Shinya Kitaoka 120a6e
        lcf->addRef();
Shinya Kitaoka 120a6e
        if (m_fx) m_fx->release();
Shinya Kitaoka 120a6e
        m_fx = lcf;
Shinya Kitaoka 120a6e
        lcf->setColumn(this);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else if (tagName == "fxnodes")  // per compatibilita' con 1.x e precedenti
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      TFxSet fxSet;
Shinya Kitaoka 120a6e
      fxSet.loadData(is);
shun-iwasawa f84c65
    } else if (loadCellMarks(tagName, is)) {
shun-iwasawa f84c65
      // do nothing
shun-iwasawa f84c65
    } else
Shinya Kitaoka 120a6e
      throw TException("TXshLevelColumn, unknown tag: " + tagName);
Shinya Kitaoka 120a6e
    is.closeChild();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TXshLevelColumn::saveData(TOStream &os) {
Shinya Kitaoka 120a6e
  os.child("status") << getStatusWord();
Shinya Kitaoka 120a6e
  if (getOpacity() < 255) os.child("camerastand_opacity") << (int)getOpacity();
shun-iwasawa a266be
  if (getColorFilterId() != 0)
shun-iwasawa a266be
    os.child("filter_color_id") << (int)getColorFilterId();
Shinya Kitaoka 120a6e
  int r0, r1;
Shinya Kitaoka 120a6e
  if (getRange(r0, r1)) {
Shinya Kitaoka 120a6e
    os.openChild("cells");
Shinya Kitaoka 120a6e
    for (int r = r0; r <= r1; r++) {
Shinya Kitaoka 120a6e
      TXshCell cell = getCell(r);
Shinya Kitaoka 120a6e
      if (cell.isEmpty()) continue;
Shinya Kitaoka 120a6e
      TFrameId fid = cell.m_frameId;
Shinya Kitaoka 120a6e
      int n = 1, inc = 0, dr = fid.getNumber();
Shinya Kitaoka 120a6e
      // If fid has not letter save more than one cell and its incrementation;
Shinya Kitaoka 120a6e
      // otherwise save one cell.
shun-iwasawa ef0f8b
      if (r < r1 && fid.getLetter().isEmpty()) {
Shinya Kitaoka 120a6e
        TXshCell cell2 = getCell(r + 1);
Shinya Kitaoka 120a6e
        TFrameId fid2  = cell2.m_frameId;
Shinya Kitaoka 120a6e
        if (cell2.m_level.getPointer() == cell.m_level.getPointer() &&
shun-iwasawa ef0f8b
            fid2.getLetter().isEmpty()) {
Shinya Kitaoka 120a6e
          inc = cell2.m_frameId.getNumber() - dr;
Shinya Kitaoka 120a6e
          n++;
Shinya Kitaoka 120a6e
          for (;;) {
Shinya Kitaoka 120a6e
            if (r + n > r1) break;
Shinya Kitaoka 120a6e
            cell2         = getCell(r + n);
Shinya Kitaoka 120a6e
            TFrameId fid2 = cell2.m_frameId;
Shinya Kitaoka 120a6e
            if (cell2.m_level.getPointer() != cell.m_level.getPointer() ||
shun-iwasawa ef0f8b
                !fid2.getLetter().isEmpty())
Shinya Kitaoka 120a6e
              break;
Shinya Kitaoka 120a6e
            if (fid2.getNumber() != dr + n * inc) break;
Shinya Kitaoka 120a6e
            n++;
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
      os.child("cell") << r << n << cell.m_level.getPointer() << fid.expand()
Shinya Kitaoka 120a6e
                       << inc;
Shinya Kitaoka 120a6e
      r += n - 1;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    os.closeChild();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  os.child("fx") << m_fx;
shun-iwasawa f84c65
shun-iwasawa f84c65
  // cell marks
shun-iwasawa f84c65
  saveCellMarks(os);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
shun-iwasawa fd55f6
// Used in TCellData::getNumbers
shun-iwasawa 23b326
// reservedLevel can be nonzero if the preferences option
shun-iwasawa 23b326
// "LinkColumnNameWithLevel" is ON and the column name is the same as some level
shun-iwasawa 23b326
// in the scene cast.
shun-iwasawa 23b326
bool TXshLevelColumn::setNumbers(int row, int rowCount, const TXshCell cells[],
shun-iwasawa 23b326
                                 TXshLevel *reservedLevel) {
shun-iwasawa 23b326
  if (m_cells.empty() && !reservedLevel) return false;
shun-iwasawa fd55f6
  // Check availability.
shun-iwasawa fd55f6
  // - if source cells are all empty, do nothing
shun-iwasawa fd55f6
  // - also, if source or target cells contain NO_FRAME, do nothing
shun-iwasawa fd55f6
  bool isSrcAllEmpty = true;
shun-iwasawa fd55f6
  for (int i = 0; i < rowCount; i++) {
shun-iwasawa fd55f6
    // checking target cells
shun-iwasawa fd55f6
    int currentTgtIndex = row + i - m_first;
shun-iwasawa fd55f6
    if (currentTgtIndex < m_cells.size()) {
shun-iwasawa fd55f6
      TXshCell tgtCell = m_cells[currentTgtIndex];
shun-iwasawa fd55f6
      if (!tgtCell.isEmpty() && tgtCell.m_frameId == TFrameId::NO_FRAME)
shun-iwasawa fd55f6
        return false;
shun-iwasawa fd55f6
    }
shun-iwasawa fd55f6
    // checking source cells
shun-iwasawa fd55f6
    TXshCell srcCell = cells[i];
shun-iwasawa fd55f6
    if (!srcCell.isEmpty()) {
shun-iwasawa fd55f6
      if (srcCell.m_frameId == TFrameId::NO_FRAME) return false;
shun-iwasawa fd55f6
      isSrcAllEmpty = false;
shun-iwasawa fd55f6
    }
shun-iwasawa fd55f6
  }
shun-iwasawa fd55f6
  if (isSrcAllEmpty) return false;
shun-iwasawa fd55f6
shun-iwasawa fd55f6
  // Find a level to input.
shun-iwasawa fd55f6
  // If the first target cell is empty, search the upper cells, and lower cells
luzpaz 27707d
  // and use a level of firsty-found occupied neighbor cell.
shun-iwasawa 23b326
  TXshLevelP currentLevel = reservedLevel;
shun-iwasawa 23b326
  int tmpIndex            = std::min(row - m_first, (int)m_cells.size() - 1);
shun-iwasawa fd55f6
  // search upper cells
shun-iwasawa 23b326
  if (!currentLevel) {
shun-iwasawa 23b326
    while (tmpIndex >= 0) {
shun-iwasawa 23b326
      TXshCell tmpCell = m_cells[tmpIndex];
shun-iwasawa 23b326
      if (!tmpCell.isEmpty() && tmpCell.m_frameId != TFrameId::NO_FRAME) {
shun-iwasawa 23b326
        currentLevel = tmpCell.m_level;
shun-iwasawa 23b326
        break;
shun-iwasawa 23b326
      }
shun-iwasawa 23b326
      tmpIndex--;
shun-iwasawa fd55f6
    }
shun-iwasawa fd55f6
  }
shun-iwasawa fd55f6
  // if not found any level in upper cells, then search the lower cells
shun-iwasawa fd55f6
  if (!currentLevel) {
shun-iwasawa fd55f6
    tmpIndex = std::max(row - m_first, 0);
shun-iwasawa fd55f6
    while (tmpIndex < (int)m_cells.size()) {
shun-iwasawa fd55f6
      TXshCell tmpCell = m_cells[tmpIndex];
shun-iwasawa fd55f6
      if (!tmpCell.isEmpty() && tmpCell.m_frameId != TFrameId::NO_FRAME) {
shun-iwasawa fd55f6
        currentLevel = tmpCell.m_level;
shun-iwasawa fd55f6
        break;
shun-iwasawa fd55f6
      }
shun-iwasawa fd55f6
      tmpIndex++;
shun-iwasawa fd55f6
    }
shun-iwasawa fd55f6
    // in the case any level for input could not be found
shun-iwasawa fd55f6
    if (!currentLevel) return false;
shun-iwasawa fd55f6
  }
shun-iwasawa fd55f6
shun-iwasawa fd55f6
  // Resize the cell container
shun-iwasawa fd55f6
  int ra   = row;
shun-iwasawa fd55f6
  int rb   = row + rowCount - 1;
shun-iwasawa fd55f6
  int c_rb = m_first + m_cells.size() - 1;
shun-iwasawa fd55f6
  if (row > c_rb) {
shun-iwasawa fd55f6
    int newCellCount = row - m_first + rowCount;
shun-iwasawa fd55f6
    m_cells.resize(newCellCount);
shun-iwasawa fd55f6
  } else if (row < m_first) {
shun-iwasawa fd55f6
    int delta = m_first - row;
shun-iwasawa fd55f6
    m_cells.insert(m_cells.begin(), delta, TXshCell());
shun-iwasawa fd55f6
    m_first = row;
shun-iwasawa fd55f6
  }
shun-iwasawa fd55f6
  if (rb > c_rb) {
shun-iwasawa fd55f6
    for (int i = 0; i < rb - c_rb; ++i) m_cells.push_back(TXshCell());
shun-iwasawa fd55f6
  }
shun-iwasawa fd55f6
shun-iwasawa fd55f6
  // Paste numbers.
shun-iwasawa fd55f6
  for (int i = 0; i < rowCount; i++) {
shun-iwasawa fd55f6
    int dstIndex     = row - m_first + i;
shun-iwasawa fd55f6
    TXshCell dstCell = m_cells[dstIndex];
shun-iwasawa fd55f6
    TXshCell srcCell = cells[i];
shun-iwasawa fd55f6
    if (srcCell.isEmpty()) {
shun-iwasawa fd55f6
      m_cells[dstIndex] = TXshCell();
shun-iwasawa fd55f6
    } else {
shun-iwasawa fd55f6
      if (!dstCell.isEmpty()) currentLevel = dstCell.m_level;
shun-iwasawa fd55f6
      m_cells[dstIndex] = TXshCell(currentLevel, srcCell.m_frameId);
shun-iwasawa fd55f6
    }
shun-iwasawa fd55f6
  }
shun-iwasawa fd55f6
shun-iwasawa fd55f6
  // Update the cell container.
shun-iwasawa fd55f6
  while (!m_cells.empty() && m_cells.back().isEmpty()) {
shun-iwasawa fd55f6
    m_cells.pop_back();
shun-iwasawa fd55f6
  }
shun-iwasawa fd55f6
  while (!m_cells.empty() && m_cells.front().isEmpty()) {
shun-iwasawa fd55f6
    m_cells.erase(m_cells.begin());
shun-iwasawa fd55f6
    m_first++;
shun-iwasawa fd55f6
  }
shun-iwasawa fd55f6
  if (m_cells.empty()) {
shun-iwasawa fd55f6
    m_first = 0;
shun-iwasawa fd55f6
  }
shun-iwasawa fd55f6
  return true;
shun-iwasawa fd55f6
}
shun-iwasawa fd55f6
shun-iwasawa fd55f6
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
PERSIST_IDENTIFIER(TXshLevelColumn, "levelColumn")