#include "toonz/scriptbinding_level.h" #include "toonz/scriptbinding_files.h" #include #include "timage_io.h" #include "tlevel_io.h" #include "tlevel.h" #include "toonz/tcenterlinevectorizer.h" #include "toonz/tcamera.h" #include "trop.h" #include "trasterimage.h" #include "ttoonzimage.h" #include "tvectorimage.h" #include "tpalette.h" #include "tofflinegl.h" #include "tvectorrenderdata.h" #include "tgeometry.h" #include "toonz/stage.h" #include "toonz/txshleveltypes.h" #include "toonz/levelproperties.h" #include "toonz/toonzscene.h" #include "toonz/txshsimplelevel.h" #include "toonz/levelset.h" #include "tfiletype.h" #include "tsystem.h" #include #include namespace TScriptBinding { Level::Level() : m_sl(0) , m_type(NO_XSHLEVEL) , m_scene(new ToonzScene()) , m_sceneOwner(true) {} Level::Level(TXshSimpleLevel *sl) : m_sl(sl) , m_type(sl->getType()) , m_scene(sl->getScene()) , m_sceneOwner(false) { sl->addRef(); } Level::~Level() { if (m_sceneOwner) delete m_scene; if (m_sl) m_sl->release(); } QScriptValue Level::ctor(QScriptContext *context, QScriptEngine *engine) { Level *level = new Level(); QScriptValue obj = engine->newQObject(level, QScriptEngine::AutoOwnership); if (context->argumentCount() == 1) { return obj.property("load").call(obj, context->argumentsObject()); } return obj; } QScriptValue Level::toString() { QString info = "("; QString comma = ""; if (getName() != "") { info.append(comma).append(getName()); comma = ", "; } info.append(comma).append(tr("%1 frames").arg(getFrameCount())); info.append(")"); if (m_type == PLI_XSHLEVEL) return QString("Vector level %1").arg(info); else if (m_type == TZP_XSHLEVEL) return QString("Toonz level %1").arg(info); else if (m_type == NO_XSHLEVEL) return QString("Empty level"); else if (m_type == OVL_XSHLEVEL) return QString("Raster level %1").arg(info); else return QString("Level %1").arg(info); } QString Level::getType() const { if (m_type == NO_XSHLEVEL) return "Empty"; else if (m_type == PLI_XSHLEVEL) return "Vector"; else if (m_type == TZP_XSHLEVEL) return "ToonzRaster"; else if (m_type == OVL_XSHLEVEL) return "Raster"; else return "Unknown"; } int Level::getFrameCount() const { return m_sl ? m_sl->getFrameCount() : 0; } QString Level::getName() const { return m_sl ? QString::fromStdWString(m_sl->getName()) : ""; } void Level::setName(const QString &name) { if (m_sl) m_sl->setName(name.toStdWString()); } QScriptValue Level::getPath() const { if (m_sl) { FilePath *result = new FilePath(m_sl->getPath()); return result->create(engine()); } else return QScriptValue(); return m_sl ? QString::fromStdWString(m_sl->getName()) : ""; } void Level::setPath(const QScriptValue &pathArg) { TFilePath fp; FilePath *filePath = qscriptvalue_cast(pathArg); if (filePath) fp = filePath->getToonzFilePath(); else if (pathArg.isString()) fp = TFilePath(pathArg.toString().toStdString()); else context()->throwError( tr("Bad argument (%1). It should be FilePath or string") .arg(pathArg.toString())); if (m_sl) { m_sl->setPath(fp); try { m_sl->load(); } catch (...) { context()->throwError( tr("Exception loading level (%1)") .arg(QString::fromStdWString(fp.getWideString()))); } } } QScriptValue Level::load(const QScriptValue &fpArg) { if (m_sl) { m_scene->getLevelSet()->removeLevel(m_sl, true); m_sl->release(); m_sl = 0; } // get the path TFilePath fp; QScriptValue err = checkFilePath(context(), fpArg, fp); if (err.isError()) return err; QString fpStr = fpArg.toString(); try { if (!TSystem::doesExistFileOrLevel(fp)) { return context()->throwError(tr("File %1 doesn't exist").arg(fpStr)); } TFileType::Type fileType = TFileType::getInfo(fp); if (TFileType::isVector(fileType)) m_type = PLI_XSHLEVEL; else if (0 != (fileType & TFileType::CMAPPED_IMAGE)) m_type = TZP_XSHLEVEL; else if (0 != (fileType & TFileType::RASTER_IMAGE)) m_type = OVL_XSHLEVEL; else { return context()->throwError(tr("File %1 is unsupported").arg(fpStr)); } TXshLevel *xl = m_scene->loadLevel(fp); if (xl) { m_sl = xl->getSimpleLevel(); m_sl->addRef(); } return context()->thisObject(); } catch (...) { return context()->throwError(tr("Exception reading %1").arg(fpStr)); } } QScriptValue Level::save(const QScriptValue &fpArg) { if (getFrameCount() == 0) { return context()->throwError(tr("Can't save an empty level")); } // get the path TFilePath fp; QScriptValue err = checkFilePath(context(), fpArg, fp); if (err.isError()) return err; QString fpStr = fpArg.toString(); // handle conversion (if it is needed and possible) TFileType::Type fileType = TFileType::getInfo(fp); bool isCompatible = false; if (TFileType::isFullColor(fileType)) { if (m_sl->getType() == OVL_XSHLEVEL) isCompatible = true; } else if (TFileType::isVector(fileType)) { if (m_sl->getType() == PLI_XSHLEVEL) isCompatible = true; } else if (fileType & TFileType::CMAPPED_IMAGE) { if (m_sl->getType() == TZP_XSHLEVEL) isCompatible = true; } else { return context()->throwError(tr("Unrecognized file type :").arg(fpStr)); } if (!isCompatible) { return context()->throwError( tr("Can't save a %1 level to this file type : %2") .arg(getType()) .arg(fpStr)); } try { m_sl->save(fp); } catch (TSystemException se) { return context()->throwError( tr("Exception writing %1") .arg(QString::fromStdWString(se.getMessage()))); } return context()->thisObject(); } TFrameId Level::getFid(const QScriptValue &arg, QString &err) { if (arg.isNumber() || arg.isString()) { QString s = arg.toString(); QRegExp re("(-?\\d+)(\\w?)"); if (re.exactMatch(s)) { int d = re.cap(1).toInt(); QString c = re.cap(2); TFrameId fid; if (c.length() == 1) #if QT_VERSION >= 0x050500 fid = TFrameId(d, c[0].unicode()); #else fid = TFrameId(d, c[0].toAscii()); #endif else fid = TFrameId(d); err = ""; return fid; } } err = QObject::tr("Argument '%1' does not look like a FrameId") .arg(arg.toString()); return TFrameId(); } TImageP Level::getImg(const TFrameId &fid) { if (m_sl) return m_sl->getFrame(fid, false); else return TImageP(); } QScriptValue Level::getFrame(const QScriptValue &fidArg) { if (getFrameCount() == 0) return context()->throwError("An empty level has no frames"); QString err; TFrameId fid = getFid(fidArg, err); if (err != "") return context()->throwError(err); TImageP content = m_sl->getFrame(fid, false); if (content) { Image *img = new Image(content.getPointer()); return create(img); } else { return QScriptValue(); } } QScriptValue Level::getFrameByIndex(const QScriptValue &indexArg) { if (getFrameCount() == 0) return context()->throwError("An empty level has no frames"); if (!indexArg.isNumber()) { return context()->throwError( tr("frame index (%1) must be a number").arg(indexArg.toString())); } int index = indexArg.toInteger(); if (index < 0 || index >= getFrameCount()) { return context()->throwError(tr("frame index (%1) is out of range (0-%2)") .arg(index) .arg(getFrameCount() - 1)); } TFrameId fid = m_sl->index2fid(index); TImageP content = m_sl->getFrame(fid, false); if (content) { Image *img = new Image(content.getPointer()); return create(img); } else { return QScriptValue(); } } // TODO: chiamare setFrame(const TFrameId &fid, const TImageP &img) QScriptValue Level::setFrame(const QScriptValue &fidArg, const QScriptValue &imageArg) { QString err; TFrameId fid = getFid(fidArg, err); if (err != "") return context()->throwError(err); Image *img = qscriptvalue_cast(imageArg); if (!img) { return context()->throwError( tr("second argument (%1) is not an image").arg(imageArg.toString())); } QString imgType = img->getType(); int levelType = NO_XSHLEVEL; if (imgType == "ToonzRaster") levelType = TZP_XSHLEVEL; else if (imgType == "Raster") levelType = OVL_XSHLEVEL; else if (imgType == "Vector") levelType = PLI_XSHLEVEL; else { return context()->throwError( tr("can not insert a %1 image into a level").arg(imgType)); } if (m_type == NO_XSHLEVEL) { m_type = levelType; TXshLevel *xl = m_scene->createNewLevel(levelType); m_sl = xl->getSimpleLevel(); m_sl->addRef(); m_sl->setPalette(img->getImg()->getPalette()); if (levelType != PLI_XSHLEVEL) { LevelProperties *lprop = m_sl->getProperties(); lprop->setDpiPolicy(LevelProperties::DP_ImageDpi); int xres = img->getWidth(); int yres = img->getHeight(); double dpi = img->getDpi(); lprop->setDpi(dpi); lprop->setImageDpi(TPointD(dpi, dpi)); lprop->setImageRes(TDimension(xres, yres)); // lprop->setHasAlpha(true); } } else if (m_type != levelType) { return context()->throwError(tr("can not insert a %1 image to a %2 level") .arg(imgType) .arg(getType())); } if (m_sl->getFrameCount() == 0) m_sl->setPalette(img->getImg()->getPalette()); m_sl->setFrame(fid, img->getImg()); m_sl->setDirtyFlag(true); return context()->thisObject(); } QScriptValue Level::getFrameIds() { QList fids; getFrameIds(fids); QScriptValue result = engine()->newArray(); quint32 index = 0; for (const TFrameId &fid : fids) { QString fidStr = QString::fromStdString(fid.expand()); result.setProperty(index++, fidStr); } return result; } void Level::getFrameIds(QList &result) { if (getFrameCount() > 0) { std::vector fids; m_sl->getFids(fids); for (std::vector::iterator it = fids.begin(); it != fids.end(); ++it) { result.append(*it); } } } int Level::setFrame(const TFrameId &fid, const TImageP &img) { TImage::Type imgType = img->getType(); int levelType = NO_XSHLEVEL; if (imgType == TImage::TOONZ_RASTER) levelType = TZP_XSHLEVEL; else if (imgType == TImage::RASTER) levelType = OVL_XSHLEVEL; else if (imgType == TImage::VECTOR) levelType = PLI_XSHLEVEL; else { return -1; } if (m_type == NO_XSHLEVEL) { m_type = levelType; TXshLevel *xl = m_scene->createNewLevel(levelType); m_sl = xl->getSimpleLevel(); m_sl->addRef(); m_sl->setPalette(img->getPalette()); if (levelType != PLI_XSHLEVEL) { LevelProperties *lprop = m_sl->getProperties(); lprop->setDpiPolicy(LevelProperties::DP_ImageDpi); int xres = 0, yres = 0; double dpix = 0, dpiy = 0; if (TRasterImageP ri = img) { if (ri->getRaster()) { TDimension size = ri->getRaster()->getSize(); xres = size.lx; yres = size.ly; ri->getDpi(dpix, dpiy); } } else if (TToonzImageP ti = img) { if (ti->getRaster()) { TDimension size = ri->getRaster()->getSize(); xres = size.lx; yres = size.ly; ri->getDpi(dpix, dpiy); } } lprop->setDpi(dpix); lprop->setImageDpi(TPointD(dpix, dpiy)); lprop->setImageRes(TDimension(xres, yres)); // lprop->setHasAlpha(true); } } else if (m_type != levelType) { return -2; } if (m_sl->getFrameCount() == 0) m_sl->setPalette(img->getPalette()); m_sl->setFrame(fid, img); m_sl->setDirtyFlag(true); return 1; } } // namespace TScriptBinding