| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- /*
- ** Command & Conquer Renegade(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 <http://www.gnu.org/licenses/>.
- */
- /***********************************************************************************************
- *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
- ***********************************************************************************************
- * *
- * Project Name : LevelEdit *
- * *
- * $Archive:: /Commando/Code/Tools/LevelEdit/UndoMgr.cpp $*
- * *
- * Author:: Patrick Smith *
- * *
- * $Modtime:: 4/19/01 11:34a $*
- * *
- * $Revision:: 9 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "stdafx.h"
- #include "undomgr.h"
- #include "utils.h"
- #include "nodemgr.h"
- #include "node.h"
- #include "leveleditdoc.h"
- #include "leveleditview.h"
- #include "mover.h"
- #include "zonenode.h"
- #include "damagezonenode.h"
- ////////////////////////////////////////////////////////////////////////////////////
- //
- // Local constants
- //
- ////////////////////////////////////////////////////////////////////////////////////
- const LPCTSTR OPERATION_NAMES[OPERATION_COUNT] =
- {
- "Move",
- "Rotate",
- "Delete",
- "Resize"
- };
- //**************************************************************************************************************//
- //
- // Start of UndoMgrClass
- //
- //**************************************************************************************************************//
- ///////////////////////////////////////////////////////////
- //
- // Free_Buffer_List
- //
- ///////////////////////////////////////////////////////////
- void
- UndoMgrClass::Free_Buffer_List (void)
- {
- // Free each buffer in our array
- for (int index = 0; index < m_iCurrentBuffer; index ++) {
- SAFE_DELETE (m_pBuffers[index]);
- }
- // Reset the current index
- m_iCurrentBuffer = 0;
- return ;
- }
- ///////////////////////////////////////////////////////////
- //
- // Begin_Operation
- //
- ///////////////////////////////////////////////////////////
- void
- UndoMgrClass::Begin_Operation
- (
- OPERATION_TYPE type,
- const NODE_LIST &nodes_affected
- )
- {
- UndoBufferClass *pbuffer = new UndoBufferClass;
- ASSERT (pbuffer != NULL);
- if (pbuffer != NULL) {
- // Pass the identifcation information onto the new buffer
- pbuffer->Set_Operation_Type (type);
- pbuffer->Set_ID (m_dwNextOperationID++);
-
- // Capture the current state of the world in the buffer
- switch (type)
- {
- case OPERATION_MOVE:
- case OPERATION_ROTATE:
- {
- // Record the positions and orientations of the nodes
- pbuffer->Capture_Position (nodes_affected);
- }
- break;
-
- case OPERATION_DELETE:
- {
- // Make 'backups' of the node that will be deleted
- pbuffer->Capture_Existence (nodes_affected);
- }
- break;
- case OPERATION_RESIZE:
- {
- // Record the width, height, and depth of the nodes
- pbuffer->Capture_Dimensions (nodes_affected);
- }
- break;
- }
- // Push this undo buffer onto the end of our 'stack'
- Push_Buffer (pbuffer);
- }
- return ;
- }
- ///////////////////////////////////////////////////////////
- //
- // Push_Buffer
- //
- ///////////////////////////////////////////////////////////
- void
- UndoMgrClass::Push_Buffer (UndoBufferClass *pbuffer)
- {
- // Param OK?
- ASSERT (pbuffer != NULL);
- if (pbuffer != NULL) {
-
- // Can we just add the buffer onto the end of the array?
- if (m_iCurrentBuffer < UNDO_LEVELS) {
- m_pBuffers[m_iCurrentBuffer++] = pbuffer;
- } else {
-
- // Push the first entry off the list and move everything else down a position
- SAFE_DELETE (m_pBuffers[0]);
- ::memmove (&m_pBuffers[0], &m_pBuffers[1], sizeof (UndoBufferClass *) * (UNDO_LEVELS - 1));
- // Now simply add the buffer to the end of the array
- m_iCurrentBuffer = UNDO_LEVELS;
- m_pBuffers[m_iCurrentBuffer-1] = pbuffer;
- }
- }
- return ;
- }
- //////////////////////////////////////////////////////////
- //
- // Get_Next_Undo_Name
- //
- //////////////////////////////////////////////////////////
- LPCTSTR
- UndoMgrClass::Get_Next_Undo_Name (void) const
- {
- LPCTSTR pundo_name = NULL;
- // If we have an undo stack, then return the name of the topmost buffer
- if (m_iCurrentBuffer > 0) {
- pundo_name = m_pBuffers[m_iCurrentBuffer - 1]->Get_Operation_Name ();
- }
- // Return the undo name
- return pundo_name;
- }
- //////////////////////////////////////////////////////////
- //
- // Perform_Undo
- //
- //////////////////////////////////////////////////////////
- void
- UndoMgrClass::Perform_Undo (int ilevels)
- {
- // Loop through the undo levels and restore the world state at each...
- int imin_index = ::max((m_iCurrentBuffer - ilevels), 0);
- for (int index = (m_iCurrentBuffer - 1); index >= imin_index; index --) {
-
- // Undo this level
- m_pBuffers[index]->Restore_State ();
- SAFE_DELETE (m_pBuffers[index]);
- m_iCurrentBuffer --;
- }
- return ;
- }
- //**************************************************************************************************************//
- //
- // End of UndoMgrClass
- //
- //**************************************************************************************************************//
- //**************************************************************************************************************//
- //
- // Start of UndoBufferClass
- //
- //**************************************************************************************************************//
- //////////////////////////////////////////////////////////
- //
- // operator=
- //
- //////////////////////////////////////////////////////////
- const UndoBufferClass::NodeStateClass &
- UndoBufferClass::NodeStateClass::operator= (const NodeStateClass &src)
- {
- MEMBER_ADD (node_ptr, src.node_ptr);
- transform = src.transform;
- dimensions = src.dimensions;
- return *this;
- }
- //////////////////////////////////////////////////////////
- //
- // ~NodeStateClass
- //
- //////////////////////////////////////////////////////////
- UndoBufferClass::NodeStateClass::~NodeStateClass (void)
- {
- MEMBER_RELEASE (node_ptr);
- return ;
- }
- //////////////////////////////////////////////////////////
- //
- // Capture_Dimensions
- //
- //////////////////////////////////////////////////////////
- void
- UndoBufferClass::Capture_Dimensions (const NODE_LIST &node_list)
- {
- // Loop through all the nodes in the list and copy their dimensions
- for (int index = 0; index < node_list.Count (); index ++) {
- NodeClass *node = node_list[index];
- if (node != NULL) {
-
- //
- // This operation only applies to zones. Is this a zone?
- //
- if ( node->Get_Type () == NODE_TYPE_ZONE ||
- node->Get_Type () == NODE_TYPE_DAMAGE_ZONE)
- {
- Box3DClass *box = NULL;
-
- if (node->Get_Type () == NODE_TYPE_ZONE) {
- ZoneNodeClass *zone = (ZoneNodeClass *)node;
- box = zone->Get_Box ();
- } else {
- DamageZoneNodeClass *zone = (DamageZoneNodeClass *)node;
- box = zone->Get_Box ();
- }
- //
- // Copy the node's dimensions
- //
- NodeStateClass state;
- MEMBER_ADD (state.node_ptr, node);
- state.dimensions = box->Get_Dimensions ();
- state.transform = node->Get_Transform ();
- //
- // Add this state information to our list
- //
- m_StateList.Add (state);
- }
- }
- }
- return ;
- }
- //////////////////////////////////////////////////////////
- //
- // Capture_Existence
- //
- //////////////////////////////////////////////////////////
- void
- UndoBufferClass::Capture_Existence (const NODE_LIST &node_list)
- {
- // Loop through all the nodes in the list and copy their pointers
- for (int index = 0; index < node_list.Count (); index ++) {
- NodeClass *node = node_list[index];
- if (node != NULL && node->Get_Type () != NODE_TYPE_WAYPOINT) {
-
- // Store this node in our state manager
- NodeStateClass state;
- MEMBER_ADD (state.node_ptr, node);
- // Add this state information to our list
- m_StateList.Add (state);
- }
- }
- return ;
- }
- //////////////////////////////////////////////////////////
- //
- // Capture_Position
- //
- //////////////////////////////////////////////////////////
- void
- UndoBufferClass::Capture_Position (const NODE_LIST &node_list)
- {
- // Loop through all the nodes in the list and copy their position information
- for (int index = 0; index < node_list.Count (); index ++) {
- NodeClass *node = node_list[index];
- if (node != NULL) {
-
- // Copy the node's state information
- NodeStateClass state;
- MEMBER_ADD (state.node_ptr, node);
- state.transform = node->Get_Transform ();
- // Add this state information to our list
- m_StateList.Add (state);
- }
- }
- return ;
- }
- //////////////////////////////////////////////////////////
- //
- // Restore_State
- //
- //////////////////////////////////////////////////////////
- void
- UndoBufferClass::Restore_State (void)
- {
- // Turn painting off
- CLevelEditView::Allow_Repaint (false);
- //
- // Loop through all the entries in our state list,
- // and restore their state
- //
- for (int index = 0; index < m_StateList.Count (); index ++) {
- // Alias the state structure
- NodeStateClass &state = m_StateList[index];
- // What type of undo operation is this?
- switch (m_Type)
- {
- case OPERATION_MOVE:
- case OPERATION_ROTATE:
- {
- //
- // Reset this node's position and orientation
- //
- if (state.node_ptr != NULL) {
- state.node_ptr->Set_Transform (state.transform);
- }
- }
- break;
- case OPERATION_RESIZE:
- {
- NodeClass *node = state.node_ptr;
- ASSERT (node != NULL);
- //
- // This operation only applies to zones, so if
- // this node is a zone, then resize it.
- //
- if ( node->Get_Type () == NODE_TYPE_ZONE ||
- node->Get_Type () == NODE_TYPE_DAMAGE_ZONE)
- {
- Box3DClass *box = NULL;
-
- if (node->Get_Type () == NODE_TYPE_ZONE) {
- ZoneNodeClass *zone = (ZoneNodeClass *)node;
- box = zone->Get_Box ();
- } else {
- DamageZoneNodeClass *zone = (DamageZoneNodeClass *)node;
- box = zone->Get_Box ();
- }
-
- ASSERT (box != NULL);
- box->Set_Dimensions (state.dimensions);
- node->Set_Transform (state.transform);
- }
- }
- break;
- case OPERATION_DELETE:
- {
- // Add the 'deleted' node back into the world
- ASSERT (state.node_ptr != NULL);
- if (state.node_ptr != NULL) {
- ::Get_Scene_Editor ()->Add_Node (state.node_ptr);
- state.node_ptr->On_Restore ();
- state.node_ptr->Hide (false);
- }
- }
- break;
- }
- }
- // Ensure the main view is updated
- ::Refresh_Main_View ();
- // Turn painting back on
- CLevelEditView::Allow_Repaint (true);
- return ;
- }
- //////////////////////////////////////////////////////////
- //
- // Get_Operation_Name
- //
- //////////////////////////////////////////////////////////
- LPCTSTR
- UndoBufferClass::Get_Operation_Name (void)
- {
- return OPERATION_NAMES[m_Type];
- }
- //**************************************************************************************************************//
- //
- // End of UndoBufferClass
- //
- //**************************************************************************************************************//
|