コード例 #1
0
ファイル: xshcellmover.cpp プロジェクト: SaierMe/opentoonz
bool CellsMover::canMoveCells(const TPoint &pos) {
  TXsheet *xsh = getXsheet();
  if (pos.x < 0) return false;
  if (pos.x != m_startPos.x) {
    int count = 0;
    // controlla il tipo
    int i = 0;
    while (i < m_rowCount * m_colCount) {
      TXshColumn::ColumnType srcType = getColumnTypeFromCell(i);
      int dstIndex                   = pos.x + i;
      TXshColumn *dstColumn          = xsh->getColumn(dstIndex);
      if (srcType == TXshColumn::eZeraryFxType) return false;
      if (dstColumn && !dstColumn->isEmpty() &&
          dstColumn->getColumnType() != srcType)
        return false;
      if (!dstColumn || dstColumn->isLocked() == false) count++;
      i += m_rowCount;
    }
    if (count == 0) return false;
  }
  if ((m_qualifiers & CellsMover::eInsertCells) ||
      (m_qualifiers & CellsMover::eOverwriteCells))
    return true;
  int count = 0;
  for (int i = 0; i < m_colCount; i++) {
    for (int j = 0; j < m_rowCount; j++) {
      if (!xsh->getCell(pos.y + j, pos.x + i).isEmpty()) return false;
      count++;
    }
  }
  if (count == 0) return false;
  return true;
}
コード例 #2
0
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);
}
コード例 #3
0
int addShowHideStageObjectCmds(const std::vector<int> &columnIndexes,
                               QMenu *menu, bool isShow) {
  int ii, columnIndex = -1;
  bool flag = true;

  for (ii = columnIndexes.size() - 1; ii >= 0; ii--) {
    TStageObjectId id = TStageObjectId::ColumnId(columnIndexes[ii]);
    TXshColumn *col =
        TApp::instance()->getCurrentXsheet()->getXsheet()->getColumn(
            columnIndexes[ii]);
    if (!col) continue;
    if (!isShow && col->isCamstandVisible()) {
      if (columnIndex == -1) columnIndex = columnIndexes[ii];
      if (flag) {
        menu->addSeparator();
        flag = false;
      }
      addShowHideStageObjectCmd(menu, id, false);
    } else if (isShow && !col->isCamstandVisible()) {
      if (flag) {
        menu->addSeparator();
        flag = false;
      }
      addShowHideStageObjectCmd(menu, id, true);
    }
  }
  return columnIndex;
}
コード例 #4
0
ファイル: columncommand.cpp プロジェクト: opentoonz/opentoonz
void ColumnCmd::resequence(int index) {
  if (!canResequence(index)) return;
  TXsheet *xsh       = TApp::instance()->getCurrentXsheet()->getXsheet();
  TXshColumn *column = xsh->getColumn(index);
  assert(column);
  TXshLevelColumn *lcolumn = column->getLevelColumn();
  assert(lcolumn);
  int r0 = 0, r1 = -1;
  lcolumn->getRange(r0, r1);
  assert(r0 <= r1);
  TXshCell cell = lcolumn->getCell(r0);
  assert(!cell.isEmpty());
  TXshChildLevel *xl = cell.m_level->getChildLevel();
  assert(xl);
  TXsheet *childXsh              = xl->getXsheet();
  int frameCount                 = childXsh->getFrameCount();
  if (frameCount < 1) frameCount = 1;

  TUndoManager::manager()->add(new ResequenceUndo(index, frameCount));

  lcolumn->clearCells(r0, r1 - r0 + 1);
  for (int i = 0; i < frameCount; i++) {
    cell.m_frameId = TFrameId(i + 1);
    lcolumn->setCell(r0 + i, cell);
  }

  xsh->updateFrameCount();

  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
}
コード例 #5
0
ファイル: xshrowviewer.cpp プロジェクト: CroW-CZ/opentoonz
void RowArea::mousePressEvent(QMouseEvent *event)
{
	m_viewer->setQtModifiers(event->modifiers());
	if (event->button() == Qt::LeftButton) {
		bool playRangeModifierisClicked = false;

		TApp *app = TApp::instance();
		TXsheet *xsh = app->getCurrentScene()->getScene()->getXsheet();
		TPoint pos(event->pos().x(), event->pos().y());

		int row = m_viewer->yToRow(pos.y);

		QRect visibleRect = visibleRegion().boundingRect();
		int playR0, playR1, step;
		XsheetGUI::getPlayRange(playR0, playR1, step);

		bool playRangeEnabled = playR0 <= playR1;
		if (!playRangeEnabled) {
			TXsheet *xsh = m_viewer->getXsheet();
			playR1 = xsh->getFrameCount() - 1;
			playR0 = 0;
		}

		if (playR1 == -1) { //getFrameCount = 0 i.e. xsheet is empty
			setDragTool(XsheetGUI::DragTool::makeCurrentFrameModifierTool(m_viewer));
		} else if (m_xa <= pos.x && pos.x <= m_xa + 10 && (row == playR0 || row == playR1)) {
			if (!playRangeEnabled)
				XsheetGUI::setPlayRange(playR0, playR1, step);
			setDragTool(XsheetGUI::DragTool::makePlayRangeModifierTool(m_viewer));
			playRangeModifierisClicked = true;
		} else
			setDragTool(XsheetGUI::DragTool::makeCurrentFrameModifierTool(m_viewer));

		//when shift+click the row area, select a single row region in the cell area
		if (!playRangeModifierisClicked && 0 != (event->modifiers() & Qt::ShiftModifier)) {
			int filledCol;
			for (filledCol = xsh->getColumnCount() - 1; filledCol >= 0; filledCol--) {
				TXshColumn *currentColumn = xsh->getColumn(filledCol);
				if (!currentColumn)
					continue;
				if (!currentColumn->isEmpty())
					break;
			}

			m_viewer->getCellSelection()->selectNone();
			m_viewer->getCellSelection()->selectCells(row, 0, row, tmax(0, filledCol));
			m_viewer->updateCellRowAree();
		}

		m_viewer->dragToolClick(event);
		event->accept();
	} // left-click
	// pan by middle-drag
	else if (event->button() == Qt::MidButton) {
		m_pos = event->pos();
		m_isPanning = true;
	}
}
コード例 #6
0
ファイル: xshcellmover.cpp プロジェクト: SaierMe/opentoonz
void CellsMover::getCells(std::vector<TXshCell> &cells, int r, int c) const {
  for (int i = 0; i < (int)cells.size(); i++) cells[i] = TXshCell();
  TXsheet *xsh                                         = getXsheet();
  for (int i = 0; i < m_colCount; i++) {
    TXshColumn *column = xsh->getColumn(c + i);
    if (column && column->isLocked()) continue;
    xsh->getCells(r, c + i, m_rowCount, &cells[m_rowCount * i]);
  }
}
コード例 #7
0
ファイル: txsheet.cpp プロジェクト: walkerka/opentoonz
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;
}
コード例 #8
0
void SceneViewerContextMenu::onShowHide() {
  int columnIndex = qobject_cast<QAction *>(sender())->data().toInt();
  TXsheetHandle *xsheetHandle = TApp::instance()->getCurrentXsheet();
  TXshColumn *column = xsheetHandle->getXsheet()->getColumn(columnIndex);
  if (column) {
    column->setCamstandVisible(!column->isCamstandVisible());
    xsheetHandle->notifyXsheetChanged();
  }
}
コード例 #9
0
ファイル: xshcellmover.cpp プロジェクト: SaierMe/opentoonz
// isTotallyEmptyColumn == column empty, no fx
bool LevelMoverTool::isTotallyEmptyColumn(int col) const {
  if (col < 0) return false;
  TXsheet *xsh       = getViewer()->getXsheet();
  TXshColumn *column = xsh->getColumn(col);
  if (!column) return true;
  if (!column->isEmpty()) return false;
  if (column->getFx()->getOutputConnectionCount() != 0) return false;
  // bisogna controllare lo stage object
  return true;
}
コード例 #10
0
ファイル: xshcellmover.cpp プロジェクト: SaierMe/opentoonz
//
// xsheet <- cells
//
void CellsMover::setCells(const std::vector<TXshCell> &cells, int r,
                          int c) const {
  TXsheet *xsh = getXsheet();
  for (int i = 0; i < m_colCount; i++) {
    TXshColumn *column = xsh->getColumn(c + i);
    if (column)  // skip if columns is locked or doesn't support cells operation
      if (column->getCellColumn() == 0 || column->isLocked()) continue;
    xsh->setCells(r, c + i, m_rowCount, &cells[m_rowCount * i]);
  }
}
コード例 #11
0
ファイル: keyframenavigator.cpp プロジェクト: luc--/opentoonz
TStageObject *ViewerKeyframeNavigator::getStageObject() const {
  if (!m_xsheetHandle || !m_objectHandle) return 0;

  TStageObjectId objectId = m_objectHandle->getObjectId();
  TXsheet *xsh            = m_xsheetHandle->getXsheet();
  // Se e' una colonna sound non posso settare chiavi
  if (objectId.isColumn()) {
    TXshColumn *column = xsh->getColumn(objectId.getIndex());
    if (column && column->getSoundColumn()) return 0;
  }
  return xsh->getStageObject(objectId);
}
コード例 #12
0
ファイル: skeletontool.cpp プロジェクト: titer1/opentoonz
bool SkeletonTool::doesApply() const
{
	TTool::Application *app = TTool::getApplication();
	TXsheet *xsh = app->getCurrentXsheet()->getXsheet();
	assert(xsh);
	TStageObjectId objId = app->getCurrentObject()->getObjectId();
	if (objId.isColumn()) {
		TXshColumn *column = xsh->getColumn(objId.getIndex());
		if (column && column->getSoundColumn())
			return false;
	}
	return true;
}
コード例 #13
0
ファイル: layerheaderpanel.cpp プロジェクト: jcome/opentoonz
void LayerHeaderPanel::mouseReleaseEvent(QMouseEvent *event) {
  TApp *app    = TApp::instance();
  TXsheet *xsh = m_viewer->getXsheet();
  int col, totcols = xsh->getColumnCount();
  bool sound_changed = false;

  if (m_doOnRelease != 0 && totcols > 0) {
    for (col = 0; col < totcols; col++) {
      if (!xsh->isColumnEmpty(col)) {
        TXshColumn *column = xsh->getColumn(col);

        if (m_doOnRelease == ToggleAllPreviewVisible) {
          column->setPreviewVisible(!column->isPreviewVisible());
        } else if (m_doOnRelease == ToggleAllTransparency) {
          column->setCamstandVisible(!column->isCamstandVisible());
          if (column->getSoundColumn()) sound_changed = true;
        } else if (m_doOnRelease == ToggleAllLock) {
          column->lock(!column->isLocked());
        }
      }
    }

    if (sound_changed) {
      app->getCurrentXsheet()->notifyXsheetSoundChanged();
    }

    app->getCurrentScene()->notifySceneChanged();
    app->getCurrentXsheet()->notifyXsheetChanged();
  }
  m_viewer->updateColumnArea();
  update();
  m_doOnRelease = 0;
}
コード例 #14
0
ファイル: stage.cpp プロジェクト: ideasman42/opentoonz
    static inline bool isMeshDeformed(TXsheet *xsh, TStageObject *obj,
                                      const ImagePainter::VisualSettings *vs) {
      const TStageObjectId &parentId = obj->getParent();
      if (parentId.isColumn() && obj->getParentHandle()[0] != 'H') {
        TStageObject *parentObj = xsh->getStageObject(parentId);
        if (!parentObj->getPlasticSkeletonDeformation()) return false;

        TXshColumn *parentCol = xsh->getColumn(parentId.getIndex());
        return (parentCol->getColumnType() == TXshColumn::eMeshType) &&
               (parentCol != vs->m_plasticVisualSettings.m_showOriginalColumn);
      }

      return false;
    }
