Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tmacrofx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tparamcontainer.h"
Toshihiro Shimizu 890ddd
#include "tfxattributes.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tstream.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class MatchesFx {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  MatchesFx(const TFxP &fx) : m_fx(fx) {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool operator()(const TFxP &fx) {
Shinya Kitaoka 120a6e
    return m_fx.getPointer() == fx.getPointer();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TFxP m_fx;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void pushParents(const TFxP &root, std::vector<tfxp> &fxs,</tfxp>
Shinya Kitaoka 120a6e
                 const std::vector<tfxp> &selectedFxs) {</tfxp>
Shinya Kitaoka 120a6e
  int i, count = root->getInputPortCount();
Shinya Kitaoka 120a6e
  if (count == 0) {
Shinya Kitaoka 120a6e
    std::vector<tfxp>::const_iterator found =</tfxp>
Shinya Kitaoka 120a6e
        std::find_if(fxs.begin(), fxs.end(), MatchesFx(root));
Shinya Kitaoka 120a6e
    if (found == fxs.end()) fxs.push_back(root);
Shinya Kitaoka 120a6e
    return;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (i = 0; i < count; i++) {
Shinya Kitaoka 120a6e
    TFxP inutFx = root->getInputPort(i)->getFx();
Shinya Kitaoka 120a6e
    std::vector<tfxp>::const_iterator found =</tfxp>
Shinya Kitaoka 120a6e
        std::find_if(selectedFxs.begin(), selectedFxs.end(), MatchesFx(inutFx));
Shinya Kitaoka 120a6e
    if (found != selectedFxs.end()) pushParents(inutFx, fxs, selectedFxs);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  std::vector<tfxp>::const_iterator found =</tfxp>
Shinya Kitaoka 120a6e
      std::find_if(fxs.begin(), fxs.end(), MatchesFx(root));
Shinya Kitaoka 120a6e
  if (found == fxs.end()) fxs.push_back(root);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::vector<tfxp> sortFxs(const std::vector<tfxp> &fxs) {</tfxp></tfxp>
Shinya Kitaoka 120a6e
  std::vector<tfxp> app;</tfxp>
Shinya Kitaoka 120a6e
  std::vector<tfxp> roots;</tfxp>
Shinya Kitaoka 120a6e
  // find fxs that could be in back of the vector.
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < (int)fxs.size(); i++) {
Shinya Kitaoka 120a6e
    TFxP fx = fxs[i];
Shinya Kitaoka 120a6e
    int j, count = (int)fx->getOutputConnectionCount();
Shinya Kitaoka 120a6e
    if (count == 0) {
Shinya Kitaoka 120a6e
      roots.push_back(fx);
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    for (j = 0; j < count; j++) {
Shinya Kitaoka 120a6e
      TFxP connectedFx = fx->getOutputConnection(j)->getOwnerFx();
Shinya Kitaoka 120a6e
      std::vector<tfxp>::const_iterator found =</tfxp>
Shinya Kitaoka 120a6e
          std::find_if(fxs.begin(), fxs.end(), MatchesFx(connectedFx));
Shinya Kitaoka 120a6e
      if (found == fxs.end()) {
Shinya Kitaoka 120a6e
        roots.push_back(fx);
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  for (i = 0; i < (int)roots.size(); i++) pushParents(roots[i], app, fxs);
Shinya Kitaoka 120a6e
  assert(fxs.size() == app.size());
Shinya Kitaoka 120a6e
  return app;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// raccoglie tutti i parametri dai vari TFx e li assegna anche alla macro
Shinya Kitaoka 120a6e
void collectParams(TMacroFx *macroFx) {
Shinya Kitaoka 120a6e
  int k;
Shinya Kitaoka 120a6e
  for (k = 0; k < (int)macroFx->m_fxs.size(); k++) {
Shinya Kitaoka 120a6e
    TFxP fx = macroFx->m_fxs[k];
Shinya Kitaoka 120a6e
    int j;
Shinya Kitaoka 120a6e
    for (j = 0; j < fx->getParams()->getParamCount(); j++)
Shinya Kitaoka 120a6e
      macroFx->getParams()->add(fx->getParams()->getParamVar(j)->clone());
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // anonymous namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TMacroFx::analyze(const std::vector<tfxp> &fxs, TFxP &root,</tfxp>
Shinya Kitaoka 120a6e
                       std::vector<tfxp> &roots, std::vector<tfxp> &leafs) {</tfxp></tfxp>
Shinya Kitaoka 120a6e
  if (fxs.size() == 1)
Shinya Kitaoka 120a6e
    return false;
Shinya Kitaoka 120a6e
  else {
Shinya Kitaoka 120a6e
    leafs.clear();
Shinya Kitaoka 120a6e
    roots.clear();
Shinya Kitaoka 120a6e
    std::vector<tfxp>::const_iterator it = fxs.begin();</tfxp>
Shinya Kitaoka 120a6e
    for (; it != fxs.end(); ++it) {
Shinya Kitaoka 120a6e
      TFxP fx                      = *it;
Shinya Kitaoka 120a6e
      int inputInternalConnection  = 0;
Shinya Kitaoka 120a6e
      int inputExternalConnection  = 0;
Shinya Kitaoka 120a6e
      int outputInternalConnection = 0;
Shinya Kitaoka 120a6e
      int outputExternalConnection = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int i;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // calcola se ci sono connessioni in input dall'esterno
Shinya Kitaoka 120a6e
      // verso l'interno e/o internamente a orderedFxs
Shinya Kitaoka 120a6e
      int inputPortCount = fx->getInputPortCount();
Shinya Kitaoka 120a6e
      for (i = 0; i < inputPortCount; ++i) {
Shinya Kitaoka 120a6e
        TFxPort *inputPort = fx->getInputPort(i);
Shinya Kitaoka 120a6e
        TFx *inputPortFx   = inputPort->getFx();
Shinya Kitaoka 120a6e
        if (inputPortFx) {
Shinya Kitaoka 120a6e
          if (std::find_if(fxs.begin(), fxs.end(), MatchesFx(inputPortFx)) !=
Shinya Kitaoka 120a6e
              fxs.end())
Shinya Kitaoka 120a6e
            ++inputInternalConnection;
Shinya Kitaoka 120a6e
          else
Shinya Kitaoka 120a6e
            ++inputExternalConnection;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // calcola se ci sono connessioni in output dall'interno
Shinya Kitaoka 120a6e
      // verso l'esterno e/o internamente a orderedFxs
Shinya Kitaoka 120a6e
      int outputPortCount = fx->getOutputConnectionCount();
Shinya Kitaoka 120a6e
      for (i = 0; i < outputPortCount; ++i) {
Shinya Kitaoka 120a6e
        TFxPort *outputPort = fx->getOutputConnection(i);
Shinya Kitaoka 120a6e
        TFx *outputFx       = outputPort->getOwnerFx();
Shinya Kitaoka 120a6e
        if (outputFx) {
Shinya Kitaoka 120a6e
          if (std::find_if(fxs.begin(), fxs.end(), MatchesFx(outputFx)) !=
Shinya Kitaoka 120a6e
              fxs.end())
Shinya Kitaoka 120a6e
            ++outputInternalConnection;
Shinya Kitaoka 120a6e
          else
Shinya Kitaoka 120a6e
            ++outputExternalConnection;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // se fx e' una radice
Shinya Kitaoka 120a6e
      if ((outputExternalConnection > 0) ||
Shinya Kitaoka 120a6e
          (outputExternalConnection == 0 && outputInternalConnection == 0)) {
Shinya Kitaoka 120a6e
        root = fx;
Shinya Kitaoka 120a6e
        roots.push_back(fx);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // se fx e' una foglia
Shinya Kitaoka 120a6e
      if (inputExternalConnection > 0 || fx->getInputPortCount() == 0 ||
Shinya Kitaoka 120a6e
          (inputExternalConnection == 0 &&
Shinya Kitaoka 120a6e
           inputInternalConnection < fx->getInputPortCount())) {
Shinya Kitaoka 120a6e
        leafs.push_back(fx);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (roots.size() != 1)
Shinya Kitaoka 120a6e
      return false;
Shinya Kitaoka 120a6e
    else {
Shinya Kitaoka 120a6e
      if (leafs.size() == 0) return false;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    return true;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TMacroFx::analyze(const std::vector<tfxp> &fxs) {</tfxp>
Shinya Kitaoka 120a6e
  TFxP root = 0;
Shinya Kitaoka 120a6e
  std::vector<tfxp> leafs;</tfxp>
Shinya Kitaoka 120a6e
  std::vector<tfxp> roots;</tfxp>
Shinya Kitaoka 120a6e
  return analyze(fxs, root, roots, leafs);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TMacroFx::isaLeaf(TFx *fx) const {
Shinya Kitaoka 120a6e
  int count = fx->getInputPortCount();
Shinya Kitaoka 120a6e
  if (count == 0) return true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int i = 0; i < count; ++i) {
Shinya Kitaoka 120a6e
    TFxPort *port = fx->getInputPort(i);
Shinya Kitaoka 120a6e
    TFx *inputFx  = port->getFx();
Shinya Kitaoka 120a6e
    if (inputFx) {
Shinya Kitaoka 120a6e
      if (std::find_if(m_fxs.begin(), m_fxs.end(), MatchesFx(inputFx)) ==
Shinya Kitaoka 120a6e
          m_fxs.end()) {
Shinya Kitaoka 120a6e
        // il nodo di input non appartiene al macroFx
Shinya Kitaoka 120a6e
        return true;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else {
Shinya Kitaoka 120a6e
      // la porta di input non e' connessa
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // tutte le porte di input sono connesse verso nodi appartenenti al macroFx
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TMacroFx::TMacroFx() : m_isEditing(false) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TMacroFx::~TMacroFx() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFx *TMacroFx::clone(bool recursive) const {
Shinya Kitaoka 120a6e
  int n = m_fxs.size();
Shinya Kitaoka 120a6e
  std::vector<tfxp> clones(n);</tfxp>
Shinya Kitaoka 120a6e
  std::map<tfx *,="" int=""> table;</tfx>
Shinya Kitaoka 120a6e
  std::map<tfx *,="" int="">::iterator it;</tfx>
Shinya Kitaoka 120a6e
  int i, rootIndex = -1;
Shinya Kitaoka 120a6e
  // nodi
Shinya Kitaoka 120a6e
  for (i = 0; i < n; ++i) {
Shinya Kitaoka 120a6e
    TFx *fx = m_fxs[i].getPointer();
Shinya Kitaoka 120a6e
    assert(fx);
Shinya Kitaoka 120a6e
    clones[i] = fx->clone(false);
Shinya Kitaoka 120a6e
    assert(table.count(fx) == 0);
Shinya Kitaoka 120a6e
    table[fx]                                = i;
Shinya Kitaoka 120a6e
    if (fx == m_root.getPointer()) rootIndex = i;
Shinya Kitaoka 120a6e
    TFx *linkedFx                            = fx->getLinkedFx();
Shinya Kitaoka 120a6e
    if (linkedFx && table.find(linkedFx) != table.end())
Shinya Kitaoka 120a6e
      clones[i]->linkParams(clones[table[linkedFx]].getPointer());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  assert(rootIndex >= 0);
Shinya Kitaoka 120a6e
  // connessioni
Shinya Kitaoka 120a6e
  for (i = 0; i < n; i++) {
Shinya Kitaoka 120a6e
    TFx *fx = m_fxs[i].getPointer();
Shinya Kitaoka 120a6e
    for (int j = 0; j < fx->getInputPortCount(); j++) {
Shinya Kitaoka 120a6e
      TFxPort *port = fx->getInputPort(j);
Shinya Kitaoka 120a6e
      TFx *inputFx  = port->getFx();
Shinya Kitaoka 120a6e
      if (!inputFx) continue;
Shinya Kitaoka 120a6e
      it = table.find(inputFx);
Shinya Kitaoka 120a6e
      if (it == table.end()) {
Shinya Kitaoka 120a6e
        // il j-esimo input di fx e' esterno alla macro
Shinya Kitaoka 120a6e
        if (recursive)
Shinya Kitaoka 120a6e
          clones[i]->connect(fx->getInputPortName(j), inputFx->clone(true));
Shinya Kitaoka 120a6e
      } else {
Shinya Kitaoka 120a6e
        // il j-esimo input di fx e' interno alla macro
Shinya Kitaoka 120a6e
        clones[i]->connect(fx->getInputPortName(j),
Shinya Kitaoka 120a6e
                           clones[it->second].getPointer());
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // TFx *rootClone =
Shinya Kitaoka 120a6e
  //  const_cast<tmacrofx*>(this)-></tmacrofx*>
Shinya Kitaoka 120a6e
  //  clone(m_root.getPointer(), recursive, visited, clones);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TMacroFx *clone = TMacroFx::create(clones);
Shinya Kitaoka 120a6e
  clone->setName(getName());
Shinya Kitaoka 120a6e
  clone->setFxId(getFxId());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Copy the index of the passive cache manager.
Shinya Kitaoka 120a6e
  clone->getAttributes()->passiveCacheDataIdx() =
Shinya Kitaoka 120a6e
      getAttributes()->passiveCacheDataIdx();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  assert(clone->getRoot() == clones[rootIndex].getPointer());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return clone;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TMacroFx::doGetBBox(double frame, TRectD &bBox,
Shinya Kitaoka 120a6e
                         const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  return m_root->doGetBBox(frame, bBox, info);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TMacroFx::doDryCompute(TRectD &rect, double frame,
Shinya Kitaoka 120a6e
                            const TRenderSettings &info) {
Shinya Kitaoka 120a6e
  assert(m_root);
Shinya Kitaoka 120a6e
  m_root->dryCompute(rect, frame, info);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TMacroFx::doCompute(TTile &tile, double frame, const TRenderSettings &ri) {
Shinya Kitaoka 120a6e
  assert(m_root);
Shinya Kitaoka 120a6e
  m_root->compute(tile, frame, ri);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFxTimeRegion TMacroFx::getTimeRegion() const {
Shinya Kitaoka 120a6e
  return m_root->getTimeRegion();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TMacroFx::getPluginId() const { return "Base"; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TMacroFx::setRoot(TFx *root) {
Shinya Kitaoka 120a6e
  m_root = root;
Shinya Kitaoka 120a6e
  // TFx::m_imp->m_outputPort = root->m_imp->m_outputPort;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFx *TMacroFx::getRoot() const { return m_root.getPointer(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFx *TMacroFx::getFxById(const std::wstring &id) const {
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < (int)m_fxs.size(); i++) {
Shinya Kitaoka 120a6e
    TFx *fx = m_fxs[i].getPointer();
Shinya Kitaoka 120a6e
    if (fx->getFxId() == id) return fx;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
const std::vector<tfxp> &TMacroFx::getFxs() const { return m_fxs; }</tfxp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TMacroFx::getMacroFxType() const {
Shinya Kitaoka 120a6e
  std::string name = getFxType() + "(";
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)m_fxs.size(); i++) {
Shinya Kitaoka 120a6e
    if (i > 0) name += ",";
Shinya Kitaoka 120a6e
    if (TMacroFx *childMacro = dynamic_cast<tmacrofx *="">(m_fxs[i].getPointer()))</tmacrofx>
Shinya Kitaoka 120a6e
      name += childMacro->getMacroFxType();
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      name += m_fxs[i]->getFxType();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return name + ")";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TMacroFx *TMacroFx::create(const std::vector<tfxp> &fxs) {</tfxp>
Shinya Kitaoka 120a6e
  std::vector<tfxp> leafs;</tfxp>
Shinya Kitaoka 120a6e
  std::vector<tfxp> roots;</tfxp>
Shinya Kitaoka 120a6e
  TFxP root = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<tfxp> orederedFxs = sortFxs(fxs);</tfxp>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // verifica che gli effetti selezionati siano idonei ad essere raccolti
Shinya Kitaoka 120a6e
  // in una macro. Ci deve essere un solo nodo terminale
Shinya Kitaoka 120a6e
  // (roots.size()==1, roots[0] == root) e uno o piu' nodi di ingresso
Shinya Kitaoka 120a6e
  // (assert leafs.size()>0)
Shinya Kitaoka 120a6e
  if (!analyze(orederedFxs, root, roots, leafs)) return 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // -----------------------------
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TMacroFx *macroFx = new TMacroFx;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // tutti i nodi vengono spostati (e non copiati) nella macro stessa
Shinya Kitaoka 120a6e
  std::vector<tfxp>::const_iterator it = orederedFxs.begin();</tfxp>
Shinya Kitaoka 120a6e
  for (; it != orederedFxs.end(); ++it) macroFx->m_fxs.push_back(*it);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // i nodi di ingresso vengono messi in collegamento con le
Shinya Kitaoka 120a6e
  // porte di ingresso della macro
Shinya Kitaoka 120a6e
  for (int i = 0; i < (int)leafs.size(); i++) {
Shinya Kitaoka 120a6e
    TFxP fx   = leafs[i];
Shinya Kitaoka 120a6e
    int k     = 0;
Shinya Kitaoka 120a6e
    int count = fx->getInputPortCount();
Shinya Kitaoka 120a6e
    for (; k < count; k++) {
Shinya Kitaoka 120a6e
      TFxPort *port        = fx->getInputPort(k);
Shinya Kitaoka 120a6e
      std::string portName = fx->getInputPortName(k);
Shinya Kitaoka 120a6e
      std::string fxId     = ::to_string(fx->getFxId());
Shinya Kitaoka 120a6e
      portName +=
Shinya Kitaoka 120a6e
          "_" + std::to_string(macroFx->getInputPortCount()) + "_" + fxId;
Shinya Kitaoka 120a6e
      TFx *portFx = port->getFx();
Shinya Kitaoka 120a6e
      if (portFx) {
Shinya Kitaoka 120a6e
        // se la porta k-esima del nodo di ingresso i-esimo e' collegata
Shinya Kitaoka 120a6e
        // ad un effetto, la porta viene inserita solo se l'effetto non fa
Shinya Kitaoka 120a6e
        // gia' parte della macro
Shinya Kitaoka 120a6e
        if (std::find_if(orederedFxs.begin(), orederedFxs.end(),
Shinya Kitaoka 120a6e
                         MatchesFx(portFx)) == orederedFxs.end())
Shinya Kitaoka 120a6e
          macroFx->addInputPort(portName, *port);
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        macroFx->addInputPort(portName, *port);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // le porte di uscita di root diventano le porte di uscita della macro
Shinya Kitaoka 120a6e
  int count = root->getOutputConnectionCount();
Shinya Kitaoka 120a6e
  int k     = count - 1;
Shinya Kitaoka 120a6e
  for (; k >= 0; --k) {
Shinya Kitaoka 120a6e
    TFxPort *port = root->getOutputConnection(k);
Shinya Kitaoka 120a6e
    port->setFx(macroFx);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  macroFx->setRoot(root.getPointer());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // tutti i parametri delle funzioni figlie diventano parametri della macro
Shinya Kitaoka 120a6e
  collectParams(macroFx);
Shinya Kitaoka 120a6e
  return macroFx;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TMacroFx::canHandle(const TRenderSettings &info, double frame) {
Shinya Kitaoka 120a6e
  return m_root->canHandle(info, frame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TMacroFx::getAlias(double frame,
Shinya Kitaoka 120a6e
                               const TRenderSettings &info) const {
Shinya Kitaoka 120a6e
  std::string alias = getFxType();
Shinya Kitaoka 120a6e
  alias += "[";
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // alias degli effetti connessi alle porte di input separati da virgole
Shinya Kitaoka 120a6e
  // una porta non connessa da luogo a un alias vuoto (stringa vuota)
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 0; i < getInputPortCount(); i++) {
Shinya Kitaoka 120a6e
    TFxPort *port = getInputPort(i);
Shinya Kitaoka 120a6e
    if (port->isConnected()) {
Shinya Kitaoka 120a6e
      TRasterFxP ifx = port->getFx();
Shinya Kitaoka 120a6e
      assert(ifx);
Shinya Kitaoka 120a6e
      alias += ifx->getAlias(frame, info);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    alias += ",";
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // alias dei valori dei parametri dell'effetto al frame dato
Shinya Kitaoka 120a6e
  for (int j = 0; j < (int)m_fxs.size(); j++) {
Shinya Kitaoka 120a6e
    alias += (j == 0) ? "(" : ",(";
Shinya Kitaoka 120a6e
    for (i = 0; i < m_fxs[j]->getParams()->getParamCount(); i++) {
Shinya Kitaoka 120a6e
      if (i > 0) alias += ",";
Shinya Kitaoka 120a6e
      TParam *param = m_fxs[j]->getParams()->getParam(i);
Shinya Kitaoka 120a6e
      alias += param->getName() + "=" + param->getValueAlias(frame, 2);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    alias += ")";
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  alias += "]";
Shinya Kitaoka 120a6e
  return alias;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TMacroFx::compatibilityTranslatePort(int major, int minor,
Shinya Kitaoka 120a6e
                                          std::string &portName) {
Shinya Kitaoka 120a6e
  // Reroute translation to the actual fx associated to the port
Shinya Kitaoka 120a6e
  const std::string &fxId =
Shinya Kitaoka 120a6e
      portName.substr(portName.find_last_of('_') + 1, std::string::npos);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (TFx *fx = getFxById(::to_wstring(fxId))) {
Shinya Kitaoka 120a6e
    size_t opnEnd = portName.find_first_of('_');
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    std::string originalPortName = portName.substr(0, opnEnd);
Shinya Kitaoka 120a6e
    fx->compatibilityTranslatePort(major, minor, originalPortName);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    portName.replace(0, opnEnd, originalPortName);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Seems that at a certain point, the port name got extended...
Shinya Kitaoka 120a6e
  if (VersionNumber(major, minor) == VersionNumber(1, 16)) {
Shinya Kitaoka 120a6e
    for (int i = 0; i < getInputPortCount(); ++i) {
Shinya Kitaoka 120a6e
      const std::string &name = getInputPortName(i);
Shinya Kitaoka 120a6e
      if (name.find(portName) != std::string::npos) {
Shinya Kitaoka 120a6e
        portName = name;
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TMacroFx::loadData(TIStream &is) {
Shinya Kitaoka 120a6e
  VersionNumber tnzVersion = is.getVersion();
Shinya Kitaoka 120a6e
  std::string tagName;
Shinya Kitaoka 120a6e
  while (is.openChild(tagName)) {
Shinya Kitaoka 120a6e
    if (tagName == "root") {
Shinya Kitaoka 120a6e
      TPersist *p = 0;
Shinya Kitaoka 120a6e
      is >> p;
Shinya Kitaoka 120a6e
      m_root = dynamic_cast<tfx *="">(p);</tfx>
Shinya Kitaoka 120a6e
    } else if (tagName == "nodes") {
Shinya Kitaoka 120a6e
      while (!is.eos()) {
Shinya Kitaoka 120a6e
        TPersist *p = 0;
Shinya Kitaoka 120a6e
        is >> p;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        // NOTE: In current implementation p is sharedly owned by is - it's
Shinya Kitaoka 120a6e
        // automatically
Shinya Kitaoka 120a6e
        //       released upon stream destruction if the below assignment fails
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (TFx *fx = dynamic_cast<tfx *="">(p)) {</tfx>
Shinya Kitaoka 120a6e
          m_fxs.push_back(fx);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else if (tagName == "ports") {
Shinya Kitaoka 120a6e
      int i = 0;
Shinya Kitaoka 120a6e
      while (is.matchTag(tagName)) {
Shinya Kitaoka 120a6e
        if (tagName == "port") {
Shinya Kitaoka 120a6e
          std::string name = is.getTagAttribute("name");
Shinya Kitaoka 120a6e
          if (tnzVersion < VersionNumber(1, 16) && name != "") {
Shinya Kitaoka 120a6e
            TRasterFxPort *port = new TRasterFxPort();
Shinya Kitaoka 120a6e
            addInputPort(name, *port);
Shinya Kitaoka 120a6e
          } else {
Shinya Kitaoka 120a6e
            name = is.getTagAttribute("name_inFx");
Shinya Kitaoka 120a6e
            if (tnzVersion < VersionNumber(1, 17) &&
Shinya Kitaoka 120a6e
                tnzVersion != VersionNumber(0, 0))
Shinya Kitaoka 120a6e
              name.insert(name.find("_"), "_" + std::to_string(i));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
            compatibilityTranslatePort(tnzVersion.first, tnzVersion.second,
Shinya Kitaoka 120a6e
                                       name);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
            std::string inPortName = name;
Shinya Kitaoka 120a6e
            inPortName.erase(inPortName.find("_"), inPortName.size() - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
            std::string inFxId = name;
Shinya Kitaoka 120a6e
            inFxId.erase(0, inFxId.find_last_of("_") + 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
            for (int i = 0; i < (int)m_fxs.size(); i++) {
Shinya Kitaoka 120a6e
              std::wstring fxId = m_fxs[i]->getFxId();
Shinya Kitaoka 120a6e
              if (fxId == ::to_wstring(inFxId)) {
Shinya Kitaoka 120a6e
                if (TFxPort *port = m_fxs[i]->getInputPort(inPortName))
Shinya Kitaoka 120a6e
                  addInputPort(name, *port);
Shinya Kitaoka 120a6e
              }
Shinya Kitaoka 120a6e
            }
Shinya Kitaoka 120a6e
          }
Shinya Kitaoka 120a6e
          i++;
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          throw TException("unexpected tag " + tagName);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    } else if (tagName == "super") {
Shinya Kitaoka 120a6e
      TRasterFx::loadData(is);
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      throw TException("unexpected tag " + tagName);
Shinya Kitaoka 120a6e
    is.closeChild();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  collectParams(this);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TMacroFx::saveData(TOStream &os) {
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  os.openChild("root");
Shinya Kitaoka 120a6e
  TPersist *p = m_root.getPointer();
Shinya Kitaoka 120a6e
  os << p;
Shinya Kitaoka 120a6e
  os.closeChild();
Shinya Kitaoka 120a6e
  os.openChild("nodes");
Shinya Kitaoka 120a6e
  for (i = 0; i < (int)m_fxs.size(); i++) {
Shinya Kitaoka 120a6e
    TFxP fx     = m_fxs[i];
Shinya Kitaoka 120a6e
    TPersist *p = fx.getPointer();
Shinya Kitaoka 120a6e
    os << p;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  os.closeChild();
Shinya Kitaoka 120a6e
  os.openChild("ports");
Shinya Kitaoka 120a6e
  for (i = 0; i < getInputPortCount(); i++) {
Shinya Kitaoka 120a6e
    std::string portName = getInputPortName(i);
Shinya Kitaoka 120a6e
    std::map<std::string, std::string=""> attr;</std::string,>
Shinya Kitaoka 120a6e
    attr["name_inFx"] = portName;
Shinya Kitaoka 120a6e
    os.openCloseChild("port", attr);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  os.closeChild();
Shinya Kitaoka 120a6e
  os.openChild("super");
Shinya Kitaoka 120a6e
  TRasterFx::saveData(os);
Shinya Kitaoka 120a6e
  os.closeChild();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------
Toshihiro Shimizu 890ddd
FX_IDENTIFIER(TMacroFx, "macroFx")
Shinya Kitaoka 120a6e
// FX_IDENTIFIER_IS_HIDDEN(TMacroFx, "macroFx")