#if SPECIAL #include "main.h" #endif 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 *SortedLayerArray, sorted_comp_array *SortedCompArray, uint32 TargetComp) { uint32 LayerOffset = 0; int s = 0; while (s < TargetComp) { Assert(SortedCompArray[s].LayerCount < 10000); // passed Start instead of Array! Assert(SortedCompArray[s].FakeLayerCount < 10000); LayerOffset += SortedCompArray[s].LayerCount + SortedCompArray[s].FakeLayerCount; s++; } return SortedLayerArray + 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->Block_Bezier_Index, 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->Block_Bezier_Index, 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 real32 Layer_Sort_DisplayOffset(project_state *State, memory *Memory, sorted_property_array *SortedPropertyArray, uint16 *SortedKeyframeArray, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, sorted_comp_array *SortedCompStart, sorted_layer_array *SortedLayerStart) { int32 DisplayOffset = 0; int LayerCount = SortedCompStart->LayerCount + SortedCompStart->FakeLayerCount; for (int i = LayerCount - 1; i >= 0; i--) { sorted_layer_array *SortEntry = &SortedLayerStart[i]; SortEntry->DisplayOffset = DisplayOffset; uint32 Index_Physical = SortEntry->Block_Layer_Index; block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical); sorted_property_array *SortedPropertyStart = SortedPropertyArray + SortedLayerStart->SortedPropertyStart; uint16 *SortedKeyframeStart = SortedKeyframeArray + SortedLayerStart->SortedKeyframeStart; int h = 0, c = 0, p = 0; property_channel *Property = NULL; block_effect *Effect = NULL; while (Layer_LoopChannels(State, Memory, &SortedPropertyStart, &SortedKeyframeStart, Layer, &Property, &Effect, &h, &c, &p)) { if (Property->IsToggled) { DisplayOffset++; } } if (Layer->Precomp_Toggled) { Assert(Layer->IsPrecomp); sorted_comp_array *InnerSortedCompStart = &SortedCompArray[Layer->Block_Source_Index]; sorted_layer_array *InnerSortedLayerStart = Sorted_GetLayerStart(SortedLayerArray, SortedCompArray, Layer->Block_Source_Index); real32 InnerCompOffset = Layer_Sort_DisplayOffset(State, Memory, SortedPropertyArray, SortedKeyframeArray, SortedCompArray, SortedLayerArray, InnerSortedCompStart, InnerSortedLayerStart); InnerSortedCompStart->DisplaySize = InnerCompOffset; DisplayOffset += InnerCompOffset; } } if (LayerCount > 1) { sorted_layer_array LayerEntry_Top = SortedLayerStart[SortedCompStart->LayerCount - 1]; sorted_layer_array LayerEntry_Bottom = SortedLayerStart[0]; real32 SmallestY = LayerEntry_Top.SortedOffset; real32 LargestY = LayerEntry_Bottom.SortedOffset; // block_layer *Layer_Top = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, SortedLayerStart[SortedCompStart->LayerCount - 1].Block_Layer_Index); // block_layer *Layer_Bottom = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, SortedLayerStart[0].Block_Layer_Index); // real32 SmallestY = Layer_Top->Vertical_Offset; // real32 LargestY = Layer_Bottom->Vertical_Offset; DisplayOffset = LargestY - SmallestY + 2 + DisplayOffset; } else { DisplayOffset = 2; } return DisplayOffset; } 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_Sort_Shift(project_state *State, memory *Memory, sorted_layer_array *LayerArrayStart, sorted_comp_array *CompArrayStart, uint32 LayerCount, uint32 CompCount) { 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 & 0x01) { 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); } } } #if 0 static void Layer_Sort_Shift2(project_state *State, memory *Memory, sorted_layer_array *LayerArrayStart, sorted_comp_array *CompArrayStart, uint32 LayerCount, uint32 CompCount, int32 Offset) { 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; int FauxIncrement = 0; bool32 Case = 1; while (Case) { int Idx = i + FauxIncrement; int32 EntriesPassed = 0; sorted_layer_array *LayerEntry = &SortedLayerStart[Idx]; 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; Assert(SpacesToMove == 1); while (SpacesToMove) { Layer_Sort_CheckPrev(Memory, i, Direction, SortedLayerStart, *SortedCompStart, &EntriesPassed, LayerEntry, 0); 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); } } } #endif 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); sorted_comp_array *SortedCompStart = &CompArrayStart[Layer->Block_Composition_Index]; SortedCompStart->LayerCount++; if (State->Interact_Active == interact_type_viewport_duplicate && Layer->IsSelected & 0x01) { SortedCompStart->FakeLayerCount++; } } 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) { Layer_Sort_Shift(State, Memory, LayerArrayStart, CompArrayStart, LayerCount, CompCount); } else if (State->Interact_Active == interact_type_viewport_duplicate) { 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 Direction = (State->DuplicateMode & sortflag_up) ? 1 : -1; int Furthest = (State->DuplicateMode & sortflag_furthest) ? 1 : 0; if (Furthest) { Direction *= -1; } int i = (Direction > 0) ? 0 : SortedCompStart->LayerCount - 1; int FauxIncrement = 0; int FurthestMark = -1; for (;;) { int Idx = i + ((Direction > 0) ? FauxIncrement : 0); if (FauxIncrement && Furthest && (Direction > 0)) { Idx = i + SortedCompStart->FakeLayerCount; } sorted_layer_array *LayerEntry = &SortedLayerStart[Idx]; block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, LayerEntry->Block_Layer_Index); if (Layer->IsSelected & 0x01) { if (Furthest) { if (FauxIncrement == 0) { uint8 *Address_Start = (uint8 *)(LayerEntry); uint8 *Address_End = (uint8 *)(&SortedLayerStart[SortedCompStart->LayerCount + FauxIncrement]) - 1; Assert(SortedCompStart->CurrentSortIndex != (SortedCompStart->LayerCount + SortedCompStart->FakeLayerCount)); Arbitrary_ShiftData(Address_Start, Address_End, sizeof(sorted_layer_array) * SortedCompStart->FakeLayerCount, 1); FurthestMark = i + ((Direction > 0) ? 0 : -Direction); } int FakeIdx = FurthestMark + ((Direction > 0) ? FauxIncrement : (SortedCompStart->FakeLayerCount - 1) - FauxIncrement); sorted_layer_array *FakeLayerEntry = &SortedLayerStart[FakeIdx]; *FakeLayerEntry = *LayerEntry; FakeLayerEntry->IsFake = true; FauxIncrement++; } else { uint8 *Address_Start = (uint8 *)(LayerEntry); uint8 *Address_End = (uint8 *)(&SortedLayerStart[SortedCompStart->LayerCount + FauxIncrement]) - 1; Assert(SortedCompStart->CurrentSortIndex != (SortedCompStart->LayerCount + SortedCompStart->FakeLayerCount)); Arbitrary_ShiftData(Address_Start, Address_End, sizeof(sorted_layer_array), 1); sorted_layer_array *FakeLayerEntry = LayerEntry + ((Direction > 0) ? 1 : 0); Assert(FakeLayerEntry->Block_Layer_Index == LayerEntry->Block_Layer_Index); FakeLayerEntry->IsFake = true; FauxIncrement++; } } i += Direction; if ((Direction > 0) ? (i >= SortedCompStart->LayerCount) : (i < 0)) break; } // TODO(fox): Intermediate offset? // Sort_OffsetDupes(State, Memory, SortedLayerStart, // Direction, DupeIdx, LayerCount, SortedCompStart->FakeLayerCount) } } } // 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 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); int LayerCount = SortedCompStart.LayerCount + SortedCompStart.FakeLayerCount; for (int i = 0; i < LayerCount; i++) { sorted_layer_array *SortedLayer = &SortedLayerStart[i]; if (SortedLayer->IsFake) continue; 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 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); int LayerCount = SortedCompStart.LayerCount + SortedCompStart.FakeLayerCount; for (int i = 0; i < LayerCount; i++) { sorted_layer_array *SortedLayer = &SortedLayerStart[i]; if (SortedLayer->IsFake) continue; 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; InfoLocation->KeyframeCount = 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; InfoLocation->KeyframeCount = 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}; int ExtraLayers = 0; if (State->Interact_Active == interact_type_viewport_duplicate) { int h = 0, c = 0, i = 0; while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i)) { block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); Assert(Layer->Block_Composition_Index < File->Comp_Count); ExtraLayers++; } } Sorted.Layer_SortSize = (sizeof(sorted_comp_array) * File->Comp_Count) + (sizeof(sorted_layer_array) * (File->Layer_Count + ExtraLayers)); 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->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->Comp_Count); sorted_comp_array *MainSortedCompStart = &Sorted.CompArray[File->PrincipalCompIndex]; sorted_layer_array *MainSortedLayerStart = Sorted_GetLayerStart(Sorted.LayerArray, Sorted.CompArray, File->PrincipalCompIndex); Layer_Sort_DisplayOffset(State, Memory, Sorted.PropertyStart, Sorted.PropertyArray, Sorted.CompArray, Sorted.LayerArray, MainSortedCompStart, Sorted.LayerArray); 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); }