Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tfx.h"
Toshihiro Shimizu 890ddd
#include "tfxattributes.h"
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
#include "tconst.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tbasefx.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/tstageobject.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheet.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobjecttree.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnfxset.h"
Toshihiro Shimizu 890ddd
#include "toonz/fxdag.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshzeraryfxcolumn.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnfx.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobjectspline.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonzqt/stageobjectsdata.h"
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// TODO: Method StageObjectsData::storeFxs() has no well-defined behaviour in
Shinya Kitaoka 120a6e
// cases
Toshihiro Shimizu 890ddd
//      of 'jumpy' fx selections.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    Local namespace
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Returns whether ALL input chains from fx pass through fxsSet - ie if
Toshihiro Shimizu 890ddd
//! fxsSet can completely generate fx's input.
Toshihiro Shimizu 890ddd
//! \note Columns are assumed to be generated only if they are in fxsSet.
Shinya Kitaoka 120a6e
bool canGenerate(const std::set<tfx *=""> &fxsSet, TFx *fx) {</tfx>
Shinya Kitaoka 120a6e
  assert(fx);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (fxsSet.count(fx) > 0) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int p, pCount = fx->getInputPortCount();
Shinya Kitaoka 120a6e
  for (p = 0; p != pCount; ++p) {
Shinya Kitaoka 120a6e
    TFx *inputFx = fx->getInputPort(p)->getFx();
Shinya Kitaoka 120a6e
    if (!inputFx) continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Inability to generate transmits to parents
Shinya Kitaoka 120a6e
    if (!canGenerate(fxsSet, inputFx)) return false;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return (pCount != 0);  // Columns return false, the others checked ports
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Returns whether the specified fx is a downstream node of the xsheet node.
Shinya Kitaoka 120a6e
bool hasTerminalUpstream(TFx *fx, TFxSet *terminalFxs) {
Shinya Kitaoka 120a6e
  if (TZeraryFx *zfx = dynamic_cast<tzeraryfx *="">(fx))</tzeraryfx>
Shinya Kitaoka 120a6e
    return hasTerminalUpstream(zfx->getColumnFx(), terminalFxs);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (terminalFxs->containsFx(fx)) return true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // If the fx does not have output connections, check if it's terminal
Shinya Kitaoka 120a6e
  int outputConnectionsCount = fx->getOutputConnectionCount();
Shinya Kitaoka 120a6e
  if (!outputConnectionsCount) return terminalFxs->containsFx(fx);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Search output connections
Shinya Kitaoka 120a6e
  for (int i = 0; i < outputConnectionsCount; ++i) {
Shinya Kitaoka 120a6e
    TFx *parentFx = fx->getOutputConnection(i)->getOwnerFx();
Shinya Kitaoka 120a6e
    if (parentFx && hasTerminalUpstream(parentFx, terminalFxs)) return true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Returns whether the fx is terminal or has a not-generable, terminal-upstream
Shinya Kitaoka 120a6e
//! parent.
Shinya Kitaoka 120a6e
bool isColumnSelectionTerminalFx(TFx *fx, TFxSet *terminalFxs,
Shinya Kitaoka 120a6e
                                 const std::set<tfx *=""> &columnFxs) {</tfx>
Shinya Kitaoka 120a6e
  assert(canGenerate(columnFxs, fx));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (terminalFxs->containsFx(fx)) return true;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int oc, ocCount = fx->getOutputConnectionCount();
Shinya Kitaoka 120a6e
  for (oc = 0; oc != ocCount; ++oc) {
Shinya Kitaoka 120a6e
    TFx *parentFx = fx->getOutputConnection(oc)->getOwnerFx();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (TZeraryFx *zfx = dynamic_cast<tzeraryfx *="">(parentFx))</tzeraryfx>
Shinya Kitaoka 120a6e
      parentFx = zfx->getColumnFx();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (parentFx && hasTerminalUpstream(parentFx, terminalFxs) &&
Shinya Kitaoka 120a6e
        !canGenerate(columnFxs, parentFx))
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    TStageObjectDataElement  definition
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Base class used to clone a stage object's relational data inside the stage
Shinya Kitaoka 120a6e
//! schematic.
Shinya Kitaoka 120a6e
class TStageObjectDataElement {
Toshihiro Shimizu 890ddd
protected:
Shinya Kitaoka 120a6e
  friend class StageObjectsData;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TStageObjectParams *m_params;  //!< Stage object parameters (owned)
Shinya Kitaoka 120a6e
  TPointD m_dagPos;              //!< Stage object position in the viewer
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TStageObjectDataElement();
Shinya Kitaoka 120a6e
  virtual ~TStageObjectDataElement();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  virtual TStageObjectDataElement *clone() const;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //! Stores the object data strictly regarding the object being part of
Shinya Kitaoka 120a6e
  //! the schematic stage view (TStageObjectDataElement <- TStageObjectId).
Shinya Kitaoka 120a6e
  void storeObject(const TStageObjectId &objectId, TXsheet *xsh);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //! Restores the object data in the xsheet (TStageObjectDataElement ->
Shinya Kitaoka 120a6e
  //! TXsheet) and
Shinya Kitaoka 120a6e
  //! returns the associated new stage object identifier.
Shinya Kitaoka 120a6e
  TStageObjectId restoreObject(TXsheet *xsh, bool copyPosition) const;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TStageObjectDataElement::TStageObjectDataElement()
Shinya Kitaoka 120a6e
    : m_params(0), m_dagPos(TConst::nowhere) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStageObjectDataElement::~TStageObjectDataElement() { delete m_params; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStageObjectDataElement *TStageObjectDataElement::clone() const {
Shinya Kitaoka 120a6e
  TStageObjectDataElement *data = new TStageObjectDataElement();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  data->m_params = m_params->clone();
Shinya Kitaoka 120a6e
  data->m_dagPos = m_dagPos;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return data;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TStageObjectDataElement::storeObject(const TStageObjectId &objId,
Shinya Kitaoka 120a6e
                                          TXsheet *xsh) {
Shinya Kitaoka 120a6e
  // Search the object in the xsheet (false = don't create a new one)
Shinya Kitaoka 120a6e
  TStageObject *obj = xsh->getStageObjectTree()->getStageObject(objId, false);
Shinya Kitaoka 120a6e
  assert(obj);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_params = obj->getParams();
Shinya Kitaoka 120a6e
  m_dagPos = obj->getDagNodePos();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStageObjectId TStageObjectDataElement::restoreObject(TXsheet *xsh,
Shinya Kitaoka 120a6e
                                                      bool copyPosition) const {
Shinya Kitaoka 120a6e
  int index = 2;  // Skip the table and camera 1 (I guess)
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Search the first unused common (pegbar) id
Shinya Kitaoka 120a6e
  TStageObjectTree *tree = xsh->getStageObjectTree();
Shinya Kitaoka 120a6e
  while (tree->getStageObject(TStageObjectId::PegbarId(index), false)) ++index;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Create the new object to be inserted
Shinya Kitaoka 120a6e
  TStageObject *newObj =
Shinya Kitaoka 120a6e
      tree->getStageObject(TStageObjectId::PegbarId(index), true);
Shinya Kitaoka 120a6e
  newObj->setParent(m_params->m_parentId);
Shinya Kitaoka 120a6e
  newObj->assignParams(m_params);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // If specified, copy the stored position in the viewer
Shinya Kitaoka 120a6e
  if (copyPosition) newObj->setDagNodePos(m_dagPos);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return newObj->getId();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    TColumnDataElement  definition
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Class used to clone a column stage object's relational data inside the stage
Shinya Kitaoka 120a6e
//! schematic.
Shinya Kitaoka d1f6c4
class TColumnDataElement final : public TStageObjectDataElement {
Shinya Kitaoka 120a6e
  friend class StageObjectsData;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshColumnP m_column;  //!< Column associated with the stage object
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  enum FxFlags { eDoClone = 0x1, eResetFxDagPositions = 0x2 };
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TColumnDataElement();
Shinya Kitaoka 120a6e
  ~TColumnDataElement();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //! Clones the stord data.
Shinya Kitaoka 120a6e
  //! \warning Clones the stored TXshColumnP, too.
Shinya Kitaoka 473e70
  TColumnDataElement *clone() const override;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //! Stores the stage object and column data of the specified column index in
Shinya Kitaoka 120a6e
  //! the supplied xsheet.
Shinya Kitaoka 120a6e
  //! Specifically, the TXshColumnP associated with the desired column index is
Shinya Kitaoka 120a6e
  //! stored.
Shinya Kitaoka 120a6e
  //! Supported additional flags include performing a clone of the associated
Shinya Kitaoka 120a6e
  //! TXshColumnP rather than
Shinya Kitaoka 120a6e
  //! storing the original.
Shinya Kitaoka 120a6e
  void storeColumn(TXsheet *xsheet, int index, int fxFlags);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  //! Inserts the stored column in the supplied xsheet with the specified column
Shinya Kitaoka 120a6e
  //! index, returning
Shinya Kitaoka 120a6e
  //! the new associated stage object id.
Shinya Kitaoka 120a6e
  //! Supported additional flags include performing a clone of the associated
Shinya Kitaoka 120a6e
  //! TXshColumnP rather than
Shinya Kitaoka 120a6e
  //! restoring the stored column directly.
Shinya Kitaoka 120a6e
  TStageObjectId restoreColumn(TXsheet *xsh, int index, int fxFlags,
Shinya Kitaoka 120a6e
                               bool copyPosition) const;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TColumnDataElement::TColumnDataElement()
Shinya Kitaoka 120a6e
    : TStageObjectDataElement(), m_column(0) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TColumnDataElement::~TColumnDataElement() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TColumnDataElement *TColumnDataElement::clone() const {
Shinya Kitaoka 120a6e
  TColumnDataElement *element = new TColumnDataElement();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  element->m_params = m_params->clone();
Shinya Kitaoka 120a6e
  element->m_dagPos = m_dagPos;
Shinya Kitaoka 120a6e
  element->m_column = m_column;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (element->m_column) element->m_column = element->m_column->clone();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return element;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TColumnDataElement::storeColumn(TXsheet *xsh, int index, int fxFlags) {
Shinya Kitaoka 120a6e
  if (index < 0) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool doClone             = (fxFlags & eDoClone);
Shinya Kitaoka 120a6e
  bool resetFxDagPositions = (fxFlags & eResetFxDagPositions);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Fetch the specified column (if none, return)
Shinya Kitaoka 120a6e
  TStageObject *obj = xsh->getStageObject(TStageObjectId::ColumnId(index));
Shinya Kitaoka 120a6e
  assert(obj);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshColumn *column = xsh->getColumn(index);
Shinya Kitaoka 120a6e
  if (!column) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TFx *fx = column->getFx();
Shinya Kitaoka 120a6e
  TPointD dagPos;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (fx) dagPos = fx->getAttributes()->getDagNodePos();
Shinya Kitaoka 120a6e
  if (doClone)
Shinya Kitaoka 120a6e
    column = column->clone();  // Zerary fxs clone the associated fx (drawn
Shinya Kitaoka 120a6e
                               // levels do not)
Shinya Kitaoka 120a6e
  if (fx && !resetFxDagPositions)
Shinya Kitaoka 120a6e
    column->getFx()->getAttributes()->setDagNodePos(dagPos);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_column = column;
Shinya Kitaoka 120a6e
  storeObject(obj->getId(), xsh);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStageObjectId TColumnDataElement::restoreColumn(TXsheet *xsh, int index,
Shinya Kitaoka 120a6e
                                                 int fxFlags,
Shinya Kitaoka 120a6e
                                                 bool copyPosition) const {
Shinya Kitaoka 120a6e
  bool doClone             = (fxFlags & eDoClone);
Shinya Kitaoka 120a6e
  bool resetFxDagPositions = (fxFlags & eResetFxDagPositions);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TXshColumn *column = m_column.getPointer();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // The xsheet 'changes' if a new column is inserted. If it was already there,
Shinya Kitaoka 120a6e
  // no.
Shinya Kitaoka 120a6e
  bool xsheetChange = false;
Shinya Kitaoka 120a6e
  if (column && column->getXsheet() && column->getXsheet() != xsh)
Shinya Kitaoka 120a6e
    xsheetChange = true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Insert a column at the specified index. If a column was stored, insert that
Shinya Kitaoka 120a6e
  // one.
Shinya Kitaoka 120a6e
  TPointD dagPos = TConst::nowhere;
Shinya Kitaoka 120a6e
  if (column) {
Shinya Kitaoka 120a6e
    if (column->getFx())
Shinya Kitaoka 120a6e
      dagPos            = column->getFx()->getAttributes()->getDagNodePos();
Shinya Kitaoka 120a6e
    if (doClone) column = column->clone();
Shinya Kitaoka 120a6e
    xsh->insertColumn(index, column);
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    xsh->insertColumn(index);  // Create a new one otherwise
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!resetFxDagPositions && dagPos != TConst::nowhere) {
Shinya Kitaoka 120a6e
    // Don't accept the default position (fx object)
Shinya Kitaoka 120a6e
    TXshColumn *restoredColumn = xsh->getColumn(index);
Shinya Kitaoka 120a6e
    restoredColumn->getFx()->getAttributes()->setDagNodePos(dagPos);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Retrieve the newly inserted column stage object
Shinya Kitaoka 120a6e
  TStageObject *obj = xsh->getStageObject(TStageObjectId::ColumnId(index));
Shinya Kitaoka 120a6e
  assert(obj);
Shinya Kitaoka 120a6e
  obj->assignParams(m_params, doClone);  // Assign the stored params
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (copyPosition) obj->setDagNodePos(m_dagPos);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Clone the associated curve if any
Shinya Kitaoka 120a6e
  if (xsheetChange && obj->getSpline()) {
Shinya Kitaoka 120a6e
    TStageObjectSpline *srcSpl = obj->getSpline();
Shinya Kitaoka 120a6e
    TStageObjectSpline *dstSpl = xsh->getStageObjectTree()->createSpline();
Shinya Kitaoka 120a6e
    dstSpl->addRef();
Shinya Kitaoka 120a6e
    dstSpl->setStroke(new TStroke(*srcSpl->getStroke()));
Shinya Kitaoka 120a6e
    obj->setSpline(dstSpl);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int gridType = xsh->getStageObjectTree()->getDagGridDimension();
Shinya Kitaoka 120a6e
  obj->setIsOpened(gridType ==
Shinya Kitaoka 120a6e
                   0);  // gridType is 0 if the node is opened, 1 if closed
Shinya Kitaoka 120a6e
                        // see StageSchematicScene::GridDimension
Shinya Kitaoka 120a6e
                        // TODO: Should be made PUBLIC!!
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  xsh->updateFrameCount();
Shinya Kitaoka 120a6e
  return obj->getId();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    TCameraDataElement  definition
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Class used to clone a camera stage object's relational data inside the stage
Shinya Kitaoka 120a6e
//! schematic.
Shinya Kitaoka d1f6c4
class TCameraDataElement final : public TStageObjectDataElement {
Shinya Kitaoka 120a6e
  TCamera m_camera;  //!< The object's camera
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TCameraDataElement();
Shinya Kitaoka 120a6e
  ~TCameraDataElement();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 473e70
  TCameraDataElement *clone() const override;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //! Stores the specified camera object.
Shinya Kitaoka 120a6e
  void storeCamera(const TStageObjectId &selectedObj, TXsheet *xsh);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  //! Restores the stored camera object.
Shinya Kitaoka 120a6e
  TStageObjectId restoreCamera(TXsheet *xsh, bool copyPosition) const;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TCameraDataElement::TCameraDataElement() : TStageObjectDataElement() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TCameraDataElement::~TCameraDataElement() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TCameraDataElement *TCameraDataElement::clone() const {
Shinya Kitaoka 120a6e
  TCameraDataElement *data = new TCameraDataElement();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  data->m_params = m_params->clone();
Shinya Kitaoka 120a6e
  data->m_camera = m_camera;
Shinya Kitaoka 120a6e
  data->m_dagPos = m_dagPos;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return data;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TCameraDataElement::storeCamera(const TStageObjectId &selectedObj,
Shinya Kitaoka 120a6e
                                     TXsheet *xsh) {
Shinya Kitaoka 120a6e
  TStageObject *obj =
Shinya Kitaoka 120a6e
      xsh->getStageObjectTree()->getStageObject(selectedObj, false);
Shinya Kitaoka 120a6e
  assert(obj);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_params = obj->getParams();
Shinya Kitaoka 120a6e
  m_camera = *(obj->getCamera());
Shinya Kitaoka 120a6e
  m_dagPos = obj->getDagNodePos();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStageObjectId TCameraDataElement::restoreCamera(TXsheet *xsh,
Shinya Kitaoka 120a6e
                                                 bool copyPosition) const {
Shinya Kitaoka 120a6e
  TStageObjectTree *tree = xsh->getStageObjectTree();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Search the first unused camera id in the xsheet
Shinya Kitaoka 120a6e
  int index = 0;
Shinya Kitaoka 120a6e
  while (tree->getStageObject(TStageObjectId::CameraId(index), false)) ++index;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Create the new camera object and assign stored data
Shinya Kitaoka 120a6e
  TStageObject *newCamera =
Shinya Kitaoka 120a6e
      tree->getStageObject(TStageObjectId::CameraId(index), true);
Shinya Kitaoka 120a6e
  newCamera->assignParams(m_params);
Shinya Kitaoka 120a6e
  *(newCamera->getCamera()) = m_camera;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (copyPosition) newCamera->setDagNodePos(m_dagPos);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return newCamera->getId();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    TSplineDataElement definition
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TSplineDataElement {
Shinya Kitaoka 120a6e
  enum Flags { eDoClone = 0x1, eResetFxDagPositions = 0x2 };
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TStageObjectSpline *m_spline;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  TSplineDataElement();
Shinya Kitaoka 120a6e
  ~TSplineDataElement();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TSplineDataElement *clone();
Shinya Kitaoka 120a6e
  void storeSpline(TStageObjectSpline *spline, int flag);
Shinya Kitaoka 120a6e
  TStageObjectSpline *restoreSpline(int flag) const;
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    TSplineDataElement implementation
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TSplineDataElement::TSplineDataElement() : m_spline(0) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TSplineDataElement::~TSplineDataElement() {
Shinya Kitaoka 120a6e
  if (m_spline) m_spline->release();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TSplineDataElement *TSplineDataElement::clone() {
Shinya Kitaoka 120a6e
  TSplineDataElement *data = new TSplineDataElement();
Shinya Kitaoka 120a6e
  if (m_spline) {
Shinya Kitaoka 120a6e
    data->m_spline = m_spline->clone();
Shinya Kitaoka 120a6e
    data->m_spline->addRef();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return data;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TSplineDataElement::storeSpline(TStageObjectSpline *spline, int flag) {
Shinya Kitaoka 120a6e
  if (!spline) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_spline = (flag & eDoClone) ? spline->clone() : spline;
Shinya Kitaoka 120a6e
  m_spline->addRef();
Shinya Kitaoka 120a6e
  if (flag & eResetFxDagPositions) m_spline->setDagNodePos(TConst::nowhere);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TStageObjectSpline *TSplineDataElement::restoreSpline(int flag) const {
Shinya Kitaoka 120a6e
  TStageObjectSpline *spline = (flag & eDoClone) ? m_spline->clone() : m_spline;
Shinya Kitaoka 120a6e
  if (flag & eResetFxDagPositions) spline->setDagNodePos(TConst::nowhere);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return spline;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
//    StageObjectsData  implementation
Toshihiro Shimizu 890ddd
//********************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
StageObjectsData::StageObjectsData() : DvMimeData() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
StageObjectsData::~StageObjectsData() {
Shinya Kitaoka 120a6e
  int i, elementsCount = m_elements.size();
Shinya Kitaoka 120a6e
  for (i = 0; i < elementsCount; ++i) delete m_elements[i];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (i = 0; i < m_splines.size(); ++i) delete m_splines[i];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::set<tfx *="">::iterator it;</tfx>
Shinya Kitaoka 120a6e
  for (it = m_fxs.begin(); it != m_fxs.end(); ++it) {
Shinya Kitaoka 120a6e
    TFx *fx = *it;
Shinya Kitaoka 120a6e
    if (fx) fx->release();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (it = m_terminalFxs.begin(); it != m_terminalFxs.end(); ++it) {
Shinya Kitaoka 120a6e
    TFx *fx = *it;
Shinya Kitaoka 120a6e
    if (fx) fx->release();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool StageObjectsData::checkCircularReferences(TXsheet *xsh) const {
Shinya Kitaoka 120a6e
  int i, elementsCount = m_elements.size();
Shinya Kitaoka 120a6e
  for (i = 0; i < elementsCount; ++i) {
Shinya Kitaoka 120a6e
    TColumnDataElement *columnElement =
Shinya Kitaoka 120a6e
        dynamic_cast<tcolumndataelement *="">(m_elements[i]);</tcolumndataelement>
Shinya Kitaoka 120a6e
    if (!columnElement) continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (xsh->checkCircularReferences(columnElement->m_column.getPointer()))
Shinya Kitaoka 120a6e
      return true;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
StageObjectsData *StageObjectsData::clone() const {
Shinya Kitaoka 120a6e
  StageObjectsData *data = new StageObjectsData();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Clone each element (the new data gets ownership)
Shinya Kitaoka 120a6e
  int i, elementsCount = m_elements.size();
Shinya Kitaoka 120a6e
  for (i = 0; i < elementsCount; ++i)
Shinya Kitaoka 120a6e
    data->m_elements.append(m_elements[i]->clone());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Clone each spline (the new data gets ownership)
Shinya Kitaoka 120a6e
  for (i = 0; i < m_splines.size(); ++i)
Shinya Kitaoka 120a6e
    data->m_splines.append(m_splines[i]->clone());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Same for internal fxs
Shinya Kitaoka 120a6e
  std::map<tfx *="" *,="" tfx=""> fxTable;  // And trace the pairings with the originals</tfx>
Shinya Kitaoka 120a6e
  std::set<tfx *="">::const_iterator it;</tfx>
Shinya Kitaoka 120a6e
  for (it = m_fxs.begin(); it != m_fxs.end(); ++it) {
Shinya Kitaoka 120a6e
    TFx *fxOrig = *it;
Shinya Kitaoka 120a6e
    assert(fxOrig);
Shinya Kitaoka 120a6e
    assert(fxTable.count(fxOrig) == 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TFx *fx = fxOrig->clone(false);
Shinya Kitaoka 120a6e
    fx->getAttributes()->setId(fxOrig->getAttributes()->getId());
Shinya Kitaoka 120a6e
    fx->getAttributes()->passiveCacheDataIdx() = -1;
Shinya Kitaoka 120a6e
    fx->setName(fxOrig->getName());
Shinya Kitaoka 120a6e
    fx->setFxId(fxOrig->getFxId());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    fxTable[fxOrig] = fx;
Shinya Kitaoka 120a6e
    fx->addRef();
Shinya Kitaoka 120a6e
    data->m_fxs.insert(fx);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Same with terminals
Shinya Kitaoka 120a6e
  for (it = m_terminalFxs.begin(); it != m_terminalFxs.end(); ++it) {
Shinya Kitaoka 120a6e
    TFx *fxOrig = *it;
Shinya Kitaoka 120a6e
    assert(fxOrig);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // If the fx was not already cloned above, do it now
Shinya Kitaoka 120a6e
    TFx *fx = searchFx(fxTable, fxOrig);
Shinya Kitaoka 120a6e
    if (!fx) {
Shinya Kitaoka 120a6e
      fx = fxOrig->clone(false);
Shinya Kitaoka 120a6e
      fx->getAttributes()->setId(fxOrig->getAttributes()->getId());
Shinya Kitaoka 120a6e
      fx->getAttributes()->passiveCacheDataIdx() = -1;
Shinya Kitaoka 120a6e
      fx->setName(fxOrig->getName());
Shinya Kitaoka 120a6e
      fx->setFxId(fxOrig->getFxId());
Shinya Kitaoka 120a6e
      fxTable[fxOrig] = fx;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    fx->addRef();
Shinya Kitaoka 120a6e
    data->m_terminalFxs.insert(fx);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!fxTable.empty())
Shinya Kitaoka 120a6e
    updateFxLinks(
Shinya Kitaoka 120a6e
        fxTable);  // Applies the traced map pairings to every fx descendant
Shinya Kitaoka 120a6e
                   // of each fx stored in the map.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // WARNING: m_fxsTable is NOT COPIED / CLONED !!
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return data;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void StageObjectsData::storeObjects(const std::vector<tstageobjectid> &ids,</tstageobjectid>
Shinya Kitaoka 120a6e
                                    TXsheet *xsh, int fxFlags) {
Shinya Kitaoka 120a6e
  assert(
Shinya Kitaoka 120a6e
      m_fxTable.empty());  // Should be enforced OUTSIDE. Track implicit uses.
Shinya Kitaoka 120a6e
  m_fxTable.clear();       // TO BE REMOVED
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int i, objCount = ids.size();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Discriminate sensible stage object types (ie cameras and columns from the
Shinya Kitaoka 120a6e
  // rest).
Shinya Kitaoka 120a6e
  // Store them in a map, ordered by object index.
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::map<int, tstageobjectid=""> cameraIds, columnIds, pegbarIds;</int,>
Shinya Kitaoka 120a6e
  for (i = 0; i < objCount; ++i) {
Shinya Kitaoka 120a6e
    TStageObjectId id = ids[i];
Shinya Kitaoka 120a6e
    if (id.isColumn())
Shinya Kitaoka 120a6e
      columnIds[id.getIndex()] = id;
Shinya Kitaoka 120a6e
    else if (id.isPegbar())
Shinya Kitaoka 120a6e
      pegbarIds[id.getIndex()] = id;
Shinya Kitaoka 120a6e
    else if (id.isCamera())
Shinya Kitaoka 120a6e
      cameraIds[id.getIndex()] = id;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Store a suitable object for each
Shinya Kitaoka 120a6e
  std::map<int, tstageobjectid="">::iterator it;</int,>
Shinya Kitaoka 120a6e
  for (it = cameraIds.begin(); it != cameraIds.end(); ++it) {
Shinya Kitaoka 120a6e
    // Cameras
Shinya Kitaoka 120a6e
    TCameraDataElement *cameraElement = new TCameraDataElement();
Shinya Kitaoka 120a6e
    cameraElement->storeCamera(it->second, xsh);
Shinya Kitaoka 120a6e
    m_elements.append(cameraElement);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (it = pegbarIds.begin(); it != pegbarIds.end(); ++it) {
Shinya Kitaoka 120a6e
    // Pegbars (includes curves)
Shinya Kitaoka 120a6e
    TStageObjectDataElement *objElement = new TStageObjectDataElement();
Shinya Kitaoka 120a6e
    objElement->storeObject(it->second, xsh);
Shinya Kitaoka 120a6e
    m_elements.append(objElement);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (it = columnIds.begin(); it != columnIds.end(); ++it) {
Shinya Kitaoka 120a6e
    // Columns
Shinya Kitaoka 120a6e
    int colIndex = it->second.getIndex();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TXshColumn *column = xsh->getColumn(colIndex);
Shinya Kitaoka 120a6e
    if (!column) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TColumnDataElement *columnElement = new TColumnDataElement();
Shinya Kitaoka 120a6e
    columnElement->storeColumn(xsh, colIndex, fxFlags);
Shinya Kitaoka 120a6e
    m_elements.append(columnElement);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TXshColumn *copiedColumn = columnElement->m_column.getPointer();
Shinya Kitaoka 120a6e
    if (column->getFx() && copiedColumn->getFx()) {
Shinya Kitaoka 120a6e
      // Store column fx pairings (even if the originals are not cloned)
Shinya Kitaoka 120a6e
      m_fxTable[column->getFx()] = copiedColumn->getFx();
Shinya Kitaoka 120a6e
      m_originalColumnFxs.insert(column->getFx());
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Insert terminal fxs
Shinya Kitaoka 120a6e
  set<tfx *="">::iterator jt;</tfx>
Shinya Kitaoka 120a6e
  for (jt = m_originalColumnFxs.begin(); jt != m_originalColumnFxs.end();
Shinya Kitaoka 120a6e
       ++jt) {
Shinya Kitaoka 120a6e
    if (isColumnSelectionTerminalFx(*jt, xsh->getFxDag()->getTerminalFxs(),
Shinya Kitaoka 120a6e
                                    m_originalColumnFxs)) {
Shinya Kitaoka 120a6e
      TFx *fx = m_fxTable[*jt];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      fx->addRef();
Shinya Kitaoka 120a6e
      m_terminalFxs.insert(fx);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void StageObjectsData::storeColumns(const std::set<int> &columnIndexes,</int>
Shinya Kitaoka 120a6e
                                    TXsheet *xsh, int fxFlags) {
Shinya Kitaoka 120a6e
  std::vector<tstageobjectid> ids;</tstageobjectid>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::set<int>::const_iterator it;</int>
Shinya Kitaoka 120a6e
  for (it = columnIndexes.begin(); it != columnIndexes.end(); ++it)
Shinya Kitaoka 120a6e
    ids.push_back(TStageObjectId::ColumnId(*it));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  storeObjects(ids, xsh, fxFlags);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void StageObjectsData::storeFxs(const std::set<tfx *=""> &fxs, TXsheet *xsh,</tfx>
Shinya Kitaoka 120a6e
                                int fxFlags) {
Shinya Kitaoka 120a6e
  bool doClone             = (fxFlags & eDoClone);
Shinya Kitaoka 120a6e
  bool resetFxDagPositions = (fxFlags & eResetFxDagPositions);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TFxSet *terminalFxs = xsh->getFxDag()->getTerminalFxs();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Traverse specified fxs
Shinya Kitaoka 120a6e
  std::set<tfx *="">::const_iterator it;</tfx>
Shinya Kitaoka 120a6e
  for (it = fxs.begin(); it != fxs.end(); ++it) {
Shinya Kitaoka 120a6e
    TFx *fxOrig = *it, *fx = fxOrig;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (doClone) {
Shinya Kitaoka 120a6e
      // If required, clone them
Shinya Kitaoka 120a6e
      fx = fxOrig->clone(false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      fx->setName(fxOrig->getName());
Shinya Kitaoka 120a6e
      fx->getAttributes()->setId(fxOrig->getAttributes()->getId());
Shinya Kitaoka 120a6e
      fx->getAttributes()->passiveCacheDataIdx() = -1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (resetFxDagPositions)
Shinya Kitaoka 120a6e
        fx->getAttributes()->setDagNodePos(TConst::nowhere);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Store them (and the original/clone pairing even if not cloning)
Shinya Kitaoka 120a6e
    m_fxTable[fxOrig] = fx;
Shinya Kitaoka 120a6e
    fx->addRef();
Shinya Kitaoka 120a6e
    m_fxs.insert(fx);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Find out if the fx is a terminal one in the selection. If so, store it
Shinya Kitaoka 120a6e
    // there too.
Shinya Kitaoka 120a6e
    bool isTerminal = true;
Shinya Kitaoka 120a6e
    if (!terminalFxs->containsFx(
Shinya Kitaoka 120a6e
            fxOrig))  // If it's terminal in the xsheet, no doubt
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      // Otherwise, check terminality with respect to the selection
Shinya Kitaoka 120a6e
      int i, outputConnectionsCount = fxOrig->getOutputConnectionCount();
Shinya Kitaoka 120a6e
      for (i = 0; i < outputConnectionsCount; ++i) {
Shinya Kitaoka 120a6e
        TFx *outputFx = fxOrig->getOutputConnection(i)->getOwnerFx();
Shinya Kitaoka 120a6e
        if (outputFx && fxs.count(outputFx) > 0) {
Shinya Kitaoka 120a6e
          isTerminal = false;
Shinya Kitaoka 120a6e
          break;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Well, excluding true TOutputFxs...
Shinya Kitaoka 120a6e
    TOutputFx *outFx = dynamic_cast<toutputfx *="">(fx);</toutputfx>
Shinya Kitaoka 120a6e
    if (isTerminal && !outFx) {
Shinya Kitaoka 120a6e
      fx->addRef();
Shinya Kitaoka 120a6e
      m_terminalFxs.insert(fx);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Updating terminality of the column fxs too!
Shinya Kitaoka 120a6e
  // WARNING: This requires that storeObjects() is invoked BEFORE this !
Shinya Kitaoka 120a6e
  for (it = m_originalColumnFxs.begin(); it != m_originalColumnFxs.end();
Shinya Kitaoka 120a6e
       ++it) {
Shinya Kitaoka 120a6e
    TFx *fxOrig = *it;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    bool isTerminal = true;
Shinya Kitaoka 120a6e
    if (!terminalFxs->containsFx(fxOrig)) {
Shinya Kitaoka 120a6e
      int i, outputConnectionsCount = fxOrig->getOutputConnectionCount();
Shinya Kitaoka 120a6e
      for (i = 0; i < outputConnectionsCount; ++i) {
Shinya Kitaoka 120a6e
        TFx *outputFx = fxOrig->getOutputConnection(i)->getOwnerFx();
Shinya Kitaoka 120a6e
        if (outputFx && fxs.count(outputFx) > 0) {
Shinya Kitaoka 120a6e
          isTerminal = false;
Shinya Kitaoka 120a6e
          break;
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (isTerminal) {
Shinya Kitaoka 120a6e
      TFx *fx = m_fxTable[fxOrig];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      fx->addRef();
Shinya Kitaoka 120a6e
      m_terminalFxs.insert(fx);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!m_fxTable.empty() && doClone)
Shinya Kitaoka 120a6e
    updateFxLinks(m_fxTable);  // Apply original/clone pairings
Shinya Kitaoka 120a6e
                               // to fx relatives
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void StageObjectsData::storeColumnFxs(const std::set<int> &columnIndexes,</int>
Shinya Kitaoka 120a6e
                                      TXsheet *xsh, int fxFlags) {
Shinya Kitaoka 120a6e
  bool doClone             = (fxFlags & eDoClone);
Shinya Kitaoka 120a6e
  bool resetFxDagPositions = (fxFlags & eResetFxDagPositions);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::set<tfx *=""> internalFxs;</tfx>
Shinya Kitaoka 120a6e
  xsh->getFxDag()->getInternalFxs()->getFxs(internalFxs);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Iterate internal fxs (note: columns NOT included)
Shinya Kitaoka 120a6e
  // NOTE: Could this be too heavy ? Shouldn't we travel upstream from given
Shinya Kitaoka 120a6e
  // column fxs?
Shinya Kitaoka 120a6e
  std::set<tfx *="">::iterator it;</tfx>
Shinya Kitaoka 120a6e
  for (it = internalFxs.begin(); it != internalFxs.end(); ++it) {
Shinya Kitaoka 120a6e
    TFx *fxOrig = *it, *fx = fxOrig;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_fxTable.find(fx) != m_fxTable.end())  // If already treated
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!canGenerate(m_originalColumnFxs,
Shinya Kitaoka 120a6e
                     fx))  // If not completely in the upstream
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (doClone) {
Shinya Kitaoka 120a6e
      // Clone the fx if required
Shinya Kitaoka 120a6e
      fx = fxOrig->clone(false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      fx->setName(fxOrig->getName());
Shinya Kitaoka 120a6e
      fx->getAttributes()->setId(fxOrig->getAttributes()->getId());
Shinya Kitaoka 120a6e
      fx->getAttributes()->passiveCacheDataIdx() = -1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (resetFxDagPositions)
Shinya Kitaoka 120a6e
        fx->getAttributes()->setDagNodePos(TConst::nowhere);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    m_fxTable[fxOrig] = fx;
Shinya Kitaoka 120a6e
    fx->addRef();
Shinya Kitaoka 120a6e
    m_fxs.insert(fx);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (isColumnSelectionTerminalFx(fxOrig, xsh->getFxDag()->getTerminalFxs(),
Shinya Kitaoka 120a6e
                                    m_originalColumnFxs)) {
Shinya Kitaoka 120a6e
      fx->addRef();
Shinya Kitaoka 120a6e
      m_terminalFxs.insert(fx);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (fxOrig->getLinkedFx() != fxOrig)  // Linked fx
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      if (!canGenerate(m_originalColumnFxs, fxOrig->getLinkedFx()))
Shinya Kitaoka 120a6e
        fx->linkParams(fxOrig->getLinkedFx());
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        // Insert the linked fx directly here
Shinya Kitaoka 120a6e
        TFx *linkedFx, *oldLinkedFx = fxOrig->getLinkedFx();
Shinya Kitaoka 120a6e
        if (doClone) {
Shinya Kitaoka 120a6e
          linkedFx = fx->clone(false);  // Not oldLinkedFx->clone() ?
Shinya Kitaoka 120a6e
          linkedFx->linkParams(fx);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          linkedFx->setName(oldLinkedFx->getName());
Shinya Kitaoka 120a6e
          linkedFx->getAttributes()->setId(
Shinya Kitaoka 120a6e
              oldLinkedFx->getAttributes()->getId());
Shinya Kitaoka 120a6e
          linkedFx->getAttributes()->passiveCacheDataIdx() = -1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          if (resetFxDagPositions)
Shinya Kitaoka 120a6e
            fx->getAttributes()->setDagNodePos(TConst::nowhere);  // Here too ?
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          xsh->getFxDag()->assignUniqueId(linkedFx);
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          linkedFx = oldLinkedFx;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        m_fxTable[oldLinkedFx] = linkedFx;
Shinya Kitaoka 120a6e
        linkedFx->addRef();
Shinya Kitaoka 120a6e
        m_fxs.insert(linkedFx);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (xsh->getFxDag()->getTerminalFxs()->containsFx(
Shinya Kitaoka 120a6e
                fx->getLinkedFx()))  // Here too - isATerminal ?
Shinya Kitaoka 120a6e
        {
Shinya Kitaoka 120a6e
          linkedFx->addRef();
Shinya Kitaoka 120a6e
          m_terminalFxs.insert(linkedFx);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Like in the functions above, update links
Shinya Kitaoka 120a6e
  if (!m_fxTable.empty() && doClone) updateFxLinks(m_fxTable);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void StageObjectsData::storeSplines(const std::list<int> &splineIds,</int>
Shinya Kitaoka 120a6e
                                    TXsheet *xsh, int fxFlags) {
Shinya Kitaoka 120a6e
  std::list<int>::const_iterator it;</int>
Shinya Kitaoka 120a6e
  for (it = splineIds.begin(); it != splineIds.end(); ++it) {
Shinya Kitaoka 120a6e
    TStageObjectSpline *spline = xsh->getStageObjectTree()->getSplineById(*it);
Shinya Kitaoka 120a6e
    int j;
Shinya Kitaoka 120a6e
    bool skipSpline = false;
Shinya Kitaoka 120a6e
    for (j = 0; j < m_elements.size(); j++) {
Shinya Kitaoka 120a6e
      TStageObjectDataElement *element = m_elements[j];
Shinya Kitaoka 120a6e
      if (spline == element->m_params->m_spline) {
Shinya Kitaoka 120a6e
        skipSpline = true;
Shinya Kitaoka 120a6e
        break;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
    if (skipSpline) continue;
Shinya Kitaoka 120a6e
    TSplineDataElement *splineElement = new TSplineDataElement();
Shinya Kitaoka 120a6e
    splineElement->storeSpline(spline, fxFlags);
Shinya Kitaoka 120a6e
    m_splines.append(splineElement);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::vector<tstageobjectid> StageObjectsData::restoreObjects(</tstageobjectid>
Shinya Kitaoka 120a6e
    std::set<int> &columnIndices, std::list<int> &restoredSpline, TXsheet *xsh,</int></int>
Shinya Kitaoka 120a6e
    int fxFlags, const TPointD &pos) const {
Shinya Kitaoka 120a6e
  bool doClone             = (fxFlags & eDoClone);
Shinya Kitaoka 120a6e
  bool resetFxDagPositions = (fxFlags & eResetFxDagPositions);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  QMap<tstageobjectid, tstageobjectid=""></tstageobjectid,>
Shinya Kitaoka 120a6e
      idTable;                     // Trace stored/restored id pairings
Shinya Kitaoka 120a6e
  std::map<tfx *="" *,="" tfx=""> fxTable;  // Same for fxs here</tfx>
Shinya Kitaoka 120a6e
  std::vector<tstageobjectid> restoredIds;</tstageobjectid>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::set<int>::iterator idxt = columnIndices.begin();</int>
Shinya Kitaoka 120a6e
  int index                    = -1;  // The actual column insertion index
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int i, elementsCount = m_elements.size();
Shinya Kitaoka 120a6e
  for (i = 0; i < elementsCount; ++i) {
Shinya Kitaoka 120a6e
    TStageObjectDataElement *element = m_elements[i];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TCameraDataElement *cameraElement =
Shinya Kitaoka 120a6e
        dynamic_cast<tcameradataelement *="">(element);</tcameradataelement>
Shinya Kitaoka 120a6e
    TColumnDataElement *columnElement =
Shinya Kitaoka 120a6e
        dynamic_cast<tcolumndataelement *="">(element);</tcolumndataelement>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Restore the object depending on its specific type
Shinya Kitaoka 120a6e
    TStageObjectId restoredId = TStageObjectId::NoneId;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!cameraElement && !columnElement)
Shinya Kitaoka 120a6e
      restoredId = element->restoreObject(xsh, pos != TConst::nowhere);
Shinya Kitaoka 120a6e
    else if (cameraElement)
Shinya Kitaoka 120a6e
      restoredId = cameraElement->restoreCamera(xsh, pos != TConst::nowhere);
Shinya Kitaoka 120a6e
    else if (columnElement) {
Shinya Kitaoka 120a6e
      // Build the column insertion index
Shinya Kitaoka 120a6e
      if (idxt != columnIndices.end())
Shinya Kitaoka 120a6e
        index = *idxt++;
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        ++index;
Shinya Kitaoka 120a6e
        columnIndices.insert(index);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Restore the column element
Shinya Kitaoka 120a6e
      restoredId = columnElement->restoreColumn(xsh, index, fxFlags,
Shinya Kitaoka 120a6e
                                                pos != TConst::nowhere);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      FxDag *fxDag = xsh->getFxDag();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TXshColumn *column       = columnElement->m_column.getPointer();
Shinya Kitaoka 120a6e
      TXshColumn *pastedColumn = xsh->getColumn(index);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TFx *fx       = column->getFx();
Shinya Kitaoka 120a6e
      TFx *pastedFx = pastedColumn->getFx();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (fx && pastedFx) fxTable[fx] = pastedFx;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Enforce the correct terminality. Added columns are terminal by default.
Shinya Kitaoka 120a6e
      bool terminal = (fx && (m_terminalFxs.count(fx) > 0));
Shinya Kitaoka 120a6e
      if (!terminal) fxDag->getTerminalFxs()->removeFx(pastedFx);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // In case we've cloned a zerary fx column, update the actual fx's data
Shinya Kitaoka 120a6e
      if (TXshZeraryFxColumn *zc =
Shinya Kitaoka 120a6e
              dynamic_cast<txshzeraryfxcolumn *="">(pastedColumn)) {</txshzeraryfxcolumn>
Shinya Kitaoka 120a6e
        TZeraryColumnFx *zfx = zc->getZeraryColumnFx();
Shinya Kitaoka 120a6e
        TFx *zeraryFx        = zfx->getZeraryFx();
Shinya Kitaoka 120a6e
        if (zeraryFx && doClone) {
Shinya Kitaoka 120a6e
          std::wstring app = zeraryFx->getName();
Shinya Kitaoka 120a6e
          fxDag->assignUniqueId(zeraryFx);
Shinya Kitaoka 120a6e
          zeraryFx->setName(app);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Remember stored/restored stage object pairings
Shinya Kitaoka 120a6e
    idTable[element->m_params->m_id] = restoredId;
Shinya Kitaoka 120a6e
    restoredIds.push_back(restoredId);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Apply stage object-parental relationships
Shinya Kitaoka 120a6e
  for (i = 0; i < elementsCount; ++i) {
Shinya Kitaoka 120a6e
    TStageObjectDataElement *element = m_elements[i];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TStageObjectId id       = element->m_params->m_id;
Shinya Kitaoka 120a6e
    TStageObjectId parentId = element->m_params->m_parentId;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TStageObjectId pastedId       = idTable[id];
Shinya Kitaoka 120a6e
    TStageObjectId pastedParentId = parentId;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (parentId.isColumn())  // Why discriminating for columns only ?
Shinya Kitaoka 120a6e
    {
Shinya Kitaoka 120a6e
      // Columns are redirected to table ids. If no redirected parent exists,
Shinya Kitaoka 120a6e
      // store
Shinya Kitaoka 120a6e
      // a void value that will be avoided later
Shinya Kitaoka 120a6e
      QMap<tstageobjectid, tstageobjectid="">::iterator it =</tstageobjectid,>
Shinya Kitaoka 120a6e
          idTable.find(parentId);
Shinya Kitaoka 120a6e
      pastedParentId =
Shinya Kitaoka 120a6e
          (it == idTable.end()) ? TStageObjectId::NoneId : it.value();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (pastedParentId != TStageObjectId::NoneId) {
Shinya Kitaoka 120a6e
      xsh->setStageObjectParent(pastedId, pastedParentId);
Shinya Kitaoka 120a6e
      TStageObject *pastedObj = xsh->getStageObject(pastedId);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      // Shouldn't these be done outside ?
Shinya Kitaoka 120a6e
      pastedObj->setHandle(element->m_params->m_handle);
Shinya Kitaoka 120a6e
      pastedObj->setParentHandle(element->m_params->m_parentHandle);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Iterate stored fxs
Shinya Kitaoka 120a6e
  std::set<tfx *="">::const_iterator fxt, end = m_fxs.end();</tfx>
Shinya Kitaoka 120a6e
  for (fxt = m_fxs.begin(); fxt != end; ++fxt) {
Shinya Kitaoka 120a6e
    TFx *fxOrig = *fxt, *fx = fxOrig;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Only NOT COLUMN fxs - ie internal fxs
Shinya Kitaoka 120a6e
    if (fxTable.find(fxOrig) != fxTable.end()) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Internal fxs
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (doClone) {
Shinya Kitaoka 120a6e
      fx = fxOrig->clone(false);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      fx->setName(fxOrig->getName());
Shinya Kitaoka 120a6e
      fx->getAttributes()->setId(fxOrig->getAttributes()->getId());
Shinya Kitaoka 120a6e
      fx->getAttributes()->passiveCacheDataIdx() = -1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (resetFxDagPositions)
Shinya Kitaoka 120a6e
        fx->getAttributes()->setDagNodePos(TConst::nowhere);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      xsh->getFxDag()->assignUniqueId(fx);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    fxTable[fxOrig] = fx;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Insert the passed fx in the xsheet
Shinya Kitaoka 120a6e
    TOutputFx *outFx = dynamic_cast<toutputfx *="">(fx);</toutputfx>
Shinya Kitaoka 120a6e
    if (!outFx)
Shinya Kitaoka 120a6e
      xsh->getFxDag()->getInternalFxs()->addFx(fx);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      xsh->getFxDag()->addOutputFx(outFx);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_terminalFxs.count(fxOrig) > 0)
Shinya Kitaoka 120a6e
      xsh->getFxDag()->getTerminalFxs()->addFx(fx);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!doClone) {
Shinya Kitaoka 120a6e
      // Err.... don't remember. Inquire further? :|
Shinya Kitaoka 120a6e
      int fxTypeCount = xsh->getFxDag()->getFxTypeCount(fx);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      int maxFxTypeId = std::max(fxTypeCount, fx->getAttributes()->getId());
Shinya Kitaoka 120a6e
      xsh->getFxDag()->updateFxTypeTable(fx, maxFxTypeId);
Shinya Kitaoka 120a6e
      xsh->getFxDag()->updateFxIdTable(fx);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    bool isLinked = (fxOrig->getLinkedFx() != fxOrig);
Shinya Kitaoka 120a6e
    if (isLinked) {
Shinya Kitaoka 120a6e
      if (m_fxs.find(fxOrig->getLinkedFx()) == m_fxs.end())
Shinya Kitaoka 120a6e
        fx->linkParams(fxOrig->getLinkedFx());
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        TFx *linkedFx, *oldLinkedFx = fxOrig->getLinkedFx();
Shinya Kitaoka 120a6e
        if (doClone) {
Shinya Kitaoka 120a6e
          // Clone the linked fx too
Shinya Kitaoka 120a6e
          linkedFx = fx->clone(false);
Shinya Kitaoka 120a6e
          linkedFx->linkParams(fx);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          linkedFx->setName(oldLinkedFx->getName());
Shinya Kitaoka 120a6e
          linkedFx->getAttributes()->setId(
Shinya Kitaoka 120a6e
              oldLinkedFx->getAttributes()->getId());
Shinya Kitaoka 120a6e
          linkedFx->getAttributes()->passiveCacheDataIdx() = -1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          if (resetFxDagPositions)
Shinya Kitaoka 120a6e
            linkedFx->getAttributes()->setDagNodePos(TConst::nowhere);
Shinya Kitaoka 120a6e
          else
Shinya Kitaoka 120a6e
            linkedFx->getAttributes()->setDagNodePos(
Shinya Kitaoka 120a6e
                oldLinkedFx->getAttributes()->getDagNodePos());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
          xsh->getFxDag()->assignUniqueId(linkedFx);
Shinya Kitaoka 120a6e
        } else
Shinya Kitaoka 120a6e
          linkedFx = oldLinkedFx;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        fxTable[oldLinkedFx] = linkedFx;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        xsh->getFxDag()->getInternalFxs()->addFx(linkedFx);
Shinya Kitaoka 120a6e
        if (m_terminalFxs.count(oldLinkedFx) > 0)
Shinya Kitaoka 120a6e
          xsh->getFxDag()->getTerminalFxs()->addFx(linkedFx);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (!doClone) {
Shinya Kitaoka 120a6e
          int fxTypeCount = xsh->getFxDag()->getFxTypeCount(linkedFx);
Shinya Kitaoka 120a6e
          int maxFxTypeId =
Shinya Kitaoka 120a6e
              std::max(fxTypeCount, linkedFx->getAttributes()->getId());
Shinya Kitaoka 120a6e
          xsh->getFxDag()->updateFxTypeTable(linkedFx, maxFxTypeId);
Shinya Kitaoka 120a6e
          xsh->getFxDag()->updateFxIdTable(linkedFx);
Shinya Kitaoka 120a6e
        }
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Update the link, like in functions above
Shinya Kitaoka 120a6e
  if (!fxTable.empty() && doClone) updateFxLinks(fxTable);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Paste any associated spline (not stored im m_splines)
Shinya Kitaoka 120a6e
  std::map<tstageobjectspline *="" *,="" tstageobjectspline=""> splines;</tstageobjectspline>
Shinya Kitaoka 120a6e
  for (i = 0; i < (int)restoredIds.size(); ++i) {
Shinya Kitaoka 120a6e
    TStageObjectId id = restoredIds[i];
Shinya Kitaoka 120a6e
    TStageObject *obj = xsh->getStageObject(id);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TStageObjectSpline *spline = obj->getSpline();
Shinya Kitaoka 120a6e
    if (!spline) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TStageObjectTree *objTree = xsh->getStageObjectTree();
Shinya Kitaoka 120a6e
    if (objTree->containsSpline(
Shinya Kitaoka 120a6e
            spline))  // No need to add it if it's already there
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    std::map<tstageobjectspline *="" *,="" tstageobjectspline="">::iterator it =</tstageobjectspline>
Shinya Kitaoka 120a6e
        splines.find(spline);
Shinya Kitaoka 120a6e
    if (it != splines.end()) {
Shinya Kitaoka 120a6e
      // Seems that multiple objects can have the same spline...
Shinya Kitaoka 120a6e
      // BTW, shouldn't this case stop at the continue before ?
Shinya Kitaoka 120a6e
      obj->setSpline(it->second);
Shinya Kitaoka 120a6e
      continue;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // The spline was not found. Clone and add it to the xsheet
Shinya Kitaoka 120a6e
    TStageObjectSpline *newSpline = spline->clone();  // Not checking doClone ?
Shinya Kitaoka 120a6e
    objTree->assignUniqueSplineId(newSpline);
Shinya Kitaoka 120a6e
    objTree->insertSpline(newSpline);
Shinya Kitaoka 120a6e
    obj->setSpline(newSpline);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    splines[spline] = newSpline;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // paste stored path
Shinya Kitaoka 120a6e
  QList<tsplinedataelement *="">::const_iterator splinIt;</tsplinedataelement>
Shinya Kitaoka 120a6e
  for (splinIt = m_splines.begin(); splinIt != m_splines.end(); ++splinIt) {
Shinya Kitaoka 120a6e
    TStageObjectTree *objTree    = xsh->getStageObjectTree();
Shinya Kitaoka 120a6e
    TSplineDataElement *splineEl = *splinIt;
Shinya Kitaoka 120a6e
    TStageObjectSpline *spline   = splineEl->restoreSpline(fxFlags);
Shinya Kitaoka 120a6e
    if (doClone) objTree->assignUniqueSplineId(spline);
Shinya Kitaoka 120a6e
    objTree->insertSpline(spline);
Shinya Kitaoka 120a6e
    restoredSpline.push_back(spline->getId());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  xsh->updateFrameCount();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (pos != TConst::nowhere) {
Shinya Kitaoka 120a6e
    // Update objects positions depending on the externally supplied pos
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPointD middlePos;
Shinya Kitaoka 120a6e
    int count = 0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (i = 0; i < (int)restoredIds.size(); ++i) {
Shinya Kitaoka 120a6e
      TStageObjectId id = restoredIds[i];
Shinya Kitaoka 120a6e
      TStageObject *obj = xsh->getStageObject(id);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TPointD oldPos = obj->getDagNodePos();
Shinya Kitaoka 120a6e
      if (oldPos == TConst::nowhere) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      middlePos += oldPos;
Shinya Kitaoka 120a6e
      ++count;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    middlePos      = TPointD(middlePos.x / count, middlePos.y / count);
Shinya Kitaoka 120a6e
    TPointD offset = pos - middlePos;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    for (i = 0; i < (int)restoredIds.size(); ++i) {
Shinya Kitaoka 120a6e
      TStageObjectId id = restoredIds[i];
Shinya Kitaoka 120a6e
      TStageObject *obj = xsh->getStageObject(id);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TPointD oldPos = obj->getDagNodePos();
Shinya Kitaoka 120a6e
      if (oldPos == TConst::nowhere) continue;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      obj->setDagNodePos(oldPos + offset);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return restoredIds;
Toshihiro Shimizu 890ddd
}