Undo.cpp 21 KB

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