// TnzLib includes
#include "toonz/tstageobjectcmd.h"
#include "toonz/txsheethandle.h"
#include "toonz/tobjecthandle.h"
#include "toonz/tcolumnhandle.h"
#include "toonz/tfxhandle.h"
#include "toonz/txsheet.h"
#include "toonz/toonzscene.h"
#include "toonz/tstageobjectspline.h"
#include "toonz/tstageobjecttree.h"
#include "toonz/tcamera.h"
#include "toonz/tcolumnfxset.h"
#include "toonz/fxdag.h"
// TnzBase includes
#include "tdoublekeyframe.h"
#include "tfx.h"
// TnzCore includes
#include "tundo.h"
#include "tconvert.h"
#include "historytypes.h"
// Qt includes
#include <QMap>
#include <QString>
namespace {
bool canRemoveFx(const std::set<TFx *> &leaves, TFx *fx) {
for (int i = 0; i < fx->getInputPortCount(); i++) {
TFx *inputFx = fx->getInputPort(i)->getFx();
if (!inputFx) continue;
if (leaves.count(inputFx) > 0) continue;
if (!canRemoveFx(leaves, inputFx)) return false;
}
return fx->getInputPortCount() > 0;
}
//=========================================================
//
// NewCameraUndo
//
//---------------------------------------------------------
class NewCameraUndo final : public TUndo {
TStageObjectId m_cameraId, m_oldCurrentId;
TStageObject *m_stageObject;
TXsheetHandle *m_xshHandle;
TObjectHandle *m_objHandle;
public:
NewCameraUndo(const TStageObjectId &cameraId, TXsheetHandle *xshHandle,
TObjectHandle *objHandle)
: m_cameraId(cameraId)
, m_stageObject(0)
, m_xshHandle(xshHandle)
, m_objHandle(objHandle) {
assert(cameraId.isCamera());
TXsheet *xsh = m_xshHandle->getXsheet();
m_stageObject = xsh->getStageObject(m_cameraId);
m_stageObject->addRef();
m_oldCurrentId = m_objHandle->getObjectId();
}
~NewCameraUndo() { m_stageObject->release(); }
void undo() const override {
TXsheet *xsh = m_xshHandle->getXsheet();
if (m_cameraId == m_objHandle->getObjectId())
m_objHandle->setObjectId(m_oldCurrentId);
xsh->getStageObjectTree()->removeStageObject(m_cameraId);
m_xshHandle->notifyXsheetChanged();
}
void redo() const override {
TXsheet *xsh = m_xshHandle->getXsheet();
xsh->getStageObjectTree()->insertStageObject(m_stageObject);
m_objHandle->setObjectId(m_cameraId);
m_xshHandle->notifyXsheetChanged();
}
int getSize() const override { return sizeof(*this); }
QString getHistoryString() override {
return QObject::tr("New Camera %1")
.arg(QString::fromStdString(m_cameraId.toString()));
}
int getHistoryType() override { return HistoryType::Schematic; }
private:
// not implemented
NewCameraUndo(const NewCameraUndo &);
NewCameraUndo &operator=(const NewCameraUndo &);
};
//=========================================================
//
// NewPegbarUndo
//
//---------------------------------------------------------
class NewPegbarUndo final : public TUndo {
TStageObjectId m_id, m_oldCurrentId;
TStageObject *m_stageObject;
TXsheetHandle *m_xshHandle;
TObjectHandle *m_objHandle;
public:
NewPegbarUndo(const TStageObjectId &id, TXsheetHandle *xshHandle,
TObjectHandle *objHandle)
: m_id(id)
, m_stageObject(0)
, m_xshHandle(xshHandle)
, m_objHandle(objHandle) {
assert(!id.isTable());
TXsheet *xsh = m_xshHandle->getXsheet();
m_stageObject = xsh->getStageObject(m_id);
m_stageObject->addRef();
m_oldCurrentId = m_objHandle->getObjectId();
}
~NewPegbarUndo() { m_stageObject->release(); }
void undo() const override {
TXsheet *xsh = m_xshHandle->getXsheet();
if (m_id == m_objHandle->getObjectId())
m_objHandle->setObjectId(m_oldCurrentId);
xsh->getStageObjectTree()->removeStageObject(m_id);
m_xshHandle->notifyXsheetChanged();
}
void redo() const override {
TXsheet *xsh = m_xshHandle->getXsheet();
xsh->getStageObjectTree()->insertStageObject(m_stageObject);
m_objHandle->setObjectId(m_id);
m_xshHandle->notifyXsheetChanged();
}
int getSize() const override { return sizeof(*this); }
QString getHistoryString() override {
return QObject::tr("New Pegbar %1")
.arg(QString::fromStdString(m_id.toString()));
}
int getHistoryType() override { return HistoryType::Schematic; }
private:
// not implemented
NewPegbarUndo(const NewPegbarUndo &);
NewPegbarUndo &operator=(const NewPegbarUndo &);
};
//===================================================================
//
// SetActiveCameraUndo
//
//-------------------------------------------------------------------
class SetActiveCameraUndo final : public TUndo {
TStageObjectId m_oldCameraId, m_newCameraId;
TXsheetHandle *m_xshHandle;
public:
SetActiveCameraUndo(const TStageObjectId &oldCameraId,
const TStageObjectId &newCameraId,
TXsheetHandle *xshHandle)
: m_oldCameraId(oldCameraId)
, m_newCameraId(newCameraId)
, m_xshHandle(xshHandle) {}
void undo() const override {
TXsheet *xsh = m_xshHandle->getXsheet();
xsh->getStageObjectTree()->setCurrentCameraId(m_oldCameraId);
// make the preview camera same as the final camera
xsh->getStageObjectTree()->setCurrentPreviewCameraId(m_oldCameraId);
m_xshHandle->notifyXsheetChanged();
}
void redo() const override {
TXsheet *xsh = m_xshHandle->getXsheet();
xsh->getStageObjectTree()->setCurrentCameraId(m_newCameraId);
// make the preview camera same as the final camera
xsh->getStageObjectTree()->setCurrentPreviewCameraId(m_newCameraId);
m_xshHandle->notifyXsheetChanged();
}
int getSize() const override { return sizeof(*this); }
QString getHistoryString() override {
return QObject::tr("Set Active Camera %1 > %2")
.arg(QString::fromStdString(m_oldCameraId.toString()))
.arg(QString::fromStdString(m_newCameraId.toString()));
}
int getHistoryType() override { return HistoryType::Schematic; }
};
//===================================================================
//
// RemoveSplineUndo
//
//-------------------------------------------------------------------
class RemoveSplineUndo final : public TUndo {
TStageObjectId m_id;
TStageObjectSpline *m_spline;
std::vector<TStageObjectId> m_ids;
TXsheetHandle *m_xshHandle;
public:
RemoveSplineUndo(TStageObjectSpline *spline, TXsheetHandle *xshHandle)
: m_spline(spline), m_xshHandle(xshHandle) {
m_spline->addRef();
TStageObjectTree *pegbarTree =
m_xshHandle->getXsheet()->getStageObjectTree();
for (int i = 0; i < pegbarTree->getStageObjectCount(); i++) {
TStageObject *pegbar = pegbarTree->getStageObject(i);
if (pegbar->getSpline() == m_spline) m_ids.push_back(pegbar->getId());
}
}
~RemoveSplineUndo() { m_spline->release(); }
void undo() const override {
TXsheet *xsh = m_xshHandle->getXsheet();
xsh->getStageObjectTree()->insertSpline(m_spline);
for (int i = 0; i < (int)m_ids.size(); i++) {
TStageObject *pegbar = xsh->getStageObject(m_ids[i]);
assert(pegbar);
pegbar->setSpline(m_spline);
}
m_xshHandle->notifyXsheetChanged();
}
void redo() const override {
TXsheet *xsh = m_xshHandle->getXsheet();
for (int i = 0; i < (int)m_ids.size(); i++) {
TStageObject *pegbar = xsh->getStageObject(m_ids[i]);
assert(pegbar);
pegbar->setSpline(0);
}
xsh->getStageObjectTree()->removeSpline(m_spline);
m_xshHandle->notifyXsheetChanged();
}
int getSize() const override {
return sizeof *this + sizeof(TStageObjectSpline) +
sizeof(TStageObjectId) * m_ids.size();
}
QString getHistoryString() override {
return QObject::tr("Remove Spline %1")
.arg(QString::fromStdString(m_id.toString()));
}
int getHistoryType() override { return HistoryType::Schematic; }
};
//===================================================================
//
// NewSplineUndo
//
//-------------------------------------------------------------------
class NewSplineUndo final : public TUndo {
TStageObjectId m_id;
TStageObjectSpline *m_spline;
TXsheetHandle *m_xshHandle;
public:
NewSplineUndo(const TStageObjectId &id, TStageObjectSpline *spline,
TXsheetHandle *xshHandle)
: m_id(id), m_spline(spline), m_xshHandle(xshHandle) {
m_spline->addRef();
}
~NewSplineUndo() { m_spline->release(); }
void undo() const override {
TXsheet *xsh = m_xshHandle->getXsheet();
TStageObject *pegbar = xsh->getStageObject(m_id);
assert(pegbar);
pegbar->setSpline(0);
xsh->getStageObjectTree()->removeSpline(m_spline);
m_xshHandle->notifyXsheetChanged();
}
void redo() const override {
TXsheet *xsh = m_xshHandle->getXsheet();
xsh->getStageObjectTree()->insertSpline(m_spline);
TStageObject *pegbar = xsh->getStageObject(m_id);
assert(pegbar);
pegbar->setSpline(m_spline);
m_xshHandle->notifyXsheetChanged();
}
int getSize() const override {
return sizeof *this + sizeof(TStageObjectSpline);
}
QString getHistoryString() override {
return QObject::tr("New Motion Path %1")
.arg(QString::fromStdString(m_spline->getName()));
}
int getHistoryType() override { return HistoryType::Schematic; }
};
//===================================================================
//
// SplineLinkUndo
//
//-------------------------------------------------------------------
class SplineLinkUndo final : public TUndo {
TStageObjectId m_id;
TStageObjectSpline *m_spline;
TXsheetHandle *m_xshHandle;
public:
SplineLinkUndo(const TStageObjectId &id, TStageObjectSpline *spline,
TXsheetHandle *xshHandle)
: m_id(id), m_spline(spline), m_xshHandle(xshHandle) {
m_spline->addRef();
}
~SplineLinkUndo() { m_spline->release(); }
void undo() const override {
TStageObject *object = m_xshHandle->getXsheet()->getStageObject(m_id);
object->setSpline(0);
m_xshHandle->notifyXsheetChanged();
}
void redo() const override {
TStageObject *object = m_xshHandle->getXsheet()->getStageObject(m_id);
object->setSpline(m_spline);
m_xshHandle->notifyXsheetChanged();
}
int getSize() const override {
return sizeof *this + sizeof(TStageObjectSpline);
}
QString getHistoryString() override {
return QObject::tr("Link Motion Path %1 > %2")
.arg(QString::fromStdString(m_spline->getName()))
.arg(QString::fromStdString(m_id.toString()));
}
int getHistoryType() override { return HistoryType::Schematic; }
};
//===================================================================
//
// DeleteSplineLinkUndo
//
//-------------------------------------------------------------------
class RemoveSplineLinkUndo final : public TUndo {
TStageObjectId m_id;
TStageObjectSpline *m_spline;
TXsheetHandle *m_xshHandle;
TObjectHandle *m_objHandle;
public:
RemoveSplineLinkUndo(const TStageObjectId &id, TStageObjectSpline *spline,
TXsheetHandle *xshHandle, TObjectHandle *objHandle)
: m_id(id)
, m_spline(spline)
, m_xshHandle(xshHandle)
, m_objHandle(objHandle) {
m_spline->addRef();
}
~RemoveSplineLinkUndo() { m_spline->release(); }
void undo() const override {
TXsheet *xsh = m_xshHandle->getXsheet();
TStageObjectTree *objTree = xsh->getStageObjectTree();
TStageObject *object = objTree->getStageObject(m_id, false);
if (!object) return;
object->setSpline(m_spline);
if (m_objHandle->getObjectId() == m_id) m_objHandle->setIsSpline(true);
m_xshHandle->notifyXsheetChanged();
}
void redo() const override {
TXsheet *xsh = m_xshHandle->getXsheet();
TStageObjectTree *objTree = xsh->getStageObjectTree();
TStageObject *object = objTree->getStageObject(m_id, false);
if (!object) return;
object->setSpline(0);
if (m_objHandle->getObjectId() == m_id) m_objHandle->setIsSpline(false);
m_xshHandle->notifyXsheetChanged();
}
int getSize() const override {
return sizeof *this + sizeof(TStageObjectSpline);
}
};
//===================================================================
//
// RemovePegbarNodeUndo
//
//-------------------------------------------------------------------
class RemovePegbarNodeUndo final : public TUndo {
TStageObjectId m_objId;
TXshColumnP m_column;
TStageObjectParams *m_params;
QList<TStageObjectId> m_linkedObj;
TXsheetHandle *m_xshHandle;
public:
RemovePegbarNodeUndo(TStageObjectId id, TXsheetHandle *xshHandle)
: TUndo(), m_objId(id), m_xshHandle(xshHandle), m_column(0) {
TXsheet *xsh = xshHandle->getXsheet();
TStageObject *obj = xsh->getStageObject(id);
assert(obj);
m_params = obj->getParams();
if (id.isColumn()) m_column = xsh->getColumn(id.getIndex());
}
~RemovePegbarNodeUndo() { delete m_params; }
void setLinkedObjects(const QList<TStageObjectId> &linkedObj) {
m_linkedObj = linkedObj;
}
void undo() const override {
// reinsert Object
TXsheet *xsh = m_xshHandle->getXsheet();
if (m_objId.isColumn() && m_column)
xsh->insertColumn(m_objId.getIndex(), m_column.getPointer());
TStageObject *obj = xsh->getStageObject(m_objId);
obj->assignParams(m_params);
obj->setParent(m_params->m_parentId);
int i, linkCount = m_linkedObj.size();
for (i = 0; i < linkCount; i++) {
TStageObject *linkedObj = xsh->getStageObject(m_linkedObj[i]);
assert(linkedObj);
linkedObj->setParent(m_objId);
}
m_xshHandle->notifyXsheetChanged();
}
void redo() const override {
TXsheet *xsh = m_xshHandle->getXsheet();
int pegbarsCount = xsh->getStageObjectTree()->getStageObjectCount();
int i;
for (i = 0; i < pegbarsCount; ++i) {
TStageObject *other = xsh->getStageObjectTree()->getStageObject(i);
if (other->getId() == m_objId) continue;
if (other->getParent() == m_objId)
other->setParent(xsh->getStageObjectParent(m_objId));
}
if (m_objId.isColumn())
xsh->removeColumn(m_objId.getIndex());
else
xsh->getStageObjectTree()->removeStageObject(m_objId);
m_xshHandle->notifyXsheetChanged();
}
int getSize() const override {
return sizeof *this + sizeof(TStageObjectParams) + sizeof(m_xshHandle);
}
QString getHistoryString() override {
return QObject::tr("Remove Object %1")
.arg(QString::fromStdString(m_objId.toString()));
}
int getHistoryType() override { return HistoryType::Schematic; }
};
//===================================================================
//
// RemoveColumnsUndo
//
//-------------------------------------------------------------------
class RemoveColumnsUndo final : public TUndo {
std::vector<TFx *> m_deletedFx;
std::vector<TFx *> m_terminalFx;
QMap<TStageObjectId, QList<TFxPort *>> m_columnFxConnections;
QList<TFx *> m_notTerminalColumns;
TXsheetHandle *m_xshHandle;
public:
RemoveColumnsUndo(
const std::vector<TFx *> &deletedFx, const std::vector<TFx *> &terminalFx,
const QMap<TStageObjectId, QList<TFxPort *>> columnFxConnections,
const QList<TFx *> ¬TerminalColumns, TXsheetHandle *xshHandle)
: TUndo()
, m_deletedFx(deletedFx)
, m_terminalFx(terminalFx)
, m_columnFxConnections(columnFxConnections)
, m_notTerminalColumns(notTerminalColumns)
, m_xshHandle(xshHandle) {
int i;
for (i = 0; i < (int)m_deletedFx.size(); i++) m_deletedFx[i]->addRef();
}
~RemoveColumnsUndo() {
int i;
for (i = 0; i < (int)m_deletedFx.size(); i++) m_deletedFx[i]->release();
}
void undo() const override {
TXsheet *xsh = m_xshHandle->getXsheet();
TFxSet *terminalFxs = xsh->getFxDag()->getTerminalFxs();
TFxSet *internalFxs = xsh->getFxDag()->getInternalFxs();
int i;
for (i = 0; i < (int)m_deletedFx.size(); i++)
internalFxs->addFx(m_deletedFx[i]);
for (i = 0; i < (int)m_terminalFx.size(); i++)
terminalFxs->addFx(m_terminalFx[i]);
QMap<TStageObjectId, QList<TFxPort *>>::const_iterator it;
for (it = m_columnFxConnections.begin(); it != m_columnFxConnections.end();
it++) {
TStageObjectId id = it.key();
QList<TFxPort *> ports = it.value();
TXshColumnP column = xsh->getColumn(id.getIndex());
assert(column);
int j;
for (j = 0; j < ports.size(); j++) ports[j]->setFx(column->getFx());
}
for (i = 0; i < m_notTerminalColumns.size(); i++)
terminalFxs->removeFx(m_notTerminalColumns[i]);
m_xshHandle->notifyXsheetChanged();
}
void redo() const override {
TXsheet *xsh = m_xshHandle->getXsheet();
TFxSet *terminalFxs = xsh->getFxDag()->getTerminalFxs();
TFxSet *internalFxs = xsh->getFxDag()->getInternalFxs();
int i;
for (i = 0; i < (int)m_deletedFx.size(); i++)
internalFxs->removeFx(m_deletedFx[i]);
for (i = 0; i < (int)m_terminalFx.size(); i++)
terminalFxs->removeFx(m_terminalFx[i]);
m_xshHandle->notifyXsheetChanged();
}
int getSize() const override {
return sizeof *this + m_deletedFx.size() * sizeof(TFx) +
m_terminalFx.size() * sizeof(TFx) +
m_columnFxConnections.size() *
(sizeof(TStageObjectId) + 10 * sizeof(TFxPort)) +
m_notTerminalColumns.size() * sizeof(TFx) + sizeof(TXsheetHandle);
}
QString getHistoryString() override {
QString str = QObject::tr("Remove Column ");
QMap<TStageObjectId, QList<TFxPort *>>::const_iterator it;
for (it = m_columnFxConnections.begin(); it != m_columnFxConnections.end();
it++) {
TStageObjectId id = it.key();
if (it != m_columnFxConnections.begin())
str += QString::fromStdString(", ");
str += QString::fromStdString(id.toString());
}
return str;
}
int getHistoryType() override { return HistoryType::Schematic; }
};
//===================================================================
//
// UndoGroup
//
//-------------------------------------------------------------------
class UndoGroup final : public TUndo {
QList<TStageObjectId> m_ids;
int m_groupId;
QList<int> m_positions;
TXsheetHandle *m_xshHandle;
public:
UndoGroup(const QList<TStageObjectId> &ids, int groupId,
const QList<int> &positions, TXsheetHandle *xshHandle)
: m_ids(ids)
, m_groupId(groupId)
, m_positions(positions)
, m_xshHandle(xshHandle) {}
~UndoGroup() {}
void undo() const override {
assert(m_ids.size() == m_positions.size());
TStageObjectTree *pegTree = m_xshHandle->getXsheet()->getStageObjectTree();
int i;
for (i = 0; i < m_ids.size(); i++) {
TStageObject *obj = pegTree->getStageObject(m_ids[i], false);
if (obj) {
obj->removeGroupName(m_positions[i]);
obj->removeGroupId(m_positions[i]);
}
}
m_xshHandle->notifyXsheetChanged();
}
void redo() const override {
assert(m_ids.size() == m_positions.size());
TStageObjectTree *pegTree = m_xshHandle->getXsheet()->getStageObjectTree();
int i;
for (i = 0; i < m_ids.size(); i++) {
TStageObject *obj = pegTree->getStageObject(m_ids[i], false);
if (obj) {
obj->setGroupId(m_groupId, m_positions[i]);
obj->setGroupName(L"Group " + std::to_wstring(m_groupId),
m_positions[i]);
}
}
m_xshHandle->notifyXsheetChanged();
}
int getSize() const override { return sizeof *this; }
};
//===================================================================
//
// UndoUngroup
//
//-------------------------------------------------------------------
class UndoUngroup final : public TUndo {
QList<TStageObjectId> m_objsId;
QList<int> m_positions;
int m_groupId;
std::wstring m_groupName;
TXsheetHandle *m_xshHandle;
public:
UndoUngroup(const QList<TStageObject *> &objs, TXsheetHandle *xshHandle)
: m_xshHandle(xshHandle) {
assert(objs.size() > 0);
int i;
for (i = 0; i < objs.size(); i++) {
m_objsId.append(objs[i]->getId());
if (i == 0) {
m_groupId = objs[i]->getGroupId();
m_groupName = objs[i]->getGroupName(false);
}
}
}
~UndoUngroup() {}
void setStackPositions(const QList<int> &positions) {
m_positions = positions;
}
void undo() const override {
assert(m_objsId.size() == m_positions.size());
TStageObjectTree *objTree = m_xshHandle->getXsheet()->getStageObjectTree();
if (!objTree) return;
int i;
for (i = 0; i < m_objsId.size(); i++) {
TStageObject *obj = objTree->getStageObject(m_objsId[i], false);
if (!obj) continue;
obj->setGroupId(m_groupId, m_positions[i]);
obj->setGroupName(m_groupName, m_positions[i]);
}
m_xshHandle->notifyXsheetChanged();
}
void redo() const override {
assert(m_objsId.size() == m_positions.size());
TStageObjectTree *objTree = m_xshHandle->getXsheet()->getStageObjectTree();
if (!objTree) return;
int i;
for (i = 0; i < m_objsId.size(); i++) {
TStageObject *obj = objTree->getStageObject(m_objsId[i], false);
if (!obj) continue;
obj->removeGroupName(m_positions[i]);
obj->removeGroupId(m_positions[i]);
}
m_xshHandle->notifyXsheetChanged();
}
int getSize() const override { return sizeof *this; }
};
//===================================================================
//
// UndoRenameGroup
//
//-------------------------------------------------------------------
class UndoRenameGroup final : public TUndo {
QList<TStageObject *> m_objs;
QList<int> m_positions;
std::wstring m_oldGroupName;
std::wstring m_newGroupName;
TXsheetHandle *m_xshHandle;
public:
UndoRenameGroup(const QList<TStageObject *> &objs,
const QList<int> &positions, const std::wstring &newName,
const std::wstring &oldName, TXsheetHandle *xshHandle)
: m_objs(objs)
, m_newGroupName(newName)
, m_oldGroupName(oldName)
, m_xshHandle(xshHandle)
, m_positions(positions) {
assert(objs.size() > 0);
int i;
for (i = 0; i < m_objs.size(); i++) m_objs[i]->addRef();
}
~UndoRenameGroup() {
int i;
for (i = 0; i < m_objs.size(); i++) m_objs[i]->release();
}
void undo() const override {
assert(m_objs.size() == m_positions.size());
int i;
for (i = 0; i < m_objs.size(); i++) {
m_objs[i]->removeGroupName(m_positions[i]);
m_objs[i]->setGroupName(m_oldGroupName, m_positions[i]);
}
m_xshHandle->notifyXsheetChanged();
}
void redo() const override {
assert(m_objs.size() == m_positions.size());
int i;
for (i = 0; i < m_objs.size(); i++) {
m_objs[i]->removeGroupName(m_positions[i]);
m_objs[i]->setGroupName(m_newGroupName, m_positions[i]);
}
m_xshHandle->notifyXsheetChanged();
}
int getSize() const override { return sizeof *this; }
};
//===================================================================
//
// UndoStatusChange
//
//-------------------------------------------------------------------
class UndoStatusChange final : public TUndo {
TStageObject *m_obj;
TStageObject::Status m_oldStatus, m_newStatus;
TXsheetHandle *m_xshHandle;
public:
UndoStatusChange(TStageObject *obj, TXsheetHandle *xshHandle)
: m_obj(obj), m_xshHandle(xshHandle) {
m_obj->addRef();
// devo fare addref della spline altimenti crasha in uscita
// m_obj non fa addref della spline a lui associata, e quindi crasha perche'
// la spline viene distrutta
// prima di m_obj... sarebbe piu' corretto fare addref della spline quando
// viene settata all'oggetto
// piuttosto che farla qui?
TStageObjectSpline *spline = m_obj->getSpline();
if (spline) spline->addRef();
m_oldStatus = m_obj->getStatus();
}
~UndoStatusChange() {
TStageObjectSpline *spline = m_obj->getSpline();
m_obj->release();
if (spline) spline->release();
}
void onAdd() override { m_newStatus = m_obj->getStatus(); }
void undo() const override {
m_obj->setStatus(m_oldStatus);
m_xshHandle->notifyXsheetChanged();
}
void redo() const override {
m_obj->setStatus(m_newStatus);
m_xshHandle->notifyXsheetChanged();
}
int getSize() const override { return sizeof *this; }
};
//===================================================================
//
// removePegbarNode
//
//-------------------------------------------------------------------
void removeStageObjectNode(const TStageObjectId &id, TXsheetHandle *xshHandle,
TObjectHandle *objHandle, TFxHandle *fxHandle,
bool doUndo = true) {
TXsheet *xsh = xshHandle->getXsheet();
TStageObject *pegbar = xsh->getStageObject(id);
// Lacamera corrente e il tavolo non si devono rimuovere
if (id.isTable() ||
(id.isCamera() && xsh->getStageObjectTree()->getCurrentCameraId() == id))
return;
// stacco tutti i figli e li attacco al padre
QList<TStageObjectId> linkedObjects;
int pegbarsCount = xsh->getStageObjectTree()->getStageObjectCount();
int i;
for (i = 0; i < pegbarsCount; ++i) {
TStageObject *other = xsh->getStageObjectTree()->getStageObject(i);
if (other == pegbar) continue;
if (other->getParent() == id) {
other->setParent(pegbar->getParent());
linkedObjects.push_back(other->getId());
}
}
if (id == objHandle->getObjectId())
objHandle->setObjectId(TStageObjectId::TableId);
RemovePegbarNodeUndo *undo = new RemovePegbarNodeUndo(id, xshHandle);
undo->setLinkedObjects(linkedObjects);
if (id.isColumn())
xsh->removeColumn(id.getIndex());
else
xsh->getStageObjectTree()->removeStageObject(id);
if (doUndo)
TUndoManager::manager()->add(undo);
else
delete undo;
}
//===================================================================
//
// removeColums
//
//-------------------------------------------------------------------
void removeColums(const QVector<int> &columnIndexes, TXsheetHandle *xshHandle,
TObjectHandle *objHandle, TFxHandle *fxHandle,
bool doUndo = true) {
TXsheet *xsh = xshHandle->getXsheet();
int i;
QMap<TStageObjectId, QList<TFxPort *>> columnFxConnection;
std::set<TFx *> leafesFx;
QList<TFx *> notTerminalColumns;
for (i = columnIndexes.size() - 1; i >= 0; i--) {
TStageObjectId id = TStageObjectId::ColumnId(columnIndexes[i]);
TXshColumnP column = xsh->getColumn(id.getIndex());
if (!column) continue;
TFx *columnFx = column->getFx();
if (!columnFx) continue;
int j;
for (j = 0; j < columnFx->getOutputConnectionCount(); j++)
columnFxConnection[id].append(columnFx->getOutputConnection(j));
leafesFx.insert(columnFx);
if (!xsh->getFxDag()->getTerminalFxs()->containsFx(columnFx))
notTerminalColumns.append(columnFx);
}
std::vector<TFx *> fxsToKill;
std::vector<TFx *> terminalFxsToKill;
TFxSet *fxSet = xsh->getFxDag()->getInternalFxs();
for (i = 0; i < fxSet->getFxCount(); i++) {
TFx *fx = fxSet->getFx(i);
if (canRemoveFx(leafesFx, fx)) {
fxsToKill.push_back(fx);
if (xsh->getFxDag()->getTerminalFxs()->containsFx(fx))
terminalFxsToKill.push_back(fx);
}
}
if (doUndo) {
RemoveColumnsUndo *undo =
new RemoveColumnsUndo(fxsToKill, terminalFxsToKill, columnFxConnection,
notTerminalColumns, xshHandle);
TUndoManager::manager()->add(undo);
}
for (i = 0; i < (int)fxsToKill.size(); i++) {
TFx *fx = fxsToKill[i];
if (fx == fxHandle->getFx()) fxHandle->setFx(0);
if (fx->getLinkedFx() != fx) fx->unlinkParams();
int j, outputPortCount = fx->getOutputConnectionCount();
for (j = outputPortCount - 1; j >= 0; j--) {
TFxPort *port = fx->getOutputConnection(j);
std::vector<TFx *>::iterator it =
std::find(fxsToKill.begin(), fxsToKill.end(), port->getOwnerFx());
std::set<TFx *>::iterator it2 =
std::find(leafesFx.begin(), leafesFx.end(), port->getFx());
if (it == fxsToKill.end() && it2 == leafesFx.end()) port->setFx(0);
}
fxSet->removeFx(fx);
xsh->getFxDag()->getTerminalFxs()->removeFx(fx);
}
for (i = columnIndexes.size() - 1; i >= 0; i--)
removeStageObjectNode(TStageObjectId::ColumnId(columnIndexes[i]), xshHandle,
objHandle, fxHandle, doUndo);
}
//===================================================================
//
// removeSpline
//
//-------------------------------------------------------------------
void removeSpline(TStageObjectSpline *spline, TXsheetHandle *xshHandle,
TObjectHandle *objHandle, bool doUndo = true) {
if (doUndo)
TUndoManager::manager()->add(new RemoveSplineUndo(spline, xshHandle));
TStageObjectTree *pegbarTree = xshHandle->getXsheet()->getStageObjectTree();
for (int i = 0; i < pegbarTree->getStageObjectCount(); i++) {
TStageObject *pegbar = pegbarTree->getStageObject(i);
if (pegbar->getSpline() == spline) {
pegbar->setSpline(0);
if (pegbar->getId() == objHandle->getObjectId())
objHandle->setIsSpline(false);
}
}
pegbarTree->removeSpline(spline);
// xshHandle->notifyXsheetChanged();
}
void removeLink(const QPair<TStageObjectId, TStageObjectId> &link,
TXsheetHandle *xshHandle, TObjectHandle *objHandle,
bool doUndo = true) {
TStageObjectTree *objTree = xshHandle->getXsheet()->getStageObjectTree();
if (link.first ==
link.second) { // is a link connecting a spline with an object
TStageObject *object = objTree->getStageObject(link.first, false);
if (!object) return;
TStageObjectSpline *spline = object->getSpline();
assert(spline);
object->setSpline(0);
if (objHandle->getObjectId() == link.first) objHandle->setIsSpline(false);
if (doUndo) {
TUndo *undo =
new RemoveSplineLinkUndo(link.first, spline, xshHandle, objHandle);
TUndoManager::manager()->add(undo);
}
} else {
TStageObject *object = objTree->getStageObject(link.first, false);
TStageObject *parentObject = objTree->getStageObject(link.second, false);
if (!object || !parentObject || object->isGrouped() ||
parentObject->isGrouped())
return;
assert(object->getParent() == parentObject->getId());
TStageObjectCmd::setParent(object->getId(), TStageObjectId::NoneId, "",
xshHandle, doUndo);
}
}
} // namespace
//===================================================================
//
// SetAttributeUndo & sons
//
//-------------------------------------------------------------------
namespace {
//-------------------------------------------------------------------
template <class T>
class SetAttributeUndo : public TUndo {
TStageObjectId m_id;
T m_oldValue, m_newValue;
TXsheetHandle *m_xshHandle;
public:
SetAttributeUndo(const TStageObjectId &id, TXsheetHandle *xshHandle,
T oldValue, T newValue)
: m_id(id)
, m_xshHandle(xshHandle)
, m_oldValue(oldValue)
, m_newValue(newValue) {}
TStageObjectId getId() const { return m_id; }
TStageObject *getStageObject() const {
TStageObject *pegbar = m_xshHandle->getXsheet()->getStageObject(m_id);
assert(pegbar);
return pegbar;
}
virtual void setAttribute(TStageObject *pegbar, T value) const = 0;
void setAttribute(T value) const {
TStageObject *pegbar = getStageObject();
if (pegbar) setAttribute(pegbar, value);
}
void undo() const override {
setAttribute(m_oldValue);
m_xshHandle->notifyXsheetChanged();
}
void redo() const override {
setAttribute(m_newValue);
m_xshHandle->notifyXsheetChanged();
}
int getSize() const override { return sizeof(*this); }
int getHistoryType() override { return HistoryType::Unidentified; }
QString getHistoryString() override {
return QString("%1 %2 : %3 -> %4")
.arg(getActionName())
.arg(QString::fromStdString(getId().toString()))
.arg(getStringFromValue(m_oldValue))
.arg(getStringFromValue(m_newValue));
}
virtual QString getActionName() { return QString(); }
virtual QString getStringFromValue(T value) { return QString(); }
};
//-------------------------------------------------------------------
class StageObjectRenameUndo final : public SetAttributeUndo<std::string> {
public:
StageObjectRenameUndo(const TStageObjectId &id, TXsheetHandle *xshHandle,
std::string oldName, std::string newName)
: SetAttributeUndo<std::string>(id, xshHandle, oldName, newName) {}
void setAttribute(TStageObject *pegbar, std::string name) const override {
pegbar->setName(name);
}
QString getActionName() override { return QString("Rename Object"); }
QString getStringFromValue(std::string value) override {
return QString::fromStdString(value);
}
};
//-------------------------------------------------------------------
class ResetOffsetUndo final : public SetAttributeUndo<TPointD> {
public:
ResetOffsetUndo(const TStageObjectId &id, TXsheetHandle *xshHandle,
const TPointD &oldOffset)
: SetAttributeUndo<TPointD>(id, xshHandle, oldOffset, TPointD()) {}
void setAttribute(TStageObject *pegbar, TPointD offset) const override {
pegbar->setOffset(offset);
}
QString getActionName() override { return QString("Reset Center"); }
QString getStringFromValue(TPointD value) override {
return QString("(%1,%2)")
.arg(QString::number(value.x))
.arg(QString::number(value.y));
}
};
//-------------------------------------------------------------------
class ResetCenterAndOffsetUndo final : public SetAttributeUndo<TPointD> {
public:
ResetCenterAndOffsetUndo(const TStageObjectId &id, TXsheetHandle *xshHandle,
const TPointD &oldOffset)
: SetAttributeUndo<TPointD>(id, xshHandle, oldOffset, TPointD()) {}
void setAttribute(TStageObject *pegbar, TPointD offset) const override {
pegbar->setCenterAndOffset(offset, offset);
}
QString getActionName() override { return QString("Reset Center"); }
QString getStringFromValue(TPointD value) override {
return QString("(%1,%2)")
.arg(QString::number(value.x))
.arg(QString::number(value.y));
}
};
//-------------------------------------------------------------------
class SetHandleUndo final : public SetAttributeUndo<std::string> {
TPointD m_center, m_offset;
TXsheetHandle *m_xshHandle;
public:
SetHandleUndo(const TStageObjectId &id, std::string oldHandle,
std::string newHandle, TXsheetHandle *xshHandle)
: SetAttributeUndo<std::string>(id, xshHandle, oldHandle, newHandle)
, m_xshHandle(xshHandle) {
TStageObject *pegbar = getStageObject();
if (pegbar) pegbar->getCenterAndOffset(m_center, m_offset);
}
void setAttribute(TStageObject *pegbar, std::string handle) const override {
pegbar->setHandle(handle);
}
void undo() const override {
SetAttributeUndo<std::string>::undo();
TStageObject *pegbar = getStageObject();
if (pegbar) pegbar->setCenterAndOffset(m_center, m_offset);
m_xshHandle->notifyXsheetChanged();
}
QString getActionName() override { return QString("Set Handle"); }
QString getStringFromValue(std::string value) override {
return QString::fromStdString(value);
}
};
//-------------------------------------------------------------------
class SetParentHandleUndo final : public SetAttributeUndo<std::string> {
public:
SetParentHandleUndo(const TStageObjectId &id, TXsheetHandle *xshHandle,
std::string oldHandle, std::string newHandle)
: SetAttributeUndo<std::string>(id, xshHandle, oldHandle, newHandle) {}
void setAttribute(TStageObject *pegbar, std::string handle) const override {
pegbar->setParentHandle(handle);
}
QString getActionName() override { return QString("Set Parent Handle"); }
QString getStringFromValue(std::string value) override {
return QString::fromStdString(value);
}
};
//-------------------------------------------------------------------
typedef std::pair<TStageObjectId, std::string> ParentIdAndHandle;
class SetParentUndo final : public SetAttributeUndo<ParentIdAndHandle> {
public:
SetParentUndo(const TStageObjectId &id, TXsheetHandle *xshHandle,
TStageObjectId oldParentId, std::string oldParentHandle,
TStageObjectId newParentId, std::string newParentHandle)
: SetAttributeUndo<ParentIdAndHandle>(
id, xshHandle, ParentIdAndHandle(oldParentId, oldParentHandle),
ParentIdAndHandle(newParentId, newParentHandle)) {}
void setAttribute(TStageObject *pegbar,
ParentIdAndHandle parent) const override {
pegbar->setParent(parent.first);
pegbar->setParentHandle(parent.second);
}
QString getActionName() override { return QString("Set Parent Handle"); }
QString getStringFromValue(ParentIdAndHandle value) override {
return QString("(%1,%2)")
.arg(QString::fromStdString(value.first.toString()))
.arg(QString::fromStdString(value.second));
}
};
//-------------------------------------------------------------------
class ResetPositionUndo final : public TUndo {
TXsheetHandle *m_xshHandle;
TStageObjectId m_id;
TPointD m_center, m_offset;
std::vector<TDoubleKeyframe> m_xKeyframes, m_yKeyframes;
void saveKeyframes(std::vector<TDoubleKeyframe> &keyframes,
const TDoubleParam *param) {
int n = param->getKeyframeCount();
if (n == 0)
keyframes.clear();
else {
keyframes.resize(n);
for (int i = 0; i < n; i++) keyframes[i] = param->getKeyframe(i);
}
}
void deleteAllKeyframes(TDoubleParam *param) const {
while (param->getKeyframeCount() > 0)
param->deleteKeyframe(param->keyframeIndexToFrame(0));
}
void restoreKeyframes(TDoubleParam *param,
const std::vector<TDoubleKeyframe> &keyframes) const {
deleteAllKeyframes(param);
for (int i = 0; i < (int)keyframes.size(); i++)
param->setKeyframe(keyframes[i]);
}
TStageObject *getStageObject() const {
return m_xshHandle->getXsheet()->getStageObject(m_id);
}
public:
ResetPositionUndo(const TStageObjectId &id, TXsheetHandle *xshHandle)
: m_xshHandle(xshHandle), m_id(id) {
TStageObject *stageObject = getStageObject();
if (stageObject) {
stageObject->getCenterAndOffset(m_center, m_offset);
saveKeyframes(m_xKeyframes, stageObject->getParam(TStageObject::T_X));
saveKeyframes(m_yKeyframes, stageObject->getParam(TStageObject::T_Y));
}
}
void undo() const override {
TStageObject *stageObject = getStageObject();
if (!stageObject) return;
stageObject->setCenterAndOffset(m_center, m_offset);
restoreKeyframes(stageObject->getParam(TStageObject::T_X), m_xKeyframes);
restoreKeyframes(stageObject->getParam(TStageObject::T_Y), m_yKeyframes);
m_xshHandle->notifyXsheetChanged();
}
void redo() const override {
TStageObject *stageObject = getStageObject();
if (!stageObject) return;
stageObject->setCenterAndOffset(TPointD(0, 0), TPointD(0, 0));
deleteAllKeyframes(stageObject->getParam(TStageObject::T_X));
deleteAllKeyframes(stageObject->getParam(TStageObject::T_Y));
m_xshHandle->notifyXsheetChanged();
}
int getSize() const override {
return sizeof(*this) +
sizeof(TDoubleKeyframe) *
(m_xKeyframes.size() + m_yKeyframes.size());
}
};
//-------------------------------------------------------------------
} // namespace
//===================================================================
//
// pegbar rename
//
//-------------------------------------------------------------------
void TStageObjectCmd::rename(const TStageObjectId &id, std::string name,
TXsheetHandle *xshHandle) {
TStageObject *pegbar = xshHandle->getXsheet()->getStageObject(id);
if (!pegbar) return;
std::string oldName = pegbar->getName();
if (oldName == name) return;
pegbar->setName(name);
TUndoManager::manager()->add(
new StageObjectRenameUndo(id, xshHandle, oldName, name));
}
//===================================================================
//
// resetOffset
//
//-------------------------------------------------------------------
void TStageObjectCmd::resetOffset(const TStageObjectId &id,
TXsheetHandle *xshHandle) {
TStageObject *peg = xshHandle->getXsheet()->getStageObject(id);
if (!peg) return;
TPointD oldOffset = peg->getOffset();
peg->setOffset(TPointD());
TUndoManager::manager()->add(new ResetOffsetUndo(id, xshHandle, oldOffset));
xshHandle->notifyXsheetChanged();
// TNotifier::instance()->notify(TStageChange());
}
//===================================================================
//
// resetCenterAndOffset
//
//-------------------------------------------------------------------
void TStageObjectCmd::resetCenterAndOffset(const TStageObjectId &id,
TXsheetHandle *xshHandle) {
TStageObject *peg = xshHandle->getXsheet()->getStageObject(id);
if (!peg) return;
TPointD oldOffset = peg->getOffset();
peg->setCenterAndOffset(TPointD(), TPointD());
TUndoManager::manager()->add(
new ResetCenterAndOffsetUndo(id, xshHandle, oldOffset));
xshHandle->notifyXsheetChanged();
}
//===================================================================
//
// resetPosition
//
//-------------------------------------------------------------------
void TStageObjectCmd::resetPosition(const TStageObjectId &id,
TXsheetHandle *xshHandle) {
TStageObject *obj = xshHandle->getXsheet()->getStageObject(id);
if (!obj) return;
TUndo *undo = new ResetPositionUndo(id, xshHandle);
undo->redo();
TUndoManager::manager()->add(undo);
}
//===================================================================
//
// setHandle
//
//-------------------------------------------------------------------
void TStageObjectCmd::setHandle(const TStageObjectId &id, std::string handle,
TXsheetHandle *xshHandle) {
TStageObject *peg = xshHandle->getXsheet()->getStageObject(id);
if (!peg) return;
std::string oldHandle = peg->getHandle();
TUndoManager::manager()->add(
new SetHandleUndo(id, oldHandle, handle, xshHandle));
peg->setHandle(handle);
}
//===================================================================
//
// setParentHandle
//
//-------------------------------------------------------------------
void TStageObjectCmd::setParentHandle(const std::vector<TStageObjectId> &ids,
std::string handle,
TXsheetHandle *xshHandle) {
for (int i = 0; i < (int)ids.size(); i++) {
TStageObjectId id = ids[i];
TStageObject *peg = xshHandle->getXsheet()->getStageObject(id);
if (!peg) continue;
std::string oldHandle = peg->getParentHandle();
peg->setParentHandle(handle);
TUndoManager::manager()->add(
new SetParentHandleUndo(id, xshHandle, oldHandle, handle));
}
}
//===================================================================
//
// setParent
//
//-------------------------------------------------------------------
void TStageObjectCmd::setParent(const TStageObjectId &id,
TStageObjectId parentId,
std::string parentHandle,
TXsheetHandle *xshHandle, bool doUndo) {
if (parentId == TStageObjectId::NoneId) {
if (id.isColumn() || id.isPegbar()) {
parentId = TStageObjectId::TableId;
parentHandle = "B";
}
}
TStageObject *stageObject = xshHandle->getXsheet()->getStageObject(id);
if (!stageObject) return;
TStageObjectId oldParentId = stageObject->getParent();
std::string oldParentHandle;
if (oldParentId != TStageObjectId::NoneId)
oldParentHandle = stageObject->getParentHandle();
stageObject->setParent(parentId);
stageObject->setParentHandle(parentHandle);
if (doUndo) {
TUndoManager *undoManager = TUndoManager::manager();
TUndoManager::manager()->add(new SetParentUndo(
id, xshHandle, oldParentId, oldParentHandle, parentId, parentHandle));
}
}
//===================================================================
//
// setSplineParent
//
//-------------------------------------------------------------------
void TStageObjectCmd::setSplineParent(TStageObjectSpline *spline,
TStageObject *parentObj,
TXsheetHandle *xshHandle) {
TUndoManager::manager()->add(
new SplineLinkUndo(parentObj->getId(), spline, xshHandle));
parentObj->setSpline(spline);
}
//===================================================================
//
// addNewCamera
//
//-------------------------------------------------------------------
void TStageObjectCmd::addNewCamera(TXsheetHandle *xshHandle,
TObjectHandle *objHandle,
QPointF initialPos) {
TXsheet *xsh = xshHandle->getXsheet();
int cameraIndex = 0;
TStageObjectTree *tree = xsh->getStageObjectTree();
TStageObjectId cameraId;
for (;;) {
cameraId = TStageObjectId::CameraId(cameraIndex);
if (tree->getStageObject(cameraId, false) != 0) {
cameraIndex++;
continue;
}
break;
}
// crea la nuova camera
TStageObject *newCameraPegbar = xsh->getStageObject(cameraId);
// make the new peg at the cursor position
if (!initialPos.isNull())
newCameraPegbar->setDagNodePos(TPointD(initialPos.x(), initialPos.y()));
// settings uguali a quelli della camera corrente
TCamera *currentCamera = tree->getCurrentCamera();
*newCameraPegbar->getCamera() = *currentCamera;
TUndoManager::manager()->add(
new NewCameraUndo(cameraId, xshHandle, objHandle));
xshHandle->notifyXsheetChanged();
}
//===================================================================
//
// addNewPegbar
//
//-------------------------------------------------------------------
void TStageObjectCmd::addNewPegbar(TXsheetHandle *xshHandle,
TObjectHandle *objHandle,
QPointF initialPos) {
TXsheet *xsh = xshHandle->getXsheet();
// crea la nuova pegbar
TStageObjectTree *pTree = xsh->getStageObjectTree();
int pegbarIndex = 0;
while (pTree->getStageObject(TStageObjectId::PegbarId(pegbarIndex), false))
pegbarIndex++;
TStageObjectId id = TStageObjectId::PegbarId(pegbarIndex);
TStageObject *obj = pTree->getStageObject(id, true);
if (!initialPos.isNull())
obj->setDagNodePos(TPointD(initialPos.x(), initialPos.y()));
TUndoManager::manager()->add(new NewPegbarUndo(id, xshHandle, objHandle));
xshHandle->notifyXsheetChanged();
}
//===================================================================
//
// setAsActiveCamera
//
//-------------------------------------------------------------------
void TStageObjectCmd::setAsActiveCamera(TXsheetHandle *xshHandle,
TObjectHandle *objHandle) {
TXsheet *xsh = xshHandle->getXsheet();
TStageObjectId currentPegbarId = objHandle->getObjectId();
assert(currentPegbarId.isCamera());
TStageObjectId newCameraId = currentPegbarId;
TStageObjectId oldCameraId = xsh->getStageObjectTree()->getCurrentCameraId();
xsh->getStageObjectTree()->setCurrentCameraId(newCameraId);
// make the preview camera same as the final render camera
xsh->getStageObjectTree()->setCurrentPreviewCameraId(newCameraId);
TUndoManager::manager()->add(
new SetActiveCameraUndo(oldCameraId, newCameraId, xshHandle));
xshHandle->notifyXsheetChanged();
}
//===================================================================
//
// addNewSpline
//
//-------------------------------------------------------------------
void TStageObjectCmd::addNewSpline(TXsheetHandle *xshHandle,
TObjectHandle *objHandle,
TColumnHandle *colHandle,
QPointF initialPos) {
TXsheet *xsh = xshHandle->getXsheet();
TStageObjectSpline *spline = xsh->getStageObjectTree()->createSpline();
if (!initialPos.isNull())
spline->setDagNodePos(TPointD(initialPos.x(), initialPos.y()));
TStageObjectId objId = objHandle->getObjectId();
if (objId == TStageObjectId::NoneId) {
int col = colHandle->getColumnIndex();
if (col >= 0) objId = TStageObjectId::ColumnId(col);
}
if (objId != TStageObjectId::NoneId) {
TStageObject *pegbar = xsh->getStageObject(objId);
assert(pegbar);
pegbar->setSpline(spline);
TUndoManager::manager()->add(new NewSplineUndo(objId, spline, xshHandle));
}
xshHandle->notifyXsheetChanged();
}
//===================================================================
//
// deleteSelection
//
//-------------------------------------------------------------------
void TStageObjectCmd::deleteSelection(
const std::vector<TStageObjectId> &objIds,
const std::list<QPair<TStageObjectId, TStageObjectId>> &links,
const std::list<int> &splineIds, TXsheetHandle *xshHandle,
TObjectHandle *objHandle, TFxHandle *fxHandle, bool doUndo) {
if (doUndo) TUndoManager::manager()->beginBlock();
QVector<int> columnIndexes;
QVector<int> pegbarIndexes;
QVector<int> cameraIndexes;
std::vector<TStageObjectId>::const_iterator it2;
for (it2 = objIds.begin(); it2 != objIds.end(); it2++) {
if (it2->isColumn()) columnIndexes.append(it2->getIndex());
if (it2->isPegbar()) pegbarIndexes.append(it2->getIndex());
if (it2->isCamera()) cameraIndexes.append(it2->getIndex());
}
if (!columnIndexes.isEmpty()) qSort(columnIndexes);
if (!pegbarIndexes.isEmpty()) qSort(pegbarIndexes);
if (!cameraIndexes.isEmpty()) qSort(cameraIndexes);
// remove all selected objects
removeColums(columnIndexes, xshHandle, objHandle, fxHandle, doUndo);
int i;
for (i = pegbarIndexes.size() - 1; i >= 0; i--)
removeStageObjectNode(TStageObjectId::PegbarId(pegbarIndexes[i]), xshHandle,
objHandle, fxHandle, doUndo);
for (i = cameraIndexes.size() - 1; i >= 0; i--)
removeStageObjectNode(TStageObjectId::CameraId(cameraIndexes[i]), xshHandle,
objHandle, fxHandle, doUndo);
std::list<QPair<TStageObjectId, TStageObjectId>>::const_iterator it1;
for (it1 = links.begin(); it1 != links.end() && objIds.empty(); it1++)
removeLink(*it1, xshHandle, objHandle, doUndo);
std::list<int>::const_iterator it3;
TStageObjectTree *objTree = xshHandle->getXsheet()->getStageObjectTree();
for (it3 = splineIds.begin(); it3 != splineIds.end(); it3++) {
int splineCount = objTree->getSplineCount();
int i;
for (i = 0; i < splineCount; i++) {
TStageObjectSpline *spline = objTree->getSpline(i);
if (spline->getId() == *it3) {
removeSpline(spline, xshHandle, objHandle, doUndo);
break;
}
}
}
if (doUndo) TUndoManager::manager()->endBlock();
xshHandle->notifyXsheetChanged();
}
//===================================================================
//
// group
//
//-------------------------------------------------------------------
void TStageObjectCmd::group(const QList<TStageObjectId> ids,
TXsheetHandle *xshHandle) {
TStageObjectTree *pegTree = xshHandle->getXsheet()->getStageObjectTree();
int groupId = pegTree->getNewGroupId();
int i;
QList<int> positions;
for (i = 0; i < ids.size(); i++) {
TStageObject *obj = pegTree->getStageObject(ids[i], false);
if (obj) {
int position = obj->setGroupId(groupId);
obj->setGroupName(L"Group " + std::to_wstring(groupId));
positions.append(position);
}
}
TUndoManager::manager()->add(
new UndoGroup(ids, groupId, positions, xshHandle));
}
//===================================================================
//
// ungroup
//
//-------------------------------------------------------------------
void TStageObjectCmd::ungroup(int groupId, TXsheetHandle *xshHandle) {
TStageObjectTree *objTree = xshHandle->getXsheet()->getStageObjectTree();
if (!objTree) return;
QList<TStageObject *> objs;
int i;
for (i = 0; i < objTree->getStageObjectCount(); i++) {
TStageObject *obj = objTree->getStageObject(i);
if (!obj) continue;
if (obj->getGroupId() == groupId) objs.push_back(obj);
}
QList<int> positions;
UndoUngroup *undo = new UndoUngroup(objs, xshHandle);
TUndoManager::manager()->add(undo);
for (i = 0; i < objs.size(); i++) {
TStageObject *obj = objs[i];
if (obj) {
obj->removeGroupName();
int position = obj->removeGroupId();
positions.append(position);
}
}
undo->setStackPositions(positions);
}
//===================================================================
//
// renameGroup
//
//-------------------------------------------------------------------
void TStageObjectCmd::renameGroup(const QList<TStageObject *> objs,
const std::wstring &name, bool fromEditor,
TXsheetHandle *xshHandle) {
std::wstring oldName;
TStageObjectTree *pegTree = xshHandle->getXsheet()->getStageObjectTree();
QList<int> positions;
int i;
for (i = 0; i < objs.size(); i++) {
if (i == 0) oldName = objs[i]->getGroupName(fromEditor);
int position = objs[i]->removeGroupName(fromEditor);
objs[i]->setGroupName(name, position);
positions.push_back(position);
}
TUndoManager::manager()->add(
new UndoRenameGroup(objs, positions, name, oldName, xshHandle));
}
//===================================================================
//
// renameGroup
//
//-------------------------------------------------------------------
void TStageObjectCmd::duplicateObject(const QList<TStageObjectId> ids,
TXsheetHandle *xshHandle) {
TXsheet *xsh = xshHandle->getXsheet();
TStageObjectTree *objTree = xsh->getStageObjectTree();
int i, objCount = ids.size();
for (i = 0; i < objCount; i++) {
TStageObjectId id = ids[i];
TStageObject *obj = objTree->getStageObject(id, false);
assert(obj);
TStageObject *duplicatedObj = 0;
if (id.isPegbar() || id.isCamera()) {
int index = 0;
TStageObjectId newId;
for (;;) {
newId = id.isPegbar() ? TStageObjectId::PegbarId(index)
: TStageObjectId::CameraId(index);
if (objTree->getStageObject(newId, false)) {
index++;
continue;
}
break;
}
duplicatedObj = xsh->getStageObject(newId);
TStageObjectParams *params = obj->getParams();
duplicatedObj->assignParams(params);
delete params;
if (id.isCamera()) *(duplicatedObj->getCamera()) = *(obj->getCamera());
}
}
xshHandle->notifyXsheetChanged();
}
//-------------------------------------------------------------------
void TStageObjectCmd::enableSplineAim(TStageObject *obj, int state,
TXsheetHandle *xshHandle) {
UndoStatusChange *undo = new UndoStatusChange(obj, xshHandle);
obj->enableAim(state != 2);
TUndoManager::manager()->add(undo);
}
//-------------------------------------------------------------------
void TStageObjectCmd::enableSplineUppk(TStageObject *obj, bool toggled,
TXsheetHandle *xshHandle) {
UndoStatusChange *undo = new UndoStatusChange(obj, xshHandle);
obj->enableUppk(toggled);
TUndoManager::manager()->add(undo);
}