From c27530c79fd135c499a52b222e9cec16aa1951ad Mon Sep 17 00:00:00 2001 From: Fox Caminiti Date: Fri, 11 Nov 2022 21:55:34 -0500 Subject: graph improvements --- createcalls.cpp | 195 ++++++++++++++++++++++++++++++++------------------- functions.h | 3 +- main.cpp | 100 +++++++++++++------------- main.h | 29 ++++---- memory.cpp | 11 +-- my_imgui_widgets.cpp | 110 ++++++++++++----------------- 6 files changed, 234 insertions(+), 214 deletions(-) diff --git a/createcalls.cpp b/createcalls.cpp index 176fc2f..01f1caa 100644 --- a/createcalls.cpp +++ b/createcalls.cpp @@ -67,13 +67,37 @@ Source_Generate(project_data *File, project_state *State, memory *Memory, void * } static bezier_point * -Bezier_Lookup(memory *Memory, property_channel *Property, uint16 Index) +Bezier_LookupAddress(memory *Memory, property_channel *Property, uint16 Index) { Assert(Index < MAX_KEYFRAMES_PER_BLOCK); block_bezier *Bezier = (block_bezier *)Memory_Block_AddressAtIndex(Memory, F_Bezier, Property->Block_Bezier_Index[0]); return &Bezier->Point[Index]; } +/* +if (State->Interact_Active == interact_type_keyframe_rotate) { + ImVec2 Keyframe_LocalPos_Ratio = (V2(Keyframe_LocalPos_[0]) - ImVec2(0, GraphInfo.MinVal)) * ImVec2(Increment.x, Y_Increment); + ImVec2 Keyframe_ScreenPos = Layer_ScreenPos_Min + ((ImVec2(1, -1) * Keyframe_LocalPos_Ratio + ImVec2(0, 0.5)) * TimelineZoomSize) + ImVec2(0, Layer_ScreenSize.y/2); + real32 Slope_Old = (Keyframe_ScreenPos.y - State->Interact_Offset[3]) / (Keyframe_ScreenPos.x - State->Interact_Offset[2]); + real32 Slope_New = (Keyframe_ScreenPos.y - io.MousePos.y) / (Keyframe_ScreenPos.x - io.MousePos.x); + State->Interact_Offset[0] = atan((Slope_Old - Slope_New) / (1 + Slope_Old * Slope_New)); + DebugWatchVar("Rotation: ", &State->Interact_Offset[0], d_float); +} +*/ +// Keyframe_Interact_Evaluate(Memory, State, Point->IsSelected, Point->Pos, Keyframe_LocalPos_); + + +static void +Bezier_EvaluateValue(project_state *State, bezier_point *PointAddress, v2 *Pos) +{ + Pos[0] = PointAddress->Pos[0]; + Pos[1] = PointAddress->Pos[1]; + Pos[2] = PointAddress->Pos[2]; + if (State->Interact_Active == interact_type_keyframe_move && PointAddress->IsSelected) { + Pos[0].x += (int32)State->Interact_Offset[0]; + } +} + static void Bezier_Add(memory *Memory, property_channel *Property, bezier_point PointData) { @@ -87,7 +111,7 @@ Bezier_Add(memory *Memory, property_channel *Property, bezier_point PointData) } int k = 0; for (;;) { - bezier_point *Point = Bezier_Lookup(Memory, Property, k); + bezier_point *Point = Bezier_LookupAddress(Memory, Property, k); if (!Point->Occupied) { History_Action_Swap(Memory, F_Bezier, sizeof(*Point), Point); *Point = PointData; @@ -110,45 +134,6 @@ Property_InitFloat(char *Name, real32 Val, real32 ScrubVal, real32 MinVal = PROP return Property; } -// static property_info -// Property_Sort(memory *Memory, property_channel *Property) -// { -// } - -static property_info -Property_GetInfo(memory *Memory, property_channel *Property) -{ - property_info PropertyInfo = {}; - int h = 0, c = 0, i = 0; - while (Block_Loop(Memory, Property, Property->Keyframe_Count, &h, &c, &i)) { - bezier_point *Point = Bezier_Lookup(Memory, Property, i); - PropertyInfo.MinVal = (Point->Pos[0].y < PropertyInfo.MinVal) ? Point->Pos[0].y : PropertyInfo.MinVal; - PropertyInfo.MaxVal = (Point->Pos[0].y > PropertyInfo.MaxVal) ? Point->Pos[0].y : PropertyInfo.MaxVal; - } - return PropertyInfo; -} - -static graph_info -Graph_GetInfo(project_data *File, memory *Memory) -{ - graph_info GraphInfo = {}; - for (int a = 0; a < File->Layer_Count; a++) { - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, a); - if (!Layer->IsSelected) - continue; - for (int h = 0; h < AmountOf(Layer->Property); h++) { - property_channel *Property = &Layer->Property[h]; - if (Property->Block_Bezier_Count) { - property_info PropertyInfo = Property_GetInfo(Memory, Property); - GraphInfo.MinVal = (PropertyInfo.MinVal < GraphInfo.MinVal) ? PropertyInfo.MinVal : GraphInfo.MinVal; - GraphInfo.MaxVal = (PropertyInfo.MaxVal > GraphInfo.MaxVal) ? PropertyInfo.MaxVal : GraphInfo.MaxVal; - } - } - GraphInfo.LowestOffset = (Layer->Vertical_Offset > GraphInfo.LowestOffset) ? Layer->Vertical_Offset : GraphInfo.LowestOffset; - } - return GraphInfo; -} - static void Keyframe_Interact_Evaluate(memory *Memory, project_state *State, uint8 IsSelected, v2 Pos_Initial[3], v2 Pos_New[3]) { @@ -303,63 +288,98 @@ void Layer_RecursiveDeselect(memory *Memory, sorted_comp_info *SortedCompArray, } } -void Layer_Sort_CheckPrev(memory *Memory, int i, int Direction, sorted_layer *SortedLayerInfo, sorted_comp_info SortedCompInfo, int *EntriesPassed, sorted_layer *LayerEntry) +void Property_MinMax(memory *Memory, project_state *State, property_channel *Property, uint16 *ArrayLocation, v2 *Min, v2 *Max) { - int PrevOffsetIndex = i + Direction + (*EntriesPassed * Direction); - bool32 OutOfBounds = (Direction > 0) ? (PrevOffsetIndex > (SortedCompInfo.LayerCount - 1)) : (PrevOffsetIndex < 0); - if (!OutOfBounds) { - sorted_layer *PrevLayerEntry = &SortedLayerInfo[PrevOffsetIndex]; - // block_layer *PrevLayer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, PrevLayerEntry->Block_Layer_Index); - // real32 PrevOffset = PrevLayer->Vertical_Offset; - real32 PrevOffset = PrevLayerEntry->SortedOffset; - if (PrevOffset == (LayerEntry->SortedOffset - Direction)) { - LayerEntry->SortedOffset -= Direction; - (*EntriesPassed)++; - Layer_Sort_CheckPrev(Memory, i, Direction, SortedLayerInfo, SortedCompInfo, EntriesPassed, LayerEntry); - } + v2 FirstPointPos[3]; + bezier_point *FirstPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[0]); + Bezier_EvaluateValue(State, FirstPointAddress, FirstPointPos); + Min->x = FirstPointPos[0].x; + v2 LastPointPos[3]; + bezier_point *LastPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[Property->Keyframe_Count - 1]); + Bezier_EvaluateValue(State, LastPointAddress, LastPointPos); + Max->x = LastPointPos[0].x; + int32 Offset = (State->Interact_Active == interact_type_keyframe_move) ? (int32)State->Interact_Offset[0] : 0; + real32 MinY = FLT_MAX; + real32 MaxY = FLT_MIN; + for (int p = 0; p < Property->Keyframe_Count; p++) { + bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[p]); + MinY = (MinY < PointAddress->Pos[0].y) ? MinY : PointAddress->Pos[0].y; + MaxY = (MaxY > PointAddress->Pos[0].y) ? MaxY : PointAddress->Pos[0].y; } + Min->y = MinY; + Max->y = MaxY; } -// TODO(fox): This _could_ be generalized with the layer sorting code... +// 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. -/* -Bezier_SortAll() +void Property_SortAll(memory *Memory, project_state *State, property_channel *Property, uint16 *PropertyArrayStart) { - while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i)) { - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); - sorted_comp_info *SortedCompInfo = &CompStart[Layer->Block_Composition_Index]; - sorted_layer *SortedLayerInfo = Layer_GetSortedArray(LayerArrayStart, CompStart, Layer->Block_Composition_Index); + int h = 0, c = 0, i = 0; + uint32 CurrentSortIndex = 0; + 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_EvaluateValue(State, PointAddress, PointPos); uint32 SortedIndex_Playhead = 0; while (SortedIndex_Playhead < CurrentSortIndex) { - sorted_layer LayerEntry = SortedLayerInfo[SortedIndex_Playhead]; - block_layer *TestLayer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, LayerEntry.Block_Layer_Index); - if (-Layer->Vertical_Offset < -TestLayer->Vertical_Offset) { + uint16 TestPointEntry = PropertyArrayStart[SortedIndex_Playhead]; + v2 TestPointPos[3]; + bezier_point *TestPointAddress = Bezier_LookupAddress(Memory, Property, TestPointEntry); + Bezier_EvaluateValue(State, TestPointAddress, TestPointPos); + if (PointPos[0].x < TestPointPos[0].x ) { break; } else { SortedIndex_Playhead++; } } if (SortedIndex_Playhead != CurrentSortIndex) { - uint8 *Address_Start = (uint8 *)(SortedLayerInfo + SortedIndex_Playhead); - uint8 *Address_End = (uint8 *)(SortedLayerInfo + CurrentSortIndex) - 1; - Assert(CurrentSortIndex != SortedCompInfo->LayerCount); - Arbitrary_ShiftData(Address_Start, Address_End, sizeof(sorted_layer), 1); + 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); } - sorted_layer *LayerEntry = SortedLayerInfo + SortedIndex_Playhead; - LayerEntry->Block_Layer_Index = i; - LayerEntry->SortedOffset = Layer->Vertical_Offset; + uint16 *PointEntry = PropertyArrayStart + SortedIndex_Playhead; + *PointEntry = i; CurrentSortIndex++; } } -*/ -void Layer_SortAll(project_data *File, project_state *State, memory *Memory, sorted_layer *LayerArrayStart, sorted_comp_info *CompStart, uint32 LayerCount, uint32 CompCount) +void Layer_Sort_CheckPrev(memory *Memory, int i, int Direction, sorted_layer *SortedLayerInfo, sorted_comp_info SortedCompInfo, int *EntriesPassed, sorted_layer *LayerEntry) +{ + int PrevOffsetIndex = i + Direction + (*EntriesPassed * Direction); + bool32 OutOfBounds = (Direction > 0) ? (PrevOffsetIndex > (SortedCompInfo.LayerCount - 1)) : (PrevOffsetIndex < 0); + if (!OutOfBounds) { + sorted_layer *PrevLayerEntry = &SortedLayerInfo[PrevOffsetIndex]; + real32 PrevOffset = PrevLayerEntry->SortedOffset; + if (PrevOffset == (LayerEntry->SortedOffset - Direction)) { + LayerEntry->SortedOffset -= Direction; + (*EntriesPassed)++; + Layer_Sort_CheckPrev(Memory, i, Direction, SortedLayerInfo, SortedCompInfo, EntriesPassed, LayerEntry); + } + } +} + +// 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. + +void Layer_SortAll(project_data *File, project_state *State, memory *Memory, sorted_layer *LayerArrayStart, sorted_comp_info *CompStart, uint16 *SortedPropertyArray, uint32 LayerCount, uint32 CompCount) { 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 < CompCount); CompStart[Layer->Block_Composition_Index].LayerCount++; + for (int h = 0; h < AmountOf(Layer->Property); h++) { + property_channel *Property = &Layer->Property[h]; + if (Property->Block_Bezier_Count) { + uint16 *ArrayLocation = SortedPropertyArray + (i * 7 * MAX_KEYFRAMES_PER_BLOCK) + (h * MAX_KEYFRAMES_PER_BLOCK); + Property_SortAll(Memory, State, Property, ArrayLocation); + } + } } h = 0, c = 0, i = 0; uint32 CurrentSortIndex = 0; @@ -427,6 +447,35 @@ void Layer_SortAll(project_data *File, project_state *State, memory *Memory, sor } } +sorted_file File_Sort_Push(project_data *File, project_state *State, memory *Memory) +{ + sorted_file Sorted = {0}; + Sorted.Layer_SortSize = (sizeof(sorted_comp_info) * File->Comp_Count) + + (sizeof(sorted_layer) * File->Layer_Count); + void *Layer_SortedArray = Memory_PushScratch(Memory, Sorted.Layer_SortSize); + Arbitrary_Zero((uint8 *)Layer_SortedArray, Sorted.Layer_SortSize); + Sorted.CompArray = (sorted_comp_info *)Layer_SortedArray; + Sorted.LayerArray = (sorted_layer *)((uint8 *)Layer_SortedArray + (sizeof(sorted_comp_info) * File->Comp_Count)); + + uint64 PropertyArraySize = sizeof(uint16) * 7 * MAX_KEYFRAMES_PER_BLOCK * File->Layer_Count; + uint64 PropertyInfoSize = sizeof(sorted_property_info) * 7 * File->Layer_Count; + Sorted.Property_SortSize = PropertyArraySize + PropertyInfoSize; + void *Property_SortedArray = Memory_PushScratch(Memory, Sorted.Property_SortSize); + Arbitrary_Zero((uint8 *)Property_SortedArray, Sorted.Property_SortSize); + Sorted.PropertyInfo = (sorted_property_info *)Property_SortedArray; + Sorted.PropertyArray = (uint16 *)((uint8 *)Property_SortedArray + PropertyInfoSize); + + Layer_SortAll(File, State, Memory, Sorted.LayerArray, Sorted.CompArray, Sorted.PropertyArray, File->Layer_Count, File->Comp_Count); + return Sorted; +} + +void File_Sort_Pop(memory *Memory, uint64 Layer_SortSize, uint64 Property_SortSize) +{ + Memory_PopScratch(Memory, Property_SortSize); + Memory_PopScratch(Memory, Layer_SortSize); +} + + static void Layer_Delete(project_data *File, memory *Memory, uint32 Index) { diff --git a/functions.h b/functions.h index eff7435..a6b608e 100644 --- a/functions.h +++ b/functions.h @@ -14,7 +14,8 @@ static ImVec2 Layer_LocalToScreenSpace(project_state *State, memory *Memory, blo static v2 TransformPoint(layer_transforms T, real32 Width, real32 Height, v2 Point); -static bezier_point * Bezier_Lookup(memory *Memory, property_channel *Property, uint16 Index); +static bezier_point * Bezier_LookupAddress(memory *Memory, property_channel *Property, uint16 Index); +static void Bezier_EvaluateValue(project_state *State, bezier_point *PointAddress, v2 *Pos); static void Transform_ApplyInteractive(interact_transform Interact, real32 *OutputX, real32 *OutputY, real32 *OutputRotation, real32 *OutputScale); diff --git a/main.cpp b/main.cpp index 50f9cc5..31572b4 100644 --- a/main.cpp +++ b/main.cpp @@ -130,16 +130,10 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI, if (!io.WantCaptureKeyboard) ImGui_ProcessInputs(File, State, UI, Memory, io); - uint64 SortSize = (sizeof(sorted_comp_info) * File->Comp_Count) + (sizeof(sorted_layer) * File->Layer_Count); - void *SortedArray = Memory_PushScratch(Memory, SortSize); - Arbitrary_Zero((uint8 *)SortedArray, SortSize); - sorted_comp_info *SortedCompArray = (sorted_comp_info *)SortedArray; - sorted_layer *SortedLayerArray = (sorted_layer *)((uint8 *)SortedArray + (sizeof(sorted_comp_info) * File->Comp_Count)); - Layer_SortAll(File, State, Memory, SortedLayerArray, SortedCompArray, File->Layer_Count, File->Comp_Count); - + sorted_file Sorted = File_Sort_Push(File, State, Memory); if (ImGui::IsKeyPressed(ImGuiKey_T)) { - Interact_Transform_Begin(File, Memory, State, io.MousePos, SortedCompArray, SortedLayerArray); + Interact_Transform_Begin(File, Memory, State, io.MousePos, Sorted.CompArray, Sorted.LayerArray); } ImGui::DockSpaceOverViewport(); @@ -151,22 +145,29 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI, } if (State->Initializing == 3) { - Source_UICreateButton(File, State, Memory, SortedCompArray, SortedLayerArray); + Source_UICreateButton(File, State, Memory, Sorted.CompArray, Sorted.LayerArray); block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 0); History_Entry_Commit(Memory, "Add keyframe"); property_channel *Property = &Layer->x; { - bezier_point Point = { 1, {0, 300, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 }; + bezier_point Point = { 1, {0, 800, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 }; + Bezier_Add(Memory, Property, Point); + } + { + bezier_point Point = { 1, {20, 300, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 }; + Bezier_Add(Memory, Property, Point); + } + { + bezier_point Point = { 1, {10, 200, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 }; Bezier_Add(Memory, Property, Point); } { - bezier_point Point = { 1, {20, 800, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 }; + bezier_point Point = { 1, {15, 200, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 }; Bezier_Add(Memory, Property, Point); } History_Entry_End(Memory); - bezier_point *Point2 = Bezier_Lookup(Memory, Property, 0); - + /* History_Entry_Commit(Memory, "Add keyframe"); Property = &Layer->y; { @@ -174,31 +175,33 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI, Bezier_Add(Memory, Property, Point); } { - bezier_point Point = { 1, {20, -500, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 }; + bezier_point Point = { 1, {20, 400, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 }; Bezier_Add(Memory, Property, Point); } Property = &Layer->opacity; { - bezier_point Point = { 1, {0, 0, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 }; + bezier_point Point = { 1, {0, 1, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 }; Bezier_Add(Memory, Property, Point); } { - bezier_point Point = { 1, {20, 1, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 }; + bezier_point Point = { 1, {20, 0, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 }; Bezier_Add(Memory, Property, Point); } + */ History_Entry_End(Memory); } - ImGui_Viewport(File, State, UI, Memory, io, textureID, SortedCompArray, SortedLayerArray); - ImGui_Timeline(File, State, Memory, UI, io, SortedCompArray, SortedLayerArray); - ImGui_File(File, State, Memory, io, SortedCompArray, SortedLayerArray); + ImGui_Viewport(File, State, UI, Memory, io, textureID, Sorted.CompArray, Sorted.LayerArray); + ImGui_Timeline(File, State, Memory, UI, io, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyArray); + ImGui_File(File, State, Memory, io, Sorted.CompArray, Sorted.LayerArray); ImGui_PropertiesPanel(File, State, UI, Memory, io); ImGui_ColorPanel(File, State, UI, Memory, io); ImGui_Menu(File, State, UI, Memory, io); - Memory_PopScratch(Memory, SortSize); + File_Sort_Pop(Memory, Sorted.Layer_SortSize, Sorted.Property_SortSize); + #if DEBUG Debug.Temp = {}; #endif @@ -207,7 +210,7 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI, } static void * -Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, uint32 CompIndex) +Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, uint16 *SortedPropertyArray, uint32 CompIndex) { block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, CompIndex); cache_entry *Entry_Main = Memory_Cache_Search(State, Memory, cache_entry_type_comp, CompIndex, State->Frame_Current); @@ -266,7 +269,7 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io cache_entry *Entry = Memory_Cache_Search(State, Memory, cache_entry_type_comp, Layer->Block_Source_Index, State->Frame_Current); // if (!Entry->IsCached) { uint64 Src_TimeStart = GetTime(); - Render_Comp(File, State, Memory, io, SortedCompArray, SortedLayerArray, Layer->Block_Source_Index); + Render_Comp(File, State, Memory, io, SortedCompArray, SortedLayerArray, SortedPropertyArray, Layer->Block_Source_Index); Entry->CycleTime = GetTime() - Src_TimeStart; // } BitmapAddress = Memory_Block_Bitmap_AddressAtIndex(Memory, Entry->Block_StartIndex); @@ -278,37 +281,34 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io // for (int a = 0; a < Layer->Block_Effect_Count; a++) { // } + int32 Offset = (State->Interact_Active == interact_type_keyframe_move) ? (int32)State->Interact_Offset[0] : 0; for (int h = 0; h < AmountOf(Layer->Property); h++) { property_channel *Property = &Layer->Property[h]; + uint16 *ArrayLocation = SortedPropertyArray + (i * 7 * MAX_KEYFRAMES_PER_BLOCK) + (h * MAX_KEYFRAMES_PER_BLOCK); if (Property->Block_Bezier_Count) { - bezier_point *FirstPoint = Bezier_Lookup(Memory, Property, 0); - int k = 0; - for (;;) { - bezier_point *Point = Bezier_Lookup(Memory, Property, k); - if (!Point->Occupied) - break; - k++; - } - bezier_point *LastPoint = Bezier_Lookup(Memory, Property, k - 1); - if (FirstPoint->Pos[0].x >= State->Frame_Current) { - Property->CurrentValue = FirstPoint->Pos[0].y; - } else if (LastPoint->Pos[0].x <= State->Frame_Current) { - Property->CurrentValue = LastPoint->Pos[0].y; + v2 Min, Max; + Property_MinMax(Memory, State, Property, ArrayLocation, &Min, &Max); + if (Min.x >= State->Frame_Current) { + Property->CurrentValue = Min.y; + } else if (Max.x <= State->Frame_Current) { + Property->CurrentValue = Max.y; } else { int KeyframeIndex = 0; for (;;) { - bezier_point *Point = Bezier_Lookup(Memory, Property, KeyframeIndex + 1); - if (Point->Pos[0].x >= State->Frame_Current) + v2 PointPos[3]; + bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex + 1]); + Bezier_EvaluateValue(State, PointAddress, PointPos); + if (PointPos[0].x >= State->Frame_Current) break; KeyframeIndex++; } - bezier_point *Point = Bezier_Lookup(Memory, Property, KeyframeIndex); - bezier_point *NextPoint = Bezier_Lookup(Memory, Property, KeyframeIndex + 1); - v2 Pos_New[3] = { Point->Pos[0], Point->Pos[1], Point->Pos[2] }; - v2 NextPos_New[3] = { NextPoint->Pos[0], NextPoint->Pos[1], NextPoint->Pos[2] }; - Keyframe_Interact_Evaluate(Memory, State, Point->IsSelected, Point->Pos, Pos_New); - Keyframe_Interact_Evaluate(Memory, State, NextPoint->IsSelected, NextPoint->Pos, NextPos_New); - Property->CurrentValue = Bezier_SolveYForX(Pos_New[0], Pos_New[0] + Pos_New[2], NextPos_New[0] + NextPos_New[1], NextPos_New[0], State->Frame_Current); + v2 PointPos[3]; + bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex]); + Bezier_EvaluateValue(State, PointAddress, PointPos); + v2 NextPointPos[3]; + bezier_point *NextPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex + 1]); + Bezier_EvaluateValue(State, NextPointAddress, NextPointPos); + Property->CurrentValue = Bezier_SolveYForX(PointPos[0], PointPos[0] + PointPos[2], NextPointPos[0] + NextPointPos[1], NextPointPos[0], State->Frame_Current); } } } @@ -347,17 +347,11 @@ Main_Renderer(project_data *File, project_state *State, memory *Memory, SDL_Wind block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, File->PrincipalCompIndex); - // NOTE(fox): All layers are given a slot here - uint64 SortSize = (sizeof(sorted_comp_info) * File->Comp_Count) + (sizeof(sorted_layer) * File->Layer_Count); - void *SortedArray = Memory_PushScratch(Memory, SortSize); - Arbitrary_Zero((uint8 *)SortedArray, SortSize); - sorted_comp_info *SortedCompArray = (sorted_comp_info *)SortedArray; - sorted_layer *SortedLayerArray = (sorted_layer *)((uint8 *)SortedArray + (sizeof(sorted_comp_info) * File->Comp_Count)); - Layer_SortAll(File, State, Memory, SortedLayerArray, SortedCompArray, File->Layer_Count, File->Comp_Count); + sorted_file Sorted = File_Sort_Push(File, State, Memory); - void *MainCompBuffer = Render_Comp(File, State, Memory, io, SortedCompArray, SortedLayerArray, File->PrincipalCompIndex); + void *MainCompBuffer = Render_Comp(File, State, Memory, io, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyArray, File->PrincipalCompIndex); - Memory_PopScratch(Memory, SortSize); + File_Sort_Pop(Memory, Sorted.Layer_SortSize, Sorted.Property_SortSize); glBindTexture(GL_TEXTURE_2D, textureID); diff --git a/main.h b/main.h index 096107a..26b3666 100644 --- a/main.h +++ b/main.h @@ -116,6 +116,12 @@ enum focused_window focus_timeline }; +struct sorted_property_info +{ + uint32 MinYIndex; + uint32 MaxYIndex; +}; + struct sorted_comp_info { uint32 LayerCount; @@ -127,6 +133,16 @@ struct sorted_layer real32 SortedOffset; }; +struct sorted_file +{ + sorted_layer *LayerArray; + sorted_comp_info *CompArray; + sorted_property_info *PropertyInfo; + uint16 *PropertyArray; + uint64 Layer_SortSize; + uint64 Property_SortSize; +}; + enum timeline_mode { timeline_mode_default, @@ -362,19 +378,6 @@ struct property_header real32 MaxVal; }; -struct graph_info -{ - real32 MinVal = FLT_MAX; - real32 MaxVal = FLT_MIN; - real32 LowestOffset = FLT_MIN; -}; - -struct property_info -{ - real32 MinVal = FLT_MAX; - real32 MaxVal = FLT_MIN; -}; - struct property_channel { uint8 Occupied; char *Name; diff --git a/memory.cpp b/memory.cpp index 3b3c64f..53388bf 100644 --- a/memory.cpp +++ b/memory.cpp @@ -50,7 +50,7 @@ Memory_Block_AllocateAddress(memory *Memory, memory_table_list TableName) // IMPORTANT(fox): All block data has to start with a uint8 Occupied variable! static bool32 -Block_Loop(memory *Memory, memory_table_list TableName, uint32 TotalCount, int *HasIncremented, int *CurrentCount, int *Index, void *Extra = NULL) +Block_Loop(memory *Memory, memory_table_list TableName, uint32 TotalCount, int *HasIncremented, int *CurrentCount, int *Index) { for (;;) { if (*CurrentCount == TotalCount) { @@ -60,12 +60,7 @@ Block_Loop(memory *Memory, memory_table_list TableName, uint32 TotalCount, int * *HasIncremented = 0; (*Index)++; } - uint8 *Occupied; - if (!Extra) { - Occupied = (uint8 *)Memory_Block_AddressAtIndex(Memory, TableName, *Index); - } else { - Occupied = (uint8 *)Bezier_Lookup(Memory, (property_channel *)Extra, *Index); - } + uint8 *Occupied = (uint8 *)Memory_Block_AddressAtIndex(Memory, TableName, *Index); if (*Occupied) { *HasIncremented = 1; (*CurrentCount)++; @@ -90,7 +85,7 @@ Block_Loop(memory *Memory, property_channel *Property, uint32 TotalCount, int *H *HasIncremented = 0; (*Index)++; } - uint8 *Occupied = (uint8 *)Bezier_Lookup(Memory, Property, *Index); + uint8 *Occupied = (uint8 *)Bezier_LookupAddress(Memory, Property, *Index); if (*Occupied) { *HasIncremented = 1; (*CurrentCount)++; diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp index 722ce1e..04cedb0 100644 --- a/my_imgui_widgets.cpp +++ b/my_imgui_widgets.cpp @@ -988,14 +988,14 @@ ImGui_GraphInfo(project_data *File, project_state *State, memory *Memory, ui *UI } static void -ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, ImDrawList *draw_list, graph_info GraphInfo, +ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, ImDrawList *draw_list, ImVec2 Increment, ImVec2 TimelineAbsolutePos, ImVec2 TimelineMoveSize, ImVec2 TimelineZoomSize, - ImVec2 TimelineSize, ImVec2 TimelineSizeWithBorder, real32 LayerIncrement) + ImVec2 TimelineSize, ImVec2 TimelineSizeWithBorder, real32 LayerIncrement, uint16 *SortedPropertyArray) { UI->Test.Split(draw_list, 2); - TimelineMoveSize.y = TimelineMoveSize.y + (TimelineZoomSize.y * (0.25 / 2)); - TimelineZoomSize.y = TimelineZoomSize.y * 0.75; + TimelineMoveSize.y = TimelineMoveSize.y + (TimelineZoomSize.y * (0.25 / 4)); + TimelineZoomSize.y = TimelineZoomSize.y * 0.6; int h = 0, c = 0, i = 0; while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i)) @@ -1014,9 +1014,11 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor if (State->Interact_Active == interact_type_keyframe_move) { ImVec2 DragDelta = io.MousePos - ImVec2(State->Interact_Offset[2], State->Interact_Offset[3]); - // State->Interact_Offset[0] = (DragDelta.x / TimelineSizeWithBorder.x * UI->TimelinePercentZoomed.x) / Increment.x; - // State->Interact_Offset[1] = -1 * (DragDelta.y / TimelineSizeWithBorder.y * UI->TimelinePercentZoomed.y) * ((GraphInfo.MaxVal - GraphInfo.MinVal)); - State->Interact_Offset[0] = DragDelta.x; + // NOTE(fox): I'm setting the X (time) to the transformed value and + // the Y (value) to the raw drag delta, because the Y units can be + // normalized while the X units are always universal across all the + // graphs (and it has to be passed into the sorter). + State->Interact_Offset[0] = (DragDelta.x / TimelineZoomSize.x) / Increment.x; State->Interact_Offset[1] = DragDelta.y; DebugWatchVar("DeltaX: ", &DragDelta.x, d_float); DebugWatchVar("Deltay: ", &DragDelta.y, d_float); @@ -1036,50 +1038,30 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor for (int h = 0; h < AmountOf(Layer->Property); h++) { property_channel *Property = &Layer->Property[h]; + uint16 *ArrayLocation = SortedPropertyArray + (i * 7 * MAX_KEYFRAMES_PER_BLOCK) + (h * MAX_KEYFRAMES_PER_BLOCK); ImGui::PushID(Property); if (Property->Block_Bezier_Count) { - property_info PropertyInfo = Property_GetInfo(Memory, Property); - real32 Y_Increment = 1 / (GraphInfo.MaxVal - GraphInfo.MinVal); + v2 Min, Max; + Property_MinMax(Memory, State, Property, ArrayLocation, &Min, &Max); + real32 Y_Increment = 1 / (Max.y - Min.y); bezier_point *PointAddress[2] = {}; ImVec2 Keyframe_ScreenPos[6] = {}; - int k = 0; - for (;;) { - int Idx = (k % 2); + for (int p = 0; p < Property->Keyframe_Count; p++) { + int k = ArrayLocation[p]; + int Idx = (p % 2); int NewIdx = Idx * 3; int OldIdx = (NewIdx == 3) ? 0 : 3; - PointAddress[Idx] = Bezier_Lookup(Memory, Property, k); - bezier_point *Point = PointAddress[Idx]; - - if (!Point->Occupied) - break; - - v2 Keyframe_LocalPos_[3] = { Point->Pos[0], Point->Pos[1], Point->Pos[2] }; - - if (Point->IsSelected) { - /* - if (State->Interact_Active == interact_type_keyframe_rotate) { - ImVec2 Keyframe_LocalPos_Ratio = (V2(Keyframe_LocalPos_[0]) - ImVec2(0, GraphInfo.MinVal)) * ImVec2(Increment.x, Y_Increment); - ImVec2 Keyframe_ScreenPos = Layer_ScreenPos_Min + ((ImVec2(1, -1) * Keyframe_LocalPos_Ratio + ImVec2(0, 0.5)) * TimelineZoomSize) + ImVec2(0, Layer_ScreenSize.y/2); - real32 Slope_Old = (Keyframe_ScreenPos.y - State->Interact_Offset[3]) / (Keyframe_ScreenPos.x - State->Interact_Offset[2]); - real32 Slope_New = (Keyframe_ScreenPos.y - io.MousePos.y) / (Keyframe_ScreenPos.x - io.MousePos.x); - State->Interact_Offset[0] = atan((Slope_Old - Slope_New) / (1 + Slope_Old * Slope_New)); - DebugWatchVar("Rotation: ", &State->Interact_Offset[0], d_float); - } - */ - v2 Offset = V2(State->Interact_Offset[0], State->Interact_Offset[1]); - if (State->Interact_Active == interact_type_keyframe_move) { - Keyframe_LocalPos_[0].x += (Offset.x / TimelineZoomSize.x) / Increment.x; - Keyframe_LocalPos_[0].y -= ((Offset.y / TimelineZoomSize.y)) * (GraphInfo.MaxVal - GraphInfo.MinVal); - } - // Keyframe_Interact_Evaluate(Memory, State, Point->IsSelected, Point->Pos, Keyframe_LocalPos_); - } - ImVec2 Keyframe_LocalPos[3] = { V2(Keyframe_LocalPos_[0]), V2(Keyframe_LocalPos_[0] + Keyframe_LocalPos_[1]), V2(Keyframe_LocalPos_[0] + Keyframe_LocalPos_[2]) }; + PointAddress[Idx] = Bezier_LookupAddress(Memory, Property, k); + + v2 PointPos[3]; + Bezier_EvaluateValue(State, PointAddress[Idx], PointPos); + + ImVec2 Keyframe_LocalPos[3] = { V2(PointPos[0]), V2(PointPos[0] + PointPos[1]), V2(PointPos[0] + PointPos[2]) }; ImVec2 Keyframe_LocalPos_Ratio[3]; for (int b = 0; b < 3; b++) { - Keyframe_LocalPos_Ratio[b] = (Keyframe_LocalPos[b] - ImVec2(0, GraphInfo.MinVal)) * ImVec2(Increment.x, Y_Increment); - // Keyframe_ScreenPos[NewIdx + b] = Layer_ScreenPos_Min + ((ImVec2(1, -1) * Keyframe_LocalPos_Ratio[b] + ImVec2(0, 0.5)) * TimelineZoomSize) + ImVec2(0, Layer_ScreenSize.y/2); - Keyframe_ScreenPos[NewIdx + b] = TimelineAbsolutePos + TimelineMoveSize + ((ImVec2(1, -1) * Keyframe_LocalPos_Ratio[b] + ImVec2(0, 1)) * TimelineZoomSize); + Keyframe_LocalPos_Ratio[b] = (Keyframe_LocalPos[b] - ImVec2(0, Min.y)) * ImVec2(Increment.x, Y_Increment); + Keyframe_ScreenPos[NewIdx + b] = TimelineAbsolutePos + TimelineMoveSize + ((ImVec2(1, 1) * Keyframe_LocalPos_Ratio[b]) * TimelineZoomSize); } if (UI->BoxSelect) { @@ -1091,11 +1073,11 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor if (Keyframe_ScreenPos[NewIdx].y >= Y_Top && Keyframe_ScreenPos[NewIdx].y <= Y_Bottom && Keyframe_ScreenPos[NewIdx].x >= X_Left && Keyframe_ScreenPos[NewIdx].x <= X_Right) { - if (!Point->IsSelected) { - Point->IsSelected = 1; + if (!PointAddress[Idx]->IsSelected) { + PointAddress[Idx]->IsSelected = 1; } } else if (!io.KeyShift) { - Point->IsSelected = 0; + PointAddress[Idx]->IsSelected = 0; } } @@ -1104,10 +1086,10 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor ImVec2 ButtonSize(16, 16); ImGui::PushID(k); - int Max = (Point->IsSelected) ? 2 : 0; + int Max = PointAddress[Idx]->IsSelected ? 2 : 0; for (int b = Max; b >= 0; b--) { - ImU32 PointCol = ((Point->IsSelected - 1) == b) ? ImColor(0.8f, 0.5f, 0.0f, 1.0f) : ImColor(0.1f, 0.1f, 0.1f, 1.0f); - ImU32 LineCol = ((Point->IsSelected - 1) == b) ? ImColor(0.8f, 0.5f, 0.5f, 1.0f) : ImColor(0.4f, 0.4f, 0.4f, 1.0f); + ImU32 PointCol = ((PointAddress[Idx]->IsSelected - 1) == b) ? ImColor(0.8f, 0.5f, 0.0f, 1.0f) : ImColor(0.1f, 0.1f, 0.1f, 1.0f); + ImU32 LineCol = ((PointAddress[Idx]->IsSelected - 1) == b) ? ImColor(0.8f, 0.5f, 0.5f, 1.0f) : ImColor(0.4f, 0.4f, 0.4f, 1.0f); ImGui::PushID(b); ImGui::SetCursorScreenPos(Keyframe_ScreenPos[NewIdx + b] - (ButtonSize * 0.5)); ImGui::InvisibleButton("##keyframemover", ButtonSize, ImGuiMouseButton_Left); @@ -1122,10 +1104,10 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor PointCol = ImColor(1.0f, 0.8f, 0.8f, 1.0f); if (IsItemActivated) { - Point->IsSelected = b+1; + PointAddress[Idx]->IsSelected = b+1; } - if (b != 0 && Point->IsSelected) + if (b != 0 && PointAddress[Idx]->IsSelected) draw_list->AddLine(Keyframe_ScreenPos[NewIdx], Keyframe_ScreenPos[NewIdx + b], LineCol, 2.0f); if (b == 0) @@ -1139,7 +1121,7 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor UI->Test.SetCurrentChannel(draw_list, 0); - if (k != 0) { + if (p != 0) { if (PointAddress[0]->Type == interpolation_type_bezier && PointAddress[1]->Type == interpolation_type_bezier) { draw_list->AddBezierCubic(Keyframe_ScreenPos[OldIdx], Keyframe_ScreenPos[OldIdx + 2], Keyframe_ScreenPos[NewIdx + 1], Keyframe_ScreenPos[NewIdx], col, 1.0f, 0); @@ -1147,7 +1129,6 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor draw_list->AddLine(Keyframe_ScreenPos[0], Keyframe_ScreenPos[3], col, 1.0f); } } - k++; } } ImGui::PopID(); @@ -1500,7 +1481,7 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem } static void -ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray) +ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, uint16 *SortedPropertyArray) { if (UI->TimelineMode == timeline_mode_graph) ImGui_GraphInfo(File, State, Memory, UI, io); @@ -1602,10 +1583,9 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, draw_list->AddRectFilled(WindowMinAbs, WindowMaxAbs, IM_COL32(50, 50, 50, 150)); - graph_info GraphInfo = Graph_GetInfo(File, Memory); - ImGui_Timeline_DrawGraph(File, State, Memory, UI, io, draw_list, GraphInfo, + ImGui_Timeline_DrawGraph(File, State, Memory, UI, io, draw_list, Increment, TimelineAbsolutePos, GraphMoveSize, GraphZoomSize, - TimelineSize, TimelineSizeWithBorder, LayerIncrement); + TimelineSize, TimelineSizeWithBorder, LayerIncrement, SortedPropertyArray); } ImVec2 MouseDelta = io.MouseDelta / TimelineSize; @@ -1777,17 +1757,15 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, if (!Layer->IsSelected) continue; for (int h = 0; h < AmountOf(Layer->Property); h++) { + uint16 *ArrayLocation = SortedPropertyArray + (i * 7 * MAX_KEYFRAMES_PER_BLOCK) + (h * MAX_KEYFRAMES_PER_BLOCK); property_channel *Property = &Layer->Property[h]; - if (Property->Block_Bezier_Count) { - int k = 0; - for (;;) { - bezier_point *Point = Bezier_Lookup(Memory, Property, k); - if (!Point->Occupied) - break; - if (Point->IsSelected) { - Keyframe_Interact_Evaluate(Memory, State, Point->IsSelected, Point->Pos, Point->Pos); - } - k++; + for (int p = 0; p < Property->Keyframe_Count; p++) { + int k = ArrayLocation[p]; + bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, k); + if (PointAddress->IsSelected) { + v2 NewPos[3]; + Bezier_EvaluateValue(State, PointAddress, NewPos); + PointAddress->Pos[0].x = NewPos[0].x; } } } -- cgit v1.2.3