summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFox Caminiti <fox@foxcam.net>2022-10-25 23:47:17 -0400
committerFox Caminiti <fox@foxcam.net>2022-10-25 23:47:17 -0400
commitbf01cea7274d9ac8ae13fd447c8568c95da31614 (patch)
treeed3b9fb4ae56f1e19cf3514280249954b1043070
parent87c3fbb37141827622eeadb89189c267ed4baf87 (diff)
graph development
-rw-r--r--bezier.cpp37
-rw-r--r--createcalls.cpp21
-rw-r--r--functions.h1
-rw-r--r--main.cpp125
-rw-r--r--main.h22
-rw-r--r--my_imgui_widgets.cpp411
6 files changed, 440 insertions, 177 deletions
diff --git a/bezier.cpp b/bezier.cpp
index e5f9bf9..42ed04d 100644
--- a/bezier.cpp
+++ b/bezier.cpp
@@ -1,3 +1,39 @@
+static real32 Tau = 0.9; // tension
+
+static real32
+Bezier_SolveYForX(v2 Point_P0, v2 Point_P1, v2 Point_P2, v2 Point_P3, real32 TargetX) {
+
+ real32 Y = 0;
+
+ v2 m1 = (Point_P2 - Point_P0) / (2 * Tau);
+ v2 m2 = (Point_P3 - Point_P1) / (2 * Tau);
+
+ real32 Precision = 0.001;
+ real32 t = (TargetX - Point_P0.x) / (Point_P3.x - Point_P0.x);
+
+ for (;;) {
+ real32 t2 = t * t;
+ real32 t3 = t2 * t;
+ real32 mt = 1-t;
+ real32 mt2 = mt * mt;
+ real32 mt3 = mt2 * mt;
+ v2 Point = (Point_P0 * mt3) + (3 * Point_P1 * mt2 * t) + (3 * Point_P2 * mt * t2) + (Point_P3 * t3);
+
+ bool32 Cond1 = (Point.x <= (TargetX - Precision));
+ bool32 Cond2 = (Point.x >= (TargetX + Precision));
+
+ if (Cond1 || Cond2) {
+ t = t * TargetX / Point.x;
+ } else {
+ Y = Point.y;
+ break;
+ }
+ }
+
+ return Y;
+}
+
+#if 0
// A modified version of the bezier code in ImGui with extra features for bitmap and path interaction.
// Function to convert a ratio back into a point for the bezier handles.
@@ -307,3 +343,4 @@ void Mask_TriangulateAndRasterize(memory *Memory, project_layer *Layer, mask *Ma
GL_RasterizeShape(Layer, Mask);
}
+#endif
diff --git a/createcalls.cpp b/createcalls.cpp
index c2122c2..d0ca03e 100644
--- a/createcalls.cpp
+++ b/createcalls.cpp
@@ -65,6 +65,27 @@ Property_GetInfo(memory *Memory, property_channel *Property)
return PropertyInfo;
}
+static graph_info
+Graph_GetInfo(project_data *File, memory *Memory)
+{
+ graph_info GraphInfo = {};
+ for (int a = 0; a < File->Layer_Count; a++) {
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, a);
+ if (!Layer->IsSelected)
+ continue;
+ for (int h = 0; h < AmountOf(Layer->Property); h++) {
+ property_channel *Property = &Layer->Property[h];
+ if (Property->Keyframe_Count) {
+ property_info PropertyInfo = Property_GetInfo(Memory, Property);
+ GraphInfo.MinVal = (PropertyInfo.MinVal < GraphInfo.MinVal) ? PropertyInfo.MinVal : GraphInfo.MinVal;
+ GraphInfo.MaxVal = (PropertyInfo.MaxVal > GraphInfo.MaxVal) ? PropertyInfo.MaxVal : GraphInfo.MaxVal;
+ }
+ }
+ GraphInfo.LowestOffset = (Layer->Vertical_Offset > GraphInfo.LowestOffset) ? Layer->Vertical_Offset : GraphInfo.LowestOffset;
+ }
+ return GraphInfo;
+}
+
static void
Layer_Interact_Evaluate(memory *Memory, project_state *State, uint16 Layer_Index_Physical, sorted_comp_info SortedCompInfo, sorted_layer *SortedLayerInfo,
int32 *Frame_Start, int32 *Frame_End, real32 *Vertical_Offset)
diff --git a/functions.h b/functions.h
index 4fe5a0e..07cfc25 100644
--- a/functions.h
+++ b/functions.h
@@ -5,6 +5,7 @@ static void Arbitrary_Zero(uint8 *Address_Write, uint64 Size);
static void Arbitrary_SwapData(memory *Memory, uint8 *Address_0, uint8 *Address_1, uint64 Size);
static void Arbitrary_ShiftData(uint8 *Address_Start, uint8 *Address_End, uint64 ShiftAmount, int32 Direction);
+static real32 Bezier_SolveYForX(v2 Point_P0, v2 Point_P1, v2 Point_P2, v2 Point_P3, real32 X);
# if 0
// Buffer management
diff --git a/main.cpp b/main.cpp
index bdd4786..74a9e4a 100644
--- a/main.cpp
+++ b/main.cpp
@@ -70,11 +70,11 @@ static uint32 RandomGlobalIncrement = 0;
#include "my_imgui_widgets.cpp"
#include "prenderer.cpp"
#include "gl_calls.cpp"
+#include "bezier.cpp"
#if 0
#include "effects.cpp"
#include "keyframes.cpp"
#include "layer.cpp"
-#include "bezier.cpp"
#include "bitmap_calls.cpp"
#endif
@@ -226,6 +226,38 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
// for (int a = 0; a < Layer->Block_Effect_Count; a++) {
// }
+ property_channel *Property = &Layer->x;
+
+ if (Property->Keyframe_Count) {
+ bezier_point *FirstPoint = Bezier_Lookup(Memory, Property, 0);
+ bezier_point *LastPoint = Bezier_Lookup(Memory, Property, Property->Keyframe_Count - 1);
+ if (FirstPoint->Pos[0].x >= State->Frame_Current) {
+ Property->CurrentValue = FirstPoint->Pos[0].y;
+ } else if (LastPoint->Pos[0].x <= State->Frame_Current) {
+ Property->CurrentValue = LastPoint->Pos[0].y;
+ } else {
+ int KeyframeIndex = 0;
+ for (;;) {
+ bezier_point *Point = Bezier_Lookup(Memory, Property, KeyframeIndex + 1);
+ if (Point->Pos[0].x >= State->Frame_Current)
+ break;
+ KeyframeIndex++;
+ }
+ bezier_point *Point = Bezier_Lookup(Memory, Property, KeyframeIndex);
+ bezier_point *NextPoint = Bezier_Lookup(Memory, Property, KeyframeIndex + 1);
+ Property->CurrentValue = Bezier_SolveYForX(Point->Pos[0], Point->Pos[0] + Point->Pos[2], NextPoint->Pos[0] + NextPoint->Pos[1], NextPoint->Pos[0], State->Frame_Current);
+ }
+ }
+
+ /*
+ for (int h = 0; h < AmountOf(Layer->Property); h++) {
+ property_channel *Property = &Layer->Property[h];
+ if (Property->Keyframe_Count) {
+ Property->CurrentValue = State->Frame_Current * 2;
+ }
+ }
+ */
+
transform_info T = Transform_Calculate(State, Memory, File, Layer, Comp);
T.SourceBuffer = BitmapAddress;
rectangle RenderRegion = {0, 0, Comp->Width, Comp->Height};
@@ -233,7 +265,7 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
bool32 IsRendering = true;
Renderer_Start((void *)&T, CompBuffer, RenderRegion);
while (IsRendering) {
- SDL_Delay(2);
+ SDL_Delay(1);
Renderer_Check(&IsRendering);
// TODO(fox): Make interruptable if the render time gets too long.
}
@@ -328,6 +360,7 @@ int main(int argc, char *argv[]) {
File->Occupied = 1;
ui UI = {};
+ UI.Test = ImDrawListSplitter();
block_composition *MainComp = (block_composition *)Memory_Block_AllocateAddress(&Memory, F_Precomps);
@@ -369,6 +402,7 @@ int main(int argc, char *argv[]) {
Layer->Col[1] = 0;
Layer->Col[2] = 0;
Layer->Block_Composition_Index = 0;
+ Layer->IsSelected = true;
property_channel *Property = &Layer->x;
Property->Block_Bezier_Index[0] = Memory_Block_AllocateNew(&Memory, F_Bezier);
@@ -389,6 +423,7 @@ int main(int argc, char *argv[]) {
Bezier->Point[0].Type = interpolation_type_bezier;
Bezier->Point[1].Type = interpolation_type_bezier;
Bezier->Point[2].Type = interpolation_type_bezier;
+ Bezier->Point[1].IsSelected = true;
Property->Keyframe_Count = 3;
property_channel *Property2 = &Layer->opacity;
@@ -402,7 +437,6 @@ int main(int argc, char *argv[]) {
Bezier2->Point[1].Pos[0] = V2(20, 1);
Property2->Keyframe_Count = 2;
- /*
property_channel *Property3 = &Layer->y;
Property3->Block_Bezier_Index[0] = Memory_Block_AllocateNew(&Memory, F_Bezier);
Property3->Block_Bezier_Count = 1;
@@ -423,7 +457,6 @@ int main(int argc, char *argv[]) {
Bezier3->Point[1].Type = interpolation_type_bezier;
Bezier3->Point[2].Type = interpolation_type_bezier;
Property3->Keyframe_Count = 3;
- */
}
// {
// Layer_CreateFromSource(File, State, &Memory, SourceIndex, MainComp->Frame_End);
@@ -439,15 +472,75 @@ int main(int argc, char *argv[]) {
{
uint16 SourceIndex = Source_Generate(File, State, &Memory, (void *)"../asset/b.jpg");
block_source *Source = (block_source *)Memory_Block_AddressAtIndex(&Memory, F_Sources, 1);
- // {
- // Layer_CreateFromSource(File, State, &Memory, SourceIndex, MainComp->Frame_End);
- // block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(&Memory, F_Layers, File->Layer_Count - 1);
- // Layer->Vertical_Offset = 5;
- // Layer->Col[0] = 0;
- // Layer->Col[1] = 0;
- // Layer->Col[2] = 1;
- // Layer->Block_Composition_Index = 0;
- // }
+ {
+ Layer_CreateFromSource(File, State, &Memory, SourceIndex, MainComp->Frame_End);
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(&Memory, F_Layers, File->Layer_Count - 1);
+ Layer->Vertical_Offset = 5;
+ Layer->Col[0] = 0;
+ Layer->Col[1] = 0;
+ Layer->Col[2] = 1;
+ Layer->Block_Composition_Index = 0;
+ Layer->IsSelected = true;
+
+ property_channel *Property = &Layer->x;
+ Property->Block_Bezier_Index[0] = Memory_Block_AllocateNew(&Memory, F_Bezier);
+ Property->Block_Bezier_Count = 1;
+
+ block_bezier *Bezier = (block_bezier *)Memory_Block_AddressAtIndex(&Memory, F_Bezier, Property->Block_Bezier_Index[0]);
+ Bezier->Occupied = 1;
+
+ Bezier->Point[0].Pos[0] = V2(30, 0);
+ Bezier->Point[1].Pos[0] = V2(33, 250);
+ Bezier->Point[2].Pos[0] = V2(35, -50);
+ Bezier->Point[3].Pos[0] = V2(55, 0);
+ Bezier->Point[0].Pos[1] = V2(-1, 0);
+ Bezier->Point[1].Pos[1] = V2(-1, 0);
+ Bezier->Point[2].Pos[1] = V2(-1, 0);
+ Bezier->Point[3].Pos[1] = V2(-1, 0);
+ Bezier->Point[0].Pos[2] = V2(1, 0);
+ Bezier->Point[1].Pos[2] = V2(1, 0);
+ Bezier->Point[2].Pos[2] = V2(1, 0);
+ Bezier->Point[3].Pos[2] = V2(1, 0);
+ Bezier->Point[0].Type = interpolation_type_bezier;
+ Bezier->Point[1].Type = interpolation_type_bezier;
+ Bezier->Point[2].Type = interpolation_type_bezier;
+ Bezier->Point[3].Type = interpolation_type_bezier;
+ Property->Keyframe_Count = 4;
+
+ property_channel *Property2 = &Layer->opacity;
+ Property2->Block_Bezier_Index[0] = Memory_Block_AllocateNew(&Memory, F_Bezier);
+ Property2->Block_Bezier_Count = 1;
+
+ block_bezier *Bezier2 = (block_bezier *)Memory_Block_AddressAtIndex(&Memory, F_Bezier, Property2->Block_Bezier_Index[0]);
+ Bezier2->Occupied = 1;
+
+ Bezier2->Point[0].Pos[0] = V2(25, 1);
+ Bezier2->Point[1].Pos[0] = V2(40, 0);
+ Property2->Keyframe_Count = 2;
+
+ /*
+ property_channel *Property3 = &Layer->y;
+ Property3->Block_Bezier_Index[0] = Memory_Block_AllocateNew(&Memory, F_Bezier);
+ Property3->Block_Bezier_Count = 1;
+
+ block_bezier *Bezier3 = (block_bezier *)Memory_Block_AddressAtIndex(&Memory, F_Bezier, Property3->Block_Bezier_Index[0]);
+ Bezier3->Occupied = 1;
+
+ Bezier3->Point[0].Pos[0] = V2(0, -20);
+ Bezier3->Point[1].Pos[0] = V2(10, 300);
+ Bezier3->Point[2].Pos[0] = V2(20, 100);
+ Bezier3->Point[0].Pos[1] = V2(-4, 0);
+ Bezier3->Point[1].Pos[1] = V2(-4, 0);
+ Bezier3->Point[2].Pos[1] = V2(-4, 0);
+ Bezier3->Point[0].Pos[2] = V2(4, 0);
+ Bezier3->Point[1].Pos[2] = V2(4, 0);
+ Bezier3->Point[2].Pos[2] = V2(4, 0);
+ Bezier3->Point[0].Type = interpolation_type_bezier;
+ Bezier3->Point[1].Type = interpolation_type_bezier;
+ Bezier3->Point[2].Type = interpolation_type_bezier;
+ Property3->Keyframe_Count = 3;
+ */
+ }
}
{
@@ -609,6 +702,12 @@ int main(int argc, char *argv[]) {
{
Main_InputTest(File, State, &Memory, &UI, window, textureID);
+ if (State->IsPlaying) {
+ block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(&Memory, F_Precomps, File->PrincipalCompIndex);
+ State->Frame_Current = ((State->Frame_Current + 1) >= MainComp->Frame_Count) ? 0 : State->Frame_Current + 1;
+ State->UpdateFrame = true;
+ }
+
if (State->UpdateFrame) {
Main_Renderer(File, State, &Memory, window, textureID, io);
}
diff --git a/main.h b/main.h
index cfdb816..00d97c9 100644
--- a/main.h
+++ b/main.h
@@ -77,10 +77,11 @@ enum interpolation_type
};
struct bezier_point {
+ uint8 Occupied;
v2 Pos[3];
interpolation_type Type;
- uint16 ImguiID;
- uint8 IsSelected;
+ uint8 IsSelected; //[3]
+ uint8 Color;
};
struct block_bezier {
@@ -125,15 +126,25 @@ struct sorted_layer
uint16 Block_Layer_Index;
};
+enum timeline_mode
+{
+ timeline_mode_default,
+ timeline_mode_graph
+};
+
struct ui
{
ImVec2 CompZoom; // In screen pixels, not percentage.
ImVec2 CompPos;
+ ImDrawListSplitter Test;
+
// Under 1 is zoomed in!
ImVec2 TimelinePercentZoomed;
ImVec2 TimelinePercentOffset;
+ timeline_mode TimelineMode = timeline_mode_graph;
+
bool32 BoxSelect;
ImVec2 DragDelta_Prev; // TODO(fox): Make native ImGui?
@@ -267,6 +278,13 @@ struct property_header
real32 MaxVal;
};
+struct graph_info
+{
+ real32 MinVal = FLT_MAX;
+ real32 MaxVal = FLT_MIN;
+ real32 LowestOffset = FLT_MIN;
+};
+
struct property_info
{
real32 MinVal = FLT_MAX;
diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp
index 9589abd..545af4e 100644
--- a/my_imgui_widgets.cpp
+++ b/my_imgui_widgets.cpp
@@ -157,14 +157,12 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory,
}
static void
-ImGui_TimelineHorizontalIncrementDraw(ui *UI, ImDrawList *draw_list, ImVec2 TimelineSizeWithBorder, ImVec2 TimelineAbsolutePos, block_composition MainComp)
+ImGui_TimelineHorizontalIncrementDraw(ui *UI, ImDrawList *draw_list, ImVec2 TimelineSizeWithBorder, ImVec2 TimelineAbsolutePos, block_composition MainComp,
+ ImVec2 TimelineZoomSize, ImVec2 TimelineMoveSize)
{
uint32 LineColor = IM_COL32(200, 200, 200, 40);
- real32 TimelineZoomSize = TimelineSizeWithBorder.x / UI->TimelinePercentZoomed.x ;
- real32 TimelineMoveSize = TimelineSizeWithBorder.x * UI->TimelinePercentOffset.x / UI->TimelinePercentZoomed.x;
-
- Assert(TimelineZoomSize > 0.0f);
+ Assert(TimelineZoomSize.x > 0.0f);
real32 x = 0;
bool32 RightmostEdge = false;
@@ -175,7 +173,7 @@ ImGui_TimelineHorizontalIncrementDraw(ui *UI, ImDrawList *draw_list, ImVec2 Time
Increment *= 2;
while (!RightmostEdge) {
- ImVec2 Min = ImVec2(TimelineAbsolutePos.x + TimelineMoveSize + x*TimelineZoomSize, TimelineAbsolutePos.y);
+ ImVec2 Min = ImVec2(TimelineAbsolutePos.x + TimelineMoveSize.x + x*TimelineZoomSize.x, TimelineAbsolutePos.y);
ImVec2 Max = ImVec2(Min.x + 2, TimelineAbsolutePos.y + TimelineSizeWithBorder.y);
if (Min.x < TimelineAbsolutePos.x + TimelineSizeWithBorder.x) {
draw_list->AddLine(Min, Max, LineColor);
@@ -196,32 +194,53 @@ ImGui_TimelineHorizontalIncrementDraw(ui *UI, ImDrawList *draw_list, ImVec2 Time
}
-
static void
-ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, ImDrawList *draw_list, uint16 CompIndex,
- ImVec2 Increment, ImVec2 TimelineAbsolutePos, ImVec2 TimelineMoveSize, ImVec2 TimelineZoomSize,
- ImVec2 TimelineSize, ImVec2 TimelineSizeWithBorder, real32 LayerIncrement,
- sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray)
+ImGui_GraphInfo(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io)
{
- block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, CompIndex);
- sorted_comp_info SortedCompInfo = SortedCompArray[CompIndex];
- sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, SortedCompArray, CompIndex);
-
- ImGui::PushID(CompIndex);
+ bool open = true;
+ ImGui::Begin("Graph info", &open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
- for (int i = 0; i < SortedCompInfo.LayerCount; i++)
+ for (int a = 0; a < File->Layer_Count; a++)
{
- ImGui::PushID(i);
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, a);
+ if (!Layer->IsSelected)
+ continue;
- 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_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, Layer->Block_String_Index);
+ ImGui::Text(String->Char);
+
+ ImGui::PushID(a);
+ for (int h = 0; h < AmountOf(Layer->Property); h++) {
+ property_channel *Property = &Layer->Property[h];
+ if (Property->Keyframe_Count) {
+ ImGui::PushID(Property);
+ ImGui::Text(Property->Name);
+ ImGui::PopID();
+ }
+ }
+
+ ImGui::PopID();
+ }
+
+ ImGui::End();
+}
+
+static void
+ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, ImDrawList *draw_list, graph_info GraphInfo,
+ ImVec2 Increment, ImVec2 TimelineAbsolutePos, ImVec2 TimelineMoveSize, ImVec2 TimelineZoomSize,
+ ImVec2 TimelineSize, ImVec2 TimelineSizeWithBorder, real32 LayerIncrement)
+{
+ UI->Test.Split(draw_list, 2);
+
+ for (int a = 0; a < File->Layer_Count; a++)
+ {
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, a);
+ if (!Layer->IsSelected)
+ continue;
int32 Frame_Start = Layer->Frame_Start;
int32 Frame_End = Layer->Frame_End;
- real32 Vertical_Offset = Layer->Vertical_Offset;
- if (Layer->IsSelected)
- Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End, &Vertical_Offset);
+ real32 Vertical_Offset = GraphInfo.LowestOffset; // Layer->Vertical_Offset;
ImVec2 Layer_LocalPos = ImVec2(Frame_Start, Vertical_Offset);
ImVec2 Layer_LocalSize = ImVec2(Frame_End - Frame_Start, Layer->Vertical_Height);
@@ -231,33 +250,166 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem
ImVec2 Layer_ScreenPos_Max = TimelineAbsolutePos + TimelineMoveSize + ((Layer_LocalPos_Ratio + Layer_LocalSize_Ratio) * TimelineZoomSize);
ImVec2 Layer_ScreenSize = Layer_ScreenPos_Max - Layer_ScreenPos_Min;
- if (UI->BoxSelect) {
- bool32 Test = 0;
- if (io.MouseClickedPos[0].y < io.MousePos.y)
- Test = (Layer_ScreenPos_Min.y >= io.MouseClickedPos[0].y && Layer_ScreenPos_Min.y <= io.MousePos.y);
- else
- Test = (Layer_ScreenPos_Max.y <= io.MouseClickedPos[0].y && Layer_ScreenPos_Max.y >= io.MousePos.y);
+ ImGui::PushID(a);
- if (Test) {
- if (!Layer->IsSelected) {
- Layer->IsSelected = true;
+ ImU32 col = IM_COL32(255, 255, 255, 255);
+
+ for (int h = 0; h < AmountOf(Layer->Property); h++) {
+ property_channel *Property = &Layer->Property[h];
+ ImGui::PushID(Property);
+ if (Property->Keyframe_Count) {
+ property_info PropertyInfo = Property_GetInfo(Memory, Property);
+ real32 Y_Increment = 1 / (GraphInfo.MaxVal - GraphInfo.MinVal);
+ bezier_point *PointAddress[2] = {};
+ ImVec2 Keyframe_ScreenPos[6] = {};
+ for (int k = 0; k < Property->Keyframe_Count; k++) {
+ int Idx = (k % 2);
+ int NewIdx = Idx * 3;
+ int OldIdx = (NewIdx == 3) ? 0 : 3;
+ PointAddress[Idx] = Bezier_Lookup(Memory, Property, k);
+ bezier_point *Point = PointAddress[Idx];
+
+ ImVec2 Keyframe_LocalPos[3] = { V2(Point->Pos[0]), V2(Point->Pos[0] + Point->Pos[1]), V2(Point->Pos[0] + Point->Pos[2]) };
+ ImVec2 Keyframe_LocalPos_Ratio[3];
+ for (int b = 0; b < 3; b++) {
+ Keyframe_LocalPos_Ratio[b] = (Keyframe_LocalPos[b] - ImVec2(0, GraphInfo.MinVal)) * ImVec2(Increment.x, Y_Increment);
+ Keyframe_ScreenPos[NewIdx + b] = Layer_ScreenPos_Min + ((ImVec2(1, -1) * Keyframe_LocalPos_Ratio[b] + ImVec2(0, 0.5)) * TimelineZoomSize) + ImVec2(0, Layer_ScreenSize.y/2);
+ }
+
+ UI->Test.SetCurrentChannel(draw_list, 1);
+
+ ImU32 PointCol = (Point->IsSelected) ? IM_COL32(255, 128, 0, 255) : IM_COL32(25 ,25, 25, 255);
+ draw_list->AddCircleFilled(Keyframe_ScreenPos[NewIdx], 4, PointCol);
+
+ if (Point->IsSelected) {
+ draw_list->AddCircleFilled(Keyframe_ScreenPos[NewIdx+1], 4, PointCol);
+ draw_list->AddCircleFilled(Keyframe_ScreenPos[NewIdx+2], 4, PointCol);
+ draw_list->AddLine(Keyframe_ScreenPos[NewIdx], Keyframe_ScreenPos[NewIdx+1], PointCol, 1.0f);
+ draw_list->AddLine(Keyframe_ScreenPos[NewIdx], Keyframe_ScreenPos[NewIdx+2], PointCol, 1.0f);
+ }
+
+ UI->Test.SetCurrentChannel(draw_list, 0);
+
+ if (k != 0) {
+ if (PointAddress[0]->Type == interpolation_type_bezier && PointAddress[1]->Type == interpolation_type_bezier) {
+ draw_list->AddBezierCubic(Keyframe_ScreenPos[OldIdx], Keyframe_ScreenPos[OldIdx + 2],
+ Keyframe_ScreenPos[NewIdx + 1], Keyframe_ScreenPos[NewIdx], col, 1.0f, 0);
+ } else {
+ draw_list->AddLine(Keyframe_ScreenPos[0], Keyframe_ScreenPos[3], col, 1.0f);
+ }
+ }
}
- } else if (!io.KeyShift) {
- Layer->IsSelected = false;
}
+ ImGui::PopID();
}
+ ImGui::PopID();
+ }
+ UI->Test.Merge(draw_list);
+}
+
+
+static void
+ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, ImDrawList *draw_list, uint16 CompIndex,
+ ImVec2 Increment, ImVec2 TimelineAbsolutePos, ImVec2 TimelineMoveSize, ImVec2 TimelineZoomSize,
+ ImVec2 TimelineSize, ImVec2 TimelineSizeWithBorder, real32 LayerIncrement,
+ sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray)
+{
+ block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, CompIndex);
+ sorted_comp_info SortedCompInfo = SortedCompArray[CompIndex];
+ sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, SortedCompArray, CompIndex);
+
+ ImGui::PushID(CompIndex);
- ImVec2 ResizeSize = ImVec2(Increment.x * 0.45 * TimelineZoomSize.x, Layer_ScreenSize.y);
- ImVec2 ResizePos[2] = { Layer_ScreenPos_Min, ImVec2(Layer_ScreenPos_Max.x - ResizeSize.x, Layer_ScreenPos_Min.y) };
- for (int b = 0; b < 2; b++) {
- ImGui::PushID(b);
- ImGui::SetCursorScreenPos(ResizePos[b]);
- ImGui::Button("##layer_resize", ResizeSize);
+ if (UI->TimelineMode == timeline_mode_default) {
- if (ImGui::IsItemHovered()) {
- ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
+ for (int i = 0; i < SortedCompInfo.LayerCount; i++)
+ {
+ sorted_layer SortEntry = SortedLayerInfo[i];
+ uint32 Index_Physical = SortEntry.Block_Layer_Index;
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical);
+
+ int32 Frame_Start = Layer->Frame_Start;
+ int32 Frame_End = Layer->Frame_End;
+ real32 Vertical_Offset = Layer->Vertical_Offset;
+ if (Layer->IsSelected)
+ Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End, &Vertical_Offset);
+ ImVec2 Layer_LocalPos = ImVec2(Frame_Start, Vertical_Offset);
+ ImVec2 Layer_LocalSize = ImVec2(Frame_End - Frame_Start, Layer->Vertical_Height);
+
+ ImVec2 Layer_LocalPos_Ratio = (Layer_LocalPos * Increment);
+ ImVec2 Layer_LocalSize_Ratio = Layer_LocalSize * Increment;
+ ImVec2 Layer_ScreenPos_Min = TimelineAbsolutePos + TimelineMoveSize + (Layer_LocalPos_Ratio * TimelineZoomSize);
+ ImVec2 Layer_ScreenPos_Max = TimelineAbsolutePos + TimelineMoveSize + ((Layer_LocalPos_Ratio + Layer_LocalSize_Ratio) * TimelineZoomSize);
+ ImVec2 Layer_ScreenSize = Layer_ScreenPos_Max - Layer_ScreenPos_Min;
+
+ ImGui::PushID(i);
+
+ if (UI->BoxSelect && UI->TimelineMode == timeline_mode_default) {
+ bool32 Test = 0;
+ if (io.MouseClickedPos[0].y < io.MousePos.y)
+ Test = (Layer_ScreenPos_Min.y >= io.MouseClickedPos[0].y && Layer_ScreenPos_Min.y <= io.MousePos.y);
+ else
+ Test = (Layer_ScreenPos_Max.y <= io.MouseClickedPos[0].y && Layer_ScreenPos_Max.y >= io.MousePos.y);
+
+ if (Test) {
+ if (!Layer->IsSelected) {
+ Layer->IsSelected = true;
+ }
+ } else if (!io.KeyShift) {
+ Layer->IsSelected = false;
+ }
+ }
+
+
+ ImVec2 ResizeSize = ImVec2(Increment.x * 0.45 * TimelineZoomSize.x, Layer_ScreenSize.y);
+ ImVec2 ResizePos[2] = { Layer_ScreenPos_Min, ImVec2(Layer_ScreenPos_Max.x - ResizeSize.x, Layer_ScreenPos_Min.y) };
+ for (int b = 0; b < 2; b++) {
+ ImGui::PushID(b);
+ ImGui::SetCursorScreenPos(ResizePos[b]);
+ ImGui::Button("##layer_resize", ResizeSize);
+
+ if (ImGui::IsItemHovered()) {
+ ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
+ }
+ if (ImGui::IsItemActivated()) {
+ if (!Layer->IsSelected) {
+ if (!io.KeyShift) Layer_DeselectAll(Memory, File->Layer_Count);
+ State->MostRecentlySelectedLayer = i;
+ Layer->IsSelected = true;
+ }
+ }
+ if (ImGui::IsItemActive()) {
+ if (ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1)) {
+ State->Interact_Active = interact_type_layer_timeadjust;
+ ImVec2 DragDelta = ImGui::GetMouseDragDelta();
+ DragDelta = DragDelta + (ImVec2(UI->Warp_X, UI->Warp_Y) * TimelineSize);
+
+ State->Interact_Offset[0] = (DragDelta.x / TimelineSizeWithBorder.x * UI->TimelinePercentZoomed.x) * Comp->Frame_Count;
+ State->Interact_Offset[1] = b;
+ DebugWatchVar("Offset1", &State->Interact_Offset[0], d_float);
+ }
+ }
+ if (ImGui::IsItemDeactivated()) {
+ if (State->Interact_Active == interact_type_layer_timeadjust) {
+ for (int a = 0; a < File->Layer_Count; a++) {
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, a);
+ if (Layer->IsSelected) {
+ Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Layer->Frame_Start, &Layer->Frame_End, &Layer->Vertical_Offset);
+ }
+ }
+ State->Interact_Active = interact_type_none;
+ State->Interact_Offset[0] = 0;
+ State->Interact_Offset[1] = 0;
+ }
+ }
+
+ ImGui::PopID();
}
+
+ ImGui::SetCursorScreenPos(Layer_ScreenPos_Min);
+ ImGui::InvisibleButton("##layer_mid", Layer_ScreenSize, ImGuiMouseButton_Left);
+
if (ImGui::IsItemActivated()) {
if (!Layer->IsSelected) {
if (!io.KeyShift) Layer_DeselectAll(Memory, File->Layer_Count);
@@ -265,19 +417,36 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem
Layer->IsSelected = true;
}
}
+
if (ImGui::IsItemActive()) {
if (ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1)) {
- State->Interact_Active = interact_type_layer_timeadjust;
+ if (State->Interact_Active == interact_type_none) {
+ State->Interact_Active = interact_type_layer_move;
+ // TODO(fox): Selected layers inside precomps will have interactions doubled,
+ // so I'm forcing interaction to only be with members of the same precomp.
+ // Could be made more intuitive later.
+ Layer_RecursiveDeselect(Memory, SortedCompArray, SortedLayerArray, Layer->Block_Composition_Index, File->PrincipalCompIndex);
+ }
ImVec2 DragDelta = ImGui::GetMouseDragDelta();
DragDelta = DragDelta + (ImVec2(UI->Warp_X, UI->Warp_Y) * TimelineSize);
State->Interact_Offset[0] = (DragDelta.x / TimelineSizeWithBorder.x * UI->TimelinePercentZoomed.x) * Comp->Frame_Count;
- State->Interact_Offset[1] = b;
- DebugWatchVar("Offset1", &State->Interact_Offset[0], d_float);
+ State->Interact_Offset[1] = (DragDelta.y / TimelineSizeWithBorder.y * UI->TimelinePercentZoomed.y) * LayerIncrement;
+
+ /*
+ if (UI->DragDelta_Prev.x != 0) {
+ ImVec2 Offset_Old = (UI->DragDelta_Prev / TimelineSizeWithBorder * UI->TimelinePercentZoomed) * ImVec2(MainComp->Frame_Count, LayerIncrement);
+ if ((int32)State->Interact_Offset[1] != (int32)Offset_Old.y)
+ State->UpdateFrame = true;
+ }
+
+ UI->DragDelta_Prev = DragDelta;
+ */
}
}
+
if (ImGui::IsItemDeactivated()) {
- if (State->Interact_Active == interact_type_layer_timeadjust) {
+ if (State->Interact_Active == interact_type_layer_move) {
for (int a = 0; a < File->Layer_Count; a++) {
block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, a);
if (Layer->IsSelected) {
@@ -289,62 +458,9 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem
State->Interact_Offset[1] = 0;
}
}
-
ImGui::PopID();
}
- ImGui::SetCursorScreenPos(Layer_ScreenPos_Min);
- ImGui::InvisibleButton("##layer_mid", Layer_ScreenSize, ImGuiMouseButton_Left);
-
- if (ImGui::IsItemActivated()) {
- if (!Layer->IsSelected) {
- if (!io.KeyShift) Layer_DeselectAll(Memory, File->Layer_Count);
- State->MostRecentlySelectedLayer = i;
- Layer->IsSelected = true;
- }
- }
-
- if (ImGui::IsItemActive()) {
- if (ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1)) {
- if (State->Interact_Active == interact_type_none) {
- State->Interact_Active = interact_type_layer_move;
- // TODO(fox): Selected layers inside precomps will have interactions doubled,
- // so I'm forcing interaction to only be with members of the same precomp.
- // Could be made more intuitive later.
- Layer_RecursiveDeselect(Memory, SortedCompArray, SortedLayerArray, Layer->Block_Composition_Index, File->PrincipalCompIndex);
- }
- ImVec2 DragDelta = ImGui::GetMouseDragDelta();
- DragDelta = DragDelta + (ImVec2(UI->Warp_X, UI->Warp_Y) * TimelineSize);
-
- State->Interact_Offset[0] = (DragDelta.x / TimelineSizeWithBorder.x * UI->TimelinePercentZoomed.x) * Comp->Frame_Count;
- State->Interact_Offset[1] = (DragDelta.y / TimelineSizeWithBorder.y * UI->TimelinePercentZoomed.y) * LayerIncrement;
-
- /*
- if (UI->DragDelta_Prev.x != 0) {
- ImVec2 Offset_Old = (UI->DragDelta_Prev / TimelineSizeWithBorder * UI->TimelinePercentZoomed) * ImVec2(MainComp->Frame_Count, LayerIncrement);
- if ((int32)State->Interact_Offset[1] != (int32)Offset_Old.y)
- State->UpdateFrame = true;
- }
-
- UI->DragDelta_Prev = DragDelta;
- */
- }
- }
-
- if (ImGui::IsItemDeactivated()) {
- if (State->Interact_Active == interact_type_layer_move) {
- for (int a = 0; a < File->Layer_Count; a++) {
- block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, a);
- if (Layer->IsSelected) {
- Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Layer->Frame_Start, &Layer->Frame_End, &Layer->Vertical_Offset);
- }
- }
- State->Interact_Active = interact_type_none;
- State->Interact_Offset[0] = 0;
- State->Interact_Offset[1] = 0;
- }
- }
- ImGui::PopID();
}
// Check if any layers are precomps; we want to test hit detection for them _after_ the layers in front.
@@ -404,10 +520,9 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem
// TODO(fox): Draw calls are executed in reverse order, so we need another iteration to draw layers on top of precomps.
// The ImDrawListSplitter API can probably do this without another iteration.
+
for (int i = 0; i < SortedCompInfo.LayerCount; i++)
{
- ImGui::PushID(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);
@@ -426,57 +541,18 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem
ImVec2 Layer_ScreenPos_Max = TimelineAbsolutePos + TimelineMoveSize + ((Layer_LocalPos_Ratio + Layer_LocalSize_Ratio) * TimelineZoomSize);
ImVec2 Layer_ScreenSize = Layer_ScreenPos_Max - Layer_ScreenPos_Min;
- ImU32 col = IM_COL32(255, 255, 255, 255);
-
- int NumberOfActiveProperties = 0;
- for (int h = 0; h < AmountOf(Layer->Property); h++) {
- property_channel *Property = &Layer->Property[h];
- if (Property->Keyframe_Count)
- NumberOfActiveProperties++;
- }
-
- for (int h = 0; h < AmountOf(Layer->Property); h++) {
- property_channel *Property = &Layer->Property[h];
- ImGui::PushID(Property);
- if (Property->Keyframe_Count) {
- property_info PropertyInfo = Property_GetInfo(Memory, Property);
- real32 Y_Increment = 1 / (PropertyInfo.MaxVal - PropertyInfo.MinVal);
- bezier_point *PointAddress[2] = {};
- ImVec2 Keyframe_ScreenPos[2] = {};
- ImVec2 Keyframe_ScreenPos_L[2] = {};
- ImVec2 Keyframe_ScreenPos_R[2] = {};
- for (int k = 0; k < (Property->Keyframe_Count + 1); k++) {
- int Idx = k % 2;
- PointAddress[Idx] = Bezier_Lookup(Memory, Property, k);
- bezier_point *Point = PointAddress[Idx];
-
- ImVec2 Keyframe_LocalPos[3] = { V2(Point->Pos[0]), V2(Point->Pos[0] + Point->Pos[1]), V2(Point->Pos[0] + Point->Pos[2]) };
- ImVec2 Keyframe_LocalPos_Ratio[3];
- for (int b = 0; b < 3; b++) {
- Keyframe_LocalPos_Ratio[b] = (Keyframe_LocalPos[b] - ImVec2(0, PropertyInfo.MinVal)) * ImVec2(Increment.x, Y_Increment);
- }
-
- Keyframe_ScreenPos[Idx] = Layer_ScreenPos_Min + ((Keyframe_LocalPos_Ratio[0] - ImVec2(0, 0.5)) * TimelineZoomSize) + ImVec2(0, Layer_ScreenSize.y/2);
- Keyframe_ScreenPos_L[Idx] = Layer_ScreenPos_Min + ((Keyframe_LocalPos_Ratio[1] - ImVec2(0, 0.5)) * TimelineZoomSize) + ImVec2(0, Layer_ScreenSize.y/2);
- Keyframe_ScreenPos_R[Idx] = Layer_ScreenPos_Min + ((Keyframe_LocalPos_Ratio[2] - ImVec2(0, 0.5)) * TimelineZoomSize) + ImVec2(0, Layer_ScreenSize.y/2);
-
- draw_list->AddCircle(Keyframe_ScreenPos[Idx], 2, col, 16, 1);
- if (k != 0 && k != Property->Keyframe_Count) {
- if (PointAddress[0]->Type == interpolation_type_bezier && PointAddress[1]->Type == interpolation_type_bezier) {
- draw_list->AddBezierCubic(Keyframe_ScreenPos[!Idx], Keyframe_ScreenPos_R[!Idx],
- Keyframe_ScreenPos_L[Idx], Keyframe_ScreenPos[Idx], col, 1.0f, 0);
- } else {
- draw_list->AddLine(Keyframe_ScreenPos[0], Keyframe_ScreenPos[1], col, 1.0f);
- }
- }
- }
- }
- ImGui::PopID();
+ ImU32 LayerColor = 0;
+ ImU32 BorderColor = 0;
+ if (UI->TimelineMode == timeline_mode_graph) {
+ LayerColor = ImColor(Layer->Col[0], Layer->Col[1], Layer->Col[2], 0.2f);
+ BorderColor = ImColor(0.3, 0.3, 0.3, 1.0f);
+ } else {
+ LayerColor = ImColor(Layer->Col[0], Layer->Col[1], Layer->Col[2], 1.0f);
+ BorderColor = ImColor(0.2, 0.2, 0.2, 1.0f);
}
- draw_list->AddRectFilled(Layer_ScreenPos_Min, Layer_ScreenPos_Max,
- ImColor(Layer->Col[0], Layer->Col[1], Layer->Col[2], 1.0f));
- draw_list->AddRect(Layer_ScreenPos_Min, Layer_ScreenPos_Max, ImColor(1.0f, 1.0f, 1.0f, 0.5f), 2);
+ draw_list->AddRectFilled(Layer_ScreenPos_Min, Layer_ScreenPos_Max, LayerColor);
+ draw_list->AddRect(Layer_ScreenPos_Min, Layer_ScreenPos_Max, BorderColor, 2);
// block_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, Layer->Block_String_Index);
// draw_list->AddText(Layer_ScreenPos_Min, 0xFFFFFFFF, String->Char);
@@ -484,16 +560,17 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem
draw_list->AddRectFilled(Layer_ScreenPos_Min, Layer_ScreenPos_Max, ImColor(0.25f, 0.25f, 0.25f, 0.5f), 2);
draw_list->AddRect(Layer_ScreenPos_Min, Layer_ScreenPos_Max, ImColor(1.0f, 1.0f, 1.0f, 0.5f), 2);
}
-
-
- ImGui::PopID();
}
+
ImGui::PopID();
}
static void
ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io)
{
+ if (UI->TimelineMode == timeline_mode_graph)
+ ImGui_GraphInfo(File, State, Memory, UI, io);
+
ImVec2 FramePadding = ImGui::GetStyle().FramePadding;
ImVec2 ItemSpacing = ImGui::GetStyle().ItemSpacing;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
@@ -551,11 +628,11 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI,
UI->TimelinePercentZoomed = ImVec2(1, 1);
}
- ImGui_TimelineHorizontalIncrementDraw(UI, draw_list, TimelineSizeWithBorder, TimelineAbsolutePos, *MainComp);
-
ImVec2 TimelineZoomSize = TimelineSizeWithBorder / UI->TimelinePercentZoomed;
ImVec2 TimelineMoveSize = TimelineSizeWithBorder * UI->TimelinePercentOffset / UI->TimelinePercentZoomed;
+ ImGui_TimelineHorizontalIncrementDraw(UI, draw_list, TimelineSizeWithBorder, TimelineAbsolutePos, *MainComp, TimelineZoomSize, TimelineMoveSize);
+
ImVec2 Increment = ImVec2((real32)1 / MainComp->Frame_Count, (real32)1 / LayerIncrement);
uint64 SortSize = (sizeof(sorted_comp_info) * File->Comp_Count) + (sizeof(sorted_layer) * File->Layer_Count);
@@ -570,6 +647,13 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI,
TimelineSize, TimelineSizeWithBorder, LayerIncrement,
SortedCompArray, SortedLayerArray);
+ if (UI->TimelineMode == timeline_mode_graph) {
+ graph_info GraphInfo = Graph_GetInfo(File, Memory);
+ ImGui_Timeline_DrawGraph(File, State, Memory, UI, io, draw_list, GraphInfo,
+ Increment, TimelineAbsolutePos, TimelineMoveSize, TimelineZoomSize,
+ TimelineSize, TimelineSizeWithBorder, LayerIncrement);
+ }
+
Memory_PopScratch(Memory, SortSize);
ImVec2 MouseDelta = io.MouseDelta / TimelineSize;
@@ -730,7 +814,7 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI,
}
if (IsItemActivated) {
- if (!io.KeyShift) Layer_DeselectAll(Memory, File->Layer_Count);
+ if (!io.KeyShift && UI->TimelineMode == timeline_mode_default) Layer_DeselectAll(Memory, File->Layer_Count);
UI->BoxSelect = true;
}
if (IsItemActive) {
@@ -739,15 +823,15 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI,
IM_COL32(0, 0, 200, 50));
}
+ if (IsItemDeactivated) {
+ UI->BoxSelect = false;
+ }
+
if (!ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
UI->Warp_X = 0;
UI->Warp_Y = 0;
}
- if (IsItemDeactivated) {
- UI->BoxSelect = false;
- }
-
draw_list->PopClipRect();
ImGui::PopClipRect();
@@ -770,6 +854,9 @@ ImGui_ProcessInputs(project_data *File, project_state *State, memory *Memory, Im
if (ImGui::IsKeyPressed(ImGuiKey_A)) {
State->UpdateFrame = true;
}
+ if (ImGui::IsKeyPressed(ImGuiKey_Space)) {
+ State->IsPlaying ^= 1;
+ }
if (ImGui::IsKeyPressed(ImGuiKey_T)) {
for (int a = 0; a < File->Layer_Count; a++) {
block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, a);
@@ -1840,7 +1927,7 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, memory *Memory,
Point1_ScreenPos, Point1_ScreenPos, col2, 6.0f, 0);
} else if (Point1->HandleBezier) {
draw_list->AddBezierCubic(Point0_ScreenPos, Point0_ScreenPos,
- Point1_ScreenPos_Left, Point1_ScreenPos, col2, 6.0f, 0);
+ Point1_ScreenPos_Left, Point1_ScreenPos,col2, 6.0f, 0);
} else {
draw_list->AddLine(Point0_ScreenPos, Point1_ScreenPos, col2, 6.0f);
}