Action.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. //----------------------------------------------------------------------------
  2. //
  3. // Action.cpp - implementation file for the abstract action object, and
  4. // the mgr that holds action objects. (otherwise known as the
  5. // undo manager )
  6. //
  7. //---------------------------------------------------------------------------//
  8. // Copyright (C) Microsoft Corporation. All rights reserved. //
  9. //===========================================================================//
  10. #include "terrain.h"
  11. #include "Action.h"
  12. #include "TerrTxm.h"
  13. ActionUndoMgr* ActionUndoMgr::instance = NULL;
  14. //************************************************************************
  15. // Function: c'tor
  16. // ParamsIn: none
  17. // ParamsOut: none
  18. // Returns: nothing
  19. // Description:
  20. //************************************************************************
  21. ActionUndoMgr::ActionUndoMgr()
  22. {
  23. m_CurrentPos = -1;
  24. m_PosOfLastSave = -1;
  25. gosASSERT( !instance );
  26. instance = this;
  27. }
  28. //************************************************************************
  29. // Function: d'tor
  30. // ParamsIn: none
  31. // ParamsOut: none
  32. // Returns: nothing
  33. // Description: empties list
  34. //************************************************************************
  35. ActionUndoMgr::~ActionUndoMgr()
  36. {
  37. Reset();
  38. }
  39. //***********************************************************************
  40. // Function: AddAction
  41. // ParamsIn: Action to add
  42. // ParamsOut: none
  43. // Returns: void
  44. // Descripition: adds the passed in action to the undo list
  45. //***********************************************************************
  46. void ActionUndoMgr::AddAction( Action* pAction )
  47. {
  48. gosASSERT( pAction );
  49. if ( m_listUndoActions.Count() )
  50. {
  51. if (m_PosOfLastSave > m_CurrentPos)
  52. {
  53. m_PosOfLastSave = -1;
  54. }
  55. ACTION_LIST::EIterator iter = m_listUndoActions.End();
  56. for ( int i = m_listUndoActions.Count() - 1; i > m_CurrentPos; -- i )
  57. {
  58. delete (*iter);
  59. iter--;
  60. m_listUndoActions.DeleteTail();
  61. }
  62. }
  63. m_listUndoActions.Append( pAction );
  64. m_CurrentPos = m_listUndoActions.Count() - 1;
  65. }// fun AddAction
  66. //***********************************************************************
  67. // Function: EmptyUndoList
  68. // ParamsIn: none
  69. // ParamsOut: none
  70. // Returns: void
  71. // Descripition:clears out the undo list
  72. //***********************************************************************
  73. void ActionUndoMgr::EmptyUndoList()
  74. {
  75. for (ACTION_LIST::EIterator pos = m_listUndoActions.Begin(); !pos.IsDone(); pos++ )
  76. {
  77. delete (*pos);
  78. }
  79. m_listUndoActions.Clear();
  80. m_CurrentPos = -1;
  81. m_PosOfLastSave = -1;
  82. }
  83. //***********************************************************************
  84. // Function: GetRedoString
  85. // ParamsIn: none
  86. // ParamsOut: none
  87. // Returns: string to put in the Undo prompt
  88. // Descripition: this is the string that should go in the redo prompt
  89. //***********************************************************************
  90. const char* ActionUndoMgr::GetRedoString()
  91. {
  92. const char* strRet = NULL;
  93. if ( HaveRedo() )
  94. {
  95. ACTION_POS tmp = m_CurrentPos;
  96. tmp++;
  97. ACTION_LIST::EIterator iter = m_listUndoActions.Iterator( tmp );
  98. return (*iter)->getDescription();
  99. }
  100. return strRet;
  101. }
  102. //***********************************************************************
  103. // Function: GetUndoString
  104. // ParamsIn: none
  105. // ParamsOut: none
  106. // Returns: string to put in the Udo prompt
  107. // Descripition: this is the string that should go in the undo prompt
  108. //***********************************************************************
  109. const char* ActionUndoMgr::GetUndoString()
  110. {
  111. const char* strRet = NULL;
  112. if ( HaveUndo() )
  113. {
  114. ACTION_LIST::EIterator iter = m_listUndoActions.Iterator( m_CurrentPos );
  115. return (*iter)->getDescription();
  116. }
  117. return strRet;
  118. }
  119. //***********************************************************************
  120. // Function: HaveRedo
  121. // ParamsIn: none
  122. // ParamsOut: none
  123. // Returns: whether there is a redo action to perform
  124. // Descripition: call to see wherther you can perform a redo
  125. //***********************************************************************
  126. bool ActionUndoMgr::HaveRedo() const
  127. {
  128. return m_CurrentPos + 1 != m_listUndoActions.Count();
  129. }
  130. //***********************************************************************
  131. // Function: HaveUndo
  132. // ParamsIn: none
  133. // ParamsOut: none
  134. // Returns: whether there is undo action to perform
  135. // Descripition: call to see whether you can perform an undo action
  136. //***********************************************************************
  137. bool ActionUndoMgr::HaveUndo() const
  138. {
  139. return m_CurrentPos != -1;
  140. }
  141. //************************************************************************
  142. // Function: Redo
  143. // ParamsIn: none
  144. // ParamsOut; none
  145. // Returns: success of operation
  146. // Description: gets the action at the front of the redo list, performs
  147. // it and adds it to the undo list
  148. //************************************************************************
  149. bool ActionUndoMgr::Redo()
  150. {
  151. gosASSERT( HaveRedo() );
  152. m_CurrentPos++;
  153. ACTION_LIST::EIterator iter = m_listUndoActions.Iterator( m_CurrentPos );
  154. return (*iter)->redo();
  155. }
  156. //************************************************************************
  157. // Function: Reset
  158. // ParamsIn: none
  159. // ParamsOut: none
  160. // Returns: nothing
  161. // Description: Empties all of the actions from the do and undo lists
  162. //************************************************************************
  163. void ActionUndoMgr::Reset()
  164. {
  165. EmptyUndoList();
  166. }
  167. //************************************************************************
  168. // Function: Undo
  169. // ParamsIn: none
  170. // ParamsOut; none
  171. // Returns: success of operation
  172. // Description: gets the action at the front of the undo list, performs
  173. // it and adds it to the redo list
  174. //************************************************************************
  175. bool ActionUndoMgr::Undo()
  176. {
  177. bool bRetVal = false;
  178. gosASSERT( HaveUndo() );
  179. ACTION_LIST::EIterator iter = m_listUndoActions.Iterator( m_CurrentPos );
  180. bRetVal = (*iter)->undo();
  181. m_CurrentPos --;
  182. return bRetVal;
  183. }
  184. //************************************************************************
  185. // Function: NoteThatASaveHasJustOccurred
  186. // ParamsIn: none
  187. // ParamsOut; none
  188. // Returns:
  189. // Description:
  190. //************************************************************************
  191. void ActionUndoMgr::NoteThatASaveHasJustOccurred()
  192. {
  193. m_PosOfLastSave = m_CurrentPos;
  194. }
  195. //************************************************************************
  196. // Function: ThereHasBeenANetChangeFromWhenLastSaved
  197. // ParamsIn: none
  198. // ParamsOut; none
  199. // Returns:
  200. // Description:
  201. //************************************************************************
  202. bool ActionUndoMgr::ThereHasBeenANetChangeFromWhenLastSaved()
  203. {
  204. if (m_PosOfLastSave == m_CurrentPos)
  205. {
  206. return false;
  207. }
  208. else
  209. {
  210. return true;
  211. }
  212. }
  213. //-----------------------------------------------------------------------
  214. // Function: ActionPaintTile::Redo
  215. // ParamsIn: none
  216. // ParamsOut: none
  217. // Returns: success of operation
  218. // Description: redoes a smart paint operation
  219. ////-----------------------------------------------------------------------
  220. bool ActionPaintTile::redo()
  221. {
  222. return doRedo();
  223. }
  224. bool ActionPaintTile::doRedo()
  225. {
  226. for ( VERTEX_INFO_LIST::EIterator iter = vertexInfoList.Begin();
  227. !iter.IsDone(); iter++ )
  228. {
  229. // get current values
  230. int terrain = land->getTerrain( (*iter).row, (*iter).column );
  231. int texture = land->getTexture( (*iter).row, (*iter).column );
  232. float elv = land->getTerrainElevation( (*iter).row, (*iter).column );
  233. Overlays overlay;
  234. unsigned long offset;
  235. // reset to old values
  236. land->terrainTextures->getOverlayInfoFromHandle( (*iter).textureData, overlay, offset );
  237. land->setOverlay( (*iter).row, (*iter).column, overlay, offset );
  238. land->setTerrain( (*iter).row, (*iter).column, (*iter).terrainData );
  239. land->setVertexHeight( (*iter).row * land->realVerticesMapSide + (*iter).column, (*iter).elevation );
  240. // save current valuds
  241. (*iter).terrainData = terrain;
  242. (*iter).textureData = texture;
  243. (*iter).elevation = elv;
  244. }
  245. return true;
  246. }
  247. //-----------------------------------------------------------------------
  248. // Function: Undo
  249. // ParamsIn: none
  250. // ParamsOut: none
  251. // Returns: nothing
  252. // Description: undos a smart paint operation
  253. ////-----------------------------------------------------------------------
  254. bool ActionPaintTile::undo()
  255. {
  256. // actually, undo does the same thing as redo.
  257. return doRedo();
  258. }
  259. //-----------------------------------------------------------------------
  260. // Function: AddTileInfo
  261. // ParamsIn: info to be added to the undo list
  262. // ParamsOut: none
  263. // Returns: nothing
  264. // Description: this function checks to make sure that the object isn't
  265. // already in the list before adding it.
  266. ////-----------------------------------------------------------------------
  267. void ActionPaintTile::addVertexInfo( VertexInfo& info )
  268. {
  269. for( VERTEX_INFO_LIST::EIterator iter = vertexInfoList.Begin();
  270. !iter.IsDone(); iter++ )
  271. {
  272. if ( info.row == (*iter).row && info.column == (*iter).column )
  273. return;
  274. }
  275. vertexInfoList.Append( info );
  276. }
  277. //-----------------------------------------------------------------------
  278. // Function: AddChangedVertexInfo
  279. // ParamsIn: none
  280. // ParamsOut: none
  281. // Returns: nothing
  282. // Description:
  283. ////-----------------------------------------------------------------------
  284. void ActionPaintTile::addChangedVertexInfo( int row, int column )
  285. {
  286. // get the info and add it
  287. for( VERTEX_INFO_LIST::EIterator iter = vertexInfoList.Begin();
  288. !iter.IsDone(); iter++ )
  289. {
  290. if ( row == (*iter).row && column == (*iter).column )
  291. return;
  292. }
  293. // if we made it here, it isn't in there already
  294. VertexInfo info( row, column );
  295. vertexInfoList.Append( info );
  296. }
  297. bool ActionPaintTile::getOldHeight( int row, int column, float& height )
  298. {
  299. for( VERTEX_INFO_LIST::EIterator iter = vertexInfoList.Begin();
  300. !iter.IsDone(); iter++ )
  301. {
  302. if ( row == (*iter).row && column == (*iter).column )
  303. {
  304. height = (*iter).elevation;
  305. return true;
  306. }
  307. }
  308. return false;
  309. }
  310. VertexInfo::VertexInfo( long newRow, long newColumn )
  311. {
  312. gosASSERT( newRow > -1 && newColumn > -1 );
  313. gosASSERT( newRow < land->realVerticesMapSide && newColumn < land->realVerticesMapSide );
  314. row = newRow;
  315. column = newColumn;
  316. elevation = land->getTerrainElevation( row, column );
  317. terrainData = land->getTerrain( row, column );
  318. textureData = land->getTexture( row, column );
  319. }
  320. #ifndef EDITOROBJECTMGR_H
  321. #include "EditorObjectMgr.h"
  322. #endif
  323. ModifyBuildingAction::~ModifyBuildingAction()
  324. {
  325. for ( OBJ_INFO_PTR_LIST::EIterator iter = buildingCopyPtrs.Begin(); !iter.IsDone(); iter++)
  326. {
  327. delete (*iter);
  328. }
  329. }
  330. bool ModifyBuildingAction::doRedo()
  331. {
  332. bool bRetVal = true;
  333. OBJ_INFO_PTR_LIST::EIterator iter2 = buildingPtrs.Begin();
  334. OBJ_APPEAR_LIST::EIterator iter3 = buildingAppearanceCopies.Begin();
  335. OBJ_ID_LIST::EIterator iter4 = buildingIDs.Begin();
  336. for ( OBJ_INFO_PTR_LIST::EIterator iter = buildingCopyPtrs.Begin();
  337. !iter.IsDone(); iter++)
  338. {
  339. //EditorObject *pBuilding = (*iter2);
  340. EditorObject *pBuilding = EditorObjectMgr::instance()->getObjectAtLocation((*iter4).x, (*iter4).y);
  341. if (pBuilding)
  342. {
  343. EditorObject *pBuildingSwap = (*iter)->Clone();
  344. ObjectAppearance AppearanceSwap = (*iter3);
  345. (*iter)->CastAndCopy(*pBuilding);
  346. (*iter3) = (*(pBuilding->appearance()));
  347. (*pBuilding).CastAndCopy(*pBuildingSwap);
  348. (*(pBuilding->appearance())) = AppearanceSwap;
  349. delete pBuildingSwap;
  350. {
  351. /*this is just to make sure the visuals are up-to-date*/
  352. bool d = pBuilding->getDamage();
  353. pBuilding->setDamage(!d);
  354. pBuilding->setDamage(d);
  355. }
  356. long row, column;
  357. pBuilding->getCells(row, column);
  358. EditorObjectMgr::instance()->moveBuilding(pBuilding, row, column);
  359. (*iter4).x = pBuilding->getPosition().x;
  360. (*iter4).y = pBuilding->getPosition().y;
  361. }
  362. else
  363. {
  364. gosASSERT(false);
  365. }
  366. iter2++;
  367. iter3++;
  368. iter4++;
  369. }
  370. return bRetVal;
  371. }
  372. bool ModifyBuildingAction::redo()
  373. {
  374. return doRedo();
  375. }
  376. bool ModifyBuildingAction::undo()
  377. {
  378. // actually, undo does the same thing as redo.
  379. return doRedo();
  380. }
  381. void ModifyBuildingAction::addBuildingInfo(EditorObject& info)
  382. {
  383. if ((0 < buildingPtrs.Count()) && (OBJ_INFO_PTR_LIST::INVALID_ITERATOR != buildingPtrs.Find(&info)))
  384. {
  385. return;
  386. }
  387. // if we made it here, it isn't in there already
  388. EditorObject *pInfoCopy = info.Clone();
  389. buildingCopyPtrs.Append( pInfoCopy );
  390. buildingAppearanceCopies.Append(*(info.appearance()));
  391. buildingPtrs.Append( &info );
  392. CObjectID id;
  393. id.x = info.getPosition().x;
  394. id.y = info.getPosition().y;
  395. buildingIDs.Append(id);
  396. }
  397. void ModifyBuildingAction::updateNotedObjectPositions()
  398. {
  399. OBJ_ID_LIST::EIterator iter4 = buildingIDs.Begin();
  400. for ( OBJ_INFO_PTR_LIST::EIterator iter = buildingPtrs.Begin(); !iter.IsDone(); iter++)
  401. {
  402. EditorObject *pBuilding = (*iter);
  403. if (pBuilding)
  404. {
  405. (*iter4).x = pBuilding->getPosition().x;
  406. (*iter4).y = pBuilding->getPosition().y;
  407. }
  408. else
  409. {
  410. gosASSERT(false);
  411. }
  412. iter4++;
  413. }
  414. }