void undo() const { FxDag *fxDag = TApp::instance()->getCurrentXsheet()->getXsheet()->getFxDag(); int i, j; for (i = 0; i < (int)m_fxs.size(); i++) { TApp::instance()->getCurrentFx()->setFx(m_fxs[i].m_fx.getPointer()); TFxCommand::addFx(m_fxs[i].m_fx.getPointer()); } for (i = 0; i < (int)m_fxs.size(); i++) { const Node &node = m_fxs[i]; TFx *fx = node.m_fx.getPointer(); if (node.m_xsheetConnected) fxDag->addToXsheet(fx); for (j = 0; j < (int)node.m_inputLinks.size(); j++) fx->getInputPort(j)->setFx(node.m_inputLinks[j].getPointer()); for (j = 0; j < (int)node.m_outputLinks.size(); j++) { TFx *outFx = node.m_outputLinks[j].second.getPointer(); outFx->getInputPort(node.m_outputLinks[j].first)->setFx(fx); } } for (i = 0; i < (int)m_inputConnectedToXsheet.size(); i++) { TFx *inputFx = m_inputConnectedToXsheet[i].getPointer(); fxDag->getTerminalFxs()->removeFx(inputFx); } TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); }
void TColumnDataElement::storeColumn(TXsheet *xsh, int index, int fxFlags) { if (index < 0) return; bool doClone = (fxFlags & eDoClone); bool resetFxDagPositions = (fxFlags & eResetFxDagPositions); // Fetch the specified column (if none, return) TStageObject *obj = xsh->getStageObject(TStageObjectId::ColumnId(index)); assert(obj); TXshColumn *column = xsh->getColumn(index); if (!column) return; TFx *fx = column->getFx(); TPointD dagPos; if (fx) dagPos = fx->getAttributes()->getDagNodePos(); if (doClone) column = column->clone(); // Zerary fxs clone the associated fx (drawn levels do not) if (fx && !resetFxDagPositions) column->getFx()->getAttributes()->setDagNodePos(dagPos); m_column = column; storeObject(obj->getId(), xsh); }
//!Build the scene fx for each node below the xsheet one. //!Remember that left xsheet ports must not be expanded. void MultimediaRenderer::Imp::scanSceneForLayers() { //Retrieve the terminal fxs (ie, fxs which are implicitly //connected to the xsheet one) TXsheet *xsh = m_scene->getXsheet(); TFxSet *fxs = xsh->getFxDag()->getTerminalFxs(); //Examine all of them and - eventually - expand left xsheet //ports (ie fx nodes who allow implicit overlaying) for (int i = 0; i < fxs->getFxCount(); ++i) { TFx *fx = fxs->getFx(i); TFxPort *leftXSheetPort; retry: if (!fx) continue; leftXSheetPort = fx->getXsheetPort(); if (!leftXSheetPort) { m_fxsToRender.addFx(fx); continue; } //If the leftXSheetPort is not connected, retry on port 0 if (leftXSheetPort->isConnected()) m_fxsToRender.addFx(fx); else { fx = fx->getInputPort(0)->getFx(); goto retry; } } }
void FxKeyframeNavigator::toggle() { TFx *fx = getFx(); if (!fx) return; int i, paramCount = fx->getParams()->getParamCount(); // determino in quale caso ci troviamo: // il frame corrente non e' keyframe di nessun parametro (isKeyframe=false), // di qualche parametro o di tutti i parametri (isFullKeyframe=true) bool isFullKeyframe = true; bool isKeyframe = false; int frame = getCurrentFrame(); for (i = 0; i < paramCount; i++) { TParamP param = fx->getParams()->getParam(i); if (!param->isAnimatable()) continue; if (param->isKeyframe(frame)) isKeyframe = true; else isFullKeyframe = false; } if (!isKeyframe) isFullKeyframe = false; // modifico lo stato: nokeyframe->full, full->no, partial->full bool on = !isKeyframe || isKeyframe && !isFullKeyframe; for (i = 0; i < fx->getParams()->getParamCount(); i++) { // TODO. spostare questo codice in TParam TParamP param = fx->getParams()->getParam(i); if (TDoubleParamP dp = param) { if (on) dp->setValue(frame, dp->getValue(frame)); else dp->deleteKeyframe(frame); } else if (TRangeParamP rp = param) { if (on) rp->setValue(frame, rp->getValue(frame)); else rp->deleteKeyframe(frame); } else if (TPointParamP pp = param) { if (on) pp->setValue(frame, pp->getValue(frame)); else pp->deleteKeyframe(frame); } else if (TPixelParamP pip = param) { if (on) pip->setValue(frame, pip->getValue(frame)); else pip->deleteKeyframe(frame); } else if (TSpectrumParamP sp = param) { if (on) sp->setValue(frame, sp->getValue(frame), false); else sp->deleteKeyframe(frame); } else if (TToneCurveParamP tcp = param) { if (on) tcp->setValue(frame, tcp->getValue(frame), false); else tcp->deleteKeyframe(frame); } } m_fxHandle->notifyFxChanged(); }
void FxsData::getFxs(QList<TFxP> &fxs, QMap<TFx *, int> &zeraryFxColumnSize, QList<TXshColumnP> &columns) const { QMap<TFx *, TFx *> clonedFxs; for (int i = 0; i < m_fxs.size(); i++) { TFx *clonedFx = m_fxs[i]->clone(false); TPointD pos = m_fxs[i]->getAttributes()->getDagNodePos(); clonedFx->getAttributes()->setDagNodePos(pos); clonedFx->getAttributes()->removeFromAllGroup(); fxs.append(clonedFx); if (m_fxs[i]->isZerary()) zeraryFxColumnSize[clonedFx] = m_zeraryFxColumnSize[m_fxs[i].getPointer()]; clonedFxs[m_fxs[i].getPointer()] = clonedFx; TFx *linkedFx = m_fxs[i]->getLinkedFx(); if (linkedFx && clonedFxs.contains(linkedFx)) clonedFx->linkParams(clonedFxs[linkedFx]); } QList<TXshColumnP>::const_iterator it; for (it = m_columns.begin(); it != m_columns.end(); it++) { TXshColumn *col = it->getPointer(); TXshColumn *newCol = col->clone(); newCol->getFx()->getAttributes()->setDagNodePos( col->getFx()->getAttributes()->getDagNodePos()); columns.append(newCol); clonedFxs[col->getFx()] = newCol->getFx(); } linkFxs(clonedFxs); }
bool TXsheet::setCell(int row, int col, const TXshCell &cell) { if (row < 0 || col < 0) return false; bool wasColumnEmpty = isColumnEmpty(col); TXshCellColumn *cellColumn; if (!cell.isEmpty()) { TXshLevel *level = cell.m_level.getPointer(); assert(level); int levelType = level->getType(); TXshColumn::ColumnType type = TXshColumn::eLevelType; if (levelType == SND_XSHLEVEL) type = TXshColumn::eSoundType; else if (levelType == SND_TXT_XSHLEVEL) type = TXshColumn::eSoundTextType; else if (levelType == PLT_XSHLEVEL) type = TXshColumn::ePaletteType; else if (levelType == ZERARYFX_XSHLEVEL) type = TXshColumn::eZeraryFxType; else if (levelType == MESH_XSHLEVEL) type = TXshColumn::eMeshType; cellColumn = touchColumn(col, type)->getCellColumn(); } else { TXshColumn *column = getColumn(col); cellColumn = column ? column->getCellColumn() : 0; } if (!cellColumn || cellColumn->isLocked()) return false; cellColumn->setXsheet(this); if (!cellColumn->setCell(row, cell)) { if (wasColumnEmpty) { removeColumn(col); insertColumn(col); } return false; } TFx *fx = cellColumn->getFx(); if (wasColumnEmpty && fx && fx->getOutputConnectionCount() == 0 && cellColumn->getPaletteColumn() == 0) getFxDag()->addToXsheet(fx); if (cell.isEmpty()) updateFrameCount(); else if (row >= m_imp->m_frameCount) m_imp->m_frameCount = row + 1; TNotifier::instance()->notify(TXsheetChange()); return true; }
bool FxKeyframeNavigator::isKeyframe() const { TFx *fx = getFx(); if (!fx) return false; for (int i = 0; i < fx->getParams()->getParamCount(); i++) { TParamP param = fx->getParams()->getParam(i); if (param->isKeyframe(getCurrentFrame())) return true; } return false; }
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 }
TFx *TMacroFx::clone(bool recursive) const { int n = m_fxs.size(); vector<TFxP> clones(n); std::map<TFx *, int> table; std::map<TFx *, int>::iterator it; int i, rootIndex = -1; // nodi for (i = 0; i < n; ++i) { TFx *fx = m_fxs[i].getPointer(); assert(fx); clones[i] = fx->clone(false); assert(table.count(fx) == 0); table[fx] = i; if (fx == m_root.getPointer()) rootIndex = i; TFx *linkedFx = fx->getLinkedFx(); if (linkedFx && table.find(linkedFx) != table.end()) clones[i]->linkParams(clones[table[linkedFx]].getPointer()); } assert(rootIndex >= 0); // connessioni for (i = 0; i < n; i++) { TFx *fx = m_fxs[i].getPointer(); for (int j = 0; j < fx->getInputPortCount(); j++) { TFxPort *port = fx->getInputPort(j); TFx *inputFx = port->getFx(); if (!inputFx) continue; it = table.find(inputFx); if (it == table.end()) { // il j-esimo input di fx e' esterno alla macro if (recursive) clones[i]->connect(fx->getInputPortName(j), inputFx->clone(true)); } else { // il j-esimo input di fx e' interno alla macro clones[i]->connect(fx->getInputPortName(j), clones[it->second].getPointer()); } } } //TFx *rootClone = // const_cast<TMacroFx*>(this)-> // clone(m_root.getPointer(), recursive, visited, clones); TMacroFx *clone = TMacroFx::create(clones); clone->setName(getName()); clone->setFxId(getFxId()); //Copy the index of the passive cache manager. clone->getAttributes()->passiveCacheDataIdx() = getAttributes()->passiveCacheDataIdx(); assert(clone->getRoot() == clones[rootIndex].getPointer()); return clone; }
TFx *TMacroFx::getFxById(const wstring &id) const { int i; for (i = 0; i < (int)m_fxs.size(); i++) { TFx *fx = m_fxs[i].getPointer(); if (fx->getFxId() == id) return fx; } return 0; }
bool FxKeyframeNavigator::isFullKeyframe() const { TFx *fx = getFx(); if (!fx) return false; int keyFrameCount = 0; int animatableParamCount = 0; for (int i = 0; i < fx->getParams()->getParamCount(); i++) { TParamP param = fx->getParams()->getParam(i); if (param->isAnimatable()) { animatableParamCount++; if (param->isKeyframe(getCurrentFrame())) keyFrameCount++; } } return animatableParamCount > 0 && keyFrameCount == animatableParamCount; }
void TXsheet::loadData(TIStream &is) { clearAll(); TStageObjectId cameraId = TStageObjectId::CameraId(0); TStageObject *firstCamera = getStageObject(cameraId); m_imp->m_pegTree->removeStageObject(cameraId); int col = 0; string tagName; while (is.openChild(tagName)) { if (tagName == "columns") { while (!is.eos()) { TPersist *p = 0; is >> p; TXshColumn *column = dynamic_cast<TXshColumn *>(p); if (!column) throw TException("expected xsheet column"); m_imp->m_columnSet.insertColumn(col++, column); column->setXsheet(this); if (TXshZeraryFxColumn *zc = dynamic_cast<TXshZeraryFxColumn *>(column)) { TFx *fx = zc->getZeraryColumnFx()->getZeraryFx(); int fxTypeCount = m_imp->m_fxDag->getFxTypeCount(fx); int maxFxTypeId = std::max(fxTypeCount, fx->getAttributes()->getId()); m_imp->m_fxDag->updateFxTypeTable(fx, maxFxTypeId); m_imp->m_fxDag->updateFxIdTable(fx); for (int j = 0; j < fx->getParams()->getParamCount(); j++) { TParam *param = fx->getParams()->getParam(j); if (TDoubleParam *dp = dynamic_cast<TDoubleParam *>(param)) getStageObjectTree()->setGrammar(dp); else if (dynamic_cast<TPointParam *>(param) || dynamic_cast<TRangeParam *>(param) || dynamic_cast<TPixelParam *>(param)) { TParamSet *paramSet = dynamic_cast<TParamSet *>(param); assert(paramSet); int f; for (f = 0; f < paramSet->getParamCount(); f++) { TDoubleParam *dp = dynamic_cast<TDoubleParam *>( paramSet->getParam(f).getPointer()); if (!dp) continue; getStageObjectTree()->setGrammar(dp); } } } } } } else if (tagName == "pegbars") { TPersist *p = m_imp->m_pegTree; is >> *p; } else if (tagName == "fxnodes") {
void FxGadgetController::onFxSwitched() { clearGadgets(); bool enabled = false; TFx *fx = m_fxHandle ? m_fxHandle->getFx() : 0; if (fx) { int referenceColumnIndex = fx->getReferenceColumnIndex(); if (referenceColumnIndex == -1) { TObjectHandle *oh = m_tool->getApplication()->getCurrentObject(); if (!oh->getObjectId().isCamera()) { oh->setObjectId(TStageObjectId::CameraId(0)); } enabled = true; } else if (referenceColumnIndex == m_tool->getColumnIndex()) enabled = true; } if (fx && enabled) { m_editingNonZeraryFx = true; TZeraryColumnFx *zfx = 0; if ((zfx = dynamic_cast<TZeraryColumnFx *>(fx)) || dynamic_cast<TLevelColumnFx *>(fx)) // WARNING! quick patch for huge bug: I added the || with TLevelColumnFx; // before, the levels were considered as nonZeraryFx and the edit tool // gadget was not displayed! Vinz { if (zfx) fx = zfx->getZeraryFx(); m_editingNonZeraryFx = false; } // Parse the UI Concepts returned by the fx TParamUIConcept *uiConcepts = 0; int i, count; fx->getParamUIs(uiConcepts, count); for (i = 0; i < count; ++i) { FxGadget *gadget = allocateGadget(uiConcepts[i]); if (gadget) addGadget(gadget); } delete[] uiConcepts; } else m_editingNonZeraryFx = false; m_tool->invalidate(); }
TColumnFx *MultimediaRenderer::Imp::searchColumn(TFxP fx) { //Descend ports 0 until a TColumnFx is found. Then, output its number. TFx *currFx = fx.getPointer(); TColumnFx *colFx = dynamic_cast<TColumnFx *>(currFx); while (!colFx) { if (fx->getInputPortCount() <= 0) break; currFx = currFx->getInputPort(0)->getFx(); if (!currFx) break; colFx = dynamic_cast<TColumnFx *>(currFx); } return colFx; }
TXshZeraryFxColumn::TXshZeraryFxColumn(const TXshZeraryFxColumn &src) : m_zeraryColumnFx(new TZeraryColumnFx()), m_zeraryFxLevel(new TXshZeraryFxLevel()) { m_zeraryColumnFx->addRef(); m_zeraryColumnFx->setColumn(this); m_zeraryFxLevel->addRef(); m_zeraryFxLevel->setColumn(this); m_first = src.m_first; int i; for (i = 0; i < (int)src.m_cells.size(); i++) m_cells.push_back(TXshCell(m_zeraryFxLevel, src.m_cells[i].getFrameId())); assert((int)src.m_cells.size() == (int)m_cells.size()); TFx *fx = src.getZeraryColumnFx()->getZeraryFx(); if (fx) { wstring fxName = fx->getName(); fx = fx->clone(false); fx->setName(fxName); m_zeraryColumnFx->setZeraryFx(fx); } }
StageObjectsData::~StageObjectsData() { int i, elementsCount = m_elements.size(); for (i = 0; i < elementsCount; ++i) delete m_elements[i]; for (i = 0; i < m_splines.size(); ++i) delete m_splines[i]; std::set<TFx *>::iterator it; for (it = m_fxs.begin(); it != m_fxs.end(); ++it) { TFx *fx = *it; if (fx) fx->release(); } for (it = m_terminalFxs.begin(); it != m_terminalFxs.end(); ++it) { TFx *fx = *it; if (fx) fx->release(); } }
void AddFxContextMenu::onAddFx(QAction *action) { if (action->isCheckable() && action->isChecked()) action->setChecked(false); TFx *fx = createFx(action, m_app->getCurrentXsheet()); if (fx) { QList<TFxP> fxs = m_selection->getFxs(); // try to add node at cursor position if (m_currentCursorScenePos.x() != 0 || m_currentCursorScenePos.y() != 0) { fx->getAttributes()->setDagNodePos(TPointD(m_currentCursorScenePos.x(), m_currentCursorScenePos.y())); m_currentCursorScenePos.setX(0); m_currentCursorScenePos.setY(0); } TFxCommand::addFx(fx, fxs, m_app, m_app->getCurrentColumn()->getColumnIndex(), m_app->getCurrentFrame()->getFrameIndex()); m_app->getCurrentXsheet()->notifyXsheetChanged(); //memorize the latest operation m_app->getCurrentFx()->setPreviousActionString(QString("A ") + action->data().toString()); } }
DeleteFxsUndo(const QList<TFx *> &fxs) { TApp *app = TApp::instance(); FxDag *fxDag = app->getCurrentXsheet()->getXsheet()->getFxDag(); for (int i = 0; i < (int)fxs.size(); i++) { TFx *fx = fxs[i]; TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(fx); if (zfx) fx = zfx->getZeraryFx(); Node node; node.m_fx = fx; node.m_xsheetConnected = fxDag->getTerminalFxs()->containsFx(fx); int j; for (j = 0; j < fx->getInputPortCount(); j++) { TFxP inputFx(fx->getInputPort(j)->getFx()); int i; if (inputFx && !fxDag->getTerminalFxs()->containsFx(inputFx.getPointer())) { for (i = 0; i < (int)m_inputConnectedToXsheet.size(); i++) if (m_inputConnectedToXsheet[i].getPointer() == inputFx.getPointer()) break; if (i == (int)m_inputConnectedToXsheet.size()) m_inputConnectedToXsheet.push_back(inputFx); } node.m_inputLinks.push_back(inputFx); } for (j = 0; j < fx->getOutputConnectionCount(); j++) { TFxPort *port = fx->getOutputConnection(j); TFx *outFx = port->getOwnerFx(); if (outFx) { int k; for (k = 0; k < outFx->getInputPortCount(); k++) if (outFx->getInputPort(k)->getFx() == fx) break; if (k < outFx->getInputPortCount()) node.m_outputLinks.push_back(std::make_pair(k, TFxP(outFx))); } } m_fxs.push_back(node); } }
void FxsData::setFxs(const QList<TFxP> &selectedFxs, const QList<Link> &selectedLinks, const QList<int> &columnIndexes, TXsheet *xsh) { // fx->clonedFx QMap<TFx *, TFx *> clonedFxs; for (int i = 0; i < selectedFxs.size(); i++) { TFx *fx = selectedFxs[i].getPointer(); if (!canCopyFx(fx)) continue; TZeraryColumnFx *zerayFx = dynamic_cast<TZeraryColumnFx *>(fx); if (zerayFx) fx = zerayFx->getZeraryFx(); TFx *clonedFx = fx->clone(false); TPointD pos; if (zerayFx) pos = zerayFx->getAttributes()->getDagNodePos(); else pos = fx->getAttributes()->getDagNodePos(); clonedFx->getAttributes()->setDagNodePos(pos); m_fxs.append(clonedFx); if (zerayFx) m_zeraryFxColumnSize[clonedFx] = zerayFx->getColumn()->getRowCount(); m_visitedFxs[clonedFx] = false; clonedFxs[fx] = clonedFx; TFx *linkedFx = fx->getLinkedFx(); if (linkedFx && clonedFxs.contains(linkedFx)) clonedFx->linkParams(clonedFxs[linkedFx]); } QList<int>::const_iterator it; for (it = columnIndexes.begin(); it != columnIndexes.end(); it++) { TXshColumn *col = xsh->getColumn(*it); TXshColumn *newCol = col->clone(); newCol->getFx()->getAttributes()->setDagNodePos( col->getFx()->getAttributes()->getDagNodePos()); m_columns.append(newCol); clonedFxs[col->getFx()] = newCol->getFx(); } linkFxs(clonedFxs, selectedLinks); checkConnectivity(); }
void FxSelection::visitFx(TFx *fx, QList<TFx *> &visitedFxs) { if (visitedFxs.contains(fx)) return; TZeraryColumnFx *zfx = dynamic_cast<TZeraryColumnFx *>(fx); if (zfx) fx = zfx->getZeraryFx(); if (!canGroup(fx)) return; visitedFxs.append(fx); int i; for (i = 0; i < fx->getInputPortCount(); i++) { TFx *inputFx = fx->getInputPort(i)->getFx(); TZeraryColumnFx *onputZFx = dynamic_cast<TZeraryColumnFx *>(inputFx); if (onputZFx) inputFx = onputZFx->getZeraryFx(); if (!inputFx) continue; bool canBeGrouped = !inputFx->getAttributes()->isGrouped() || (inputFx->getAttributes()->getEditingGroupId() == fx->getAttributes()->getEditingGroupId()); if (!visitedFxs.contains(inputFx) && isSelected(inputFx) && canBeGrouped) visitFx(inputFx, visitedFxs); } if (zfx) fx = zfx; if (fx->isZerary() && !zfx) { TXsheet *xsh = m_xshHandle->getXsheet(); int columnCount = xsh->getColumnCount(); int j; for (j = 0; j < columnCount; j++) { TZeraryColumnFx *zerary = dynamic_cast<TZeraryColumnFx *>(xsh->getColumn(j)->getFx()); if (zerary && zerary->getZeraryFx() == fx) { fx = zerary; break; } } } for (i = 0; i < fx->getOutputConnectionCount(); i++) { TFx *outputFx = fx->getOutputConnection(i)->getOwnerFx(); if (!outputFx) continue; bool canBeGrouped = !outputFx->getAttributes()->isGrouped() || (outputFx->getAttributes()->getEditingGroupId() == fx->getAttributes()->getEditingGroupId()); if (!visitedFxs.contains(outputFx) && isSelected(outputFx) && canBeGrouped) visitFx(outputFx, visitedFxs); } }
StageObjectsData *StageObjectsData::clone() const { StageObjectsData *data = new StageObjectsData(); // Clone each element (the new data gets ownership) int i, elementsCount = m_elements.size(); for (i = 0; i < elementsCount; ++i) data->m_elements.append(m_elements[i]->clone()); // Clone each spline (the new data gets ownership) for (i = 0; i < m_splines.size(); ++i) data->m_splines.append(m_splines[i]->clone()); // Same for internal fxs std::map<TFx *, TFx *> fxTable; // And trace the pairings with the originals std::set<TFx *>::const_iterator it; for (it = m_fxs.begin(); it != m_fxs.end(); ++it) { TFx *fxOrig = *it; assert(fxOrig); assert(fxTable.count(fxOrig) == 0); TFx *fx = fxOrig->clone(false); fx->getAttributes()->setId(fxOrig->getAttributes()->getId()); fx->getAttributes()->passiveCacheDataIdx() = -1; fx->setName(fxOrig->getName()); fx->setFxId(fxOrig->getFxId()); fxTable[fxOrig] = fx; fx->addRef(); data->m_fxs.insert(fx); } // Same with terminals for (it = m_terminalFxs.begin(); it != m_terminalFxs.end(); ++it) { TFx *fxOrig = *it; assert(fxOrig); // If the fx was not already cloned above, do it now TFx *fx = searchFx(fxTable, fxOrig); if (!fx) { fx = fxOrig->clone(false); fx->getAttributes()->setId(fxOrig->getAttributes()->getId()); fx->getAttributes()->passiveCacheDataIdx() = -1; fx->setName(fxOrig->getName()); fx->setFxId(fxOrig->getFxId()); fxTable[fxOrig] = fx; } fx->addRef(); data->m_terminalFxs.insert(fx); } if (!fxTable.empty()) updateFxLinks(fxTable); // Applies the traced map pairings to every fx descendant // of each fx stored in the map. // WARNING: m_fxsTable is NOT COPIED / CLONED !! return data; }
Link FxSelection::getBoundingFxs(SchematicPort *inputPort, SchematicPort *outputPort) { Link boundingFxs; FxSchematicNode *inputNode = dynamic_cast<FxSchematicNode *>(outputPort->getNode()); FxSchematicNode *outputNode = dynamic_cast<FxSchematicNode *>(inputPort->getNode()); FxGroupNode *groupNode = dynamic_cast<FxGroupNode *>(inputNode); if (!inputNode || !outputNode || (groupNode && groupNode->getOutputConnectionsCount() != 1)) return boundingFxs; if (dynamic_cast<TXsheetFx *>(outputNode->getFx())) { if (!groupNode) boundingFxs.m_inputFx = inputNode->getFx(); else { TFxSet *terminals = m_xshHandle->getXsheet()->getFxDag()->getTerminalFxs(); QList<TFxP> roots = groupNode->getRootFxs(); int i; for (i = 0; i < roots.size(); i++) if (terminals->containsFx(roots[i].getPointer())) { boundingFxs.m_inputFx = roots[i]; break; } } boundingFxs.m_outputFx = outputNode->getFx(); return boundingFxs; } if (outputNode->isA(eGroupedFx)) { // devo prima trovare l'effetto interno al gruppo al quale inputNode e' // linkato. FxGroupNode *groupNode = dynamic_cast<FxGroupNode *>(outputNode); assert(groupNode); QList<TFx *> fxs; TFx *inputFx = inputNode->getFx(); int i; for (i = 0; i < inputFx->getOutputConnectionCount(); i++) { TFx *outputFx = inputFx->getOutputConnection(i)->getOwnerFx(); if (!outputFx) continue; if (groupNode->contains(outputFx)) fxs.push_back(outputFx); } if (fxs.size() != 1) // un nodo esterno al gruppo puo' essere linkato a // piu' nodi interni al gruppo return boundingFxs; TFx *outputFx = fxs[0]; // ho tovato l'effetto, ora devo trovare l'indice della porta a cui e' // linkato l'effetto in input for (i = 0; i < outputFx->getInputPortCount(); i++) { TFxPort *inputPort = outputFx->getInputPort(i); TFx *fx = inputPort->getFx(); if (fx == inputFx) break; } if (i >= outputFx->getInputPortCount()) return boundingFxs; boundingFxs.m_inputFx = inputFx; boundingFxs.m_outputFx = outputFx; boundingFxs.m_index = i; return boundingFxs; } else { bool found = false; int i, index = -1; for (i = 0; i < outputNode->getInputPortCount() && !found; i++) { FxSchematicPort *inputAppPort = outputNode->getInputPort(i); int j; for (j = 0; j < inputAppPort->getLinkCount(); j++) { FxSchematicNode *outputAppNode = dynamic_cast<FxSchematicNode *>(inputAppPort->getLinkedNode(j)); if (!outputAppNode) continue; FxSchematicPort *outputAppPort = outputAppNode->getOutputPort(); if (inputAppPort == inputPort && outputPort == outputAppPort) { found = true; index = i; break; } } } if (index == -1) return boundingFxs; TFx *inputFx = inputNode->getFx(); TFx *outputFx = outputNode->getFx(); boundingFxs.m_inputFx = inputFx; boundingFxs.m_outputFx = outputFx; boundingFxs.m_index = index; return boundingFxs; } }
void MultimediaRenderer::Imp::start() { //Retrieve some useful infos double stretchTo = m_renderSettings.m_timeStretchTo; double stretchFrom = m_renderSettings.m_timeStretchFrom; double timeStretchFactor = stretchFrom / stretchTo; bool fieldRendering = m_renderSettings.m_fieldPrevalence != TRenderSettings::NoField; std::wstring modeStr; switch (m_multimediaMode) { case COLUMNS: modeStr = L"_col"; break; case LAYERS: modeStr = L"_lay"; break; default: assert(0); } //Build the post processing fxs tree std::vector<TFxP> postFxs(m_framesToRender.size()); std::set<double>::iterator jt; int j; for (j = 0, jt = m_framesToRender.begin(); jt != m_framesToRender.end(); ++j, ++jt) postFxs[j] = buildPostSceneFx(m_scene, *jt, m_renderSettings.m_shrinkX, false); // Adds camera and camera dpi transforms //For each node to be rendered int i, count = m_fxsToRender.getFxCount(); for (i = 0; i < count; ++i) { //In case the process has been canceled, return if (m_canceled) return; //Then, build the scene fx for each frame to be rendered std::vector<std::pair<double, TFxPair>> pairsToBeRendered; //NOTE: The above pairs should not be directly added to a previously declared movierenderer, //since an output level would be created even before knowing if any cell to be rendered is //actually available. const BSFX_Transforms_Enum transforms = // Do NOT add camera and BSFX_Transforms_Enum(BSFX_COLUMN_TR); // camera dpi transforms int j; for (j = 0, jt = m_framesToRender.begin(); jt != m_framesToRender.end(); ++j, ++jt) { TFxPair fx; if (m_renderSettings.m_stereoscopic) m_scene->shiftCameraX(-m_renderSettings.m_stereoscopicShift / 2); fx.m_frameA = buildSceneFx(m_scene, *jt, 0, m_fxsToRender.getFx(i), transforms); if (m_renderSettings.m_stereoscopic) { m_scene->shiftCameraX(m_renderSettings.m_stereoscopicShift); fx.m_frameB = buildSceneFx(m_scene, *jt, 0, m_fxsToRender.getFx(i), transforms); m_scene->shiftCameraX(-m_renderSettings.m_stereoscopicShift / 2); } else if (fieldRendering) fx.m_frameB = buildSceneFx(m_scene, *jt + 0.5 * timeStretchFactor, 0, m_fxsToRender.getFx(i), transforms); else fx.m_frameB = TRasterFxP(); //Substitute with the post-process... if (fx.m_frameA) fx.m_frameA = addPostProcessing(fx.m_frameA, postFxs[j]); if (fx.m_frameB) fx.m_frameB = addPostProcessing(fx.m_frameB, postFxs[j]); if (fx.m_frameA) //Could be 0, if the corresponding cell is void / not rendered pairsToBeRendered.push_back(std::pair<double, TFxPair>(*jt, fx)); } if (pairsToBeRendered.size() == 0) continue; //Could be, if no cell for this column was in the frame range. //Build the output name TColumnFx *colFx = searchColumn(m_fxsToRender.getFx(i)); TFx *currFx = m_fxsToRender.getFx(i); assert(colFx); if (!colFx) continue; int columnIndex = colFx->getColumnIndex(); std::wstring columnName(colFx->getColumnName()); std::wstring columnId(colFx->getColumnId()); std::wstring fxName(currFx->getName()); std::wstring fxNameNoSpaces(::removeSpaces(fxName)); std::wstring fxId(currFx->getFxId()); std::wstring fpName = m_fp.getWideName() + L"_" + columnName + (columnId == columnName ? L"" : L"(" + columnId + L")") + (fxId.empty() ? L"" : L"_" + fxName + (fxId == fxNameNoSpaces ? L"" : L"(" + fxId + L")")); TFilePath movieFp(m_fp.withName(fpName)); //Initialize a MovieRenderer with our infos MovieRenderer movieRenderer(m_scene, movieFp, m_threadCount, false); movieRenderer.setRenderSettings(m_renderSettings); movieRenderer.setDpi(m_xDpi, m_yDpi); movieRenderer.enablePrecomputing(m_precomputingEnabled); movieRenderer.addListener(this); for (unsigned int j = 0; j < pairsToBeRendered.size(); ++j) { std::pair<double, TFxPair> ¤tPair = pairsToBeRendered[j]; movieRenderer.addFrame(currentPair.first, currentPair.second); } //Finally, start rendering currently initialized MovieRenderer. m_currentFx = i; m_currentFrame = m_framesToRender.begin(); m_currentTRenderer = movieRenderer.getTRenderer(); movieRenderer.start(); //I don't recall Toonz currently supports different, simultaneous rendering processes. //However, one rendering process is supposed to be exhausting the machine's resources //on its own - so, we'll just set up an idle (but GUI-reactive) loop here. //It will quit looping whenever the "onSequenceCompleted" notification gets called. m_eventLoop.exec(); //---------------------- Loops here -------------------------- } //Lastly, inform everyone that rendering stopped onRenderCompleted(); }
void StageObjectsData::storeObjects(const std::vector<TStageObjectId> &ids, TXsheet *xsh, int fxFlags) { assert(m_fxTable.empty()); // Should be enforced OUTSIDE. Track implicit uses. m_fxTable.clear(); // TO BE REMOVED int i, objCount = ids.size(); // Discriminate sensible stage object types (ie cameras and columns from the rest). // Store them in a map, ordered by object index. std::map<int, TStageObjectId> cameraIds, columnIds, pegbarIds; for (i = 0; i < objCount; ++i) { TStageObjectId id = ids[i]; if (id.isColumn()) columnIds[id.getIndex()] = id; else if (id.isPegbar()) pegbarIds[id.getIndex()] = id; else if (id.isCamera()) cameraIds[id.getIndex()] = id; } // Store a suitable object for each std::map<int, TStageObjectId>::iterator it; for (it = cameraIds.begin(); it != cameraIds.end(); ++it) { // Cameras TCameraDataElement *cameraElement = new TCameraDataElement(); cameraElement->storeCamera(it->second, xsh); m_elements.append(cameraElement); } for (it = pegbarIds.begin(); it != pegbarIds.end(); ++it) { // Pegbars (includes curves) TStageObjectDataElement *objElement = new TStageObjectDataElement(); objElement->storeObject(it->second, xsh); m_elements.append(objElement); } for (it = columnIds.begin(); it != columnIds.end(); ++it) { // Columns int colIndex = it->second.getIndex(); TXshColumn *column = xsh->getColumn(colIndex); if (!column) continue; TColumnDataElement *columnElement = new TColumnDataElement(); columnElement->storeColumn(xsh, colIndex, fxFlags); m_elements.append(columnElement); TXshColumn *copiedColumn = columnElement->m_column.getPointer(); if (column->getFx() && copiedColumn->getFx()) { // Store column fx pairings (even if the originals are not cloned) m_fxTable[column->getFx()] = copiedColumn->getFx(); m_originalColumnFxs.insert(column->getFx()); } } // Insert terminal fxs set<TFx *>::iterator jt; for (jt = m_originalColumnFxs.begin(); jt != m_originalColumnFxs.end(); ++jt) { if (isColumnSelectionTerminalFx( *jt, xsh->getFxDag()->getTerminalFxs(), m_originalColumnFxs)) { TFx *fx = m_fxTable[*jt]; fx->addRef(); m_terminalFxs.insert(fx); } } }
void StageObjectsData::storeFxs(const std::set<TFx *> &fxs, TXsheet *xsh, int fxFlags) { bool doClone = (fxFlags & eDoClone); bool resetFxDagPositions = (fxFlags & eResetFxDagPositions); TFxSet *terminalFxs = xsh->getFxDag()->getTerminalFxs(); // Traverse specified fxs std::set<TFx *>::const_iterator it; for (it = fxs.begin(); it != fxs.end(); ++it) { TFx *fxOrig = *it, *fx = fxOrig; if (doClone) { // If required, clone them fx = fxOrig->clone(false); fx->setName(fxOrig->getName()); fx->getAttributes()->setId(fxOrig->getAttributes()->getId()); fx->getAttributes()->passiveCacheDataIdx() = -1; if (resetFxDagPositions) fx->getAttributes()->setDagNodePos(TConst::nowhere); } // Store them (and the original/clone pairing even if not cloning) m_fxTable[fxOrig] = fx; fx->addRef(); m_fxs.insert(fx); // Find out if the fx is a terminal one in the selection. If so, store it there too. bool isTerminal = true; if (!terminalFxs->containsFx(fxOrig)) // If it's terminal in the xsheet, no doubt { // Otherwise, check terminality with respect to the selection int i, outputConnectionsCount = fxOrig->getOutputConnectionCount(); for (i = 0; i < outputConnectionsCount; ++i) { TFx *outputFx = fxOrig->getOutputConnection(i)->getOwnerFx(); if (outputFx && fxs.count(outputFx) > 0) { isTerminal = false; break; } } } // Well, excluding true TOutputFxs... TOutputFx *outFx = dynamic_cast<TOutputFx *>(fx); if (isTerminal && !outFx) { fx->addRef(); m_terminalFxs.insert(fx); } } // Updating terminality of the column fxs too! // WARNING: This requires that storeObjects() is invoked BEFORE this ! for (it = m_originalColumnFxs.begin(); it != m_originalColumnFxs.end(); ++it) { TFx *fxOrig = *it; bool isTerminal = true; if (!terminalFxs->containsFx(fxOrig)) { int i, outputConnectionsCount = fxOrig->getOutputConnectionCount(); for (i = 0; i < outputConnectionsCount; ++i) { TFx *outputFx = fxOrig->getOutputConnection(i)->getOwnerFx(); if (outputFx && fxs.count(outputFx) > 0) { isTerminal = false; break; } } } if (isTerminal) { TFx *fx = m_fxTable[fxOrig]; fx->addRef(); m_terminalFxs.insert(fx); } } if (!m_fxTable.empty() && doClone) updateFxLinks(m_fxTable); // Apply original/clone pairings // to fx relatives }
bool TXsheet::setCells(int row, int col, int rowCount, const TXshCell cells[]) { static const TXshCell emptyCell; int i = 0; while (i < rowCount && cells[i].isEmpty()) i++; // inserito da Elisa verso novembre 2009. // cosi' ha il difetto che se assegno celle vuote non fa nulla // per ora lo commento. bisogna indagare se questo rompe qualcosa // ho modificato il seguito per gestire il caso in cui i>=rowCount // => niente livelli dentro cells // if(i>=rowCount) // return false; TXshColumn::ColumnType type = TXshColumn::eLevelType; if (i < rowCount) { TXshLevel *level = cells[i].m_level.getPointer(); int levelType = level->getType(); if (levelType == SND_XSHLEVEL) type = TXshColumn::eSoundType; else if (levelType == SND_TXT_XSHLEVEL) type = TXshColumn::eSoundTextType; else if (levelType == PLT_XSHLEVEL) type = TXshColumn::ePaletteType; else if (levelType == ZERARYFX_XSHLEVEL) type = TXshColumn::eZeraryFxType; else if (levelType == MESH_XSHLEVEL) type = TXshColumn::eMeshType; } bool wasColumnEmpty = isColumnEmpty(col); TXshCellColumn *column = touchColumn(col, type)->getCellColumn(); if (!column) return false; int oldColRowCount = column->getMaxFrame() + 1; bool ret = column->setCells(row, rowCount, cells); if (!ret || column->isLocked()) { if (wasColumnEmpty) { removeColumn(col); insertColumn(col); } return false; } int newColRowCount = column->getMaxFrame() + 1; TFx *fx = column->getFx(); if (wasColumnEmpty && fx && fx->getOutputConnectionCount() == 0) getFxDag()->addToXsheet(fx); column->setXsheet(this); if (newColRowCount > m_imp->m_frameCount) m_imp->m_frameCount = newColRowCount; else { if (oldColRowCount == m_imp->m_frameCount && newColRowCount < m_imp->m_frameCount) updateFrameCount(); } return true; }
void StageObjectsData::storeColumnFxs(const std::set<int> &columnIndexes, TXsheet *xsh, int fxFlags) { bool doClone = (fxFlags & eDoClone); bool resetFxDagPositions = (fxFlags & eResetFxDagPositions); std::set<TFx *> internalFxs; xsh->getFxDag()->getInternalFxs()->getFxs(internalFxs); // Iterate internal fxs (note: columns NOT included) // NOTE: Could this be too heavy ? Shouldn't we travel upstream from given column fxs? std::set<TFx *>::iterator it; for (it = internalFxs.begin(); it != internalFxs.end(); ++it) { TFx *fxOrig = *it, *fx = fxOrig; if (m_fxTable.find(fx) != m_fxTable.end()) // If already treated continue; if (!canGenerate(m_originalColumnFxs, fx)) // If not completely in the upstream continue; if (doClone) { // Clone the fx if required fx = fxOrig->clone(false); fx->setName(fxOrig->getName()); fx->getAttributes()->setId(fxOrig->getAttributes()->getId()); fx->getAttributes()->passiveCacheDataIdx() = -1; if (resetFxDagPositions) fx->getAttributes()->setDagNodePos(TConst::nowhere); } m_fxTable[fxOrig] = fx; fx->addRef(); m_fxs.insert(fx); if (isColumnSelectionTerminalFx( fxOrig, xsh->getFxDag()->getTerminalFxs(), m_originalColumnFxs)) { fx->addRef(); m_terminalFxs.insert(fx); } if (fxOrig->getLinkedFx() != fxOrig) // Linked fx { if (!canGenerate(m_originalColumnFxs, fxOrig->getLinkedFx())) fx->linkParams(fxOrig->getLinkedFx()); else { // Insert the linked fx directly here TFx *linkedFx, *oldLinkedFx = fxOrig->getLinkedFx(); if (doClone) { linkedFx = fx->clone(false); // Not oldLinkedFx->clone() ? linkedFx->linkParams(fx); linkedFx->setName(oldLinkedFx->getName()); linkedFx->getAttributes()->setId(oldLinkedFx->getAttributes()->getId()); linkedFx->getAttributes()->passiveCacheDataIdx() = -1; if (resetFxDagPositions) fx->getAttributes()->setDagNodePos(TConst::nowhere); // Here too ? xsh->getFxDag()->assignUniqueId(linkedFx); } else linkedFx = oldLinkedFx; m_fxTable[oldLinkedFx] = linkedFx; linkedFx->addRef(); m_fxs.insert(linkedFx); if (xsh->getFxDag()->getTerminalFxs()->containsFx(fx->getLinkedFx())) // Here too - isATerminal ? { linkedFx->addRef(); m_terminalFxs.insert(linkedFx); } } } } // Like in the functions above, update links if (!m_fxTable.empty() && doClone) updateFxLinks(m_fxTable); }
std::vector<TStageObjectId> StageObjectsData::restoreObjects(std::set<int> &columnIndices, std::list<int> &restoredSpline, TXsheet *xsh, int fxFlags, const TPointD &pos) const { bool doClone = (fxFlags & eDoClone); bool resetFxDagPositions = (fxFlags & eResetFxDagPositions); QMap<TStageObjectId, TStageObjectId> idTable; // Trace stored/restored id pairings std::map<TFx *, TFx *> fxTable; // Same for fxs here std::vector<TStageObjectId> restoredIds; std::set<int>::iterator idxt = columnIndices.begin(); int index = -1; // The actual column insertion index int i, elementsCount = m_elements.size(); for (i = 0; i < elementsCount; ++i) { TStageObjectDataElement *element = m_elements[i]; TCameraDataElement *cameraElement = dynamic_cast<TCameraDataElement *>(element); TColumnDataElement *columnElement = dynamic_cast<TColumnDataElement *>(element); // Restore the object depending on its specific type TStageObjectId restoredId = TStageObjectId::NoneId; if (!cameraElement && !columnElement) restoredId = element->restoreObject(xsh, pos != TConst::nowhere); else if (cameraElement) restoredId = cameraElement->restoreCamera(xsh, pos != TConst::nowhere); else if (columnElement) { // Build the column insertion index if (idxt != columnIndices.end()) index = *idxt++; else { ++index; columnIndices.insert(index); } // Restore the column element restoredId = columnElement->restoreColumn(xsh, index, fxFlags, pos != TConst::nowhere); FxDag *fxDag = xsh->getFxDag(); TXshColumn *column = columnElement->m_column.getPointer(); TXshColumn *pastedColumn = xsh->getColumn(index); TFx *fx = column->getFx(); TFx *pastedFx = pastedColumn->getFx(); if (fx && pastedFx) fxTable[fx] = pastedFx; // Enforce the correct terminality. Added columns are terminal by default. bool terminal = (fx && (m_terminalFxs.count(fx) > 0)); if (!terminal) fxDag->getTerminalFxs()->removeFx(pastedFx); // In case we've cloned a zerary fx column, update the actual fx's data if (TXshZeraryFxColumn *zc = dynamic_cast<TXshZeraryFxColumn *>(pastedColumn)) { TZeraryColumnFx *zfx = zc->getZeraryColumnFx(); TFx *zeraryFx = zfx->getZeraryFx(); if (zeraryFx && doClone) { std::wstring app = zeraryFx->getName(); fxDag->assignUniqueId(zeraryFx); zeraryFx->setName(app); } } } // Remember stored/restored stage object pairings idTable[element->m_params->m_id] = restoredId; restoredIds.push_back(restoredId); } // Apply stage object-parental relationships for (i = 0; i < elementsCount; ++i) { TStageObjectDataElement *element = m_elements[i]; TStageObjectId id = element->m_params->m_id; TStageObjectId parentId = element->m_params->m_parentId; TStageObjectId pastedId = idTable[id]; TStageObjectId pastedParentId = parentId; if (parentId.isColumn()) // Why discriminating for columns only ? { //Columns are redirected to table ids. If no redirected parent exists, store //a void value that will be avoided later QMap<TStageObjectId, TStageObjectId>::iterator it = idTable.find(parentId); pastedParentId = (it == idTable.end()) ? TStageObjectId::NoneId : it.value(); } if (pastedParentId != TStageObjectId::NoneId) { xsh->setStageObjectParent(pastedId, pastedParentId); TStageObject *pastedObj = xsh->getStageObject(pastedId); // Shouldn't these be done outside ? pastedObj->setHandle(element->m_params->m_handle); pastedObj->setParentHandle(element->m_params->m_parentHandle); } } // Iterate stored fxs std::set<TFx *>::const_iterator fxt, end = m_fxs.end(); for (fxt = m_fxs.begin(); fxt != end; ++fxt) { TFx *fxOrig = *fxt, *fx = fxOrig; // Only NOT COLUMN fxs - ie internal fxs if (fxTable.find(fxOrig) != fxTable.end()) continue; // Internal fxs if (doClone) { fx = fxOrig->clone(false); fx->setName(fxOrig->getName()); fx->getAttributes()->setId(fxOrig->getAttributes()->getId()); fx->getAttributes()->passiveCacheDataIdx() = -1; if (resetFxDagPositions) fx->getAttributes()->setDagNodePos(TConst::nowhere); xsh->getFxDag()->assignUniqueId(fx); } fxTable[fxOrig] = fx; // Insert the passed fx in the xsheet TOutputFx *outFx = dynamic_cast<TOutputFx *>(fx); if (!outFx) xsh->getFxDag()->getInternalFxs()->addFx(fx); else xsh->getFxDag()->addOutputFx(outFx); if (m_terminalFxs.count(fxOrig) > 0) xsh->getFxDag()->getTerminalFxs()->addFx(fx); if (!doClone) { // Err.... don't remember. Inquire further? :| int fxTypeCount = xsh->getFxDag()->getFxTypeCount(fx); int maxFxTypeId = std::max(fxTypeCount, fx->getAttributes()->getId()); xsh->getFxDag()->updateFxTypeTable(fx, maxFxTypeId); xsh->getFxDag()->updateFxIdTable(fx); } bool isLinked = (fxOrig->getLinkedFx() != fxOrig); if (isLinked) { if (m_fxs.find(fxOrig->getLinkedFx()) == m_fxs.end()) fx->linkParams(fxOrig->getLinkedFx()); else { TFx *linkedFx, *oldLinkedFx = fxOrig->getLinkedFx(); if (doClone) { // Clone the linked fx too linkedFx = fx->clone(false); linkedFx->linkParams(fx); linkedFx->setName(oldLinkedFx->getName()); linkedFx->getAttributes()->setId(oldLinkedFx->getAttributes()->getId()); linkedFx->getAttributes()->passiveCacheDataIdx() = -1; if (resetFxDagPositions) linkedFx->getAttributes()->setDagNodePos(TConst::nowhere); else linkedFx->getAttributes()->setDagNodePos(oldLinkedFx->getAttributes()->getDagNodePos()); xsh->getFxDag()->assignUniqueId(linkedFx); } else linkedFx = oldLinkedFx; fxTable[oldLinkedFx] = linkedFx; xsh->getFxDag()->getInternalFxs()->addFx(linkedFx); if (m_terminalFxs.count(oldLinkedFx) > 0) xsh->getFxDag()->getTerminalFxs()->addFx(linkedFx); if (!doClone) { int fxTypeCount = xsh->getFxDag()->getFxTypeCount(linkedFx); int maxFxTypeId = std::max(fxTypeCount, linkedFx->getAttributes()->getId()); xsh->getFxDag()->updateFxTypeTable(linkedFx, maxFxTypeId); xsh->getFxDag()->updateFxIdTable(linkedFx); } } } } // Update the link, like in functions above if (!fxTable.empty() && doClone) updateFxLinks(fxTable); // Paste any associated spline (not stored im m_splines) std::map<TStageObjectSpline *, TStageObjectSpline *> splines; for (i = 0; i < (int)restoredIds.size(); ++i) { TStageObjectId id = restoredIds[i]; TStageObject *obj = xsh->getStageObject(id); TStageObjectSpline *spline = obj->getSpline(); if (!spline) continue; TStageObjectTree *objTree = xsh->getStageObjectTree(); if (objTree->containsSpline(spline)) // No need to add it if it's already there continue; std::map<TStageObjectSpline *, TStageObjectSpline *>::iterator it = splines.find(spline); if (it != splines.end()) { // Seems that multiple objects can have the same spline... // BTW, shouldn't this case stop at the continue before ? obj->setSpline(it->second); continue; } // The spline was not found. Clone and add it to the xsheet TStageObjectSpline *newSpline = spline->clone(); // Not checking doClone ? objTree->assignUniqueSplineId(newSpline); objTree->insertSpline(newSpline); obj->setSpline(newSpline); splines[spline] = newSpline; } //paste stored path QList<TSplineDataElement *>::const_iterator splinIt; for (splinIt = m_splines.begin(); splinIt != m_splines.end(); ++splinIt) { TStageObjectTree *objTree = xsh->getStageObjectTree(); TSplineDataElement *splineEl = *splinIt; TStageObjectSpline *spline = splineEl->restoreSpline(fxFlags); if (doClone) objTree->assignUniqueSplineId(spline); objTree->insertSpline(spline); restoredSpline.push_back(spline->getId()); } xsh->updateFrameCount(); if (pos != TConst::nowhere) { // Update objects positions depending on the externally supplied pos TPointD middlePos; int count = 0; for (i = 0; i < (int)restoredIds.size(); ++i) { TStageObjectId id = restoredIds[i]; TStageObject *obj = xsh->getStageObject(id); TPointD oldPos = obj->getDagNodePos(); if (oldPos == TConst::nowhere) continue; middlePos += oldPos; ++count; } middlePos = TPointD(middlePos.x / count, middlePos.y / count); TPointD offset = pos - middlePos; for (i = 0; i < (int)restoredIds.size(); ++i) { TStageObjectId id = restoredIds[i]; TStageObject *obj = xsh->getStageObject(id); TPointD oldPos = obj->getDagNodePos(); if (oldPos == TConst::nowhere) continue; obj->setDagNodePos(oldPos + offset); } } return restoredIds; }