-/*
-=============
-Undo_Undo
-=============
-*/
-void Undo_Undo(boolean bSilent)
-{
- // spog - disable undo if undo levels = 0
- if (g_PrefsDlg.m_nUndoLevels == 0)
- {
- Sys_Printf("Undo_Undo: undo is disabled.\n");
- return;
- }
-
- undo_t *undo, *redo;
- brush_t *pBrush, *pNextBrush;
- entity_t *pEntity, *pNextEntity, *pUndoEntity;
-
- if (!g_lastundo)
- {
- Sys_Printf("Nothing left to undo.\n");
- return;
- }
- if (!g_lastundo->done)
- {
- Sys_Printf("Undo_Undo: WARNING: last undo not yet finished!\n");
- }
- // get the last undo
- undo = g_lastundo;
- if (g_lastundo->prev) g_lastundo->prev->next = NULL;
- else g_undolist = NULL;
- g_lastundo = g_lastundo->prev;
-
- //allocate a new redo
- redo = (undo_t *) malloc(sizeof(undo_t));
- if (!redo) return;
- memset(redo, 0, sizeof(undo_t));
- redo->brushlist.next = &redo->brushlist;
- redo->brushlist.prev = &redo->brushlist;
- redo->entitylist.next = &redo->entitylist;
- redo->entitylist.prev = &redo->entitylist;
- if (g_lastredo) g_lastredo->next = redo;
- else g_redolist = redo;
- redo->prev = g_lastredo;
- redo->next = NULL;
- g_lastredo = redo;
- redo->time = Sys_DoubleTime();
- redo->id = g_redoId++;
- redo->done = true;
- redo->operation = undo->operation;
-
- //reset the redo IDs of all brushes using the new ID
- for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush = pBrush->next)
- {
- if (pBrush->redoId == redo->id)
- {
- pBrush->redoId = 0;
- }
- }
- for (pBrush = selected_brushes.next; pBrush != NULL && pBrush != &selected_brushes; pBrush = pBrush->next)
- {
- if (pBrush->redoId == redo->id)
- {
- pBrush->redoId = 0;
- }
- }
- //reset the redo IDs of all entities using thew new ID
- for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next)
- {
- if (pEntity->redoId == redo->id)
- {
- pEntity->redoId = 0;
- }
- }
-
- // deselect current sutff
- Select_Deselect();
- // move "created" brushes to the redo
- for (pBrush = active_brushes.next; pBrush != NULL && pBrush != &active_brushes; pBrush=pNextBrush)
- {
- pNextBrush = pBrush->next;
- if (pBrush->undoId == undo->id)
- {
- //Brush_Free(pBrush);
- //move the brush to the redo
- Brush_RemoveFromList(pBrush);
- Brush_AddToList(pBrush, &redo->brushlist);
- //make sure the ID of the owner is stored
- pBrush->ownerId = pBrush->owner->entityId;
- //unlink the brush from the owner entity
- Entity_UnlinkBrush(pBrush);
- }
- }
- // move "created" entities to the redo
- for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pNextEntity)
- {
- pNextEntity = pEntity->next;
- if (pEntity->undoId == undo->id)
- {
- // check if this entity is in the undo
- for (pUndoEntity = undo->entitylist.next; pUndoEntity != NULL && pUndoEntity != &undo->entitylist; pUndoEntity = pUndoEntity->next)
- {
- // move brushes to the undo entity
- if (pUndoEntity->entityId == pEntity->entityId)
- {
- pUndoEntity->brushes.next = pEntity->brushes.next;
- pUndoEntity->brushes.prev = pEntity->brushes.prev;
- pEntity->brushes.next = &pEntity->brushes;
- pEntity->brushes.prev = &pEntity->brushes;
- }
- }
- //
- //Entity_Free(pEntity);
- //move the entity to the redo
- Entity_RemoveFromList(pEntity);
- Entity_AddToList(pEntity, &redo->entitylist);
- }
- }
- // add the undo entities back into the entity list
- for (pEntity = undo->entitylist.next; pEntity != NULL && pEntity != &undo->entitylist; pEntity = undo->entitylist.next)
- {
- g_undoMemorySize -= Entity_MemorySize(pEntity);
- //if this is the world entity
- if (pEntity->entityId == world_entity->entityId)
- {
- epair_t* tmp = world_entity->epairs;
- world_entity->epairs = pEntity->epairs;
- pEntity->epairs = tmp;
- Entity_Free(pEntity);
- }
- else
- {
- Entity_RemoveFromList(pEntity);
- Entity_AddToList(pEntity, &entities);
- pEntity->redoId = redo->id;
- }
- }
- // add the undo brushes back into the selected brushes
- for (pBrush = undo->brushlist.next; pBrush != NULL && pBrush != &undo->brushlist; pBrush = undo->brushlist.next)
- {
- //Sys_Printf("Owner ID: %i\n",pBrush->ownerId);
- g_undoMemorySize -= Brush_MemorySize(pBrush);
- Brush_RemoveFromList(pBrush);
- Brush_AddToList(pBrush, &active_brushes);
- for (pEntity = entities.next; pEntity != NULL && pEntity != &entities; pEntity = pEntity->next) // fixes broken undo on entities
- {
- //Sys_Printf("Entity ID: %i\n",pEntity->entityId);
- if (pEntity->entityId == pBrush->ownerId)
- {
- Entity_LinkBrush(pEntity, pBrush);
- break;
- }
- }
- //if the brush is not linked then it should be linked into the world entity
- //++timo FIXME: maybe not, maybe we've lost this entity's owner!
- if (pEntity == NULL || pEntity == &entities)
- {
- Entity_LinkBrush(world_entity, pBrush);
- }
- //build the brush
- //Brush_Build(pBrush);
- Select_Brush(pBrush);
- pBrush->redoId = redo->id;
- }
- if (!bSilent)
- Sys_Printf("%s undone.\n", undo->operation);
- // free the undo
- g_undoMemorySize -= sizeof(undo_t);
- free(undo);
- g_undoSize--;
- g_undoId--;
- if (g_undoId <= 0) g_undoId = 2 * g_undoMaxSize;
- //
- g_bScreenUpdates = true;
- UpdateSurfaceDialog();
- Sys_UpdateWindows(W_ALL);
-}