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);
}
Esempio n. 3
0
//!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;
		}
	}
}
Esempio n. 4
0
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();
}
Esempio n. 5
0
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);
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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;
}
Esempio n. 11
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;
}
Esempio n. 12
0
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") {
Esempio n. 13
0
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();
}
Esempio n. 14
0
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);
	}
}
Esempio n. 16
0
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);
   }
 }
Esempio n. 19
0
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();
}
Esempio n. 20
0
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);
  }
}
Esempio n. 21
0
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;
}
Esempio n. 22
0
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;
  }
}
Esempio n. 23
0
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> &currentPair = 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();
}
Esempio n. 24
0
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);
		}
	}
}
Esempio n. 25
0
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
}
Esempio n. 26
0
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;
}
Esempio n. 27
0
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);
}
Esempio n. 28
0
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;
}