2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
\r
5 This file is part of GtkRadiant.
\r
7 GtkRadiant is free software; you can redistribute it and/or modify
\r
8 it under the terms of the GNU General Public License as published by
\r
9 the Free Software Foundation; either version 2 of the License, or
\r
10 (at your option) any later version.
\r
12 GtkRadiant is distributed in the hope that it will be useful,
\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
15 GNU General Public License for more details.
\r
17 You should have received a copy of the GNU General Public License
\r
18 along with GtkRadiant; if not, write to the Free Software
\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\r
30 <-g_undolist---------g_lastundo> <---map data---> <-g_lastredo---------g_redolist->
\r
33 undo/redo on the world_entity is special, only the epair changes are remembered
\r
34 and the world entity never gets deleted.
\r
36 FIXME: maybe reset the Undo system at map load
\r
37 maybe also reset the entityId at map load
\r
42 typedef struct undo_s
\r
44 double time; //time operation was performed
\r
45 int id; //every undo has an unique id
\r
46 int done; //true when undo is build
\r
47 char *operation; //name of the operation
\r
48 brush_t brushlist; //deleted brushes
\r
49 entity_t entitylist; //deleted entities
\r
50 struct undo_s *prev, *next; //next and prev undo in list
\r
53 undo_t *g_undolist; //first undo in the list
\r
54 undo_t *g_lastundo; //last undo in the list
\r
55 undo_t *g_redolist; //first redo in the list
\r
56 undo_t *g_lastredo; //last undo in list
\r
57 int g_undoMaxSize = 64; //maximum number of undos
\r
58 int g_undoSize = 0; //number of undos in the list
\r
59 int g_undoMaxMemorySize = 2*1024*1024; //maximum undo memory (default 2 MB)
\r
60 int g_undoMemorySize = 0; //memory size of undo buffer
\r
61 int g_undoId = 1; //current undo ID (zero is invalid id)
\r
62 int g_redoId = 1; //current redo ID (zero is invalid id)
\r
69 int Undo_MemorySize(void)
\r
71 return g_undoMemorySize;
\r
79 void Undo_ClearRedo(void)
\r
81 undo_t *redo, *nextredo;
\r
82 brush_t *pBrush, *pNextBrush;
\r
83 entity_t *pEntity, *pNextEntity;
\r
85 for (redo = g_redolist; redo; redo = nextredo)
\r
87 nextredo = redo->next;
\r
88 for (pBrush = redo->brushlist.next ; pBrush != NULL && pBrush != &redo->brushlist ; pBrush = pNextBrush)
\r
90 pNextBrush = pBrush->next;
\r
93 for (pEntity = redo->entitylist.next; pEntity != NULL && pEntity != &redo->entitylist; pEntity = pNextEntity)
\r
95 pNextEntity = pEntity->next;
\r
96 Entity_Free(pEntity);
\r
109 Clears the undo buffer.
\r
112 void Undo_Clear(void)
\r
114 undo_t *undo, *nextundo;
\r
115 brush_t *pBrush, *pNextBrush;
\r
116 entity_t *pEntity, *pNextEntity;
\r
119 for (undo = g_undolist; undo; undo = nextundo)
\r
121 nextundo = undo->next;
\r
122 for (pBrush = undo->brushlist.next ; pBrush != NULL && pBrush != &undo->brushlist ; pBrush = pNextBrush)
\r
124 pNextBrush = pBrush->next;
\r
125 g_undoMemorySize -= Brush_MemorySize(pBrush);
\r
126 Brush_Free(pBrush);
\r
128 for (pEntity = undo->entitylist.next; pEntity != NULL && pEntity != &undo->entitylist; pEntity = pNextEntity)
\r
130 pNextEntity = pEntity->next;
\r
131 g_undoMemorySize -= Entity_MemorySize(pEntity);
\r
132 Entity_Free(pEntity);
\r
134 g_undoMemorySize -= sizeof(undo_t);
\r
140 g_undoMemorySize = 0;
\r
149 void Undo_SetMaxSize(int size)
\r
152 if (size < 1) g_undoMaxSize = 1;
\r
153 else g_undoMaxSize = size;
\r
161 int Undo_GetMaxSize(void)
\r
163 return g_undoMaxSize;
\r
168 Undo_SetMaxMemorySize
\r
171 void Undo_SetMaxMemorySize(int size)
\r
174 if (size < 1024) g_undoMaxMemorySize = 1024;
\r
175 else g_undoMaxMemorySize = size;
\r
180 Undo_GetMaxMemorySize
\r
183 int Undo_GetMaxMemorySize(void)
\r
185 return g_undoMaxMemorySize;
\r
193 void Undo_FreeFirstUndo(void)
\r
196 brush_t *pBrush, *pNextBrush;
\r
197 entity_t *pEntity, *pNextEntity;
\r
199 //remove the oldest undo from the undo buffer
\r
201 g_undolist = g_undolist->next;
\r
202 g_undolist->prev = NULL;
\r
204 for (pBrush = undo->brushlist.next ; pBrush != NULL && pBrush != &undo->brushlist ; pBrush = pNextBrush)
\r
206 pNextBrush = pBrush->next;
\r
207 g_undoMemorySize -= Brush_MemorySize(pBrush);
\r
208 Brush_Free(pBrush);
\r
210 for (pEntity = undo->entitylist.next; pEntity != NULL && pEntity != &undo->entitylist; pEntity = pNextEntity)
\r
212 pNextEntity = pEntity->next;
\r
213 g_undoMemorySize -= Entity_MemorySize(pEntity);
\r
214 Entity_Free(pEntity);
\r
216 g_undoMemorySize -= sizeof(undo_t);
\r
226 void Undo_GeneralStart(char *operation)
\r
235 if (!g_lastundo->done)
\r
237 Sys_Printf("Undo_Start: WARNING last undo not finished.\n");
\r
241 undo = (undo_t *) malloc(sizeof(undo_t));
\r
244 memset(undo, 0, sizeof(undo_t));
\r
245 undo->brushlist.next = &undo->brushlist;
\r
246 undo->brushlist.prev = &undo->brushlist;
\r
247 undo->entitylist.next = &undo->entitylist;
\r
248 undo->entitylist.prev = &undo->entitylist;
\r
250 g_lastundo->next = undo;
\r
253 undo->prev = g_lastundo;
\r
257 undo->time = Sys_DoubleTime();
\r
259 if (g_undoId > g_undoMaxSize * 2) g_undoId = 1;
\r
260 if (g_undoId <= 0) g_undoId = 1;
\r
261 undo->id = g_undoId++;
\r
262 undo->done = false;
\r
263 undo->operation = operation;
\r
264 //reset the undo IDs of all brushes using the new ID
\r
265 for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush = pBrush->next)
\r
267 if (pBrush->undoId == undo->id)
\r
269 pBrush->undoId = 0;
\r
272 for (pBrush = selected_brushes.next; pBrush != NULL && pBrush != &selected_brushes; pBrush = pBrush->next)
\r
274 if (pBrush->undoId == undo->id)
\r
276 pBrush->undoId = 0;
\r
279 //reset the undo IDs of all entities using thew new ID
\r
280 for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next)
\r
282 if (pEntity->undoId == undo->id)
\r
284 pEntity->undoId = 0;
\r
287 g_undoMemorySize += sizeof(undo_t);
\r
289 //undo buffer is bound to a max
\r
290 if (g_undoSize > g_undoMaxSize)
\r
292 Undo_FreeFirstUndo();
\r
301 int Undo_BrushInUndo(undo_t *undo, brush_t *brush)
\r
305 for (b = undo->brushlist.next; b != &undo->brushlist; b = b->next)
\r
307 // Arnout: NOTE - can't do a pointer compare as the brushes get cloned into the undo brushlist, and not just referenced from it
\r
308 // For entities we have a unique ID, for brushes we have numberID - but brush full clone increases that anyway so it's useless right now.
\r
309 if (b == brush) return true;
\r
311 // Arnout: function is pointless right now, see above explanation
\r
320 int Undo_EntityInUndo(undo_t *undo, entity_t *ent)
\r
324 for (e = undo->entitylist.next; e != &undo->entitylist; e = e->next)
\r
326 // Arnout: NOTE - can't do a pointer compare as the entities get cloned into the undo entitylist, and not just referenced from it
\r
327 //if (e == ent) return true;
\r
328 if( e->entityId == ent->entityId ) return true;
\r
338 void Undo_Start(char *operation)
\r
340 // spog - disable undo if undo levels = 0
\r
341 if (g_PrefsDlg.m_nUndoLevels == 0)
\r
344 Sys_Printf("Undo_Start: undo is disabled.\n");
\r
350 Undo_GeneralStart(operation);
\r
358 void Undo_AddBrush(brush_t *pBrush)
\r
360 // spog - disable undo if undo levels = 0
\r
361 if (g_PrefsDlg.m_nUndoLevels == 0)
\r
364 Sys_Printf("Undo_AddBrush: undo is disabled.\n");
\r
371 Sys_Printf("Undo_AddBrushList: no last undo.\n");
\r
374 if (g_lastundo->entitylist.next != &g_lastundo->entitylist)
\r
376 Sys_Printf("Undo_AddBrushList: WARNING adding brushes after entity.\n");
\r
378 //if the brush is already in the undo
\r
379 if (Undo_BrushInUndo(g_lastundo, pBrush))
\r
382 brush_t* pClone = Brush_FullClone(pBrush);
\r
383 //save the ID of the owner entity
\r
384 pClone->ownerId = pBrush->owner->entityId;
\r
385 //save the old undo ID for previous undos
\r
386 pClone->undoId = pBrush->undoId;
\r
387 Brush_AddToList (pClone, &g_lastundo->brushlist);
\r
389 g_undoMemorySize += Brush_MemorySize(pClone);
\r
395 TTimo: some brushes are just there for UI, and the information is somewhere else
\r
396 for patches it's in the patchMesh_t structure, so when we clone the brush we get that information (brush_t::pPatch)
\r
397 but: models are stored in pBrush->owner->md3Class, and owner epairs and origin parameters are important
\r
398 so, we detect models and push the entity in the undo session (as well as it's BBox brush)
\r
399 same for other items like weapons and ammo etc.
\r
402 void Undo_AddBrushList(brush_t *brushlist)
\r
404 // spog - disable undo if undo levels = 0
\r
405 if (g_PrefsDlg.m_nUndoLevels == 0)
\r
408 Sys_Printf("Undo_AddBrushList: undo is disabled.\n");
\r
417 Sys_Printf("Undo_AddBrushList: no last undo.\n");
\r
420 if (g_lastundo->entitylist.next != &g_lastundo->entitylist)
\r
422 Sys_Printf("Undo_AddBrushList: WARNING adding brushes after entity.\n");
\r
424 //copy the brushes to the undo
\r
425 for (pBrush = brushlist->next ; pBrush != NULL && pBrush != brushlist; pBrush=pBrush->next)
\r
427 //if the brush is already in the undo
\r
428 //++timo FIXME: when does this happen?
\r
429 if (Undo_BrushInUndo(g_lastundo, pBrush))
\r
431 // do we need to store this brush's entity in the undo?
\r
432 // if it's a fixed size entity, the brush that reprents it is not really relevant, it's used for selecting and moving around
\r
433 // what we want to store for undo is the owner entity, epairs and origin/angle stuff
\r
434 //++timo FIXME: if the entity is not fixed size I don't know, so I don't do it yet
\r
435 if (pBrush->owner->eclass->fixedsize == 1)
\r
436 Undo_AddEntity( pBrush->owner );
\r
438 brush_t* pClone = Brush_FullClone(pBrush);
\r
439 // save the ID of the owner entity
\r
440 pClone->ownerId = pBrush->owner->entityId;
\r
441 // save the old undo ID from previous undos
\r
442 pClone->undoId = pBrush->undoId;
\r
443 Brush_AddToList (pClone, &g_lastundo->brushlist);
\r
444 // track memory size used by undo
\r
445 g_undoMemorySize += Brush_MemorySize(pClone);
\r
454 void Undo_EndBrush(brush_t *pBrush)
\r
456 // spog - disable undo if undo levels = 0
\r
457 if (g_PrefsDlg.m_nUndoLevels == 0)
\r
460 Sys_Printf("Undo_EndBrush: undo is disabled.\n");
\r
468 //Sys_Printf("Undo_End: no last undo.\n");
\r
471 if (g_lastundo->done)
\r
473 //Sys_Printf("Undo_End: last undo already finished.\n");
\r
476 pBrush->undoId = g_lastundo->id;
\r
484 void Undo_EndBrushList(brush_t *brushlist)
\r
486 // spog - disable undo if undo levels = 0
\r
487 if (g_PrefsDlg.m_nUndoLevels == 0)
\r
490 Sys_Printf("Undo_EndBrushList: undo is disabled.\n");
\r
498 //Sys_Printf("Undo_End: no last undo.\n");
\r
501 if (g_lastundo->done)
\r
503 //Sys_Printf("Undo_End: last undo already finished.\n");
\r
506 for (brush_t* pBrush = brushlist->next; pBrush != NULL && pBrush != brushlist; pBrush=pBrush->next)
\r
508 pBrush->undoId = g_lastundo->id;
\r
517 void Undo_AddEntity(entity_t *entity)
\r
519 // spog - disable undo if undo levels = 0
\r
520 if (g_PrefsDlg.m_nUndoLevels == 0)
\r
523 Sys_Printf("Undo_AddEntity: undo is disabled.\n");
\r
533 Sys_Printf("Undo_AddEntity: no last undo.\n");
\r
536 //if the entity is already in the undo
\r
537 if (Undo_EntityInUndo(g_lastundo, entity))
\r
540 pClone = Entity_Clone(entity);
\r
541 //save the old undo ID for previous undos
\r
542 pClone->undoId = entity->undoId;
\r
543 //save the entity ID (we need a full clone)
\r
544 pClone->entityId = entity->entityId;
\r
546 Entity_AddToList(pClone, &g_lastundo->entitylist);
\r
548 g_undoMemorySize += Entity_MemorySize(pClone);
\r
556 void Undo_EndEntity(entity_t *entity)
\r
558 // spog - disable undo if undo levels = 0
\r
559 if (g_PrefsDlg.m_nUndoLevels == 0)
\r
562 Sys_Printf("Undo_EndEntity: undo is disabled.\n");
\r
571 Sys_Printf("Undo_End: no last undo.\n");
\r
575 if (g_lastundo->done)
\r
578 Sys_Printf("Undo_End: last undo already finished.\n");
\r
582 if (entity == world_entity)
\r
584 //Sys_Printf("Undo_AddEntity: undo on world entity.\n");
\r
585 //NOTE: we never delete the world entity when undoing an operation
\r
586 // we only transfer the epairs
\r
589 entity->undoId = g_lastundo->id;
\r
597 void Undo_End(void)
\r
599 // spog - disable undo if undo levels = 0
\r
600 if (g_PrefsDlg.m_nUndoLevels == 0)
\r
603 Sys_Printf("Undo_End: undo is disabled.\n");
\r
611 //Sys_Printf("Undo_End: no last undo.\n");
\r
614 if (g_lastundo->done)
\r
616 //Sys_Printf("Undo_End: last undo already finished.\n");
\r
619 g_lastundo->done = true;
\r
621 //undo memory size is bound to a max
\r
622 while (g_undoMemorySize > g_undoMaxMemorySize)
\r
624 //always keep one undo
\r
625 if (g_undolist == g_lastundo) break;
\r
626 Undo_FreeFirstUndo();
\r
629 //Sys_Printf("undo size = %d, undo memory = %d\n", g_undoSize, g_undoMemorySize);
\r
637 void Undo_Undo(boolean bSilent)
\r
639 // spog - disable undo if undo levels = 0
\r
640 if (g_PrefsDlg.m_nUndoLevels == 0)
\r
642 Sys_Printf("Undo_Undo: undo is disabled.\n");
\r
646 undo_t *undo, *redo;
\r
647 brush_t *pBrush, *pNextBrush;
\r
648 entity_t *pEntity, *pNextEntity, *pUndoEntity;
\r
652 Sys_Printf("Nothing left to undo.\n");
\r
655 if (!g_lastundo->done)
\r
657 Sys_Printf("Undo_Undo: WARNING: last undo not yet finished!\n");
\r
659 // get the last undo
\r
661 if (g_lastundo->prev) g_lastundo->prev->next = NULL;
\r
662 else g_undolist = NULL;
\r
663 g_lastundo = g_lastundo->prev;
\r
665 //allocate a new redo
\r
666 redo = (undo_t *) malloc(sizeof(undo_t));
\r
668 memset(redo, 0, sizeof(undo_t));
\r
669 redo->brushlist.next = &redo->brushlist;
\r
670 redo->brushlist.prev = &redo->brushlist;
\r
671 redo->entitylist.next = &redo->entitylist;
\r
672 redo->entitylist.prev = &redo->entitylist;
\r
673 if (g_lastredo) g_lastredo->next = redo;
\r
674 else g_redolist = redo;
\r
675 redo->prev = g_lastredo;
\r
678 redo->time = Sys_DoubleTime();
\r
679 redo->id = g_redoId++;
\r
681 redo->operation = undo->operation;
\r
683 //reset the redo IDs of all brushes using the new ID
\r
684 for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush = pBrush->next)
\r
686 if (pBrush->redoId == redo->id)
\r
688 pBrush->redoId = 0;
\r
691 for (pBrush = selected_brushes.next; pBrush != NULL && pBrush != &selected_brushes; pBrush = pBrush->next)
\r
693 if (pBrush->redoId == redo->id)
\r
695 pBrush->redoId = 0;
\r
698 //reset the redo IDs of all entities using thew new ID
\r
699 for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next)
\r
701 if (pEntity->redoId == redo->id)
\r
703 pEntity->redoId = 0;
\r
707 // deselect current sutff
\r
709 // move "created" brushes to the redo
\r
710 for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush=pNextBrush)
\r
712 pNextBrush = pBrush->next;
\r
713 if (pBrush->undoId == undo->id)
\r
715 //Brush_Free(pBrush);
\r
716 //move the brush to the redo
\r
717 Brush_RemoveFromList(pBrush);
\r
718 Brush_AddToList(pBrush, &redo->brushlist);
\r
719 //make sure the ID of the owner is stored
\r
720 pBrush->ownerId = pBrush->owner->entityId;
\r
721 //unlink the brush from the owner entity
\r
722 Entity_UnlinkBrush(pBrush);
\r
725 // move "created" entities to the redo
\r
726 for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pNextEntity)
\r
728 pNextEntity = pEntity->next;
\r
729 if (pEntity->undoId == undo->id)
\r
731 // check if this entity is in the undo
\r
732 for (pUndoEntity = undo->entitylist.next; pUndoEntity != NULL && pUndoEntity != &undo->entitylist; pUndoEntity = pUndoEntity->next)
\r
734 // move brushes to the undo entity
\r
735 if (pUndoEntity->entityId == pEntity->entityId)
\r
737 pUndoEntity->brushes.next = pEntity->brushes.next;
\r
738 pUndoEntity->brushes.prev = pEntity->brushes.prev;
\r
739 pEntity->brushes.next = &pEntity->brushes;
\r
740 pEntity->brushes.prev = &pEntity->brushes;
\r
744 //Entity_Free(pEntity);
\r
745 //move the entity to the redo
\r
746 Entity_RemoveFromList(pEntity);
\r
747 Entity_AddToList(pEntity, &redo->entitylist);
\r
750 // add the undo entities back into the entity list
\r
751 for (pEntity = undo->entitylist.next; pEntity != NULL && pEntity != &undo->entitylist; pEntity = undo->entitylist.next)
\r
753 g_undoMemorySize -= Entity_MemorySize(pEntity);
\r
754 //if this is the world entity
\r
755 if (pEntity->entityId == world_entity->entityId)
\r
757 epair_t* tmp = world_entity->epairs;
\r
758 world_entity->epairs = pEntity->epairs;
\r
759 pEntity->epairs = tmp;
\r
760 Entity_Free(pEntity);
\r
764 Entity_RemoveFromList(pEntity);
\r
765 Entity_AddToList(pEntity, &entities);
\r
766 pEntity->redoId = redo->id;
\r
769 // add the undo brushes back into the selected brushes
\r
770 for (pBrush = undo->brushlist.next; pBrush != NULL && pBrush != &undo->brushlist; pBrush = undo->brushlist.next)
\r
772 //Sys_Printf("Owner ID: %i\n",pBrush->ownerId);
\r
773 g_undoMemorySize -= Brush_MemorySize(pBrush);
\r
774 Brush_RemoveFromList(pBrush);
\r
775 Brush_AddToList(pBrush, &active_brushes);
\r
776 for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next) // fixes broken undo on entities
\r
778 //Sys_Printf("Entity ID: %i\n",pEntity->entityId);
\r
779 if (pEntity->entityId == pBrush->ownerId)
\r
781 Entity_LinkBrush(pEntity, pBrush);
\r
785 //if the brush is not linked then it should be linked into the world entity
\r
786 //++timo FIXME: maybe not, maybe we've lost this entity's owner!
\r
787 if (pEntity == NULL || pEntity == &entities)
\r
789 Entity_LinkBrush(world_entity, pBrush);
\r
792 //Brush_Build(pBrush);
\r
793 Select_Brush(pBrush);
\r
794 pBrush->redoId = redo->id;
\r
797 Sys_Printf("%s undone.\n", undo->operation);
\r
799 g_undoMemorySize -= sizeof(undo_t);
\r
803 if (g_undoId <= 0) g_undoId = 2 * g_undoMaxSize;
\r
805 g_bScreenUpdates = true;
\r
806 UpdateSurfaceDialog();
\r
807 Sys_UpdateWindows(W_ALL);
\r
815 void Undo_Redo(void)
\r
817 // spog - disable undo if undo levels = 0
\r
818 if (g_PrefsDlg.m_nUndoLevels == 0)
\r
820 Sys_Printf("Undo_Redo: undo is disabled.\n");
\r
825 brush_t *pBrush, *pNextBrush;
\r
826 entity_t *pEntity, *pNextEntity, *pRedoEntity;
\r
830 Sys_Printf("Nothing left to redo.\n");
\r
835 if (!g_lastundo->done)
\r
837 Sys_Printf("WARNING: last undo not finished.\n");
\r
840 // get the last redo
\r
842 if (g_lastredo->prev) g_lastredo->prev->next = NULL;
\r
843 else g_redolist = NULL;
\r
844 g_lastredo = g_lastredo->prev;
\r
846 Undo_GeneralStart(redo->operation);
\r
847 // remove current selection
\r
849 // move "created" brushes back to the last undo
\r
850 for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush = pNextBrush)
\r
852 pNextBrush = pBrush->next;
\r
853 if (pBrush->redoId == redo->id)
\r
855 //move the brush to the undo
\r
856 Brush_RemoveFromList(pBrush);
\r
857 Brush_AddToList(pBrush, &g_lastundo->brushlist);
\r
858 g_undoMemorySize += Brush_MemorySize(pBrush);
\r
859 pBrush->ownerId = pBrush->owner->entityId;
\r
860 Entity_UnlinkBrush(pBrush);
\r
863 // move "created" entities back to the last undo
\r
864 for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pNextEntity)
\r
866 pNextEntity = pEntity->next;
\r
867 if (pEntity->redoId == redo->id)
\r
869 // check if this entity is in the redo
\r
870 for (pRedoEntity = redo->entitylist.next; pRedoEntity != NULL && pRedoEntity != &redo->entitylist; pRedoEntity = pRedoEntity->next)
\r
872 // move brushes to the redo entity
\r
873 if (pRedoEntity->entityId == pEntity->entityId)
\r
875 pRedoEntity->brushes.next = pEntity->brushes.next;
\r
876 pRedoEntity->brushes.prev = pEntity->brushes.prev;
\r
877 pEntity->brushes.next = &pEntity->brushes;
\r
878 pEntity->brushes.prev = &pEntity->brushes;
\r
882 //Entity_Free(pEntity);
\r
883 //move the entity to the redo
\r
884 Entity_RemoveFromList(pEntity);
\r
885 Entity_AddToList(pEntity, &g_lastundo->entitylist);
\r
886 g_undoMemorySize += Entity_MemorySize(pEntity);
\r
889 // add the undo entities back into the entity list
\r
890 for (pEntity = redo->entitylist.next; pEntity != NULL && pEntity != &redo->entitylist; pEntity = redo->entitylist.next)
\r
892 //if this is the world entity
\r
893 if (pEntity->entityId == world_entity->entityId)
\r
895 epair_t* tmp = world_entity->epairs;
\r
896 world_entity->epairs = pEntity->epairs;
\r
897 pEntity->epairs = tmp;
\r
898 Entity_Free(pEntity);
\r
902 Entity_RemoveFromList(pEntity);
\r
903 Entity_AddToList(pEntity, &entities);
\r
906 // add the redo brushes back into the selected brushes
\r
907 for (pBrush = redo->brushlist.next; pBrush != NULL && pBrush != &redo->brushlist; pBrush = redo->brushlist.next)
\r
909 Brush_RemoveFromList(pBrush);
\r
910 Brush_AddToList(pBrush, &active_brushes);
\r
911 for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next) // fixes broken undo on entities
\r
913 if (pEntity->entityId == pBrush->ownerId)
\r
915 Entity_LinkBrush(pEntity, pBrush);
\r
919 //if the brush is not linked then it should be linked into the world entity
\r
920 if (pEntity == NULL || pEntity == &entities)
\r
922 Entity_LinkBrush(world_entity, pBrush);
\r
925 //Brush_Build(pBrush);
\r
926 Select_Brush(pBrush);
\r
931 Sys_Printf("%s redone.\n", redo->operation);
\r
937 g_bScreenUpdates = true;
\r
938 UpdateSurfaceDialog();
\r
939 Sys_UpdateWindows(W_ALL);
\r
947 int Undo_RedoAvailable(void)
\r
949 if (g_lastredo) return true;
\r
953 int Undo_GetUndoId(void)
\r
956 return g_lastundo->id;
\r
965 int Undo_UndoAvailable(void)
\r
969 if (g_lastundo->done)
\r