summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFox Caminiti <fox@foxcam.net>2022-12-03 21:57:53 -0500
committerFox Caminiti <fox@foxcam.net>2022-12-03 21:57:53 -0500
commited27ab2e6bbe40120702dcc57e9b21434bfb4944 (patch)
treeb53af27a4e17855be6336e1f82bd48d91ef711ca
parentdc0d4a23fdbddef51d5e026f2eefef1731c4e338 (diff)
v2.0, effects functional
-rw-r--r--bezier.cpp1
-rw-r--r--createcalls.cpp328
-rw-r--r--defines.h2
-rw-r--r--effects.cpp46
-rw-r--r--effects_constructors.cpp31
-rw-r--r--effects_gl.cpp31
-rw-r--r--effects_software.cpp28
-rw-r--r--functions.h5
-rw-r--r--imgui_ops.h10
-rw-r--r--keybinds.h6
-rw-r--r--main.cpp29
-rw-r--r--main.h7
-rw-r--r--my_imgui_widgets.cpp403
-rwxr-xr-xpackage.sh6
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,11 +624,13 @@ 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
@@ -36,6 +36,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,
sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray)
@@ -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