From cdef06c259ff6182180d7d4912995df2fa0d3533 Mon Sep 17 00:00:00 2001 From: manongjohn <19245851+manongjohn@users.noreply.github.com> Date: Wed, 27 Sep 2023 13:47:58 -0400 Subject: [PATCH] Render Key Drawings Only --- toonz/sources/include/tfarmtask.h | 9 ++- .../include/toonz/multimediarenderer.h | 5 +- toonz/sources/include/toutputproperties.h | 4 ++ toonz/sources/tcomposer/tcomposer.cpp | 9 ++- toonz/sources/toonz/batches.cpp | 3 +- toonz/sources/toonz/outputsettingspopup.cpp | 27 +++++++- toonz/sources/toonz/outputsettingspopup.h | 2 + toonz/sources/toonz/rendercommand.cpp | 12 +++- toonz/sources/toonz/tasksviewer.cpp | 36 ++++++++++- toonz/sources/toonz/tasksviewer.h | 2 + toonz/sources/toonzfarm/tfarm/tfarmtask.cpp | 37 ++++++----- toonz/sources/toonzlib/multimediarenderer.cpp | 62 ++++++++++++++++--- toonz/sources/toonzlib/outputproperties.cpp | 3 + toonz/sources/toonzlib/sceneproperties.cpp | 8 +++ 14 files changed, 181 insertions(+), 38 deletions(-) diff --git a/toonz/sources/include/tfarmtask.h b/toonz/sources/include/tfarmtask.h index 03751bc8..5ed368bd 100644 --- a/toonz/sources/include/tfarmtask.h +++ b/toonz/sources/include/tfarmtask.h @@ -97,6 +97,8 @@ public: int m_chunkSize; //!< Sub-tasks size int m_multimedia; + bool m_renderKeysOnly; + int m_threadsIndex; int m_maxTileSizeIndex; @@ -118,8 +120,8 @@ public: const QString &user, const QString &host, int stepCount, int priority, const TFilePath &taskFilePath, const TFilePath &outputPath, int from, int to, int step, int shrink, - int multimedia, int chunksize, int threadsIndex, - int maxTileSizeIndex, OverwriteBehavior overwrite, + int multimedia, bool renderKeysOnly, int chunksize, + int threadsIndex, int maxTileSizeIndex, OverwriteBehavior overwrite, bool onlyvisible); virtual ~TFarmTask() { delete m_dependencies; } @@ -155,7 +157,8 @@ public: const QString &host, int stepCount, int priority, const TFilePath &taskFilePath, const TFilePath &outputPath, int from, int to, int step, int shrink, int multimedia, - int chunksize, int threadsIndex, int maxTileSizeIndex); + bool renderKeysOnly, int chunksize, int threadsIndex, + int maxTileSizeIndex); TFarmTaskGroup(const QString &id, const QString &name, const QString &user, const QString &host, int stepCount, int priority, diff --git a/toonz/sources/include/toonz/multimediarenderer.h b/toonz/sources/include/toonz/multimediarenderer.h index fd3d7a72..b88f1b07 100644 --- a/toonz/sources/include/toonz/multimediarenderer.h +++ b/toonz/sources/include/toonz/multimediarenderer.h @@ -67,8 +67,8 @@ public: //---------------------------------------------------------------- MultimediaRenderer(ToonzScene *scene, const TFilePath &moviePath, - int multimediaMode, int threadCount = 1, - bool cacheResults = true); + int multimediaMode, bool renderKeysOnly, + int threadCount = 1, bool cacheResults = true); ~MultimediaRenderer(); @@ -84,6 +84,7 @@ public: enum { COLUMNS = 1, LAYERS = 2 }; int getMultimediaMode() const; + bool isRenderKeysOnly() const; //! Returns the currently active TRenderer. TRenderer *getTRenderer(); diff --git a/toonz/sources/include/toutputproperties.h b/toonz/sources/include/toutputproperties.h index 0002bec6..1b8b57e5 100644 --- a/toonz/sources/include/toutputproperties.h +++ b/toonz/sources/include/toutputproperties.h @@ -86,6 +86,7 @@ private: int m_offset, m_step; int m_multimediaRendering; + bool m_renderKeysOnly; int m_maxTileSizeIndex; int m_threadIndex; @@ -211,6 +212,9 @@ Insert in \b v all extension in format properties of output settings. void setMultimediaRendering(int mode) { m_multimediaRendering = mode; } int getMultimediaRendering() const { return m_multimediaRendering; } + void setRenderKeysOnly(bool keysOnly) { m_renderKeysOnly = keysOnly; } + bool isRenderKeysOnly() const { return m_renderKeysOnly; } + /*! Sets the granularity of raster allocations for rendering processes. The specified value refers to an index associated with const values, spanning from 0 (no bound, ie giant rasters are allowed) to 3 (highly diff --git a/toonz/sources/tcomposer/tcomposer.cpp b/toonz/sources/tcomposer/tcomposer.cpp index 1b93b2b0..05538b63 100644 --- a/toonz/sources/tcomposer/tcomposer.cpp +++ b/toonz/sources/tcomposer/tcomposer.cpp @@ -486,6 +486,7 @@ static std::pair generateMovie(ToonzScene *scene, const TFilePath &fp, double stepd = step * timeStretchFactor; int multimediaRender = outputSettings.getMultimediaRendering(); + bool renderKeysOnly = outputSettings.isRenderKeysOnly(); //--------------------------------------------------------- // Multimedia render @@ -493,7 +494,7 @@ static std::pair generateMovie(ToonzScene *scene, const TFilePath &fp, if (multimediaRender) { MultimediaRenderer multimediaRenderer(scene, fp, multimediaRender, - threadCount); + renderKeysOnly, threadCount); TRenderSettings rs = outputSettings.getRenderSettings(); rs.m_maxTileSize = maxTileSize; rs.m_shrinkX = rs.m_shrinkY = shrink; @@ -608,6 +609,7 @@ int main(int argc, char *argv[]) { IntQualifier stepOpt("-step n", "Step"); IntQualifier shrinkOpt("-shrink n", "Shrink"); IntQualifier multimedia("-multimedia n", "Multimedia rendering mode"); + IntQualifier renderKeysOnly("-renderkeysonly n", "Render keys drawings only"); StringQualifier farmData("-farm data", "TFarm Controller"); StringQualifier idq("-id n", "id"); StringQualifier nthreads("-nthreads n", "Number of rendering threads"); @@ -615,7 +617,7 @@ int main(int argc, char *argv[]) { "Enable tile rendering of max n MB per tile"); StringQualifier tmsg("-tmsg val", "only internal use"); usageLine = srcName + dstName + range + stepOpt + shrinkOpt + multimedia + - farmData + idq + nthreads + tileSize + tmsg; + renderKeysOnly + farmData + idq + nthreads + tileSize + tmsg; // system path qualifiers std::map>> @@ -927,6 +929,9 @@ int main(int argc, char *argv[]) { if (multimedia.isSelected()) scene->getProperties()->getOutputProperties()->setMultimediaRendering( multimedia.getValue()); + if (renderKeysOnly.isSelected()) + scene->getProperties()->getOutputProperties()->setRenderKeysOnly( + renderKeysOnly.getValue()); // Retrieve Thread count const int procCount = TSystem::getProcessorCount(); diff --git a/toonz/sources/toonz/batches.cpp b/toonz/sources/toonz/batches.cpp index 3c4478b6..2ec2b63b 100644 --- a/toonz/sources/toonz/batches.cpp +++ b/toonz/sources/toonz/batches.cpp @@ -360,6 +360,7 @@ void BatchesController::addComposerTask(const TFilePath &_taskFilePath) { int shrink = rs.m_shrinkX; int multimedia = out.getMultimediaRendering(); + bool renderKeysOnly = out.isRenderKeysOnly(); int threadsIndex = out.getThreadIndex(); int maxTileSizeIndex = out.getMaxTileSizeIndex(); @@ -385,7 +386,7 @@ void BatchesController::addComposerTask(const TFilePath &_taskFilePath) { TFarmTaskGroup *taskGroup = new TFarmTaskGroup( id, name, TSystem::getUserName(), TSystem::getHostName(), sceneFrameCount, 50, taskFilePath, outputPath, r0, r1, step, shrink, multimedia, - taskChunkSize, threadsIndex, maxTileSizeIndex); + renderKeysOnly, taskChunkSize, threadsIndex, maxTileSizeIndex); try { BatchesController::instance()->addTask(id, taskGroup); diff --git a/toonz/sources/toonz/outputsettingspopup.cpp b/toonz/sources/toonz/outputsettingspopup.cpp index 80496376..d5041e54 100644 --- a/toonz/sources/toonz/outputsettingspopup.cpp +++ b/toonz/sources/toonz/outputsettingspopup.cpp @@ -938,6 +938,9 @@ QFrame *OutputSettingsPopup::createMoreSettingsBox() { m_multimediaOm->installEventFilter(this); m_stereoShift->setEnabled(false); + m_renderKeysOnly = new DVGui::CheckBox(tr("Render Key Drawings Only"), this); + m_renderKeysOnly->setEnabled(false); + //----- QGridLayout *lay = new QGridLayout(); @@ -978,11 +981,13 @@ QFrame *OutputSettingsPopup::createMoreSettingsBox() { Qt::AlignRight | Qt::AlignVCenter); lay->addWidget(m_multimediaOm, 5, 1, 1, 3, Qt::AlignLeft | Qt::AlignVCenter); + lay->addWidget(m_renderKeysOnly, 6, 1, 1, 3, + Qt::AlignLeft | Qt::AlignVCenter); - lay->addWidget(m_doStereoscopy, 6, 0); - lay->addWidget(new QLabel(tr("Camera Shift:")), 6, 1, 1, 2, + lay->addWidget(m_doStereoscopy, 7, 0); + lay->addWidget(new QLabel(tr("Camera Shift:")), 7, 1, 1, 2, Qt::AlignRight | Qt::AlignVCenter); - lay->addWidget(m_stereoShift, 6, 3, Qt::AlignLeft | Qt::AlignVCenter); + lay->addWidget(m_stereoShift, 8, 3, Qt::AlignLeft | Qt::AlignVCenter); } lay->setColumnStretch(4, 1); @@ -1013,6 +1018,8 @@ QFrame *OutputSettingsPopup::createMoreSettingsBox() { SLOT(onStereoChecked(int))); ret = ret && connect(m_stereoShift, SIGNAL(editingFinished()), SLOT(onStereoChanged())); + ret = ret && connect(m_renderKeysOnly, SIGNAL(stateChanged(int)), this, + SLOT(onRenderKeysOnlyChecked(int))); assert(ret); return moreSettingsBox; } @@ -1165,6 +1172,8 @@ void OutputSettingsPopup::updateField() { m_fileFormat->setCurrentIndex( m_fileFormat->findText(QString::fromStdString(path.getType()))); m_multimediaOm->setCurrentIndex(prop->getMultimediaRendering()); + m_renderKeysOnly->setChecked(prop->isRenderKeysOnly()); + m_renderKeysOnly->setEnabled(prop->getMultimediaRendering()); } // Refresh format if allow-multithread was toggled @@ -1831,6 +1840,18 @@ void OutputSettingsPopup::onMultimediaChanged(int state) { if (prop->getMultimediaRendering() == state) return; prop->setMultimediaRendering(state); + m_renderKeysOnly->setEnabled(state); + + TApp::instance()->getCurrentScene()->setDirtyFlag(true); +} + +//----------------------------------------------------------------------------- + +void OutputSettingsPopup::onRenderKeysOnlyChecked(int) { + if (!getCurrentScene()) return; + TOutputProperties *prop = getProperties(); + prop->setRenderKeysOnly(m_renderKeysOnly->isChecked()); + TApp::instance()->getCurrentScene()->setDirtyFlag(true); } diff --git a/toonz/sources/toonz/outputsettingspopup.h b/toonz/sources/toonz/outputsettingspopup.h index 4a1cc0c0..4b73dc0d 100644 --- a/toonz/sources/toonz/outputsettingspopup.h +++ b/toonz/sources/toonz/outputsettingspopup.h @@ -70,6 +70,7 @@ class OutputSettingsPopup : public DVGui::Dialog { QComboBox *m_rasterGranularityOm; QComboBox *m_threadsComboOm; bool m_allowMT; + DVGui::CheckBox *m_renderKeysOnly; DVGui::DoubleLineEdit *m_frameRateFld; QPushButton *m_fileFormatButton; @@ -131,6 +132,7 @@ protected slots: void onApplyShrinkChecked(int state); void onSubcameraChecked(int state); void onMultimediaChanged(int mode); + void onRenderKeysOnlyChecked(int); void onThreadsComboChanged(int type); void onRasterGranularityChanged(int type); void onStereoChecked(int); diff --git a/toonz/sources/toonz/rendercommand.cpp b/toonz/sources/toonz/rendercommand.cpp index 5bfa9676..33f6b7b8 100644 --- a/toonz/sources/toonz/rendercommand.cpp +++ b/toonz/sources/toonz/rendercommand.cpp @@ -162,6 +162,7 @@ class RenderCommand { double m_timeStretchFactor; int m_multimediaRender; + bool m_renderKeysOnly; public: RenderCommand() @@ -173,7 +174,8 @@ public: , m_stepd(1) , m_oldCameraRes(0, 0) , m_timeStretchFactor(1) - , m_multimediaRender(0) { + , m_multimediaRender(0) + , m_renderKeysOnly(false) { setCommandHandler("MI_Render", this, &RenderCommand::onRender); setCommandHandler("MI_SaveAndRender", this, &RenderCommand::onSaveAndRender); setCommandHandler("MI_FastRender", this, &RenderCommand::onFastRender); @@ -238,6 +240,7 @@ sprop->getOutputProperties()->setRenderSettings(rso);*/ m_r = m_r0; m_stepd = m_step; m_multimediaRender = 0; + m_renderKeysOnly = false; return true; } @@ -302,6 +305,7 @@ sprop->getOutputProperties()->setRenderSettings(rso);*/ // Update the multimedia render switch m_multimediaRender = outputSettings.getMultimediaRendering(); + m_renderKeysOnly = outputSettings.isRenderKeysOnly(); return true; } @@ -731,8 +735,10 @@ void RenderCommand::multimediaRender() { TRenderSettings rs = prop->getRenderSettings(); rs.m_maxTileSize = maxTileSizes[index]; - MultimediaRenderer multimediaRenderer( - scene, m_fp, prop->getMultimediaRendering(), threadCount); + int multimedia = prop->getMultimediaRendering(); + bool renderKeysOnly = prop->isRenderKeysOnly(); + MultimediaRenderer multimediaRenderer(scene, m_fp, multimedia, renderKeysOnly, + threadCount); multimediaRenderer.setRenderSettings(rs); TPointD cameraDpi = scene->getCurrentCamera()->getDpi(); diff --git a/toonz/sources/toonz/tasksviewer.cpp b/toonz/sources/toonz/tasksviewer.cpp index 2c188a53..95573a12 100644 --- a/toonz/sources/toonz/tasksviewer.cpp +++ b/toonz/sources/toonz/tasksviewer.cpp @@ -340,6 +340,8 @@ void TaskSheet::update(TFarmTask *task) { m_step->setText(QString::number(task->m_step)); m_shrink->setText(QString::number(task->m_shrink)); m_multimedia->setCurrentIndex(task->m_multimedia); + m_renderKeysOnly->setChecked(task->m_renderKeysOnly); + m_renderKeysOnly->setEnabled(m_multimedia->currentIndex()); m_threadsCombo->setCurrentIndex(task->m_threadsIndex); m_rasterGranularityCombo->setCurrentIndex(task->m_maxTileSizeIndex); @@ -445,9 +447,9 @@ void inline create(QLabel *&ret, QGridLayout *layout, QString name, int row, //----------------------------------------------------------------------------- -void inline create(CheckBox *&ret, QGridLayout *layout, QString name, int row) { +void inline create(CheckBox *&ret, QGridLayout *layout, QString name, int row, int col = 0) { ret = new CheckBox(name); - layout->addWidget(ret, row, 0, 1, 2, Qt::AlignLeft | Qt::AlignVCenter); + layout->addWidget(ret, row, col, 1, 2, Qt::AlignLeft | Qt::AlignVCenter); } //----------------------------------------------------------------------------- @@ -692,6 +694,30 @@ void TaskSheet::setMultimedia(int) { taskGroup->getTask(i)->m_multimedia = taskGroup->m_multimedia; } + m_renderKeysOnly->setEnabled(m_multimedia->currentIndex()); + + m_viewer->startTimer(); +} + +//----------------------------------------------------------------------------- + +void TaskSheet::setRenderKeysOnly(int) { + if (!m_task) return; + if (m_task->m_renderKeysOnly == + (m_renderKeysOnly->checkState() == Qt::Checked)) + return; + + m_task->m_renderKeysOnly = (m_renderKeysOnly->checkState() == Qt::Checked); + m_commandLine->setText(m_task->getCommandLine()); + BatchesController::instance()->setDirtyFlag(true); + + // Update children tasks, if present. + TFarmTaskGroup *taskGroup = dynamic_cast(m_task); + if (taskGroup) { + for (int i = 0; i < taskGroup->getTaskCount(); ++i) + taskGroup->getTask(i)->m_renderKeysOnly = taskGroup->m_renderKeysOnly; + } + m_viewer->startTimer(); } @@ -845,6 +871,8 @@ TaskSheet::TaskSheet(TasksViewer *owner) : QScrollArea(owner) { ::create(m_chunkSize, m_multimedia, layout1, tr("Frames per Chunk:"), tr("Multimedia:"), Qt::AlignRight | Qt::AlignTop, Qt::AlignLeft | Qt::AlignTop, row1++); + ::create(m_renderKeysOnly, layout1, tr("Render Key Drawings Only"), row1++, + 4); ::create(m_from, m_to, layout1, tr("From:"), tr("To:"), Qt::AlignRight | Qt::AlignTop, Qt::AlignRight | Qt::AlignTop, row1++); @@ -858,6 +886,8 @@ TaskSheet::TaskSheet(TasksViewer *owner) : QScrollArea(owner) { << tr("Fx Schematic Terminal Nodes"); m_multimedia->addItems(multimediaTypes); + m_renderKeysOnly->setEnabled(false); + ::create(m_threadsCombo, layout1, tr("Dedicated CPUs:"), row1++, 3); QStringList threadsTypes; threadsTypes << tr("Single") << tr("Half") << tr("All"); @@ -953,6 +983,8 @@ TaskSheet::TaskSheet(TasksViewer *owner) : QScrollArea(owner) { ret = ret && connect(m_multimedia, SIGNAL(currentIndexChanged(int)), this, SLOT(setMultimedia(int))); + ret = ret && connect(m_renderKeysOnly, SIGNAL(stateChanged(int)), this, + SLOT(setRenderKeysOnly(int))); ret = ret && connect(m_visible, SIGNAL(stateChanged(int)), this, SLOT(setVisible(int))); diff --git a/toonz/sources/toonz/tasksviewer.h b/toonz/sources/toonz/tasksviewer.h index 827375e6..2bb0cf4b 100644 --- a/toonz/sources/toonz/tasksviewer.h +++ b/toonz/sources/toonz/tasksviewer.h @@ -126,6 +126,7 @@ class TaskSheet final : public QScrollArea { QListWidget *m_addedBox; QListWidget *m_notAddedBox; DVGui::CheckBox *m_visible; + DVGui::CheckBox *m_renderKeysOnly; QComboBox *m_overwrite; QComboBox *m_multimedia; QComboBox *m_threadsCombo; @@ -148,6 +149,7 @@ protected slots: void setVisible(int); void setOverwrite(int); void setMultimedia(int); + void setRenderKeysOnly(int); void setThreadsCombo(int); void setGranularityCombo(int); void setPriority(); diff --git a/toonz/sources/toonzfarm/tfarm/tfarmtask.cpp b/toonz/sources/toonzfarm/tfarm/tfarmtask.cpp index 28fd4b29..0bd6b564 100644 --- a/toonz/sources/toonzfarm/tfarm/tfarmtask.cpp +++ b/toonz/sources/toonzfarm/tfarm/tfarmtask.cpp @@ -129,6 +129,7 @@ TFarmTask::TFarmTask(const QString &name) , m_shrink(-1) , m_chunkSize(-1) , m_multimedia(0) // Full render, no multimedia + , m_renderKeysOnly(false) , m_threadsIndex(2) // All threads , m_maxTileSizeIndex(0) // No tiling , m_overwrite() @@ -142,8 +143,8 @@ TFarmTask::TFarmTask(const QString &id, const QString &name, bool composerTask, const QString &user, const QString &host, int stepCount, int priority, const TFilePath &taskFilePath, const TFilePath &outputPath, int from, int to, int step, - int shrink, int multimedia, int chunksize, - int threadsIndex, int maxTileSizeIndex, + int shrink, int multimedia, bool renderKeysOnly, + int chunksize, int threadsIndex, int maxTileSizeIndex, OverwriteBehavior overwrite, bool onlyvisible) : m_isComposerTask(composerTask) @@ -164,6 +165,7 @@ TFarmTask::TFarmTask(const QString &id, const QString &name, bool composerTask, , m_step(step) , m_shrink(shrink) , m_multimedia(multimedia) + , m_renderKeysOnly(renderKeysOnly) , m_threadsIndex(threadsIndex) , m_maxTileSizeIndex(maxTileSizeIndex) , m_chunkSize(chunksize) @@ -221,6 +223,7 @@ TFarmTask &TFarmTask::operator=(const TFarmTask &rhs) { m_onlyVisible = rhs.m_onlyVisible; m_overwrite = rhs.m_overwrite; m_multimedia = rhs.m_multimedia; + m_renderKeysOnly = rhs.m_renderKeysOnly; m_threadsIndex = rhs.m_threadsIndex; m_maxTileSizeIndex = rhs.m_maxTileSizeIndex; m_chunkSize = rhs.m_chunkSize; @@ -262,6 +265,7 @@ bool TFarmTask::operator==(const TFarmTask &task) { task.m_from == m_from && task.m_to == m_to && task.m_step == m_step && task.m_shrink == m_shrink && task.m_onlyVisible == m_onlyVisible && task.m_overwrite == m_overwrite && task.m_multimedia == m_multimedia && + task.m_renderKeysOnly == m_renderKeysOnly && task.m_threadsIndex == m_threadsIndex && task.m_maxTileSizeIndex == m_maxTileSizeIndex && task.m_chunkSize == m_chunkSize && equalDependencies); @@ -442,6 +446,9 @@ void TFarmTask::parseCommandLine(QString commandLine) { } else if (l.at(i) == "-multimedia") { m_multimedia = (l.at(i + 1).toInt()); i += 2; + } else if (l.at(i) == "-renderkeysonly") { + m_renderKeysOnly = (l.at(i + 1).toInt()); + i += 2; } else if (l.at(i) == "-nthreads") { QString str(l.at(i + 1)); @@ -526,6 +533,7 @@ QString TFarmTask::getCommandLineArguments() const { cmdline += " -step " + QString::number(m_step); cmdline += " -shrink " + QString::number(m_shrink); cmdline += " -multimedia " + QString::number(m_multimedia); + cmdline += " -renderkeysonly " + QString::number(m_renderKeysOnly ? 1 : 0); const QString threadCounts[3] = {"single", "half", "all"}; cmdline += " -nthreads " + threadCounts[m_threadsIndex]; @@ -579,6 +587,7 @@ QStringList TFarmTask::getCommandLineArgumentsList() const { ret << "-step" << QString::number(m_step); ret << "-shrink" << QString::number(m_shrink); ret << "-multimedia" << QString::number(m_multimedia); + ret << "-renderkeysonly" << QString::number(m_renderKeysOnly ? 1 : 0); const QString threadCounts[3] = {"single", "half", "all"}; ret << "-nthreads" << threadCounts[m_threadsIndex]; @@ -664,8 +673,8 @@ bool TFarmTaskGroup::changeChunkSize(int chunksize) { TFarmTask *subTask = new TFarmTask( m_id + "." + toString(i, 2, '0'), subName, true, m_user, m_hostName, rb - ra + 1, m_priority, m_taskFilePath, m_outputPath, ra, rb, - m_step, m_shrink, m_multimedia, m_chunkSize, m_threadsIndex, - m_maxTileSizeIndex, Overwrite_Off, false); + m_step, m_shrink, m_multimedia, m_renderKeysOnly, m_chunkSize, + m_threadsIndex, m_maxTileSizeIndex, Overwrite_Off, false); subTask->m_parentId = m_id; addTask(subTask); @@ -688,12 +697,12 @@ TFarmTaskGroup::TFarmTaskGroup(const QString &id, const QString &name, const TFilePath &taskFilePath, const TFilePath &outputPath, int from, int to, int step, int shrink, int multimedia, - int chunksize, int threadsIndex, - int maxTileSizeIndex) + bool renderKeysOnly, int chunksize, + int threadsIndex, int maxTileSizeIndex) : TFarmTask(id, name, true, user, host, stepCount, priority, taskFilePath, - outputPath, from, to, step, shrink, multimedia, chunksize, - threadsIndex, maxTileSizeIndex, Overwrite_Off, false) + outputPath, from, to, step, shrink, multimedia, renderKeysOnly, + chunksize, threadsIndex, maxTileSizeIndex, Overwrite_Off, false) , m_imp(new Imp()) { int subCount = 0; if (chunksize > 0) subCount = tceil((to - from + 1) / (double)chunksize); @@ -708,11 +717,11 @@ TFarmTaskGroup::TFarmTaskGroup(const QString &id, const QString &name, name + " " + toString(ra, 2, '0') + "-" + toString(rb, 2, '0'); stepCount = rb - ra + 1; - TFarmTask *subTask = - new TFarmTask(id + "." + toString(i, 2, '0'), subName, true, user, - host, stepCount, priority, taskFilePath, outputPath, - ra, rb, step, shrink, multimedia, chunksize, - threadsIndex, maxTileSizeIndex, Overwrite_Off, false); + TFarmTask *subTask = new TFarmTask( + id + "." + toString(i, 2, '0'), subName, true, user, host, + stepCount, priority, taskFilePath, outputPath, ra, rb, step, shrink, + multimedia, renderKeysOnly, chunksize, threadsIndex, + maxTileSizeIndex, Overwrite_Off, false); subTask->m_parentId = id; addTask(subTask); @@ -733,7 +742,7 @@ TFarmTaskGroup::TFarmTaskGroup(const QString &id, const QString &name, const TFilePath &taskFilePath, OverwriteBehavior overwrite, bool onlyvisible) : TFarmTask(id, name, false, user, host, stepCount, priority, taskFilePath, - TFilePath(), 0, 0, 0, 0, 0, 0, 0, 0, overwrite, onlyvisible) + TFilePath(), 0, 0, 0, 0, 0, 0, 0, 0, 0, overwrite, onlyvisible) , m_imp(new Imp()) {} //------------------------------------------------------------------------------ diff --git a/toonz/sources/toonzlib/multimediarenderer.cpp b/toonz/sources/toonzlib/multimediarenderer.cpp index abc4272a..f4c47f15 100644 --- a/toonz/sources/toonzlib/multimediarenderer.cpp +++ b/toonz/sources/toonzlib/multimediarenderer.cpp @@ -10,6 +10,9 @@ #include "toonz/txsheet.h" #include "toonz/fxdag.h" #include "toonz/tcolumnfxset.h" +#include "toonz/txshlevelcolumn.h" +#include "toonz/txshzeraryfxcolumn.h" +#include "toonz/txshcell.h" // Fxs tree decomposition #include "toonz/scenefx.h" @@ -69,9 +72,10 @@ public: QEventLoop m_eventLoop; int m_multimediaMode; + bool m_renderKeysOnly; Imp(ToonzScene *scene, const TFilePath &moviePath, int multimediaMode, - int threadCount, bool cacheResults); + bool renderKeysOnly, int threadCount, bool cacheResults); ~Imp(); @@ -79,6 +83,7 @@ public: void scanSceneForColumns(); void scanSceneForLayers(); bool scanColsRecursive(TFx *fx); + bool hasKeyDrawing(TFx *fx, int row); TColumnFx *searchColumn(TFxP fx); TFxP addPostProcessing(TFxP fx, TFxP postProc); void addPostProcessingRecursive(TFxP fx, TFxP postProc); @@ -94,8 +99,8 @@ public: //--------------------------------------------------------- MultimediaRenderer::Imp::Imp(ToonzScene *scene, const TFilePath &moviePath, - int multimediaMode, int threadCount, - bool cacheResults) + int multimediaMode, bool renderKeysOnly, + int threadCount, bool cacheResults) : m_scene(scene) , m_fp(moviePath) , m_threadCount(threadCount) @@ -108,7 +113,8 @@ MultimediaRenderer::Imp::Imp(ToonzScene *scene, const TFilePath &moviePath, , m_canceled(false) , m_currentFx(0) , m_currentFrame() - , m_multimediaMode(multimediaMode) { + , m_multimediaMode(multimediaMode) + , m_renderKeysOnly(renderKeysOnly) { // Retrieve all fx nodes to be rendered in this process. scanSceneForRenderNodes(); } @@ -172,6 +178,35 @@ bool MultimediaRenderer::Imp::scanColsRecursive(TFx *fx) { return false; } +bool MultimediaRenderer::Imp::hasKeyDrawing(TFx *fx, int row) { + TColumnFx *colFx = dynamic_cast(fx); + if (colFx) { + TXshColumn *col = colFx->getXshColumn(); + if (!col) return false; + TXshCellColumn *celCol = col->getCellColumn(); + if (!celCol) return false; + + TXshCell cell = celCol->getCell(row, false); + TXshCell prevCell = row > 0 ? celCol->getCell(row - 1, false) : TXshCell(); + + if (cell.isEmpty() || cell.getFrameId().isStopFrame() || cell == prevCell) + return false; + + return true; + } + + // Search for key drawings in every port + bool doesChildHaveKey; + for (int i = 0; i < fx->getInputPortCount(); ++i) { + TFx *childFx = fx->getInputPort(i)->getFx(); + if (!childFx) continue; + doesChildHaveKey = hasKeyDrawing(childFx, row); + if (doesChildHaveKey) return true; + } + + return false; +} + //--------------------------------------------------------- //! Build the scene fx for each node below the xsheet one. @@ -310,6 +345,11 @@ void MultimediaRenderer::Imp::start() { int j; for (j = 0, jt = m_framesToRender.begin(); jt != m_framesToRender.end(); ++j, ++jt) { + + if (m_multimediaMode && m_renderKeysOnly && + !hasKeyDrawing(m_fxsToRender.getFx(i), *jt)) + continue; + TFxPair fx; if (m_renderSettings.m_stereoscopic) @@ -446,10 +486,10 @@ void MultimediaRenderer::Imp::onRenderCompleted() { MultimediaRenderer::MultimediaRenderer(ToonzScene *scene, const TFilePath &moviePath, - int multimediaMode, int threadCount, - bool cacheResults) - : m_imp(new Imp(scene, moviePath, multimediaMode, threadCount, - cacheResults)) { + int multimediaMode, bool renderKeysOnly, + int threadCount, bool cacheResults) + : m_imp(new Imp(scene, moviePath, multimediaMode, renderKeysOnly, + threadCount, cacheResults)) { m_imp->addRef(); } @@ -481,6 +521,12 @@ int MultimediaRenderer::getMultimediaMode() const { //--------------------------------------------------------- +bool MultimediaRenderer::isRenderKeysOnly() const { + return m_imp->m_renderKeysOnly; +} + +//--------------------------------------------------------- + void MultimediaRenderer::setRenderSettings( const TRenderSettings &renderSettings) { // assert(m_imp->m_framesOnRendering.empty()); diff --git a/toonz/sources/toonzlib/outputproperties.cpp b/toonz/sources/toonzlib/outputproperties.cpp index 5b718966..fa171df6 100644 --- a/toonz/sources/toonzlib/outputproperties.cpp +++ b/toonz/sources/toonzlib/outputproperties.cpp @@ -38,6 +38,7 @@ TOutputProperties::TOutputProperties() , m_step(1) , m_whichLevels(false) , m_multimediaRendering(0) + , m_renderKeysOnly(false) , m_maxTileSizeIndex(0) , m_threadIndex(2) , m_subcameraPreview(false) @@ -61,6 +62,7 @@ TOutputProperties::TOutputProperties(const TOutputProperties &src) , m_offset(src.m_offset) , m_step(src.m_step) , m_multimediaRendering(src.m_multimediaRendering) + , m_renderKeysOnly(src.m_renderKeysOnly) , m_maxTileSizeIndex(src.m_maxTileSizeIndex) , m_threadIndex(src.m_threadIndex) , m_subcameraPreview(src.m_subcameraPreview) @@ -96,6 +98,7 @@ TOutputProperties &TOutputProperties::operator=(const TOutputProperties &src) { m_step = src.m_step; m_multimediaRendering = src.m_multimediaRendering; + m_renderKeysOnly = src.m_renderKeysOnly; m_maxTileSizeIndex = src.m_maxTileSizeIndex; m_threadIndex = src.m_threadIndex; m_subcameraPreview = src.m_subcameraPreview; diff --git a/toonz/sources/toonzlib/sceneproperties.cpp b/toonz/sources/toonzlib/sceneproperties.cpp index 8fc09057..f74c32f4 100644 --- a/toonz/sources/toonzlib/sceneproperties.cpp +++ b/toonz/sources/toonzlib/sceneproperties.cpp @@ -258,6 +258,10 @@ void TSceneProperties::saveData(TOStream &os) const { os.child("syncColorSettings") << (out.isColorSettingsSynced() ? 1 : 0); os.child("multimedia") << out.getMultimediaRendering(); + // Save render keys only if enabled and multimedia set to anything except + // None + if (out.getMultimediaRendering() && out.isRenderKeysOnly()) + os.child("renderKeysOnly") << (out.isRenderKeysOnly() ? 1 : 0); os.child("threadsIndex") << out.getThreadIndex(); os.child("maxTileSizeIndex") << out.getMaxTileSizeIndex(); os.child("subcameraPrev") << (out.isSubcameraPreview() ? 1 : 0); @@ -589,6 +593,10 @@ void TSceneProperties::loadData(TIStream &is, bool isLoadingProject) { int j; is >> j; out.setMultimediaRendering(j); + } else if (tagName == "renderKeysOnly") { + int renderKeysOnly; + is >> renderKeysOnly; + out.setRenderKeysOnly(renderKeysOnly == 1); } else if (tagName == "threadsIndex") { int j; is >> j;