summaryrefslogtreecommitdiff
path: root/src/sorted.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sorted.cpp')
-rw-r--r--src/sorted.cpp336
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);
+}