Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/scriptbinding_scene.h"
Toshihiro Shimizu 890ddd
#include "toonz/scriptbinding_level.h"
Toshihiro Shimizu 890ddd
#include "toonz/scriptbinding_files.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshleveltypes.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tsystem.h"
Toshihiro Shimizu 890ddd
#include "tfiletype.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/tproject.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzscene.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheet.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshcell.h"
Toshihiro Shimizu 890ddd
#include "toonz/levelset.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace TScriptBinding {
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
Scene::Scene() {
Shinya Kitaoka 120a6e
  m_scene = new ToonzScene();
Shinya Kitaoka 120a6e
  TProjectManager::instance()->initializeScene(m_scene);
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
Scene::~Scene() { delete m_scene; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
QScriptValue Scene::ctor(QScriptContext *context, QScriptEngine *engine) {
Shinya Kitaoka 120a6e
  QScriptValue obj = create(engine, new Scene());
Shinya Kitaoka 120a6e
  if (context->argumentCount() == 1) {
Shinya Kitaoka 120a6e
    return obj.property("load").call(obj, context->argumentsObject());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return obj;
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
QScriptValue Scene::toString() {
Shinya Kitaoka 120a6e
  return QString("Scene (%1 frames)").arg(getFrameCount());
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
int Scene::getFrameCount() { return m_scene->getFrameCount(); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
int Scene::getColumnCount() { return m_scene->getXsheet()->getColumnCount(); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
QScriptValue Scene::load(const QScriptValue &fpArg) {
Shinya Kitaoka 120a6e
  TFilePath fp;
Shinya Kitaoka 120a6e
  QScriptValue err = checkFilePath(context(), fpArg, fp);
Shinya Kitaoka 120a6e
  if (err.isError()) return err;
Shinya Kitaoka 120a6e
  if (!fp.isAbsolute())
Shinya Kitaoka 120a6e
    fp = TProjectManager::instance()->getCurrentProject()->getScenesPath() + fp;
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    if (!TSystem::doesExistFileOrLevel(fp)) {
Shinya Kitaoka 120a6e
      return context()->throwError(
Shinya Kitaoka 120a6e
          tr("File %1 doesn't exist").arg(fpArg.toString()));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    m_scene->load(fp);
Shinya Kitaoka 120a6e
    return context()->thisObject();
Shinya Kitaoka 120a6e
  } catch (...) {
Shinya Kitaoka 120a6e
    return context()->throwError(
Shinya Kitaoka 120a6e
        tr("Exception reading %1").arg(fpArg.toString()));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
QScriptValue Scene::save(const QScriptValue &fpArg) {
Shinya Kitaoka 120a6e
  TFilePath fp;
Shinya Kitaoka 120a6e
  QScriptValue err = checkFilePath(context(), fpArg, fp);
Shinya Kitaoka 120a6e
  if (err.isError()) return err;
Shinya Kitaoka 120a6e
  if (!fp.isAbsolute())
Shinya Kitaoka 120a6e
    fp = TProjectManager::instance()->getCurrentProject()->getScenesPath() + fp;
Shinya Kitaoka 120a6e
  try {
Shinya Kitaoka 120a6e
    m_scene->save(fp);
Shinya Kitaoka 120a6e
    return context()->thisObject();
Shinya Kitaoka 120a6e
  } catch (...) {
Shinya Kitaoka 120a6e
    return context()->throwError(
Shinya Kitaoka 120a6e
        tr("Exception writing %1").arg(fpArg.toString()));
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
QScriptValue Scene::getLevels() const {
Shinya Kitaoka 120a6e
  QScriptValue result = engine()->newArray();
Shinya Kitaoka 120a6e
  qint32 index        = 0;
Shinya Kitaoka 120a6e
  std::vector<txshlevel *=""> levels;</txshlevel>
Shinya Kitaoka 120a6e
  m_scene->getLevelSet()->listLevels(levels);
Shinya Kitaoka 120a6e
  for (std::vector<txshlevel *="">::iterator it = levels.begin();</txshlevel>
Shinya Kitaoka 120a6e
       it != levels.end(); ++it) {
Shinya Kitaoka 120a6e
    TXshSimpleLevel *sl = (*it)->getSimpleLevel();
Shinya Kitaoka 120a6e
    if (sl) {
Shinya Kitaoka 120a6e
      Level *level = new Level(sl);
Shinya Kitaoka 120a6e
      result.setProperty(index++, create(engine(), level));
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return result;
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
QScriptValue Scene::getLevel(const QString &name) const {
Shinya Kitaoka 120a6e
  TXshLevel *xl       = m_scene->getLevelSet()->getLevel(name.toStdWString());
Shinya Kitaoka 120a6e
  TXshSimpleLevel *sl = xl ? xl->getSimpleLevel() : 0;
Shinya Kitaoka 120a6e
  if (sl) {
Shinya Kitaoka 120a6e
    Level *level = new Level(sl);
Shinya Kitaoka 120a6e
    return create(engine(), level);
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    return QScriptValue();
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
QScriptValue Scene::newLevel(const QString &levelTypeStr,
Shinya Kitaoka 120a6e
                             const QString &levelName) const {
Shinya Kitaoka 120a6e
  int levelType = NO_XSHLEVEL;
Shinya Kitaoka 120a6e
  if (levelTypeStr == "Vector")
Shinya Kitaoka 120a6e
    levelType = PLI_XSHLEVEL;
Shinya Kitaoka 120a6e
  else if (levelTypeStr == "ToonzRaster")
Shinya Kitaoka 120a6e
    levelType = TZP_XSHLEVEL;
Shinya Kitaoka 120a6e
  else if (levelTypeStr == "Raster")
Shinya Kitaoka 120a6e
    levelType = OVL_XSHLEVEL;
Shinya Kitaoka 120a6e
  if (levelType == NO_XSHLEVEL)
Shinya Kitaoka 120a6e
    return context()->throwError(
Shinya Kitaoka 120a6e
        tr("Bad level type (%1): must be Vector,Raster or ToonzRaster")
Shinya Kitaoka 120a6e
            .arg(levelTypeStr));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_scene->getLevelSet()->hasLevel(levelName.toStdWString()))
Shinya Kitaoka 120a6e
    return context()->throwError(
Shinya Kitaoka 120a6e
        tr("Can't add the level: name(%1) is already used").arg(levelName));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TXshLevel *xl = m_scene->createNewLevel(levelType, levelName.toStdWString());
Shinya Kitaoka 120a6e
  xl->getSimpleLevel()->setDirtyFlag(true);
Shinya Kitaoka 120a6e
  return create(engine(), new Level(xl->getSimpleLevel()));
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
QScriptValue Scene::loadLevel(const QString &levelName,
Shinya Kitaoka 120a6e
                              const QScriptValue &fpArg) const {
Shinya Kitaoka 120a6e
  if (m_scene->getLevelSet()->hasLevel(levelName.toStdWString()))
Shinya Kitaoka 120a6e
    return context()->throwError(
Shinya Kitaoka 120a6e
        tr("Can't add the level: name(%1) is already used").arg(levelName));
Shinya Kitaoka 120a6e
  TFilePath fp;
Shinya Kitaoka 120a6e
  QScriptValue err = checkFilePath(context(), fpArg, fp);
Shinya Kitaoka 120a6e
  if (err.isError()) return err;
Shinya Kitaoka 120a6e
  TFileType::Type type = TFileType::getInfo(fp);
Shinya Kitaoka 120a6e
  if ((type & TFileType::VIEWABLE) == 0)
Shinya Kitaoka 120a6e
    return context()->throwError(
Shinya Kitaoka 120a6e
        tr("Can't load this kind of file as a level : %1")
Shinya Kitaoka 120a6e
            .arg(fpArg.toString()));
Shinya Kitaoka 120a6e
  TXshLevel *xl = m_scene->loadLevel(fp);
Shinya Kitaoka 120a6e
  if (!xl || !xl->getSimpleLevel())
Shinya Kitaoka 120a6e
    return context()->throwError(
Shinya Kitaoka 120a6e
        tr("Could not load level %1").arg(fpArg.toString()));
Shinya Kitaoka 120a6e
  return create(engine(), new Level(xl->getSimpleLevel()));
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
QString Scene::doSetCell(int row, int col, const QScriptValue &levelArg,
Shinya Kitaoka 120a6e
                         const QScriptValue &fidArg) {
Shinya Kitaoka 120a6e
  if (row < 0 || col < 0) {
Shinya Kitaoka 120a6e
    return "Bad row/col values";
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  QString err;
Shinya Kitaoka 120a6e
  TXshCell cell;
Shinya Kitaoka 120a6e
  cell.m_frameId = Level::getFid(fidArg, err);
Shinya Kitaoka 120a6e
  if (err != "") return err;
Shinya Kitaoka 120a6e
  Level *level = qscriptvalue_cast<level *="">(levelArg);</level>
Shinya Kitaoka 120a6e
  if (level) {
Shinya Kitaoka 120a6e
    TXshSimpleLevel *sl = level->getSimpleLevel();
Shinya Kitaoka 120a6e
    TXshLevel *xl       = m_scene->getLevelSet()->getLevel(sl->getName());
Shinya Kitaoka 120a6e
    if (!xl || xl->getSimpleLevel() != sl) {
Shinya Kitaoka 120a6e
      return tr("Level is not included in the scene : %1")
Shinya Kitaoka 120a6e
          .arg(levelArg.toString());
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    cell.m_level = sl;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    if (!levelArg.isString())
Shinya Kitaoka 120a6e
      return tr("%1 : Expected a Level instance or a level name")
Shinya Kitaoka 120a6e
          .arg(levelArg.toString());
Shinya Kitaoka 120a6e
    QString levelName = levelArg.toString();
Shinya Kitaoka 120a6e
    TXshLevel *xl = m_scene->getLevelSet()->getLevel(levelName.toStdWString());
Shinya Kitaoka 120a6e
    if (!xl)
Shinya Kitaoka 120a6e
      return tr("Level '%1' is not included in the scene").arg(levelName);
Shinya Kitaoka 120a6e
    cell.m_level = xl;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  m_scene->getXsheet()->setCell(row, col, cell);
Shinya Kitaoka 120a6e
  return "";
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
QScriptValue Scene::setCell(int row, int col, const QScriptValue &level,
Shinya Kitaoka 120a6e
                            const QScriptValue &fid) {
Shinya Kitaoka 120a6e
  QString err = doSetCell(row, col, level, fid);
Shinya Kitaoka 120a6e
  if (err != "") return context()->throwError(err);
Shinya Kitaoka 120a6e
  return context()->thisObject();
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
QScriptValue Scene::setCell(int row, int col, const QScriptValue &cellArg) {
Shinya Kitaoka 120a6e
  if (cellArg.isUndefined()) {
Shinya Kitaoka 120a6e
    if (row >= 0 && col >= 0)
Shinya Kitaoka 120a6e
      m_scene->getXsheet()->setCell(row, col, TXshCell());
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    if (!cellArg.isObject() || cellArg.property("level").isUndefined() ||
Shinya Kitaoka 120a6e
        cellArg.property("fid").isUndefined())
Shinya Kitaoka 120a6e
      return context()->throwError(
Shinya Kitaoka 120a6e
          "Third argument should be an object with attributes 'level' and "
Shinya Kitaoka 120a6e
          "'fid'");
Shinya Kitaoka 120a6e
    QScriptValue levelArg = cellArg.property("level");
Shinya Kitaoka 120a6e
    QScriptValue fidArg   = cellArg.property("fid");
Shinya Kitaoka 120a6e
    QString err           = doSetCell(row, col, levelArg, fidArg);
Shinya Kitaoka 120a6e
    if (err != "") return context()->throwError(err);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return context()->thisObject();
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
QScriptValue Scene::getCell(int row, int col) {
Shinya Kitaoka 120a6e
  TXshCell cell       = m_scene->getXsheet()->getCell(row, col);
Shinya Kitaoka 120a6e
  TXshSimpleLevel *sl = cell.getSimpleLevel();
Shinya Kitaoka 120a6e
  if (sl) {
Shinya Kitaoka 120a6e
    QScriptValue level = create(engine(), new Level(sl));
Shinya Kitaoka 120a6e
    QScriptValue fid;
Shinya Kitaoka 120a6e
    if (cell.m_frameId.getLetter() == 0)
Shinya Kitaoka 120a6e
      fid = cell.m_frameId.getNumber();
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      fid               = QString::fromStdString(cell.m_frameId.expand());
Shinya Kitaoka 120a6e
    QScriptValue result = engine()->newObject();
Shinya Kitaoka 120a6e
    result.setProperty("level", level);
Shinya Kitaoka 120a6e
    result.setProperty("fid", fid);
Shinya Kitaoka 120a6e
    return result;
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    return QScriptValue();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
QScriptValue Scene::insertColumn(int col) {
Shinya Kitaoka 120a6e
  m_scene->getXsheet()->insertColumn(col);
Shinya Kitaoka 120a6e
  return context()->thisObject();
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
QScriptValue Scene::deleteColumn(int col) {
Shinya Kitaoka 120a6e
  m_scene->getXsheet()->removeColumn(col);
Shinya Kitaoka 120a6e
  return context()->thisObject();
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
}  // namespace TScriptBinding