std::vector<const TFx *> calculateSortedFxs(TRasterFxP rootFx) { std::map<const TFx *, std::set<const TFx *>> E; /* 辺の情報 */ std::set<const TFx *> Sources; /* 入次数0のノード群 */ std::queue<const TFx *> Q; Q.push(rootFx.getPointer()); E[rootFx.getPointer()] = std::set<const TFx *>(); while (!Q.empty()) { const TFx *vptr = Q.front(); Q.pop(); if (!vptr) { continue; } /* 繋がっている入力ポートの先の Fx を訪問する 入力ポートが無ければ終了 */ int portCount = vptr->getInputPortCount(); if (portCount < 1) { Sources.insert(vptr); continue; } for (int i = 0; i < portCount; i++) { TFxPort *port = vptr->getInputPort(i); if (!port) { continue; } TFxP u = port->getFx(); const TFx *uptr = u.getPointer(); if (E.count(uptr) == 0) { E[uptr] = std::set<const TFx *>(); } if (E[uptr].count(vptr) == 0) { E[uptr].insert(vptr); } Q.push(uptr); } } /* トポロジカルソート */ std::set<const TFx *> visited; std::vector<const TFx *> L; std::function<void(const TFx *)> visit = [&visit, &visited, &E, &L](const TFx *fx) { if (visited.count(fx)) return; visited.insert(fx); auto edge = E[fx]; for (auto i = edge.cbegin(); i != edge.cend(); i++) { visit(*i); } L.insert(L.begin(), fx); }; for (auto i = E.cbegin(); i != E.cend(); i++) { visit(i->first); } return L; }
void SwatchCacheManager::setFx(const TFxP &fx) { QMutexLocker locker(&m_mutex); //Update the fxs id data if (fx == TFxP()) { //Clear if no fx is set m_setFxId = 0; m_childrenFxIds.clear(); } else { m_setFxId = fx->getIdentifier(); m_childrenFxIds.clear(); assert(m_setFxId != 0); TRasterFx *rfx = dynamic_cast<TRasterFx *>(fx.getPointer()); assert(rfx); for (int i = 0; i < fx->getInputPortCount(); ++i) { //Fxs not allowing cache on the input port are skipped if (!rfx->allowUserCacheOnPort(i)) continue; TFxPort *iport = fx->getInputPort(i); if (iport && iport->isConnected()) { TFx *child = iport->getFx(); //In the zerary case, extract the actual fx TZeraryColumnFx *zcfx = dynamic_cast<TZeraryColumnFx *>(child); if (zcfx) child = zcfx->getZeraryFx(); assert(child && child->getIdentifier() != 0); m_childrenFxIds.insert(child->getIdentifier()); } } } //NOTE: Check if this should be avoided in some case... //Release the locks and clear the resources if (m_currEditedFxResult) m_currEditedFxResult->releaseLock(); m_currEditedFxResult = TCacheResourceP(); std::set<TCacheResourceP>::iterator it; for (it = m_swatchCacheContainer.begin(); it != m_swatchCacheContainer.end(); ++it) (*it)->releaseLock(); m_swatchCacheContainer.clear(); #ifdef USE_SQLITE_HDPOOL TCacheResourcePool::instance()->releaseReferences("S"); #else for (it = m_genericCacheContainer.begin(); it != m_genericCacheContainer.end(); ++it) (*it)->releaseLock(); m_genericCacheContainer.clear(); #endif }
TFxP MultimediaRenderer::Imp::addPostProcessing(TFxP fx, TFxP postProc) { if (dynamic_cast<TXsheetFx *>(postProc.getPointer())) return fx; //Clone the postProcessing tree and substitute recursively postProc = postProc->clone(true); addPostProcessingRecursive(fx, postProc); return postProc; }
bool FxSelection::isSelected(TFxP fx) const { int i; for (i = 0; i < m_selectedFxs.size(); i++) { TFx *selectedFx = m_selectedFxs[i].getPointer(); TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(selectedFx); if (zfx && (fx.getPointer() == zfx || fx.getPointer() == zfx->getZeraryFx())) return true; if (fx.getPointer() == selectedFx) return true; } return false; }
void MultimediaRenderer::Imp::addPostProcessingRecursive(TFxP fx, TFxP postProc) { if (!postProc) return; int i, count = postProc->getInputPortCount(); for (i = 0; i < count; ++i) { TFxPort *port = postProc->getInputPort(i); TFx *childFx = port->getFx(); if (dynamic_cast<TXsheetFx *>(childFx)) port->setFx(fx.getPointer()); else addPostProcessingRecursive(fx, childFx); } }
void SwatchViewer::setFx(const TFxP &fx, const TFxP &actualFx, int frame) { m_fx = m_actualFxClone = fx; m_frame = frame; m_points.clear(); m_pointPairs.clear(); if (!fx) { ::setFxForCaching(0); computeContent(); return; } // abilita la cache nel nuovo effetto corrente ::setFxForCaching(actualFx.getPointer()); if (NaAffineFx *affFx = dynamic_cast<NaAffineFx *>(m_fx.getPointer())) m_fxAff = affFx->getPlacement(m_frame); else m_fxAff = TAffine(); int i; for (i = 0; i < actualFx->getParams()->getParamCount(); i++) { TPointParam *pointParam = dynamic_cast<TPointParam *>(actualFx->getParams()->getParam(i)); if (pointParam) m_points.push_back(Point(i, pointParam)); } // cerco i segmenti int n = m_points.size(); for (i = 0; i < n; i++) { string name = m_points[i].m_param->getName(); string prefix = matchSuffix(name, "_a"); if (prefix == "") continue; string otherName = prefix + "_b"; int j; for (j = 0; j < n; j++) if (i != j && m_points[j].m_param->getName() == otherName) break; if (j < n) { m_pointPairs.push_back(std::make_pair(i, j)); m_points[i].m_pairFlag = m_points[j].m_pairFlag = true; } } computeContent(); }
void SwatchCacheManager::getResource( TCacheResourceP &resource, const string &alias, const TFxP &fx, double frame, const TRenderSettings &rs, ResourceDeclaration *resData) { //Only FX RESULTS are interesting - plus, avoid if we're not currently //editing an fx. if (!(fx && m_setFxId > 0)) return; QMutexLocker locker(&m_mutex); //Cache the result in case the fx's id is among the stored ones. unsigned long fxId = fx->getIdentifier(); if (fxId == m_setFxId && rs.m_isSwatch) { if (!resource) resource = TCacheResourceP(alias, true); resource->addLock(); if (m_currEditedFxResult) m_currEditedFxResult->releaseLock(); m_currEditedFxResult = resource; return; } if (m_childrenFxIds.find(fxId) != m_childrenFxIds.end()) { if (!resource) resource = TCacheResourceP(alias, true); if (rs.m_isSwatch) { std::set<TCacheResourceP>::iterator it = m_swatchCacheContainer.find(resource); if (it == m_swatchCacheContainer.end()) { resource->addLock(); m_swatchCacheContainer.insert(resource); } } else { #ifdef USE_SQLITE_HDPOOL resource->enableBackup(); TCacheResourcePool::instance()->addReference(resource, "S"); #else std::set<TCacheResourceP>::iterator it = m_genericCacheContainer.find(resource); if (it == m_genericCacheContainer.end()) { resource->addLock(); m_genericCacheContainer.insert(resource); } #endif } } }
bool TMacroFx::analyze(const vector<TFxP> &fxs, TFxP &root, vector<TFxP> &roots, vector<TFxP> &leafs) { if (fxs.size() == 1) return false; else { leafs.clear(); roots.clear(); std::vector<TFxP>::const_iterator it = fxs.begin(); for (; it != fxs.end(); ++it) { TFxP fx = *it; int inputInternalConnection = 0; int inputExternalConnection = 0; int outputInternalConnection = 0; int outputExternalConnection = 0; int i; // calcola se ci sono connessioni in input dall'esterno // verso l'interno e/o internamente a orderedFxs int inputPortCount = fx->getInputPortCount(); for (i = 0; i < inputPortCount; ++i) { TFxPort *inputPort = fx->getInputPort(i); TFx *inputPortFx = inputPort->getFx(); if (inputPortFx) { if (std::find_if(fxs.begin(), fxs.end(), MatchesFx(inputPortFx)) != fxs.end()) ++inputInternalConnection; else ++inputExternalConnection; } } // calcola se ci sono connessioni in output dall'interno // verso l'esterno e/o internamente a orderedFxs int outputPortCount = fx->getOutputConnectionCount(); for (i = 0; i < outputPortCount; ++i) { TFxPort *outputPort = fx->getOutputConnection(i); TFx *outputFx = outputPort->getOwnerFx(); if (outputFx) { if (std::find_if(fxs.begin(), fxs.end(), MatchesFx(outputFx)) != fxs.end()) ++outputInternalConnection; else ++outputExternalConnection; } } // se fx e' una radice if ((outputExternalConnection > 0) || (outputExternalConnection == 0 && outputInternalConnection == 0)) { root = fx; roots.push_back(fx); } // se fx e' una foglia if (inputExternalConnection > 0 || fx->getInputPortCount() == 0 || (inputExternalConnection == 0 && inputInternalConnection < fx->getInputPortCount())) { leafs.push_back(fx); } } if (roots.size() != 1) return false; else { if (leafs.size() == 0) return false; } return true; } }
TMacroFx *TMacroFx::create(const vector<TFxP> &fxs) { std::vector<TFxP> leafs; std::vector<TFxP> roots; TFxP root = 0; vector<TFxP> orederedFxs = sortFxs(fxs); // verifica che gli effetti selezionati siano idonei ad essere raccolti // in una macro. Ci deve essere un solo nodo terminale // (roots.size()==1, roots[0] == root) e uno o piu' nodi di ingresso // (assert leafs.size()>0) if (!analyze(orederedFxs, root, roots, leafs)) return 0; // ----------------------------- TMacroFx *macroFx = new TMacroFx; // tutti i nodi vengono spostati (e non copiati) nella macro stessa std::vector<TFxP>::const_iterator it = orederedFxs.begin(); for (; it != orederedFxs.end(); ++it) macroFx->m_fxs.push_back(*it); // i nodi di ingresso vengono messi in collegamento con le // porte di ingresso della macro for (int i = 0; i < (int)leafs.size(); i++) { TFxP fx = leafs[i]; int k = 0; int count = fx->getInputPortCount(); for (; k < count; k++) { TFxPort *port = fx->getInputPort(k); string portName = fx->getInputPortName(k); string fxId = toString(fx->getFxId()); portName += "_" + toString(macroFx->getInputPortCount()) + "_" + fxId; TFx *portFx = port->getFx(); if (portFx) { // se la porta k-esima del nodo di ingresso i-esimo e' collegata // ad un effetto, la porta viene inserita solo se l'effetto non fa // gia' parte della macro if (std::find_if(orederedFxs.begin(), orederedFxs.end(), MatchesFx(portFx)) == orederedFxs.end()) macroFx->addInputPort(portName, *port); } else macroFx->addInputPort(portName, *port); } } // le porte di uscita di root diventano le porte di uscita della macro int count = root->getOutputConnectionCount(); int k = count - 1; for (; k >= 0; --k) { TFxPort *port = root->getOutputConnection(k); port->setFx(macroFx); } macroFx->setRoot(root.getPointer()); // tutti i parametri delle funzioni figlie diventano parametri della macro collectParams(macroFx); return macroFx; }