summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bezier.cpp6
-rw-r--r--createcalls.cpp27
-rw-r--r--main.cpp101
-rw-r--r--main.h10
-rw-r--r--memory.cpp3
-rw-r--r--my_imgui_widgets.cpp203
6 files changed, 279 insertions, 71 deletions
diff --git a/bezier.cpp b/bezier.cpp
index 42ed04d..f476986 100644
--- a/bezier.cpp
+++ b/bezier.cpp
@@ -8,9 +8,10 @@ Bezier_SolveYForX(v2 Point_P0, v2 Point_P1, v2 Point_P2, v2 Point_P3, real32 Tar
v2 m1 = (Point_P2 - Point_P0) / (2 * Tau);
v2 m2 = (Point_P3 - Point_P1) / (2 * Tau);
- real32 Precision = 0.001;
+ real32 Precision = 0.000001;
real32 t = (TargetX - Point_P0.x) / (Point_P3.x - Point_P0.x);
+ int Iterations = 0;
for (;;) {
real32 t2 = t * t;
real32 t3 = t2 * t;
@@ -22,8 +23,9 @@ Bezier_SolveYForX(v2 Point_P0, v2 Point_P1, v2 Point_P2, v2 Point_P3, real32 Tar
bool32 Cond1 = (Point.x <= (TargetX - Precision));
bool32 Cond2 = (Point.x >= (TargetX + Precision));
- if (Cond1 || Cond2) {
+ if ((Cond1 || Cond2) && Iterations < 10) {
t = t * TargetX / Point.x;
+ Iterations++;
} else {
Y = Point.y;
break;
diff --git a/createcalls.cpp b/createcalls.cpp
index d0ca03e..5c569fb 100644
--- a/createcalls.cpp
+++ b/createcalls.cpp
@@ -57,10 +57,14 @@ static property_info
Property_GetInfo(memory *Memory, property_channel *Property)
{
property_info PropertyInfo = {};
- for (int k = 0; k < Property->Keyframe_Count; k++) {
+ int k = 0;
+ for (;;) {
bezier_point *Point = Bezier_Lookup(Memory, Property, k);
+ if (!Point->Occupied)
+ break;
PropertyInfo.MinVal = (Point->Pos[0].y < PropertyInfo.MinVal) ? Point->Pos[0].y : PropertyInfo.MinVal;
PropertyInfo.MaxVal = (Point->Pos[0].y > PropertyInfo.MaxVal) ? Point->Pos[0].y : PropertyInfo.MaxVal;
+ k++;
}
return PropertyInfo;
}
@@ -75,7 +79,7 @@ Graph_GetInfo(project_data *File, memory *Memory)
continue;
for (int h = 0; h < AmountOf(Layer->Property); h++) {
property_channel *Property = &Layer->Property[h];
- if (Property->Keyframe_Count) {
+ if (Property->Block_Bezier_Count) {
property_info PropertyInfo = Property_GetInfo(Memory, Property);
GraphInfo.MinVal = (PropertyInfo.MinVal < GraphInfo.MinVal) ? PropertyInfo.MinVal : GraphInfo.MinVal;
GraphInfo.MaxVal = (PropertyInfo.MaxVal > GraphInfo.MaxVal) ? PropertyInfo.MaxVal : GraphInfo.MaxVal;
@@ -87,6 +91,25 @@ Graph_GetInfo(project_data *File, memory *Memory)
}
static void
+Keyframe_Interact_Evaluate(memory *Memory, project_state *State, uint8 IsSelected, v2 Pos_Initial[3], v2 Pos_New[3])
+{
+ Assert(Pos_New[0].y == Pos_Initial[0].y);
+ v2 Offset = V2(State->Interact_Offset[0], State->Interact_Offset[1]);
+ if (State->Interact_Active == interact_type_keyframe_move) {
+ Pos_New[0] = Pos_New[0] + Offset;
+ } else if (State->Interact_Active == interact_type_keyframe_scale) {
+ Pos_New[1].x += (IsSelected - 1 == 0 || IsSelected - 1 == 1) ? Offset.x : 0;
+ Pos_New[2].x -= (IsSelected - 1 == 0 || IsSelected - 1 == 2) ? Offset.x : 0;
+ } else if (State->Interact_Active == interact_type_keyframe_rotate) {
+ real32 Rad = State->Interact_Offset[0];
+ v2 XAxis = V2(8, 8) * V2(cos(Rad), sin(Rad));
+ v2 YAxis = V2(sin(Rad), -cos(Rad));
+ Pos_New[2].x += XAxis.x + XAxis.y;
+ Pos_New[2].y += YAxis.x + YAxis.y;
+ }
+}
+
+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/main.cpp b/main.cpp
index 74a9e4a..7920727 100644
--- a/main.cpp
+++ b/main.cpp
@@ -128,7 +128,7 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI,
ImGui::DockSpaceOverViewport();
if (!io.WantCaptureKeyboard)
- ImGui_ProcessInputs(File, State, Memory, io);
+ ImGui_ProcessInputs(File, State, UI, Memory, io);
#if 0
@@ -154,7 +154,7 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI,
if (Debug.ToggleWindow) {
ImGui::ShowDemoWindow();
- ImGui_DebugMemoryViewer(State);
+ ImGui_DebugMemoryViewer(Memory, State);
}
// ImGui::ShowDemoWindow();
@@ -165,12 +165,18 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI,
ImGui::EndFrame();
}
-static void
+static void *
Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, uint32 CompIndex)
{
block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, CompIndex);
cache_entry *Entry_Main = Memory_Cache_Search(State, Memory, State->Render.Entry, cache_entry_type_comp, CompIndex, State->Frame_Current);
void *CompBuffer = Memory_Block_Bitmap_AddressAtIndex(Memory, Entry_Main->Block_StartIndex);
+
+ if (Entry_Main->IsCached)
+ return CompBuffer;
+
+ uint64 Comp_TimeStart = GetTime();
+
sorted_comp_info *SortedCompInfo = &SortedCompArray[CompIndex];
sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, SortedCompArray, CompIndex);
for (int i = 0; i < SortedCompInfo->LayerCount; i++) {
@@ -205,6 +211,7 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
Entry->CycleTime = GetTime() - Src_TimeStart;
Layer->x.CurrentValue = (Layer->Block_Source_Index == 0) ? 200 : Comp->Width/2;
Layer->y.CurrentValue = Comp->Height/2;
+ Entry->IsCached = true;
}
BitmapAddress = Memory_Block_Bitmap_AddressAtIndex(Memory, Entry->Block_StartIndex);
} else {
@@ -228,9 +235,16 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
property_channel *Property = &Layer->x;
- if (Property->Keyframe_Count) {
+ if (Property->Block_Bezier_Count) {
bezier_point *FirstPoint = Bezier_Lookup(Memory, Property, 0);
- bezier_point *LastPoint = Bezier_Lookup(Memory, Property, Property->Keyframe_Count - 1);
+ int k = 0;
+ for (;;) {
+ bezier_point *Point = Bezier_Lookup(Memory, Property, k);
+ if (!Point->Occupied)
+ break;
+ k++;
+ }
+ bezier_point *LastPoint = Bezier_Lookup(Memory, Property, k - 1);
if (FirstPoint->Pos[0].x >= State->Frame_Current) {
Property->CurrentValue = FirstPoint->Pos[0].y;
} else if (LastPoint->Pos[0].x <= State->Frame_Current) {
@@ -245,7 +259,11 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
}
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);
+ v2 Pos_New[3] = { Point->Pos[0], Point->Pos[1], Point->Pos[2] };
+ v2 NextPos_New[3] = { NextPoint->Pos[0], NextPoint->Pos[1], NextPoint->Pos[2] };
+ Keyframe_Interact_Evaluate(Memory, State, Point->IsSelected, Point->Pos, Pos_New);
+ Keyframe_Interact_Evaluate(Memory, State, NextPoint->IsSelected, NextPoint->Pos, NextPos_New);
+ Property->CurrentValue = Bezier_SolveYForX(Pos_New[0], Pos_New[0] + Pos_New[2], NextPos_New[0] + NextPos_New[1], NextPos_New[0], State->Frame_Current);
}
}
@@ -271,6 +289,9 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
}
}
}
+ Entry_Main->CycleTime = GetTime() - Comp_TimeStart;
+ Entry_Main->IsCached = true;
+ return CompBuffer;
}
static void
@@ -278,11 +299,7 @@ Main_Renderer(project_data *File, project_state *State, memory *Memory, SDL_Wind
{
State->UpdateFrame = false;
- uint64 Comp_TimeStart = GetTime();
-
block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, File->PrincipalCompIndex);
- cache_entry *Entry_Main = Memory_Cache_Search(State, Memory, State->Render.Entry, cache_entry_type_comp, File->PrincipalCompIndex, State->Frame_Current);
- void *MainCompBuffer = Memory_Block_Bitmap_AddressAtIndex(Memory, Entry_Main->Block_StartIndex);
// NOTE(fox): All layers are given a slot here
uint64 SortSize = (sizeof(sorted_comp_info) * File->Comp_Count) + (sizeof(sorted_layer) * File->Layer_Count);
@@ -292,19 +309,19 @@ Main_Renderer(project_data *File, project_state *State, memory *Memory, SDL_Wind
sorted_layer *SortedLayerArray = (sorted_layer *)((uint8 *)SortedArray + (sizeof(sorted_comp_info) * File->Comp_Count));
Layer_SortAll(Memory, SortedLayerArray, SortedCompArray, File->Layer_Count, File->Comp_Count);
- Render_Comp(File, State, Memory, io, SortedCompArray, SortedLayerArray, File->PrincipalCompIndex);
+ void *MainCompBuffer = Render_Comp(File, State, Memory, io, SortedCompArray, SortedLayerArray, File->PrincipalCompIndex);
Memory_PopScratch(Memory, SortSize);
glBindTexture(GL_TEXTURE_2D, textureID);
int ByteFlag2 = (MainComp->BytesPerPixel == 4) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT;
- if (!Entry_Main->CycleTime)
+ if (State->FirstFrame) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, MainComp->Width, MainComp->Height, 0, GL_RGBA, ByteFlag2, MainCompBuffer);
+ State->FirstFrame = false;
+ }
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, MainComp->Width, MainComp->Height, GL_RGBA, ByteFlag2, MainCompBuffer);
- Entry_Main->CycleTime = GetTime() - Comp_TimeStart;
-
// TODO(fox): garbage collect AV state!
}
@@ -340,7 +357,7 @@ int main(int argc, char *argv[]) {
Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Strings, "Strings", sizeof(block_string));
Memory_InitTable(&GlobalMemory, &Memory, (uint64)64 * 1024 * 1024, B_ScratchSpace, "Scratch");
- Memory_InitTable(&GlobalMemory, &Memory, (uint64)50 * 1024 * 1024, B_CachedBitmaps, "Cached bitmap buffer");
+ Memory_InitTable(&GlobalMemory, &Memory, (uint64)200 * 1024 * 1024, B_CachedBitmaps, "Cached bitmap buffer");
#if ARM
InstructionMode = instruction_mode_neon;
@@ -412,8 +429,8 @@ int main(int argc, char *argv[]) {
Bezier->Occupied = 1;
Bezier->Point[0].Pos[0] = V2(0, 0);
- Bezier->Point[1].Pos[0] = V2(10, 50);
- Bezier->Point[2].Pos[0] = V2(20, -50);
+ Bezier->Point[1].Pos[0] = V2(20, 50);
+ Bezier->Point[2].Pos[0] = V2(40, -50);
Bezier->Point[0].Pos[1] = V2(-4, 0);
Bezier->Point[1].Pos[1] = V2(-4, 0);
Bezier->Point[2].Pos[1] = V2(-4, 0);
@@ -423,8 +440,10 @@ 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;
+ Bezier->Point[1].IsSelected = false;
+ Bezier->Point[0].Occupied = true;
+ Bezier->Point[1].Occupied = true;
+ Bezier->Point[2].Occupied = true;
property_channel *Property2 = &Layer->opacity;
Property2->Block_Bezier_Index[0] = Memory_Block_AllocateNew(&Memory, F_Bezier);
@@ -435,7 +454,8 @@ int main(int argc, char *argv[]) {
Bezier2->Point[0].Pos[0] = V2(0, 0);
Bezier2->Point[1].Pos[0] = V2(20, 1);
- Property2->Keyframe_Count = 2;
+ Bezier2->Point[0].Occupied = true;
+ Bezier2->Point[1].Occupied = true;
property_channel *Property3 = &Layer->y;
Property3->Block_Bezier_Index[0] = Memory_Block_AllocateNew(&Memory, F_Bezier);
@@ -445,8 +465,8 @@ int main(int argc, char *argv[]) {
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[1].Pos[0] = V2(20, 300);
+ Bezier3->Point[2].Pos[0] = V2(40, 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);
@@ -456,7 +476,9 @@ int main(int argc, char *argv[]) {
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;
+ Bezier3->Point[0].Occupied = true;
+ Bezier3->Point[1].Occupied = true;
+ Bezier3->Point[2].Occupied = true;
}
// {
// Layer_CreateFromSource(File, State, &Memory, SourceIndex, MainComp->Frame_End);
@@ -472,6 +494,7 @@ int main(int argc, char *argv[]) {
{
uint16 SourceIndex = Source_Generate(File, State, &Memory, (void *)"../asset/b.jpg");
block_source *Source = (block_source *)Memory_Block_AddressAtIndex(&Memory, F_Sources, 1);
+#if 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);
@@ -505,7 +528,10 @@ int main(int argc, char *argv[]) {
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;
+ Bezier->Point[0].Occupied = true;
+ Bezier->Point[1].Occupied = true;
+ Bezier->Point[2].Occupied = true;
+ Bezier->Point[3].Occupied = true;
property_channel *Property2 = &Layer->opacity;
Property2->Block_Bezier_Index[0] = Memory_Block_AllocateNew(&Memory, F_Bezier);
@@ -516,31 +542,10 @@ int main(int argc, char *argv[]) {
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;
- */
+ Bezier2->Point[0].Occupied = true;
+ Bezier2->Point[1].Occupied = true;
}
+#endif
}
{
diff --git a/main.h b/main.h
index 00d97c9..7e07597 100644
--- a/main.h
+++ b/main.h
@@ -80,7 +80,8 @@ struct bezier_point {
uint8 Occupied;
v2 Pos[3];
interpolation_type Type;
- uint8 IsSelected; //[3]
+ uint8 IsSelected;
+ uint8 PointSelect[3];
uint8 Color;
};
@@ -187,7 +188,10 @@ enum interact_type
{
interact_type_none,
interact_type_layer_move,
- interact_type_layer_timeadjust
+ interact_type_layer_timeadjust,
+ interact_type_keyframe_move,
+ interact_type_keyframe_scale,
+ interact_type_keyframe_rotate,
};
struct project_state
@@ -204,6 +208,7 @@ struct project_state
bool32 IsRunning = 1;
bool32 IsPlaying;
+ bool32 FirstFrame = 1;
int16 MostRecentlySelectedLayer = -1;
// selection_type RecentSelectionType = selection_none;
@@ -295,7 +300,6 @@ struct property_channel {
char *Name;
uint16 Block_Bezier_Index[MAX_KEYFRAME_BLOCKS];
uint16 Block_Bezier_Count;
- uint16 Keyframe_Count;
real32 CurrentValue;
real32 MaxVal;
diff --git a/memory.cpp b/memory.cpp
index 1dd7ae6..3037eb0 100644
--- a/memory.cpp
+++ b/memory.cpp
@@ -84,11 +84,12 @@ Memory_Block_Bitmap_AllocateNew(project_state *State, memory *Memory, cache_entr
} break;
}
+ uint32 Blocks_Max = Memory->Slot[B_CachedBitmaps].Size / BitmapBlockSize;
+ Assert(Blocks_Max > LastBlock);
return LastBlock + LastEntry_BlockCount;
/*
uint32 Blocks_Needed = (NewSize / BitmapBlockSize) + 1;
- uint32 Blocks_Max = Memory->Slot[B_CachedBitmaps].Size / BitmapBlockSize;
uint32 Block_Index_Available = 0;
*/
diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp
index 545af4e..c5a4049 100644
--- a/my_imgui_widgets.cpp
+++ b/my_imgui_widgets.cpp
@@ -4,16 +4,51 @@
#include "imgui_helper_widgets.cpp"
static void
-ImGui_DebugMemoryViewer(project_state *State)
+ImGui_DebugMemoryViewer(memory *Memory, project_state *State)
{
ImGui::Begin("Memory viewer");
+
+ ImVec2 ViewportMin = ImGui::GetCursorScreenPos();
+ ImVec2 ViewportScale = ImGui::GetContentRegionAvail();
+ ImVec2 ViewportMax = ImVec2(ViewportMin.x + ViewportScale.x, ViewportMin.y + ViewportScale.y);
+
+ // ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
+ // ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
+
cache_entry *EntryArray = State->Render.Entry;
char *Type[4] = { "unassigned", "comp", "source", "layer" };
int c = 0;
- while (EntryArray[c].CycleTime != 0) {
- ImGui::Text("Type - %s, Start - %i, Info - %i", Type[EntryArray[c].Type], EntryArray[c].Block_StartIndex, EntryArray[c].TypeInfo);
+ uint32 Blocks_Total = Memory->Slot[B_CachedBitmaps].Size / BitmapBlockSize;
+ uint32 PerRow = sqrt(Blocks_Total);
+ real32 BlockSize = ViewportScale.x / PerRow;
+ while (EntryArray[c+1].CycleTime != 0) {
+ ImGui::PushID(c);
+ cache_entry Entry = EntryArray[c];
+ cache_entry NextEntry = EntryArray[c+1];
+ uint32 BlockSpan = NextEntry.Block_StartIndex - Entry.Block_StartIndex;
+ ImVec2 ButtonPos = ViewportMin + ImVec2((Entry.Block_StartIndex % PerRow) * BlockSize, BlockSize * (Entry.Block_StartIndex / PerRow));
+ ImVec2 ButtonSize = ImVec2(BlockSpan * BlockSize, BlockSize);
+ ImGui::SetCursorScreenPos(ButtonPos);
+ char size[20];
+ sprintf(size, "%lu##uimemoryblock", EntryArray[c].CycleTime);
+ if (ButtonPos.x + ButtonSize.x > ViewportMax.x) {
+ real32 ButtonSizeSplit = ViewportMax.x - ButtonPos.x;
+ ImGui::Button(size, ImVec2(ButtonSizeSplit, ButtonSize.y));
+ ImVec2 ButtonPos2 = ImVec2(ViewportMin.x, ButtonPos.y + BlockSize);
+ ImGui::SetCursorScreenPos(ButtonPos2);
+ ImGui::Button("##uimemoryblockpad", ImVec2(ButtonSize.x - ButtonSizeSplit, ButtonSize.y));
+ } else {
+ ImGui::Button(size, ButtonSize);
+ }
+ if (ImGui::IsItemHovered()) {
+ ImGui::BeginTooltip();
+ ImGui::Text("Type - %s, Start - %i, Info - %i, %i", Type[EntryArray[c].Type], EntryArray[c].Block_StartIndex, EntryArray[c].TypeInfo, EntryArray[c].TypeInfo_Sub);
+ ImGui::EndTooltip();
+ }
c++;
+ ImGui::PopID();
}
+ // ImGui::PopStyleVar(2);
ImGui::End();
}
@@ -212,7 +247,7 @@ ImGui_GraphInfo(project_data *File, project_state *State, memory *Memory, ui *UI
ImGui::PushID(a);
for (int h = 0; h < AmountOf(Layer->Property); h++) {
property_channel *Property = &Layer->Property[h];
- if (Property->Keyframe_Count) {
+ if (Property->Block_Bezier_Count) {
ImGui::PushID(Property);
ImGui::Text(Property->Name);
ImGui::PopID();
@@ -254,39 +289,117 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor
ImU32 col = IM_COL32(255, 255, 255, 255);
+ if (State->Interact_Active == interact_type_keyframe_move) {
+ ImVec2 DragDelta = io.MousePos - ImVec2(State->Interact_Offset[2], State->Interact_Offset[3]);
+ State->Interact_Offset[0] = (DragDelta.x / TimelineSizeWithBorder.x * UI->TimelinePercentZoomed.x) / Increment.x;
+ State->Interact_Offset[1] = -1 * (DragDelta.y / TimelineSizeWithBorder.y * UI->TimelinePercentZoomed.y) * ((GraphInfo.MaxVal - GraphInfo.MinVal));
+ } else if (State->Interact_Active == interact_type_keyframe_scale) {
+ ImVec2 DragDelta = io.MousePos - ImVec2(State->Interact_Offset[2], State->Interact_Offset[3]);
+ State->Interact_Offset[0] = (DragDelta.x / TimelineSizeWithBorder.x * UI->TimelinePercentZoomed.x) / Increment.x;
+ // TODO(fox): Pass min/max to sort to calculate this better!
+ }
+
+ if ((io.MouseDelta.x || io.MouseDelta.y) &&
+ (State->Interact_Active == interact_type_keyframe_move ||
+ State->Interact_Active == interact_type_keyframe_rotate ||
+ State->Interact_Active == interact_type_keyframe_scale))
+ {
+ }
+
for (int h = 0; h < AmountOf(Layer->Property); h++) {
property_channel *Property = &Layer->Property[h];
ImGui::PushID(Property);
- if (Property->Keyframe_Count) {
+ if (Property->Block_Bezier_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 k = 0;
+ for (;;) {
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]) };
+ if (!Point->Occupied)
+ break;
+
+ v2 Keyframe_LocalPos_[3] = { Point->Pos[0], Point->Pos[1], Point->Pos[2] };
+
+ if (Point->IsSelected) {
+ if (State->Interact_Active == interact_type_keyframe_rotate) {
+ ImVec2 Keyframe_LocalPos_Ratio = (V2(Keyframe_LocalPos_[0]) - ImVec2(0, GraphInfo.MinVal)) * ImVec2(Increment.x, Y_Increment);
+ ImVec2 Keyframe_ScreenPos = Layer_ScreenPos_Min + ((ImVec2(1, -1) * Keyframe_LocalPos_Ratio + ImVec2(0, 0.5)) * TimelineZoomSize) + ImVec2(0, Layer_ScreenSize.y/2);
+ real32 Slope_Old = (Keyframe_ScreenPos.y - State->Interact_Offset[3]) / (Keyframe_ScreenPos.x - State->Interact_Offset[2]);
+ real32 Slope_New = (Keyframe_ScreenPos.y - io.MousePos.y) / (Keyframe_ScreenPos.x - io.MousePos.x);
+ State->Interact_Offset[0] = atan((Slope_Old - Slope_New) / (1 + Slope_Old * Slope_New));
+ DebugWatchVar("Rotation: ", &State->Interact_Offset[0], d_float);
+ }
+ Keyframe_Interact_Evaluate(Memory, State, Point->IsSelected, Point->Pos, Keyframe_LocalPos_);
+ }
+ ImVec2 Keyframe_LocalPos[3] = { V2(Keyframe_LocalPos_[0]), V2(Keyframe_LocalPos_[0] + Keyframe_LocalPos_[1]), V2(Keyframe_LocalPos_[0] + Keyframe_LocalPos_[2]) };
+
ImVec2 Keyframe_LocalPos_Ratio[3];
for (int b = 0; b < 3; b++) {
Keyframe_LocalPos_Ratio[b] = (Keyframe_LocalPos[b] - ImVec2(0, GraphInfo.MinVal)) * ImVec2(Increment.x, Y_Increment);
Keyframe_ScreenPos[NewIdx + b] = Layer_ScreenPos_Min + ((ImVec2(1, -1) * Keyframe_LocalPos_Ratio[b] + ImVec2(0, 0.5)) * TimelineZoomSize) + ImVec2(0, Layer_ScreenSize.y/2);
}
+ if (UI->BoxSelect) {
+ real32 Y_Top = (io.MouseClickedPos[0].y < io.MousePos.y) ? io.MouseClickedPos[0].y : io.MousePos.y;
+ real32 Y_Bottom = (io.MouseClickedPos[0].y > io.MousePos.y) ? io.MouseClickedPos[0].y : io.MousePos.y;
+ real32 X_Left = (io.MouseClickedPos[0].x < io.MousePos.x) ? io.MouseClickedPos[0].x : io.MousePos.x;
+ real32 X_Right = (io.MouseClickedPos[0].x > io.MousePos.x) ? io.MouseClickedPos[0].x : io.MousePos.x;
+
+ if (Keyframe_ScreenPos[NewIdx].y >= Y_Top && Keyframe_ScreenPos[NewIdx].y <= Y_Bottom &&
+ Keyframe_ScreenPos[NewIdx].x >= X_Left && Keyframe_ScreenPos[NewIdx].x <= X_Right)
+ {
+ if (!Point->IsSelected) {
+ Point->IsSelected = 1;
+ }
+ } else if (!io.KeyShift) {
+ Point->IsSelected = 0;
+ }
+ }
+
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);
+ ImVec2 ButtonSize(16, 16);
- 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);
+ ImGui::PushID(k);
+ int Max = (Point->IsSelected) ? 2 : 0;
+ for (int b = Max; b >= 0; b--) {
+ ImU32 PointCol = ((Point->IsSelected - 1) == b) ? ImColor(0.8f, 0.5f, 0.0f, 1.0f) : ImColor(0.1f, 0.1f, 0.1f, 1.0f);
+ ImU32 LineCol = ((Point->IsSelected - 1) == b) ? ImColor(0.8f, 0.5f, 0.5f, 1.0f) : ImColor(0.4f, 0.4f, 0.4f, 1.0f);
+ ImGui::PushID(b);
+ ImGui::SetCursorScreenPos(Keyframe_ScreenPos[NewIdx + b] - (ButtonSize * 0.5));
+ ImGui::InvisibleButton("##keyframemover", ButtonSize, ImGuiMouseButton_Left);
+ bool32 IsHovered = ImGui::IsItemHovered();
+ bool32 IsItemActive = ImGui::IsItemActive();
+ bool32 IsItemActivated = ImGui::IsItemActivated();
+ bool32 IsItemDeactivated = ImGui::IsItemDeactivated();
+ bool32 LeftClick = ImGui::IsMouseDown(ImGuiMouseButton_Left);
+ bool32 RightClick = ImGui::IsMouseDown(ImGuiMouseButton_Right);
+
+ if (IsHovered)
+ PointCol = ImColor(1.0f, 0.8f, 0.8f, 1.0f);
+
+ if (IsItemActivated) {
+ Point->IsSelected = b+1;
+ }
+
+ if (b != 0 && Point->IsSelected)
+ draw_list->AddLine(Keyframe_ScreenPos[NewIdx], Keyframe_ScreenPos[NewIdx + b], LineCol, 2.0f);
+
+ if (b == 0)
+ draw_list->AddCircleFilled(Keyframe_ScreenPos[NewIdx + b], 4, PointCol);
+ else
+ draw_list->AddCircle(Keyframe_ScreenPos[NewIdx + b], 6, PointCol, 0, 2);
+
+ ImGui::PopID();
}
+ ImGui::PopID();
UI->Test.SetCurrentChannel(draw_list, 0);
@@ -298,6 +411,7 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor
draw_list->AddLine(Keyframe_ScreenPos[0], Keyframe_ScreenPos[3], col, 1.0f);
}
}
+ k++;
}
}
ImGui::PopID();
@@ -648,10 +762,14 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI,
SortedCompArray, SortedLayerArray);
if (UI->TimelineMode == timeline_mode_graph) {
+ // uint64 Keyframe_SortSize = (sizeof(sorted_comp_info) * File->Comp_Count) + (sizeof(sorted_layer) * File->Layer_Count);
+ // void *SortedArray = Memory_PushScratch(Memory, Keyframe_SortSize);
+ // Arbitrary_Zero((uint8 *)SortedArray, SortSize);
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, Keyframe_SortSize);
}
Memory_PopScratch(Memory, SortSize);
@@ -815,6 +933,35 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI,
if (IsItemActivated) {
if (!io.KeyShift && UI->TimelineMode == timeline_mode_default) Layer_DeselectAll(Memory, File->Layer_Count);
+ if (State->Interact_Active == interact_type_keyframe_move ||
+ State->Interact_Active == interact_type_keyframe_rotate ||
+ State->Interact_Active == interact_type_keyframe_scale) {
+ for (int a = 0; a < File->Layer_Count; a++) {
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, a);
+ if (!Layer->IsSelected)
+ continue;
+ for (int h = 0; h < AmountOf(Layer->Property); h++) {
+ property_channel *Property = &Layer->Property[h];
+ if (Property->Block_Bezier_Count) {
+ int k = 0;
+ for (;;) {
+ bezier_point *Point = Bezier_Lookup(Memory, Property, k);
+ if (!Point->Occupied)
+ break;
+ if (Point->IsSelected) {
+ Keyframe_Interact_Evaluate(Memory, State, Point->IsSelected, Point->Pos, Point->Pos);
+ }
+ k++;
+ }
+ }
+ }
+ }
+ State->Interact_Offset[0] = 0;
+ State->Interact_Offset[1] = 0;
+ State->Interact_Offset[2] = 0;
+ State->Interact_Offset[3] = 0;
+ State->Interact_Active = interact_type_none;
+ }
UI->BoxSelect = true;
}
if (IsItemActive) {
@@ -846,7 +993,7 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI,
}
static void
-ImGui_ProcessInputs(project_data *File, project_state *State, memory *Memory, ImGuiIO io)
+ImGui_ProcessInputs(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io)
{
if (ImGui::IsKeyPressed(ImGuiKey_Q)) {
State->IsRunning = false;
@@ -854,6 +1001,32 @@ ImGui_ProcessInputs(project_data *File, project_state *State, memory *Memory, Im
if (ImGui::IsKeyPressed(ImGuiKey_A)) {
State->UpdateFrame = true;
}
+ if (UI->TimelineMode == timeline_mode_graph) {
+ if (ImGui::IsKeyPressed(ImGuiKey_G)) {
+ State->Interact_Offset[2] = io.MousePos.x;
+ State->Interact_Offset[3] = io.MousePos.y;
+ State->Interact_Active = interact_type_keyframe_move;
+ } else if (ImGui::IsKeyPressed(ImGuiKey_R)) {
+ State->Interact_Offset[2] = io.MousePos.x;
+ State->Interact_Offset[3] = io.MousePos.y;
+ State->Interact_Active = interact_type_keyframe_rotate;
+ } else if (ImGui::IsKeyPressed(ImGuiKey_S)) {
+ State->Interact_Offset[2] = io.MousePos.x;
+ State->Interact_Offset[3] = io.MousePos.y;
+ State->Interact_Active = interact_type_keyframe_scale;
+ }
+ }
+ if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
+ if (State->Interact_Active == interact_type_keyframe_move ||
+ State->Interact_Active == interact_type_keyframe_rotate ||
+ State->Interact_Active == interact_type_keyframe_scale) {
+ State->Interact_Offset[0] = 0;
+ State->Interact_Offset[1] = 0;
+ State->Interact_Offset[2] = 0;
+ State->Interact_Offset[3] = 0;
+ State->Interact_Active = interact_type_none;
+ }
+ }
if (ImGui::IsKeyPressed(ImGuiKey_Space)) {
State->IsPlaying ^= 1;
}