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