From dc0d4a23fdbddef51d5e026f2eefef1731c4e338 Mon Sep 17 00:00:00 2001 From: Fox Caminiti Date: Tue, 29 Nov 2022 21:04:09 -0500 Subject: effects integration halfway --- createcalls.cpp | 120 +++++++++++++--- effects.cpp | 11 +- effects_constructors.cpp | 8 +- effects_gl.cpp | 74 ++++++++++ gl_calls.cpp | 67 +++------ main.cpp | 37 +++-- main.h | 3 + my_imgui_widgets.cpp | 350 +++++++++++++++++++++++++++-------------------- 8 files changed, 439 insertions(+), 231 deletions(-) create mode 100644 effects_gl.cpp diff --git a/createcalls.cpp b/createcalls.cpp index a984454..145a58a 100644 --- a/createcalls.cpp +++ b/createcalls.cpp @@ -242,6 +242,15 @@ Bezier_Add(memory *Memory, property_channel *Property, bezier_point PointData, u } } +static void +Property_AddKeyframe(memory *Memory, 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); + History_Entry_End(Memory); +} + // static void // Property_InitFloat(char *Name, real32 Val, real32 ScrubVal, real32 MinVal = PROPERTY_REAL_MIN, real32 MaxVal = PROPERTY_REAL_MAX, bool32 AlwaysInteger = 0) { // { @@ -440,14 +449,57 @@ void Source_DeselectAll(project_data *File, memory *Memory) } } +// h: index of the total amount of properties and effects +// c: index of the amount of properties in a given effect +// p: prior property's keyframe count, so we can increment the sorted keyframe array properly +static bool32 +Layer_LoopChannels(project_state *State, memory *Memory, sorted_property_info **SortedProperty, uint16 **SortedKeyframe, block_layer *Layer, + 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); + while (*h < Amount) { + if (*h < AmountOf(Layer->Property)) { + *Property = &Layer->Property[*h]; + if (*h != 0) { + *SortedProperty += 1; + *SortedKeyframe += *p; + } + *h += 1; + *p = (**Property).Keyframe_Count; + return 1; + } else { + uint16 EffectIdx = Layer->Block_Effect_Index[*h - AmountOf(Layer->Property)]; + block_effect *Effect = (block_effect *)Memory_Block_AddressAtIndex(Memory, F_Effects, EffectIdx); + if (EffectOut) + *EffectOut = Effect; + header_effect *EffectHeader = Effect_EntryFromID(State, Effect->ID); + 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]); + *SortedKeyframe += *p; + *p = (**Property).Keyframe_Count; + *h += 1; + *c += 1; + return 1; + } + *c = 0; + } + } + Assert(*h != (Amount - 1)); + return 0; +} + inline sorted_property_info * Property_GetSortedInfo(sorted_property_info *SortedPropertyInfo, int i, int h) { + Assert(0); return SortedPropertyInfo + (i * 8) + h; } inline uint16 * Property_GetSortedArray(uint16 *SortedPropertyArray, int i, int h) { + Assert(0); return SortedPropertyArray + (i * 8 * MAX_KEYFRAMES_PER_BLOCK) + (h * MAX_KEYFRAMES_PER_BLOCK); } @@ -911,15 +963,6 @@ void Layer_SortAll(project_data *File, project_state *State, memory *Memory, sor block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); Assert(Layer->Block_Composition_Index < CompCount); CompStart[Layer->Block_Composition_Index].LayerCount++; - for (int h = 0; h < AmountOf(Layer->Property); h++) { - property_channel *Property = &Layer->Property[h]; - if (Property->Block_Bezier_Count) { - sorted_property_info *InfoLocation = Property_GetSortedInfo(SortedPropertyInfo, i, h); - uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, i, h); - Property_SortAll(Memory, State, Property, InfoLocation, ArrayLocation); - int x = 0; - } - } } h = 0, c = 0, i = 0; while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i)) { @@ -986,6 +1029,50 @@ void Layer_SortAll(project_data *File, project_state *State, memory *Memory, sor } } +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) +{ + 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) { + sorted_property_info *InfoLocation = SortedPropertyInfo + SortedPropertyPlayhead; + uint16 *ArrayLocation = SortedPropertyArray + SortedKeyframePlayhead; + Property_SortAll(Memory, State, Property, InfoLocation, ArrayLocation); + 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) { + sorted_property_info *InfoLocation = SortedPropertyInfo + SortedPropertyPlayhead; + uint16 *ArrayLocation = SortedPropertyArray + SortedKeyframePlayhead; + Property_SortAll(Memory, State, Property, InfoLocation, ArrayLocation); + SortedKeyframePlayhead += Property->Keyframe_Count; + } + SortedPropertyPlayhead++; + } + } + } + } + int a = 0; +} + sorted_file File_Sort_Push(project_data *File, project_state *State, memory *Memory) { sorted_file Sorted = {0}; @@ -996,6 +1083,12 @@ sorted_file File_Sort_Push(project_data *File, project_state *State, memory *Mem Sorted.CompArray = (sorted_comp_info *)Layer_SortedArray; Sorted.LayerArray = (sorted_layer *)((uint8 *)Layer_SortedArray + (sizeof(sorted_comp_info) * File->Comp_Count)); + uint64 SourceArraySize = sizeof(uint16) * File->Source_Count; + Sorted.Source_SortSize = SourceArraySize; + void *Source_SortedArray = Memory_PushScratch(Memory, Sorted.Source_SortSize); + 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; Sorted.Property_SortSize = PropertyArraySize + PropertyInfoSize; @@ -1004,21 +1097,16 @@ sorted_file File_Sort_Push(project_data *File, project_state *State, memory *Mem Sorted.PropertyInfo = (sorted_property_info *)Property_SortedArray; Sorted.PropertyArray = (uint16 *)((uint8 *)Property_SortedArray + PropertyInfoSize); - uint64 SourceArraySize = sizeof(uint16) * File->Source_Count; - Sorted.Source_SortSize = SourceArraySize; - void *Source_SortedArray = Memory_PushScratch(Memory, Sorted.Source_SortSize); - Arbitrary_Zero((uint8 *)Source_SortedArray, Sorted.Source_SortSize); - Sorted.SourceArray = (uint16 *)Source_SortedArray; - 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); + LayerProperty_SortAll(File, State, Memory, Sorted.LayerArray, Sorted.CompArray, Sorted.PropertyInfo, Sorted.PropertyArray, File->Layer_Count, File->Comp_Count); return Sorted; } void File_Sort_Pop(memory *Memory, uint64 Layer_SortSize, uint64 Property_SortSize, uint64 Source_SortSize) { - Memory_PopScratch(Memory, Source_SortSize); Memory_PopScratch(Memory, Property_SortSize); + Memory_PopScratch(Memory, Source_SortSize); Memory_PopScratch(Memory, Layer_SortSize); } diff --git a/effects.cpp b/effects.cpp index 98d6984..c5a07af 100644 --- a/effects.cpp +++ b/effects.cpp @@ -1,9 +1,18 @@ #include "effects_software.cpp" +#include "effects_gl.cpp" 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_Software_DrawColor(Width, Height, BytesPerPixel, EffectBitmapAddress, Color, BlendMode); + Effect_GL_DrawColor(Width, Height, BytesPerPixel, EffectBitmapAddress, ShaderProgram, Color, BlendMode); + // Effect_Software_DrawColor(Width, Height, BytesPerPixel, EffectBitmapAddress, Color, BlendMode); +} + +static void +Effect_GaussianBlur(real32 *Data, int Width, int Height, int BytesPerPixel, void *EffectBitmapAddress, uint16 ShaderProgram) +{ + real32 Radius = Data[0]; + Effect_GL_GaussianBlur(Width, Height, BytesPerPixel, EffectBitmapAddress, ShaderProgram, Radius); } diff --git a/effects_constructors.cpp b/effects_constructors.cpp index 13fec9a..7eb2143 100644 --- a/effects_constructors.cpp +++ b/effects_constructors.cpp @@ -95,15 +95,15 @@ Effect_InitEntries(project_state *State) 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); /* 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); } - // 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); // 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 new file mode 100644 index 0000000..2b8eac1 --- /dev/null +++ b/effects_gl.cpp @@ -0,0 +1,74 @@ +void GL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height, uint16 BytesPerPixel, bool32 Multisample); +static uint16 Effect_GL_InitShader(const char *Effect); +static void GL_BindDefaultVertexArrays(); + +void Effect_GL_Start(gl_effect_layer *Test, int Width, int Height, int BytesPerPixel, void *EffectBitmapAddress, uint16 ShaderProgram) +{ + GL_UpdateTexture(Test, EffectBitmapAddress, Width, Height, BytesPerPixel, 0); + + GL_BindDefaultVertexArrays(); + + glUseProgram(ShaderProgram); + + glBindFramebuffer(GL_FRAMEBUFFER, Test->FramebufferObject); + glBindRenderbuffer(GL_RENDERBUFFER, Test->Color_Renderbuffer); + + glBindTexture(GL_TEXTURE_2D, Test->Texture); + int ByteFlag = (BytesPerPixel == 4) ? GL_RGBA : GL_RGBA16; + int ByteFlag2 = (BytesPerPixel == 4) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT; + glTexImage2D(GL_TEXTURE_2D, 0, ByteFlag, Width, Height, 0, GL_RGBA, + ByteFlag2, EffectBitmapAddress); +} + +void Effect_GL_DrawColor(int Width, int Height, int BytesPerPixel, void *EffectBitmapAddress, + uint16 ShaderProgram, v4 Color, blend_mode BlendMode) +{ + 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, "Color"); + glUniform4f(Uniform, Color.r, Color.g, Color.b, Color.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); +} + +void Effect_GL_GaussianBlur(int Width, int Height, int BytesPerPixel, void *EffectBitmapAddress, + uint16 ShaderProgram, real32 Radius) +{ + 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); + + // horizontal pass + int Uniform = glGetUniformLocation(ShaderProgram, "Radius"); + glUniform1f(Uniform, Radius + 1.60f); + Uniform = glGetUniformLocation(ShaderProgram, "Direction"); + glUniform2f(Uniform, 1.0f, 0.0f); + + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + glReadPixels(0, 0, Width, Height, GL_RGBA, ByteFlag2, EffectBitmapAddress); + // + + // vertical pass + glTexImage2D(GL_TEXTURE_2D, 0, ByteFlag, Width, Height, 0, GL_RGBA, + ByteFlag2, EffectBitmapAddress); + + Radius = glGetUniformLocation(ShaderProgram, "Direction"); + glUniform2f(Uniform, 0.0f, 1.0f); + + 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/gl_calls.cpp b/gl_calls.cpp index 277db2e..1cb408a 100644 --- a/gl_calls.cpp +++ b/gl_calls.cpp @@ -29,56 +29,6 @@ const char *DefaultFragmentShaderSource = "#version 330 core\n" " FragColor = vec4(vec3(1.0f), Col.a);\n" "}\n" "}\0"; -const char *FragmentShaderEffectSource[] = {"", -"#version 330 core\n" -"out vec4 FragColor;\n" -"in vec2 TexCoord;\n" -"uniform float Start;\n" -"uniform float Mid;\n" -"uniform float End;\n" -"uniform vec4 StartCol;\n" -"uniform vec4 MidCol;\n" -"uniform vec4 EndCol;\n" -"uniform sampler2D ourTexture;\n" -"void main()\n" -"{\n" -"vec4 OutCol = texture(ourTexture, TexCoord);\n" -// individual channels -"vec4 ColorI = pow(OutCol, MidCol);\n" -"vec4 ValI = 1.0f / (EndCol - StartCol) * (ColorI - StartCol);\n" -// global channel (doesn't affect alpha) -"vec4 ColorG = pow(ValI, vec4(Mid));\n" -"vec4 ValG = 1.0f / (End - Start) * (ColorG - Start);\n" -"ValG = vec4(ValG.rgb, ValI.a);\n" -"FragColor = clamp(ValG, 0.0f, 1.0f);\n" -"}\0", -"#version 330 core\n" -"uniform float Radius;\n" -"uniform vec2 Direction;\n" -"uniform sampler2D ourTexture;\n" -"out vec4 FragColor;\n" -"in vec2 TexCoord;\n" -"\n" -"vec4 blur(sampler2D image, vec2 uv, vec2 resolution, vec2 direction) {\n" -" vec4 color = vec4(0.0f);\n" -" float Omega = Radius / 3;\n" -" float Divisor = 2*Omega*Omega;\n" -" float A2 = 1.0f / (Omega * sqrt(2*3.141592));\n" -" for (float Span = -round(Radius); Span < round(Radius); Span++) {\n" -" float Dividend = -Span * Span;\n" -" float Multiplier = A2 * exp(Dividend/Divisor);\n" -" vec2 Dir = Span*direction;\n" -" color += texture2D(image, uv + (Dir / resolution)) * Multiplier;\n" -" }\n" -" return color;\n" -"}\n" -"void main(void) {\n" -" gl_FragColor = blur(ourTexture, TexCoord, vec2(1280, 720), Direction);\n" -"}\0" -}; - - -// #include "effects_gl.cpp" static void GL_InitDefaultShader() { DefaultVertexShader = glCreateShader(GL_VERTEX_SHADER); @@ -168,6 +118,23 @@ GL_GenAndBindTexture(GLuint *GLTexture, int Width, int Height, int BytesPerPixel glTexImage2D(GL_TEXTURE_2D, 0, ByteFlag, Width, Height, 0, GL_RGBA, ByteFlag2, BufferAddress); } +static void +GL_BindDefaultVertexArrays() +{ + glBindVertexArray(DefaultVerts.VertexArrayObject); + // Switch to main buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, DefaultVerts.ElementBufferObject); + glBindBuffer(GL_ARRAY_BUFFER, DefaultVerts.VertexBufferObject); + glBufferData(GL_ARRAY_BUFFER, sizeof(GL_DefaultVertices), GL_DefaultVertices, GL_STATIC_DRAW); + // position attribute + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); + glEnableVertexAttribArray(0); + // texture coordinate (note the last parameter's offset) + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); + glEnableVertexAttribArray(1); + +} + void GL_InitHWBuffer(gl_effect_layer *Test) { diff --git a/main.cpp b/main.cpp index 76b085e..bb780c4 100644 --- a/main.cpp +++ b/main.cpp @@ -187,7 +187,7 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI, // } 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.PropertyArray); + ImGui_PropertiesPanel(File, State, UI, Memory, io, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyInfo, Sorted.PropertyArray); ImGui_ColorPanel(File, State, UI, Memory, io); ImGui_EffectsPanel(File, State, Memory, UI, io); #if STABLE @@ -221,22 +221,24 @@ Render_Main(void *Data, void *OutputBuffer, render_type RenderType, rectangle Re } static void -Layer_UpdateAllKeyframes(project_data *File, project_state *State, memory *Memory, block_layer *Layer, uint16 Index_Physical, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray, uint16 Frame_Current) +Layer_UpdateAllKeyframes(project_data *File, project_state *State, memory *Memory, block_layer *Layer, uint16 Index_Physical, + sorted_property_info *SortedProperty, uint16 *SortedKeyframe, uint16 Frame_Current) { int32 Offset = (State->Interact_Active == interact_type_keyframe_move) ? (int32)State->Interact_Offset[0] : 0; - for (int h = 0; h < AmountOf(Layer->Property); h++) { - property_channel *Property = &Layer->Property[h]; - sorted_property_info *InfoLocation = Property_GetSortedInfo(SortedPropertyInfo, Index_Physical, h); - uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, Index_Physical, h); + int h = 0, c = 0, p = 0; + property_channel *Property = NULL; + while (Layer_LoopChannels(State, Memory, &SortedProperty, &SortedKeyframe, Layer, &Property, NULL, &h, &c, &p)) + { + Assert(Property); if (Property->Block_Bezier_Count) { real32 MinY, MaxY; - Property_MinMax_Y(Memory, State, Property, InfoLocation, &MinY, &MaxY); + Property_MinMax_Y(Memory, State, Property, SortedProperty, &MinY, &MaxY); real32 Y_Increment = 1 / (MaxY - MinY); v2 FirstPointPos[3]; - bezier_point *FirstPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[0]); + bezier_point *FirstPointAddress = Bezier_LookupAddress(Memory, Property, SortedKeyframe[0]); Bezier_EvaluateValue(State, FirstPointAddress, FirstPointPos); v2 LastPointPos[3]; - bezier_point *LastPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[Property->Keyframe_Count - 1]); + bezier_point *LastPointAddress = Bezier_LookupAddress(Memory, Property, SortedKeyframe[Property->Keyframe_Count - 1]); Bezier_EvaluateValue(State, LastPointAddress, LastPointPos); if (FirstPointPos[0].x >= Frame_Current) { Property->CurrentValue = FirstPointPos[0].y; @@ -246,17 +248,17 @@ Layer_UpdateAllKeyframes(project_data *File, project_state *State, memory *Memor int KeyframeIndex = 0; for (;;) { v2 PointPos[3]; - bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex + 1]); + bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, SortedKeyframe[KeyframeIndex + 1]); Bezier_EvaluateValue(State, PointAddress, PointPos, 1, Y_Increment); if (PointPos[0].x >= Frame_Current) break; KeyframeIndex++; } v2 PointPos[3]; - bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex]); + bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, SortedKeyframe[KeyframeIndex]); Bezier_EvaluateValue(State, PointAddress, PointPos, 1, Y_Increment); v2 NextPointPos[3]; - bezier_point *NextPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex + 1]); + bezier_point *NextPointAddress = Bezier_LookupAddress(Memory, Property, SortedKeyframe[KeyframeIndex + 1]); Bezier_EvaluateValue(State, NextPointAddress, NextPointPos, 1, Y_Increment); if (PointAddress->Type == interpolation_type_hold) { Property->CurrentValue = PointPos[0].y; @@ -298,7 +300,9 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io Layer->Frame_End > Frame_Current && Layer->IsVisible) { if (State->UpdateKeyframes) { - Layer_UpdateAllKeyframes(File, State, Memory, Layer, Index_Physical, SortedPropertyInfo, SortedPropertyArray, Frame_Current); + sorted_property_info *SortedLayerProperties = SortedPropertyInfo + SortedLayerInfo->SortedPropertyStart; + uint16 *SortedLayerKeyframes = SortedPropertyArray + SortedLayerInfo->SortedKeyframeStart; + Layer_UpdateAllKeyframes(File, State, Memory, Layer, Index_Physical, SortedLayerProperties, SortedLayerKeyframes, Frame_Current); } layer_bitmap_state *BitmapState = &State->Render.Bitmap[Index_Physical]; @@ -628,6 +632,13 @@ int main(int argc, char *argv[]) { curl_state ProgHandle = {}; #endif +#if DEBUG + sprintf(State->DummyName, "test2"); + File_Open(File, State, &Memory, State->DummyName); + State->UpdateFrame = true; + State->MostRecentlySelectedLayer = 0; +#endif + while (State->IsRunning) { // State->Interact_Active = interact_type_layer_move; diff --git a/main.h b/main.h index b322173..c1b37f3 100644 --- a/main.h +++ b/main.h @@ -152,6 +152,9 @@ struct sorted_layer { uint16 Block_Layer_Index; real32 SortedOffset; + uint16 Sorted_Effect_Index[MAX_EFFECTS]; + uint16 SortedPropertyStart; + uint16 SortedKeyframeStart; }; struct sorted_file diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp index 4bdedea..dbadd11 100644 --- a/my_imgui_widgets.cpp +++ b/my_imgui_widgets.cpp @@ -36,12 +36,18 @@ ImGui_PropertyInteract_Slider(project_state *State, memory *Memory, property_cha } static void -ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io, uint16 *SortedPropertyArray) +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) { bool32 Display = 1; block_layer *Layer = NULL; + sorted_layer *SortedLayer = NULL; if (State->MostRecentlySelectedLayer > -1) { Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, State->MostRecentlySelectedLayer, 0); + sorted_comp_info SortedCompInfo = SortedCompArray[Layer->Block_Composition_Index]; + sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, &SortedCompInfo, Layer->Block_Composition_Index); + SortedLayer = &SortedLayerInfo[State->MostRecentlySelectedLayer]; if (!Layer->Occupied) Display = 0; } else { @@ -58,22 +64,49 @@ ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory * ImVec2 WindowMinAbs = ImGui::GetWindowPos(); ImVec2 WindowMaxAbs = WindowMinAbs + WindowSize; ImGui::Text("Transform"); - for (int h = 0; h < AmountOf(Layer->Property); h++) { - property_channel *Property = &Layer->Property[h]; + + sorted_property_info *InfoLocation = SortedPropertyInfo + SortedLayer->SortedPropertyStart; + uint16 *ArrayLocation = SortedPropertyArray + SortedLayer->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)) + { ImGui::PushID(Property); - if (ImGui::Button("K")) { - History_Entry_Commit(Memory, "Add keyframe"); - bezier_point Point = { 1, {(real32)State->Frame_Current, Property->CurrentValue, -1, 0, 1, 0}, interpolation_type_linear, 0, {0, 0, 0}, 0 }; - uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, State->MostRecentlySelectedLayer, h); - Bezier_Add(Memory, Property, Point, ArrayLocation); - History_Entry_End(Memory); + if ((h - 1) < AmountOf(Layer->Property)) { + if (ImGui::Button("K")) { + uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, State->MostRecentlySelectedLayer, h-1); + Property_AddKeyframe(Memory, Property, State->Frame_Current, ArrayLocation); + } + ImGui::SameLine(); + char *Name = DefaultChannel[h-1]; + 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 ((c - 1) == 0) { + ImGui::PushID(Effect->Index); + ImGui::Text(EffectHeader->Name); + 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); + } + 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); + } else { + Assert(0); + } } - ImGui::SameLine(); - char *Name = DefaultChannel[h]; - 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); ImGui::PopID(); } +#if 0 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]); @@ -81,12 +114,19 @@ ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory * ImGui::PushID(Effect.Index); ImGui::Text(EffectHeader->Name); ImGui::PopID(); - if (EffectHeader->DisplayType == effect_display_type_standard) { for (int c = 0; c < EffectHeader->Property_Count; c++) { header_property ChannelHeader = State->Property[EffectHeader->PropertyStartIndex + c]; property_channel *Property = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect.Block_Property_Index[c]); ImGui::PushID(Property); + // NOTE(fox): We might have to make a system for processing create/delete + // calls after the UI if things like the Count get incremented and invalid + // data is read. 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); + } + 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); } else if (ChannelHeader.DisplayType == property_display_type_color) { @@ -155,6 +195,7 @@ ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory * Assert(0); } } +#endif if (Layer->IsPrecomp) { block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, Layer->Block_Source_Index); ImGui::DragScalar("Width", ImGuiDataType_U16, &Comp->Width); @@ -1503,165 +1544,178 @@ ImGui_Timeline_DrawKeySheet(project_data *File, project_state *State, memory *Me static void ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, ImDrawList *draw_list, ImVec2 Increment, ImVec2 TimelineAbsolutePos, ImVec2 TimelineMoveSize, ImVec2 TimelineZoomSize, - ImVec2 TimelineSize, ImVec2 TimelineSizeWithBorder, real32 LayerIncrement, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray) + ImVec2 TimelineSize, ImVec2 TimelineSizeWithBorder, real32 LayerIncrement, + sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, + sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray) { // I'm using the draw splitter here to be able to draw the dots on top of the graph lines. State->Test.Split(draw_list, 2); - int h = 0, c = 0, i = 0; - while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i)) - { - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); - if (!Layer->IsSelected) - continue; - - int32 Frame_Start = Layer->Frame_Start; + for (int c = 0; c < File->Comp_Count; c++) { + sorted_comp_info SortedCompInfo = SortedCompArray[c]; + sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, &SortedCompInfo, 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); + if (!Layer->IsSelected) + continue; - ImGui::PushID(i); + int32 Frame_Start = Layer->Frame_Start; - if ((State->Interact_Active == interact_type_keyframe_move || - State->Interact_Active == interact_type_keyframe_rotate || - State->Interact_Active == interact_type_keyframe_scale)) - { - ImGui_WarpMouse(State, io.MousePos, TimelineAbsolutePos, TimelineAbsolutePos + TimelineSizeWithBorder); - ImVec2 DragDelta = io.MousePos - ImVec2(State->Interact_Offset[2], State->Interact_Offset[3]); - DragDelta = DragDelta + (ImVec2(State->Warp_X, State->Warp_Y) * TimelineSize); - if (io.MouseDelta.x || io.MouseDelta.y) { - State->UpdateFrame = true; - } - if (State->Interact_Active == interact_type_keyframe_move) { - // The Y increment varies between graphs, so we have to do it in the Bezier_EvaluateValue call. - State->Interact_Offset[0] = (DragDelta.x / TimelineZoomSize.x) / Increment.x; - State->Interact_Offset[1] = DragDelta.y; - } else if (State->Interact_Active == interact_type_keyframe_scale) { - State->Interact_Offset[0] = (DragDelta.x / TimelineSizeWithBorder.x * UI->TimelinePercentZoomed.x) / Increment.x; - } else if (State->Interact_Active == interact_type_keyframe_rotate) { - State->Interact_Offset[0] = (DragDelta.x / TimelineZoomSize.x); - /* - 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)); - */ - } - ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); - } + ImGui::PushID(i); - for (int h = 0; h < AmountOf(Layer->Property); h++) { - property_channel *Property = &Layer->Property[h]; - sorted_property_info *InfoLocation = Property_GetSortedInfo(SortedPropertyInfo, i, h); - uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, i, h); - ImGui::PushID(Property); - if (Property->Block_Bezier_Count) { - real32 MinY, MaxY; - Property_MinMax_Y(Memory, State, Property, InfoLocation, &MinY, &MaxY, 0); - real32 Y_Increment = 1 / (MaxY - MinY); - - real32 GraphScale = 0; - real32 GraphPos = 0; - if ((1 / Y_Increment) < 5) { - GraphScale = 0.2; - GraphPos = 0.3; - } else if ((1 / Y_Increment) > 700) { - GraphScale = 0.6; - GraphPos = 0.06; - } else { - GraphScale = 0.4; - GraphPos = 0.2; + if ((State->Interact_Active == interact_type_keyframe_move || + State->Interact_Active == interact_type_keyframe_rotate || + State->Interact_Active == interact_type_keyframe_scale)) + { + ImGui_WarpMouse(State, io.MousePos, TimelineAbsolutePos, TimelineAbsolutePos + TimelineSizeWithBorder); + ImVec2 DragDelta = io.MousePos - ImVec2(State->Interact_Offset[2], State->Interact_Offset[3]); + DragDelta = DragDelta + (ImVec2(State->Warp_X, State->Warp_Y) * TimelineSize); + if (io.MouseDelta.x || io.MouseDelta.y) { + State->UpdateFrame = true; } + if (State->Interact_Active == interact_type_keyframe_move) { + // The Y increment varies between graphs, so we have to do it in the Bezier_EvaluateValue call. + State->Interact_Offset[0] = (DragDelta.x / TimelineZoomSize.x) / Increment.x; + State->Interact_Offset[1] = DragDelta.y; + } else if (State->Interact_Active == interact_type_keyframe_scale) { + State->Interact_Offset[0] = (DragDelta.x / TimelineSizeWithBorder.x * UI->TimelinePercentZoomed.x) / Increment.x; + } else if (State->Interact_Active == interact_type_keyframe_rotate) { + State->Interact_Offset[0] = (DragDelta.x / TimelineZoomSize.x); + /* + 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)); + */ + } + ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); + } + sorted_property_info *InfoLocation = SortedPropertyInfo + SortedLayer->SortedPropertyStart; + uint16 *ArrayLocation = SortedPropertyArray + SortedLayer->SortedKeyframeStart; + int h1 = 0, c1 = 0, p = 0; + property_channel *Property = NULL; + while (Layer_LoopChannels(State, Memory, &InfoLocation, &ArrayLocation, Layer, &Property, NULL, &h1, &c1, &p)) + { + ImGui::PushID(Property); + if (Property->Block_Bezier_Count) { + real32 MinY, MaxY; + Property_MinMax_Y(Memory, State, Property, InfoLocation, &MinY, &MaxY, 0); + 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; + real32 GraphPos = 0; + if ((1 / Y_Increment) < 5) { + GraphScale = 0.2; + GraphPos = 0.3; + } else if ((1 / Y_Increment) > 700) { + GraphScale = 0.6; + GraphPos = 0.06; + } else { + GraphScale = 0.4; + GraphPos = 0.2; + } - real32 GraphMoveHeight = TimelineMoveSize.y + (TimelineZoomSize.y * GraphPos); - real32 GraphZoomHeight = TimelineZoomSize.y * GraphScale; - - uint32 GraphCol = InfoLocation->IsGraphSelected ? IM_COL32(255, 180, 150, 255) : IM_COL32(255, 255, 255, 70); - - bezier_point *PointAddress[2] = {}; - ImVec2 Keyframe_ScreenPos[6] = {}; - for (int p = 0; p < Property->Keyframe_Count; p++) { - int k = ArrayLocation[p]; - int Idx = (p % 2); - int NewIdx = Idx * 3; - int OldIdx = (NewIdx == 3) ? 0 : 3; - PointAddress[Idx] = Bezier_LookupAddress(Memory, Property, k); - - v2 PointPos[3]; - Bezier_EvaluateValue(State, PointAddress[Idx], PointPos, GraphZoomHeight, Y_Increment); - - ImVec2 Keyframe_LocalPos[3] = { V2(PointPos[0]), V2(PointPos[0] + PointPos[1]), V2(PointPos[0] + PointPos[2]) }; - ImVec2 Keyframe_LocalPos_Ratio[3]; - for (int b = 0; b < 3; b++) { - Keyframe_LocalPos_Ratio[b] = (Keyframe_LocalPos[b] - ImVec2(0, MinY)) * ImVec2(Increment.x, Y_Increment); - Keyframe_ScreenPos[NewIdx + b] = TimelineAbsolutePos + ImVec2(TimelineMoveSize.x, GraphMoveHeight) + ((ImVec2(1, -1) * Keyframe_LocalPos_Ratio[b] + ImVec2(0, 1)) * ImVec2(TimelineZoomSize.x, GraphZoomHeight)); - } + real32 GraphMoveHeight = TimelineMoveSize.y + (TimelineZoomSize.y * GraphPos); + real32 GraphZoomHeight = TimelineZoomSize.y * GraphScale; - if (State->BoxSelect) { - if (ImGui_TestBoxSelection_Point(Keyframe_ScreenPos[NewIdx], io, &PointAddress[Idx]->IsSelected)) - State->RecentSelectionType = selection_type_keyframe; - } + uint32 GraphCol = InfoLocation->IsGraphSelected ? IM_COL32(255, 180, 150, 255) : IM_COL32(255, 255, 255, 70); - State->Test.SetCurrentChannel(draw_list, 1); - - ImVec2 ButtonSize(16, 16); - - ImGui::PushID(k); - int Max = PointAddress[Idx]->IsSelected ? 2 : 0; - for (int b = Max; b >= 0; b--) { - ImU32 PointCol = ((PointAddress[Idx]->IsSelected - 1) == b) ? ImColor(0.8f, 0.5f, 0.0f, 1.0f) : ImColor(0.1f, 0.1f, 0.1f, 1.0f); - ImU32 LineCol = ((PointAddress[Idx]->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); - ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); + bezier_point *PointAddress[2] = {}; + ImVec2 Keyframe_ScreenPos[6] = {}; + for (int p = 0; p < Property->Keyframe_Count; p++) { + int k = ArrayLocation[p]; + if (Property->Keyframe_Count == 1) + int b = 0; + int Idx = (p % 2); + int NewIdx = Idx * 3; + int OldIdx = (NewIdx == 3) ? 0 : 3; + PointAddress[Idx] = Bezier_LookupAddress(Memory, Property, k); + + v2 PointPos[3]; + Bezier_EvaluateValue(State, PointAddress[Idx], PointPos, GraphZoomHeight, Y_Increment); + + ImVec2 Keyframe_LocalPos[3] = { V2(PointPos[0]), V2(PointPos[0] + PointPos[1]), V2(PointPos[0] + PointPos[2]) }; + + ImVec2 Keyframe_LocalPos_Ratio[3]; + for (int b = 0; b < 3; b++) { + Keyframe_LocalPos_Ratio[b] = (Keyframe_LocalPos[b] - ImVec2(0, MinY)) * ImVec2(Increment.x, Y_Increment); + Keyframe_ScreenPos[NewIdx + b] = TimelineAbsolutePos + ImVec2(TimelineMoveSize.x, GraphMoveHeight) + ((ImVec2(1, -1) * Keyframe_LocalPos_Ratio[b] + ImVec2(0, 1)) * ImVec2(TimelineZoomSize.x, GraphZoomHeight)); } - if (IsItemActivated) { - PointAddress[Idx]->IsSelected = b+1; + if (State->BoxSelect) { + if (ImGui_TestBoxSelection_Point(Keyframe_ScreenPos[NewIdx], io, &PointAddress[Idx]->IsSelected)) + State->RecentSelectionType = selection_type_keyframe; } - if (b != 0 && PointAddress[Idx]->IsSelected) - draw_list->AddLine(Keyframe_ScreenPos[NewIdx], Keyframe_ScreenPos[NewIdx + b], LineCol, 2.0f); + State->Test.SetCurrentChannel(draw_list, 1); + + ImVec2 ButtonSize(16, 16); + + ImGui::PushID(k); + int Max = PointAddress[Idx]->IsSelected ? 2 : 0; + for (int b = Max; b >= 0; b--) { + ImU32 PointCol = ((PointAddress[Idx]->IsSelected - 1) == b) ? ImColor(0.8f, 0.5f, 0.0f, 1.0f) : ImColor(0.1f, 0.1f, 0.1f, 1.0f); + ImU32 LineCol = ((PointAddress[Idx]->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); + ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); + } - if (b == 0) { - draw_list->AddCircleFilled(Keyframe_ScreenPos[NewIdx + b], 4, PointCol); - if (InfoLocation->IsGraphSelected) { - char buf[8]; - sprintf(buf, "%.2f", Keyframe_LocalPos[0].y); - draw_list->AddText(Keyframe_ScreenPos[NewIdx + b], 0xFFFFFFFF, buf); + if (IsItemActivated) { + PointAddress[Idx]->IsSelected = b+1; + } + + if (b != 0 && PointAddress[Idx]->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); + if (InfoLocation->IsGraphSelected) { + char buf[8]; + sprintf(buf, "%.2f", Keyframe_LocalPos[0].y); + draw_list->AddText(Keyframe_ScreenPos[NewIdx + b], 0xFFFFFFFF, buf); + } + } else { + draw_list->AddCircle(Keyframe_ScreenPos[NewIdx + b], 6, PointCol, 0, 2); } - } else { - draw_list->AddCircle(Keyframe_ScreenPos[NewIdx + b], 6, PointCol, 0, 2); - } + ImGui::PopID(); + } ImGui::PopID(); - } - ImGui::PopID(); - State->Test.SetCurrentChannel(draw_list, 0); + State->Test.SetCurrentChannel(draw_list, 0); - if (p != 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], GraphCol, 1.0f, 0); - } else { - draw_list->AddLine(Keyframe_ScreenPos[0], Keyframe_ScreenPos[3], GraphCol, 1.0f); + if (p != 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], GraphCol, 1.0f, 0); + } else { + draw_list->AddLine(Keyframe_ScreenPos[0], Keyframe_ScreenPos[3], GraphCol, 1.0f); + } } } } + ImGui::PopID(); } ImGui::PopID(); } - - ImGui::PopID(); } State->Test.Merge(draw_list); } @@ -2025,8 +2079,8 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, State->FocusedWindow = focus_timeline; } - if (State->TimelineMode == timeline_mode_graph) - ImGui_GraphInfo(File, State, Memory, UI, io, SortedPropertyInfo, SortedPropertyArray); + // if (State->TimelineMode == timeline_mode_graph) + // ImGui_GraphInfo(File, State, Memory, UI, io, SortedPropertyInfo, SortedPropertyArray); real32 FontHeight = ImGui::GetFontSize(); @@ -2123,7 +2177,9 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, IM_COL32(50, 50, 50, 230)); ImGui_Timeline_DrawGraph(File, State, Memory, UI, io, draw_list, Increment, TimelineAbsolutePos, GraphMoveSize, GraphZoomSize, - TimelineSize, TimelineSizeWithBorder, LayerIncrement, SortedPropertyInfo, SortedPropertyArray); + TimelineSize, TimelineSizeWithBorder, LayerIncrement, + SortedCompArray, SortedLayerArray, + SortedPropertyInfo, SortedPropertyArray); } ImGui_Timeline_HorizontalIncrementDraw(State, UI, draw_list, TimelineSizeWithBorder, TimelineAbsolutePos, *MainComp, TimelineZoomSize, TimelineMoveSize); -- cgit v1.2.3