From 23085f49c0763d220fb834d2bfa9128c6ca2d3d3 Mon Sep 17 00:00:00 2001 From: Rodney Date: Feb 05 2022 11:44:15 +0000 Subject: Merge pull request #4241 from shun-iwasawa/frame_format Raster level frame number format & PNG for new Raster level --- diff --git a/stuff/config/qss/Blue/Blue.qss b/stuff/config/qss/Blue/Blue.qss index 09d5d1d..2a0918b 100644 --- a/stuff/config/qss/Blue/Blue.qss +++ b/stuff/config/qss/Blue/Blue.qss @@ -1727,6 +1727,15 @@ ProjectPopup QLabel { padding-right: 5px; } /* ----------------------------------------------------------------------------- + Frame format settings box in FormatSettingsPopup +----------------------------------------------------------------------------- */ +#FrameFormatBoxInput { + border-color: rgba(135, 22, 22, 0.82); +} +#FrameFormatBoxOutput { + border-color: rgba(21, 22, 136, 0.82); +} +/* ----------------------------------------------------------------------------- Schematic Viewer ----------------------------------------------------------------------------- */ SchematicViewer { diff --git a/stuff/config/qss/Dark/Dark.qss b/stuff/config/qss/Dark/Dark.qss index f62c3e7..7baa0b1 100644 --- a/stuff/config/qss/Dark/Dark.qss +++ b/stuff/config/qss/Dark/Dark.qss @@ -1727,6 +1727,15 @@ ProjectPopup QLabel { padding-right: 5px; } /* ----------------------------------------------------------------------------- + Frame format settings box in FormatSettingsPopup +----------------------------------------------------------------------------- */ +#FrameFormatBoxInput { + border-color: rgba(124, 10, 10, 0.82); +} +#FrameFormatBoxOutput { + border-color: rgba(10, 10, 124, 0.82); +} +/* ----------------------------------------------------------------------------- Schematic Viewer ----------------------------------------------------------------------------- */ SchematicViewer { diff --git a/stuff/config/qss/Default/Default.qss b/stuff/config/qss/Default/Default.qss index 91656df..ca58c07 100644 --- a/stuff/config/qss/Default/Default.qss +++ b/stuff/config/qss/Default/Default.qss @@ -1727,6 +1727,15 @@ ProjectPopup QLabel { padding-right: 5px; } /* ----------------------------------------------------------------------------- + Frame format settings box in FormatSettingsPopup +----------------------------------------------------------------------------- */ +#FrameFormatBoxInput { + border-color: rgba(138, 24, 24, 0.82); +} +#FrameFormatBoxOutput { + border-color: rgba(24, 24, 138, 0.82); +} +/* ----------------------------------------------------------------------------- Schematic Viewer ----------------------------------------------------------------------------- */ SchematicViewer { diff --git a/stuff/config/qss/Default/less/layouts/popups.less b/stuff/config/qss/Default/less/layouts/popups.less index e2a290b..5f5c9eb 100644 --- a/stuff/config/qss/Default/less/layouts/popups.less +++ b/stuff/config/qss/Default/less/layouts/popups.less @@ -127,3 +127,13 @@ ProjectPopup { padding-left: 5px; padding-right: 5px; } + +/* ----------------------------------------------------------------------------- + Frame format settings box in FormatSettingsPopup +----------------------------------------------------------------------------- */ +#FrameFormatBoxInput { + border-color: mix(@accent, rgba(255, 0, 0, 0.7), 40); +} +#FrameFormatBoxOutput { + border-color: mix(@accent, rgba(0, 0, 255, 0.7), 40); +} \ No newline at end of file diff --git a/stuff/config/qss/Light/Light.qss b/stuff/config/qss/Light/Light.qss index d7e84ff..df9ba4c 100644 --- a/stuff/config/qss/Light/Light.qss +++ b/stuff/config/qss/Light/Light.qss @@ -1727,6 +1727,15 @@ ProjectPopup QLabel { padding-right: 5px; } /* ----------------------------------------------------------------------------- + Frame format settings box in FormatSettingsPopup +----------------------------------------------------------------------------- */ +#FrameFormatBoxInput { + border-color: rgba(207, 93, 93, 0.82); +} +#FrameFormatBoxOutput { + border-color: rgba(93, 93, 207, 0.82); +} +/* ----------------------------------------------------------------------------- Schematic Viewer ----------------------------------------------------------------------------- */ SchematicViewer { diff --git a/stuff/config/qss/Neutral/Neutral.qss b/stuff/config/qss/Neutral/Neutral.qss index f13c1f4..99e8eef 100644 --- a/stuff/config/qss/Neutral/Neutral.qss +++ b/stuff/config/qss/Neutral/Neutral.qss @@ -1727,6 +1727,15 @@ ProjectPopup QLabel { padding-right: 5px; } /* ----------------------------------------------------------------------------- + Frame format settings box in FormatSettingsPopup +----------------------------------------------------------------------------- */ +#FrameFormatBoxInput { + border-color: rgba(164, 50, 50, 0.82); +} +#FrameFormatBoxOutput { + border-color: rgba(50, 50, 164, 0.82); +} +/* ----------------------------------------------------------------------------- Schematic Viewer ----------------------------------------------------------------------------- */ SchematicViewer { diff --git a/toonz/sources/common/timage_io/tlevel_io.cpp b/toonz/sources/common/timage_io/tlevel_io.cpp index 4451d5e..3a6e379 100644 --- a/toonz/sources/common/timage_io/tlevel_io.cpp +++ b/toonz/sources/common/timage_io/tlevel_io.cpp @@ -186,7 +186,8 @@ TLevelWriter::TLevelWriter(const TFilePath &path, TPropertyGroup *prop) : TSmartObject(m_classCode) , m_path(path) , m_properties(prop) - , m_contentHistory(0) { + , m_contentHistory(0) + , m_frameFormatTemplateFId(TFrameId::NO_FRAME) { string ext = path.getType(); if (!prop) m_properties = Tiio::makeWriterProperties(ext); } @@ -250,6 +251,12 @@ void TLevelWriter::getSupportedFormats(QStringList &names, //----------------------------------------------------------- TImageWriterP TLevelWriter::getFrameWriter(TFrameId fid) { + // change the frame format with the template + if (!m_frameFormatTemplateFId.isNoFrame()) { + fid.setZeroPadding(m_frameFormatTemplateFId.getZeroPadding()); + fid.setStartSeqInd(m_frameFormatTemplateFId.getStartSeqInd()); + } + TImageWriterP iw(m_path.withFrame(fid)); iw->setProperties(m_properties); return iw; diff --git a/toonz/sources/common/tsystem/tfilepath.cpp b/toonz/sources/common/tsystem/tfilepath.cpp index 33e2338..2f479d1 100644 --- a/toonz/sources/common/tsystem/tfilepath.cpp +++ b/toonz/sources/common/tsystem/tfilepath.cpp @@ -567,6 +567,36 @@ std::string TFilePath::getDots() const { //----------------------------------------------------------------------------- +QChar TFilePath::getSepChar() const { + if (!TFilePath::m_useStandard) return analyzePath().sepChar; + //----- + QString type = QString::fromStdString(getType()).toLower(); + if (isFfmpegType()) return QChar(); + int i = getLastSlash(m_path); + std::wstring str = m_path.substr(i + 1); + // potrei anche avere a.b.c.d dove d e' l'estensione + i = str.rfind(L"."); + if (i == (int)std::wstring::npos || str == L"..") return QChar(); + + int j = str.substr(0, i).rfind(L"."); + + if (j != (int)std::wstring::npos) + return (j == i - 1 || (checkForSeqNum(type) && isNumbers(str, j, i))) + ? QChar('.') + : QChar(); + if (!m_underscoreFormatAllowed) return QChar(); + + j = str.substr(0, i).rfind(L"_"); + if (j != (int)std::wstring::npos) + return (j == i - 1 || (checkForSeqNum(type) && isNumbers(str, j, i))) + ? QChar('_') + : QChar(); + else + return QChar(); +} + +//----------------------------------------------------------------------------- + std::string TFilePath::getDottedType() const // ritorna l'estensione con PUNTO (se c'e') { @@ -875,7 +905,8 @@ TFilePath TFilePath::withFrame(const TFrameId &frame, if (frame.isNoFrame()) { return TFilePath(info.parentDir + info.levelName + "." + info.extension); } - QString sepChar = (info.sepChar.isNull()) ? "." : QString(info.sepChar); + QString sepChar = (info.sepChar.isNull()) ? QString(frame.getStartSeqInd()) + : QString(info.sepChar); return TFilePath(info.parentDir + info.levelName + sepChar + QString::fromStdString(frame.expand(format)) + "." + diff --git a/toonz/sources/include/tfilepath.h b/toonz/sources/include/tfilepath.h index 72700ae..0ed8bf6 100644 --- a/toonz/sources/include/tfilepath.h +++ b/toonz/sources/include/tfilepath.h @@ -311,6 +311,8 @@ type is a string that indicate the filename extension(ex:. bmp or .bmp)*/ void split(std::wstring &head, TFilePath &tail) const; TFilePathInfo analyzePath() const; + + QChar getSepChar() const; }; //----------------------------------------------------------------------------- diff --git a/toonz/sources/include/tlevel_io.h b/toonz/sources/include/tlevel_io.h index 056364f..c5f3de7 100644 --- a/toonz/sources/include/tlevel_io.h +++ b/toonz/sources/include/tlevel_io.h @@ -82,12 +82,11 @@ public: static FormatType getFormatType(std::string extension); - static void define( - QString extension, int reader, - // nel caso in cui ci siano piu' lettori per lo stesso formato - // (es. flash) + static void define(QString extension, int reader, + // nel caso in cui ci siano piu' lettori per lo stesso + // formato (es. flash) - TLevelReaderCreateProc *proc); + TLevelReaderCreateProc *proc); static inline void define(QString extension, TLevelReaderCreateProc *proc) { define(extension, 0, proc); @@ -136,6 +135,9 @@ protected: TContentHistory *m_contentHistory; QString m_creator; + // if template is not used, frame number is set to TFrameId::NO_FRAME + TFrameId m_frameFormatTemplateFId; + public: TLevelWriter(const TFilePath &path, TPropertyGroup *winfo = 0); // ottiene l'ownership @@ -203,6 +205,10 @@ public: static void define(QString extension, TLevelWriterCreateProc *proc, bool isRenderFormat); + + void setFrameFormatTemplateFId(const TFrameId &tmplFId) { + m_frameFormatTemplateFId = tmplFId; + } }; //----------------------------------------------------------- diff --git a/toonz/sources/include/toonz/levelupdater.h b/toonz/sources/include/toonz/levelupdater.h index 5666b9c..f8657f7 100644 --- a/toonz/sources/include/toonz/levelupdater.h +++ b/toonz/sources/include/toonz/levelupdater.h @@ -124,7 +124,8 @@ class DVAPI LevelUpdater { public: LevelUpdater(); LevelUpdater(TXshSimpleLevel *sl); - LevelUpdater(const TFilePath &path, TPropertyGroup *lwProperties = 0); + LevelUpdater(const TFilePath &path, TPropertyGroup *lwProperties = 0, + const TFrameId &tmplFId = TFrameId(TFrameId::NO_FRAME)); ~LevelUpdater(); TLevelWriterP getLevelWriter() { return m_lw; } @@ -142,7 +143,8 @@ public: //! This function may throw in case the specified path has an unrecognized //! extension, or the file could //! not be opened for write. - void open(const TFilePath &src, TPropertyGroup *lwProperties); + void open(const TFilePath &src, TPropertyGroup *lwProperties, + const TFrameId &tmplFId); //! Attaches the updater to the specified simple level instance. Format //! properties are the default in case the level diff --git a/toonz/sources/include/toonz/preferences.h b/toonz/sources/include/toonz/preferences.h index 365948d..1855ea1 100644 --- a/toonz/sources/include/toonz/preferences.h +++ b/toonz/sources/include/toonz/preferences.h @@ -9,6 +9,7 @@ #include "tcommon.h" #include "tgeometry.h" #include "tpixel.h" +#include "tfilepath.h" // TnzLib includes #include "toonz/levelproperties.h" @@ -36,7 +37,6 @@ // Forward declarations -class TFilePath; class QSettings; //============================================================== @@ -286,7 +286,8 @@ public: bool getFfmpegMultiThread() const { return getBoolValue(ffmpegMultiThread); } // Drawing tab - QString getScanLevelType() const { return getStringValue(scanLevelType); } + QString getDefRasterFormat() const { return getStringValue(DefRasterFormat); } + // QString getScanLevelType() const { return getStringValue(scanLevelType); } int getDefLevelType() const { return getIntValue(DefLevelType); } bool isNewLevelSizeToCameraSizeEnabled() const { return getBoolValue(newLevelSizeToCameraSizeEnabled); diff --git a/toonz/sources/include/toonz/preferencesitemids.h b/toonz/sources/include/toonz/preferencesitemids.h index ada431e..b84e28d 100644 --- a/toonz/sources/include/toonz/preferencesitemids.h +++ b/toonz/sources/include/toonz/preferencesitemids.h @@ -79,7 +79,8 @@ enum PreferencesItemId { //---------- // Drawing - scanLevelType, + DefRasterFormat, + // scanLevelType,// deprecated DefLevelType, newLevelSizeToCameraSizeEnabled, DefLevelWidth, diff --git a/toonz/sources/include/toonz/sceneproperties.h b/toonz/sources/include/toonz/sceneproperties.h index 06b1b9d..c79e2ea 100644 --- a/toonz/sources/include/toonz/sceneproperties.h +++ b/toonz/sources/include/toonz/sceneproperties.h @@ -295,6 +295,10 @@ and height. bool hasDefaultCellMarks() const; // check if the cell mark settings are modified + // templateFId in preview settings is used for "input" file format + // such as new raster level, captured images by camera capture feature, etc. + TFrameId &formatTemplateFIdForInput(); + private: // not implemented TSceneProperties(const TSceneProperties &); diff --git a/toonz/sources/include/toonz/txshsimplelevel.h b/toonz/sources/include/toonz/txshsimplelevel.h index 0a2c2b9..2ed4b8e 100644 --- a/toonz/sources/include/toonz/txshsimplelevel.h +++ b/toonz/sources/include/toonz/txshsimplelevel.h @@ -185,6 +185,7 @@ table) it returns the proper insertion index //! from each entry to the next. int guessStep() const; + void formatFId(TFrameId &fid, TFrameId tmplFId); void setFrame(const TFrameId &fid, const TImageP &img); TImageP getFrame(const TFrameId &fid, UCHAR imgManagerParamsMask, diff --git a/toonz/sources/include/toonzqt/imageutils.h b/toonz/sources/include/toonzqt/imageutils.h index ce355d9..95d3ba1 100644 --- a/toonz/sources/include/toonzqt/imageutils.h +++ b/toonz/sources/include/toonzqt/imageutils.h @@ -98,10 +98,11 @@ void DVAPI convert( const TPixel &bgColor = TPixel::Transparent, //!< Destination Background color. bool removeDotBeforeFrameNumber = - false /*-- ConvertPopup - での指定に合わせて、[レベル名].[フレーム番号].[拡張子]のうち、 - [レベル名]と[フレーム番号]の間のドットを消す。 --*/ -); //!< Converts a saved level to fullcolor, and saves the result. + false, /*-- ConvertPopup + での指定に合わせて、[レベル名].[フレーム番号].[拡張子]のうち、 + [レベル名]と[フレーム番号]の間のドットを消す。 --*/ + const TFrameId &tmplFId = TFrameId() //!< frame format template +); //!< Converts a saved level to fullcolor, and saves the result. void DVAPI convertNaa2Tlv( const TFilePath &source, //!< Level path to convert from. diff --git a/toonz/sources/include/toutputproperties.h b/toonz/sources/include/toutputproperties.h index ff12ee1..a12382d 100644 --- a/toonz/sources/include/toutputproperties.h +++ b/toonz/sources/include/toutputproperties.h @@ -94,6 +94,10 @@ private: BoardSettings *m_boardSettings; + // templateFId in preview settings is used for "input" file format + // such as new raster level, captured images by camera capture feature, etc. + TFrameId m_formatTemplateFId; + public: /*! Constructs TOutputProperties with default value. @@ -221,6 +225,8 @@ machine's CPU). void setSubcameraPreview(bool enabled) { m_subcameraPreview = enabled; } BoardSettings *getBoardSettings() const { return m_boardSettings; } + + TFrameId &formatTemplateFId() { return m_formatTemplateFId; } }; //-------------------------------------------- diff --git a/toonz/sources/tnztools/tool.cpp b/toonz/sources/tnztools/tool.cpp index 1468a64..3477fc3 100644 --- a/toonz/sources/tnztools/tool.cpp +++ b/toonz/sources/tnztools/tool.cpp @@ -34,6 +34,7 @@ #include "toonz/dpiscale.h" #include "toonz/palettecontroller.h" #include "toonz/tonionskinmaskhandle.h" +#include "toutputproperties.h" // TnzCore includes #include "tvectorimage.h" @@ -312,6 +313,11 @@ TImage *TTool::touchImage() { TFrameHandle *currentFrame = m_application->getCurrentFrame(); TXshLevelHandle *currentLevel = m_application->getCurrentLevel(); + TFrameId tmplFId = m_application->getCurrentScene() + ->getScene() + ->getProperties() + ->formatTemplateFIdForInput(); + if (currentFrame->isEditingLevel()) { // Editing level @@ -330,6 +336,8 @@ TImage *TTool::touchImage() { // create a new drawing img = sl->createEmptyFrame(); + // modify frameId to be with the same frame format as existing frames + sl->formatFId(fid, tmplFId); sl->setFrame(fid, img); currentLevel->notifyLevelChange(); m_isFrameCreated = true; @@ -390,6 +398,8 @@ TImage *TTool::touchImage() { // create the new drawing TImageP img = sl->createEmptyFrame(); m_isFrameCreated = true; + // modify frameId to be with the same frame format as existing frames + sl->formatFId(fid, tmplFId); // insert the drawing in the level sl->setFrame(fid, img); // update the cell @@ -469,6 +479,9 @@ TImage *TTool::touchImage() { // create the new drawing TImageP img = sl->createEmptyFrame(); m_isFrameCreated = true; + + // modify frameId to be with the same frame format as existing frames + sl->formatFId(fid, tmplFId); // insert the drawing in the level sl->setFrame(fid, img); // update the cell @@ -517,6 +530,8 @@ TImage *TTool::touchImage() { TFrameId fid = animationSheetEnabled ? getNewFrameId(sl, row) : TFrameId(1); TImageP img = sl->createEmptyFrame(); m_isFrameCreated = true; + // modify frameId to be with the same frame format as existing frames + sl->formatFId(fid, tmplFId); sl->setFrame(fid, img); cell = TXshCell(sl, fid); xsh->setCell(row, col, cell); diff --git a/toonz/sources/toonz/cellselection.cpp b/toonz/sources/toonz/cellselection.cpp index 1f648ab..5abc0bf 100644 --- a/toonz/sources/toonz/cellselection.cpp +++ b/toonz/sources/toonz/cellselection.cpp @@ -54,6 +54,8 @@ #include "toonz/tstageobjecttree.h" #include "toonz/stage.h" #include "vectorizerpopup.h" +#include "toonz/sceneproperties.h" +#include "toutputproperties.h" // TnzCore includes #include "timagecache.h" @@ -607,7 +609,9 @@ bool pasteRasterImageInCellWithoutUndo(int row, int col, TXshSimpleLevel *sl = 0; TFrameId fid(1); ToonzScene *scene = app->getCurrentScene()->getScene(); - TCamera *camera = scene->getCurrentCamera(); + TFrameId tmplFId = scene->getProperties()->formatTemplateFIdForInput(); + + TCamera *camera = scene->getCurrentCamera(); if (cell.isEmpty()) { if (row > 0) cell = xsh->getCell(row - 1, col); sl = cell.getSimpleLevel(); @@ -635,6 +639,10 @@ bool pasteRasterImageInCellWithoutUndo(int row, int col, img = sl->createEmptyFrame(); } else return false; + + // modify frameId to be with the same frame format as existing frames + sl->formatFId(fid, tmplFId); + sl->setFrame(fid, img); app->getCurrentLevel()->setLevel(sl); app->getCurrentLevel()->notifyLevelChange(); @@ -647,6 +655,10 @@ bool pasteRasterImageInCellWithoutUndo(int row, int col, std::vector fids; sl->getFids(fids); if (fids.size() > 0) fid = TFrameId(fids.back().getNumber() + 1); + + // modify frameId to be with the same frame format as existing frames + sl->formatFId(fid, tmplFId); + sl->setFrame(fid, img); } xsh->setCell(row, col, TXshCell(sl, fid)); @@ -2932,6 +2944,10 @@ static void createNewDrawing(TXsheet *xsh, int row, int col, while (fid.getLetter().toUtf8().at(0) < 'z' && sl->isFid(fid)) fid = TFrameId(fid.getNumber(), fid.getLetter().toUtf8().at(0) + 1); } + // modify frameId to be with the same frame format as existing frames + TFrameId tmplFId = + xsh->getScene()->getProperties()->formatTemplateFIdForInput(); + sl->formatFId(fid, tmplFId); // add the new frame sl->setFrame(fid, sl->createEmptyFrame()); TApp::instance()->getCurrentLevel()->notifyLevelChange(); diff --git a/toonz/sources/toonz/convertpopup.cpp b/toonz/sources/toonz/convertpopup.cpp index c6c32dc..2dbeb33 100644 --- a/toonz/sources/toonz/convertpopup.cpp +++ b/toonz/sources/toonz/convertpopup.cpp @@ -228,7 +228,8 @@ void ConvertPopup::Converter::convertLevel( TPixel32 bgColor = m_parent->m_bgColorField->getColor(); ImageUtils::convert(sourceFileFullPath, dstFileFullPath, from, to, framerate, prop, m_parent->m_notifier, bgColor, - m_parent->m_removeDotBeforeFrameNumber->isChecked()); + m_parent->m_removeDotBeforeFrameNumber->isChecked(), + oprop->formatTemplateFId()); } popup->m_notifier->notifyLevelCompleted(dstFileFullPath); @@ -1046,12 +1047,11 @@ TFilePath ConvertPopup::getDestinationFilePath( const TFilePath &sourceFilePath) { // Build the DECODED output folder path TFilePath destFolder = sourceFilePath.getParentDir(); + ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); if (!m_saveInFileFld->getPath().isEmpty()) { TFilePath dir(m_saveInFileFld->getPath().toStdWString()); - - ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); - destFolder = scene->decodeFilePath(dir); + destFolder = scene->decodeFilePath(dir); } // Build the output level name @@ -1066,10 +1066,11 @@ TFilePath ConvertPopup::getDestinationFilePath( TFilePath destName = TFilePath(name).withType(ext); if (TFileType::isLevelFilePath(sourceFilePath) && - !TFileType::isLevelExtension(ext)) - destName = destName.withFrame(TFrameId::EMPTY_FRAME); // use the '..' - // format to denote - // an output level + !TFileType::isLevelExtension(ext)) { + // add ".." or "_." according to the output settings' frame format template. + TOutputProperties *prop = scene->getProperties()->getOutputProperties(); + destName = destName.withFrame(prop->formatTemplateFId()); + } // Merge the two return destFolder + destName; @@ -1280,8 +1281,12 @@ void ConvertPopup::onOptionsClicked() { std::string ext = m_fileFormat->currentText().toStdString(); TPropertyGroup *props = getFormatProperties(ext); + // use output settings' frame format. + ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); + TOutputProperties *prop = scene->getProperties()->getOutputProperties(); + openFormatSettingsPopup( - this, ext, props, + this, ext, props, &prop->formatTemplateFId(), false, m_srcFilePaths.size() == 1 ? m_srcFilePaths[0] : TFilePath()); } diff --git a/toonz/sources/toonz/exportlevelcommand.cpp b/toonz/sources/toonz/exportlevelcommand.cpp index e0b7c90..d2752e9 100644 --- a/toonz/sources/toonz/exportlevelcommand.cpp +++ b/toonz/sources/toonz/exportlevelcommand.cpp @@ -442,8 +442,15 @@ bool IoCmd::exportLevel(const TFilePath &path, TXshSimpleLevel *sl, QString::fromStdString(m_sl->index2fid(i).expand()) + "." + QString::fromStdString(m_path.getType()); fpout = TFilePath(pathOut.toStdString()); - } else - fpout = TFilePath(m_path.withFrame(m_sl->index2fid(i))); + } else { + // change frame format for saving + TFrameId formattedFId(m_sl->index2fid(i)); + formattedFId.setZeroPadding( + m_opts.m_formatTemplateFId.getZeroPadding()); + formattedFId.setStartSeqInd( + m_opts.m_formatTemplateFId.getStartSeqInd()); + fpout = TFilePath(m_path.withFrame(formattedFId)); + } // Ask for overwrite permission in case a level with the built path // already exists diff --git a/toonz/sources/toonz/exportlevelcommand.h b/toonz/sources/toonz/exportlevelcommand.h index 72a5462..652e3d1 100644 --- a/toonz/sources/toonz/exportlevelcommand.h +++ b/toonz/sources/toonz/exportlevelcommand.h @@ -46,9 +46,9 @@ struct ProgressCallbacks { virtual ~ProgressCallbacks() {} virtual void setProcessedName(const QString &name) = 0; - virtual void setRange(int min, int max) = 0; - virtual void setValue(int val) = 0; - virtual bool canceled() const = 0; + virtual void setRange(int min, int max) = 0; + virtual void setValue(int val) = 0; + virtual bool canceled() const = 0; }; //************************************************************************************ @@ -79,12 +79,15 @@ struct ExportLevelOptions { //! \li Transparent pixels mapped to white bool m_noAntialias; //!< Whether antialias must be removed from images. + TFrameId m_formatTemplateFId; + public: ExportLevelOptions() : m_props(0) , m_bgColor(TPixel32::Transparent) , m_forRetas(false) - , m_noAntialias(false) { + , m_noAntialias(false) + , m_formatTemplateFId() { m_thicknessTransform[0][0] = 0.0, m_thicknessTransform[0][1] = 1.0; m_thicknessTransform[1][0] = 0.0, m_thicknessTransform[1][1] = 1.0; } @@ -111,7 +114,7 @@ TImageP exportedImage( const TXshSimpleLevel &sl, //!< Level host of the image to be exported. const TFrameId &fid, //!< Frame of the image in sl. const ExportLevelOptions &opts = ExportLevelOptions() //!< Export options. - ); +); //--------------------------------------------------------------------- @@ -142,7 +145,7 @@ bool exportLevel( 0, //!< External callbacks to overwrite requests. ProgressCallbacks *progressCB = 0 //!< External callbacks to progress notifications. - ); +); } // namespace IoCmd diff --git a/toonz/sources/toonz/exportlevelpopup.cpp b/toonz/sources/toonz/exportlevelpopup.cpp index 05a286c..8e5b3e6 100644 --- a/toonz/sources/toonz/exportlevelpopup.cpp +++ b/toonz/sources/toonz/exportlevelpopup.cpp @@ -36,6 +36,7 @@ #include "toonz/txshlevelhandle.h" #include "toonz/txsheethandle.h" #include "toonz/tscenehandle.h" +#include "toutputproperties.h" // TnzCore includes #include "tiio.h" @@ -477,6 +478,10 @@ IoCmd::ExportLevelOptions ExportLevelPopup::getOptions(const std::string &ext) { opts.m_props = getFormatProperties(ext); opts.m_forRetas = (m_retas->checkState() == Qt::Checked); + ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); + opts.m_formatTemplateFId = + scene->getProperties()->formatTemplateFIdForInput(); + return opts; } @@ -521,14 +526,20 @@ void ExportLevelPopup::checkAlpha() { void ExportLevelPopup::onOptionsClicked() { std::string ext = m_format->currentText().toStdString(); TPropertyGroup *props = getFormatProperties(ext); - setModal(false); - if (DVGui::Dialog *dialog = - openFormatSettingsPopup(this, ext, props, m_browser->getFolder())) { - bool ret; - ret = connect(dialog, SIGNAL(dialogClosed()), SLOT(checkAlpha())), - assert(ret); + // use preview settings' frame format. + // hide options when the Retas option is enabled. + TFrameId *tmplFId = nullptr; + if (!m_retas->isChecked()) { + ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); + tmplFId = &scene->getProperties()->formatTemplateFIdForInput(); } + + setModal(false); + + if (openFormatSettingsPopup(this, ext, props, tmplFId, true, + m_browser->getFolder())) + checkAlpha(); } //-------------------------------------------------------------- @@ -616,14 +627,19 @@ bool ExportLevelPopup::execute() { const std::string &ext = m_format->currentText().toStdString(); const IoCmd::ExportLevelOptions &opts = getOptions(ext); + TApp *app = TApp::instance(); + + ToonzScene *scene = app->getCurrentScene()->getScene(); + TFrameId tmplFId = scene->getProperties()->formatTemplateFIdForInput(); + // Retrieve current column selection - TApp *app = TApp::instance(); + TSelection *selection = app->getCurrentSelection()->getSelection(); TColumnSelection *colSelection = dynamic_cast(selection); if (colSelection && colSelection->getIndices().size() > 1) { fp = TFilePath(m_browser->getFolder() + TFilePath("a")) .withType(ext) - .withFrame(); + .withFrame(tmplFId); bool ret = true; MultiExportOverwriteCB overwriteCB; @@ -661,7 +677,7 @@ bool ExportLevelPopup::execute() { if (isReservedFileName_message(QString::fromStdString(fp.getName()))) return false; - return IoCmd::exportLevel(fp.withType(ext).withFrame(), 0, opts); + return IoCmd::exportLevel(fp.withType(ext).withFrame(tmplFId), 0, opts); } } diff --git a/toonz/sources/toonz/formatsettingspopups.cpp b/toonz/sources/toonz/formatsettingspopups.cpp index 9cdac24..de8ab31 100644 --- a/toonz/sources/toonz/formatsettingspopups.cpp +++ b/toonz/sources/toonz/formatsettingspopups.cpp @@ -22,6 +22,7 @@ #include "tproperty.h" #include "movsettings.h" #include "timageinfo.h" +#include "tfiletype.h" // Qt includes #include @@ -29,6 +30,17 @@ #include #include #include +#include + +namespace { +bool checkForSeqNum(QString type) { + TFileType::Type typeInfo = TFileType::getInfoFromExtension(type); + if ((typeInfo & TFileType::IMAGE) && !(typeInfo & TFileType::LEVEL)) + return true; + else + return false; +} +}; // namespace //********************************************************************************** // FormatSettingsPopup implementation @@ -36,7 +48,8 @@ FormatSettingsPopup::FormatSettingsPopup(QWidget *parent, const std::string &format, - TPropertyGroup *props) + TPropertyGroup *props, + TFrameId *tmplFrameId, bool forInput) : Dialog(parent) , m_format(format) , m_props(props) @@ -46,7 +59,9 @@ FormatSettingsPopup::FormatSettingsPopup(QWidget *parent, , m_codecComboBox(0) , m_configureCodec(0) #endif -{ + , m_sepCharCB(nullptr) + , m_paddingCB(nullptr) + , m_tmplFId(tmplFrameId) { setWindowTitle(tr("File Settings")); setWindowFlags(Qt::Dialog | Qt::WindowStaysOnTopHint); @@ -58,20 +73,22 @@ FormatSettingsPopup::FormatSettingsPopup(QWidget *parent, m_mainLayout->setColumnStretch(0, 0); m_mainLayout->setColumnStretch(1, 1); - int i = 0; - for (i = 0; i < m_props->getPropertyCount(); i++) { - if (dynamic_cast(m_props->getProperty(i))) - buildPropertyComboBox(i, m_props); - else if (dynamic_cast(m_props->getProperty(i))) - buildValueField(i, m_props); - else if (dynamic_cast(m_props->getProperty(i))) - buildDoubleField(i, m_props); - else if (dynamic_cast(m_props->getProperty(i))) - buildPropertyCheckBox(i, m_props); - else if (dynamic_cast(m_props->getProperty(i))) - buildPropertyLineEdit(i, m_props); - else - assert(false); + if (m_props) { + int i = 0; + for (i = 0; i < m_props->getPropertyCount(); i++) { + if (dynamic_cast(m_props->getProperty(i))) + buildPropertyComboBox(i, m_props); + else if (dynamic_cast(m_props->getProperty(i))) + buildValueField(i, m_props); + else if (dynamic_cast(m_props->getProperty(i))) + buildDoubleField(i, m_props); + else if (dynamic_cast(m_props->getProperty(i))) + buildPropertyCheckBox(i, m_props); + else if (dynamic_cast(m_props->getProperty(i))) + buildPropertyLineEdit(i, m_props); + else + assert(false); + } } #ifdef _WIN32 @@ -91,6 +108,51 @@ FormatSettingsPopup::FormatSettingsPopup(QWidget *parent, } #endif + if (checkForSeqNum(QString::fromStdString(format)) && tmplFrameId) { + m_sepCharCB = new QComboBox(this); + m_paddingCB = new QComboBox(this); + + m_sepCharCB->addItem(tr(". (period)"), QChar('.')); + m_sepCharCB->addItem(tr("_ (underscore)"), QChar('_')); + m_sepCharCB->setCurrentIndex(m_sepCharCB->findData( + QChar::fromLatin1(tmplFrameId->getStartSeqInd()))); + + m_paddingCB->addItem(tr("No padding"), 0); + for (int p = 1; p <= 6; p++) m_paddingCB->addItem(QString::number(p), p); + m_paddingCB->setCurrentIndex( + m_paddingCB->findData(tmplFrameId->getZeroPadding())); + + int currentRow = m_mainLayout->rowCount(); + if (currentRow > 0) + m_mainLayout->addItem(new QSpacerItem(15, 15), currentRow, 0); + + QGroupBox *frameFormatGB = new QGroupBox(tr("Frame Number Format"), this); + + frameFormatGB->setObjectName((forInput) ? "FrameFormatBoxInput" + : "FrameFormatBoxOutput"); + + QGridLayout *frameFormatLay = new QGridLayout(); + frameFormatLay->setColumnStretch(0, 0); + frameFormatLay->setColumnStretch(1, 1); + { + frameFormatLay->addWidget(new QLabel(tr("Separate Character:"), this), 0, + 0, Qt::AlignRight); + frameFormatLay->addWidget(m_sepCharCB, 0, 1, Qt::AlignLeft); + + frameFormatLay->addWidget(new QLabel(tr("Padding:"), this), 1, 0, + Qt::AlignRight); + frameFormatLay->addWidget(m_paddingCB, 1, 1, Qt::AlignLeft); + } + frameFormatGB->setLayout(frameFormatLay); + + m_mainLayout->addWidget(frameFormatGB, currentRow + 1, 0, 1, 2); + + connect(m_sepCharCB, SIGNAL(activated(int)), this, + SLOT(onSepCharCBChanged())); + connect(m_paddingCB, SIGNAL(activated(int)), this, + SLOT(onPaddingCBChanged())); + } + QPushButton *closeButton = new QPushButton(tr("Close")); closeButton->setContentsMargins(4, 4, 4, 4); closeButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); @@ -318,14 +380,27 @@ void FormatSettingsPopup::showEvent(QShowEvent *se) { Dialog::showEvent(se); } +//----------------------------------------------------------------------------- + +void FormatSettingsPopup::onSepCharCBChanged() { + assert(m_tmplFId); + m_tmplFId->setStartSeqInd(m_sepCharCB->currentData().toChar().toLatin1()); +} + +//----------------------------------------------------------------------------- + +void FormatSettingsPopup::onPaddingCBChanged() { + assert(m_tmplFId); + m_tmplFId->setZeroPadding(m_paddingCB->currentData().toInt()); +} + //********************************************************************************** // API functions //********************************************************************************** -FormatSettingsPopup *openFormatSettingsPopup(QWidget *parent, - const std::string &format, - TPropertyGroup *props, - const TFilePath &levelPath) { +bool openFormatSettingsPopup(QWidget *parent, const std::string &format, + TPropertyGroup *props, TFrameId *tmplFId, + bool forInput, const TFilePath &levelPath) { if (format == "mov" || format == "3gp") // trattato diversamente; il format // popup dei mov e' quello di // quicktime @@ -341,19 +416,21 @@ FormatSettingsPopup *openFormatSettingsPopup(QWidget *parent, openMovSettingsPopup(props); popupIsOpen = false; - return 0; + return true; } - if (!props || props->getPropertyCount() == 0) return 0; + if ((!props || props->getPropertyCount() == 0) && + !(checkForSeqNum(QString::fromStdString(format)) && tmplFId)) + return false; - FormatSettingsPopup *popup = new FormatSettingsPopup(parent, format, props); + FormatSettingsPopup *popup = + new FormatSettingsPopup(parent, format, props, tmplFId, forInput); popup->setAttribute(Qt::WA_DeleteOnClose); popup->setModal(true); if (!levelPath.isEmpty()) popup->setLevelPath(levelPath); - popup->show(); - popup->raise(); + popup->exec(); - return popup; + return true; } diff --git a/toonz/sources/toonz/formatsettingspopups.h b/toonz/sources/toonz/formatsettingspopups.h index 5e3bc27..7ac6f08 100644 --- a/toonz/sources/toonz/formatsettingspopups.h +++ b/toonz/sources/toonz/formatsettingspopups.h @@ -18,11 +18,12 @@ class TPropertyGroup; class QLabel; +class QComboBox; namespace DVGui { class PropertyWidget; class PropertyComboBox; -} +} // namespace DVGui //============================================================== @@ -35,7 +36,8 @@ class FormatSettingsPopup final : public DVGui::Dialog { public: FormatSettingsPopup(QWidget *parent, const std::string &format, - TPropertyGroup *props); + TPropertyGroup *props, TFrameId *tmplFrameId = nullptr, + bool forInput = true); void setLevelPath(const TFilePath &path) { m_levelPath = path; } void setFormatProperties(TPropertyGroup *props); @@ -59,6 +61,9 @@ private: #endif + TFrameId *m_tmplFId; + QComboBox *m_sepCharCB, *m_paddingCB; + private: void buildPropertyComboBox(int index, TPropertyGroup *props); void buildValueField(int index, TPropertyGroup *props); @@ -70,6 +75,9 @@ private: private Q_SLOTS: void onComboBoxIndexChanged(const QString &); void onAviCodecConfigure(); + + void onSepCharCBChanged(); + void onPaddingCBChanged(); }; //********************************************************************************** @@ -101,14 +109,18 @@ private Q_SLOTS: format. */ -FormatSettingsPopup *openFormatSettingsPopup( +bool openFormatSettingsPopup( QWidget *parent, //!< Parent for the new format popup. const std::string &format, //!< File extension of the displayed format. TPropertyGroup *props, //!< Properties to be shown for the format. + TFrameId *tmplFId = + nullptr, //!< Template TFrameId to specify frame number format + bool forInput = + true, // specifies border color for the frame number format box const TFilePath &levelPath = TFilePath() //!< May be used to choose available codecs //! depending on a level's resolution. - ); //!< Opens a suitable popup with settings +); //!< Opens a suitable popup with settings //! for an input level format. #endif // FORMATSETTINGSPOPUPS_H diff --git a/toonz/sources/toonz/levelcreatepopup.cpp b/toonz/sources/toonz/levelcreatepopup.cpp index ef9326e..c1c8866 100644 --- a/toonz/sources/toonz/levelcreatepopup.cpp +++ b/toonz/sources/toonz/levelcreatepopup.cpp @@ -6,6 +6,7 @@ #include "menubarcommandids.h" #include "tapp.h" #include "levelcommand.h" +#include "formatsettingspopups.h" // TnzTools includes #include "tools/toolhandle.h" @@ -36,6 +37,7 @@ #include "toonz/tproject.h" #include "toonz/namebuilder.h" #include "toonz/childstack.h" +#include "toutputproperties.h" // TnzCore includes #include "tsystem.h" @@ -177,6 +179,10 @@ LevelCreatePopup::LevelCreatePopup() m_dpiLabel = new QLabel(tr("DPI:")); m_dpiFld = new DoubleLineEdit(0, 66.76); + m_rasterFormatLabel = new QLabel(tr("Format:")); + m_rasterFormatOm = new QComboBox(); + m_frameFormatBtn = new QPushButton(tr("Frame Format")); + QPushButton *okBtn = new QPushButton(tr("OK"), this); QPushButton *cancelBtn = new QPushButton(tr("Cancel"), this); QPushButton *applyBtn = new QPushButton(tr("Apply"), this); @@ -203,6 +209,11 @@ LevelCreatePopup::LevelCreatePopup() m_heightFld->setRange(0.1, (std::numeric_limits::max)()); m_dpiFld->setRange(0.1, (std::numeric_limits::max)()); + m_rasterFormatOm->addItem("tif", "tif"); + m_rasterFormatOm->addItem("png", "png"); + m_rasterFormatOm->setCurrentIndex(m_rasterFormatOm->findData( + Preferences::instance()->getDefRasterFormat())); + okBtn->setDefault(true); //--- layout @@ -245,15 +256,21 @@ LevelCreatePopup::LevelCreatePopup() Qt::AlignRight | Qt::AlignVCenter); guiLay->addWidget(m_pathFld, 4, 1, 1, 4); + // Format options (for Raster/Scan levels) + guiLay->addWidget(m_rasterFormatLabel, 5, 0, + Qt::AlignRight | Qt::AlignVCenter); + guiLay->addWidget(m_rasterFormatOm, 5, 1, Qt::AlignLeft); + guiLay->addWidget(m_frameFormatBtn, 5, 2, 1, 2, Qt::AlignLeft); + // Width - Height - guiLay->addWidget(m_widthLabel, 5, 0, Qt::AlignRight | Qt::AlignVCenter); - guiLay->addWidget(m_widthFld, 5, 1); - guiLay->addWidget(m_heightLabel, 5, 2, Qt::AlignRight | Qt::AlignVCenter); - guiLay->addWidget(m_heightFld, 5, 3); + guiLay->addWidget(m_widthLabel, 6, 0, Qt::AlignRight | Qt::AlignVCenter); + guiLay->addWidget(m_widthFld, 6, 1); + guiLay->addWidget(m_heightLabel, 6, 2, Qt::AlignRight | Qt::AlignVCenter); + guiLay->addWidget(m_heightFld, 6, 3); // DPI - guiLay->addWidget(m_dpiLabel, 6, 0, Qt::AlignRight | Qt::AlignVCenter); - guiLay->addWidget(m_dpiFld, 6, 1, 1, 3); + guiLay->addWidget(m_dpiLabel, 7, 0, Qt::AlignRight | Qt::AlignVCenter); + guiLay->addWidget(m_dpiFld, 7, 1); } guiLay->setColumnStretch(0, 0); guiLay->setColumnStretch(1, 0); @@ -278,12 +295,15 @@ LevelCreatePopup::LevelCreatePopup() bool ret = true; ret = ret && connect(m_levelTypeOm, SIGNAL(currentIndexChanged(int)), SLOT(onLevelTypeChanged(int))); + ret = ret && connect(m_frameFormatBtn, SIGNAL(clicked()), this, + SLOT(onFrameFormatButton())); ret = ret && connect(okBtn, SIGNAL(clicked()), this, SLOT(onOkBtn())); ret = ret && connect(cancelBtn, SIGNAL(clicked()), this, SLOT(reject())); ret = ret && connect(applyBtn, SIGNAL(clicked()), this, SLOT(onApplyButton())); setSizeWidgetEnable(false); + setRasterWidgetVisible(false); } //----------------------------------------------------------------------------- @@ -375,6 +395,15 @@ void LevelCreatePopup::setSizeWidgetEnable(bool isEnable) { //----------------------------------------------------------------------------- +void LevelCreatePopup::setRasterWidgetVisible(bool isVisible) { + m_rasterFormatLabel->setVisible(isVisible); + m_rasterFormatOm->setVisible(isVisible); + m_frameFormatBtn->setVisible(isVisible); + updateGeometry(); +} + +//----------------------------------------------------------------------------- + int LevelCreatePopup::getLevelType() const { return m_levelTypeOm->currentData().toInt(); } @@ -387,6 +416,9 @@ void LevelCreatePopup::onLevelTypeChanged(int index) { setSizeWidgetEnable(true); else setSizeWidgetEnable(false); + + setRasterWidgetVisible(type == OVL_XSHLEVEL || type == TZI_XSHLEVEL); + updatePath(); std::wstring levelName = m_nameFld->text().toStdWString(); @@ -420,6 +452,17 @@ void LevelCreatePopup::onApplyButton() { //----------------------------------------------------------------------------- +void LevelCreatePopup::onFrameFormatButton() { + // Tentatively use the preview output settings + ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); + if (!scene) return; + std::string ext = m_rasterFormatOm->currentData().toString().toStdString(); + openFormatSettingsPopup(this, ext, nullptr, + &scene->getProperties()->formatTemplateFIdForInput()); +} + +//----------------------------------------------------------------------------- + bool LevelCreatePopup::apply() { TApp *app = TApp::instance(); int row = app->getCurrentFrame()->getFrame(); @@ -497,6 +540,9 @@ bool LevelCreatePopup::apply() { TFilePath fp = scene->getDefaultLevelPath(lType, levelName).withParentDir(parentDir); + if (lType == OVL_XSHLEVEL || lType == TZI_XSHLEVEL) + fp = fp.withType(m_rasterFormatOm->currentData().toString().toStdString()); + TFilePath actualFp = scene->decodeFilePath(fp); if (TSystem::doesExistFileOrLevel(actualFp)) { error( @@ -583,7 +629,6 @@ bool LevelCreatePopup::apply() { for (i = from; i <= to; i += inc) { TFrameId fid(i); - TXshCell cell(sl, fid); if (lType == PLI_XSHLEVEL) sl->setFrame(fid, new TVectorImage()); else if (lType == TZP_XSHLEVEL) { @@ -598,8 +643,12 @@ bool LevelCreatePopup::apply() { raster->clear(); TRasterImageP ri(raster); ri->setDpi(dpi, dpi); + // modify frameId to be with the same frame format as existing frames + TFrameId tmplFId = scene->getProperties()->formatTemplateFIdForInput(); + sl->formatFId(fid, tmplFId); sl->setFrame(fid, ri); } + TXshCell cell(sl, fid); for (j = 0; j < step; j++) xsh->setCell(row++, col, cell); } diff --git a/toonz/sources/toonz/levelcreatepopup.h b/toonz/sources/toonz/levelcreatepopup.h index 229137d..b47f54b 100644 --- a/toonz/sources/toonz/levelcreatepopup.h +++ b/toonz/sources/toonz/levelcreatepopup.h @@ -34,10 +34,16 @@ class LevelCreatePopup final : public DVGui::Dialog { DVGui::MeasuredDoubleLineEdit *m_heightFld; DVGui::DoubleLineEdit *m_dpiFld; + QLabel *m_rasterFormatLabel; + QComboBox *m_rasterFormatOm; + QPushButton *m_frameFormatBtn; + public: LevelCreatePopup(); void setSizeWidgetEnable(bool isEnable); + void setRasterWidgetVisible(bool isVisible); + int getLevelType() const; void update(); @@ -55,6 +61,7 @@ public slots: void onOkBtn(); void onApplyButton(); + void onFrameFormatButton(); }; #endif // LEVELCREATEPOPUP_H diff --git a/toonz/sources/toonz/outputsettingspopup.cpp b/toonz/sources/toonz/outputsettingspopup.cpp index 5412485..7ed1341 100644 --- a/toonz/sources/toonz/outputsettingspopup.cpp +++ b/toonz/sources/toonz/outputsettingspopup.cpp @@ -1057,7 +1057,7 @@ void OutputSettingsPopup::onFormatChanged(const QString &str) { ext == "spritesheet"; }; - TOutputProperties *prop = getProperties(); + TOutputProperties *prop = getProperties(); bool wasMultiRenderInvalid = isMultiRenderInvalid(prop->getPath().getType(), m_allowMT); TFilePath fp = prop->getPath().withType(str.toStdString()); @@ -1091,9 +1091,25 @@ void OutputSettingsPopup::onFormatChanged(const QString &str) { void OutputSettingsPopup::openSettingsPopup() { TOutputProperties *prop = getProperties(); std::string ext = prop->getPath().getType(); - openFormatSettingsPopup(this, ext, prop->getFileFormatProperties(ext)); + + TFrameId oldTmplFId = prop->formatTemplateFId(); + + bool ret = + openFormatSettingsPopup(this, ext, prop->getFileFormatProperties(ext), + &prop->formatTemplateFId(), false); + + if (!ret) return; if (m_presetCombo) m_presetCombo->setCurrentIndex(0); + + if (oldTmplFId.getZeroPadding() != + prop->formatTemplateFId().getZeroPadding() || + oldTmplFId.getStartSeqInd() != + prop->formatTemplateFId().getStartSeqInd()) { + TFilePath fp = + prop->getPath().withNoFrame().withFrame(prop->formatTemplateFId()); + prop->setPath(fp); + } } //----------------------------------------------------------------------------- diff --git a/toonz/sources/toonz/penciltestpopup.cpp b/toonz/sources/toonz/penciltestpopup.cpp index 0688e3e..a8fcfd6 100644 --- a/toonz/sources/toonz/penciltestpopup.cpp +++ b/toonz/sources/toonz/penciltestpopup.cpp @@ -1859,13 +1859,19 @@ void PencilTestPopup::onResolutionComboActivated() { //----------------------------------------------------------------------------- void PencilTestPopup::onFileFormatOptionButtonPressed() { - if (m_fileTypeCombo->currentIndex() == 0) return; // Tentatively use the preview output settings ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); if (!scene) return; TOutputProperties* prop = scene->getProperties()->getPreviewProperties(); std::string ext = m_fileTypeCombo->currentText().toStdString(); - openFormatSettingsPopup(this, ext, prop->getFileFormatProperties(ext)); + TFrameId oldTmplFId = scene->getProperties()->formatTemplateFIdForInput(); + openFormatSettingsPopup(this, ext, prop->getFileFormatProperties(ext), + &scene->getProperties()->formatTemplateFIdForInput()); + + TFrameId newTmplFId = scene->getProperties()->formatTemplateFIdForInput(); + if (oldTmplFId.getZeroPadding() != newTmplFId.getZeroPadding() || + oldTmplFId.getStartSeqInd() != newTmplFId.getStartSeqInd()) + refreshFrameInfo(); } //----------------------------------------------------------------------------- @@ -2459,9 +2465,12 @@ bool PencilTestPopup::importImage(QImage image) { } } + TFrameId tmplFId = scene->getProperties()->formatTemplateFIdForInput(); + TFilePath levelFp = TFilePath(m_saveInFileFld->getPath()) + - TFilePath(levelName + L".." + - m_fileTypeCombo->currentText().toStdWString()); + TFilePath(levelName + L"." + + m_fileTypeCombo->currentText().toStdWString()) + .withFrame(tmplFId); TFilePath actualLevelFp = scene->decodeFilePath(levelFp); TXshSimpleLevel* sl = 0; @@ -2498,6 +2507,11 @@ bool PencilTestPopup::importImage(QImage image) { "The captured image size does not match with the existing level.")); return false; } + + // if the level already has a frame, use the same zero padding regardless of + // the frame format setting + sl->formatFId(fId, tmplFId); + /* if the level already have the same frame, then ask if overwrite it */ TFilePath frameFp(actualLevelFp.withFrame(fId)); if (TFileStatus(frameFp).doesExist()) { @@ -2533,6 +2547,9 @@ bool PencilTestPopup::importImage(QImage image) { "The captured image size does not match with the existing level.")); return false; } + // if the level already has a frame, use the same zero padding regardless + // of the frame format setting + sl->formatFId(fId, tmplFId); /* confirm overwrite */ TFilePath frameFp(actualLevelFp.withFrame(fId)); @@ -2577,6 +2594,7 @@ bool PencilTestPopup::importImage(QImage image) { sl->getProperties()->setImageDpi(dpi); sl->getProperties()->setImageRes( TDimension(image.width(), image.height())); + sl->formatFId(fId, tmplFId); } state = NEWLEVEL; @@ -2727,9 +2745,12 @@ void PencilTestPopup::refreshFrameInfo() { // level with the same name TXshLevel* level_sameName = levelSet->getLevel(levelName); + TFrameId tmplFId = currentScene->getProperties()->formatTemplateFIdForInput(); + TFilePath levelFp = TFilePath(m_saveInFileFld->getPath()) + - TFilePath(levelName + L".." + - m_fileTypeCombo->currentText().toStdWString()); + TFilePath(levelName + L"." + + m_fileTypeCombo->currentText().toStdWString()) + .withFrame(tmplFId); // level with the same path TXshLevel* level_samePath = levelSet->getLevel(*(currentScene), levelFp); @@ -2781,8 +2802,11 @@ void PencilTestPopup::refreshFrameInfo() { int frameCount = level_p->getFrameCount(); TLevel::Iterator it = level_p->begin(); std::vector fids; - for (int i = 0; it != level_p->end(); ++it, ++i) + for (int i = 0; it != level_p->end(); ++it, ++i) { fids.push_back(it->first); + // in case fId with different format + if (!frameExist && fId == it->first) frameExist = true; + } tooltipStr += tr("The level is not registered in the scene, but exists in the file " diff --git a/toonz/sources/toonz/penciltestpopup_qt.cpp b/toonz/sources/toonz/penciltestpopup_qt.cpp index 58aa19b..5dee764 100644 --- a/toonz/sources/toonz/penciltestpopup_qt.cpp +++ b/toonz/sources/toonz/penciltestpopup_qt.cpp @@ -2041,13 +2041,19 @@ void PencilTestPopup::onResolutionComboActivated(const QString& itemText) { //----------------------------------------------------------------------------- void PencilTestPopup::onFileFormatOptionButtonPressed() { - if (m_fileTypeCombo->currentIndex() == 0) return; // Tentatively use the preview output settings ToonzScene* scene = TApp::instance()->getCurrentScene()->getScene(); if (!scene) return; TOutputProperties* prop = scene->getProperties()->getPreviewProperties(); std::string ext = m_fileTypeCombo->currentText().toStdString(); - openFormatSettingsPopup(this, ext, prop->getFileFormatProperties(ext)); + TFrameId oldTmplFId = scene->getProperties()->formatTemplateFIdForInput(); + openFormatSettingsPopup(this, ext, prop->getFileFormatProperties(ext), + &scene->getProperties()->formatTemplateFIdForInput()); + + TFrameId newTmplFId = scene->getProperties()->formatTemplateFIdForInput(); + if (oldTmplFId.getZeroPadding() != newTmplFId.getZeroPadding() || + oldTmplFId.getStartSeqInd() != newTmplFId.getStartSeqInd()) + refreshFrameInfo(); } //----------------------------------------------------------------------------- @@ -2531,9 +2537,12 @@ bool PencilTestPopup::importImage(QImage image) { } } + TFrameId tmplFId = scene->getProperties()->formatTemplateFIdForInput(); + TFilePath levelFp = TFilePath(m_saveInFileFld->getPath()) + - TFilePath(levelName + L".." + - m_fileTypeCombo->currentText().toStdWString()); + TFilePath(levelName + L"." + + m_fileTypeCombo->currentText().toStdWString()) + .withFrame(tmplFId); TFilePath actualLevelFp = scene->decodeFilePath(levelFp); TXshSimpleLevel* sl = 0; @@ -2570,6 +2579,11 @@ bool PencilTestPopup::importImage(QImage image) { "The captured image size does not match with the existing level.")); return false; } + + // if the level already has a frame, use the same zero padding regardless of + // the frame format setting + sl->formatFId(fId, tmplFId); + /* if the level already have the same frame, then ask if overwrite it */ TFilePath frameFp(actualLevelFp.withFrame(fId)); if (TFileStatus(frameFp).doesExist()) { @@ -2605,6 +2619,9 @@ bool PencilTestPopup::importImage(QImage image) { "The captured image size does not match with the existing level.")); return false; } + // if the level already has a frame, use the same zero padding regardless + // of the frame format setting + sl->formatFId(fId, tmplFId); /* confirm overwrite */ TFilePath frameFp(actualLevelFp.withFrame(fId)); @@ -2649,6 +2666,7 @@ bool PencilTestPopup::importImage(QImage image) { sl->getProperties()->setImageDpi(dpi); sl->getProperties()->setImageRes( TDimension(image.width(), image.height())); + sl->formatFId(fId, tmplFId); } state = NEWLEVEL; @@ -2799,9 +2817,14 @@ void PencilTestPopup::refreshFrameInfo() { // level with the same name TXshLevel* level_sameName = levelSet->getLevel(levelName); + TOutputProperties* prop = + currentScene->getProperties()->getPreviewProperties(); + TFrameId tmplFId = prop->formatTemplateFId(); + TFilePath levelFp = TFilePath(m_saveInFileFld->getPath()) + - TFilePath(levelName + L".." + - m_fileTypeCombo->currentText().toStdWString()); + TFilePath(levelName + L"." + + m_fileTypeCombo->currentText().toStdWString()) + .withFrame(tmplFId); // level with the same path TXshLevel* level_samePath = levelSet->getLevel(*(currentScene), levelFp); @@ -2853,8 +2876,11 @@ void PencilTestPopup::refreshFrameInfo() { int frameCount = level_p->getFrameCount(); TLevel::Iterator it = level_p->begin(); std::vector fids; - for (int i = 0; it != level_p->end(); ++it, ++i) + for (int i = 0; it != level_p->end(); ++it, ++i) { fids.push_back(it->first); + // in case fId with different format + if (!frameExist && fId == it->first) frameExist = true; + } tooltipStr += tr("The level is not registered in the scene, but exists in the file " diff --git a/toonz/sources/toonz/preferencespopup.cpp b/toonz/sources/toonz/preferencespopup.cpp index a655dc4..7d2cd76 100644 --- a/toonz/sources/toonz/preferencespopup.cpp +++ b/toonz/sources/toonz/preferencespopup.cpp @@ -8,6 +8,7 @@ #include "levelsettingspopup.h" #include "tapp.h" #include "cleanupsettingsmodel.h" +#include "formatsettingspopups.h" // TnzQt includes #include "toonzqt/tabbar.h" @@ -1043,15 +1044,26 @@ void PreferencesPopup::insertUI(PreferencesItemId id, QGridLayout* layout, // CheckBox contains label in itself if (item.type == QMetaType::Bool) - layout->addWidget(widget, layout->rowCount(), 0, 1, 2); + layout->addWidget(widget, layout->rowCount(), 0, 1, 3, Qt::AlignLeft); else { // insert labels for other types int row = layout->rowCount(); layout->addWidget(new QLabel(getUIString(id), this), row, 0, Qt::AlignRight | Qt::AlignVCenter); if (isFileField) layout->addWidget(widget, row, 1, 1, 2); - else - layout->addWidget(widget, row, 1, Qt::AlignLeft | Qt::AlignVCenter); + else { + bool isWideComboBox = false; + for (auto cbItem : comboItems) { + if (widget->fontMetrics().width(cbItem.first) > 100) { + isWideComboBox = true; + break; + } + } + if (id == interfaceFont) isWideComboBox = true; + + layout->addWidget(widget, row, 1, 1, (isWideComboBox) ? 2 : 1, + Qt::AlignLeft | Qt::AlignVCenter); + } } } @@ -1086,7 +1098,7 @@ void PreferencesPopup::insertFootNote(QGridLayout* layout) { QLabel* note = new QLabel( tr("* Changes will take effect the next time you run OpenToonz")); note->setStyleSheet("font-size: 10px; font: italic;"); - layout->addWidget(note, layout->rowCount(), 0, 1, 2, + layout->addWidget(note, layout->rowCount(), 0, 1, 3, Qt::AlignLeft | Qt::AlignVCenter); } @@ -1183,7 +1195,8 @@ QString PreferencesPopup::getUIString(PreferencesItemId id) { tr("Allow Multi-Thread in FFMPEG Rendering (UNSTABLE)")}, // Drawing - {scanLevelType, tr("Scan File Format:")}, + {DefRasterFormat, tr("Default Raster / Scan Level Format:")}, + //{scanLevelType, tr("Scan File Format:")}, {DefLevelType, tr("Default Level Type:")}, {newLevelSizeToCameraSizeEnabled, tr("New Levels Default to the Current Camera Size")}, @@ -1262,7 +1275,7 @@ QString PreferencesPopup::getUIString(PreferencesItemId id) { {blanksCount, tr("Blank Frames:")}, {blankColor, tr("Blank Frames Color:")}, {rewindAfterPlayback, tr("Rewind after Playback")}, - {shortPlayFrameCount, tr("Number of Frames to Play for Short Play:")}, + {shortPlayFrameCount, tr("Number of Frames to Play \nfor Short Play:")}, {previewAlwaysOpenNewFlip, tr("Display in a New Flipbook Window")}, {fitToFlipbook, tr("Fit to Flipbook")}, {generatedMovieViewEnabled, tr("Open Flipbook after Rendering")}, @@ -1347,7 +1360,8 @@ QList PreferencesPopup::getComboItemList( {columnIconLoadingPolicy, {{tr("At Once"), Preferences::LoadAtOnce}, {tr("On Demand"), Preferences::LoadOnDemand}}}, - {scanLevelType, {{"tif", "tif"}, {"png", "png"}}}, + {DefRasterFormat, {{"tif", "tif"}, {"png", "png"}}}, + //{scanLevelType, {{"tif", "tif"}, {"png", "png"}}}, {DefLevelType, {{tr("Toonz Vector Level"), PLI_XSHLEVEL}, {tr("Toonz Raster Level"), TZP_XSHLEVEL}, @@ -1592,7 +1606,7 @@ QWidget* PreferencesPopup::createInterfacePage() { insertUI(CurrentStyleSheetName, lay, styleSheetItemList); int row = lay->rowCount(); - lay->addWidget(additionalStyleSheetBtn, row - 1, 3); + lay->addWidget(additionalStyleSheetBtn, row - 1, 2, Qt::AlignRight); lay->addWidget(new QLabel(tr("Icon Theme*:"), this), 2, 0, Qt::AlignRight | Qt::AlignVCenter); @@ -1604,7 +1618,7 @@ QWidget* PreferencesPopup::createInterfacePage() { lay->addWidget(new QLabel(tr("Pixels Only:"), this), 5, 0, Qt::AlignRight | Qt::AlignVCenter); - lay->addWidget(createUI(pixelsOnly), 5, 1); + lay->addWidget(createUI(pixelsOnly), 5, 1, 1, 2, Qt::AlignLeft); insertUI(CurrentRoomChoice, lay, roomItemList); insertUI(functionEditorToggle, lay, getComboItemList(functionEditorToggle)); @@ -1621,7 +1635,7 @@ QWidget* PreferencesPopup::createInterfacePage() { { insertUI(colorCalibrationLutPaths, colorCalibLay); } insertUI(displayIn30bit, lay); row = lay->rowCount(); - lay->addWidget(check30bitBtn, row - 1, 3); + lay->addWidget(check30bitBtn, row - 1, 2, Qt::AlignRight); insertUI(showIconsInMenu, lay); lay->setRowStretch(lay->rowCount(), 1); @@ -1797,7 +1811,7 @@ QWidget* PreferencesPopup::createImportExportPage() { putLabel("", lay); putLabel( - tr("Enabling multi-thread rendering will render significantly faster " + tr("Enabling multi-thread rendering will render significantly faster \n" "but a random crash might occur, use at your own risk."), lay); insertUI(ffmpegMultiThread, lay); @@ -1815,7 +1829,7 @@ QWidget* PreferencesPopup::createDrawingPage() { QGridLayout* lay = new QGridLayout(); setupLayout(lay); - insertUI(scanLevelType, lay, getComboItemList(scanLevelType)); + insertUI(DefRasterFormat, lay, getComboItemList(DefRasterFormat)); insertUI(DefLevelType, lay, getComboItemList(DefLevelType)); insertUI(newLevelSizeToCameraSizeEnabled, lay); insertDualUIs(DefLevelWidth, DefLevelHeight, lay); diff --git a/toonz/sources/toonz/xdtsio.cpp b/toonz/sources/toonz/xdtsio.cpp index dc82aaa..21bdcca 100644 --- a/toonz/sources/toonz/xdtsio.cpp +++ b/toonz/sources/toonz/xdtsio.cpp @@ -551,6 +551,8 @@ bool XdtsIo::loadXdtsScene(ToonzScene *scene, const TFilePath &scenePath) { int tick1Id, tick2Id; popup.getMarkerIds(tick1Id, tick2Id); + TFrameId tmplFId = scene->getProperties()->formatTemplateFIdForInput(); + TXsheet *xsh = scene->getXsheet(); XdtsTimeTableFieldItem cellField = xdtsData.timeTable().getCellField(); XdtsTimeTableHeaderItem cellHeader = xdtsData.timeTable().getCellHeader(); @@ -558,8 +560,9 @@ 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); + QString levelName = layerNames.at(column); + TXshLevel *level = levels.value(levelName); + TXshSimpleLevel *sl = level->getSimpleLevel(); QList tick1, tick2; QVector track = cellField.getColumnTrack(column, tick1, tick2); @@ -568,13 +571,18 @@ bool XdtsIo::loadXdtsScene(ToonzScene *scene, const TFilePath &scenePath) { for (TFrameId fid : track) { if (fid.getNumber() == -1) // EMPTY cell case row++; - else + else { + // modify frameId to be with the same frame format as existing frames + if (sl) sl->formatFId(fid, tmplFId); 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 TFrameId lastFid = track.last(); if (lastFid.getNumber() != -1) { + // modify frameId to be with the same frame format as existing frames + if (sl) sl->formatFId(lastFid, tmplFId); for (; row < duration; row++) xsh->setCell(row, column, TXshCell(level, TFrameId(lastFid))); } diff --git a/toonz/sources/toonz/xshcellviewer.cpp b/toonz/sources/toonz/xshcellviewer.cpp index 121a008..6c0e3a6 100644 --- a/toonz/sources/toonz/xshcellviewer.cpp +++ b/toonz/sources/toonz/xshcellviewer.cpp @@ -57,6 +57,7 @@ #include "toonz/txshpalettelevel.h" #include "toonz/doubleparamcmd.h" #include "toonz/preferences.h" +#include "toutputproperties.h" // TnzBase includes #include "tdoublekeyframe.h" @@ -864,6 +865,9 @@ void RenameCellField::renameCell() { TApp::instance()->getCurrentSelection()->getSelection()); if (!cellSelection) return; + ToonzScene *scene = m_viewer->getXsheet()->getScene(); + TFrameId tmplFId = scene->getProperties()->formatTemplateFIdForInput(); + QList cells; bool hasFrameZero = false; @@ -901,15 +905,20 @@ void RenameCellField::renameCell() { } } - TXshLevel *xl = cell.m_level.getPointer(); - if (!xl || (xl->getSimpleLevel() && !xl->getSimpleLevel()->isEmpty() && - xl->getSimpleLevel()->getFirstFid() == TFrameId::NO_FRAME)) { + TXshLevel *xl = cell.m_level.getPointer(); + TXshSimpleLevel *sl = (xl) ? xl->getSimpleLevel() : nullptr; + if (!xl || + (sl && !sl->isEmpty() && sl->getFirstFid() == TFrameId::NO_FRAME)) { cells.append(TXshCell()); continue; } // if the next upper cell is empty, then make this cell empty too if (fid == TFrameId::NO_FRAME) fid = (m_row - tmpRow <= 1) ? cell.m_frameId : TFrameId(0); + + // modify frameId to be with the same frame format as existing frames + if (sl) sl->formatFId(fid, tmplFId); + cells.append(TXshCell(xl, fid)); changed = true; hasFrameZero = (fid.getNumber() == 0 && xl->getSimpleLevel() && @@ -917,7 +926,6 @@ void RenameCellField::renameCell() { } if (!changed) return; } else { - ToonzScene *scene = m_viewer->getXsheet()->getScene(); TLevelSet *levelSet = scene->getLevelSet(); TXshLevel *xl = levelSet->getLevel(levelName); if (!xl && fid != TFrameId::NO_FRAME) { @@ -926,12 +934,19 @@ void RenameCellField::renameCell() { int levelType = pref->getDefLevelType(); xl = scene->createNewLevel(levelType, levelName); TXshSimpleLevel *sl = xl->getSimpleLevel(); - if (levelType == TZP_XSHLEVEL || levelType == OVL_XSHLEVEL) + if (levelType == TZP_XSHLEVEL || levelType == OVL_XSHLEVEL) { + // modify frameId to be with the same frame format as existing frames + sl->formatFId(fid, tmplFId); sl->setFrame(fid, sl->createEmptyFrame()); + } } else xl = scene->createNewLevel(TZI_XSHLEVEL, levelName); } if (!xl) return; + + // modify frameId to be with the same frame format as existing frames + if (xl->getSimpleLevel()) xl->getSimpleLevel()->formatFId(fid, tmplFId); + cells.append(TXshCell(xl, fid)); hasFrameZero = (fid.getNumber() == 0 && xl->getSimpleLevel() && xl->getSimpleLevel()->isFid(fid)); diff --git a/toonz/sources/toonzlib/levelupdater.cpp b/toonz/sources/toonzlib/levelupdater.cpp index 1f8ca57..31df108 100644 --- a/toonz/sources/toonzlib/levelupdater.cpp +++ b/toonz/sources/toonzlib/levelupdater.cpp @@ -26,10 +26,9 @@ namespace { inline bool supportsRandomAccess(const TFilePath &fp) { const std::string &type = fp.getType(); return type == "tlv" || // TLVs do support random access - // type == "pli" || // PLIs... I - // thought they would - but no :( - // type == "mov" || // MOVs are - // 'on the way' to support it... for now, no + // type == "pli" || // PLIs... I thought they would - + // but no :( type == "mov" || // MOVs are 'on the + // way' to support it... for now, no fp.getDots() == ".."; // Multi-file levels of course do } @@ -98,14 +97,15 @@ LevelUpdater::LevelUpdater(TXshSimpleLevel *sl) //----------------------------------------------------------------------------- -LevelUpdater::LevelUpdater(const TFilePath &fp, TPropertyGroup *lwProperties) +LevelUpdater::LevelUpdater(const TFilePath &fp, TPropertyGroup *lwProperties, + const TFrameId &tmplFId) : m_pg(0) , m_inputLevel(0) , m_imageInfo(0) , m_currIdx(0) , m_opened(false) , m_usingTemporaryFile(false) { - open(fp, lwProperties); + open(fp, lwProperties, tmplFId); } //----------------------------------------------------------------------------- @@ -207,7 +207,8 @@ void LevelUpdater::buildProperties(const TFilePath &fp) { //----------------------------------------------------------------------------- -void LevelUpdater::open(const TFilePath &fp, TPropertyGroup *pg) { +void LevelUpdater::open(const TFilePath &fp, TPropertyGroup *pg, + const TFrameId &tmplFId) { assert(!m_lw); // Find out if a corresponding level already exists on disk - in that case, @@ -261,6 +262,10 @@ void LevelUpdater::open(const TFilePath &fp, TPropertyGroup *pg) { assert(iconSize.lx > 0 && iconSize.ly > 0); m_lw->setIconSize(iconSize); + // set the frame format template (to be used in + // TLevelWriter::getFrameWriter()) + if (!tmplFId.isNoFrame()) m_lw->setFrameFormatTemplateFId(tmplFId); + m_opened = true; } diff --git a/toonz/sources/toonzlib/movierenderer.cpp b/toonz/sources/toonzlib/movierenderer.cpp index c864ab1..538c003 100644 --- a/toonz/sources/toonzlib/movierenderer.cpp +++ b/toonz/sources/toonzlib/movierenderer.cpp @@ -276,7 +276,8 @@ void MovieRenderer::Imp::prepareForStart() { locals::eraseUncompatibleExistingLevel(m_fp, cameraResI); m_levelUpdaterA.reset(new LevelUpdater( - m_fp, oprop->getFileFormatProperties(m_fp.getType()))); + m_fp, oprop->getFileFormatProperties(m_fp.getType()), + oprop->formatTemplateFId())); m_levelUpdaterA->getLevelWriter()->setFrameRate(frameRate); } else { TFilePath leftFp = m_fp.withName(m_fp.getName() + "_l"); @@ -286,11 +287,13 @@ void MovieRenderer::Imp::prepareForStart() { locals::eraseUncompatibleExistingLevel(rightFp, cameraResI); m_levelUpdaterA.reset(new LevelUpdater( - leftFp, oprop->getFileFormatProperties(leftFp.getType()))); + leftFp, oprop->getFileFormatProperties(leftFp.getType()), + oprop->formatTemplateFId())); m_levelUpdaterA->getLevelWriter()->setFrameRate(frameRate); m_levelUpdaterB.reset(new LevelUpdater( - rightFp, oprop->getFileFormatProperties(rightFp.getType()))); + rightFp, oprop->getFileFormatProperties(rightFp.getType()), + oprop->formatTemplateFId())); m_levelUpdaterB->getLevelWriter()->setFrameRate(frameRate); } } catch (...) { @@ -538,7 +541,7 @@ void MovieRenderer::Imp::doRenderRasterCompleted(const RenderData &renderData) { // This thread will be the one processing ft - remove it from the map to // prevent another // thread from interfering - double frame = ft->first; + double frame = ft->first; std::pair rasters = ft->second; ++m_nextFrameIdxToSave; diff --git a/toonz/sources/toonzlib/outputproperties.cpp b/toonz/sources/toonzlib/outputproperties.cpp index dc04614..a0a3473 100644 --- a/toonz/sources/toonzlib/outputproperties.cpp +++ b/toonz/sources/toonzlib/outputproperties.cpp @@ -41,7 +41,8 @@ TOutputProperties::TOutputProperties() , m_maxTileSizeIndex(0) , m_threadIndex(2) , m_subcameraPreview(false) - , m_boardSettings(new BoardSettings()) { + , m_boardSettings(new BoardSettings()) + , m_formatTemplateFId() { m_renderSettings = new TRenderSettings(); } @@ -61,7 +62,8 @@ TOutputProperties::TOutputProperties(const TOutputProperties &src) , m_maxTileSizeIndex(src.m_maxTileSizeIndex) , m_threadIndex(src.m_threadIndex) , m_subcameraPreview(src.m_subcameraPreview) - , m_boardSettings(new BoardSettings(*src.m_boardSettings)) { + , m_boardSettings(new BoardSettings(*src.m_boardSettings)) + , m_formatTemplateFId(src.m_formatTemplateFId) { std::map::iterator ft, fEnd = m_formatProperties.end(); for (ft = m_formatProperties.begin(); ft != fEnd; ++ft) { @@ -108,6 +110,8 @@ TOutputProperties &TOutputProperties::operator=(const TOutputProperties &src) { delete m_boardSettings; m_boardSettings = new BoardSettings(*src.m_boardSettings); + m_formatTemplateFId = src.m_formatTemplateFId; + return *this; } diff --git a/toonz/sources/toonzlib/preferences.cpp b/toonz/sources/toonzlib/preferences.cpp index aa94996..9a4c889 100644 --- a/toonz/sources/toonzlib/preferences.cpp +++ b/toonz/sources/toonzlib/preferences.cpp @@ -18,7 +18,6 @@ #include "tconvert.h" #include "tundo.h" #include "tbigmemorymanager.h" -#include "tfilepath.h" #include "timage_io.h" // Qt includes @@ -501,7 +500,8 @@ void Preferences::definePreferenceItems() { define(ffmpegMultiThread, "ffmpegMultiThread", QMetaType::Bool, false); // Drawing - define(scanLevelType, "scanLevelType", QMetaType::QString, "tif"); + define(DefRasterFormat, "DefRasterFormat", QMetaType::QString, "tif"); + // define(scanLevelType, "scanLevelType", QMetaType::QString, "tif"); define(DefLevelType, "DefLevelType", QMetaType::Int, TZP_XSHLEVEL); define(newLevelSizeToCameraSizeEnabled, "newLevelSizeToCameraSizeEnabled", QMetaType::Bool, false); @@ -781,6 +781,12 @@ void Preferences::resolveCompatibility() { else // Default (level name on top of each cell block) setValue(levelNameDisplayType, ShowLevelName_Default); } + // "scanLevelType" is changed to "DefRasterFormat", enabling to specify + // default format for both the Scan and the Raster levels. + if (m_settings->contains("scanLevelType") && + !m_settings->contains("DefRasterFormat")) { + setValue(DefRasterFormat, m_settings->value("scanLevelType").toString()); + } } //----------------------------------------------------------------- diff --git a/toonz/sources/toonzlib/sceneproperties.cpp b/toonz/sources/toonzlib/sceneproperties.cpp index 72627fe..6a420e7 100644 --- a/toonz/sources/toonzlib/sceneproperties.cpp +++ b/toonz/sources/toonzlib/sceneproperties.cpp @@ -320,6 +320,16 @@ void TSceneProperties::saveData(TOStream &os) const { os.closeChild(); } + if (out.formatTemplateFId().getZeroPadding() != + TFrameId().getZeroPadding() || + out.formatTemplateFId().getStartSeqInd() != + TFrameId().getStartSeqInd()) { + os.openChild("frameFormat"); + os.child("padding") << (int)out.formatTemplateFId().getZeroPadding(); + os.child("sepchar") << QString(out.formatTemplateFId().getStartSeqInd()); + os.closeChild(); + } + os.closeChild(); // } os.closeChild(); @@ -690,6 +700,20 @@ void TSceneProperties::loadData(TIStream &is, bool isLoadingProject) { } else if (tagName == "clapperboardSettings") { assert(out.getBoardSettings()); out.getBoardSettings()->loadData(is); + } else if (tagName == "frameFormat") { + while (is.matchTag(tagName)) { + if (tagName == "padding") { + int padding; + is >> padding; + out.formatTemplateFId().setZeroPadding(padding); + } else if (tagName == "sepchar") { + QString sepChar; + is >> sepChar; + out.formatTemplateFId().setStartSeqInd(sepChar[0].toLatin1()); + } else + throw TException("unexpected tag: " + tagName); + is.closeChild(); + } // end while } else { throw TException("unexpected property tag: " + tagName); } @@ -845,4 +869,11 @@ bool TSceneProperties::hasDefaultCellMarks() const { return false; } return true; -} \ No newline at end of file +} + +//----------------------------------------------------------------------------- +// templateFId in preview settings is used for "input" file format +// such as new raster level, captured images by camera capture feature, etc. +TFrameId &TSceneProperties::formatTemplateFIdForInput() { + return m_previewProp->formatTemplateFId(); +} diff --git a/toonz/sources/toonzlib/toonzscene.cpp b/toonz/sources/toonzlib/toonzscene.cpp index 6de0982..a14f116 100644 --- a/toonz/sources/toonzlib/toonzscene.cpp +++ b/toonz/sources/toonzlib/toonzscene.cpp @@ -1373,21 +1373,19 @@ TFilePath ToonzScene::getDefaultLevelPath(int levelType, TProject *project = getProject(); assert(project); TFilePath levelPath; - QString scanLevelType; switch (levelType) { case TZI_XSHLEVEL: - scanLevelType = Preferences::instance()->getScanLevelType(); - levelPath = TFilePath(levelName + L".." + scanLevelType.toStdWString()); - break; + case OVL_XSHLEVEL: { + QString rasterLevelType = Preferences::instance()->getDefRasterFormat(); + TFrameId tmplFId = getProperties()->formatTemplateFIdForInput(); + levelPath = TFilePath(levelName + L"." + rasterLevelType.toStdWString()) + .withFrame(tmplFId); + } break; case PLI_XSHLEVEL: levelPath = TFilePath(levelName).withType("pli"); break; case TZP_XSHLEVEL: levelPath = TFilePath(levelName).withType("tlv"); - break; - case OVL_XSHLEVEL: - levelPath = TFilePath(levelName + L"..tif"); - break; default: levelPath = TFilePath(levelName + L"..png"); } diff --git a/toonz/sources/toonzlib/txshsimplelevel.cpp b/toonz/sources/toonzlib/txshsimplelevel.cpp index b867a91..04a3fca 100644 --- a/toonz/sources/toonzlib/txshsimplelevel.cpp +++ b/toonz/sources/toonzlib/txshsimplelevel.cpp @@ -34,6 +34,7 @@ #include "tstream.h" #include "tsystem.h" #include "tcontenthistory.h" +#include "tfilepath.h" // Qt includes #include @@ -780,6 +781,27 @@ TImageP buildIcon(const TImageP &img, const TDimension &size) { //----------------------------------------------------------------------------- +// modify frameId to be with the same frame format as existing frames +void TXshSimpleLevel::formatFId(TFrameId &fid, TFrameId _tmplFId) { + if (m_type != OVL_XSHLEVEL && m_type != TZI_XSHLEVEL) return; + + if (!m_frames.empty()) { + TFrameId tmplFId = *m_frames.begin(); + fid.setZeroPadding(tmplFId.getZeroPadding()); + fid.setStartSeqInd(tmplFId.getStartSeqInd()); + } + // since there is no reference frame, take sepChar from the path + else { + // override sepchar by the path + QChar sepChar = m_path.getSepChar(); + if (!sepChar.isNull()) _tmplFId.setStartSeqInd(sepChar.toLatin1()); + fid.setZeroPadding(_tmplFId.getZeroPadding()); + fid.setStartSeqInd(_tmplFId.getStartSeqInd()); + } +} + +//----------------------------------------------------------------------------- + void TXshSimpleLevel::setFrame(const TFrameId &fid, const TImageP &img) { assert(m_type != UNKNOWN_XSHLEVEL); diff --git a/toonz/sources/toonzqt/colorfield.cpp b/toonz/sources/toonzqt/colorfield.cpp index dfb4f53..3aada34 100644 --- a/toonz/sources/toonzqt/colorfield.cpp +++ b/toonz/sources/toonzqt/colorfield.cpp @@ -489,7 +489,7 @@ ColorField::ColorField(QWidget *parent, bool isAlphaActive, TPixel32 color, */ void ColorField::setAlphaActive(bool active) { - if (active && !m_alphaChannel->isVisible()) { + if (active && !m_alphaChannel->isVisibleTo(this)) { m_alphaChannel->show(); connect(m_alphaChannel, SIGNAL(valueChanged(int, bool)), SLOT(onAlphaChannelChanged(int, bool))); @@ -498,7 +498,7 @@ void ColorField::setAlphaActive(bool active) { m_color.m = 0; m_colorSample->setColor(m_color); emit colorChanged(m_color, false); - } else if (!active && m_alphaChannel->isVisible()) { + } else if (!active && m_alphaChannel->isVisibleTo(this)) { m_alphaChannel->hide(); disconnect(m_alphaChannel, SIGNAL(valueChanged(int, bool)), this, SLOT(onAlphaChannelChanged(int, bool))); diff --git a/toonz/sources/toonzqt/imageutils.cpp b/toonz/sources/toonzqt/imageutils.cpp index eedf823..1ee0bf9 100644 --- a/toonz/sources/toonzqt/imageutils.cpp +++ b/toonz/sources/toonzqt/imageutils.cpp @@ -592,7 +592,8 @@ static void convertFromVector(const TLevelReaderP &lr, const TLevelWriterP &lw, void convert(const TFilePath &source, const TFilePath &dest, const TFrameId &from, const TFrameId &to, double framerate, TPropertyGroup *prop, FrameTaskNotifier *frameNotifier, - const TPixel &bgColor, bool removeDotBeforeFrameNumber) { + const TPixel &bgColor, bool removeDotBeforeFrameNumber, + const TFrameId &tmplFId) { std::string dstExt = dest.getType(), srcExt = source.getType(); // Load source level structure @@ -621,6 +622,7 @@ void convert(const TFilePath &source, const TFilePath &dest, // Write the destination level TLevelWriterP lw(dest, prop); lw->setFrameRate(framerate); + lw->setFrameFormatTemplateFId(tmplFId); if (srcExt == "tlv") convertFromCM(lr, level->getPalette(), lw, frames, TAffine(),