Undo.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "qe3.h"
  23. #include "Radiant.h"
  24. /*
  25. QERadiant Undo/Redo
  26. basic setup:
  27. <-g_undolist---------g_lastundo> <---map data---> <-g_lastredo---------g_redolist->
  28. undo/redo on the world_entity is special, only the epair changes are remembered
  29. and the world entity never gets deleted.
  30. FIXME: maybe reset the Undo system at map load
  31. maybe also reset the entityId at map load
  32. */
  33. typedef struct undo_s
  34. {
  35. double time; //time operation was performed
  36. int id; //every undo has an unique id
  37. int done; //true when undo is build
  38. char *operation; //name of the operation
  39. brush_t brushlist; //deleted brushes
  40. entity_t entitylist; //deleted entities
  41. struct undo_s *prev, *next; //next and prev undo in list
  42. } undo_t;
  43. undo_t *g_undolist; //first undo in the list
  44. undo_t *g_lastundo; //last undo in the list
  45. undo_t *g_redolist; //first redo in the list
  46. undo_t *g_lastredo; //last undo in list
  47. int g_undoMaxSize = 64; //maximum number of undos
  48. int g_undoSize = 0; //number of undos in the list
  49. int g_undoMaxMemorySize = 2*1024*1024; //maximum undo memory (default 2 MB)
  50. int g_undoMemorySize = 0; //memory size of undo buffer
  51. int g_undoId = 1; //current undo ID (zero is invalid id)
  52. int g_redoId = 1; //current redo ID (zero is invalid id)
  53. /*
  54. =============
  55. Undo_MemorySize
  56. =============
  57. */
  58. int Undo_MemorySize(void)
  59. {
  60. /*
  61. int size;
  62. undo_t *undo;
  63. brush_t *pBrush;
  64. entity_t *pEntity;
  65. size = 0;
  66. for (undo = g_undolist; undo; undo = undo->next)
  67. {
  68. for (pBrush = undo->brushlist.next ; pBrush != NULL && pBrush != &undo->brushlist ; pBrush = pBrush->next)
  69. {
  70. size += Brush_MemorySize(pBrush);
  71. }
  72. for (pEntity = undo->entitylist.next; pEntity != NULL && pEntity != &undo->entitylist; pEntity = pEntity->next)
  73. {
  74. size += Entity_MemorySize(pEntity);
  75. }
  76. size += sizeof(undo_t);
  77. }
  78. return size;
  79. */
  80. return g_undoMemorySize;
  81. }
  82. /*
  83. =============
  84. Undo_ClearRedo
  85. =============
  86. */
  87. void Undo_ClearRedo(void)
  88. {
  89. undo_t *redo, *nextredo;
  90. brush_t *pBrush, *pNextBrush;
  91. entity_t *pEntity, *pNextEntity;
  92. for (redo = g_redolist; redo; redo = nextredo)
  93. {
  94. nextredo = redo->next;
  95. for (pBrush = redo->brushlist.next ; pBrush != NULL && pBrush != &redo->brushlist ; pBrush = pNextBrush)
  96. {
  97. pNextBrush = pBrush->next;
  98. Brush_Free(pBrush);
  99. }
  100. for (pEntity = redo->entitylist.next; pEntity != NULL && pEntity != &redo->entitylist; pEntity = pNextEntity)
  101. {
  102. pNextEntity = pEntity->next;
  103. Entity_Free(pEntity);
  104. }
  105. Mem_Free(redo);
  106. }
  107. g_redolist = NULL;
  108. g_lastredo = NULL;
  109. g_redoId = 1;
  110. }
  111. /*
  112. =============
  113. Undo_Clear
  114. Clears the undo buffer.
  115. =============
  116. */
  117. void Undo_Clear(void)
  118. {
  119. undo_t *undo, *nextundo;
  120. brush_t *pBrush, *pNextBrush;
  121. entity_t *pEntity, *pNextEntity;
  122. Undo_ClearRedo();
  123. for (undo = g_undolist; undo; undo = nextundo)
  124. {
  125. nextundo = undo->next;
  126. for (pBrush = undo->brushlist.next ; pBrush != NULL && pBrush != &undo->brushlist ; pBrush = pNextBrush)
  127. {
  128. pNextBrush = pBrush->next;
  129. g_undoMemorySize -= Brush_MemorySize(pBrush);
  130. Brush_Free(pBrush);
  131. }
  132. for (pEntity = undo->entitylist.next; pEntity != NULL && pEntity != &undo->entitylist; pEntity = pNextEntity)
  133. {
  134. pNextEntity = pEntity->next;
  135. g_undoMemorySize -= Entity_MemorySize(pEntity);
  136. Entity_Free(pEntity);
  137. }
  138. g_undoMemorySize -= sizeof(undo_t);
  139. Mem_Free(undo);
  140. }
  141. g_undolist = NULL;
  142. g_lastundo = NULL;
  143. g_undoSize = 0;
  144. g_undoMemorySize = 0;
  145. g_undoId = 1;
  146. }
  147. /*
  148. =============
  149. Undo_SetMaxSize
  150. =============
  151. */
  152. void Undo_SetMaxSize(int size)
  153. {
  154. Undo_Clear();
  155. if (size < 1) g_undoMaxSize = 1;
  156. else g_undoMaxSize = size;
  157. }
  158. /*
  159. =============
  160. Undo_GetMaxSize
  161. =============
  162. */
  163. int Undo_GetMaxSize(void)
  164. {
  165. return g_undoMaxSize;
  166. }
  167. /*
  168. =============
  169. Undo_SetMaxMemorySize
  170. =============
  171. */
  172. void Undo_SetMaxMemorySize(int size)
  173. {
  174. Undo_Clear();
  175. if (size < 1024) g_undoMaxMemorySize = 1024;
  176. else g_undoMaxMemorySize = size;
  177. }
  178. /*
  179. =============
  180. Undo_GetMaxMemorySize
  181. =============
  182. */
  183. int Undo_GetMaxMemorySize(void)
  184. {
  185. return g_undoMaxMemorySize;
  186. }
  187. /*
  188. =============
  189. Undo_FreeFirstUndo
  190. =============
  191. */
  192. void Undo_FreeFirstUndo(void)
  193. {
  194. undo_t *undo;
  195. brush_t *pBrush, *pNextBrush;
  196. entity_t *pEntity, *pNextEntity;
  197. //remove the oldest undo from the undo buffer
  198. undo = g_undolist;
  199. g_undolist = g_undolist->next;
  200. g_undolist->prev = NULL;
  201. //
  202. for (pBrush = undo->brushlist.next ; pBrush != NULL && pBrush != &undo->brushlist ; pBrush = pNextBrush)
  203. {
  204. pNextBrush = pBrush->next;
  205. g_undoMemorySize -= Brush_MemorySize(pBrush);
  206. Brush_Free(pBrush);
  207. }
  208. for (pEntity = undo->entitylist.next; pEntity != NULL && pEntity != &undo->entitylist; pEntity = pNextEntity)
  209. {
  210. pNextEntity = pEntity->next;
  211. g_undoMemorySize -= Entity_MemorySize(pEntity);
  212. Entity_Free(pEntity);
  213. }
  214. g_undoMemorySize -= sizeof(undo_t);
  215. Mem_Free(undo);
  216. g_undoSize--;
  217. }
  218. /*
  219. =============
  220. Undo_GeneralStart
  221. =============
  222. */
  223. void Undo_GeneralStart(char *operation)
  224. {
  225. undo_t *undo;
  226. brush_t *pBrush;
  227. entity_t *pEntity;
  228. if (g_lastundo)
  229. {
  230. if (!g_lastundo->done)
  231. {
  232. common->Printf("Undo_Start: WARNING last undo not finished.\n");
  233. }
  234. }
  235. undo = (undo_t *) Mem_ClearedAlloc(sizeof(undo_t));
  236. if (!undo) return;
  237. memset(undo, 0, sizeof(undo_t));
  238. undo->brushlist.next = &undo->brushlist;
  239. undo->brushlist.prev = &undo->brushlist;
  240. undo->entitylist.next = &undo->entitylist;
  241. undo->entitylist.prev = &undo->entitylist;
  242. if (g_lastundo) g_lastundo->next = undo;
  243. else g_undolist = undo;
  244. undo->prev = g_lastundo;
  245. undo->next = NULL;
  246. g_lastundo = undo;
  247. undo->time = Sys_DoubleTime();
  248. //
  249. if (g_undoId > g_undoMaxSize * 2) g_undoId = 1;
  250. if (g_undoId <= 0) g_undoId = 1;
  251. undo->id = g_undoId++;
  252. undo->done = false;
  253. undo->operation = operation;
  254. //reset the undo IDs of all brushes using the new ID
  255. for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush = pBrush->next)
  256. {
  257. if (pBrush->undoId == undo->id)
  258. {
  259. pBrush->undoId = 0;
  260. }
  261. }
  262. for (pBrush = selected_brushes.next; pBrush != NULL && pBrush != &selected_brushes; pBrush = pBrush->next)
  263. {
  264. if (pBrush->undoId == undo->id)
  265. {
  266. pBrush->undoId = 0;
  267. }
  268. }
  269. //reset the undo IDs of all entities using thew new ID
  270. for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next)
  271. {
  272. if (pEntity->undoId == undo->id)
  273. {
  274. pEntity->undoId = 0;
  275. }
  276. }
  277. g_undoMemorySize += sizeof(undo_t);
  278. g_undoSize++;
  279. //undo buffer is bound to a max
  280. if (g_undoSize > g_undoMaxSize)
  281. {
  282. Undo_FreeFirstUndo();
  283. }
  284. }
  285. /*
  286. =============
  287. Undo_BrushInUndo
  288. =============
  289. */
  290. int Undo_BrushInUndo(undo_t *undo, brush_t *brush)
  291. {
  292. brush_t *b;
  293. for (b = undo->brushlist.next; b != &undo->brushlist; b = b->next)
  294. {
  295. if (b == brush) return true;
  296. }
  297. return false;
  298. }
  299. /*
  300. =============
  301. Undo_EntityInUndo
  302. =============
  303. */
  304. int Undo_EntityInUndo(undo_t *undo, entity_t *ent)
  305. {
  306. entity_t *e;
  307. for (e = undo->entitylist.next; e != &undo->entitylist; e = e->next)
  308. {
  309. if (e == ent) return true;
  310. }
  311. return false;
  312. }
  313. /*
  314. =============
  315. Undo_Start
  316. =============
  317. */
  318. void Undo_Start(char *operation)
  319. {
  320. Undo_ClearRedo();
  321. Undo_GeneralStart(operation);
  322. }
  323. /*
  324. =============
  325. Undo_AddBrush
  326. =============
  327. */
  328. void Undo_AddBrush(brush_t *pBrush)
  329. {
  330. if (!g_lastundo)
  331. {
  332. Sys_Status("Undo_AddBrushList: no last undo.\n");
  333. return;
  334. }
  335. if (g_lastundo->entitylist.next != &g_lastundo->entitylist)
  336. {
  337. Sys_Status("Undo_AddBrushList: WARNING adding brushes after entity.\n");
  338. }
  339. //if the brush is already in the undo
  340. if (Undo_BrushInUndo(g_lastundo, pBrush))
  341. return;
  342. //clone the brush
  343. brush_t* pClone = Brush_FullClone(pBrush);
  344. //save the ID of the owner entity
  345. pClone->ownerId = pBrush->owner->entityId;
  346. if (pBrush->owner && !(pBrush->owner->eclass->nShowFlags & ECLASS_WORLDSPAWN)) {
  347. Undo_AddEntity(pBrush->owner);
  348. }
  349. //save the old undo ID for previous undos
  350. pClone->undoId = pBrush->undoId;
  351. Brush_AddToList (pClone, &g_lastundo->brushlist);
  352. //
  353. g_undoMemorySize += Brush_MemorySize(pClone);
  354. }
  355. /*
  356. =============
  357. Undo_AddBrushList
  358. =============
  359. */
  360. void Undo_AddBrushList(brush_t *brushlist)
  361. {
  362. brush_t *pBrush;
  363. if (!g_lastundo)
  364. {
  365. Sys_Status("Undo_AddBrushList: no last undo.\n");
  366. return;
  367. }
  368. if (g_lastundo->entitylist.next != &g_lastundo->entitylist)
  369. {
  370. Sys_Status("Undo_AddBrushList: WARNING adding brushes after entity.\n");
  371. }
  372. //copy the brushes to the undo
  373. for (pBrush = brushlist->next ; pBrush != NULL && pBrush != brushlist; pBrush=pBrush->next)
  374. {
  375. //if the brush is already in the undo
  376. if (Undo_BrushInUndo(g_lastundo, pBrush))
  377. continue;
  378. //clone the brush
  379. brush_t* pClone = Brush_FullClone(pBrush);
  380. //save the ID of the owner entity
  381. pClone->ownerId = pBrush->owner->entityId;
  382. //save the old undo ID from previous undos
  383. pClone->undoId = pBrush->undoId;
  384. if ( pBrush->owner && pBrush->owner != world_entity ) {
  385. Undo_AddEntity(pBrush->owner);
  386. }
  387. Brush_AddToList (pClone, &g_lastundo->brushlist);
  388. //
  389. g_undoMemorySize += Brush_MemorySize(pClone);
  390. }
  391. }
  392. /*
  393. =============
  394. Undo_EndBrush
  395. =============
  396. */
  397. void Undo_EndBrush(brush_t *pBrush)
  398. {
  399. if (!g_lastundo)
  400. {
  401. //Sys_Status("Undo_End: no last undo.\n");
  402. return;
  403. }
  404. if (g_lastundo->done)
  405. {
  406. //Sys_Status("Undo_End: last undo already finished.\n");
  407. return;
  408. }
  409. pBrush->undoId = g_lastundo->id;
  410. }
  411. /*
  412. =============
  413. Undo_EndBrushList
  414. =============
  415. */
  416. void Undo_EndBrushList(brush_t *brushlist)
  417. {
  418. if (!g_lastundo)
  419. {
  420. //Sys_Status("Undo_End: no last undo.\n");
  421. return;
  422. }
  423. if (g_lastundo->done)
  424. {
  425. //Sys_Status("Undo_End: last undo already finished.\n");
  426. return;
  427. }
  428. for (brush_t* pBrush = brushlist->next; pBrush != NULL && pBrush != brushlist; pBrush=pBrush->next)
  429. {
  430. pBrush->undoId = g_lastundo->id;
  431. }
  432. }
  433. /*
  434. =============
  435. Undo_AddEntity
  436. =============
  437. */
  438. void Undo_AddEntity(entity_t *entity)
  439. {
  440. entity_t* pClone;
  441. if (!g_lastundo)
  442. {
  443. Sys_Status("Undo_AddEntity: no last undo.\n");
  444. return;
  445. }
  446. //if the entity is already in the undo
  447. if (Undo_EntityInUndo(g_lastundo, entity))
  448. return;
  449. //clone the entity
  450. pClone = Entity_Clone(entity);
  451. //NOTE: Entity_Clone adds the entity to the entity list
  452. // so we remove it from that list here
  453. Entity_RemoveFromList(pClone);
  454. //save the old undo ID for previous undos
  455. pClone->undoId = entity->undoId;
  456. //save the entity ID (we need a full clone)
  457. pClone->entityId = entity->entityId;
  458. //
  459. Entity_AddToList(pClone, &g_lastundo->entitylist);
  460. //
  461. g_undoMemorySize += Entity_MemorySize(pClone);
  462. }
  463. /*
  464. =============
  465. Undo_EndEntity
  466. =============
  467. */
  468. void Undo_EndEntity(entity_t *entity)
  469. {
  470. if (!g_lastundo)
  471. {
  472. //Sys_Status("Undo_End: no last undo.\n");
  473. return;
  474. }
  475. if (g_lastundo->done)
  476. {
  477. //Sys_Status("Undo_End: last undo already finished.\n");
  478. return;
  479. }
  480. if (entity == world_entity)
  481. {
  482. //Sys_Status("Undo_AddEntity: undo on world entity.\n");
  483. //NOTE: we never delete the world entity when undoing an operation
  484. // we only transfer the epairs
  485. return;
  486. }
  487. entity->undoId = g_lastundo->id;
  488. }
  489. /*
  490. =============
  491. Undo_End
  492. =============
  493. */
  494. void Undo_End(void)
  495. {
  496. if (!g_lastundo)
  497. {
  498. //Sys_Status("Undo_End: no last undo.\n");
  499. return;
  500. }
  501. if (g_lastundo->done)
  502. {
  503. //Sys_Status("Undo_End: last undo already finished.\n");
  504. return;
  505. }
  506. g_lastundo->done = true;
  507. //undo memory size is bound to a max
  508. while (g_undoMemorySize > g_undoMaxMemorySize)
  509. {
  510. //always keep one undo
  511. if (g_undolist == g_lastundo) break;
  512. Undo_FreeFirstUndo();
  513. }
  514. //
  515. //Sys_Status("undo size = %d, undo memory = %d\n", g_undoSize, g_undoMemorySize);
  516. }
  517. /*
  518. =============
  519. Undo_Undo
  520. =============
  521. */
  522. void Undo_Undo(void)
  523. {
  524. undo_t *undo, *redo;
  525. brush_t *pBrush, *pNextBrush;
  526. entity_t *pEntity, *pNextEntity, *pUndoEntity;
  527. if (!g_lastundo)
  528. {
  529. Sys_Status("Nothing left to undo.\n");
  530. return;
  531. }
  532. if (!g_lastundo->done)
  533. {
  534. Sys_Status("Undo_Undo: WARNING: last undo not yet finished!\n");
  535. }
  536. // get the last undo
  537. undo = g_lastundo;
  538. if (g_lastundo->prev) g_lastundo->prev->next = NULL;
  539. else g_undolist = NULL;
  540. g_lastundo = g_lastundo->prev;
  541. //allocate a new redo
  542. redo = (undo_t *) Mem_ClearedAlloc(sizeof(undo_t));
  543. if (!redo) return;
  544. memset(redo, 0, sizeof(undo_t));
  545. redo->brushlist.next = &redo->brushlist;
  546. redo->brushlist.prev = &redo->brushlist;
  547. redo->entitylist.next = &redo->entitylist;
  548. redo->entitylist.prev = &redo->entitylist;
  549. if (g_lastredo) g_lastredo->next = redo;
  550. else g_redolist = redo;
  551. redo->prev = g_lastredo;
  552. redo->next = NULL;
  553. g_lastredo = redo;
  554. redo->time = Sys_DoubleTime();
  555. redo->id = g_redoId++;
  556. redo->done = true;
  557. redo->operation = undo->operation;
  558. //reset the redo IDs of all brushes using the new ID
  559. for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush = pBrush->next)
  560. {
  561. if (pBrush->redoId == redo->id)
  562. {
  563. pBrush->redoId = 0;
  564. }
  565. }
  566. for (pBrush = selected_brushes.next; pBrush != NULL && pBrush != &selected_brushes; pBrush = pBrush->next)
  567. {
  568. if (pBrush->redoId == redo->id)
  569. {
  570. pBrush->redoId = 0;
  571. }
  572. }
  573. //reset the redo IDs of all entities using thew new ID
  574. for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next)
  575. {
  576. if (pEntity->redoId == redo->id)
  577. {
  578. pEntity->redoId = 0;
  579. }
  580. }
  581. // remove current selection
  582. Select_Deselect();
  583. // move "created" brushes to the redo
  584. for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush=pNextBrush)
  585. {
  586. pNextBrush = pBrush->next;
  587. if (pBrush->undoId == undo->id)
  588. {
  589. //Brush_Free(pBrush);
  590. //move the brush to the redo
  591. Brush_RemoveFromList(pBrush);
  592. Brush_AddToList(pBrush, &redo->brushlist);
  593. //make sure the ID of the owner is stored
  594. pBrush->ownerId = pBrush->owner->entityId;
  595. //unlink the brush from the owner entity
  596. Entity_UnlinkBrush(pBrush);
  597. }
  598. }
  599. // move "created" entities to the redo
  600. for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pNextEntity)
  601. {
  602. pNextEntity = pEntity->next;
  603. if (pEntity->undoId == undo->id)
  604. {
  605. // check if this entity is in the undo
  606. for (pUndoEntity = undo->entitylist.next; pUndoEntity != NULL && pUndoEntity != &undo->entitylist; pUndoEntity = pUndoEntity->next)
  607. {
  608. // move brushes to the undo entity
  609. if (pUndoEntity->entityId == pEntity->entityId)
  610. {
  611. pUndoEntity->brushes.next = pEntity->brushes.next;
  612. pUndoEntity->brushes.prev = pEntity->brushes.prev;
  613. pEntity->brushes.next = &pEntity->brushes;
  614. pEntity->brushes.prev = &pEntity->brushes;
  615. }
  616. }
  617. //
  618. //Entity_Free(pEntity);
  619. //move the entity to the redo
  620. Entity_RemoveFromList(pEntity);
  621. Entity_AddToList(pEntity, &redo->entitylist);
  622. }
  623. }
  624. // add the undo entities back into the entity list
  625. for (pEntity = undo->entitylist.next; pEntity != NULL && pEntity != &undo->entitylist; pEntity = undo->entitylist.next)
  626. {
  627. g_undoMemorySize -= Entity_MemorySize(pEntity);
  628. //if this is the world entity
  629. if (pEntity->entityId == world_entity->entityId)
  630. {
  631. //free the epairs of the world entity
  632. Entity_FreeEpairs(world_entity);
  633. //set back the original epairs
  634. world_entity->epairs = pEntity->epairs;
  635. //free the world_entity clone that stored the epairs
  636. Entity_Free(pEntity);
  637. }
  638. else
  639. {
  640. Entity_RemoveFromList(pEntity);
  641. Entity_AddToList(pEntity, &entities);
  642. pEntity->redoId = redo->id;
  643. }
  644. }
  645. // add the undo brushes back into the selected brushes
  646. for (pBrush = undo->brushlist.next; pBrush != NULL && pBrush != &undo->brushlist; pBrush = undo->brushlist.next)
  647. {
  648. g_undoMemorySize -= Brush_MemorySize(pBrush);
  649. Brush_RemoveFromList(pBrush);
  650. Brush_AddToList(pBrush, &active_brushes);
  651. for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next)
  652. {
  653. if (pEntity->entityId == pBrush->ownerId)
  654. {
  655. Entity_LinkBrush(pEntity, pBrush);
  656. break;
  657. }
  658. }
  659. //if the brush is not linked then it should be linked into the world entity
  660. if (pEntity == NULL || pEntity == &entities)
  661. {
  662. Entity_LinkBrush(world_entity, pBrush);
  663. }
  664. //build the brush
  665. //Brush_Build(pBrush);
  666. Select_Brush(pBrush);
  667. pBrush->redoId = redo->id;
  668. }
  669. //
  670. common->Printf("%s undone.\n", undo->operation);
  671. // free the undo
  672. g_undoMemorySize -= sizeof(undo_t);
  673. Mem_Free(undo);
  674. g_undoSize--;
  675. g_undoId--;
  676. if (g_undoId <= 0) g_undoId = 2 * g_undoMaxSize;
  677. //
  678. Sys_BeginWait();
  679. brush_t *b, *next;
  680. for (b = active_brushes.next ; b != NULL && b != &active_brushes ; b=next) {
  681. next = b->next;
  682. Brush_Build( b, true, false, false );
  683. }
  684. for (b = selected_brushes.next ; b != NULL && b != &selected_brushes ; b=next) {
  685. next = b->next;
  686. Brush_Build( b, true, false, false );
  687. }
  688. Sys_EndWait();
  689. g_bScreenUpdates = true;
  690. Sys_UpdateWindows(W_ALL);
  691. }
  692. /*
  693. =============
  694. Undo_Redo
  695. =============
  696. */
  697. void Undo_Redo(void)
  698. {
  699. undo_t *redo;
  700. brush_t *pBrush, *pNextBrush;
  701. entity_t *pEntity, *pNextEntity, *pRedoEntity;
  702. if (!g_lastredo)
  703. {
  704. Sys_Status("Nothing left to redo.\n");
  705. return;
  706. }
  707. if (g_lastundo)
  708. {
  709. if (!g_lastundo->done)
  710. {
  711. Sys_Status("WARNING: last undo not finished.\n");
  712. }
  713. }
  714. // get the last redo
  715. redo = g_lastredo;
  716. if (g_lastredo->prev) g_lastredo->prev->next = NULL;
  717. else g_redolist = NULL;
  718. g_lastredo = g_lastredo->prev;
  719. //
  720. Undo_GeneralStart(redo->operation);
  721. // remove current selection
  722. Select_Deselect();
  723. // move "created" brushes back to the last undo
  724. for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush = pNextBrush)
  725. {
  726. pNextBrush = pBrush->next;
  727. if (pBrush->redoId == redo->id)
  728. {
  729. //move the brush to the undo
  730. Brush_RemoveFromList(pBrush);
  731. Brush_AddToList(pBrush, &g_lastundo->brushlist);
  732. g_undoMemorySize += Brush_MemorySize(pBrush);
  733. pBrush->ownerId = pBrush->owner->entityId;
  734. Entity_UnlinkBrush(pBrush);
  735. }
  736. }
  737. // move "created" entities back to the last undo
  738. for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pNextEntity)
  739. {
  740. pNextEntity = pEntity->next;
  741. if (pEntity->redoId == redo->id)
  742. {
  743. // check if this entity is in the redo
  744. for (pRedoEntity = redo->entitylist.next; pRedoEntity != NULL && pRedoEntity != &redo->entitylist; pRedoEntity = pRedoEntity->next)
  745. {
  746. // move brushes to the redo entity
  747. if (pRedoEntity->entityId == pEntity->entityId)
  748. {
  749. pRedoEntity->brushes.next = pEntity->brushes.next;
  750. pRedoEntity->brushes.prev = pEntity->brushes.prev;
  751. pEntity->brushes.next = &pEntity->brushes;
  752. pEntity->brushes.prev = &pEntity->brushes;
  753. }
  754. }
  755. //
  756. //Entity_Free(pEntity);
  757. //move the entity to the redo
  758. Entity_RemoveFromList(pEntity);
  759. Entity_AddToList(pEntity, &g_lastundo->entitylist);
  760. g_undoMemorySize += Entity_MemorySize(pEntity);
  761. }
  762. }
  763. // add the undo entities back into the entity list
  764. for (pEntity = redo->entitylist.next; pEntity != NULL && pEntity != &redo->entitylist; pEntity = redo->entitylist.next)
  765. {
  766. //if this is the world entity
  767. if (pEntity->entityId == world_entity->entityId)
  768. {
  769. //free the epairs of the world entity
  770. Entity_FreeEpairs(world_entity);
  771. //set back the original epairs
  772. world_entity->epairs = pEntity->epairs;
  773. //free the world_entity clone that stored the epairs
  774. Entity_Free(pEntity);
  775. }
  776. else
  777. {
  778. Entity_RemoveFromList(pEntity);
  779. Entity_AddToList(pEntity, &entities);
  780. }
  781. }
  782. // add the redo brushes back into the selected brushes
  783. for (pBrush = redo->brushlist.next; pBrush != NULL && pBrush != &redo->brushlist; pBrush = redo->brushlist.next)
  784. {
  785. Brush_RemoveFromList(pBrush);
  786. Brush_AddToList(pBrush, &active_brushes);
  787. for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next)
  788. {
  789. if (pEntity->entityId == pBrush->ownerId)
  790. {
  791. Entity_LinkBrush(pEntity, pBrush);
  792. break;
  793. }
  794. }
  795. //if the brush is not linked then it should be linked into the world entity
  796. if (pEntity == NULL || pEntity == &entities)
  797. {
  798. Entity_LinkBrush(world_entity, pBrush);
  799. }
  800. //build the brush
  801. //Brush_Build(pBrush);
  802. Select_Brush(pBrush);
  803. }
  804. //
  805. Undo_End();
  806. //
  807. common->Printf("%s redone.\n", redo->operation);
  808. //
  809. g_redoId--;
  810. // free the undo
  811. Mem_Free(redo);
  812. //
  813. g_bScreenUpdates = true;
  814. Sys_UpdateWindows(W_ALL);
  815. }
  816. /*
  817. =============
  818. Undo_RedoAvailable
  819. =============
  820. */
  821. int Undo_RedoAvailable(void)
  822. {
  823. if (g_lastredo) return true;
  824. return false;
  825. }
  826. /*
  827. =============
  828. Undo_UndoAvailable
  829. =============
  830. */
  831. int Undo_UndoAvailable(void)
  832. {
  833. if (g_lastundo)
  834. {
  835. if (g_lastundo->done)
  836. return true;
  837. }
  838. return false;
  839. }