summaryrefslogtreecommitdiff
path: root/undo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'undo.cpp')
-rw-r--r--undo.cpp745
1 files changed, 243 insertions, 502 deletions
diff --git a/undo.cpp b/undo.cpp
index bb49772..a86e214 100644
--- a/undo.cpp
+++ b/undo.cpp
@@ -1,554 +1,295 @@
-// get ready for some MLG...
-
-// The undo system currently works in two layers: a lower-level structless
-// stack that records "actions" and a higher-level array of "entries" that
-// bundle actions together. An action can either record a single change to a
-// specific memory address or a shift of pointers. Entries are what the user
-// sees and can contain multiple actions (i.e. adding a source changes the
-// value of the string and the increment of how many sources there are).
-// Entries are allowed to call functions in case there's something that can't
-// be incorporated into this memory model (i.e. deallocating libav contexts
-// when a layer's creation is undone), though they should be used only
-// when necessary.
-
-// These get four things pushed together: what type the data is, address, the
-// original data, and the type again. The type is encoded twice so we always
-// know how big the data is whether we're undoing or redoing.
-// We need to encode data that's able to go from A -> B as well as B -> A. Thus
-// for the ints I encode the difference instead of just whatever the last value
-// was. Strings currently just stores both.
-void History_Action_Change(memory *Memory, void *DataAddress, void *OriginalData, void *NewData, action_type ActionChange)
+void Arbitrary_WriteInto(uint8 *Address_Read, uint8 *Address_Write, uint64 Size)
{
- Memory->Action.Entry[Memory->Action.Index].NumberOfActions++;
- void *Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
- *(action_type *)Data = ActionChange;
- void *UndoEntry = Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
- *(ptrsize *)UndoEntry = (ptrsize)DataAddress;
- switch (ActionChange)
- {
- case action_type_change_u16:
- {
- uint16 OriginalValue = *(uint16 *)OriginalData;
- uint16 NewValue = *(uint16 *)NewData;
- uint16 Difference = NewValue - OriginalValue;
- void *Data = Memory_Advance(Memory, sizeof(uint16), P_UndoBuffer);
- *(uint16 *)Data = Difference;
- *(uint16 *)DataAddress = *(uint16 *)NewData;
- } break;
- case action_type_change_i16:
- {
- int16 OriginalValue = *(int16 *)OriginalData;
- int16 NewValue = *(int16 *)NewData;
- int16 Difference = NewValue - OriginalValue;
- void *Data = Memory_Advance(Memory, sizeof(int16), P_UndoBuffer);
- *(int16 *)Data = Difference;
- *(int16 *)DataAddress = *(int16 *)NewData;
- } break;
- case action_type_change_u32:
- {
- uint32 OriginalValue = *(uint32 *)OriginalData;
- uint32 NewValue = *(uint32 *)NewData;
- uint32 Difference = NewValue - OriginalValue;
- void *Data = Memory_Advance(Memory, sizeof(uint32), P_UndoBuffer);
- *(uint32 *)Data = Difference;
- *(uint32 *)DataAddress = *(uint32 *)NewData;
- } break;
- case action_type_change_i32:
- {
- int32 OriginalValue = *(int32 *)OriginalData;
- int32 NewValue = *(int32 *)NewData;
- int32 Difference = NewValue - OriginalValue;
- void *Data = Memory_Advance(Memory, sizeof(int32), P_UndoBuffer);
- *(int32 *)Data = Difference;
- *(int32 *)DataAddress = *(int32 *)NewData;
- } break;
- case action_type_change_r32:
- {
- real32 OriginalValue = *(real32 *)OriginalData;
- real32 NewValue = *(real32 *)NewData;
- real32 Difference = NewValue - OriginalValue;
- void *Data = Memory_Advance(Memory, sizeof(real32), P_UndoBuffer);
- *(real32 *)Data = Difference;
- *(real32 *)DataAddress = *(real32 *)NewData;
- } break;
- case action_type_change_u64:
- {
- uint64 OriginalValue = *(uint64 *)OriginalData;
- uint64 NewValue = *(uint64 *)NewData;
- uint64 Difference = NewValue - OriginalValue;
- void *Data = Memory_Advance(Memory, sizeof(uint64), P_UndoBuffer);
- *(uint64 *)Data = Difference;
- *(uint64 *)DataAddress = *(uint64 *)NewData;
- } break;
- case action_type_change_ptr:
- {
- ptrsize OriginalValue = *(ptrsize *)OriginalData;
- ptrsize NewValue = *(ptrsize *)NewData;
- ptrsize Difference = NewValue - OriginalValue;
- void *Data = Memory_Advance(Memory, sizeof(ptrsize), P_UndoBuffer);
- *(ptrsize *)Data = Difference;
- *(ptrsize *)DataAddress = *(ptrsize *)NewData;
- } break;
- case action_type_change_string:
- {
- void *Data = Memory_Advance(Memory, STRING_SIZE, P_UndoBuffer);
- CopyStrings(Data, OriginalData);
- Data = Memory_Advance(Memory, STRING_SIZE, P_UndoBuffer);
- CopyStrings(Data, NewData);
- CopyStrings(DataAddress, NewData);
- } break;
- default:
- {
- Assert(0);
- }
-
+ uint64 i = 0;
+ while (i < Size) {
+ *(Address_Write + i) = *(Address_Read + i);
+ i++;
}
- Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
- *(action_type *)Data = ActionChange;
}
-// Helper functions for common types of data changes.
-void History_Action_Change_SwapBool(memory *Memory, bool32 *Bool)
+void Arbitrary_Zero(uint8 *Address_Write, uint64 Size)
{
- bool32 OppositeBool = *Bool ^ 1;
- History_Action_Change(Memory, Bool, Bool, &OppositeBool, action_type_change_i32);
+ uint64 i = 0;
+ while (i < Size) {
+ *(Address_Write + i) = 0;
+ i++;
+ }
}
-void History_Action_Change_V2(memory *Memory, v2 *DataAddress, v2 *OriginalData, v2 *NewData)
+void Arbitrary_SwapData(memory *Memory, uint8 *Address_0, uint8 *Address_1, uint64 Size)
{
- History_Action_Change(Memory, (void *)&DataAddress->x, (void *)&OriginalData->x, (void *)&NewData->x, action_type_change_r32);
- History_Action_Change(Memory, (void *)&DataAddress->y, (void *)&OriginalData->y, (void *)&NewData->y, action_type_change_r32);
+ uint8 *Buffer_Scratch = (uint8 *)Memory_PushScratch(Memory, Size);
+ Arbitrary_WriteInto(Address_0, Buffer_Scratch, Size);
+ Arbitrary_WriteInto(Address_1, Address_0, Size);
+ Arbitrary_WriteInto(Buffer_Scratch, Address_1, Size);
+ Memory_PopScratch(Memory, Size);
}
-void History_Action_Change_Increment(memory *Memory, void *Data, action_type ActionChange)
+
+static void
+Arbitrary_ShiftData(uint8 *Address_Start, uint8 *Address_End, uint64 ShiftAmount, int32 Direction)
{
- switch (ActionChange)
- {
- case action_type_change_u16:
- {
- uint16 DataPlusOne = (*(uint16 *)Data) + 1;
- History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange);
- } break;
- case action_type_change_i16:
- {
- int16 DataPlusOne = (*(int16 *)Data) + 1;
- History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange);
- } break;
- case action_type_change_u32:
- {
- uint32 DataPlusOne = (*(uint32 *)Data) + 1;
- History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange);
- } break;
- case action_type_change_i32:
- {
- int32 DataPlusOne = (*(int32 *)Data) + 1;
- History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange);
- } break;
- case action_type_change_r32:
- {
- real32 DataPlusOne = (*(real32 *)Data) + 1;
- History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange);
- } break;
- case action_type_change_u64:
- {
- uint64 DataPlusOne = (*(uint64 *)Data) + 1;
- History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange);
- } break;
- default:
- {
- Assert(0);
+ if (Direction > 0) {
+ uint8 *AddressPlayhead = Address_End;
+ while ((ptrsize)AddressPlayhead >= (ptrsize)Address_Start) {
+ *(AddressPlayhead + ShiftAmount) = *AddressPlayhead;
+ AddressPlayhead--;
+ }
+ } else {
+ uint8 *AddressPlayhead = Address_Start;
+ while ((ptrsize)AddressPlayhead < (ptrsize)Address_End) {
+ *(AddressPlayhead - ShiftAmount) = *AddressPlayhead;
+ AddressPlayhead++;
}
}
}
-void History_Action_Change_Decrement(memory *Memory, void *Data, action_type ActionChange)
+struct history_info {
+ uint16 ActionCount_Total;
+ uint16 ActionCount_EndOfPlayhead;
+ uint16 ActionCount_Current;
+
+ uint64 ActionOffset_Total;
+ uint64 ActionOffset_EndOfPlayhead;
+ uint64 ActionOffset_Current;
+
+ uint64 EntrySize_Current;
+};
+
+static uint64
+History_GetActionSize(history_entry_list *History, int i, uint16 ActionCount_EndOfPlayhead)
+{
+ history_action *Action = &History->Action[i];
+ if (Action->Type == action_type_swap)
+ return Action->Size;
+ return 0;
+}
+
+// Returns information on the undo tree based on three points of data: the
+// total amount of entries, the location of the playhead, and whatever location
+// SampleIndex is set to, which should be either one minus playhead or the playhead.
+
+// I wrote this with the intent of precomputing things like the tree's total
+// size and the size of the current action, because calculating them in the
+// Action_Redo/Undo calls got extremely confusing.
+
+static history_info
+History_GetTreeInfo(history_entry_list *History, uint16 SampleIndex)
{
- switch (ActionChange)
+ history_info Info = {};
+
+ for (int i = 0; i < History->NumberOfEntries; i++)
{
- case action_type_change_u16:
- {
- uint16 DataPlusOne = (*(uint16 *)Data) - 1;
- History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange);
- } break;
- case action_type_change_i16:
- {
- int16 DataPlusOne = (*(int16 *)Data) - 1;
- History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange);
- } break;
- case action_type_change_u32:
- {
- uint32 DataPlusOne = (*(uint32 *)Data) - 1;
- History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange);
- } break;
- case action_type_change_i32:
- {
- int32 DataPlusOne = (*(int32 *)Data) - 1;
- History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange);
- } break;
- case action_type_change_r32:
- {
- real32 DataPlusOne = (*(real32 *)Data) - 1;
- History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange);
- } break;
- case action_type_change_u64:
- {
- uint64 DataPlusOne = (*(uint64 *)Data) - 1;
- History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange);
- } break;
- default:
- {
- Assert(0);
- }
+ history_entry *Entry = &History->Entry[i];
+ Info.ActionCount_Total += Entry->NumberOfActions;
+ if (i < History->EntryPlayhead)
+ Info.ActionCount_EndOfPlayhead += Entry->NumberOfActions;
+ if (i < SampleIndex)
+ Info.ActionCount_Current += Entry->NumberOfActions;
}
-}
-static void
-Arbitrary_ShiftData(action_shift_data ShiftData) {
- int16 StopAt = ShiftData.Index;
- if (ShiftData.Direction > 0) {
- int16 i = ShiftData.NumberOf - 1;
- while (i >= StopAt) {
- uint8 *CurrentData = (uint8 *)ShiftData.StartingAddress + (ShiftData.Size * i);
- uint8 *NextData = (uint8 *)ShiftData.StartingAddress + (ShiftData.Size * (i + ShiftData.Direction));
- uint32 Bytes = 0;
- while (Bytes < ShiftData.Size) {
- *NextData++ = *CurrentData++;
- Bytes++;
- }
- i--;
- }
- } else {
- int16 i = StopAt;
- while (i <= ShiftData.NumberOf - 1) {
- uint8 *CurrentData = (uint8 *)ShiftData.StartingAddress + (ShiftData.Size * i);
- uint8 *NextData = (uint8 *)ShiftData.StartingAddress + (ShiftData.Size * (i - ShiftData.Direction));
- uint32 Bytes = 0;
- while (Bytes < ShiftData.Size) {
- *CurrentData++ = *NextData++;
- Bytes++;
- }
- i++;
- }
+ for (int i = 0; i < Info.ActionCount_Total; i++)
+ {
+ uint64 Size = History_GetActionSize(History, i, Info.ActionCount_EndOfPlayhead);
+ Info.ActionOffset_Total += Size;
+ if (i < Info.ActionCount_EndOfPlayhead)
+ Info.ActionOffset_EndOfPlayhead += Size;
+
+ if (i < Info.ActionCount_Current)
+ Info.ActionOffset_Current += Size;
+ else if (i < Info.ActionCount_EndOfPlayhead) // Only increment the current size if i is between
+ Info.EntrySize_Current += Size; // the current count and playhead count!
}
+
+ return Info;
}
-void History_Action_Shift_2(memory *Memory, void *StartingAddress, uint32 Size, uint16 NumberOf, int16 Direction, int16 Index)
+void History_Action_Undo(memory *Memory, history_info Info, history_action *ActionPointer, uint64 Action_Offset)
{
- Memory->Action.Entry[Memory->Action.Index].NumberOfActions++;
- void *Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
- *(action_type *)Data = action_type_shift;
- action_shift_data *ShiftData = (action_shift_data *)Memory_Advance(Memory, sizeof(action_shift_data), P_UndoBuffer);
- ShiftData->StartingAddress = StartingAddress;
- ShiftData->Size = Size;
- ShiftData->NumberOf = NumberOf;
- ShiftData->Index = Index;
- ShiftData->Direction = Direction;
- Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
- *(action_type *)Data = action_type_shift;
- Arbitrary_ShiftData(*ShiftData);
+ history_entry_list *History = &Memory->History;
+
+ // Only swap_bitmap should touch the data!
+ history_action Action = *ActionPointer;
+
+ uint8 *Address_HistoryTree_Start = (uint8 *)Memory_AddressAtOffset(Memory, P_UndoBuffer, Action_Offset);
+ uint8 *Address_HistoryTree_End = (uint8 *)Memory_AddressAtOffset(Memory, P_UndoBuffer, Info.ActionOffset_Total);
+ uint8 *Address_Data = (uint8 *)Memory_AddressAtOffset(Memory, Action.TableName, Action.ByteOffset);
+
+ if (Action.Type == action_type_swap) {
+ Arbitrary_SwapData(Memory, Address_HistoryTree_Start, Address_Data, Action.Size);
+ } else if (Action.Type == action_type_shift) {
+ // In order to shift back we have to start the address at where the
+ // shifted chunk is _now_, not when we called the function.
+ uint64 NewByteOffset = (Action.Direction > 0) ? Action.ByteOffset + Action.ShiftAmount : Action.ByteOffset - Action.ShiftAmount;
+ void *Address_Start = Memory_AddressAtOffset(Memory, Action.TableName, NewByteOffset);
+ uint8 *Address_End = (uint8 *)Address_Start + Action.Size;
+ // Direction also needs to be reversed.
+ int16 Direction = Action.Direction * -1;
+ Arbitrary_ShiftData((uint8 *)Address_Start, Address_End, Action.ShiftAmount, Direction);
+ } else {
+ Assert(0);
+ }
}
-void History_Action_Shift(memory *Memory, action_type ActionChange, void *DataAddress, int16 Direction, int16 Index)
-{
- Memory->Action.Entry[Memory->Action.Index].NumberOfActions++;
- void *Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
- *(action_type *)Data = ActionChange;
- switch (ActionChange)
- {
- case action_type_shift_keyframe:
- {
- void *DataPropertyAddress = Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
- *(ptrsize *)DataPropertyAddress = (ptrsize)DataAddress;
- void *DataDirection = Memory_Advance(Memory, sizeof(int16), P_UndoBuffer);
- *(ptrsize *)DataDirection = (ptrsize)Direction;
- void *DataIndex = Memory_Advance(Memory, sizeof(int16), P_UndoBuffer);
- *(ptrsize *)DataIndex = (ptrsize)Index;
- } break;
- case action_type_shift_bezier:
- {
- void *DataPropertyAddress = Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
- *(ptrsize *)DataPropertyAddress = (ptrsize)DataAddress;
- void *DataDirection = Memory_Advance(Memory, sizeof(int16), P_UndoBuffer);
- *(ptrsize *)DataDirection = (ptrsize)Direction;
- void *DataIndex = Memory_Advance(Memory, sizeof(int16), P_UndoBuffer);
- *(ptrsize *)DataIndex = (ptrsize)Index;
- } break;
- default:
- {
- Assert(0);
- } break;
+void History_Action_Redo(memory *Memory, history_info Info, history_action *ActionPointer, uint64 Action_Offset) {
+
+ history_entry_list *History = &Memory->History;
+
+ history_action Action = *ActionPointer;
+
+ uint8 *Address_HistoryTree_Start = (uint8 *)Memory_AddressAtOffset(Memory, P_UndoBuffer, Action_Offset);
+ uint8 *Address_HistoryTree_End = (uint8 *)Memory_AddressAtOffset(Memory, P_UndoBuffer, Info.ActionOffset_Total);
+ uint8 *Address_Data = (uint8 *)Memory_AddressAtOffset(Memory, Action.TableName, Action.ByteOffset);
+
+ if (Action.Type == action_type_swap) {
+ Arbitrary_SwapData(Memory, Address_HistoryTree_Start, Address_Data, Action.Size);
+ } else if (Action.Type == action_type_shift) {
+ void *Address_Start = Memory_AddressAtOffset(Memory, Action.TableName, Action.ByteOffset);
+ uint8 *Address_End = (uint8 *)Address_Start + Action.Size;
+ int16 Direction = Action.Direction;
+ Arbitrary_ShiftData((uint8 *)Address_Start, Address_End, Action.ShiftAmount, Direction);
+ } else {
+ Assert(0);
}
- Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
- *(action_type *)Data = ActionChange;
}
-// Overwrite area with arbitrary-sized memory. Only use if the previous data
-// doesn't need to be recorded, like pushing to the end of a stack.
-void History_Action_StoreData(memory *Memory, void *DataAddress, uint64 ByteSize)
-{
- Memory->Action.Entry[Memory->Action.Index].NumberOfActions++;
- void *Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
- *(action_type *)Data = action_type_storedata;
- Data = Memory_Advance(Memory, sizeof(uint64), P_UndoBuffer);
- *(uint64 *)Data = ByteSize;
- Data = Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
- *(ptrsize *)Data = (ptrsize)DataAddress;
- uint64 i = 0;
- while (i < ByteSize) {
- void *DataIndex = Memory_Advance(Memory, 1, P_UndoBuffer);
- *(uint8 *)DataIndex = *((uint8 *)DataAddress + i++);
+void History_Undo(memory *Memory) {
+ history_entry_list *History = &Memory->History;
+ if (History->EntryPlayhead == 0) return;
+
+ // We want Current to represent the beginning of the current entry, so we
+ // subtract one from the playhead.
+ history_info Info = History_GetTreeInfo(History, History->EntryPlayhead - 1);
+ history_entry *Entry = &History->Entry[History->EntryPlayhead - 1];
+
+ // This puts us at the end of the current entry's offset.
+ uint64 ActionOffset_Stepback = Info.ActionOffset_Current + Info.EntrySize_Current;
+
+ for (int i = Entry->NumberOfActions - 1; i >= 0; i--) {
+ history_action *Action = &History->Action[Info.ActionCount_Current + i];
+
+ // We step backwards only if the action is currently storing data.
+ if (Action->Type != action_type_shift)
+ ActionOffset_Stepback -= Action->Size;
+
+ History_Action_Undo(Memory, Info, Action, ActionOffset_Stepback);
}
- Data = Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
- *(ptrsize *)Data = (ptrsize)DataAddress;
- Data = Memory_Advance(Memory, sizeof(uint64), P_UndoBuffer);
- *(uint64 *)Data = ByteSize;
- Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
- *(action_type *)Data = action_type_storedata;
+
+ History->EntryPlayhead--;
+
}
-// This is only called when we're certain the action is going to be taken.
-void History_Entry_Commit(memory *Memory, action_entry_type Type, char *Name)
-{
- // We need to at least clear NumberOfActions in case this index is being reused.
- Memory->Action.Entry[Memory->Action.Index] = {};
- Memory->Action.Entry[Memory->Action.Index].Name = Name;
- Memory->Action.Entry[Memory->Action.Index].Type = Type;
- // Effectively deletes entries in front if we're beginning out of an undo.
- // It wouldn't be all that much more difficult to support branched undoing
- // now that I think about it... (would anyone use it though?)
- if (Memory->Action.Index != Memory->Action.NumberOfEntries) {
- Memory->Action.NumberOfEntries = Memory->Action.Index;
+void History_Redo(memory *Memory) {
+ history_entry_list *History = &Memory->History;
+ if (History->EntryPlayhead == History->NumberOfEntries) return;
+
+ // NOTE(fox): The third part of this function for recording the "current"
+ // action's size is only necessary for the undo call, so it's not correct on the redo.
+ history_info Info = History_GetTreeInfo(History, History->EntryPlayhead);
+ history_entry *Entry = &History->Entry[History->EntryPlayhead];
+
+ History->EntryPlayhead++;
+
+ uint64 ActionOffset_Stepforward = Info.ActionOffset_Current;
+
+ for (int i = 0; i < Entry->NumberOfActions; i++) {
+ history_action *Action = &History->Action[Info.ActionCount_Current + i];
+
+ History_Action_Redo(Memory, Info, Action, ActionOffset_Stepforward);
+
+ // We step forwards only if the action is currently storing data.
+ if (Action->Type != action_type_shift)
+ ActionOffset_Stepforward += Action->Size;
+
}
+
}
-void History_Entry_SetPointer(memory *Memory, void *Data)
+// This is only called when we're certain the action is going to be taken.
+void History_Entry_Commit(memory *Memory, char *Name)
{
- Memory->Action.Entry[Memory->Action.Index].ExtraPointer = Data;
+ history_entry_list *History = &Memory->History;
+ history_entry *Entry = &History->Entry[History->EntryPlayhead];
+ Entry->Name = Name;
+ Entry->NumberOfActions = 0;
+ // Effectively deletes entries in front if we're beginning out of an undo.
+ if (History->NumberOfEntries != History->EntryPlayhead)
+ History->NumberOfEntries = History->EntryPlayhead;
+ History->NumberOfEntries++;
+ History->EntryPlayhead++;
+ Memory->IsFileSaved = false;
+#if DEBUG
+ Assert(Debug.UndoState != 1);
+ Debug.UndoState = 1;
+#endif
}
void History_Entry_End(memory *Memory)
{
- Memory->Action.Index++;
- Memory->Action.NumberOfEntries++;
+ history_entry_list *History = &Memory->History;
+#if DEBUG
+ Debug.UndoState = 0;
+#endif
}
-// The pointer is unwinded.
-void History_Action_Undo(memory *Memory) {
- void *LastPos = Memory_Rewind(Memory, sizeof(action_type), P_UndoBuffer);
- action_type *ActionType = (action_type *)LastPos;
+// NOTE(fox): Shift is the only action that additionally changes the data after
+// the info is put on the tree, since it's always the same function used.
- switch (*ActionType)
+static void History_Action_Add(memory *Memory, history_action ActionData, void *ReferenceData = NULL)
+{
+ history_entry_list *History = &Memory->History;
+ history_entry *Entry = &History->Entry[History->EntryPlayhead - 1];
+
+ history_info Info = History_GetTreeInfo(History, History->EntryPlayhead - 1);
+
+ history_action *Action = &History->Action[Info.ActionCount_Total];
+ *Action = ActionData;
+
+ if (Action->Type == action_type_swap)
{
- case action_type_change_u16:
- {
- uint16 *Difference = (uint16 *)Memory_Rewind(Memory, sizeof(uint16), P_UndoBuffer);
- void **Address = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer);
- *(uint16 *)*Address -= *Difference;
- } break;
- case action_type_change_i16:
- {
- int16 *Difference = (int16 *)Memory_Rewind(Memory, sizeof(int16), P_UndoBuffer);
- void **Address = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer);
- *(int16 *)*Address -= *Difference;
- } break;
- case action_type_change_u32:
- {
- uint32 *Difference = (uint32 *)Memory_Rewind(Memory, sizeof(uint32), P_UndoBuffer);
- void **Address = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer);
- *(uint32 *)*Address -= *Difference;
- } break;
- case action_type_change_i32:
- {
- int32 *Difference = (int32 *)Memory_Rewind(Memory, sizeof(int32), P_UndoBuffer);
- void **Address = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer);
- *(int32 *)*Address -= *Difference;
- } break;
- case action_type_change_r32:
- {
- real32 *Difference = (real32 *)Memory_Rewind(Memory, sizeof(real32), P_UndoBuffer);
- void **Address = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer);
- *(real32 *)*Address -= *Difference;
- } break;
- case action_type_change_u64:
- {
- uint64 *Difference = (uint64 *)Memory_Rewind(Memory, sizeof(uint64), P_UndoBuffer);
- void **Address = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer);
- *(uint64 *)*Address -= *Difference;
- } break;
- case action_type_change_ptr:
- {
- ptrsize *Difference = (ptrsize *)Memory_Rewind(Memory, sizeof(ptrsize), P_UndoBuffer);
- void **Address = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer);
- *(ptrsize *)*Address -= *Difference;
- } break;
- case action_type_change_string:
- {
- Assert(0);
- } break;
- case action_type_shift_keyframe:
- {
- void *DataIndex = Memory_Rewind(Memory, sizeof(int16), P_UndoBuffer);
- void *DataDirection = Memory_Rewind(Memory, sizeof(int16), P_UndoBuffer);
- void **DataPropertyAddress = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer);
- Keyframe_ShiftPointers((property_channel *)*DataPropertyAddress, *(int16 *)DataDirection * -1, *(int16 *)DataIndex);
- } break;
- case action_type_shift_bezier:
- {
- void *DataIndex = Memory_Rewind(Memory, sizeof(int16), P_UndoBuffer);
- void *DataDirection = Memory_Rewind(Memory, sizeof(int16), P_UndoBuffer);
- void **DataPropertyAddress = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer);
- Mask_ShiftPointers((mask *)*DataPropertyAddress, *(int16 *)DataDirection * -1, *(int16 *)DataIndex);
- } break;
- case action_type_shift:
- {
- action_shift_data ShiftData = *(action_shift_data *)Memory_Rewind(Memory, sizeof(action_shift_data), P_UndoBuffer);
- ShiftData.Direction *= -1;
- Arbitrary_ShiftData(ShiftData);
- } break;
- case action_type_storedata:
- {
- uint64 *ByteSize = (uint64 *)Memory_Rewind(Memory, sizeof(uint64), P_UndoBuffer);
- void *DataAddress = *(void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer);
- void *DataStart = Memory_Rewind(Memory, *ByteSize, P_UndoBuffer);
- uint64 i = 0;
- while (i < *ByteSize) {
- void *DataIndex = Memory_GetAddressAt(Memory, i, P_UndoBuffer);
- *((uint8 *)DataAddress + i++) = *(uint8 *)DataIndex;
- }
- DataStart = Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer);
- DataStart = Memory_Rewind(Memory, sizeof(uint64), P_UndoBuffer);
- } break;
- default:
- {
- Assert(0);
- } break;
+ void *Address_HistoryTree = Memory_AddressAtOffset(Memory, P_UndoBuffer, Info.ActionOffset_Total);
+ void *Address_Data = Memory_AddressAtOffset(Memory, Action->TableName, Action->ByteOffset);
+ Arbitrary_WriteInto((uint8 *)Address_Data, (uint8 *)Address_HistoryTree, Action->Size);
+ } else if (Action->Type == action_type_shift)
+ {
+ void *Address_Start = Memory_AddressAtOffset(Memory, Action->TableName, Action->ByteOffset);
+ uint8 *Address_End = (uint8 *)Address_Start + Action->Size;
+ Arbitrary_ShiftData((uint8 *)Address_Start, Address_End, Action->ShiftAmount, Action->Direction);
}
- void *EndPos = Memory_Rewind(Memory, sizeof(action_type), P_UndoBuffer);
+
+ Entry->NumberOfActions++;
}
-// The pointer is rewinded.
-void History_Action_Redo(memory *Memory) {
- void *LastPos = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
- action_type *ActionType = (action_type *)LastPos;
+// Helper functions for different tables.
- switch (*ActionType)
- {
- case action_type_change_u16:
- {
- void **Address = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
- uint16 *Difference = (uint16 *)Memory_Advance(Memory, sizeof(uint16), P_UndoBuffer);
- *(uint16 *)*Address += *Difference;
- } break;
- case action_type_change_i16:
- {
- void **Address = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
- int16 *Difference = (int16 *)Memory_Advance(Memory, sizeof(int16), P_UndoBuffer);
- *(int16 *)*Address += *Difference;
- } break;
- case action_type_change_u32:
- {
- void **Address = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
- uint32 *Difference = (uint32 *)Memory_Advance(Memory, sizeof(uint32), P_UndoBuffer);
- *(uint32 *)*Address += *Difference;
- } break;
- case action_type_change_i32:
- {
- void **Address = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
- int32 *Difference = (int32 *)Memory_Advance(Memory, sizeof(int32), P_UndoBuffer);
- *(int32 *)*Address += *Difference;
- } break;
- case action_type_change_r32:
- {
- void **Address = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
- real32 *Difference = (real32 *)Memory_Advance(Memory, sizeof(real32), P_UndoBuffer);
- *(real32 *)*Address += *Difference;
- } break;
- case action_type_change_u64:
- {
- void **Address = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
- uint64 *Difference = (uint64 *)Memory_Advance(Memory, sizeof(uint64), P_UndoBuffer);
- *(uint64 *)*Address += *Difference;
- } break;
- case action_type_change_ptr:
- {
- void **Address = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
- ptrsize *Difference = (ptrsize *)Memory_Advance(Memory, sizeof(ptrsize), P_UndoBuffer);
- *(ptrsize *)*Address += *Difference;
- } break;
- case action_type_change_string:
- {
- Assert(0);
- } break;
- case action_type_shift_keyframe:
- {
- void **DataPropertyAddress = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
- void *DataDirection = Memory_Advance(Memory, sizeof(int16), P_UndoBuffer);
- void *DataIndex = Memory_Advance(Memory, sizeof(int16), P_UndoBuffer);
- Keyframe_ShiftPointers((property_channel *)*DataPropertyAddress, *(int16 *)DataDirection, *(int16 *)DataIndex);
- } break;
- case action_type_shift_bezier:
- {
- void **DataPropertyAddress = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
- void *DataDirection = Memory_Advance(Memory, sizeof(int16), P_UndoBuffer);
- void *DataIndex = Memory_Advance(Memory, sizeof(int16), P_UndoBuffer);
- Mask_ShiftPointers((mask *)*DataPropertyAddress, *(int16 *)DataDirection, *(int16 *)DataIndex);
- } break;
- case action_type_shift:
- {
- action_shift_data ShiftData = *(action_shift_data *)Memory_Advance(Memory, sizeof(action_shift_data), P_UndoBuffer);
- Arbitrary_ShiftData(ShiftData);
- } break;
- case action_type_storedata:
- {
- // NOTE(fox): Right now I'm only using this to overwrite data, so all we need to do is advance.
- uint64 *ByteSize = (uint64 *)Memory_Advance(Memory, sizeof(uint64), P_UndoBuffer);
- void *DataAddress = *(void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
- void *DataEnd = Memory_Advance(Memory, *ByteSize, P_UndoBuffer);
- DataEnd = Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
- DataEnd = Memory_Advance(Memory, sizeof(uint64), P_UndoBuffer);
- } break;
- default:
- {
- Assert(0);
- } break;
- }
- void *EndPos = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
+
+static void History_Action_Shift(memory *Memory, memory_table_list TableName,
+ void *Address0, void *Address1, uint64 Amount, int16 Direction)
+{
+ void *Address_Start = Memory->Slot[TableName].Address;
+ uint64 ByteOffset = (ptrsize)Address0 - (ptrsize)Address_Start;
+ uint64 Size = (ptrsize)Address1 - (ptrsize)Address0;
+
+ history_action Action = { TableName, action_type_shift, Size, ByteOffset, Amount, Direction };
+
+ History_Action_Add(Memory, Action);
}
-void History_Undo(memory *Memory) {
- if (Memory->Action.Index != 0) {
- Memory->Action.Index--;
- action_entry Entry = Memory->Action.Entry[Memory->Action.Index];
- switch (Entry.Type)
- {
- case action_entry_layerinit:
- {
- AV_Dealloc((av_info *)*(ptrsize *)Entry.ExtraPointer);
- *(ptrsize *)Entry.ExtraPointer = 0x0; // what actually dereferences the pointer
- } break;
- case action_entry_default:
- {
- } break;
- }
- for (int i = 0; i < Entry.NumberOfActions; i++)
- History_Action_Undo(Memory);
- }
+static void History_Action_Block_Swap(memory *Memory, memory_table_list TableName, void *Address_Data)
+{
+ void *Address_Start = Memory->Slot[TableName].Address;
+ uint64 Size = Memory->Slot[TableName].Block_ElementSize;
+ uint64 ByteOffset = (ptrsize)Address_Data - (ptrsize)Address_Start;
+ history_action Action = { TableName, action_type_swap, Size, ByteOffset, 0 };
+ History_Action_Add(Memory, Action);
}
-void History_Redo(memory *Memory) {
- if (Memory->Action.Index != Memory->Action.NumberOfEntries) {
- action_entry Entry = Memory->Action.Entry[Memory->Action.Index];
- switch (Entry.Type)
- {
- case action_entry_layerinit:
- {
- } break;
- case action_entry_default:
- {
- } break;
- }
- for (int i = 0; i < Entry.NumberOfActions; i++)
- History_Action_Redo(Memory);
- Memory->Action.Index++;
- }
+// Remember to dereference pointers if taking the sizeof() a variable, or else Size will be 8!
+
+static void History_Action_Swap(memory *Memory, memory_table_list TableName, uint64 Size, void *Address_Data)
+{
+ void *Address_Start = Memory->Slot[TableName].Address;
+ uint64 ByteOffset = (ptrsize)Address_Data - (ptrsize)Address_Start;
+ history_action Action = { TableName, action_type_swap, Size, ByteOffset, 0 };
+ History_Action_Add(Memory, Action);
}