From 0b0aa3b06fac0bcdeb31d5e2211d1ba149531692 Mon Sep 17 00:00:00 2001 From: Fox Caminiti Date: Thu, 6 Oct 2022 14:30:48 -0400 Subject: GL renderer preparation --- undo.cpp | 745 +++++++++++++++++++++------------------------------------------ 1 file changed, 243 insertions(+), 502 deletions(-) (limited to 'undo.cpp') 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); } -- cgit v1.2.3