コード例 #15
0
ファイル: xshcellmover.cpp プロジェクト: SaierMe/opentoonz
//
// xsheet <- m_cells; insert cells if qualifiers contain eInsertCells
//
void CellsMover::moveCells(const TPoint &pos) const {
  int r        = pos.y;
  int c        = pos.x;
  TXsheet *xsh = getXsheet();
  if (m_qualifiers & eInsertCells) {
    for (int i = 0; i < m_colCount; i++) {
      TXshColumn *column = xsh->getColumn(c + i);
      if (column) {
        if (column->getCellColumn() == 0 || column->isLocked()) continue;
        xsh->insertCells(r, c + i, m_rowCount);
      }
    }
  }
  setCells(m_cells, r, c);
}
コード例 #16
0
ファイル: txsheet.cpp プロジェクト: walkerka/opentoonz
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") {
コード例 #17
0
void SchematicViewer::updateScenes() {
  TStageObjectId id = m_stageScene->getCurrentObject();
  if (id.isColumn()) {
    m_stageScene->update();
    TXsheet *xsh = m_stageScene->getXsheetHandle()->getXsheet();
    if (!xsh) return;
    TXshColumn *column = xsh->getColumn(id.getIndex());
    if (!column) {
      m_fxScene->getFxHandle()->setFx(0, false);
      return;
    }
    TFx *fx = column->getFx();
    m_fxScene->getFxHandle()->setFx(fx, false);
    m_fxScene->update();
  }
}
コード例 #18
0
ファイル: fxdata.cpp プロジェクト: Makoto-Sasahara/opentoonz
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);
}
コード例 #19
0
ファイル: xshcellmover.cpp プロジェクト: SaierMe/opentoonz
bool LevelMoverTool::canMoveColumns(const TPoint &pos) {
  TXsheet *xsh = getViewer()->getXsheet();
  if (pos.x < 0) return false;
  if (pos.x != m_lastPos.x) {
    int count = 0;
    // controlla il tipo
    for (int i = 0; i < m_range.lx; i++) {
      int srcIndex          = m_lastPos.x + i;
      int dstIndex          = pos.x + i;
      TXshColumn *srcColumn = xsh->getColumn(srcIndex);
      if (srcColumn && srcColumn->isLocked()) continue;
      TXshColumn *dstColumn          = xsh->getColumn(dstIndex);
      TXshColumn::ColumnType srcType = TXshColumn::eLevelType;
      if (srcColumn) srcType         = srcColumn->getColumnType();
      if (srcType == TXshColumn::eZeraryFxType) return false;
      /*
qDebug() << "check: " << srcIndex << ":" <<
(srcColumn ? QString::number(srcType) : "empty") <<
" => " << dstIndex << ":" <<
(dstColumn ? QString::number(dstColumn->getColumnType()) : "empty");
*/

      if (dstColumn && !dstColumn->isEmpty() &&
          dstColumn->getColumnType() != srcType) {
        return false;
      }
      if (!dstColumn || dstColumn->isLocked() == false) {
        count++;
      }
    }
    if (count == 0) return false;
  }
  return true;
}
コード例 #20
0
TStageObjectId TColumnDataElement::restoreColumn(TXsheet *xsh, int index, int fxFlags, bool copyPosition) const
{
	bool doClone = (fxFlags & eDoClone);
	bool resetFxDagPositions = (fxFlags & eResetFxDagPositions);

	TXshColumn *column = m_column.getPointer();

	// The xsheet 'changes' if a new column is inserted. If it was already there, no.
	bool xsheetChange = false;
	if (column && column->getXsheet() && column->getXsheet() != xsh)
		xsheetChange = true;

	// Insert a column at the specified index. If a column was stored, insert that one.
	TPointD dagPos = TConst::nowhere;
	if (column) {
		if (column->getFx())
			dagPos = column->getFx()->getAttributes()->getDagNodePos();
		if (doClone)
			column = column->clone();
		xsh->insertColumn(index, column);
	} else
		xsh->insertColumn(index); // Create a new one otherwise

	if (!resetFxDagPositions && dagPos != TConst::nowhere) {
		// Don't accept the default position (fx object)
		TXshColumn *restoredColumn = xsh->getColumn(index);
		restoredColumn->getFx()->getAttributes()->setDagNodePos(dagPos);
	}

	// Retrieve the newly inserted column stage object
	TStageObject *obj = xsh->getStageObject(TStageObjectId::ColumnId(index));
	assert(obj);
	obj->assignParams(m_params, doClone); // Assign the stored params

	if (copyPosition)
		obj->setDagNodePos(m_dagPos);

	// Clone the associated curve if any
	if (xsheetChange && obj->getSpline()) {
		TStageObjectSpline *srcSpl = obj->getSpline();
		TStageObjectSpline *dstSpl = xsh->getStageObjectTree()->createSpline();
		dstSpl->addRef();
		dstSpl->setStroke(new TStroke(*srcSpl->getStroke()));
		obj->setSpline(dstSpl);
	}

	int gridType = xsh->getStageObjectTree()->getDagGridDimension();
	obj->setIsOpened(gridType == 0); // gridType is 0 if the node is opened, 1 if closed
									 // see StageSchematicScene::GridDimension
									 // TODO: Should be made PUBLIC!!

	xsh->updateFrameCount();
	return obj->getId();
}
コード例 #21
0
ファイル: xshcellmover.cpp プロジェクト: SaierMe/opentoonz
void CellsMover::restoreColumns(int c) const {
  std::set<int> ii;
  for (int i   = 0; i < m_colCount; i++) ii.insert(c + i);
  TXsheet *xsh = getXsheet();
  for (int i = 0; i < m_colCount; i++) xsh->removeColumn(c);
  std::list<int> restoredSplineIds;
  m_columnsData->restoreObjects(
      ii, restoredSplineIds, xsh,
      StageObjectsData::eDoClone | StageObjectsData::eResetFxDagPositions);
  for (int i = 0; i < m_colCount; i++) {
    TXshColumn *column = xsh->getColumn(c + i);
    if (!column) continue;
    TXshCellColumn *cellColumn = column->getCellColumn();
    if (!cellColumn) continue;
    int r0 = 0, r1 = -1;
    cellColumn->getRange(r0, r1);
    if (r0 <= r1) cellColumn->clearCells(r0, r1 - r0 + 1);
  }
}
コード例 #22
0
ファイル: comboviewerpane.cpp プロジェクト: luc--/opentoonz
void ComboViewerPanel::onDrawFrame(
    int frame, const ImagePainter::VisualSettings &settings) {
  TApp *app = TApp::instance();
  m_sceneViewer->setVisual(settings);
  TFrameHandle *frameHandle = app->getCurrentFrame();

  if (m_sceneViewer->isPreviewEnabled()) {
    class Previewer *pr = Previewer::instance(m_sceneViewer->getPreviewMode() ==
                                              SceneViewer::SUBCAMERA_PREVIEW);

    pr->getRaster(frame - 1);  // the 'getRaster' starts the render of the frame
                               // is not already started
    int curFrame = frame;
    if (frameHandle->isPlaying() &&
        !pr->isFrameReady(
            frame - 1))  // stops on last rendered frame until current is ready!
    {
      while (frame > 0 && !pr->isFrameReady(frame - 1)) frame--;
      if (frame == 0)
        frame = curFrame;  // if no frame is ready, I stay on current...no use
                           // to rewind
      m_flipConsole->setCurrentFrame(frame);
    }
  }

  assert(frame >= 0);
  if (frame != frameHandle->getFrameIndex() + 1) {
    if (frameHandle->isEditingScene()) {
      TXshColumn *column = app->getCurrentXsheet()->getXsheet()->getColumn(
          app->getCurrentColumn()->getColumnIndex());
      if (column) {
        TXshSoundColumn *soundColumn = column->getSoundColumn();
        if (soundColumn && !soundColumn->isPlaying())
          app->getCurrentFrame()->scrubColumn(frame, frame, soundColumn);
      }
    }
    frameHandle->setCurrentFrame(frame);
  }

  else if (settings.m_blankColor != TPixel::Transparent)
    m_sceneViewer->update();
}
コード例 #23
0
ファイル: columncommand.cpp プロジェクト: opentoonz/opentoonz
bool ColumnCmd::canResequence(int index) {
  TXsheet *xsh       = TApp::instance()->getCurrentXsheet()->getXsheet();
  TXshColumn *column = xsh->getColumn(index);
  if (!column) return false;
  TXshLevelColumn *lcolumn = column->getLevelColumn();
  if (!lcolumn) return false;
  int r0 = 0, r1 = -1;
  if (lcolumn->getRange(r0, r1) == 0) return false;
  assert(r0 <= r1);
  TXshCell cell = lcolumn->getCell(r0);
  assert(!cell.isEmpty());
  TXshLevel *xl = cell.m_level->getChildLevel();
  if (!xl) return false;
  for (int r = r0 + 1; r <= r1; r++) {
    cell = lcolumn->getCell(r);
    if (cell.isEmpty()) continue;
    if (cell.m_level.getPointer() != xl) return false;
  }
  return true;
}
コード例 #24
0
// data -> xsh
bool TKeyframeData::getKeyframes(std::set<Position> &positions, TXsheet *xsh) const
{
	std::set<TKeyframeSelection::Position>::iterator it2 = positions.begin();
	int r0 = it2->first;
	int c0 = it2->second;
	for (++it2; it2 != positions.end(); ++it2) {
		r0 = std::min(r0, it2->first);
		c0 = std::min(c0, it2->second);
	}
	positions.clear();
	TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId();
	Iterator it;
	bool keyFrameChanged = false;
	for (it = m_keyData.begin(); it != m_keyData.end(); ++it) {
		Position pos = it->first;
		int row = r0 + pos.first;
		int col = c0 + pos.second;
		positions.insert(std::make_pair(row, col));
		TXshColumn *column = xsh->getColumn(col);
		if (column && column->getSoundColumn())
			continue;
		TStageObject *pegbar = xsh->getStageObject(col >= 0 ? TStageObjectId::ColumnId(col) : cameraId);
		if (pegbar->getId().isColumn() && xsh->getColumn(col) && xsh->getColumn(col)->isLocked())
			continue;
		keyFrameChanged = true;
		assert(pegbar);
		pegbar->setKeyframeWithoutUndo(row, it->second);
	}
	if (!keyFrameChanged)
		return false;

	for (auto const pegbar : m_isPegbarsCycleEnabled) {
		int const col = pegbar.first;
		TStageObjectId objectId = (col >= 0) ? TStageObjectId::ColumnId(col) : cameraId;
		xsh->getStageObject(objectId)->enableCycle(pegbar.second);
	}
	return true;
}
コード例 #25
0
ファイル: fxdata.cpp プロジェクト: Makoto-Sasahara/opentoonz
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();
}
コード例 #26
0
ファイル: xshcellmover.cpp プロジェクト: SaierMe/opentoonz
void LevelMoverTool::onCellChange(int row, int col) {
  TXsheet *xsh = getViewer()->getXsheet();

  TPoint pos           = TPoint(col, row) + m_grabOffset;
  if (pos.y < 0) pos.y = 0;
  if (pos.x < 0) return;
  if (pos == m_aimedPos) return;

  m_aimedPos   = pos;
  TPoint delta = m_aimedPos - m_lastPos;

  m_validPos = canMoveColumns(pos);
  if (!m_validPos) return;

  CellsMover *cellsMover = m_undo->getCellsMover();
  if (m_moved) cellsMover->undoMoveCells();
  m_validPos = canMove(pos);

  if (m_validPos) {
    //----------------------
    if (delta.x != 0 && (m_qualifiers & CellsMover::eMoveColumns)) {
      // spostamento di colonne
      int colCount = m_range.lx;

      bool emptySrc = true;
      for (int i = 0; i < colCount; i++) {
        TXshColumn *column = xsh->getColumn(m_lastPos.x + i);
        if (column && !column->isEmpty()) {
          emptySrc = false;
          break;
        }
      }

      bool lockedDst = false;
      bool emptyDst  = true;
      for (int i = 0; i < colCount; i++) {
        if (!isTotallyEmptyColumn(pos.x + i)) emptyDst = false;
        TXshColumn *column                          = xsh->getColumn(pos.x + i);
        if (column && column->isLocked()) lockedDst = true;
      }

      if (emptySrc) {
        if (m_lastPos.x == m_startPos.x)
          m_undo->getCellsMover()->m_uffa |=
              1;  // first column(s) has/have been cleared
        cellsMover->emptyColumns(m_lastPos.x);
      }

      if (emptyDst && !lockedDst) {
        if (pos.x == m_startPos.x)
          m_undo->getCellsMover()->m_uffa &=
              ~1;  // first column(s) has/have been restored
        else
          m_undo->getCellsMover()->m_uffa |=
              2;  // columns data have been copied on the current position
        cellsMover->restoreColumns(pos.x);
      } else {
        m_undo->getCellsMover()->m_uffa &=
            ~2;  // no columns data have been copied on the current position
      }
    }

    //----------------------

    m_lastPos = pos;
    cellsMover->setPos(pos.y, pos.x);
    cellsMover->saveCells();
    cellsMover->moveCells();
    m_moved = true;
  } else {
    cellsMover->moveCells();
  }

  xsh->updateFrameCount();
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
  if (cellsMover->getColumnTypeFromCell(0) == TXshColumn::eSoundType)
    TApp::instance()->getCurrentXsheet()->notifyXsheetSoundChanged();
  TRect selection(m_aimedPos, m_range);
  getViewer()->getCellSelection()->selectCells(selection.y0, selection.x0,
                                               selection.y1, selection.x1);
}
コード例 #27
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);
		}
	}
}
コード例 #28
0
ファイル: columncommand.cpp プロジェクト: opentoonz/opentoonz
  void execute() override {
    TColumnSelection *selection = dynamic_cast<TColumnSelection *>(
        TApp::instance()->getCurrentSelection()->getSelection());
    TXsheet *xsh       = TApp::instance()->getCurrentXsheet()->getXsheet();
    int cc             = TApp::instance()->getCurrentColumn()->getColumnIndex();
    bool sound_changed = false;
    TTool *tool        = TApp::instance()->getCurrentTool()->getTool();
    TTool::Viewer *viewer = tool ? tool->getViewer() : nullptr;
    bool viewer_changed   = false;

    for (int i = 0; i < xsh->getColumnCount(); i++) {
      /*- 空のカラムの場合は飛ばす -*/
      if (xsh->isColumnEmpty(i)) continue;
      /*- カラムが取得できなかったら飛ばす -*/
      TXshColumn *column = xsh->getColumn(i);
      if (!column) continue;
      /*- ターゲットが選択カラムのモードで、選択されていなかった場合は飛ばす -*/
      bool isSelected = selection && selection->isColumnSelected(i);
      if (m_target == TARGET_SELECTED && !isSelected) continue;

      /*-
       * ターゲットが「カレントカラムより右側」のモードで、iがカレントカラムより左の場合は飛ばす
       * -*/
      if (m_target == TARGET_UPPER && i < cc) continue;

      bool negate = m_target == TARGET_CURRENT && cc != i ||
                    m_target == TARGET_OTHER && cc == i ||
                    m_target == TARGET_UPPER && cc == i;

      int cmd = m_cmd;

      if (cmd & (CMD_LOCK | CMD_UNLOCK | CMD_TOGGLE_LOCK)) {
        if (cmd & CMD_LOCK)
          column->lock(!negate);
        else if (cmd & CMD_UNLOCK)
          column->lock(negate);
        else
          column->lock(!column->isLocked());
        viewer_changed = true;
      }
      if (cmd &
          (CMD_ENABLE_PREVIEW | CMD_DISABLE_PREVIEW | CMD_TOGGLE_PREVIEW)) {
        if (cmd & CMD_ENABLE_PREVIEW)
          column->setPreviewVisible(!negate);
        else if (cmd & CMD_DISABLE_PREVIEW)
          column->setPreviewVisible(negate);
        else
          column->setPreviewVisible(!column->isPreviewVisible());
      }
      if (cmd &
          (CMD_ENABLE_CAMSTAND | CMD_DISABLE_CAMSTAND | CMD_TOGGLE_CAMSTAND)) {
        if (cmd & CMD_ENABLE_CAMSTAND)
          column->setCamstandVisible(!negate);
        else if (cmd & CMD_DISABLE_CAMSTAND)
          column->setCamstandVisible(negate);
        else
          column->setCamstandVisible(!column->isCamstandVisible());
        if (column->getSoundColumn()) sound_changed = true;
        viewer_changed                              = true;
      }
      /*TAB
if(cmd & (CMD_ENABLE_PREVIEW|CMD_DISABLE_PREVIEW|CMD_TOGGLE_PREVIEW))
{ //In Tab preview e cameraStand vanno settati entrambi
if(cmd&CMD_ENABLE_PREVIEW)
{
column->setPreviewVisible(!negate);
column->setCamstandVisible(!negate);
}
else if(cmd&CMD_DISABLE_PREVIEW)
{
column->setPreviewVisible(negate);
column->setCamstandVisible(negate);
}
else
{
column->setPreviewVisible(!column->isPreviewVisible());
column->setCamstandVisible(!column->isCamstandVisible());
}
}
      */
    }
    if (sound_changed)
      TApp::instance()->getCurrentXsheet()->notifyXsheetSoundChanged();
    TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
    TApp::instance()->getCurrentScene()->setDirtyFlag(true);
    if (viewer && viewer_changed) viewer->invalidateToolStatus();
  }
