/*
** Command & Conquer Generals(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see .
*/
// CUndoable.h
// Class to handle undo/redo.
// Author: John Ahlquist, April 2001
#pragma once
#ifndef CUNDOABLE_H
#define CUNDOABLE_H
#include "Lib\BaseType.h"
#include "../../gameengine/include/common/MapObject.h"
#include "../../gameengine/include/common/GameCommon.h"
#include "../../gameengine/include/GameLogic/SidesList.h"
#include "RefCount.h"
#include
class PolygonTrigger;
class BuildListInfo;
/*************************************************************************
** Undoable
***************************************************************************/
/// Base command class for all undoable commands. Just the virtual shell.
class Undoable : public RefCountClass
{
protected:
Undoable *mNext;
public:
Undoable(void);
~Undoable(void);
public:
virtual void Do(void)=0; ///< pure virtual.
virtual void Undo(void)=0;///< pure virtual.
virtual void Redo(void);
void LinkNext(Undoable *pNext);
Undoable *GetNext(void) {return mNext;};
};
class CWorldBuilderDoc;
class WorldHeightMapEdit;
class MapObject;
/*************************************************************************
** CWBDocUndoable
***************************************************************************/
/// Command that saves & restores entire height map.
/** An undoable that actually undoes something. Saves and restores the
entire height map. */
class WBDocUndoable : public Undoable
{
protected:
CWorldBuilderDoc *mPDoc; ///< Not ref counted. This undoable should be in a list attached to the doc anyway.
WorldHeightMapEdit *mPNewHeightMapData; ///< ref counted.
WorldHeightMapEdit *mPOldHeightMapData; ///< ref counted.
Bool m_offsetObjects; ///< If true, apply m_objOffset.
Coord3D m_objOffset; ///< Offset to adjust all objects.
public:
WBDocUndoable(CWorldBuilderDoc *pDoc, WorldHeightMapEdit *pNewHtMap, Coord3D *pObjOffset = NULL);
// destructor.
~WBDocUndoable(void);
virtual void Do(void);
virtual void Undo(void);
virtual void Redo(void);
};
/// AddObjectUndoable
/** An undoable that actually undoes something. Adds an object
to the height map. If it is a linked list, adds all objects. */
class AddObjectUndoable : public Undoable
{
protected:
CWorldBuilderDoc *m_pDoc; ///< Not ref counted. This undoable should be in a list attached to the doc anyway.
MapObject *m_objectToAdd;
Int m_numObjects;
Bool m_addedToList;
public:
AddObjectUndoable(CWorldBuilderDoc *pDoc, MapObject *pObjectToAdd);
// destructor.
~AddObjectUndoable(void);
virtual void Do(void);
virtual void Undo(void);
};
/// ModifyObjectUndoable
/** An undoable that actually undoes something. Modifies an object's
location and angle. */
// Helper class
class MoveInfo
{
public:
MoveInfo(MapObject *pObjToMove);
~MoveInfo();
void DoMove(CWorldBuilderDoc *pDoc);
void UndoMove(CWorldBuilderDoc *pDoc);
void SetOffset(CWorldBuilderDoc *pDoc, Real x, Real y);
void SetZOffset(CWorldBuilderDoc *pDoc, Real z);
void RotateTo(CWorldBuilderDoc *pDoc, Real angle);
void SetThingTemplate(CWorldBuilderDoc *pDoc, const ThingTemplate* thing);
void SetName(CWorldBuilderDoc *pDoc, AsciiString name);
public:
MapObject *m_objectToModify;
MoveInfo *m_next;
Real m_newAngle;
Real m_oldAngle;
Coord3D m_newLocation;
Coord3D m_oldLocation;
const ThingTemplate* m_oldThing;
const ThingTemplate* m_newThing;
AsciiString m_oldName;
AsciiString m_newName;
};
class ModifyObjectUndoable : public Undoable
{
protected:
CWorldBuilderDoc* m_pDoc; ///< Not ref counted. This undoable should be in a list attached to the doc anyway.
MoveInfo* m_moveList;
Bool m_inval;
public:
ModifyObjectUndoable(CWorldBuilderDoc *pDoc);
// destructor.
~ModifyObjectUndoable(void);
virtual void Do(void);
virtual void Undo(void);
virtual void Redo(void);
void SetOffset(Real x, Real y);
void SetZOffset(Real z);
void RotateTo(Real angle);
void SetThingTemplate(const ThingTemplate* thing);
void SetName(AsciiString name);
};
/// ModifyFlagsUndoable
/** An undoable that actually undoes something. Modifies an object's
flags. */
// Helper class
class FlagsInfo
{
public:
FlagsInfo(MapObject *pObjToMove, Int flagMask, Int flagValue );
~FlagsInfo();
void DoFlags(CWorldBuilderDoc *pDoc);
void UndoFlags(CWorldBuilderDoc *pDoc);
public:
MapObject *m_objectToModify;
FlagsInfo *m_next;
Int m_flagMask;
Int m_newValue;
Int m_oldValue;
};
class ModifyFlagsUndoable : public Undoable
{
protected:
CWorldBuilderDoc *m_pDoc; ///< Not ref counted. This undoable should be in a list attached to the doc anyway.
FlagsInfo *m_flagsList;
public:
ModifyFlagsUndoable(CWorldBuilderDoc *pDoc, Int flagMask, Int flagValue);
// destructor.
~ModifyFlagsUndoable(void);
virtual void Do(void);
virtual void Undo(void);
virtual void Redo(void);
};
class SidesListUndoable : public Undoable
{
protected:
SidesList m_old, m_new;
CWorldBuilderDoc *m_pDoc; ///< Not ref counted. This undoable should be in a list attached to the doc anyway.
public:
SidesListUndoable(const SidesList& newSL, CWorldBuilderDoc *pDoc);
~SidesListUndoable(void);
virtual void Do(void);
virtual void Undo(void);
};
class DictItemUndoable : public Undoable
{
protected:
Int m_numDictsToModify;
std::vector m_dictToModify;
std::vector m_oldDictData;
Dict m_newDictData;
CWorldBuilderDoc *m_pDoc;
Bool m_inval;
NameKeyType m_key;
public:
static Dict buildSingleItemDict(AsciiString k, Dict::DataType t, AsciiString v);
// if you want to just add/modify/remove a single dict item, pass the item's key.
// if you want to substitute the entire contents of the new dict, pass NAMEKEY_INVALID.
DictItemUndoable(Dict **d, Dict data, NameKeyType key, Int dictsToModify = 1, CWorldBuilderDoc *pDoc = NULL, Bool inval = false);
// destructor.
~DictItemUndoable(void);
virtual void Do(void);
virtual void Undo(void);
};
/// DeleteObjectUndoable
/** An undoable that actually undoes something. Deletes an object. */
// Helper class
class DeleteInfo
{
public:
DeleteInfo(MapObject *pObjToDelete);
~DeleteInfo(void);
void DoDelete(WorldHeightMapEdit *pMap);
void UndoDelete(WorldHeightMapEdit *pMap);
public:
Bool m_didDelete;
MapObject *m_objectToDelete;
MapObject *m_priorObject;
DeleteInfo *m_next;
};
class DeleteObjectUndoable : public Undoable
{
protected:
CWorldBuilderDoc *m_pDoc; ///< Not ref counted. This undoable should be in a list attached to the doc anyway.
DeleteInfo *m_deleteList;
public:
DeleteObjectUndoable(CWorldBuilderDoc *pDoc);
// destructor.
~DeleteObjectUndoable(void);
virtual void Do(void);
virtual void Undo(void);
};
/// AddPolygonUndoable
/** An undoable that actually undoes something. Adds a polygon. */
class AddPolygonUndoable : public Undoable
{
protected:
PolygonTrigger *m_trigger;
Bool m_isTriggerInList;
public:
AddPolygonUndoable( PolygonTrigger *pTrig);
// destructor.
~AddPolygonUndoable(void);
virtual void Do(void);
virtual void Undo(void);
};
/// AddPolygonPointUndoable
/** An undoable that actually undoes something. Adds a polygon. */
class AddPolygonPointUndoable : public Undoable
{
protected:
PolygonTrigger *m_trigger;
ICoord3D m_point;
public:
AddPolygonPointUndoable(PolygonTrigger *pTrig, ICoord3D pt);
// destructor.
~AddPolygonPointUndoable(void);
virtual void Do(void);
virtual void Undo(void);
};
/// ModifyPolygonPointUndoable
/** An undoable that actually undoes something. Modifys a polygon. */
class ModifyPolygonPointUndoable : public Undoable
{
protected:
PolygonTrigger *m_trigger;
Int m_pointIndex;
ICoord3D m_point;
ICoord3D m_savPoint;
public:
ModifyPolygonPointUndoable(PolygonTrigger *pTrig, Int ndx);
// destructor.
~ModifyPolygonPointUndoable(void);
virtual void Do(void);
virtual void Undo(void);
};
/// MovePolygonUndoable
/** An undoable that actually undoes something. Moves a polygon. */
class MovePolygonUndoable : public Undoable
{
protected:
PolygonTrigger *m_trigger;
ICoord3D m_point;
ICoord3D m_offset;
public:
MovePolygonUndoable(PolygonTrigger *pTrig);
// destructor.
~MovePolygonUndoable(void);
virtual void Do(void);
virtual void Undo(void);
void SetOffset(const ICoord3D &offset);
PolygonTrigger *getTrigger(void) {return m_trigger;}
};
/// InsertPolygonPointUndoable
/** An undoable that actually undoes something. Inserts a polygon point. */
class InsertPolygonPointUndoable : public Undoable
{
protected:
PolygonTrigger *m_trigger;
Int m_pointIndex;
ICoord3D m_point;
public:
InsertPolygonPointUndoable(PolygonTrigger *pTrig, ICoord3D pt, Int ndx);
// destructor.
~InsertPolygonPointUndoable(void);
virtual void Do(void);
virtual void Undo(void);
};
/// DeletePolygonPointUndoable
/** An undoable that actually undoes something. Deletes a polygon point. */
class DeletePolygonPointUndoable : public Undoable
{
protected:
PolygonTrigger *m_trigger;
Int m_pointIndex;
ICoord3D m_point;
public:
DeletePolygonPointUndoable(PolygonTrigger *pTrig, Int ndx);
// destructor.
~DeletePolygonPointUndoable(void);
virtual void Do(void);
virtual void Undo(void);
};
/// DeletePolygonUndoable
/** An undoable that actually undoes something. Deletes a polygon. */
class DeletePolygonUndoable : public Undoable
{
protected:
PolygonTrigger *m_trigger;
Bool m_isTriggerInList;
public:
DeletePolygonUndoable(PolygonTrigger *pTrig);
// destructor.
~DeletePolygonUndoable(void);
virtual void Do(void);
virtual void Undo(void);
};
#endif //CUNDOABLE_H