From ed27ab2e6bbe40120702dcc57e9b21434bfb4944 Mon Sep 17 00:00:00 2001 From: Fox Caminiti Date: Sat, 3 Dec 2022 21:57:53 -0500 Subject: v2.0, effects functional --- bezier.cpp | 1 - createcalls.cpp | 328 +++++++++++++++++++++++++++++++------- defines.h | 2 + effects.cpp | 46 +++++- effects_constructors.cpp | 31 ++-- effects_gl.cpp | 31 +++- effects_software.cpp | 28 ++-- functions.h | 5 + imgui_ops.h | 10 ++ keybinds.h | 6 +- main.cpp | 29 ++-- main.h | 7 +- my_imgui_widgets.cpp | 403 ++++++++++++++++++++++++++++++++++++++++++----- package.sh | 6 +- 14 files changed, 775 insertions(+), 158 deletions(-) diff --git a/bezier.cpp b/bezier.cpp index f476986..1a177c4 100644 --- a/bezier.cpp +++ b/bezier.cpp @@ -1,4 +1,3 @@ -static real32 Tau = 0.9; // tension static real32 Bezier_SolveYForX(v2 Point_P0, v2 Point_P1, v2 Point_P2, v2 Point_P3, real32 TargetX) { diff --git a/createcalls.cpp b/createcalls.cpp index 145a58a..912917f 100644 --- a/createcalls.cpp +++ b/createcalls.cpp @@ -206,14 +206,14 @@ Bezier_EvaluateValue(project_state *State, bezier_point *PointAddress, v2 *Pos, static void -Bezier_Add(memory *Memory, property_channel *Property, bezier_point PointData, uint16 *ArrayLocation) +Bezier_Add(memory *Memory, memory_table_list TableName, property_channel *Property, bezier_point PointData, uint16 *ArrayLocation) { 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], 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); + History_Action_Swap(Memory, TableName, sizeof(Property->Block_Bezier_Count), &Property->Block_Bezier_Count); Property->Block_Bezier_Count++; } // First check to see if the point to add overlaps an existing keyframe: @@ -234,7 +234,7 @@ Bezier_Add(memory *Memory, property_channel *Property, bezier_point PointData, u 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); + History_Action_Swap(Memory, TableName, sizeof(Property->Keyframe_Count), &Property->Keyframe_Count); Property->Keyframe_Count++; return; } @@ -243,11 +243,11 @@ Bezier_Add(memory *Memory, property_channel *Property, bezier_point PointData, u } static void -Property_AddKeyframe(memory *Memory, property_channel *Property, int Frame, uint16 *ArrayLocation) +Property_AddKeyframe(memory *Memory, memory_table_list TableName, property_channel *Property, int Frame, uint16 *ArrayLocation) { History_Entry_Commit(Memory, "Add keyframe"); bezier_point Point = { 1, {(real32)Frame, Property->CurrentValue, -1, 0, 1, 0}, interpolation_type_linear, 0, {0, 0, 0}, 0 }; - Bezier_Add(Memory, Property, Point, ArrayLocation); + Bezier_Add(Memory, TableName, Property, Point, ArrayLocation); History_Entry_End(Memory); } @@ -257,9 +257,8 @@ Property_AddKeyframe(memory *Memory, property_channel *Property, int Frame, uint // } static property_channel -Property_InitFloat(char *Name, real32 Val, real32 ScrubVal, real32 MinVal = PROPERTY_REAL_MIN, real32 MaxVal = PROPERTY_REAL_MAX, bool32 AlwaysInteger = 0) { +Property_InitFloat(real32 Val, real32 ScrubVal, real32 MinVal = PROPERTY_REAL_MIN, real32 MaxVal = PROPERTY_REAL_MAX, bool32 AlwaysInteger = 0) { property_channel Property = {}; - Property.Name = Name; Property.CurrentValue = Val; Property.MinVal = MinVal; Property.MaxVal = MaxVal; @@ -331,7 +330,7 @@ Effect_Init(project_state *State, memory *Memory, uint32 EffectEntryIndex, int E property_channel *Property = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[e], 0); Property->Occupied = true; header_property PropertyHeader = State->Property[EffectHeader->PropertyStartIndex + e]; - Property->Name = PropertyHeader.Name; + Property->Identifier = -1; Property->CurrentValue = PropertyHeader.DefaultValue; Property->MinVal = PropertyHeader.MinVal; Property->MaxVal = PropertyHeader.MaxVal; @@ -373,13 +372,32 @@ Layer_UpdateMasksEffects(project_state *State, block_layer *Layer, memory *Memor header_effect *EffectEntry = Effect_EntryFromID(State, Effect.ID); if (Effect.IsToggled) { - real32 *Data = (real32 *)Memory_PushScratch(Memory, sizeof(real32) * 50); - for (int c = 0; c < EffectEntry->Property_Count; c++) { - property_channel *Property = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect.Block_Property_Index[c]); - Data[c] = Property->CurrentValue; + uint64 Size = (sizeof(real32) * MAX_PROPERTIES_PER_EFFECT) + (sizeof(real32) * 10); + real32 *Data; + if (EffectEntry->DisplayType == effect_display_type_curves) { + Data = (real32 *)Memory_PushScratch(Memory, Size); + uint16 SortedPointIndex[MAX_PROPERTIES_PER_EFFECT]; + v2 *SortedPointValues = (v2 *)(Data + 5); + for (int c = 0; c < 5; c++) { + *(Data + c) = Effect.ExtraData[c]; + uint32 Shift = MAX_PROPERTIES_PER_EFFECT / 5 * c; + uint16 *SortedPointIndexPlayhead = SortedPointIndex + Shift; + v2 *SortedPointValuesPlayhead = SortedPointValues + Shift; + Effect_Curves_Sort(Memory, &Effect, SortedPointIndexPlayhead, c); + for (int a = 0; a < Effect.ExtraData[c]; a++) { + *SortedPointValuesPlayhead = Effect_V2(Memory, &Effect, SortedPointIndexPlayhead[a]); + SortedPointValuesPlayhead++; + } + } + } else { + Data = (real32 *)Memory_PushScratch(Memory, Size); + for (int c = 0; c < EffectEntry->Property_Count; c++) { + property_channel *Property = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect.Block_Property_Index[c]); + Data[c] = Property->CurrentValue; + } } EffectEntry->func(Data, Width, Height, BytesPerPixel, EffectBitmapAddress, EffectEntry->GLShaderIndex); - Memory_PopScratch(Memory, sizeof(real32) * 50); + Memory_PopScratch(Memory, Size); } } /* @@ -457,9 +475,9 @@ Layer_LoopChannels(project_state *State, memory *Memory, sorted_property_info ** property_channel **Property, block_effect **EffectOut, int *h, int *c, int *p) { uint32 Amount = AmountOf(Layer->Property) + Layer->Block_Effect_Count; - Assert(Layer->Block_Effect_Count < 2); + // Assert(Layer->Block_Effect_Count < 2); while (*h < Amount) { - if (*h < AmountOf(Layer->Property)) { + if (*h < AmountOf(Layer->Property) && *c == 0) { *Property = &Layer->Property[*h]; if (*h != 0) { *SortedProperty += 1; @@ -477,12 +495,13 @@ Layer_LoopChannels(project_state *State, memory *Memory, sorted_property_info ** while (*c < EffectHeader->Property_Count) { // header_property ChannelHeader = State->Property[EffectHeader->PropertyStartIndex + c]; *Property = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[*c]); + *SortedProperty += 1; *SortedKeyframe += *p; *p = (**Property).Keyframe_Count; - *h += 1; *c += 1; return 1; } + *h += 1; *c = 0; } } @@ -490,6 +509,53 @@ Layer_LoopChannels(project_state *State, memory *Memory, sorted_property_info ** return 0; } +static void +Layer_ToggleAllChannels(project_state *State, memory *Memory, block_layer *Layer, + sorted_comp_info *SortedCompInfo, sorted_layer *SortedLayerInfo, + sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray) +{ + bool32 ToggleMode = 1; + { + sorted_property_info *InfoLocation = SortedPropertyInfo + SortedLayerInfo->SortedPropertyStart; + uint16 *ArrayLocation = SortedPropertyArray + SortedLayerInfo->SortedKeyframeStart; + int h = 0, c = 0, p = 0; + property_channel *Property = NULL; + block_effect *Effect = NULL; + while (Layer_LoopChannels(State, Memory, &InfoLocation, &ArrayLocation, Layer, &Property, &Effect, &h, &c, &p)) + { + if (Property->IsToggled) { + ToggleMode = 0; + break; + } + } + } + sorted_property_info *InfoLocation = SortedPropertyInfo + SortedLayerInfo->SortedPropertyStart; + uint16 *ArrayLocation = SortedPropertyArray + SortedLayerInfo->SortedKeyframeStart; + int h = 0, c = 0, p = 0; + property_channel *Property = NULL; + block_effect *Effect = NULL; + while (Layer_LoopChannels(State, Memory, &InfoLocation, &ArrayLocation, Layer, &Property, &Effect, &h, &c, &p)) + { + if (Property->Keyframe_Count) { + Property->IsToggled = ToggleMode; + } + } +} + +static void +Project_ToggleAllChannels(project_data *File, project_state *State, memory *Memory, + sorted_comp_info *SortedCompInfo, sorted_layer *SortedLayerInfo, + sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray) +{ + 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_ToggleAllChannels(State, Memory, Layer, SortedCompInfo, SortedLayerInfo, SortedPropertyInfo, SortedPropertyArray); + } + } +} + inline sorted_property_info * Property_GetSortedInfo(sorted_property_info *SortedPropertyInfo, int i, int h) { @@ -503,17 +569,36 @@ Property_GetSortedArray(uint16 *SortedPropertyArray, int i, int h) return SortedPropertyArray + (i * 8 * MAX_KEYFRAMES_PER_BLOCK) + (h * MAX_KEYFRAMES_PER_BLOCK); } +static sorted_layer * +Layer_GetSortedArray(sorted_layer *LayerArrayStart, sorted_comp_info *SortedCompStart, uint32 TargetComp) +{ + uint32 LayerOffset = 0; int s = 0; + while (s < TargetComp) { + LayerOffset += SortedCompStart[s].LayerCount; + s++; + } + return LayerArrayStart + LayerOffset; +} + static void -Bezier_Commit(project_data *File, project_state *State, memory *Memory, uint16 *SortedPropertyArray) { +Bezier_Commit(project_data *File, project_state *State, memory *Memory, + sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, + sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray) +{ History_Entry_Commit(Memory, "Move keyframe"); 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); + sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, SortedCompArray, Layer->Block_Composition_Index); if ((State->TimelineMode == timeline_mode_graph) && !Layer->IsSelected) continue; - for (int h = 0; h < AmountOf(Layer->Property); h++) { - uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, i, h); - property_channel *Property = &Layer->Property[h]; + sorted_property_info *InfoLocation = SortedPropertyInfo + SortedLayerInfo->SortedPropertyStart; + uint16 *ArrayLocation = SortedPropertyArray + SortedLayerInfo->SortedKeyframeStart; + int h = 0, c = 0, p = 0; + property_channel *Property = NULL; + block_effect *Effect = NULL; + while (Layer_LoopChannels(State, Memory, &InfoLocation, &ArrayLocation, Layer, &Property, &Effect, &h, &c, &p)) + { if ((State->TimelineMode != timeline_mode_graph) && !Property->IsToggled) continue; for (int p = 0; p < Property->Keyframe_Count; p++) { @@ -582,6 +667,8 @@ void Clipboard_Paste(project_data *File, project_state *State, memory *Memory, s break; // NOTE(fox): This loop assumes all layers and the clipboard have // channels laid out in the same way! + Assert(0); + /* for (int h = 0; h < AmountOf(Layer->Property); h++) { property_channel *Property = &Layer->Property[h]; if (Property->Name == Channel->Name) { @@ -589,7 +676,7 @@ void Clipboard_Paste(project_data *File, project_state *State, memory *Memory, s bezier_point PointData = *(bezier_point *)((uint8 *)State->ClipboardBuffer + ClipboardPos); PointData.Pos[0].x += State->Frame_Current; uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, i, h); - Bezier_Add(Memory, Property, PointData, ArrayLocation); + Bezier_Add(Memory, F_Layers, Property, PointData, ArrayLocation); ClipboardPos += sizeof(bezier_point); } b++; @@ -603,6 +690,7 @@ void Clipboard_Paste(project_data *File, project_state *State, memory *Memory, s else b = 0; } + */ } } @@ -648,7 +736,8 @@ void Clipboard_Store(project_data *File, project_state *State, memory *Memory, s LocalOffset = i; Contents->ChannelCount++; Channel->LayerOffset = LocalOffset - i; - Channel->Name = Property->Name; + Assert(0); + // Channel->Name = Property->Name; } } } @@ -658,17 +747,6 @@ void Clipboard_Store(project_data *File, project_state *State, memory *Memory, s } } -static sorted_layer * -Layer_GetSortedArray(sorted_layer *LayerArrayStart, sorted_comp_info *SortedCompStart, uint32 TargetComp) -{ - uint32 LayerOffset = 0; int s = 0; - while (s < TargetComp) { - LayerOffset += SortedCompStart[s].LayerCount; - s++; - } - return LayerArrayStart + LayerOffset; -} - static void Layer_Select_Traverse(uint16 PrincipalCompIndex, memory *Memory, project_state *State, int32 IndexToFind, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, int16 RecursionIdx[MAX_PRECOMP_RECURSIONS], int32 *Recursions) @@ -734,8 +812,22 @@ int32 Layer_TestSelection(memory *Memory, project_state *State, ui *UI, sorted_c block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, PrincipalIndex); sorted_comp_info SortedCompInfo = SortedCompArray[PrincipalIndex]; sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, SortedCompArray, PrincipalIndex); + int SelectionCount = 0; + int SelectedLayerIndex = 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); + block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index); + layer_transforms T = Layer_GetTransforms(Layer); + v2 UV = T_CompUVToLayerUV(T, Comp->Width, Comp->Height, Source->Width, Source->Height, State->TempZoomRatio); + if (UV.x <= 1.0f && UV.x >= 0.0f && UV.y <= 1.0f && UV.y >= 0.0f && Layer->IsSelected) + { + SelectionCount++; + SelectedLayerIndex = i; + } + } int32 LayerIndex = -1; - // for (int i = 0; i < SortedCompInfo.LayerCount; i++) { for (int i = SortedCompInfo.LayerCount - 1; i >= 0; i--) { sorted_layer SortEntry = SortedLayerInfo[i]; uint32 Index_Physical = SortEntry.Block_Layer_Index; @@ -745,8 +837,15 @@ int32 Layer_TestSelection(memory *Memory, project_state *State, ui *UI, sorted_c v2 UV = T_CompUVToLayerUV(T, Comp->Width, Comp->Height, Source->Width, Source->Height, State->TempZoomRatio); if (UV.x <= 1.0f && UV.x >= 0.0f && UV.y <= 1.0f && UV.y >= 0.0f && !Layer->IsSelected) { - LayerIndex = Index_Physical; - break; + if (SelectionCount == 1) { + if (i < SelectedLayerIndex) { + LayerIndex = Index_Physical; + break; + } + } else { + LayerIndex = Index_Physical; + break; + } } // if (Layer->IsPrecomp) { // Layer_RecursiveDeselect(Memory, SortedCompArray, SortedLayerArray, TargetIndex, Layer->Block_Source_Index); @@ -808,6 +907,55 @@ void Property_MinMax_Y(memory *Memory, project_state *State, property_channel *P } } +inline property_channel * +Effect_Property(memory *Memory, block_effect *Effect, int Offset) +{ + return (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[Offset]); +}; + +inline v2 Effect_V2(memory *Memory, block_effect *Effect, int Offset) +{ + property_channel *Property_X = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[Offset]); + property_channel *Property_Y = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[Offset + 1]); + return V2(Property_X->CurrentValue, Property_Y->CurrentValue); +} + +// TODO(fox): Merge with other sorting code. +void Effect_Curves_Sort(memory *Memory, block_effect *Effect, uint16 *SortedPointStart, uint16 Which) +{ + int i = 0; + int SortedPoints = 0; + for (;;) { + property_channel *CurrentProperty = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[i]); + v2 Point = Effect_V2(Memory, Effect, i); + uint32 SortedIndex_Playhead = 0; + if (CurrentProperty->Identifier == Which) { + while (SortedIndex_Playhead < SortedPoints) { + uint16 TestPointEntry = SortedPointStart[SortedIndex_Playhead]; + Assert(((property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[TestPointEntry]))->Identifier == Which); + v2 TestPoint = Effect_V2(Memory, Effect, TestPointEntry); + if (Point.x < TestPoint.x) { + break; + } else { + SortedIndex_Playhead += 1; + } + } + if (SortedIndex_Playhead != SortedPoints) { + uint8 *Address_Start = (uint8 *)(SortedPointStart + SortedIndex_Playhead); + uint8 *Address_End = (uint8 *)(SortedPointStart + SortedPoints) - 1; + Arbitrary_ShiftData(Address_Start, Address_End, sizeof(uint16), 1); + } + + uint16 *PointEntry = SortedPointStart + SortedIndex_Playhead; + *PointEntry = i; + SortedPoints++; + } + i += 2; + if (i > (MAX_PROPERTIES_PER_EFFECT - 1)) + break; + } +} + // 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. @@ -816,15 +964,16 @@ void Property_SortAll(memory *Memory, project_state *State, property_channel *Pr { int h = 0, c = 0, i = 0; uint32 CurrentSortIndex = 0; - real32 MinY = FLT_MAX; - real32 MaxY = FLT_MIN; + real32 MinY = 1000000; + real32 MaxY = -1000000; int32 Offset = (State->Interact_Active == interact_type_keyframe_move) ? (int32)State->Interact_Offset[0] : 0; while (Block_Loop(Memory, Property, Property->Keyframe_Count, &h, &c, &i)) { v2 PointPos[3]; bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, i); - if (PointAddress->IsSelected) + if (PointAddress->IsSelected) { PropertyInfo->IsGraphSelected = true; + } Bezier_EvaluateValue(State, PointAddress, PointPos); @@ -861,16 +1010,23 @@ void Property_SortAll(memory *Memory, project_state *State, property_channel *Pr } } -void Property_DeselectAll(project_data *File, memory *Memory, uint16 *SortedPropertyArray) +void Property_DeselectAll(project_data *File, project_state *State, memory *Memory, + sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, + sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray) { 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]; - uint16 *ArrayLocation = SortedPropertyArray + (i * 7 * MAX_KEYFRAMES_PER_BLOCK) + (h * MAX_KEYFRAMES_PER_BLOCK); + sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, SortedCompArray, Layer->Block_Composition_Index); + sorted_property_info *InfoLocation = SortedPropertyInfo + SortedLayerInfo->SortedPropertyStart; + uint16 *ArrayLocation = SortedPropertyArray + SortedLayerInfo->SortedKeyframeStart; + int h = 0, c = 0, p = 0; + property_channel *Property = NULL; + block_effect *Effect = NULL; + while (Layer_LoopChannels(State, Memory, &InfoLocation, &ArrayLocation, Layer, &Property, &Effect, &h, &c, &p)) + { for (int p = 0; p < Property->Keyframe_Count; p++) { int k = ArrayLocation[p]; bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, k); @@ -899,11 +1055,19 @@ void Layer_Sort_CheckPrev(memory *Memory, int i, int Direction, sorted_layer *So } } -void Layer_Evaluate_Display(block_layer *Layer, sorted_layer *LayerArrayStart, sorted_comp_info *CompStart, sorted_layer *SortedLayerInfo, int i, real32 *Offset) +void Layer_Evaluate_Display(project_state *State, memory *Memory, block_layer *Layer, + sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray, + sorted_layer *LayerArrayStart, sorted_comp_info *CompStart, sorted_layer *SortedLayerInfo, + int i, real32 *Offset) { int ExtraPad = 1; - for (int h = 0; h < AmountOf(Layer->Property); h++) { - property_channel *Property = &Layer->Property[h]; + sorted_property_info *InfoLocation = SortedPropertyInfo + SortedLayerInfo->SortedPropertyStart; + uint16 *ArrayLocation = SortedPropertyArray + SortedLayerInfo->SortedKeyframeStart; + int h = 0, c = 0, p = 0; + property_channel *Property = NULL; + block_effect *Effect = NULL; + while (Layer_LoopChannels(State, Memory, &InfoLocation, &ArrayLocation, Layer, &Property, &Effect, &h, &c, &p)) + { if (Property->IsToggled) { *Offset += 1 + ExtraPad; ExtraPad = 0; @@ -954,8 +1118,8 @@ void TempSource_SortAll(project_data *File, project_state *State, memory *Memory // 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, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray, +void Layer_SortAll(project_data *File, project_state *State, memory *Memory, + sorted_layer *LayerArrayStart, sorted_comp_info *CompStart, uint32 LayerCount, uint32 CompCount) { int h = 0, c = 0, i = 0; @@ -1029,6 +1193,45 @@ void Layer_SortAll(project_data *File, project_state *State, memory *Memory, sor } } +// NOTE(fox): We could be slightly more efficient and just allocate redundant data +// instead of having another loop. +void LayerProperty_Allocate(project_data *File, project_state *State, memory *Memory, sorted_layer *LayerArrayStart, + sorted_comp_info *CompStart, uint32 LayerCount, uint32 CompCount, + uint32 *TotalPropertyCount, uint32 *TotalKeyframeCount) +{ + uint32 SortedPropertyPlayhead = 0; + uint32 SortedKeyframePlayhead = 0; + for (int c = 0; c < CompCount; c++) { + sorted_comp_info SortedCompInfo = CompStart[c]; + sorted_layer *SortedLayerInfo = Layer_GetSortedArray(LayerArrayStart, CompStart, c); + for (int i = 0; i < SortedCompInfo.LayerCount; i++) { + sorted_layer *SortedLayer = &SortedLayerInfo[i]; + block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, SortedLayer->Block_Layer_Index); + SortedLayer->SortedPropertyStart = SortedPropertyPlayhead; + SortedLayer->SortedKeyframeStart = SortedKeyframePlayhead; + for (int h = 0; h < AmountOf(Layer->Property); h++) { + property_channel *Property = &Layer->Property[h]; + if (Property->Keyframe_Count) { + SortedKeyframePlayhead += Property->Keyframe_Count; + } + SortedPropertyPlayhead++; + } + for (int i = 0; i < Layer->Block_Effect_Count; i++) { + block_effect Effect = *(block_effect *)Memory_Block_AddressAtIndex(Memory, F_Effects, Layer->Block_Effect_Index[i]); + header_effect *EffectHeader = Effect_EntryFromID(State, Effect.ID); + for (int h = 0; h < EffectHeader->Property_Count; h++) { + header_property ChannelHeader = State->Property[EffectHeader->PropertyStartIndex + h]; + property_channel *Property = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect.Block_Property_Index[h]); + if (Property->Keyframe_Count) { + SortedKeyframePlayhead += Property->Keyframe_Count; + } + SortedPropertyPlayhead++; + } + } + } + } +} + void LayerProperty_SortAll(project_data *File, project_state *State, memory *Memory, sorted_layer *LayerArrayStart, sorted_comp_info *CompStart, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray, uint32 LayerCount, uint32 CompCount) @@ -1089,8 +1292,11 @@ sorted_file File_Sort_Push(project_data *File, project_state *State, memory *Mem Arbitrary_Zero((uint8 *)Source_SortedArray, Sorted.Source_SortSize); Sorted.SourceArray = (uint16 *)Source_SortedArray; - uint64 PropertyArraySize = sizeof(uint16) * 8 * MAX_KEYFRAMES_PER_BLOCK * File->Layer_Count; - uint64 PropertyInfoSize = sizeof(sorted_property_info) * 8 * File->Layer_Count; + uint32 TotalPropertyCount = 0; + uint32 TotalKeyframeCount = 0; + LayerProperty_Allocate(File, State, Memory, Sorted.LayerArray, Sorted.CompArray, File->Layer_Count, File->Comp_Count, &TotalPropertyCount, &TotalKeyframeCount); + uint64 PropertyInfoSize = TotalPropertyCount * sizeof(sorted_property_info); + uint64 PropertyArraySize = TotalKeyframeCount * sizeof(uint16); Sorted.Property_SortSize = PropertyArraySize + PropertyInfoSize; void *Property_SortedArray = Memory_PushScratch(Memory, Sorted.Property_SortSize); Arbitrary_Zero((uint8 *)Property_SortedArray, Sorted.Property_SortSize); @@ -1098,7 +1304,7 @@ sorted_file File_Sort_Push(project_data *File, project_state *State, memory *Mem Sorted.PropertyArray = (uint16 *)((uint8 *)Property_SortedArray + PropertyInfoSize); TempSource_SortAll(File, State, Memory, Sorted.SourceArray, &Sorted.TempSourceCount); - Layer_SortAll(File, State, Memory, Sorted.LayerArray, Sorted.CompArray, Sorted.PropertyInfo, Sorted.PropertyArray, File->Layer_Count, File->Comp_Count); + Layer_SortAll(File, State, Memory, Sorted.LayerArray, Sorted.CompArray, File->Layer_Count, File->Comp_Count); LayerProperty_SortAll(File, State, Memory, Sorted.LayerArray, Sorted.CompArray, Sorted.PropertyInfo, Sorted.PropertyArray, File->Layer_Count, File->Comp_Count); return Sorted; } @@ -1138,14 +1344,14 @@ block_layer * Layer_Init(project_data *File, memory *Memory) sprintf(String->Char, "Layer %i", File->Layer_Count + 1); // CSbros... String->Occupied = 1; - Layer->x = Property_InitFloat("X Position", 0.0f, 1.0f); - Layer->y = Property_InitFloat("Y Position", 0.0f, 1.0f); - Layer->ax = Property_InitFloat("Anchor X", 0.5f, 0.005f); - Layer->ay = Property_InitFloat("Anchor Y", 0.5f, 0.005f); - Layer->scale = Property_InitFloat("Scale", 1.0f, 0.005f); - Layer->rotation = Property_InitFloat("Rotation", 0.0f, 1.0f); - Layer->opacity = Property_InitFloat("Opacity", 1.0f, 0.005f, 0.0f, 1.0f); - Layer->time = Property_InitFloat("Frame Number", 0.0f, 1.0f, 0, 100000, 1); + Layer->x = Property_InitFloat(0.0f, 1.0f); + Layer->y = Property_InitFloat(0.0f, 1.0f); + Layer->ax = Property_InitFloat(0.5f, 0.005f); + Layer->ay = Property_InitFloat(0.5f, 0.005f); + Layer->scale = Property_InitFloat(1.0f, 0.005f); + Layer->rotation = Property_InitFloat(0.0f, 1.0f); + Layer->opacity = Property_InitFloat(1.0f, 0.005f, 0.0f, 1.0f); + Layer->time = Property_InitFloat(0.0f, 1.0f, 0, 100000, 1); Layer->IsVisible = 1; @@ -1265,8 +1471,8 @@ void Precomp_UICreateButton(project_data *File, project_state *State, memory *Me block_layer *PrecompLayer = Layer_Init(File, Memory); bezier_point Point0 = { 1, {0, 0, 1, 0, 1, 0}, interpolation_type_linear, 0, {0, 0, 0}, 0 }; bezier_point Point1 = { 1, {(real32)NewComp->Frame_End, (real32)NewComp->Frame_End, 1, 0, 1, 0}, interpolation_type_linear, 0, {0, 0, 0}, 0 }; - Bezier_Add(Memory, &PrecompLayer->time, Point0, NULL); - Bezier_Add(Memory, &PrecompLayer->time, Point1, NULL); + Bezier_Add(Memory, F_Layers, &PrecompLayer->time, Point0, NULL); + Bezier_Add(Memory, F_Layers, &PrecompLayer->time, Point1, NULL); PrecompLayer->IsPrecomp = true; Layer_Select(Memory, State, Memory_Block_LazyIndexAtAddress(Memory, F_Layers, PrecompLayer)); PrecompLayer->Block_Source_Index = File->Comp_Count - 1; diff --git a/defines.h b/defines.h index 12db869..8216f1c 100644 --- a/defines.h +++ b/defines.h @@ -48,3 +48,5 @@ typedef uint64 ptrsize; // is there a compiler variable for 32 vs 64 bit like #define GetCPUTime() __rdtsc() #endif +static real32 Tau = 0.9; // tension + diff --git a/effects.cpp b/effects.cpp index c5a07af..1aacddb 100644 --- a/effects.cpp +++ b/effects.cpp @@ -5,9 +5,7 @@ static void Effect_DrawColor(real32 *Data, int Width, int Height, int BytesPerPixel, void *EffectBitmapAddress, uint16 ShaderProgram) { v4 Color = { Data[0], Data[1], Data[2], Data[3] }; - blend_mode BlendMode = (blend_mode)Data[4]; - Effect_GL_DrawColor(Width, Height, BytesPerPixel, EffectBitmapAddress, ShaderProgram, Color, BlendMode); - // Effect_Software_DrawColor(Width, Height, BytesPerPixel, EffectBitmapAddress, Color, BlendMode); + Effect_GL_DrawColor(Width, Height, BytesPerPixel, EffectBitmapAddress, ShaderProgram, Color); } static void @@ -16,3 +14,45 @@ Effect_GaussianBlur(real32 *Data, int Width, int Height, int BytesPerPixel, void real32 Radius = Data[0]; Effect_GL_GaussianBlur(Width, Height, BytesPerPixel, EffectBitmapAddress, ShaderProgram, Radius); } + +static void +Effect_Curves_Init(block_effect *Effect, property_channel *Property) +{ + for (int i = 0; i < 5; i++) { + Property->Identifier = i; + Property++; + Property->Identifier = i; + Property++; + + Property->CurrentValue = 1.0f; + Property->Identifier = i; + Property++; + Property->CurrentValue = 1.0f; + Property->Identifier = i; + Property++; + + Effect->ExtraData[i] = 2; + } +} + +static void +Effect_Levels(real32 *Data, int Width, int Height, int BytesPerPixel, void *EffectBitmapAddress, uint16 ShaderProgram) +{ + real32 Min = Data[0]; + real32 Mid = Data[1]; + real32 Max = Data[2]; + + v4 ColMin = *(v4 *)&Data[3]; + v4 ColMid = *(v4 *)&Data[3+4]; + v4 ColMax = *(v4 *)&Data[3+8]; + Effect_GL_Levels(Width, Height, BytesPerPixel, EffectBitmapAddress, ShaderProgram, Min, Mid, Max, ColMin, ColMid, ColMax); +} + +static void +Effect_Curves(real32 *Data, int Width, int Height, int BytesPerPixel, void *EffectBitmapAddress, uint16 ShaderProgram) +{ + real32 PointCount = *Data; + v4 PointCount_Col = *(v4 *)(Data + 1); + v2 *PointData = (v2 *)(Data + 5); + Effect_Software_Curves(Width, Height, BytesPerPixel, EffectBitmapAddress, PointData, PointCount, PointCount_Col); +} diff --git a/effects_constructors.cpp b/effects_constructors.cpp index 7eb2143..406cb08 100644 --- a/effects_constructors.cpp +++ b/effects_constructors.cpp @@ -67,16 +67,6 @@ static void Effect_InitEntries(project_state *State) { /* - Effect_AddEntry(State, "Levels", "LVLS", &Effect_Levels, effect_display_type_levels); - // Levels - // min/max is handled by the UI - Effect_AddProperty_Real(State, "All start point", 0.0f); - Effect_AddProperty_Real(State, "All mid point", 1.0f); - Effect_AddProperty_Real(State, "All end point", 1.0f); - Effect_AddProperty_Col(State, "Channel start point", V4(0.0f)); - Effect_AddProperty_Col(State, "Channel mid point", V4(1.0f)); - Effect_AddProperty_Col(State, "Channel end point", V4(1.0f)); - Effect_EndEntry(State); */ // Curves /* @@ -90,20 +80,35 @@ Effect_InitEntries(project_state *State) } Effect_EndEntry(State); */ + // Solid color - Effect_AddEntry(State, "Solid color", "REALSCOL", Effect_DrawColor, GLShader_SolidColor); + Effect_AddEntry(State, "Solid color", "REALSCOL", &Effect_DrawColor, GLShader_SolidColor); Effect_AddProperty_Col(State, "Color", V4(0.3f, 0.2f, 0.6f, 1.0f)); - Effect_AddProperty_Blendmode(State, "Blend mode", blend_softlight); Effect_EndEntry(State); + // Gaussian blur Effect_AddEntry(State, "Gaussian blur", "REALGBLR", &Effect_GaussianBlur, GLShader_GaussianBlur); Effect_AddProperty_Real(State, "Radius", 1.0f, 0.0f, 200.0f); Effect_EndEntry(State); - /* + + // Curves Effect_AddEntry(State, "Curves", "REALCRVS", &Effect_Curves, NULL, effect_display_type_curves); for (int i = 0; i < MAX_PROPERTIES_PER_EFFECT; i++) { Effect_AddProperty_Real(State, "point", 0.0f); } + Effect_EndEntry(State); + + // Levels + Effect_AddEntry(State, "Levels", "REALLVLS", &Effect_Levels, GLShader_Levels, effect_display_type_levels); + // min/max is handled by the UI + Effect_AddProperty_Real(State, "All start point", 0.0f); + Effect_AddProperty_Real(State, "All mid point", 1.0f); + Effect_AddProperty_Real(State, "All end point", 1.0f); + Effect_AddProperty_Col(State, "Channel start point", V4(0.0f)); + Effect_AddProperty_Col(State, "Channel mid point", V4(1.0f)); + Effect_AddProperty_Col(State, "Channel end point", V4(1.0f)); + Effect_EndEntry(State); + /* // Test gradient Effect_AddEntry(State, "Test gradient", "REALTGRD", &Effect_TestGradient, NULL); Effect_AddProperty_Col(State, "Color", V4(0.3f, 0.2f, 0.6f, 1.0f)); diff --git a/effects_gl.cpp b/effects_gl.cpp index 2b8eac1..c3ff444 100644 --- a/effects_gl.cpp +++ b/effects_gl.cpp @@ -21,7 +21,7 @@ void Effect_GL_Start(gl_effect_layer *Test, int Width, int Height, int BytesPerP } void Effect_GL_DrawColor(int Width, int Height, int BytesPerPixel, void *EffectBitmapAddress, - uint16 ShaderProgram, v4 Color, blend_mode BlendMode) + uint16 ShaderProgram, v4 Color) { gl_effect_layer Test = {}; @@ -72,3 +72,32 @@ void Effect_GL_GaussianBlur(int Width, int Height, int BytesPerPixel, void *Effe glBindFramebuffer(GL_FRAMEBUFFER, 0); GL_DeleteHWBuffer(&Test); } + +void Effect_GL_Levels(int Width, int Height, int BytesPerPixel, void *EffectBitmapAddress, + uint16 ShaderProgram, real32 Min, real32 Mid, real32 Max, v4 ColMin, v4 ColMid, v4 ColMax) +{ + gl_effect_layer Test = {}; + + int ByteFlag = (BytesPerPixel == 4) ? GL_RGBA : GL_RGBA16; + int ByteFlag2 = (BytesPerPixel == 4) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT; + Effect_GL_Start(&Test, Width, Height, BytesPerPixel, EffectBitmapAddress, ShaderProgram); + + int Uniform = glGetUniformLocation(ShaderProgram, "Start"); + glUniform1f(Uniform, Min); + Uniform = glGetUniformLocation(ShaderProgram, "Mid"); + glUniform1f(Uniform, Mid); + Uniform = glGetUniformLocation(ShaderProgram, "End"); + glUniform1f(Uniform, Max); + Uniform = glGetUniformLocation(ShaderProgram, "StartCol"); + glUniform4f(Uniform, ColMin.r, ColMin.g, ColMin.b, ColMin.a); + Uniform = glGetUniformLocation(ShaderProgram, "MidCol"); + glUniform4f(Uniform, ColMid.r, ColMid.g, ColMid.b, ColMid.a); + Uniform = glGetUniformLocation(ShaderProgram, "EndCol"); + glUniform4f(Uniform, ColMax.r, ColMax.g, ColMax.b, ColMax.a); + + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + glReadPixels(0, 0, Width, Height, GL_RGBA, ByteFlag2, EffectBitmapAddress); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + GL_DeleteHWBuffer(&Test); +} diff --git a/effects_software.cpp b/effects_software.cpp index 71023e0..031f0a6 100644 --- a/effects_software.cpp +++ b/effects_software.cpp @@ -107,23 +107,15 @@ CurvesSolver(real32 *LUT, v2 Point_P1, v2 Point_P2, v2 m1, v2 m2, int i) } } -/* static void -Effect_Curves(file_source *Source, void *BitmapAddress, uint16 ShaderProgram, uint8 *FileEffectAddress) +Effect_Software_Curves(int Width, int Height, int BytesPerPixel, void *EffectBitmapAddress, v2 *PointData, real32 PointCount, v4 PointCount_Col) { - uint32 ChannelIndex = *(uint32 *)(real32 *)FileEffectAddress; - FileEffectAddress += sizeof(real32); - real32 NumberOfPoints_Main = *(real32 *)FileEffectAddress; - FileEffectAddress += sizeof(real32); - v4 NumberOfPoints_Col = *(v4 *)FileEffectAddress; - FileEffectAddress += sizeof(v4); - real32 LUT[5][256] = {}; for (int a = 0; a < 5; a++) { - int Num = (a == 0) ? NumberOfPoints_Main : NumberOfPoints_Col.E[a-1]; - v2 *CurvePoint = (v2 *)(FileEffectAddress + (a * (sizeof(v2) * 10))); + int Num = (a == 0) ? (int)PointCount : (int)PointCount_Col.E[a-1]; + v2 *CurvePoint = PointData + (MAX_PROPERTIES_PER_EFFECT / 5 * a); for (int i = 0; i < Num; i++) { v2 Point_P1 = CurvePoint[i]; @@ -164,13 +156,14 @@ Effect_Curves(file_source *Source, void *BitmapAddress, uint16 ShaderProgram, ui } - uint64 Size = Source->Width*Source->Height; + uint64 Size = Width*Height; int i = 0; Assert(BytesPerPixel == 4); while (i < Size) { - uint32 *Pixel = (uint32 *)BitmapAddress + i; + uint32 *Pixel = (uint32 *)EffectBitmapAddress + i; v4 t = Uint32ToCol8(*Pixel); +#if 1 real32 R_Lookup = LUT[1][(uint32)(t.r)]; real32 G_Lookup = LUT[2][(uint32)(t.g)]; real32 B_Lookup = LUT[3][(uint32)(t.b)]; @@ -179,8 +172,14 @@ Effect_Curves(file_source *Source, void *BitmapAddress, uint16 ShaderProgram, ui real32 R_Lookup_All = LUT[0][(uint32)(R_Lookup*255)]; real32 G_Lookup_All = LUT[0][(uint32)(G_Lookup*255)]; real32 B_Lookup_All = LUT[0][(uint32)(B_Lookup*255)]; +#else + real32 R_Lookup_All = LUT[0][(uint32)(t.r)]; + real32 G_Lookup_All = LUT[0][(uint32)(t.g)]; + real32 B_Lookup_All = LUT[0][(uint32)(t.b)]; +#endif + - uint32 Result = (((uint32)((A_Lookup * 255.0f) + 0.5) << 24) | + uint32 Result = (((uint32)((t.a) + 0.5) << 24) | ((uint32)((B_Lookup_All * 255.0f) + 0.5) << 16) | ((uint32)((G_Lookup_All * 255.0f) + 0.5) << 8) | ((uint32)((R_Lookup_All * 255.0f) + 0.5) << 0)); @@ -189,4 +188,3 @@ Effect_Curves(file_source *Source, void *BitmapAddress, uint16 ShaderProgram, ui i++; } } -*/ diff --git a/functions.h b/functions.h index 2825f85..ffba30c 100644 --- a/functions.h +++ b/functions.h @@ -5,9 +5,14 @@ static void Arbitrary_ShiftData(uint8 *Address_Start, uint8 *Address_End, uint64 static void Render_Main(void *Data, void *OutputBuffer, render_type RenderType, rectangle RenderRegion); +static void Effect_Curves_Init(block_effect *Effect, property_channel *Property); + static v2 T_CompUVToLayerUV(layer_transforms T, uint32 FileWidth, uint32 FileHeight, uint32 SourceWidth, uint32 SourceHeight, v2 CompUV); static header_effect* Effect_EntryFromID(project_state *State, char *ID); +void Effect_Curves_Sort(memory *Memory, block_effect *Effect, uint16 *SortedPointStart, uint16 Which); +inline v2 Effect_V2(memory *Memory, block_effect *Effect, int Offset); + 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, ImVec2 CompPos, ImVec2 CompZoom, ImVec2 ViewportMin, ImVec2 Point); diff --git a/imgui_ops.h b/imgui_ops.h index 2bf6335..6089f94 100644 --- a/imgui_ops.h +++ b/imgui_ops.h @@ -20,6 +20,16 @@ ImVec2 operator+(ImVec2 A, int B) return Result; } +ImVec2 operator-(ImVec2 A, int B) +{ + ImVec2 Result; + + Result.x = A.x - B; + Result.y = A.y - B; + + return Result; +} + ImVec2 operator-(ImVec2 A, ImVec2 B) { ImVec2 Result; diff --git a/keybinds.h b/keybinds.h index 4cddb29..3fe5f64 100644 --- a/keybinds.h +++ b/keybinds.h @@ -38,6 +38,7 @@ static shortcut_entry ShortcutArray[] { { ImGuiKey_P, Mod_Ctrl, key_mode_all, "Paste" }, { ImGuiKey_Z, Mod_Ctrl, key_mode_all, "Undo" }, { ImGuiKey_Z, Mod_Ctrl, key_mode_all, "Redo" }, + { ImGuiKey_Space, Mod_Shift, key_mode_all, "Focus effects search" }, { ImGuiKey_Slash, Mod_Shift, key_mode_all, "Open help" }, { ImGuiKey_None, Mod_None, key_mode_viewport, "Hold right click to pan." }, @@ -53,8 +54,9 @@ static shortcut_entry ShortcutArray[] { { ImGuiKey_S, Mod_None, key_mode_timeline, "Toggle scale keyframes" }, { ImGuiKey_T, Mod_None, key_mode_timeline, "Toggle time remapping keyframes" }, { ImGuiKey_T, Mod_Shift, key_mode_timeline, "Toggle opacity keyframes" }, - { ImGuiKey_B, Mod_None, key_mode_timeline, "Mark frame start" }, - { ImGuiKey_N, Mod_None, key_mode_timeline, "Mark frame end" }, + { ImGuiKey_U, Mod_None, key_mode_timeline, "Toggle all active channels" }, + { ImGuiKey_N, Mod_None, key_mode_timeline, "Mark frame start" }, + { ImGuiKey_N, Mod_Shift, key_mode_timeline, "Mark frame end" }, { ImGuiKey_G, Mod_None, key_mode_graph, "Enter keyframe moving mode" }, { ImGuiKey_X, Mod_None, key_mode_graph, "Constrain to X axis" }, diff --git a/main.cpp b/main.cpp index bb780c4..a32598f 100644 --- a/main.cpp +++ b/main.cpp @@ -161,6 +161,14 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI, { Clipboard_Paste(File, State, Memory, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyArray); } break; + case hotkey_togglechannels: + { + Project_ToggleAllChannels(File, State, Memory, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyInfo, Sorted.PropertyArray); + } break; + default: + { + Assert(0); + } break; } State->HotkeyInput = hotkey_none; } @@ -176,15 +184,7 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI, } #endif - // if (State->FocusedWindow == focus_viewport && State->SetFocus) { - // ImGui::SetNextWindowFocus(); - // State->SetFocus = false; - // } ImGui_Viewport(File, State, UI, Memory, io, textureID, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyArray); - // if (State->FocusedWindow == focus_timeline && State->SetFocus) { - // ImGui::SetNextWindowFocus(); - // State->SetFocus = false; - // } ImGui_Timeline(File, State, Memory, UI, io, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyInfo, Sorted.PropertyArray); ImGui_File(File, State, Memory, io, Sorted.CompArray, Sorted.LayerArray); ImGui_PropertiesPanel(File, State, UI, Memory, io, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyInfo, Sorted.PropertyArray); @@ -197,7 +197,7 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI, } #endif ImGui_Menu(File, State, UI, Memory, io); - ImGui_Popups(File, State, UI, Memory, io); // NOTE(fox): If popup disappears unexpectedly it means something else took its focus! + ImGui_Popups(File, State, UI, Memory, io); File_Sort_Pop(Memory, Sorted.Layer_SortSize, Sorted.Property_SortSize, Sorted.Source_SortSize); @@ -505,15 +505,6 @@ int main(int argc, char *argv[]) { File->Comp_Count = 1; - -#if 0 - { - uint16 SourceIndex = Source_Generate(File, State, &Memory, (void *)"../asset/a_small.jpg"); - block_source *Source = (block_source *)Memory_Block_AddressAtIndex(&Memory, F_Sources, File->Source_Count - 1); - Source->IsSelected = true; - } -#endif - SDL_Init(SDL_INIT_VIDEO); Semaphore = SDL_CreateSemaphore(0); @@ -633,10 +624,12 @@ int main(int argc, char *argv[]) { #endif #if DEBUG +#if 1 sprintf(State->DummyName, "test2"); File_Open(File, State, &Memory, State->DummyName); State->UpdateFrame = true; State->MostRecentlySelectedLayer = 0; +#endif #endif while (State->IsRunning) diff --git a/main.h b/main.h index c1b37f3..37701e4 100644 --- a/main.h +++ b/main.h @@ -256,7 +256,8 @@ enum hotkey_input hotkey_none, hotkey_transform, hotkey_copy, - hotkey_paste + hotkey_paste, + hotkey_togglechannels }; enum property_display_type @@ -300,6 +301,7 @@ struct block_effect bool32 IsToggled; uint16 Index; uint32 Block_Property_Index[MAX_PROPERTIES_PER_EFFECT]; + real32 ExtraData[16]; }; struct header_effect @@ -520,11 +522,12 @@ struct block_source struct property_channel { uint8 Occupied; - char *Name; // TODO(fox): Delete this. uint16 Block_Bezier_Index[MAX_KEYFRAME_BLOCKS]; uint16 Block_Bezier_Count; uint16 Keyframe_Count; + int32 Identifier; + real32 CurrentValue; real32 MaxVal; real32 MinVal; diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp index dbadd11..36bc79e 100644 --- a/my_imgui_widgets.cpp +++ b/my_imgui_widgets.cpp @@ -35,6 +35,248 @@ ImGui_PropertyInteract_Slider(project_state *State, memory *Memory, property_cha } } +static void +ImGui_RGBAModeSwitch(project_state *State, memory *Memory, ImGuiIO io, uint32 *Channel) +{ + char *Names[5] = {"All", "R", "G", "B", "A" }; + if (ImGui::BeginListBox("RGB")) { + for (int i = 0; i < 5; i++) { + if (ImGui::Selectable(Names[i], (*Channel == i))) { + *Channel = i; + } + } + ImGui::EndListBox(); + } +} + +static void +ImGui_CurvesUI(project_state *State, memory *Memory, ImGuiIO io, block_effect *Effect, property_channel *PropertyStart, uint16 *SortedPointStart) +{ + + real32 Padding = ImGui::GetFontSize()*6; + ImVec2 ViewportMin = ImGui::GetCursorScreenPos() + Padding/6; + ImVec2 ViewportScale = ImGui::GetContentRegionAvail(); + ViewportScale.y = ViewportScale.x = ViewportScale.x - Padding; // square seems nice + ImVec2 ViewportMax = ViewportMin + ViewportScale; + + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->AddRectFilled(ViewportMin, ViewportMax, IM_COL32(50, 50, 50, 255)); + draw_list->AddRect(ViewportMin, ViewportMax, IM_COL32(255, 255, 255, 255)); + + real32 PointSize = 40; + + ImU32 col = ImGui::GetColorU32(ImGuiCol_Text); + ImU32 col_light = ImGui::GetColorU32(ImGuiCol_TextDisabled); + + ImVec2 Point_ScreenPos[4]; + + // ocd? + draw_list->PushClipRect(ViewportMin + 2, ViewportMax - 2, true); + + for (real32 i = 0.25; i < 1.0; i += 0.25) { + ImVec2 Horizontal = ViewportMin + ViewportScale * ImVec2(0, i); + ImVec2 Vertical = ViewportMin + ViewportScale * ImVec2(i, 0); + draw_list->AddLine(Horizontal, Horizontal + ImVec2(ViewportScale.x, 0), col_light, 1.0f); + draw_list->AddLine(Vertical, Vertical + ImVec2(0, ViewportScale.y), col_light, 1.0f); + } + + draw_list->PopClipRect(); + + +#if 0 + real32 LUT[5][256] = {}; + + for (int a = 0; a < 5; a++) { + + int Num = (a == 0) ? *NumberOfPoints_Main : NumberOfPoints_Col->E[a-1]; + v2 *CurvePoint = (v2 *)(FileEffectAddress + (a * (sizeof(v2) * 10))); + + for (int i = 0; i < Num; i++) { + v2 Point_P1 = CurvePoint[i]; + v2 Point_P2 = CurvePoint[i + 1]; + v2 Point_P0 = (i != 0) ? CurvePoint[i - 1] : V2(0, 0); + v2 Point_P3 = (i != (Num - 2)) ? CurvePoint[i + 2] : V2(1, 1); + + v2 m1 = (Point_P2 - Point_P0) / (2 * Tau); + v2 m2 = (Point_P3 - Point_P1) / (2 * Tau); + + CurvesSolver(LUT[a], Point_P1, Point_P2, m1, m2, i); + } + + if (CurvePoint[0].x > 0.0f) { + real32 Count_Start = 0; + real32 Count_End = (CurvePoint[0].x * 255); + real32 Count = Count_Start; + while (Count < Count_End) { + LUT[a][(uint32)Count] = LUT[a][(uint32)Count_End]; + Count++; + } + } + + if (CurvePoint[Num-1].x < 1.0f) { + real32 Count_Start = (CurvePoint[Num-1].x * 255) - 0.5; + real32 Count_End = 255; + real32 Count = Count_Start; + while (Count < Count_End) { + LUT[a][(uint32)Count] = LUT[a][(uint32)Count_Start]; + Count++; + } + } + + for (int i = 0; i < Num; i++) { + if (CurvePoint[i].y == 1.0f) + LUT[a][255] = 1.0f; + } + } +#endif + + real32 *Num = &Effect->ExtraData[0]; + uint32 *SelectedChannel = (uint32 *)&Effect->ExtraData[5]; + + v2 Pos = {}; + bool32 AddPoint = 0; + + for (uint32 i = 0; i < *(uint32 *)Num; i += 1) { + + v2 Point_P1 = Effect_V2(Memory, Effect, SortedPointStart[i]); + v2 Point_P2 = Effect_V2(Memory, Effect, SortedPointStart[i + 1]); + v2 Point_P0 = (i != 0) ? Effect_V2(Memory, Effect, SortedPointStart[i - 1]) : V2(0, 0); + v2 Point_P3 = (i != (*Num - 2)) ? Effect_V2(Memory, Effect, SortedPointStart[i + 2]) : V2(1, 1); + + ImVec2 Point_P0_ScreenPos = ViewportMin + (ImVec2(Point_P0.x, 1.0f - Point_P0.y) * ViewportScale); + ImVec2 Point_P1_ScreenPos = ViewportMin + (ImVec2(Point_P1.x, 1.0f - Point_P1.y) * ViewportScale); + ImVec2 Point_P2_ScreenPos = ViewportMin + (ImVec2(Point_P2.x, 1.0f - Point_P2.y) * ViewportScale); + ImVec2 Point_P3_ScreenPos = ViewportMin + (ImVec2(Point_P3.x, 1.0f - Point_P3.y) * ViewportScale); + + ImGui::PushID(&PropertyStart[SortedPointStart[i]]); + + draw_list->AddNgon(Point_P1_ScreenPos, 2, col, 8, 5.0f); + + ImGui::SetCursorScreenPos(Point_P1_ScreenPos - ImVec2(PointSize/2, PointSize/2)); + ImGui::InvisibleButton("##point", ImVec2(PointSize, PointSize), ImGuiButtonFlags_MouseButtonLeft); + + if (ImGui::IsItemHovered()) { + ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); + } + + if (ImGui::IsItemActivated()) { + if (io.KeyCtrl && *Num != 2) { + property_channel *Property_X = Effect_Property(Memory, Effect, SortedPointStart[i]); + Property_X->Identifier = -1; + property_channel *Property_Y = Effect_Property(Memory, Effect, SortedPointStart[i]+1); + Property_Y->Identifier = -1; + Effect->ExtraData[*SelectedChannel]--; + } + } + + if (ImGui::IsItemActive()) { + property_channel *Property_X = Effect_Property(Memory, Effect, SortedPointStart[i]); + property_channel *Property_Y = Effect_Property(Memory, Effect, SortedPointStart[i]+1); + v2 Point = V2(((io.MousePos - ViewportMin) / ViewportScale)); + Point.y = 1.0f - Point.y; + Point.x = Normalize(Point.x); + Point.y = Normalize(Point.y); + Property_X->CurrentValue = Point.x; + Property_Y->CurrentValue = Point.y; + State->UpdateFrame = true; + } + + if (i == (*Num - 1)) { + ImGui::PopID(); + break; + } + + // Conversion from Catmull-Rom curves to Bezier curves for display, + // referencing https://pomax.github.io/bezierinfo/#catmullconv + + ImVec2 bez_m1 = (Point_P2_ScreenPos - Point_P0_ScreenPos) / (6 * Tau); + ImVec2 bez_m2 = (Point_P3_ScreenPos - Point_P1_ScreenPos) / (6 * Tau); + + ImVec2 Point_Bez[4]; + Point_Bez[0] = Point_P1_ScreenPos; + Point_Bez[1] = Point_P1_ScreenPos + bez_m1; + Point_Bez[2] = Point_P2_ScreenPos - bez_m2; + Point_Bez[3] = Point_P2_ScreenPos; + + draw_list->PushClipRect(ViewportMin, ViewportMax, true); + + draw_list->AddBezierCubic(Point_Bez[0], Point_Bez[1], Point_Bez[2], Point_Bez[3], col, 1.0f, 0); + + if (ImGui::BezierInteractive(Point_Bez[0], Point_Bez[1], Point_Bez[2], Point_Bez[3]) && + io.MousePos.x > (Point_P1_ScreenPos.x + PointSize/2) && + io.MousePos.x < (Point_P2_ScreenPos.x - PointSize/2)) + { + ImGui::SetCursorScreenPos(io.MousePos - ImVec2(5,5)); + ImGui::Button("pointclick", ImVec2(10, 10)); + if (ImGui::IsItemActivated()) { + Pos = V2(((io.MousePos - ViewportMin) / ViewportScale)); + Pos.y = 1.0f - Pos.y; + Pos.x = Normalize(Pos.x); + Pos.y = Normalize(Pos.y); + AddPoint = true; + } + } + + if (i == 0) + draw_list->AddLine(ImVec2(ViewportMin.x, Point_Bez[0].y), Point_Bez[0], col, 1.0f); + if (i == (*Num - 2)) + draw_list->AddLine(ImVec2(ViewportMax.x, Point_Bez[3].y), Point_Bez[3], col, 1.0f); + + draw_list->PopClipRect(); + +#if 0 + for (int x = 0; x < 256; x++) { + v2 Point = V2((real32)x/256, LUT[*ChannelIndex][x]); + ImVec2 Point_ScreenPos = ViewportMin + (ImVec2(Point.x, 1.0f - Point.y) * ViewportScale); + draw_list->AddNgon(Point_ScreenPos, 1, col, 8, 5.0f); + } +#endif + + draw_list->AddNgon(Point_P1_ScreenPos, 2, col, 8, 5.0f); + + + ImGui::PopID(); + } + + + if (AddPoint) { + int x = 0; + for (;;) { + property_channel *Property_X = Effect_Property(Memory, Effect, x); + if (Property_X->Identifier == -1) { + Property_X->CurrentValue = Pos.x; + Property_X->Identifier = *SelectedChannel; + property_channel *Property_Y = Effect_Property(Memory, Effect, x+1); + Assert(Property_Y->Identifier == -1); + Property_Y->CurrentValue = Pos.y; + Property_Y->Identifier = *SelectedChannel; + x = MAX_PROPERTIES_PER_EFFECT; + } + if (x > MAX_PROPERTIES_PER_EFFECT) + break; + x++; + } + Effect->ExtraData[*SelectedChannel]++; + AddPoint = false; + } + + // ImVec2 ButtonPos = ImGui::GetCursorScreenPos(); + ImGui::SetCursorScreenPos(ViewportMin); + + ImGui::InvisibleButton("canvas", ViewportScale, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight); + bool32 IsHovered = ImGui::IsItemHovered(); + bool32 IsActive = ImGui::IsItemActive(); + bool32 IsActivated = ImGui::IsItemActivated(); + bool32 IsDeactivated = ImGui::IsItemDeactivated(); + + ImVec2 EndPos = ImGui::GetCursorScreenPos(); + + ImGui::SetCursorScreenPos(ViewportMin + ImVec2(ViewportScale.x + 20, 0)); + ImGui_RGBAModeSwitch(State, Memory, io, SelectedChannel); + + ImGui::SetCursorScreenPos(EndPos); +} + static void ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, @@ -73,33 +315,99 @@ ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory * while (Layer_LoopChannels(State, Memory, &InfoLocation, &ArrayLocation, Layer, &Property, &Effect, &h, &c, &p)) { ImGui::PushID(Property); - if ((h - 1) < AmountOf(Layer->Property)) { + if ((h - 1) < AmountOf(Layer->Property) && c == 0) { if (ImGui::Button("K")) { - uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, State->MostRecentlySelectedLayer, h-1); - Property_AddKeyframe(Memory, Property, State->Frame_Current, ArrayLocation); + Property_AddKeyframe(Memory, F_Layers, Property, State->Frame_Current, ArrayLocation); } ImGui::SameLine(); +#if DEBUG + char size[64]; + sprintf(size, "%s, %i", DefaultChannel[h-1], Property->Keyframe_Count); + char *Name = size; +#else char *Name = DefaultChannel[h-1]; +#endif ImGui::DragScalar(Name, ImGuiDataType_Float, &Property->CurrentValue, Property->ScrubVal, &Property->MinVal, &Property->MaxVal, "%f"); ImGui_PropertyInteract_Slider(State, Memory, Property, io, WindowMinAbs, WindowMaxAbs, F_Layers); } else { Assert(Effect); header_effect *EffectHeader = Effect_EntryFromID(State, Effect->ID); header_property ChannelHeader = State->Property[EffectHeader->PropertyStartIndex + c - 1]; - Assert(EffectHeader->DisplayType == effect_display_type_standard); +#if DEBUG + char size[64]; + sprintf(size, "%s, %i", ChannelHeader.Name, Property->Keyframe_Count); + char *Name = size; +#else + char *Name = ChannelHeader.Name; +#endif if ((c - 1) == 0) { ImGui::PushID(Effect->Index); +#if DEBUG + ImGui::Text("%s, %i", EffectHeader->Name, Effect->Index); +#else ImGui::Text(EffectHeader->Name); +#endif ImGui::PopID(); } - if (ChannelHeader.DisplayType == property_display_type_standard) { - if (ImGui::Button("K")) { - // uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, State->MostRecentlySelectedLayer, h); - // Property_AddKeyframe(Memory, Property, State->Frame_Current, ArrayLocation); + if (EffectHeader->DisplayType == effect_display_type_standard) { + if (ChannelHeader.DisplayType == property_display_type_standard) { + if (ImGui::Button("K")) { + Property_AddKeyframe(Memory, F_Properties, Property, State->Frame_Current, ArrayLocation); + } + ImGui::SameLine(); + ImGui::DragScalar(Name, ImGuiDataType_Float, &Property->CurrentValue, Property->ScrubVal, &Property->MinVal, &Property->MaxVal, "%f"); + ImGui_PropertyInteract_Slider(State, Memory, Property, io, WindowMinAbs, WindowMaxAbs, F_Properties); + } else if (ChannelHeader.DisplayType == property_display_type_color) { + if (ImGui::Button("K")) { + Property_AddKeyframe(Memory, F_Properties, Property, State->Frame_Current, ArrayLocation); + } + ImGui::SameLine(); + ImGui::DragScalar(Name, ImGuiDataType_Float, &Property->CurrentValue, Property->ScrubVal, &Property->MinVal, &Property->MaxVal, "%f"); + ImGui_PropertyInteract_Slider(State, Memory, Property, io, WindowMinAbs, WindowMaxAbs, F_Properties); + // if (c == 3) { + // ImGui::ColorEdit4("col", Col, ImGuiColorEditFlags_Float); + // } + } else { + Assert(0); + } + } else if (EffectHeader->DisplayType == effect_display_type_curves) { +#if DEBUG + ImGui::Text("Points (RGBA): %.02f, Points (indiv): %.02f, %.02f, %.02f, %.02f", Effect->ExtraData[0], + Effect->ExtraData[1], Effect->ExtraData[2], Effect->ExtraData[3], Effect->ExtraData[4]); +#endif + if (Property->Identifier == -1) { + Effect_Curves_Init(Effect, Property); + } + uint16 SortedPointStart[MAX_PROPERTIES_PER_EFFECT/5]; + uint32 VisibleChannel = *(uint32 *)&Effect->ExtraData[5]; + Effect_Curves_Sort(Memory, Effect, SortedPointStart, VisibleChannel); + ImGui_CurvesUI(State, Memory, io, Effect, Property, SortedPointStart); + c = EffectHeader->Property_Count; // Causes this loop to only iterate once. + } else if (EffectHeader->DisplayType == effect_display_type_levels) { + ImGui::Text("Levels!"); + uint32 VisibleChannel = *(uint32 *)&Effect->ExtraData[0]; + real32 *P_Left = 0, *P_Mid = 0, *P_Right = 0; + if (VisibleChannel == 0) { + property_channel *Property0 = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[0]); + property_channel *Property1 = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[1]); + property_channel *Property2 = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[2]); + P_Left = &Property0->CurrentValue; + P_Mid = &Property1->CurrentValue; + P_Right = &Property2->CurrentValue; + } else { + property_channel *Property0 = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[3+(VisibleChannel-1)]); + property_channel *Property1 = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[7+(VisibleChannel-1)]); + property_channel *Property2 = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[11+(VisibleChannel-1)]); + P_Left = &Property0->CurrentValue; + P_Mid = &Property1->CurrentValue; + P_Right = &Property2->CurrentValue; + } + ImGui::SliderLevels("1", "2,", "3", (void *)P_Mid, (void *)P_Left, (void *)P_Right); + if (ImGui::IsItemActive()) { + State->UpdateFrame = true; } - ImGui::SameLine(); - ImGui::DragScalar(ChannelHeader.Name, ImGuiDataType_Float, &Property->CurrentValue, Property->ScrubVal, &Property->MinVal, &Property->MaxVal, "%f"); - ImGui_PropertyInteract_Slider(State, Memory, Property, io, WindowMinAbs, WindowMaxAbs, F_Properties); + ImGui_RGBAModeSwitch(State, Memory, io, (uint32 *)&Effect->ExtraData[0]); + c = EffectHeader->Property_Count; } else { Assert(0); } @@ -959,7 +1267,7 @@ ImGui_TransformUI(project_data *File, project_state *State, memory *Memory, ui * History_Entry_Commit(Memory, "Add keyframe"); bezier_point Point = { 1, {(real32)State->Frame_Current, Val[a], -1, 0, 1, 0}, interpolation_type_linear, 0, {0, 0, 0}, 0 }; uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, State->MostRecentlySelectedLayer, h); - Bezier_Add(Memory, Property[a], Point, ArrayLocation); + Bezier_Add(Memory, F_Layers, Property[a], Point, ArrayLocation); History_Entry_End(Memory); } } @@ -1093,7 +1401,6 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, ImGui::Begin("Viewport", &open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); if (ImGui::IsWindowHovered(ImGuiFocusedFlags_ChildWindows)) { - State->SetFocus = true; State->FocusedWindow = focus_viewport; } @@ -1287,7 +1594,7 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, } } - if (ImGui::IsKeyDown(ImGuiKey_Z)) { + if (ImGui::IsKeyDown(ImGuiKey_Z) && ImGui::IsWindowHovered()) { if (IsActive) ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); else @@ -1420,7 +1727,9 @@ ImGui_Timeline_HorizontalIncrementDraw(project_state *State, ui *UI, ImDrawList static void -ImGui_GraphInfo(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray) +ImGui_GraphInfo(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, + sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, + sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray) { bool open = true; ImGui::Begin("Graph info"); @@ -1443,7 +1752,7 @@ ImGui_GraphInfo(project_data *File, project_state *State, memory *Memory, ui *UI uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, i, h); ImGui::PushID(Property); if (ImGui::Selectable(DefaultChannel[h], InfoLocation->IsGraphSelected)) { - Property_DeselectAll(File, Memory, SortedPropertyArray); + Property_DeselectAll(File, State, Memory, SortedCompArray, SortedLayerArray, SortedPropertyInfo, SortedPropertyArray); for (int p = 0; p < Property->Keyframe_Count; p++) { int k = ArrayLocation[p]; bezier_point *Point = Bezier_LookupAddress(Memory, Property, k); @@ -1464,7 +1773,8 @@ ImGui_GraphInfo(project_data *File, project_state *State, memory *Memory, ui *UI static void ImGui_Timeline_DrawKeySheet(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, ImDrawList *draw_list, property_channel *Property, uint16 *ArrayLocation, ImVec2 Increment, ImVec2 TimelineAbsolutePos, ImVec2 GraphPos, ImVec2 TimelineMoveSize, ImVec2 TimelineZoomSize, - ImVec2 TimelineSize, ImVec2 TimelineSizeWithBorder, real32 LayerIncrement, uint16 *SortedPropertyArray) + ImVec2 TimelineSize, ImVec2 TimelineSizeWithBorder, real32 LayerIncrement, + sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray) { ImGui::PushID(Property); @@ -1531,7 +1841,7 @@ ImGui_Timeline_DrawKeySheet(project_data *File, project_state *State, memory *Me } if (IsItemDeactivated) { - Bezier_Commit(File, State, Memory, SortedPropertyArray); + Bezier_Commit(File, State, Memory, SortedCompArray, SortedLayerArray, SortedPropertyInfo, SortedPropertyArray); } draw_list->AddCircleFilled(Keyframe_ScreenPos, 4, PointCol); @@ -1604,8 +1914,6 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor Assert(InfoLocation->MinYIndex < Property->Keyframe_Count); Assert(InfoLocation->MaxYIndex < Property->Keyframe_Count); Assert(MaxY >= MinY); - if (MaxY <= MinY) - int p = 0; real32 Y_Increment = (MaxY - MinY) ? (1 / (MaxY - MinY)) : 0.5; real32 GraphScale = 0; @@ -1752,7 +2060,7 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem int32 Frame_End = Layer->Frame_End; real32 Vertical_Offset = SortEntry.SortedOffset + DisplayOffset; - Layer_Evaluate_Display(Layer, SortedLayerArray, SortedCompArray, SortedLayerInfo, i, &DisplayOffset); + Layer_Evaluate_Display(State, Memory, Layer, SortedPropertyInfo, SortedPropertyArray, SortedLayerArray, SortedCompArray, SortedLayerInfo, i, &DisplayOffset); if (Layer->IsSelected) Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End); @@ -2004,15 +2312,25 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem // Keyframe view uint32 Channel = 0; - for (int h = 0; h < AmountOf(Layer->Property); h++) { - property_channel *Property = &Layer->Property[h]; + + sorted_property_info *InfoLocation = SortedPropertyInfo + SortedLayerInfo->SortedPropertyStart; + uint16 *ArrayLocation = SortedPropertyArray + SortedLayerInfo->SortedKeyframeStart; + int h = 0, c = 0, p = 0; + property_channel *Property = NULL; + block_effect *Effect = NULL; + while (Layer_LoopChannels(State, Memory, &InfoLocation, &ArrayLocation, Layer, &Property, &Effect, &h, &c, &p)) + { if (Property->IsToggled) { - sorted_property_info *InfoLocation = Property_GetSortedInfo(SortedPropertyInfo, i, h); - uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, i, h); - ImVec2 GraphPos(TimelineAbsolutePos.x, Layer_ScreenPos_Min.y + (Layer_ScreenSize.y * 2) + (Layer_ScreenSize.y * Channel)); + ImVec2 GraphMinPos = ImVec2(TimelineAbsolutePos.x, Layer_ScreenPos_Min.y + Layer_ScreenSize.y + (Layer_ScreenSize.y * Channel)); + ImVec2 GraphPos = GraphMinPos + ImVec2(0, Layer_ScreenSize.y); + ImVec2 GraphMinBounds = GraphMinPos + ImVec2(0, Layer_ScreenSize.y * 0.5); + ImVec2 GraphMaxBounds = GraphMinBounds + ImVec2(TimelineSizeWithBorder.x, Layer_ScreenSize.y); + uint32 col = (Channel % 2) ? IM_COL32(50, 50, 50, 255) : IM_COL32(50, 50, 50, 128); + draw_list->AddRectFilled(GraphMinBounds, GraphMaxBounds, col); ImGui_Timeline_DrawKeySheet(File, State, Memory, UI, io, draw_list, Property, ArrayLocation, Increment, TimelineAbsolutePos, GraphPos, TimelineMoveSize, TimelineZoomSize, - TimelineSize, TimelineSizeWithBorder, LayerIncrement, SortedPropertyArray); + TimelineSize, TimelineSizeWithBorder, LayerIncrement, + SortedCompArray, SortedLayerArray, SortedPropertyInfo, SortedPropertyArray); Channel++; } } @@ -2075,7 +2393,6 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImGui::Begin("Timeline", NULL); if (ImGui::IsWindowHovered(ImGuiFocusedFlags_ChildWindows)) { - State->SetFocus = true; State->FocusedWindow = focus_timeline; } @@ -2348,7 +2665,7 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, if (State->Interact_Active == interact_type_keyframe_move || State->Interact_Active == interact_type_keyframe_rotate || State->Interact_Active == interact_type_keyframe_scale) { - Bezier_Commit(File, State, Memory, SortedPropertyArray); + Bezier_Commit(File, State, Memory, SortedCompArray, SortedLayerArray, SortedPropertyInfo, SortedPropertyArray); } State->BoxSelect = true; } @@ -2520,13 +2837,11 @@ ImGui_Popups(project_data *File, project_state *State, ui *UI, memory *Memory, I { ImGui::OpenPopup("Save as"); ImGui::SetKeyboardFocusHere(); - State->SetFocus = 0; } break; case popup_keybinds: { ImGui::OpenPopup("Keybinds"); ImGui::SetKeyboardFocusHere(); - State->SetFocus = 0; } break; default: { @@ -2575,6 +2890,9 @@ ImGui_ProcessInputs(project_data *File, project_state *State, ui *UI, memory *Me State->Brush.EraseMode ^= 1; } } + if (ImGui::IsKeyPressed(ImGuiKey_U)) { + State->HotkeyInput = hotkey_togglechannels; + } if (ImGui::IsKeyPressed(ImGuiKey_X)) { if (State->TimelineMode == timeline_mode_graph && State->Interact_Active == interact_type_keyframe_move) { if (State->Interact_Modifier != 1) @@ -2603,14 +2921,15 @@ ImGui_ProcessInputs(project_data *File, project_state *State, ui *UI, memory *Me } // NOTE(fox): File data not tracked on undo tree! if (ImGui::IsKeyPressed(ImGuiKey_N)) { - block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, File->PrincipalCompIndex); - if (MainComp->Frame_Start < State->Frame_Current) - MainComp->Frame_End = State->Frame_Current; - } - if (ImGui::IsKeyPressed(ImGuiKey_B)) { - block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, File->PrincipalCompIndex); - if (MainComp->Frame_End > State->Frame_Current) - MainComp->Frame_Start = State->Frame_Current; + if (io.KeyShift) { + block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, File->PrincipalCompIndex); + if (MainComp->Frame_Start < State->Frame_Current) + MainComp->Frame_End = State->Frame_Current; + } else { + block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, File->PrincipalCompIndex); + if (MainComp->Frame_End > State->Frame_Current) + MainComp->Frame_Start = State->Frame_Current; + } } if (ImGui::IsKeyPressed(ImGuiKey_Tab)) { State->TimelineMode = (State->TimelineMode == timeline_mode_default) ? timeline_mode_graph : timeline_mode_default; @@ -2618,6 +2937,9 @@ ImGui_ProcessInputs(project_data *File, project_state *State, ui *UI, memory *Me UI->GraphMoveSize = ImVec2(0, 0); } if (!io.KeyCtrl) { + // NOTE(fox): Checking IsWindowHovered seems to be all we need to do to + // make per-window hotkeys work; setting it as the focused window causes + // problems with popups. if (State->FocusedWindow == focus_timeline) { if (State->TimelineMode == timeline_mode_default) { if (ImGui::IsKeyPressed(ImGuiKey_G)) { @@ -2857,8 +3179,7 @@ ImGui_EffectsPanel(project_data *File, project_state *State, memory *Memory, ui header_effect *EffectHeader = &State->Effect[i]; if (State->filter.PassFilter(EffectHeader->Name)) { if (EffectSel == p && State->MostRecentlySelectedLayer != -1) { - Assert(0); - // AddEffect(File->Layer[State->MostRecentlySelectedLayer], Memory, i); + Effect_Add(File, State, Memory, i); State->UpdateFrame = true; } p++; diff --git a/package.sh b/package.sh index 01868b1..f1861b4 100755 --- a/package.sh +++ b/package.sh @@ -2,6 +2,7 @@ # simple helper to zip up the builds cd bin +mkdir zip # windows mkdir real2d_windows @@ -17,4 +18,7 @@ zip -r zip/real2d_m1_mac.zip real_arm.app zip -r zip/real2d_x86_linux.zip real2d_x86_linux zip -r zip/real2d_arm_linux.zip real2d_arm_linux -rsync -avz bin/zip/* root@foxcam.net:/var/www/foxcam/bin/ +rsync -avz zip/* root@foxcam.net:/var/www/foxcam/bin/ + +rm -r zip +rm -r real2d_windows -- cgit v1.2.3