Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Rendering components
Toshihiro Shimizu 890ddd
#include "toonz/multimediarenderer.h"
Toshihiro Shimizu 890ddd
#include "toonz/movierenderer.h"
Toshihiro Shimizu 890ddd
#include "trenderer.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Scene structures
Toshihiro Shimizu 890ddd
#include "toonz/toonzscene.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheet.h"
Toshihiro Shimizu 890ddd
#include "toonz/fxdag.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnfxset.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Fxs tree decomposition
Toshihiro Shimizu 890ddd
#include "toonz/scenefx.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnfx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Idle processing
Toshihiro Shimizu 890ddd
#include <qeventloop></qeventloop>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//  Local stuff
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
wstring removeSpaces(const wstring &str)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	wstring result;
Toshihiro Shimizu 890ddd
	wstring::size_type a = 0, b;
Toshihiro Shimizu 890ddd
	while ((b = str.find_first_of(L" ", a)) != wstring::npos) {
Toshihiro Shimizu 890ddd
		result += str.substr(a, b - a);
Toshihiro Shimizu 890ddd
		a = b + 1;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	result += str.substr(a, wstring::npos);
Toshihiro Shimizu 890ddd
	return result;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//    MultimediaRenderer::Imp   class
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class MultimediaRenderer::Imp
Toshihiro Shimizu 890ddd
	: public MovieRenderer::Listener,
Toshihiro Shimizu 890ddd
	  public TSmartObject
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	ToonzScene *m_scene;
Toshihiro Shimizu 890ddd
	TFilePath m_fp;
Toshihiro Shimizu 890ddd
	int m_threadCount;
Toshihiro Shimizu 890ddd
	bool m_cacheResults;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Output movie frames. May be remapped from rendered ones.
Toshihiro Shimizu 890ddd
	double m_xDpi, m_yDpi;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRenderSettings m_renderSettings;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	vector<multimediarenderer::listener *=""> m_listeners;</multimediarenderer::listener>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool m_precomputingEnabled;
Toshihiro Shimizu 890ddd
	bool m_canceled;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int m_currentFx;
Toshihiro Shimizu 890ddd
	set<double>::iterator m_currentFrame;</double>
Toshihiro Shimizu 890ddd
	TRenderer *m_currentTRenderer;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TFxSet m_fxsToRender;
Toshihiro Shimizu 890ddd
	set<double> m_framesToRender;</double>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QEventLoop m_eventLoop;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int m_multimediaMode;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	Imp(ToonzScene *scene,
Toshihiro Shimizu 890ddd
		const TFilePath &moviePath,
Toshihiro Shimizu 890ddd
		int multimediaMode,
Toshihiro Shimizu 890ddd
		int threadCount,
Toshihiro Shimizu 890ddd
		bool cacheResults);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	~Imp();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void scanSceneForRenderNodes();
Toshihiro Shimizu 890ddd
	void scanSceneForColumns();
Toshihiro Shimizu 890ddd
	void scanSceneForLayers();
Toshihiro Shimizu 890ddd
	bool scanColsRecursive(TFx *fx);
Toshihiro Shimizu 890ddd
	TColumnFx *searchColumn(TFxP fx);
Toshihiro Shimizu 890ddd
	TFxP addPostProcessing(TFxP fx, TFxP postProc);
Toshihiro Shimizu 890ddd
	void addPostProcessingRecursive(TFxP fx, TFxP postProc);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	void start();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	bool onFrameCompleted(int frame);
Toshihiro Shimizu 890ddd
	bool onFrameFailed(int frame, TException &e);
Toshihiro Shimizu 890ddd
	void onSequenceCompleted(const TFilePath &fp);
Toshihiro Shimizu 890ddd
	void onRenderCompleted();
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MultimediaRenderer::Imp::Imp(
Toshihiro Shimizu 890ddd
	ToonzScene *scene,
Toshihiro Shimizu 890ddd
	const TFilePath &moviePath,
Toshihiro Shimizu 890ddd
	int multimediaMode,
Toshihiro Shimizu 890ddd
	int threadCount,
Toshihiro Shimizu 890ddd
	bool cacheResults)
Toshihiro Shimizu 890ddd
	: m_scene(scene), m_fp(moviePath), m_threadCount(threadCount), m_cacheResults(cacheResults), m_xDpi(72), m_yDpi(72), m_renderSettings(), m_listeners(), m_precomputingEnabled(true), m_canceled(false), m_currentFx(0), m_currentFrame(), m_multimediaMode(multimediaMode)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Retrieve all fx nodes to be rendered in this process.
Toshihiro Shimizu 890ddd
	scanSceneForRenderNodes();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MultimediaRenderer::Imp::~Imp()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MultimediaRenderer::Imp::scanSceneForRenderNodes()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	switch (m_multimediaMode) {
Toshihiro Shimizu 890ddd
	case COLUMNS:
Toshihiro Shimizu 890ddd
		scanSceneForColumns();
Toshihiro Shimizu 890ddd
		CASE LAYERS : scanSceneForLayers();
Toshihiro Shimizu 890ddd
	DEFAULT:
Toshihiro Shimizu 890ddd
		assert(0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!Retrieve the first level of scene columns, climb their paths
Toshihiro Shimizu 890ddd
//!along unary fxs, and then build the scene fxs.
Toshihiro Shimizu 890ddd
void MultimediaRenderer::Imp::scanSceneForColumns()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Retrieve the terminal fxs (ie, fxs which are implicitly
Toshihiro Shimizu 890ddd
	//connected to the xsheet one)
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_scene->getXsheet();
Toshihiro Shimizu 890ddd
	TFxSet *fxs = xsh->getFxDag()->getTerminalFxs();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Launch the recursive column climber procedure for each
Toshihiro Shimizu 890ddd
	for (int i = 0; i < fxs->getFxCount(); ++i) {
Toshihiro Shimizu 890ddd
		TFx *fx = fxs->getFx(i);
Toshihiro Shimizu 890ddd
		if (!fx)
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		bool isItARenderFx = scanColsRecursive(fx);
Toshihiro Shimizu 890ddd
		if (isItARenderFx)
Toshihiro Shimizu 890ddd
			m_fxsToRender.addFx(fx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!Returns true if the passed fx is a valid column representant
Toshihiro Shimizu 890ddd
bool MultimediaRenderer::Imp::scanColsRecursive(TFx *fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Columns should return true - they are column representant
Toshihiro Shimizu 890ddd
	if (dynamic_cast<tcolumnfx *="">(fx))</tcolumnfx>
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Search columns in every port
Toshihiro Shimizu 890ddd
	bool isChildAnFxRepres;
Toshihiro Shimizu 890ddd
	for (int i = 0; i < fx->getInputPortCount(); ++i) {
Toshihiro Shimizu 890ddd
		TFx *childFx = fx->getInputPort(i)->getFx();
Toshihiro Shimizu 890ddd
		if (!childFx)
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		isChildAnFxRepres = scanColsRecursive(childFx);
Toshihiro Shimizu 890ddd
		if (isChildAnFxRepres && fx->getInputPortCount() > 1)
Toshihiro Shimizu 890ddd
			m_fxsToRender.addFx(childFx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (isChildAnFxRepres && fx->getInputPortCount() == 1)
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!Build the scene fx for each node below the xsheet one.
Toshihiro Shimizu 890ddd
//!Remember that left xsheet ports must not be expanded.
Toshihiro Shimizu 890ddd
void MultimediaRenderer::Imp::scanSceneForLayers()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Retrieve the terminal fxs (ie, fxs which are implicitly
Toshihiro Shimizu 890ddd
	//connected to the xsheet one)
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_scene->getXsheet();
Toshihiro Shimizu 890ddd
	TFxSet *fxs = xsh->getFxDag()->getTerminalFxs();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Examine all of them and - eventually - expand left xsheet
Toshihiro Shimizu 890ddd
	//ports (ie fx nodes who allow implicit overlaying)
Toshihiro Shimizu 890ddd
	for (int i = 0; i < fxs->getFxCount(); ++i) {
Toshihiro Shimizu 890ddd
		TFx *fx = fxs->getFx(i);
Toshihiro Shimizu 890ddd
		TFxPort *leftXSheetPort;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	retry:
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!fx)
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		leftXSheetPort = fx->getXsheetPort();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!leftXSheetPort) {
Toshihiro Shimizu 890ddd
			m_fxsToRender.addFx(fx);
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//If the leftXSheetPort is not connected, retry on port 0
Toshihiro Shimizu 890ddd
		if (leftXSheetPort->isConnected())
Toshihiro Shimizu 890ddd
			m_fxsToRender.addFx(fx);
Toshihiro Shimizu 890ddd
		else {
Toshihiro Shimizu 890ddd
			fx = fx->getInputPort(0)->getFx();
Toshihiro Shimizu 890ddd
			goto retry;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TColumnFx *MultimediaRenderer::Imp::searchColumn(TFxP fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Descend ports 0 until a TColumnFx is found. Then, output its number.
Toshihiro Shimizu 890ddd
	TFx *currFx = fx.getPointer();
Toshihiro Shimizu 890ddd
	TColumnFx *colFx = dynamic_cast<tcolumnfx *="">(currFx);</tcolumnfx>
Toshihiro Shimizu 890ddd
	while (!colFx) {
Toshihiro Shimizu 890ddd
		if (fx->getInputPortCount() <= 0)
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		currFx = currFx->getInputPort(0)->getFx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!currFx)
Toshihiro Shimizu 890ddd
			break;
Toshihiro Shimizu 890ddd
		colFx = dynamic_cast<tcolumnfx *="">(currFx);</tcolumnfx>
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return colFx;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFxP MultimediaRenderer::Imp::addPostProcessing(TFxP fx, TFxP postProc)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (dynamic_cast<txsheetfx *="">(postProc.getPointer()))</txsheetfx>
Toshihiro Shimizu 890ddd
		return fx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Clone the postProcessing tree and substitute recursively
Toshihiro Shimizu 890ddd
	postProc = postProc->clone(true);
Toshihiro Shimizu 890ddd
	addPostProcessingRecursive(fx, postProc);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return postProc;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MultimediaRenderer::Imp::addPostProcessingRecursive(TFxP fx, TFxP postProc)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!postProc)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i, count = postProc->getInputPortCount();
Toshihiro Shimizu 890ddd
	for (i = 0; i < count; ++i) {
Toshihiro Shimizu 890ddd
		TFxPort *port = postProc->getInputPort(i);
Toshihiro Shimizu 890ddd
		TFx *childFx = port->getFx();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (dynamic_cast<txsheetfx *="">(childFx))</txsheetfx>
Toshihiro Shimizu 890ddd
			port->setFx(fx.getPointer());
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			addPostProcessingRecursive(fx, childFx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MultimediaRenderer::Imp::start()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Retrieve some useful infos
Toshihiro Shimizu 890ddd
	double stretchTo = m_renderSettings.m_timeStretchTo;
Toshihiro Shimizu 890ddd
	double stretchFrom = m_renderSettings.m_timeStretchFrom;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	double timeStretchFactor = stretchFrom / stretchTo;
Toshihiro Shimizu 890ddd
	bool fieldRendering = m_renderSettings.m_fieldPrevalence != TRenderSettings::NoField;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	wstring modeStr;
Toshihiro Shimizu 890ddd
	switch (m_multimediaMode) {
Toshihiro Shimizu 890ddd
	case COLUMNS:
Toshihiro Shimizu 890ddd
		modeStr = L"_col";
Toshihiro Shimizu 890ddd
		CASE LAYERS : modeStr = L"_lay";
Toshihiro Shimizu 890ddd
	DEFAULT:
Toshihiro Shimizu 890ddd
		assert(0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Build the post processing fxs tree
Toshihiro Shimizu 890ddd
	std::vector<tfxp> postFxs(m_framesToRender.size());</tfxp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::set<double>::iterator jt;</double>
Toshihiro Shimizu 890ddd
	int j;
Toshihiro Shimizu 890ddd
	for (j = 0, jt = m_framesToRender.begin(); jt != m_framesToRender.end(); ++j, ++jt)
Toshihiro Shimizu 890ddd
		postFxs[j] = buildPostSceneFx(m_scene, *jt, m_renderSettings.m_shrinkX, false); // Adds camera and camera dpi transforms
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//For each node to be rendered
Toshihiro Shimizu 890ddd
	int i, count = m_fxsToRender.getFxCount();
Toshihiro Shimizu 890ddd
	for (i = 0; i < count; ++i) {
Toshihiro Shimizu 890ddd
		//In case the process has been canceled, return
Toshihiro Shimizu 890ddd
		if (m_canceled)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Then, build the scene fx for each frame to be rendered
Toshihiro Shimizu 890ddd
		std::vector<std::pair<double, tfxpair="">> pairsToBeRendered;</std::pair<double,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//NOTE: The above pairs should not be directly added to a previously declared movierenderer,
Toshihiro Shimizu 890ddd
		//since an output level would be created even before knowing if any cell to be rendered is
Toshihiro Shimizu 890ddd
		//actually available.
Toshihiro Shimizu 890ddd
		const BSFX_Transforms_Enum transforms =   // Do NOT add camera and
Toshihiro Shimizu 890ddd
			BSFX_Transforms_Enum(BSFX_COLUMN_TR); // camera dpi transforms
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int j;
Toshihiro Shimizu 890ddd
		for (j = 0, jt = m_framesToRender.begin(); jt != m_framesToRender.end(); ++j, ++jt) {
Toshihiro Shimizu 890ddd
			TFxPair fx;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (m_renderSettings.m_stereoscopic)
Toshihiro Shimizu 890ddd
				m_scene->shiftCameraX(-m_renderSettings.m_stereoscopicShift / 2);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			fx.m_frameA = buildSceneFx(m_scene, *jt, 0, m_fxsToRender.getFx(i),
Toshihiro Shimizu 890ddd
									   transforms);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (m_renderSettings.m_stereoscopic) {
Toshihiro Shimizu 890ddd
				m_scene->shiftCameraX(m_renderSettings.m_stereoscopicShift);
Toshihiro Shimizu 890ddd
				fx.m_frameB = buildSceneFx(m_scene, *jt, 0, m_fxsToRender.getFx(i),
Toshihiro Shimizu 890ddd
										   transforms);
Toshihiro Shimizu 890ddd
				m_scene->shiftCameraX(-m_renderSettings.m_stereoscopicShift / 2);
Toshihiro Shimizu 890ddd
			} else if (fieldRendering)
Toshihiro Shimizu 890ddd
				fx.m_frameB = buildSceneFx(m_scene, *jt + 0.5 * timeStretchFactor, 0,
Toshihiro Shimizu 890ddd
										   m_fxsToRender.getFx(i), transforms);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				fx.m_frameB = TRasterFxP();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//Substitute with the post-process...
Toshihiro Shimizu 890ddd
			if (fx.m_frameA)
Toshihiro Shimizu 890ddd
				fx.m_frameA = addPostProcessing(fx.m_frameA, postFxs[j]);
Toshihiro Shimizu 890ddd
			if (fx.m_frameB)
Toshihiro Shimizu 890ddd
				fx.m_frameB = addPostProcessing(fx.m_frameB, postFxs[j]);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (fx.m_frameA) //Could be 0, if the corresponding cell is void / not rendered
Toshihiro Shimizu 890ddd
				pairsToBeRendered.push_back(std::pair<double, tfxpair="">(*jt, fx));</double,>
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (pairsToBeRendered.size() == 0)
Toshihiro Shimizu 890ddd
			continue; //Could be, if no cell for this column was in the frame range.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Build the output name
Toshihiro Shimizu 890ddd
		TColumnFx *colFx = searchColumn(m_fxsToRender.getFx(i));
Toshihiro Shimizu 890ddd
		TFx *currFx = m_fxsToRender.getFx(i);
Toshihiro Shimizu 890ddd
		assert(colFx);
Toshihiro Shimizu 890ddd
		if (!colFx)
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		int columnIndex = colFx->getColumnIndex();
Toshihiro Shimizu 890ddd
		wstring columnName(colFx->getColumnName());
Toshihiro Shimizu 890ddd
		wstring columnId(colFx->getColumnId());
Toshihiro Shimizu 890ddd
		wstring fxName(currFx->getName());
Toshihiro Shimizu 890ddd
		wstring fxNameNoSpaces(::removeSpaces(fxName));
Toshihiro Shimizu 890ddd
		wstring fxId(currFx->getFxId());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		wstring fpName = m_fp.getWideName() +
Toshihiro Shimizu 890ddd
						 L"_" + columnName + (columnId == columnName ? L"" : L"(" + columnId + L")") +
Toshihiro Shimizu 890ddd
						 (fxId.empty() ? L"" : L"_" + fxName + (fxId == fxNameNoSpaces ? L"" : L"(" + fxId + L")"));
Toshihiro Shimizu 890ddd
		//+ modeStr + toWideString(columnIndex+1);
Toshihiro Shimizu 890ddd
		TFilePath movieFp(m_fp.withName(fpName));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Initialize a MovieRenderer with our infos
Toshihiro Shimizu 890ddd
		MovieRenderer movieRenderer(m_scene, movieFp, m_threadCount, false);
Toshihiro Shimizu 890ddd
		movieRenderer.setRenderSettings(m_renderSettings);
Toshihiro Shimizu 890ddd
		movieRenderer.setDpi(m_xDpi, m_yDpi);
Toshihiro Shimizu 890ddd
		movieRenderer.enablePrecomputing(m_precomputingEnabled);
Toshihiro Shimizu 890ddd
		movieRenderer.addListener(this);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		for (unsigned int j = 0; j < pairsToBeRendered.size(); ++j) {
Toshihiro Shimizu 890ddd
			std::pair<double, tfxpair=""> ¤tPair = pairsToBeRendered[j];</double,>
Toshihiro Shimizu 890ddd
			movieRenderer.addFrame(currentPair.first, currentPair.second);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Finally, start rendering currently initialized MovieRenderer.
Toshihiro Shimizu 890ddd
		m_currentFx = i;
Toshihiro Shimizu 890ddd
		m_currentFrame = m_framesToRender.begin();
Toshihiro Shimizu 890ddd
		m_currentTRenderer = movieRenderer.getTRenderer();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		movieRenderer.start();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//I don't recall Toonz currently supports different, simultaneous rendering processes.
Toshihiro Shimizu 890ddd
		//However, one rendering process is supposed to be exhausting the machine's resources
Toshihiro Shimizu 890ddd
		//on its own - so, we'll just set up an idle (but GUI-reactive) loop here.
Toshihiro Shimizu 890ddd
		//It will quit looping whenever the "onSequenceCompleted" notification gets called.
Toshihiro Shimizu 890ddd
		m_eventLoop.exec();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//---------------------- Loops here --------------------------
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Lastly, inform everyone that rendering stopped
Toshihiro Shimizu 890ddd
	onRenderCompleted();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool MultimediaRenderer::Imp::onFrameCompleted(int frame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Inform all listeners
Toshihiro Shimizu 890ddd
	for (unsigned int i = 0; i < m_listeners.size(); ++i)
Toshihiro Shimizu 890ddd
		m_listeners[i]->onFrameCompleted(*m_currentFrame, m_currentFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_currentFrame++;
Toshihiro Shimizu 890ddd
	return !m_canceled;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool MultimediaRenderer::Imp::onFrameFailed(int frame, TException &e)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Inform all listeners
Toshihiro Shimizu 890ddd
	for (unsigned int i = 0; i < m_listeners.size(); ++i)
Toshihiro Shimizu 890ddd
		m_listeners[i]->onFrameFailed(*m_currentFrame, m_currentFx, e);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_currentFrame++;
Toshihiro Shimizu 890ddd
	return !m_canceled;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MultimediaRenderer::Imp::onSequenceCompleted(const TFilePath &fp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Inform all listeners
Toshihiro Shimizu 890ddd
	m_currentTRenderer = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (unsigned int i = 0; i < m_listeners.size(); ++i)
Toshihiro Shimizu 890ddd
		m_listeners[i]->onSequenceCompleted(m_currentFx);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_eventLoop.quit();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MultimediaRenderer::Imp::onRenderCompleted()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	for (unsigned int i = 0; i < m_listeners.size(); ++i)
Toshihiro Shimizu 890ddd
		m_listeners[i]->onRenderCompleted();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=============================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//    MultimediaRenderer   class
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//---------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MultimediaRenderer::MultimediaRenderer(
Toshihiro Shimizu 890ddd
	ToonzScene *scene, const TFilePath &moviePath, int multimediaMode,
Toshihiro Shimizu 890ddd
	int threadCount, bool cacheResults)
Toshihiro Shimizu 890ddd
	: m_imp(new Imp(scene, moviePath, multimediaMode, threadCount, cacheResults))
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->addRef();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MultimediaRenderer::~MultimediaRenderer()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->release();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
const TFilePath &MultimediaRenderer::getFilePath()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_fp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int MultimediaRenderer::getFrameCount()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_framesToRender.size();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int MultimediaRenderer::getColumnsCount()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_fxsToRender.getFxCount();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
int MultimediaRenderer::getMultimediaMode() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_multimediaMode;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MultimediaRenderer::setRenderSettings(const TRenderSettings &renderSettings)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//assert(m_imp->m_framesOnRendering.empty());
Toshihiro Shimizu 890ddd
	m_imp->m_renderSettings = renderSettings;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MultimediaRenderer::setDpi(double xDpi, double yDpi)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_xDpi = xDpi;
Toshihiro Shimizu 890ddd
	m_imp->m_yDpi = yDpi;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MultimediaRenderer::addListener(Listener *listener)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_listeners.push_back(listener);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MultimediaRenderer::addFrame(double frame)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_framesToRender.insert(frame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MultimediaRenderer::enablePrecomputing(bool on)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_precomputingEnabled = on;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//!\b NOTE: Such render may vary from time to time, and even be 0 if no renderer is currently
Toshihiro Shimizu 890ddd
//!active, for example due to preprocessing states.
Toshihiro Shimizu 890ddd
TRenderer *MultimediaRenderer::getTRenderer()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_currentTRenderer;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool MultimediaRenderer::isPrecomputingEnabled() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_imp->m_precomputingEnabled;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MultimediaRenderer::start()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->start();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void MultimediaRenderer::onCanceled()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_imp->m_canceled = true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
bool MultimediaRenderer::done() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
*/