From 38bf0102300c97335d8e78b4683cb9b9476dcde0 Mon Sep 17 00:00:00 2001 From: Fox Caminiti Date: Thu, 10 Nov 2022 22:34:17 -0500 Subject: graph implementation --- createcalls.cpp | 150 ++++++++++++----- defines.h | 2 +- functions.h | 8 +- main.cpp | 141 ++++++++++------ main.h | 6 +- memory.cpp | 41 ++++- my_imgui_widgets.cpp | 463 +++++++++++++++++++++++++++++++++++---------------- prenderer.cpp | 149 ++++++++++++++--- 8 files changed, 691 insertions(+), 269 deletions(-) diff --git a/createcalls.cpp b/createcalls.cpp index c018eaa..176fc2f 100644 --- a/createcalls.cpp +++ b/createcalls.cpp @@ -74,6 +74,32 @@ Bezier_Lookup(memory *Memory, property_channel *Property, uint16 Index) return &Bezier->Point[Index]; } +static void +Bezier_Add(memory *Memory, property_channel *Property, bezier_point PointData) +{ + if (!Property->Block_Bezier_Count) { + Property->Block_Bezier_Index[0] = Memory_Block_AllocateNew(Memory, F_Bezier); + block_bezier *Bezier = (block_bezier *)Memory_Block_AddressAtIndex(Memory, F_Bezier, Property->Block_Bezier_Index[0]); + Bezier->Occupied = true; + // NOTE(fox): Effects will change this! + History_Action_Swap(Memory, F_Layers, sizeof(Property->Block_Bezier_Count), &Property->Block_Bezier_Count); + Property->Block_Bezier_Count++; + } + int k = 0; + for (;;) { + bezier_point *Point = Bezier_Lookup(Memory, Property, k); + if (!Point->Occupied) { + History_Action_Swap(Memory, F_Bezier, sizeof(*Point), Point); + *Point = PointData; + History_Action_Swap(Memory, F_Layers, sizeof(Property->Keyframe_Count), &Property->Keyframe_Count); + Property->Keyframe_Count++; + return; + } + k++; + } +} + + static property_channel Property_InitFloat(char *Name, real32 Val, real32 ScrubVal, real32 MinVal = PROPERTY_REAL_MIN, real32 MaxVal = PROPERTY_REAL_MAX) { property_channel Property = {}; Property.Name = Name; @@ -84,18 +110,20 @@ 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 k = 0; - for (;;) { - bezier_point *Point = Bezier_Lookup(Memory, Property, k); - if (!Point->Occupied) - break; + 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; - k++; } return PropertyInfo; } @@ -124,10 +152,11 @@ Graph_GetInfo(project_data *File, memory *Memory) static void Keyframe_Interact_Evaluate(memory *Memory, project_state *State, uint8 IsSelected, v2 Pos_Initial[3], v2 Pos_New[3]) { + /* Assert(Pos_New[0].y == Pos_Initial[0].y); - v2 Offset = V2(State->Interact_Offset[0], State->Interact_Offset[1]); if (State->Interact_Active == interact_type_keyframe_move) { - Pos_New[0] = Pos_New[0] + Offset; + Pos_New[0].x = Pos_New[0].x + Offset.x; + Pos_New[0].y = Pos_New[0].y + Offset.y; } else if (State->Interact_Active == interact_type_keyframe_scale) { Pos_New[1].x += (IsSelected - 1 == 0 || IsSelected - 1 == 1) ? Offset.x : 0; Pos_New[2].x -= (IsSelected - 1 == 0 || IsSelected - 1 == 2) ? Offset.x : 0; @@ -138,37 +167,45 @@ Keyframe_Interact_Evaluate(memory *Memory, project_state *State, uint8 IsSelecte Pos_New[2].x += XAxis.x + XAxis.y; Pos_New[2].y += YAxis.x + YAxis.y; } + */ +} + +static block_composition * +Precomp_Init(project_data *File, memory *Memory) +{ + if (File->Comp_Count + 1 > MAX_COMPS) { + Assert(0); + } + block_composition *Comp = (block_composition *)Memory_Block_AllocateAddress(Memory, F_Precomps); + History_Action_Block_Swap(Memory, F_Precomps, Comp); + + *Comp = {}; + Comp->Occupied = 1; + + Comp->Name_String_Index = Memory_Block_AllocateNew(Memory, F_Strings); + block_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, Comp->Name_String_Index); + sprintf(String->Char, "Comp %i", File->Comp_Count); + String->Occupied = 1; + + History_Action_Swap(Memory, F_File, sizeof(File->Comp_Count), &File->Comp_Count); + File->Comp_Count++; + return Comp; +} + +static layer_transforms +Layer_GetTransforms(block_layer *Layer) { + return { Layer->x.CurrentValue, Layer->y.CurrentValue, Layer->ax.CurrentValue, Layer->ay.CurrentValue, Layer->rotation.CurrentValue, Layer->scale.CurrentValue }; } -/* static void Layer_Interact_Evaluate(memory *Memory, project_state *State, uint16 Layer_Index_Physical, sorted_comp_info SortedCompInfo, sorted_layer *SortedLayerInfo, - int32 *Frame_Start, int32 *Frame_End, real32 *Vertical_Offset) + int32 *Frame_Start, int32 *Frame_End) { if (State->Interact_Active == interact_type_layer_move) { *Frame_Start += (int32)(State->Interact_Offset[0] + 0); *Frame_End += (int32)(State->Interact_Offset[0] + 0); - - real32 DesiredOffset = *Vertical_Offset + (int32)State->Interact_Offset[1]; - bool32 Direction = ((int32)State->Interact_Offset[1] > 0) ? 1 : -1; - int i = (Direction > 0) ? SortedCompInfo.LayerCount - 1 : 0; - bool32 Case = 1; - while (Case) { - sorted_layer SortEntry = SortedLayerInfo[i]; - uint32 Index_Physical = SortEntry.Block_Layer_Index; - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical); - bool32 Test = (Direction > 0) ? - ((Layer->Vertical_Offset <= DesiredOffset) && (Layer->Vertical_Offset > *Vertical_Offset)) : - ((Layer->Vertical_Offset >= DesiredOffset) && (Layer->Vertical_Offset < *Vertical_Offset)); - if (!Layer->IsSelected && Test) { - DesiredOffset += Direction; - } - i -= Direction; - Case = (Direction > 0) ? (i >= 0) : (i < SortedCompInfo.LayerCount); - } - *Vertical_Offset = DesiredOffset; } - else if (State->Interact_Active == interact_type_layer_timeadjust) { + if (State->Interact_Active == interact_type_layer_timeadjust) { int Side[2] = {0}; Assert(State->Interact_Offset[1] == 0 || State->Interact_Offset[1] == 1); Side[(int)State->Interact_Offset[1]] = 1; @@ -178,17 +215,8 @@ Layer_Interact_Evaluate(memory *Memory, project_state *State, uint16 Layer_Index *Frame_End += (int32)(State->Interact_Offset[0] * Side[1]); if (*Frame_End <= *Frame_Start) *Frame_End = *Frame_Start + 1; - } else if (State->Interact_Active == interact_type_viewport_transform) { - int i = SortedCompInfo.LayerCount - 1; - while (i >= 0) { - sorted_layer SortEntry = SortedLayerInfo[i]; - uint32 Index_Physical = SortEntry.Block_Layer_Index; - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical); - i--; - } } } -*/ static void Layer_Select(memory *Memory, project_state *State, int32 i) @@ -292,6 +320,38 @@ void Layer_Sort_CheckPrev(memory *Memory, int i, int Direction, sorted_layer *So } } +// TODO(fox): This _could_ be generalized with the layer sorting code... + +/* +Bezier_SortAll() +{ + 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); + 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) { + 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); + } + sorted_layer *LayerEntry = SortedLayerInfo + SortedIndex_Playhead; + LayerEntry->Block_Layer_Index = i; + LayerEntry->SortedOffset = Layer->Vertical_Offset; + CurrentSortIndex++; + } +} +*/ void Layer_SortAll(project_data *File, project_state *State, memory *Memory, sorted_layer *LayerArrayStart, sorted_comp_info *CompStart, uint32 LayerCount, uint32 CompCount) { @@ -300,15 +360,15 @@ void Layer_SortAll(project_data *File, project_state *State, memory *Memory, sor block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); Assert(Layer->Block_Composition_Index < CompCount); CompStart[Layer->Block_Composition_Index].LayerCount++; - } h = 0, c = 0, i = 0; + uint32 CurrentSortIndex = 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); sorted_comp_info *SortedCompInfo = &CompStart[Layer->Block_Composition_Index]; sorted_layer *SortedLayerInfo = Layer_GetSortedArray(LayerArrayStart, CompStart, Layer->Block_Composition_Index); uint32 SortedIndex_Playhead = 0; - while (SortedIndex_Playhead < SortedCompInfo->CurrentSortIndex) { + 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) { @@ -317,16 +377,16 @@ void Layer_SortAll(project_data *File, project_state *State, memory *Memory, sor SortedIndex_Playhead++; } } - if (SortedIndex_Playhead != SortedCompInfo->CurrentSortIndex) { + if (SortedIndex_Playhead != CurrentSortIndex) { uint8 *Address_Start = (uint8 *)(SortedLayerInfo + SortedIndex_Playhead); - uint8 *Address_End = (uint8 *)(SortedLayerInfo + SortedCompInfo->CurrentSortIndex) - 1; - Assert(SortedCompInfo->CurrentSortIndex != SortedCompInfo->LayerCount); + uint8 *Address_End = (uint8 *)(SortedLayerInfo + CurrentSortIndex) - 1; + Assert(CurrentSortIndex != SortedCompInfo->LayerCount); Arbitrary_ShiftData(Address_Start, Address_End, sizeof(sorted_layer), 1); } sorted_layer *LayerEntry = SortedLayerInfo + SortedIndex_Playhead; LayerEntry->Block_Layer_Index = i; LayerEntry->SortedOffset = Layer->Vertical_Offset; - SortedCompInfo->CurrentSortIndex++; + CurrentSortIndex++; } if (State->Interact_Active == interact_type_layer_move) { int32 Offset = (int32)State->Interact_Offset[1]; diff --git a/defines.h b/defines.h index f2d58f2..fd63c30 100644 --- a/defines.h +++ b/defines.h @@ -31,11 +31,11 @@ typedef uint64 ptrsize; // is there a compiler variable for 32 vs 64 bit like #define MAX_LAYERS 2048 #define MAX_EFFECTS 32 #define MAX_SOURCES 1024 +#define MAX_COMPS 1024 #define MAX_MASKS 8 #define MAX_PROPERTIES_PER_EFFECT 16 #define MAX_KEYFRAME_BLOCKS 64 #define MAX_KEYFRAMES_PER_BLOCK 32 // max keyframes on a single channel is 2048 -#define MAX_BITMAP_CHUNKS 64 // Up to 2048x2048-size textures #define MAX_SELECTED_PROPERTIES 16 diff --git a/functions.h b/functions.h index d4a4cfa..eff7435 100644 --- a/functions.h +++ b/functions.h @@ -7,10 +7,14 @@ static void Arbitrary_ShiftData(uint8 *Address_Start, uint8 *Address_End, uint64 static v2 T_CompUVToLayerUV(layer_transforms T, uint32 FileWidth, uint32 FileHeight, uint32 SourceWidth, uint32 SourceHeight, v2 CompUV); -static void Interact_Transform_Begin(project_data *File, memory *Memory, project_state *State, ImVec2 OGPos); +static void Interact_Transform_Begin(project_data *File, memory *Memory, project_state *State, ImVec2 OGPos, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray); static v2 Transform_ScreenSpaceToLocal(layer_transforms T, uint32 FileWidth, uint32 FileHeight, uint32 SourceWidth, uint32 SourceHeight, ui UI, ImVec2 ViewportMin, ImVec2 Point); -static ImVec2 Layer_LocalToScreenSpace(project_state *State, block_layer *Layer, ui *UI, real32 SourceWidth, real32 SourceHeight, real32 CompWidth, real32 CompHeight, v2 Point); +static ImVec2 Layer_LocalToScreenSpace(project_state *State, memory *Memory, block_layer *Layer, ui *UI, uint32 PrincipalCompIndex, v2 Point); + +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 void Transform_ApplyInteractive(interact_transform Interact, real32 *OutputX, real32 *OutputY, real32 *OutputRotation, real32 *OutputScale); diff --git a/main.cpp b/main.cpp index 0a5e9ed..50f9cc5 100644 --- a/main.cpp +++ b/main.cpp @@ -125,6 +125,8 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI, UI->Warp_WantSetPos = false; } + // NOTE(fox): The only requirement for something that needs to happen before the sort is anything that creates/deletes layers. + // The requirement for something after the sort is things that depend on the sort. (obvious) if (!io.WantCaptureKeyboard) ImGui_ProcessInputs(File, State, UI, Memory, io); @@ -135,6 +137,11 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI, 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); + + if (ImGui::IsKeyPressed(ImGuiKey_T)) { + Interact_Transform_Begin(File, Memory, State, io.MousePos, SortedCompArray, SortedLayerArray); + } + ImGui::DockSpaceOverViewport(); if (Debug.ToggleWindow) { @@ -143,8 +150,45 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI, ImGui_DebugUndoTree(Memory, State); } - // if (State->Initializing == 3) - // Source_UICreateButton(File, State, Memory, SortedCompArray, SortedLayerArray); + if (State->Initializing == 3) { + Source_UICreateButton(File, State, Memory, SortedCompArray, SortedLayerArray); + 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_Add(Memory, Property, Point); + } + { + bezier_point Point = { 1, {20, 800, -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; + { + bezier_point Point = { 1, {0, 400, -5, 0, 5, 0}, interpolation_type_bezier, 0, {0, 0, 0}, 0 }; + Bezier_Add(Memory, Property, Point); + } + { + bezier_point Point = { 1, {20, -500, -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_Add(Memory, Property, Point); + } + { + bezier_point Point = { 1, {20, 1, -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); @@ -162,11 +206,6 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI, ImGui::EndFrame(); } -static layer_transforms -Layer_GetTransforms(block_layer *Layer) { - return { Layer->x.CurrentValue, Layer->y.CurrentValue, Layer->ax.CurrentValue, Layer->ay.CurrentValue, Layer->rotation.CurrentValue, Layer->scale.CurrentValue }; -} - static void * Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, uint32 CompIndex) { @@ -189,7 +228,7 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io uint32 Index_Physical = SortEntry.Block_Layer_Index; block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical); if (Layer->Frame_Start <= State->Frame_Current && - Layer->Frame_End >= State->Frame_Current && Layer->IsVisible) + Layer->Frame_End > State->Frame_Current && Layer->IsVisible) { layer_bitmap_state *BitmapState = &State->Render.Bitmap[Index_Physical]; void *BitmapAddress = NULL; @@ -225,13 +264,11 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io } else { block_composition *Precomp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, Layer->Block_Source_Index); 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); - Layer->x.CurrentValue = (Layer->Block_Source_Index == 0) ? 200 : Comp->Width/2; - Layer->y.CurrentValue = Comp->Height/2; - Entry->CycleTime = GetTime() - Src_TimeStart; - } + // if (!Entry->IsCached) { + uint64 Src_TimeStart = GetTime(); + Render_Comp(File, State, Memory, io, SortedCompArray, SortedLayerArray, Layer->Block_Source_Index); + Entry->CycleTime = GetTime() - Src_TimeStart; + // } BitmapAddress = Memory_Block_Bitmap_AddressAtIndex(Memory, Entry->Block_StartIndex); } Assert(BitmapAddress); @@ -241,37 +278,38 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io // for (int a = 0; a < Layer->Block_Effect_Count; a++) { // } - property_channel *Property = &Layer->x; - - 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; - } else { - int KeyframeIndex = 0; + for (int h = 0; h < AmountOf(Layer->Property); h++) { + property_channel *Property = &Layer->Property[h]; + if (Property->Block_Bezier_Count) { + bezier_point *FirstPoint = Bezier_Lookup(Memory, Property, 0); + int k = 0; for (;;) { - bezier_point *Point = Bezier_Lookup(Memory, Property, KeyframeIndex + 1); - if (Point->Pos[0].x >= State->Frame_Current) + bezier_point *Point = Bezier_Lookup(Memory, Property, k); + if (!Point->Occupied) break; - KeyframeIndex++; + 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; + } else { + int KeyframeIndex = 0; + for (;;) { + bezier_point *Point = Bezier_Lookup(Memory, Property, KeyframeIndex + 1); + if (Point->Pos[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); } - 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); } } @@ -361,11 +399,12 @@ int main(int argc, char *argv[]) { Memory_InitTable(&GlobalMemory, &Memory, 40 * 1024 * 1024, P_MiscCache, "Misc persistent"); Memory_InitTable(&GlobalMemory, &Memory, sizeof(project_data), F_File, "File", sizeof(project_data)); - Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Precomps, "Precomps", sizeof(block_composition)); - Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Layers, "Layers", sizeof(block_layer)); - Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Sources, "Sources", sizeof(block_source)); - Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Bezier, "Bezier paths (keyframes, masks)", sizeof(block_bezier)); - Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Strings, "Strings", sizeof(block_string)); + Memory_InitTable(&GlobalMemory, &Memory, 1 * 1024 * 1024, F_Precomps, "Precomps", sizeof(block_composition)); + Memory_InitTable(&GlobalMemory, &Memory, 2 * 1024 * 1024, F_Layers, "Layers", sizeof(block_layer)); + Memory_InitTable(&GlobalMemory, &Memory, 1 * 1024 * 1024, F_Sources, "Sources", sizeof(block_source)); + Memory_InitTable(&GlobalMemory, &Memory, 2 * 1024 * 1024, F_Properties, "Properties", sizeof(property_channel)); + Memory_InitTable(&GlobalMemory, &Memory, 4 * 1024 * 1024, F_Bezier, "Bezier paths (keyframes, masks)", sizeof(block_bezier)); + Memory_InitTable(&GlobalMemory, &Memory, 4 * 1024 * 1024, F_Strings, "Strings", sizeof(block_string)); Memory_InitTable(&GlobalMemory, &Memory, (uint64)50 * 1024 * 1024, F_PrincipalBitmaps, "Principal bitmap data", BitmapBlockSize); Memory_InitTable(&GlobalMemory, &Memory, (uint64)64 * 1024 * 1024, B_ScratchSpace, "Scratch"); @@ -428,8 +467,6 @@ int main(int argc, char *argv[]) { Comp2->Name_String_Index = String_AddToFile(&Memory, "Another comp"); */ - File->Comp_Count = 1; - { uint16 SourceIndex = Source_Generate(File, State, &Memory, (void *)"../asset/a.jpg"); block_source *Source = (block_source *)Memory_Block_AddressAtIndex(&Memory, F_Sources, 0); @@ -528,7 +565,7 @@ int main(int argc, char *argv[]) { { uint16 SourceIndex = Source_Generate(File, State, &Memory, (void *)"../asset/b.jpg"); block_source *Source = (block_source *)Memory_Block_AddressAtIndex(&Memory, F_Sources, 1); - Source->IsSelected = true; + // Source->IsSelected = true; /* { Layer_CreateFromSource(File, State, &Memory, SourceIndex, MainComp->Frame_End); @@ -585,7 +622,7 @@ int main(int argc, char *argv[]) { { uint16 SourceIndex = Source_Generate(File, State, &Memory, (void *)"../asset/c.jpg"); block_source *Source = (block_source *)Memory_Block_AddressAtIndex(&Memory, F_Sources, 2); - Source->IsSelected = true; + // Source->IsSelected = true; /* { Layer_CreateFromSource(File, State, &Memory, SourceIndex, MainComp->Frame_End); diff --git a/main.h b/main.h index 1b386ce..096107a 100644 --- a/main.h +++ b/main.h @@ -119,7 +119,6 @@ enum focused_window struct sorted_comp_info { uint32 LayerCount; - uint32 CurrentSortIndex; }; struct sorted_layer @@ -145,6 +144,9 @@ struct ui ImVec2 TimelinePercentZoomed; ImVec2 TimelinePercentOffset; + ImVec2 GraphZoomSize; + ImVec2 GraphMoveSize; + uint32 InteractTransformMode; // Whether a drag on the Shift+T UI is scale (1), rotation (2), or position (3). timeline_mode TimelineMode; @@ -374,9 +376,11 @@ struct property_info }; struct property_channel { + uint8 Occupied; char *Name; uint16 Block_Bezier_Index[MAX_KEYFRAME_BLOCKS]; uint16 Block_Bezier_Count; + uint16 Keyframe_Count; real32 CurrentValue; real32 MaxVal; diff --git a/memory.cpp b/memory.cpp index 6e70055..3b3c64f 100644 --- a/memory.cpp +++ b/memory.cpp @@ -34,6 +34,13 @@ Memory_Block_AddressAtIndex(memory *Memory, memory_table_list TableName, uint32 return (void *)Address; } +static uint16 +Memory_Block_IndexAtAddress(memory *Memory, memory_table_list TableName, void *Address) +{ + memory_table *Table = &Memory->Slot[TableName]; + return ((uint8 *)Address - (uint8 *)Table->Address) / Table->Block_ElementSize; +} + static void * Memory_Block_AllocateAddress(memory *Memory, memory_table_list TableName) { @@ -43,7 +50,37 @@ 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) +Block_Loop(memory *Memory, memory_table_list TableName, uint32 TotalCount, int *HasIncremented, int *CurrentCount, int *Index, void *Extra = NULL) +{ + for (;;) { + if (*CurrentCount == TotalCount) { + return 0; + } + if (*HasIncremented) { + *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); + } + if (*Occupied) { + *HasIncremented = 1; + (*CurrentCount)++; + return 1; + } + (*Index)++; + Assert(*CurrentCount <= TotalCount); + Assert(*Index <= TotalCount*100); // This can get triggered normally if 100+ items are added and the first 99 in memory are deleted. + } + Assert(0); + return 0; +} + +static bool32 +Block_Loop(memory *Memory, property_channel *Property, uint32 TotalCount, int *HasIncremented, int *CurrentCount, int *Index) { for (;;) { if (*CurrentCount == TotalCount) { @@ -53,7 +90,7 @@ Block_Loop(memory *Memory, memory_table_list TableName, uint32 TotalCount, int * *HasIncremented = 0; (*Index)++; } - uint8 *Occupied = (uint8 *)Memory_Block_AddressAtIndex(Memory, TableName, *Index); + uint8 *Occupied = (uint8 *)Bezier_Lookup(Memory, Property, *Index); if (*Occupied) { *HasIncremented = 1; (*CurrentCount)++; diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp index e1e9ffc..722ce1e 100644 --- a/my_imgui_widgets.cpp +++ b/my_imgui_widgets.cpp @@ -138,9 +138,7 @@ ImGui_File(project_data *File, project_state *State, memory *Memory, ImGuiIO io, ImGui::Begin("Files"); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); - if (!ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) - Source_DeselectAll(File, Memory); - else if (ImGui::IsKeyPressed(ImGuiKey_Backspace)) { + if (ImGui::IsKeyPressed(ImGuiKey_Backspace)) { /* uint64 SortSize = (sizeof(uint16) * File->Comp_Count); @@ -214,6 +212,9 @@ ImGui_File(project_data *File, project_state *State, memory *Memory, ImGuiIO io, ImGui::EndPopup(); } + // if (!ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) + // Source_DeselectAll(File, Memory); + #if DEBUG for (int i = 0; i < Debug.Temp.WatchedProperties; i++) { @@ -603,6 +604,7 @@ ImGui_TransformUI(project_data *File, project_state *State, memory *Memory, ui * } if (ImGui::IsKeyPressed(ImGuiKey_Escape)) { + State->Interact_Active = interact_type_none; State->UpdateFrame = true; } @@ -631,6 +633,106 @@ ImGui_TransformUI(project_data *File, project_state *State, memory *Memory, ui * } +static void +ImGui_LayerViewportUI(project_state *State, memory *Memory, ui *UI, ImDrawList *draw_list, block_composition *MainComp, uint32 CompIndex, block_layer *ParentLayer[4], uint32 Recursions, + sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray) +{ + sorted_comp_info *SortedCompInfo = &SortedCompArray[CompIndex]; + sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, SortedCompArray, CompIndex); + ImU32 wcol = ImGui::GetColorU32(ImGuiCol_Text); + for (int i = 0; i < SortedCompInfo->LayerCount; i++) + { + sorted_layer SortEntry = SortedLayerInfo[i]; + uint32 Index_Physical = SortEntry.Block_Layer_Index; + block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical); + if (Layer->IsPrecomp) { + ParentLayer[Recursions] = Layer; + ImGui_LayerViewportUI(State, Memory, UI, draw_list, MainComp, Layer->Block_Source_Index, ParentLayer, Recursions + 1, SortedCompArray, SortedLayerArray); + } + if (Layer->IsSelected) { + uint32 Width = 0, Height = 0; + if (!Layer->IsPrecomp) { + block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index); + Width = Source->Width; + Height = Source->Height; + } else { + block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, Layer->Block_Source_Index); + Width = Comp->Width; + Height = Comp->Height; + } + + v2 Point[5] = { V2(Width*Layer->ax.CurrentValue, Height*Layer->ay.CurrentValue), V2(0, 0), V2(Width, 0), V2(0, Height), V2(Width, Height) }; + + layer_transforms T = Layer_GetTransforms(Layer); + + if (State->Interact_Active == interact_type_viewport_transform && Layer->IsSelected) { + Transform_ApplyInteractive(*(interact_transform *)&State->Interact_Offset[0], &T.x, &T.y, &T.rotation, &T.scale); + } + + v2 NewPos[5]; + for (int i = 0; i < 5; i++) { + NewPos[i] = TransformPoint(T, Width, Height, Point[i]); + } + + int i = 0; + while (i < Recursions) { + T = Layer_GetTransforms(ParentLayer[i]); + block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, ParentLayer[i]->Block_Source_Index); + Width = Comp->Width; + Height = Comp->Height; + for (int i = 0; i < 5; i++) { + NewPos[i] = TransformPoint(T, Width, Height, NewPos[i]); + } + i++; + } + + ImVec2 ScreenPoint[5]; + for (int i = 0; i < 5; i++) { + v2 CompUV = NewPos[i] / V2(MainComp->Width, MainComp->Height); + + ScreenPoint[i] = ImVec2(UI->CompPos.x + CompUV.x * UI->CompZoom.x, + UI->CompPos.y + CompUV.y * UI->CompZoom.y); + + } + draw_list->AddNgon(ScreenPoint[0], 20, wcol, 8, 10.0f); + draw_list->AddLine(ScreenPoint[1], ScreenPoint[2], wcol, 2.0f); + draw_list->AddLine(ScreenPoint[2], ScreenPoint[4], wcol, 2.0f); + draw_list->AddLine(ScreenPoint[1], ScreenPoint[3], wcol, 2.0f); + draw_list->AddLine(ScreenPoint[3], ScreenPoint[4], wcol, 2.0f); + } + /* + if (Layer->IsSelected) { + uint32 Width = 0, Height = 0; + if (!Layer->IsPrecomp) { + block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index); + Width = Source->Width; + Height = Source->Height; + } else { + block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, Layer->Block_Source_Index); + Width = Comp->Width; + Height = Comp->Height; + } + // Anchor point UI + v2 CenterPoint = V2(Width*Layer->ax.CurrentValue, Height*Layer->ay.CurrentValue); + ImVec2 ScreenAP = Layer_LocalToScreenSpace(State, Memory, Layer, UI, File->PrincipalCompIndex, CenterPoint); + draw_list->AddNgon(ScreenAP, 20, wcol, 8, 10.0f); + + // Bounding box UI + ImVec2 P1 = Layer_LocalToScreenSpace(State, Memory, Layer, UI, File->PrincipalCompIndex, V2(0, 0)); + ImVec2 P2 = Layer_LocalToScreenSpace(State, Memory, Layer, UI, File->PrincipalCompIndex, V2(Width, 0)); + ImVec2 P3 = Layer_LocalToScreenSpace(State, Memory, Layer, UI, File->PrincipalCompIndex, V2(0, Height)); + ImVec2 P4 = Layer_LocalToScreenSpace(State, Memory, Layer, UI, File->PrincipalCompIndex, V2(Width, Height)); + draw_list->AddLine(P1, P2, wcol, 2.0f); + draw_list->AddLine(P2, P4, wcol, 2.0f); + draw_list->AddLine(P1, P3, wcol, 2.0f); + draw_list->AddLine(P3, P4, wcol, 2.0f); + + } + */ + + } +} + static void ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io, GLuint textureID, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray) @@ -668,35 +770,11 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, draw_list->AddImage((void *)(intptr_t)textureID, CompPosMin, CompPosMax); draw_list->PopClipRect(); - ImU32 wcol = ImGui::GetColorU32(ImGuiCol_Text); // UI+interaction for layer if (State->MostRecentlySelectedLayer > -1) { - 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); - if (Layer->IsSelected) { - block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index); - - // Anchor point UI - v2 CenterPoint = V2(Source->Width*Layer->ax.CurrentValue, Source->Height*Layer->ay.CurrentValue); - ImVec2 ScreenAP = Layer_LocalToScreenSpace(State, Layer, UI, Source->Width, Source->Height, MainComp->Width, MainComp->Height, CenterPoint); - draw_list->AddNgon(ScreenAP, 20, wcol, 8, 10.0f); - - // Bounding box UI - ImVec2 P1 = Layer_LocalToScreenSpace(State, Layer, UI, Source->Width, Source->Height, MainComp->Width, MainComp->Height, V2(0, 0)); - ImVec2 P2 = Layer_LocalToScreenSpace(State, Layer, UI, Source->Width, Source->Height, MainComp->Width, MainComp->Height, V2(Source->Width, 0)); - ImVec2 P3 = Layer_LocalToScreenSpace(State, Layer, UI, Source->Width, Source->Height, MainComp->Width, MainComp->Height, V2(0, Source->Height)); - ImVec2 P4 = Layer_LocalToScreenSpace(State, Layer, UI, Source->Width, Source->Height, MainComp->Width, MainComp->Height, V2(Source->Width, Source->Height)); - draw_list->AddLine(P1, P2, wcol, 2.0f); - draw_list->AddLine(P2, P4, wcol, 2.0f); - draw_list->AddLine(P1, P3, wcol, 2.0f); - draw_list->AddLine(P3, P4, wcol, 2.0f); - - } - } - + block_layer *ParentLayer[4]; + ImGui_LayerViewportUI(State, Memory, UI, draw_list, MainComp, File->PrincipalCompIndex, ParentLayer, 0, SortedCompArray, SortedLayerArray); if (State->Interact_Active == interact_type_viewport_transform) { ImGui_TransformUI(File, State, Memory, UI, draw_list, io, (interact_transform *)&State->Interact_Offset[0], ViewportMin, MainComp->Width, MainComp->Height); } @@ -916,6 +994,9 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor { UI->Test.Split(draw_list, 2); + TimelineMoveSize.y = TimelineMoveSize.y + (TimelineZoomSize.y * (0.25 / 2)); + TimelineZoomSize.y = TimelineZoomSize.y * 0.75; + int h = 0, c = 0, i = 0; while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i)) { @@ -924,16 +1005,8 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor continue; int32 Frame_Start = Layer->Frame_Start; - int32 Frame_End = Layer->Frame_End; - real32 Vertical_Offset = GraphInfo.LowestOffset; // Layer->Vertical_Offset; - ImVec2 Layer_LocalPos = ImVec2(Frame_Start, Vertical_Offset); - ImVec2 Layer_LocalSize = ImVec2(Frame_End - Frame_Start, Layer->Vertical_Height); - ImVec2 Layer_LocalPos_Ratio = (Layer_LocalPos * Increment); - ImVec2 Layer_LocalSize_Ratio = Layer_LocalSize * Increment; - ImVec2 Layer_ScreenPos_Min = TimelineAbsolutePos + TimelineMoveSize + (Layer_LocalPos_Ratio * TimelineZoomSize); - ImVec2 Layer_ScreenPos_Max = TimelineAbsolutePos + TimelineMoveSize + ((Layer_LocalPos_Ratio + Layer_LocalSize_Ratio) * TimelineZoomSize); - ImVec2 Layer_ScreenSize = Layer_ScreenPos_Max - Layer_ScreenPos_Min; + ImVec2 Layer_ScreenPos_Min = TimelineAbsolutePos + TimelineMoveSize; // (* TimelineZoomSize); ImGui::PushID(i); @@ -941,8 +1014,12 @@ 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 / 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; + State->Interact_Offset[1] = DragDelta.y; + DebugWatchVar("DeltaX: ", &DragDelta.x, d_float); + DebugWatchVar("Deltay: ", &DragDelta.y, d_float); } else if (State->Interact_Active == interact_type_keyframe_scale) { 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; @@ -954,7 +1031,6 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor State->Interact_Active == interact_type_keyframe_rotate || State->Interact_Active == interact_type_keyframe_scale)) { - Assert(0); // Memory_Cache_Invalidate(State, Memory, cache_entry_type_comp, Lay } @@ -980,6 +1056,7 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor 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); @@ -988,14 +1065,21 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor 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_); + */ + 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]) }; 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] = 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); } if (UI->BoxSelect) { @@ -1098,8 +1182,8 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem int32 Frame_Start = Layer->Frame_Start; int32 Frame_End = Layer->Frame_End; real32 Vertical_Offset = SortEntry.SortedOffset; - // if (Layer->IsSelected) - // Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End, &Vertical_Offset); + if (Layer->IsSelected) + Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End); ImVec2 Layer_LocalPos = ImVec2(Frame_Start, Vertical_Offset); ImVec2 Layer_LocalSize = ImVec2(Frame_End - Frame_Start, Layer->Vertical_Height); @@ -1118,6 +1202,11 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem else Test = (Layer_ScreenPos_Max.y <= io.MouseClickedPos[0].y && Layer_ScreenPos_Max.y >= io.MousePos.y); + if (io.MouseClickedPos[0].x < io.MousePos.x) + Test &= (Layer_ScreenPos_Max.x >= io.MouseClickedPos[0].x && Layer_ScreenPos_Min.x <= io.MousePos.x); + else + Test &= (Layer_ScreenPos_Min.x <= io.MouseClickedPos[0].x && Layer_ScreenPos_Max.x >= io.MousePos.x); + if (Test) { if (!Layer->IsSelected) { Layer->IsSelected = true; @@ -1146,6 +1235,7 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem } if (ImGui::IsItemActive()) { if (ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1)) { + Assert(Layer->IsSelected); State->Interact_Active = interact_type_layer_timeadjust; ImVec2 DragDelta = ImGui::GetMouseDragDelta(); DragDelta = DragDelta + (ImVec2(UI->Warp_X, UI->Warp_Y) * TimelineSize); @@ -1157,19 +1247,21 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem } if (ImGui::IsItemDeactivated()) { if (State->Interact_Active == interact_type_layer_timeadjust) { - Assert(0); - /* + History_Entry_Commit(Memory, "Adjust layer timing"); 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); - // if (Layer->IsSelected) { - // Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Layer->Frame_Start, &Layer->Frame_End, &Layer->Vertical_Offset); - // } + if (Layer->IsSelected) { + // NOTE(fox): Some data on the tree could be saved here. + History_Action_Swap(Memory, F_File, sizeof(Layer->Frame_Start), &Layer->Frame_Start); + History_Action_Swap(Memory, F_File, sizeof(Layer->Frame_End), &Layer->Frame_End); + Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Layer->Frame_Start, &Layer->Frame_End); + } } + History_Entry_End(Memory); State->Interact_Active = interact_type_none; State->Interact_Offset[0] = 0; State->Interact_Offset[1] = 0; - */ } } @@ -1186,6 +1278,70 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem } } + ImGui::OpenPopupOnItemClick("layerpopup", ImGuiPopupFlags_MouseButtonRight); + if (ImGui::BeginPopup("layerpopup")) { + if (ImGui::MenuItem("Pre-compose layer")) { + History_Entry_Commit(Memory, "Pre-compose layer"); + block_composition *NewComp = Precomp_Init(File, Memory); + NewComp->Width = Comp->Width; + NewComp->Height = Comp->Height; + NewComp->FPS = Comp->FPS; + NewComp->BytesPerPixel = Comp->BytesPerPixel; + NewComp->Frame_Count = Comp->Frame_Count; + NewComp->Frame_Start = Comp->Frame_Start; + NewComp->Frame_End = Comp->Frame_End; + int32 TopOffset = 0; + for (int i = SortedCompInfo.LayerCount - 1; i >= 0; i--) + { + sorted_layer SortEntry = SortedLayerInfo[i]; + uint32 Index_Physical = SortEntry.Block_Layer_Index; + block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical); + if (Layer->IsSelected) { + TopOffset = Layer->Vertical_Offset; + break; + } + } + for (int i = SortedCompInfo.LayerCount - 1; i >= 0; i--) + { + sorted_layer SortEntry = SortedLayerInfo[i]; + uint32 Index_Physical = SortEntry.Block_Layer_Index; + block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical); + if (Layer->IsSelected) { + History_Action_Swap(Memory, F_File, sizeof(Layer->Block_Composition_Index), &Layer->Block_Composition_Index); + Layer->Block_Composition_Index = 1; + } + } + block_layer *PrecompLayer = Layer_Init(File, Memory); + PrecompLayer->IsPrecomp = true; + PrecompLayer->Block_Source_Index = 1; + PrecompLayer->Block_Composition_Index = 0; + PrecompLayer->Vertical_Offset = TopOffset; + PrecompLayer->Frame_End = NewComp->Frame_End; + PrecompLayer->ColIndex = 3; + PrecompLayer->x.CurrentValue = Comp->Width/2; + PrecompLayer->y.CurrentValue = Comp->Height/2; + History_Entry_End(Memory); + State->UpdateFrame = true; + } + if (ImGui::BeginMenu("Layer color")) + { + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); + for (int c = 0; c < AmountOf(UI->LayerColors); c++) { + ImGui::PushID(c); + ImGui::PushStyleColor(ImGuiCol_Button, UI->LayerColors[c]); + real32 Size = ImGui::GetFontSize() * 2; + ImVec2 ColSize(Size, Size); + ImGui::Button("##test", ColSize); + if ((c+1) % 4) { ImGui::SameLine(); } + ImGui::PopStyleColor(); + ImGui::PopID(); + } + ImGui::PopStyleVar(); + ImGui::EndMenu(); + } + ImGui::EndPopup(); + } + if (ImGui::IsItemActive()) { if (ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1)) { if (State->Interact_Active == interact_type_none) { @@ -1218,8 +1374,12 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem uint32 Index_Physical = SortEntry.Block_Layer_Index; block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical); if (Layer->IsSelected) { + // NOTE(fox): Some data on the tree could be saved here. History_Action_Swap(Memory, F_File, sizeof(Layer->Vertical_Offset), &Layer->Vertical_Offset); + History_Action_Swap(Memory, F_File, sizeof(Layer->Frame_Start), &Layer->Frame_Start); + History_Action_Swap(Memory, F_File, sizeof(Layer->Frame_End), &Layer->Frame_End); Layer->Vertical_Offset = SortEntry.SortedOffset; + Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Layer->Frame_Start, &Layer->Frame_End); } } State->Interact_Active = interact_type_none; @@ -1243,8 +1403,8 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem int32 Frame_Start = Layer->Frame_Start; int32 Frame_End = Layer->Frame_End; real32 Vertical_Offset = SortEntry.SortedOffset; - // if (Layer->IsSelected) - // Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End, &Vertical_Offset); + if (Layer->IsSelected) + Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End); ImVec2 Layer_LocalPos = ImVec2(Frame_Start, Vertical_Offset); ImVec2 Layer_LocalSize = ImVec2(Frame_End - Frame_Start, Layer->Vertical_Height); @@ -1298,8 +1458,8 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem int32 Frame_Start = Layer->Frame_Start; int32 Frame_End = Layer->Frame_End; real32 Vertical_Offset = SortEntry.SortedOffset; - // if (Layer->IsSelected) - // Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End, &Vertical_Offset); + if (Layer->IsSelected) + Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End); ImVec2 Layer_LocalPos = ImVec2(Frame_Start, Vertical_Offset); ImVec2 Layer_LocalSize = ImVec2(Frame_End - Frame_Start, Layer->Vertical_Height); @@ -1311,6 +1471,9 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem ImU32 LayerColor = 0; ImU32 BorderColor = 0; + LayerColor = ImColor(UI->LayerColors[Layer->ColIndex]); + BorderColor = ImColor(0.2, 0.2, 0.2, 1.0f); + /* if (UI->TimelineMode == timeline_mode_graph) { LayerColor = ImColor(UI->LayerColors[Layer->ColIndex]); BorderColor = ImColor(0.3, 0.3, 0.3, 1.0f); @@ -1318,11 +1481,14 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem LayerColor = ImColor(UI->LayerColors[Layer->ColIndex]); BorderColor = ImColor(0.2, 0.2, 0.2, 1.0f); } + */ draw_list->AddRectFilled(Layer_ScreenPos_Min, Layer_ScreenPos_Max, LayerColor); draw_list->AddRect(Layer_ScreenPos_Min, Layer_ScreenPos_Max, BorderColor, 2); // block_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, Layer->Block_String_Index); - // draw_list->AddText(Layer_ScreenPos_Min, 0xFFFFFFFF, String->Char); + char buf[21]; + sprintf(buf, "%.2f, %.2f", Layer->Vertical_Offset, SortEntry.SortedOffset); + draw_list->AddText(Layer_ScreenPos_Min, 0xFFFFFFFF, buf); if (Layer->IsSelected) { draw_list->AddRectFilled(Layer_ScreenPos_Min, Layer_ScreenPos_Max, ImColor(0.25f, 0.25f, 0.25f, 0.5f), 2); @@ -1392,32 +1558,54 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImVec2 Val_Min(0, 0); ImVec2 Val_Max(40, LayerIncrement); - if (UI->TimelinePercentZoomed.x == 0) { - UI->TimelinePercentZoomed = ImVec2(1, 1); + // ImVec2 *ActivePercentZoomed = (UI->TimelineMode != timeline_mode_graph) ? &UI->TimelinePercentZoomed : &UI->GraphPercentZoomed; + // ImVec2 *ActivePercentOffset = (UI->TimelineMode != timeline_mode_graph) ? &UI->TimelinePercentOffset : &UI->GraphPercentOffset; + ImVec2 *ActivePercentZoomed = &UI->TimelinePercentZoomed; + ImVec2 *ActivePercentOffset = &UI->TimelinePercentOffset; + + if (ActivePercentZoomed->x == 0) { + *ActivePercentZoomed = ImVec2(1, 1); } + ImVec2 ActiveZoomSize = TimelineSizeWithBorder / *ActivePercentZoomed; + ImVec2 ActiveMoveSize = TimelineSizeWithBorder * *ActivePercentOffset / *ActivePercentZoomed; + ImVec2 TimelineZoomSize = TimelineSizeWithBorder / UI->TimelinePercentZoomed; ImVec2 TimelineMoveSize = TimelineSizeWithBorder * UI->TimelinePercentOffset / UI->TimelinePercentZoomed; + DebugWatchVar("TimelineY: ", &TimelineMoveSize.y, d_float); + ImGui_TimelineHorizontalIncrementDraw(State, UI, draw_list, TimelineSizeWithBorder, TimelineAbsolutePos, *MainComp, TimelineZoomSize, TimelineMoveSize); ImVec2 Increment = ImVec2((real32)1 / MainComp->Frame_Count, (real32)1 / LayerIncrement); - ImGui_Timeline_DrawPrecomp(File, State, Memory, UI, io, draw_list, File->PrincipalCompIndex, Increment, TimelineAbsolutePos, TimelineMoveSize, TimelineZoomSize, TimelineSize, TimelineSizeWithBorder, LayerIncrement, SortedCompArray, SortedLayerArray); if (UI->TimelineMode == timeline_mode_graph) { - // uint64 Keyframe_SortSize = (sizeof(sorted_comp_info) * File->Comp_Count) + (sizeof(sorted_layer) * File->Layer_Count); - // void *SortedArray = Memory_PushScratch(Memory, Keyframe_SortSize); - // Arbitrary_Zero((uint8 *)SortedArray, SortSize); + + if (UI->GraphMoveSize.y == 0) { + UI->GraphZoomSize = ImVec2(1, UI->TimelinePercentZoomed.y ); + UI->GraphMoveSize = ImVec2(0, -UI->TimelinePercentOffset.y ); + } + + ImVec2 ZoomDifference = (UI->TimelinePercentZoomed / UI->GraphZoomSize); + ImVec2 MoveDifference = (UI->TimelinePercentOffset + (UI->GraphMoveSize)); + DebugWatchVar("zoomdif: ", &ZoomDifference.y, d_float); + DebugWatchVar("movedif: ", &MoveDifference.y, d_float); + ImVec2 GraphZoomSize = TimelineSizeWithBorder / ZoomDifference; + ImVec2 GraphMoveSize = TimelineSizeWithBorder * (MoveDifference) / UI->TimelinePercentZoomed; + DebugWatchVar("zoomsize: ", &GraphZoomSize.y, d_float); + DebugWatchVar("movesize: ", &GraphMoveSize.y, d_float); + + 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, - Increment, TimelineAbsolutePos, TimelineMoveSize, TimelineZoomSize, + Increment, TimelineAbsolutePos, GraphMoveSize, GraphZoomSize, TimelineSize, TimelineSizeWithBorder, LayerIncrement); - // Memory_PopScratch(Memory, Keyframe_SortSize); } ImVec2 MouseDelta = io.MouseDelta / TimelineSize; @@ -1426,8 +1614,8 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, real32 BarThickness = 50; real32 BarMinZoom = 0.01; - real32 BarH_Pos = -TimelineSizeWithBorder.x * UI->TimelinePercentOffset.x; - real32 BarH_Size = TimelineSizeWithBorder.x / (1 / UI->TimelinePercentZoomed.x); + real32 BarH_Pos = -TimelineSizeWithBorder.x * ActivePercentOffset->x; + real32 BarH_Size = TimelineSizeWithBorder.x / (1 / ActivePercentZoomed->x); // I use "UI" to denote the size/position after clipping the bar so that it // doesn't go out of bounds and the handles are always selectable at the edges. @@ -1454,9 +1642,9 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, if ((ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1))) { - if ((UI->TimelinePercentZoomed.x - MouseDelta.x) > BarMinZoom) { - UI->TimelinePercentZoomed.x -= MouseDelta.x; - UI->TimelinePercentOffset.x -= MouseDelta.x; + if ((ActivePercentZoomed->x - MouseDelta.x) > BarMinZoom) { + ActivePercentZoomed->x -= MouseDelta.x; + ActivePercentOffset->x -= MouseDelta.x; } BarHeld = true; } @@ -1466,7 +1654,7 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1)) { - UI->TimelinePercentOffset.x -= MouseDelta.x; + ActivePercentOffset->x -= MouseDelta.x; BarHeld = true; } @@ -1475,8 +1663,8 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, if ((ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1))) { - if ((UI->TimelinePercentZoomed.x + MouseDelta.x) > BarMinZoom) { - UI->TimelinePercentZoomed.x += MouseDelta.x; + if ((ActivePercentZoomed->x + MouseDelta.x) > BarMinZoom) { + ActivePercentZoomed->x += MouseDelta.x; } BarHeld = true; } @@ -1485,11 +1673,11 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImGui_WarpMouse(UI, io.MousePos, TimelineAbsolutePos, TimelineAbsolutePos + TimelineSizeWithBorder, 1); } - Assert(UI->TimelinePercentZoomed.x > BarMinZoom); + Assert(ActivePercentZoomed->x > BarMinZoom); real32 BarV_MaxSize = TimelineSizeWithBorder.y - BarThickness/2; - real32 BarV_Pos = -BarV_MaxSize * UI->TimelinePercentOffset.y; - real32 BarV_Size = BarV_MaxSize / (1 / UI->TimelinePercentZoomed.y); + real32 BarV_Pos = -BarV_MaxSize * ActivePercentOffset->y; + real32 BarV_Size = BarV_MaxSize / (1 / ActivePercentZoomed->y); BarV_Size = Max(BarV_Size, FontHeight*4); real32 BarV_Offset = Max(BarV_Pos, 0); @@ -1514,8 +1702,8 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, if ((ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1))) { - UI->TimelinePercentZoomed.y -= MouseDelta.y; - UI->TimelinePercentOffset.y -= MouseDelta.y; + ActivePercentZoomed->y -= MouseDelta.y; + ActivePercentOffset->y -= MouseDelta.y; BarHeld = true; } @@ -1524,12 +1712,12 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, if (ImGui::IsItemHovered() && io.MouseWheel) { - UI->TimelinePercentOffset.y -= io.MouseWheel/10; + ActivePercentOffset->y -= io.MouseWheel/10; } if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1)) { - UI->TimelinePercentOffset.y -= MouseDelta.y; + ActivePercentOffset->y -= MouseDelta.y; BarHeld = true; } @@ -1538,11 +1726,11 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, if ((ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1))) { - UI->TimelinePercentZoomed.y += MouseDelta.y; + ActivePercentZoomed->y += MouseDelta.y; BarHeld = true; } - UI->TimelinePercentZoomed.y = Max(UI->TimelinePercentZoomed.y, 0.01); + ActivePercentZoomed->y = Max(ActivePercentZoomed->y, 0.01); if (BarHeld) { ImGui_WarpMouse(UI, io.MousePos, TimelineAbsolutePos, TimelineAbsolutePos + TimelineSizeWithBorder, 2); @@ -1558,91 +1746,74 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, bool32 LeftClick = ImGui::IsMouseDown(ImGuiMouseButton_Left); bool32 RightClick = ImGui::IsMouseDown(ImGuiMouseButton_Right); - ImGui::OpenPopupOnItemClick("layercolor", ImGuiPopupFlags_MouseButtonRight); - if (ImGui::BeginPopup("layercolor")) { - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); - for (int c = 0; c < AmountOf(UI->LayerColors); c++) { - ImGui::PushID(c); - ImGui::PushStyleColor(ImGuiCol_Button, UI->LayerColors[c]); - real32 Size = ImGui::GetFontSize() * 2; - ImVec2 ColSize(Size, Size); - ImGui::Button("##test", ColSize); - if ((c+1) % 4) { ImGui::SameLine(); } - ImGui::PopStyleColor(); - ImGui::PopID(); - } - ImGui::PopStyleVar(); - ImGui::EndPopup(); - } - if (IsHovered && io.MouseWheel) { real32 Increment = 0.1; bool32 Direction = (io.MouseWheel > 0) ? 1 : -1; - ImVec2 Offset = (io.MousePos - (TimelineAbsolutePos + TimelineMoveSize)) / TimelineZoomSize; + ImVec2 Offset = (io.MousePos - (TimelineAbsolutePos + ActiveMoveSize)) / ActiveZoomSize; if (io.KeyShift) { - UI->TimelinePercentOffset.y += Increment*Direction; + ActivePercentOffset->y += Increment*Direction; } else if (io.KeyCtrl) { - UI->TimelinePercentOffset.x += Increment*Direction*0.3; + ActivePercentOffset->x += Increment*Direction*0.3; } else { if (Direction == 1) { - UI->TimelinePercentZoomed = UI->TimelinePercentZoomed - (UI->TimelinePercentZoomed * Increment); - UI->TimelinePercentOffset = UI->TimelinePercentOffset - ((UI->TimelinePercentOffset * Increment) + Offset*Increment); + *ActivePercentZoomed = *ActivePercentZoomed - (*ActivePercentZoomed * Increment); + *ActivePercentOffset = *ActivePercentOffset - ((*ActivePercentOffset * Increment) + Offset*Increment); } else { - UI->TimelinePercentOffset = ((UI->TimelinePercentOffset + Offset*Increment) / (1.0f - Increment)); - UI->TimelinePercentZoomed = (UI->TimelinePercentZoomed / (1.0f - Increment)); + *ActivePercentOffset = ((*ActivePercentOffset + Offset*Increment) / (1.0f - Increment)); + *ActivePercentZoomed = (*ActivePercentZoomed / (1.0f - Increment)); } } } - if (IsItemActivated) { - if (!io.KeyShift && UI->TimelineMode == timeline_mode_default) Layer_DeselectAll(Memory, File->Layer_Count); - if (State->Interact_Active == interact_type_keyframe_move || - State->Interact_Active == interact_type_keyframe_rotate || - State->Interact_Active == interact_type_keyframe_scale) { - 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); - if (!Layer->IsSelected) - continue; - for (int h = 0; h < AmountOf(Layer->Property); h++) { - 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); + if (LeftClick) { + if (IsItemActivated) { + if (!io.KeyShift && UI->TimelineMode == timeline_mode_default) Layer_DeselectAll(Memory, File->Layer_Count); + if (State->Interact_Active == interact_type_keyframe_move || + State->Interact_Active == interact_type_keyframe_rotate || + State->Interact_Active == interact_type_keyframe_scale) { + 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); + if (!Layer->IsSelected) + continue; + for (int h = 0; h < AmountOf(Layer->Property); h++) { + 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++; } - k++; } } } + State->Interact_Offset[0] = 0; + State->Interact_Offset[1] = 0; + State->Interact_Offset[2] = 0; + State->Interact_Offset[3] = 0; + State->Interact_Active = interact_type_none; } - State->Interact_Offset[0] = 0; - State->Interact_Offset[1] = 0; - State->Interact_Offset[2] = 0; - State->Interact_Offset[3] = 0; - State->Interact_Active = interact_type_none; + UI->BoxSelect = true; } - UI->BoxSelect = true; - } - if (IsItemActive) { - Assert(UI->BoxSelect); - draw_list->AddRectFilled(io.MouseClickedPos[0], io.MousePos, - IM_COL32(0, 0, 200, 50)); + if (IsItemActive) { + Assert(UI->BoxSelect); + draw_list->AddRectFilled(io.MouseClickedPos[0], io.MousePos, + IM_COL32(0, 0, 200, 50)); + } + } else { + UI->Warp_X = 0; + UI->Warp_Y = 0; } if (IsItemDeactivated) { UI->BoxSelect = false; } - if (!ImGui::IsMouseDown(ImGuiMouseButton_Left)) { - UI->Warp_X = 0; - UI->Warp_Y = 0; - } - draw_list->PopClipRect(); ImGui::PopClipRect(); @@ -1684,8 +1855,10 @@ ImGui_ProcessInputs(project_data *File, project_state *State, ui *UI, memory *Me if (ImGui::IsKeyPressed(ImGuiKey_B)) { State->Tool = tool_brush; } - if (ImGui::IsKeyPressed(ImGuiKey_T)) { - Interact_Transform_Begin(File, Memory, State, io.MousePos); + if (ImGui::IsKeyPressed(ImGuiKey_Tab)) { + UI->TimelineMode = (UI->TimelineMode == timeline_mode_default) ? timeline_mode_graph : timeline_mode_default; + UI->GraphZoomSize = ImVec2(0, 0); + UI->GraphMoveSize = ImVec2(0, 0); } if (UI->TimelineMode == timeline_mode_graph) { if (ImGui::IsKeyPressed(ImGuiKey_G)) { @@ -1716,7 +1889,7 @@ ImGui_ProcessInputs(project_data *File, project_state *State, ui *UI, memory *Me if (ImGui::IsKeyPressed(ImGuiKey_Space)) { State->IsPlaying ^= 1; } - if (ImGui::IsKeyPressed(ImGuiKey_T)) { + if (ImGui::IsKeyPressed(ImGuiKey_2)) { 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); diff --git a/prenderer.cpp b/prenderer.cpp index dcb4577..58e1b22 100644 --- a/prenderer.cpp +++ b/prenderer.cpp @@ -63,13 +63,13 @@ Transform_ApplyInteractive(interact_transform Interact, real32 *OutputX, real32 } static void -Transform_IterateOuterBounds(block_layer *Layer, block_source *Source, real32 *MinX, real32 *MinY, real32 *MaxX, real32 *MaxY) +Transform_IterateOuterBounds(block_layer *Layer, uint32 Width, uint32 Height, real32 *MinX, real32 *MinY, real32 *MaxX, real32 *MaxY) { real32 Rad = (Layer->rotation.CurrentValue * (PI / 180)); real32 s = Layer->scale.CurrentValue; - v2 XAxis = (Source->Width * s)*V2(cos(Rad), sin(Rad)); - v2 YAxis = (Source->Height * -s)*V2(sin(Rad), -cos(Rad)); + v2 XAxis = (Width * s)*V2(cos(Rad), sin(Rad)); + v2 YAxis = (Height * -s)*V2(sin(Rad), -cos(Rad)); real32 AnchorX = Layer->ax.CurrentValue; real32 AnchorY = Layer->ay.CurrentValue; @@ -89,23 +89,109 @@ Transform_IterateOuterBounds(block_layer *Layer, block_source *Source, real32 *M } } +static void +Transform_Recurse(project_state *State, memory *Memory, block_composition *MainComp, uint32 CompIndex, block_layer *ParentLayer[4], uint32 Recursions, + sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, + real32 *MinX, real32 *MinY, real32 *MaxX, real32 *MaxY) +{ + sorted_comp_info *SortedCompInfo = &SortedCompArray[CompIndex]; + sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, SortedCompArray, CompIndex); + for (int i = 0; i < SortedCompInfo->LayerCount; i++) + { + sorted_layer SortEntry = SortedLayerInfo[i]; + uint32 Index_Physical = SortEntry.Block_Layer_Index; + block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical); + if (Layer->IsPrecomp) { + ParentLayer[Recursions] = Layer; + Transform_Recurse(State, Memory, MainComp, Layer->Block_Source_Index, ParentLayer, Recursions + 1, SortedCompArray, SortedLayerArray, + MinX, MinY, MaxX, MaxY); + } + if (Layer->IsSelected) { + uint32 Width = 0, Height = 0; + if (!Layer->IsPrecomp) { + block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index); + Width = Source->Width; + Height = Source->Height; + } else { + block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, Layer->Block_Source_Index); + Width = Comp->Width; + Height = Comp->Height; + } + + v2 Point[5] = { V2(Width*Layer->ax.CurrentValue, Height*Layer->ay.CurrentValue), V2(0, 0), V2(Width, 0), V2(0, Height), V2(Width, Height) }; + + layer_transforms T = Layer_GetTransforms(Layer); + + v2 NewPos[5]; + for (int i = 0; i < 5; i++) { + NewPos[i] = TransformPoint(T, Width, Height, Point[i]); + } + + int i = 0; + while (i < Recursions) { + T = Layer_GetTransforms(ParentLayer[i]); + block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, ParentLayer[i]->Block_Source_Index); + Width = Comp->Width; + Height = Comp->Height; + for (int i = 0; i < 5; i++) { + NewPos[i] = TransformPoint(T, Width, Height, NewPos[i]); + } + i++; + } + + for (int i = 0; i < 4; i++) { + if (NewPos[i+1].x < *MinX) { *MinX = NewPos[i+1].x; } + if (NewPos[i+1].y < *MinY) { *MinY = NewPos[i+1].y; } + if (NewPos[i+1].x > *MaxX) { *MaxX = NewPos[i+1].x; } + if (NewPos[i+1].y > *MaxY) { *MaxY = NewPos[i+1].y; } + } + } + } +} + // IMPORTANT(fox): The selection state and ordering of layers cannot change // until this action is exited/committed! static void -Interact_Transform_Begin(project_data *File, memory *Memory, project_state *State, ImVec2 OGPos) +Interact_Transform_Begin(project_data *File, memory *Memory, project_state *State, ImVec2 OGPos, + sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray) { real32 MinX = 100000; real32 MinY = 100000; real32 MaxX = -100000; real32 MaxY = -100000; + block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, File->PrincipalCompIndex); + block_layer *ParentLayer[4]; + Transform_Recurse(State, Memory, MainComp, File->PrincipalCompIndex, ParentLayer, 0, + SortedCompArray, SortedLayerArray, + &MinX, &MinY, &MaxX, &MaxY); + if (MinX != 100000) { + State->Interact_Active = interact_type_viewport_transform; + interact_transform *Interact = (interact_transform *)&State->Interact_Offset[0]; + Interact->Min = V2(MinX, MinY); + Interact->Max = V2(MaxX, MaxY); + Interact->Position = V2(0); + Interact->Radians = 0; + Interact->Scale = 1.0f; + Interact->OGPos = OGPos; + } + /* bool32 Activate = false; // Find the max dimensions of all the selected layers. for (int i = 0; i < File->Layer_Count; i++) { block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); if (!Layer->IsSelected) continue; - block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index); - Transform_IterateOuterBounds(Layer, Source, &MinX, &MinY, &MaxX, &MaxY); + uint32 Width = 0, Height = 0; + if (!Layer->IsPrecomp) { + block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index); + Width = Source->Width; + Height = Source->Height; + } else { + block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, Layer->Block_Source_Index); + Width = Comp->Width; + Height = Comp->Height; + } + Transform_IterateOuterBounds(Layer, Width, Height, &MinX, &MinY, &MaxX, &MaxY); Activate = true; } if (Activate) { @@ -118,30 +204,51 @@ Interact_Transform_Begin(project_data *File, memory *Memory, project_state *Stat Interact->Scale = 1.0f; Interact->OGPos = OGPos; } + */ +} + +static v2 +TransformPoint(layer_transforms T, real32 Width, real32 Height, v2 Point) +{ + real32 Rad = (T.rotation * (PI / 180)); + v2 XAxis = (Point.x - T.ax*Width) * T.scale * V2(cos(Rad), sin(Rad)); + v2 YAxis = (Point.y - T.ay*Height) * -T.scale * V2(sin(Rad), -cos(Rad)); + v2 LocalPoint = XAxis + YAxis; + return V2(T.x + LocalPoint.x, T.y + LocalPoint.y); } + static ImVec2 -Layer_LocalToScreenSpace(project_state *State, block_layer *Layer, ui *UI, - real32 SourceWidth, real32 SourceHeight, real32 CompWidth, real32 CompHeight, v2 Point) +Layer_LocalToScreenSpace(project_state *State, memory *Memory, block_layer *Layer, ui *UI, uint32 PrincipalCompIndex, v2 Point) { - real32 Rotation = Layer->rotation.CurrentValue; - real32 s = Layer->scale.CurrentValue; - real32 X = Layer->x.CurrentValue; - real32 Y = Layer->y.CurrentValue; + block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, PrincipalCompIndex); + + uint32 Width = 0, Height = 0; + if (!Layer->IsPrecomp) { + block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index); + Width = Source->Width; + Height = Source->Height; + } else { + block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, Layer->Block_Source_Index); + Width = Comp->Width; + Height = Comp->Height; + } + + layer_transforms T = Layer_GetTransforms(Layer); if (State->Interact_Active == interact_type_viewport_transform && Layer->IsSelected) { - Transform_ApplyInteractive(*(interact_transform *)&State->Interact_Offset[0], &X, &Y, &Rotation, &s); + Transform_ApplyInteractive(*(interact_transform *)&State->Interact_Offset[0], &T.x, &T.y, &T.rotation, &T.scale); } - real32 Rad = (Rotation * (PI / 180)); - real32 AX = Layer->ax.CurrentValue; - real32 AY = Layer->ay.CurrentValue; + v2 NewPos = TransformPoint(T, Width, Height, Point); + + if (Layer->Block_Composition_Index != PrincipalCompIndex) { + layer_transforms T = Layer_GetTransforms(Layer); + NewPos = TransformPoint(T, Width, Height, NewPos); + } + + v2 CompUV = NewPos / V2(MainComp->Width, MainComp->Height); - v2 XAxis = (Point.x - AX*SourceWidth) * s * V2(cos(Rad), sin(Rad)); - v2 YAxis = (Point.y - AY*SourceHeight) * -s * V2(sin(Rad), -cos(Rad)); - v2 LocalPoint = XAxis + YAxis; - v2 CompUV = V2((X + LocalPoint.x) / CompWidth, - (Y + LocalPoint.y) / CompHeight); v2 ScreenPoint = V2(UI->CompPos.x + CompUV.x * UI->CompZoom.x, UI->CompPos.y + CompUV.y * UI->CompZoom.y); -- cgit v1.2.3