コード例 #29
0
ファイル: columncommand.cpp プロジェクト: opentoonz/opentoonz
void ColumnCmd::cloneChild(int index) {
  if (!canResequence(index)) return;

  /*-- カラムを取得 --*/
  TXsheet *xsh       = TApp::instance()->getCurrentXsheet()->getXsheet();
  TXshColumn *column = xsh->getColumn(index);
  assert(column);

  // get the subxsheet to clone (childLevel, childXsh)
  /*-- SubXsheetレベルを取得 --*/
  TXshLevelColumn *lcolumn = column->getLevelColumn();
  assert(lcolumn);
  int r0 = 0, r1 = -1;
  lcolumn->getRange(r0, r1);
  assert(r0 <= r1);
  /*-- SubXsheetの一番頭のセル --*/
  TXshCell cell = lcolumn->getCell(r0);
  assert(!cell.isEmpty());
  /*- cell内に格納されているLevelを取得 -*/
  TXshChildLevel *childLevel = cell.m_level->getChildLevel();
  assert(childLevel);
  /*- SubXsheetのXsheetを取得 -*/
  TXsheet *childXsh = childLevel->getXsheet();

  // insert a new empty column
  /*- 隣に空きColumnをInsertしてCloneに備える -*/
  int newColumnIndex = index + 1;
  xsh->insertColumn(newColumnIndex);

  // create a subxsheet (newChildLevel, newChildXsh)
  ToonzScene *scene      = TApp::instance()->getCurrentScene()->getScene();
  ChildStack *childStack = scene->getChildStack();
  TXshChildLevel *newChildLevel = childStack->createChild(0, newColumnIndex);
  TXsheet *newChildXsh          = newChildLevel->getXsheet();

  // copy columns.
  std::set<int> indices;
  for (int i = 0; i < childXsh->getColumnCount(); i++) indices.insert(i);
  StageObjectsData *data = new StageObjectsData();
  data->storeColumns(indices, childXsh, 0);
  data->storeColumnFxs(indices, childXsh, 0);
  std::list<int> restoredSplineIds;
  data->restoreObjects(indices, restoredSplineIds, newChildXsh,
                       StageObjectsData::eDoClone);
  delete data;

  cloneNotColumnLinkedFxsAndOutputsFx(childXsh, newChildXsh);
  cloneXsheetTStageObjectTree(childXsh, newChildXsh);
  /*--以下は、Clone SubXsheet
  するときに、SubXsheet内にある子SubXsheetをクローンする関数
  クローンされた中にある子SubXsheetは、同じもので良いので、スキップする --*/
  // cloneSubXsheets(newChildXsh);

  /*-- XSheetノードのFxSchematicでのDagNodePosを再現
  FxやColumnノードの位置の再現は上のsetColumnで行っている
--*/
  newChildXsh->getFxDag()->getXsheetFx()->getAttributes()->setDagNodePos(
      childXsh->getFxDag()->getXsheetFx()->getAttributes()->getDagNodePos());

  newChildXsh->updateFrameCount();

  /*-- TXshChildLevel作成時にsetCellした1つ目のセルを消去 --*/
  xsh->removeCells(0, newColumnIndex);
  /*-- CloneしたColumnのセル番号順を再現 --*/
  for (int r = r0; r <= r1; r++) {
    TXshCell cell = lcolumn->getCell(r);
    if (cell.isEmpty()) continue;

    cell.m_level = newChildLevel;
    xsh->setCell(r, newColumnIndex, cell);
  }

  TStageObjectId currentObjectId =
      TApp::instance()->getCurrentObject()->getObjectId();
  xsh->getStageObject(TStageObjectId::ColumnId(newColumnIndex))
      ->setParent(xsh->getStageObjectParent(currentObjectId));

  xsh->updateFrameCount();
  TUndoManager::manager()->add(
      new CloneChildUndo(newChildLevel, newColumnIndex));

  // notify changes
  TApp::instance()->getCurrentScene()->setDirtyFlag(true);
  TApp::instance()->getCurrentXsheet()->notifyXsheetChanged();
}
コード例 #30
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;
}