diff options
Diffstat (limited to 'src/sorted.cpp')
-rw-r--r-- | src/sorted.cpp | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/src/sorted.cpp b/src/sorted.cpp new file mode 100644 index 0000000..394c82f --- /dev/null +++ b/src/sorted.cpp @@ -0,0 +1,336 @@ + +inline sorted_property_array * +Property_GetSortedInfo(sorted_property_array *SortedPropertyStart, int i, int h) +{ + Assert(0); + return SortedPropertyStart + (i * 8) + h; +} +inline uint16 * +Property_GetSortedArray(uint16 *SortedKeyframeArray, int i, int h) +{ + Assert(0); + return SortedKeyframeArray + (i * 8 * MAX_KEYFRAMES_PER_BLOCK) + (h * MAX_KEYFRAMES_PER_BLOCK); +} + +static sorted_layer_array * +Sorted_GetLayerStart(sorted_layer_array *LayerArrayStart, sorted_comp_array *SortedCompStart, uint32 TargetComp) +{ + uint32 LayerOffset = 0; int s = 0; + while (s < TargetComp) { + LayerOffset += SortedCompStart[s].LayerCount; + s++; + } + return LayerArrayStart + LayerOffset; +} + +// The sorting algorithm is straightforward: read every point, evaluate it if +// it's currently being interacted with by the user, record index in a sorted +// list, and repeat, shiftig the list as necessary. + +void Property_SortAll(memory *Memory, project_state *State, property_channel *Property, sorted_property_array *PropertyStart, uint16 *PropertyArrayStart) +{ + int h = 0, c = 0, i = 0; + uint32 CurrentSortIndex = 0; + real32 MinY = 1000000; + real32 MaxY = -1000000; + int32 Offset = (State->Interact_Active == interact_type_keyframe_move) ? (int32)State->Interact_Offset[0] : 0; + while (Block_Loop(Memory, Property, Property->Keyframe_Count, &h, &c, &i)) { + v2 PointPos[3]; + bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, i); + + Bezier_Interact_Evaluate(State, PointAddress, PointPos); + + if (MinY > PointAddress->Pos[0].y) { + MinY = PointAddress->Pos[0].y; + PropertyStart->MinYIndex = i; + } + if (MaxY < PointAddress->Pos[0].y) { + MaxY = PointAddress->Pos[0].y; + PropertyStart->MaxYIndex = i; + } + + uint32 SortedIndex_Playhead = 0; + while (SortedIndex_Playhead < CurrentSortIndex) { + uint16 TestPointEntry = PropertyArrayStart[SortedIndex_Playhead]; + v2 TestPointPos[3]; + bezier_point *TestPointAddress = Bezier_LookupAddress(Memory, Property, TestPointEntry); + Bezier_Interact_Evaluate(State, TestPointAddress, TestPointPos); + if (PointPos[0].x < TestPointPos[0].x ) { + break; + } else { + SortedIndex_Playhead++; + } + } + if (SortedIndex_Playhead != CurrentSortIndex) { + uint8 *Address_Start = (uint8 *)(PropertyArrayStart + SortedIndex_Playhead); + uint8 *Address_End = (uint8 *)(PropertyArrayStart + CurrentSortIndex) - 1; + Assert(CurrentSortIndex != Property->Keyframe_Count); + Arbitrary_ShiftData(Address_Start, Address_End, sizeof(uint16), 1); + } + uint16 *PointEntry = PropertyArrayStart + SortedIndex_Playhead; + *PointEntry = i; + CurrentSortIndex++; + } +} + + +static void +Layer_Sort_CheckPrev(memory *Memory, int i, int Direction, sorted_layer_array *SortedLayerStart, sorted_comp_array SortedCompStart, int *EntriesPassed, sorted_layer_array *LayerEntry, bool32 AltMethod) +{ + int PrevOffsetIndex = i + Direction + (*EntriesPassed * Direction); + bool32 OutOfBounds = (Direction > 0) ? (PrevOffsetIndex > (SortedCompStart.LayerCount - 1)) : (PrevOffsetIndex < 0); + if (!OutOfBounds) { + sorted_layer_array *PrevLayerEntry = &SortedLayerStart[PrevOffsetIndex]; + real32 PrevOffset = PrevLayerEntry->SortedOffset; + if (PrevOffset == (LayerEntry->SortedOffset - Direction)) { + (*EntriesPassed)++; + if (!AltMethod) { + PrevLayerEntry->SortedOffset += Direction; + } else { + LayerEntry->SortedOffset -= Direction; + Layer_Sort_CheckPrev(Memory, i, Direction, SortedLayerStart, SortedCompStart, EntriesPassed, LayerEntry, AltMethod); + } + } + } +} + + +// The first loop is for counting how many layers are in each precomp, the +// second is for sorting the layers by offset, and the third is for applying +// interactivity if the user is moving any layers. + +static void +Layer_SortAll(project_state *State, memory *Memory, + sorted_layer_array *LayerArrayStart, sorted_comp_array *CompArrayStart, + uint32 LayerCount, uint32 CompCount) +{ + int h = 0, c = 0, i = 0; + while (Block_Loop(Memory, F_Layers, LayerCount, &h, &c, &i)) { + block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); + Assert(Layer->Block_Composition_Index < CompCount); + CompArrayStart[Layer->Block_Composition_Index].LayerCount++; + } + h = 0, c = 0, i = 0; + while (Block_Loop(Memory, F_Layers, LayerCount, &h, &c, &i)) { + block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); + sorted_comp_array *SortedCompStart = &CompArrayStart[Layer->Block_Composition_Index]; + sorted_layer_array *SortedLayerStart = Sorted_GetLayerStart(LayerArrayStart, CompArrayStart, Layer->Block_Composition_Index); + uint32 SortedIndex_Playhead = 0; + while (SortedIndex_Playhead < SortedCompStart->CurrentSortIndex) { + sorted_layer_array LayerEntry = SortedLayerStart[SortedIndex_Playhead]; + block_layer *TestLayer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, LayerEntry.Block_Layer_Index); + if (-Layer->Vertical_Offset < -TestLayer->Vertical_Offset) { + break; + } else { + SortedIndex_Playhead++; + } + } + if (SortedIndex_Playhead != SortedCompStart->CurrentSortIndex) { + uint8 *Address_Start = (uint8 *)(SortedLayerStart + SortedIndex_Playhead); + uint8 *Address_End = (uint8 *)(SortedLayerStart + SortedCompStart->CurrentSortIndex) - 1; + Assert(SortedCompStart->CurrentSortIndex != SortedCompStart->LayerCount); + Arbitrary_ShiftData(Address_Start, Address_End, sizeof(sorted_layer_array), 1); + } + sorted_layer_array *LayerEntry = SortedLayerStart + SortedIndex_Playhead; + LayerEntry->Block_Layer_Index = i; + LayerEntry->SortedOffset = Layer->Vertical_Offset; + SortedCompStart->CurrentSortIndex++; + } + if (State->Interact_Active == interact_type_layer_move) { + int32 Offset = (int32)State->Interact_Offset[1]; + bool32 Direction = (Offset > 0) ? 1 : -1; + for (uint32 c = 0; c < CompCount; c++) { + sorted_comp_array *SortedCompStart = &CompArrayStart[c]; + if (!SortedCompStart->LayerCount) + continue; + sorted_layer_array *SortedLayerStart = Sorted_GetLayerStart(LayerArrayStart, CompArrayStart, c); + int i = (Direction > 0) ? SortedCompStart->LayerCount - 1 : 0; + bool32 Case = 1; + while (Case) { + int32 EntriesPassed = 0; + sorted_layer_array *LayerEntry = &SortedLayerStart[i]; + block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, LayerEntry->Block_Layer_Index); + Assert(LayerEntry->SortedOffset == Layer->Vertical_Offset); + if (Layer->IsSelected) { + int32 SpacesToMove = Offset * Direction; + while (SpacesToMove) { + Layer_Sort_CheckPrev(Memory, i, Direction, SortedLayerStart, *SortedCompStart, &EntriesPassed, LayerEntry, 0); + LayerEntry->SortedOffset -= Direction; + SpacesToMove--; + } + } + int b = 0; + while (b < EntriesPassed) { + sorted_layer_array *FrontEntry = &SortedLayerStart[i+(b*Direction)]; + sorted_layer_array *BackEntry = &SortedLayerStart[i+((b+1)*Direction)]; + sorted_layer_array Swap = *FrontEntry; + *FrontEntry = *BackEntry; + *BackEntry = Swap; + b++; + } + i -= Direction; + Case = (Direction > 0) ? (i >= 0) : (i < SortedCompStart->LayerCount); + } + } + } +} + +// NOTE(fox): We could be slightly more efficient and just allocate redundant data +// instead of having another loop. +void LayerProperty_Count(project_data *File, project_state *State, memory *Memory, sorted_layer_array *LayerArrayStart, + sorted_comp_array *CompStart, uint32 LayerCount, uint32 CompCount, + uint32 *TotalPropertyCount, uint32 *TotalKeyframeCount) +{ + uint32 SortedPropertyPlayhead = 0; + uint32 SortedKeyframePlayhead = 0; + for (int c = 0; c < CompCount; c++) { + sorted_comp_array SortedCompStart = CompStart[c]; + sorted_layer_array *SortedLayerStart = Sorted_GetLayerStart(LayerArrayStart, CompStart, c); + for (int i = 0; i < SortedCompStart.LayerCount; i++) { + sorted_layer_array *SortedLayer = &SortedLayerStart[i]; + block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, SortedLayer->Block_Layer_Index); + SortedLayer->SortedPropertyStart = SortedPropertyPlayhead; + SortedLayer->SortedKeyframeStart = SortedKeyframePlayhead; + for (int h = 0; h < AmountOf(Layer->Property); h++) { + property_channel *Property = &Layer->Property[h]; + if (Property->Keyframe_Count) { + SortedKeyframePlayhead += Property->Keyframe_Count; + } + SortedPropertyPlayhead++; + } + for (int i = 0; i < Layer->Block_Effect_Count; i++) { + block_effect Effect = *(block_effect *)Memory_Block_AddressAtIndex(Memory, F_Effects, Layer->Block_Effect_Index[i]); + header_effect *EffectHeader = Effect_EntryFromID(State, Effect.ID); + for (int h = 0; h < EffectHeader->Property_Count; h++) { + header_property ChannelHeader = State->Property[EffectHeader->PropertyStartIndex + h]; + property_channel *Property = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect.Block_Property_Index[h]); + if (Property->Keyframe_Count) { + SortedKeyframePlayhead += Property->Keyframe_Count; + } + SortedPropertyPlayhead++; + } + } + } + } + *TotalPropertyCount = SortedPropertyPlayhead; + *TotalKeyframeCount = SortedKeyframePlayhead; +} + +void LayerProperty_SortAll(project_data *File, project_state *State, memory *Memory, sorted_layer_array *LayerArrayStart, + sorted_comp_array *CompStart, sorted_property_array *SortedPropertyStart, uint16 *SortedKeyframeArray, + uint32 LayerCount, uint32 CompCount) +{ + uint32 SortedPropertyPlayhead = 0; + uint32 SortedKeyframePlayhead = 0; + for (int c = 0; c < CompCount; c++) { + sorted_comp_array SortedCompStart = CompStart[c]; + sorted_layer_array *SortedLayerStart = Sorted_GetLayerStart(LayerArrayStart, CompStart, c); + for (int i = 0; i < SortedCompStart.LayerCount; i++) { + sorted_layer_array *SortedLayer = &SortedLayerStart[i]; + block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, SortedLayer->Block_Layer_Index); + SortedLayer->SortedPropertyStart = SortedPropertyPlayhead; + SortedLayer->SortedKeyframeStart = SortedKeyframePlayhead; + for (int h = 0; h < AmountOf(Layer->Property); h++) { + property_channel *Property = &Layer->Property[h]; + if (Property->Keyframe_Count) { + sorted_property_array *InfoLocation = SortedPropertyStart + SortedPropertyPlayhead; + uint16 *ArrayLocation = SortedKeyframeArray + SortedKeyframePlayhead; + Property_SortAll(Memory, State, Property, InfoLocation, ArrayLocation); + SortedKeyframePlayhead += Property->Keyframe_Count; + } + SortedPropertyPlayhead++; + } + for (int i = 0; i < Layer->Block_Effect_Count; i++) { + block_effect Effect = *(block_effect *)Memory_Block_AddressAtIndex(Memory, F_Effects, Layer->Block_Effect_Index[i]); + header_effect *EffectHeader = Effect_EntryFromID(State, Effect.ID); + for (int h = 0; h < EffectHeader->Property_Count; h++) { + header_property ChannelHeader = State->Property[EffectHeader->PropertyStartIndex + h]; + property_channel *Property = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect.Block_Property_Index[h]); + if (Property->Keyframe_Count) { + sorted_property_array *InfoLocation = SortedPropertyStart + SortedPropertyPlayhead; + uint16 *ArrayLocation = SortedKeyframeArray + SortedKeyframePlayhead; + Property_SortAll(Memory, State, Property, InfoLocation, ArrayLocation); + SortedKeyframePlayhead += Property->Keyframe_Count; + } + SortedPropertyPlayhead++; + } + } + } + } +} + +static void +TempSource_SortAll(project_data *File, project_state *State, memory *Memory, uint16 *SourceArrayStart, uint16 *TempSourceCount) +{ + int count = 0; + int h = 0, c = 0, i = 0; + while (Block_Loop(Memory, F_Sources, File->Source_Count, &h, &c, &i)) { + block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, i); + if (Source->Type == source_type_principal_temp) { + uint32 Playhead = 0; + while (Playhead < count) { + block_source *TestSource = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, SourceArrayStart[Playhead]); + Assert(TestSource->Type == source_type_principal_temp); + if (TestSource->RelativeTimestamp > Source->RelativeTimestamp) { + break; + } else { + Playhead++; + } + } + if (Playhead != count) { + uint8 *Address_Start = (uint8 *)(SourceArrayStart + Playhead); + uint8 *Address_End = (uint8 *)(SourceArrayStart + count) - 1; + Arbitrary_ShiftData(Address_Start, Address_End, sizeof(uint16), 1); + } + SourceArrayStart[Playhead] = i; + count++; + } + } + *TempSourceCount = count; +} + + +static sorted_file +File_Sort_Push(project_data *File, project_state *State, memory *Memory) +{ + sorted_file Sorted = {0}; + Sorted.Layer_SortSize = (sizeof(sorted_comp_array) * File->Comp_Count) + + (sizeof(sorted_layer_array) * File->Layer_Count); + void *Layer_SortedArray = Memory_PushScratch(Memory, Sorted.Layer_SortSize); + Arbitrary_Zero((uint8 *)Layer_SortedArray, Sorted.Layer_SortSize); + Sorted.CompArray = (sorted_comp_array *)Layer_SortedArray; + Sorted.LayerArray = (sorted_layer_array *)((uint8 *)Layer_SortedArray + (sizeof(sorted_comp_array) * File->Comp_Count)); + + uint64 SourceArraySize = sizeof(uint16) * File->Source_Count; + Sorted.Source_SortSize = SourceArraySize; + void *Source_SortedArray = Memory_PushScratch(Memory, Sorted.Source_SortSize); + Arbitrary_Zero((uint8 *)Source_SortedArray, Sorted.Source_SortSize); + Sorted.SourceArray = (uint16 *)Source_SortedArray; + + TempSource_SortAll(File, State, Memory, Sorted.SourceArray, &Sorted.TempSourceCount); + Layer_SortAll(State, Memory, Sorted.LayerArray, Sorted.CompArray, File->Layer_Count, File->Comp_Count); + + // Property sorting depends on above precomp/layer sorting! + + uint32 TotalPropertyCount = 0; + uint32 TotalKeyframeCount = 0; + LayerProperty_Count(File, State, Memory, Sorted.LayerArray, Sorted.CompArray, File->Layer_Count, File->Comp_Count, &TotalPropertyCount, &TotalKeyframeCount); + uint64 PropertyStartSize = TotalPropertyCount * sizeof(sorted_property_array); + uint64 PropertyArraySize = TotalKeyframeCount * sizeof(uint16); + Sorted.Property_SortSize = PropertyArraySize + PropertyStartSize; + void *Property_SortedArray = Memory_PushScratch(Memory, Sorted.Property_SortSize); + Arbitrary_Zero((uint8 *)Property_SortedArray, Sorted.Property_SortSize); + Sorted.PropertyStart = (sorted_property_array *)Property_SortedArray; + Sorted.PropertyArray = (uint16 *)((uint8 *)Property_SortedArray + PropertyStartSize); + + LayerProperty_SortAll(File, State, Memory, Sorted.LayerArray, Sorted.CompArray, Sorted.PropertyStart, Sorted.PropertyArray, File->Layer_Count, File->Comp_Count); + return Sorted; +} + +static void +File_Sort_Pop(memory *Memory, uint64 Layer_SortSize, uint64 Property_SortSize, uint64 Source_SortSize) +{ + Memory_PopScratch(Memory, Property_SortSize); + Memory_PopScratch(Memory, Source_SortSize); + Memory_PopScratch(Memory, Layer_SortSize); +} |