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; }