diff options
author | Fox Caminiti <fox@foxcam.net> | 2022-08-21 10:20:31 -0400 |
---|---|---|
committer | Fox Caminiti <fox@foxcam.net> | 2022-08-21 10:20:31 -0400 |
commit | ed51dab429e467fc144f0bfbed70a5291c8a0a27 (patch) | |
tree | f79fc3bb577ca996b49b34f1bad5bff4a40ce6a9 | |
parent | 8c5f06c37f3c267ecd8f867cd49765c366b5f47c (diff) |
multisampled gl masks
-rw-r--r-- | bezier.cpp | 6 | ||||
-rw-r--r-- | createcalls.cpp | 140 | ||||
-rw-r--r-- | effects.cpp | 2 | ||||
-rw-r--r-- | functions.h | 23 | ||||
-rw-r--r-- | gl_calls.cpp | 111 | ||||
-rw-r--r-- | keyframes.cpp | 161 | ||||
-rw-r--r-- | main.cpp | 5 | ||||
-rw-r--r-- | main.h | 48 | ||||
-rw-r--r-- | memory.cpp | 19 | ||||
-rw-r--r-- | my_imgui_widgets.cpp | 492 | ||||
-rw-r--r-- | prenderer.cpp | 15 | ||||
-rw-r--r-- | undo.cpp | 315 |
12 files changed, 738 insertions, 599 deletions
@@ -177,9 +177,9 @@ Mask_PushPoint(mask *Mask, v2 Pos) Mask->NumberOfPoints++; } -Mask_DeletePoint(mask *Mask, uint32 p) -{ -} +// Mask_DeletePoint(mask *Mask, uint32 p) +// { +// } static void Mask_AddPointToCurve(mask *Mask, uint16 Index, real32 ratio) diff --git a/createcalls.cpp b/createcalls.cpp index 2e754af..1d4e2e5 100644 --- a/createcalls.cpp +++ b/createcalls.cpp @@ -19,11 +19,11 @@ Source_Generate(project_data *File, memory *Memory, void *Path) Source->SourceType = source_type_video; else Source->SourceType = source_type_image; - Action_Entry_Commit(Memory, action_entry_default, "Add source"); - Action_Change_Commit(Memory, &Source->Path, &Source->Path, &Path, action_change_ptr); + History_Entry_Commit(Memory, action_entry_default, "Add source"); + History_Action_Change(Memory, &Source->Path, &Source->Path, &Path, action_type_change_ptr); uint32 i = File->NumberOfSources + 1; - Action_Change_Commit(Memory, &File->NumberOfSources, &File->NumberOfSources, &i, action_change_u16); - Action_Entry_End(Memory); + History_Action_Change(Memory, &File->NumberOfSources, &File->NumberOfSources, &i, action_type_change_u16); + History_Entry_End(Memory); return 1; } else { // PostMsg(State, "File open fail..."); @@ -41,7 +41,6 @@ InitFloatProperty(char *Name, real32 Val, real32 ScrubVal, real32 MinVal = PROPE Property.MaxVal.f = MaxVal; Property.ScrubVal.f = ScrubVal; Property.VarType = type_real; - Property.GraphWindowHeight = 300; return Property; } @@ -61,30 +60,6 @@ PostMsg(project_state *State, char *msg) State->Msg = msg; } -/* -static project_layer * -CreateSolidLayer(project_data *File, memory *Memory, uint16 Width, uint16 Height, v4 Col) -{ - project_layer *Layer = CreateLayer(File, Memory); - Layer->RenderInfo = AllocateMemory(Memory, sizeof(source_image), P_SourceData); - source_image *Source = (source_image *)Layer->RenderInfo; - Source->Raster = CreateSolidBitmap(Memory, Width, Height, Col); - Layer->SourceType = source_type_image; - return Layer; -} - -static project_layer * -CreateDebugLayer(project_data *File, memory *Memory, uint16 Width, uint16 Height, int i) -{ - project_layer *Layer = CreateLayer(File, Memory); - Layer->RenderInfo = AllocateMemory(Memory, sizeof(source_image), P_SourceData); - source_image *Source = (source_image *)Layer->RenderInfo; - Source->Raster = CreateDebugBitmap(Memory, Width, Height); - Layer->SourceType = source_type_image; - return Layer; -} -*/ - // Note we use total bytes here so we can use this memory for both packed and unpacked bitmaps. void * Layer_AllocateBitmap(memory *Memory, uint16 Width, uint16 Height, uint16 BytesPerPixel) { @@ -102,16 +77,16 @@ project_layer * Layer_Init(project_data *File, memory *Memory) // from this index in the Action tree since all we need to do to "delete" // the layer is to unset this. The layer that gets made here is always at // the top of the index. - Action_Entry_Commit(Memory, action_entry_layerinit, "Create layer"); - Action_Change_Commit(Memory, &File->NumberOfLayers, &Index, &NextIndex, action_change_u16); + History_Entry_Commit(Memory, action_entry_layerinit, "Create layer"); + History_Action_Change(Memory, &File->NumberOfLayers, &Index, &NextIndex, action_type_change_u16); File->Layer[Index] = (project_layer *)AllocateMemory(Memory, sizeof(project_layer), F_Layers); project_layer *Layer = File->Layer[Index]; - Action_Entry_SetPointer(Memory, &Layer->BitmapInfo.AVInfo); + History_Entry_SetPointer(Memory, &Layer->BitmapInfo.AVInfo); - Action_Entry_End(Memory); + History_Entry_End(Memory); Layer->Name = (char *)AllocateMemory(Memory, STRING_SIZE, F_Strings); sprintf(Layer->Name, "Layer %i", NextIndex); // CSbros... @@ -208,7 +183,13 @@ Mask_TriangulateAndRasterize(memory *Memory, project_layer *Layer, mask *Mask) Mask_RasterizePoints(Mask); gl_vertex_shader VertData; - gl_effect_layer Test = Layer->BitmapInfo.Test; + gl_effect_layer Test = Layer->BitmapInfo.TestM; + gl_effect_layer Test2 = Layer->BitmapInfo.Test; + + uint32 Width = Layer->Source->Info.Width; + uint32 Height = Layer->Source->Info.Height; + + uint8 *Data = (uint8 *)Layer->BitmapInfo.BitmapBuffer; glBindFramebuffer(GL_FRAMEBUFFER, Test.FramebufferObject); @@ -223,7 +204,12 @@ Mask_TriangulateAndRasterize(memory *Memory, project_layer *Layer, mask *Mask) glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - glUseProgram(MaskShaderProgram); + glUseProgram(DefaultShaderProgram); + + int VertexMode = glGetUniformLocation(DefaultShaderProgram, "VertexMode"); + int FragmentMode = glGetUniformLocation(DefaultShaderProgram, "FragmentMode"); + glUniform1i(VertexMode, 1); + glUniform1i(FragmentMode, 0); // secondary VBO glGenVertexArrays(1, &VertData.VertexArrayObject); @@ -235,8 +221,8 @@ Mask_TriangulateAndRasterize(memory *Memory, project_layer *Layer, mask *Mask) glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); - int Scale = glGetUniformLocation(MaskShaderProgram, "CompDimensions"); - glUniform3f(Scale, (real32)Layer->Source->Info.Width, (real32)Layer->Source->Info.Height, 0); + int Scale = glGetUniformLocation(DefaultShaderProgram, "CompDimensions"); + glUniform3f(Scale, Width, Height, 0); glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP); @@ -251,11 +237,14 @@ Mask_TriangulateAndRasterize(memory *Memory, project_layer *Layer, mask *Mask) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glBindVertexArray(0); - // glStencilFunc(GL_EQUAL, 1, 0xFF); - // glStencilMask(0x00); // disables stencil writing - glBindRenderbuffer(GL_RENDERBUFFER, Test.Color_Renderbuffer); - glUseProgram(DefaultShaderProgram); + // glBindRenderbuffer(GL_RENDERBUFFER, Test.Color_Renderbuffer); + + VertexMode = glGetUniformLocation(DefaultShaderProgram, "VertexMode"); + FragmentMode = glGetUniformLocation(DefaultShaderProgram, "FragmentMode"); + glUniform1i(VertexMode, 0); + glUniform1i(FragmentMode, 1); + // // Switch to main buffer glBindBuffer(GL_ARRAY_BUFFER, DefaultVerts.VertexBufferObject); @@ -267,10 +256,6 @@ Mask_TriangulateAndRasterize(memory *Memory, project_layer *Layer, mask *Mask) glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); - //glStencilFunc(GL_EQUAL, 0, 0xFF); - //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - //glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_INT, 0); - glStencilFunc(GL_NOTEQUAL, 0, 0xFF); glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_INT, 0); @@ -279,10 +264,16 @@ Mask_TriangulateAndRasterize(memory *Memory, project_layer *Layer, mask *Mask) glStencilMask(0xFF); glStencilFunc(GL_ALWAYS, 0, 0xFF); - uint8 *Data = (uint8 *)Layer->BitmapInfo.BitmapBuffer; - glReadPixels(0, 0, Layer->Source->Info.Width, Layer->Source->Info.Height, GL_RGBA, GL_UNSIGNED_BYTE, &Data[0]); + glBindFramebuffer(GL_READ_FRAMEBUFFER, Test.FramebufferObject); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, Test2.FramebufferObject); + glBlitFramebuffer(0, 0, Width, Height, 0, 0, Width, Height, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_FRAMEBUFFER, Test2.FramebufferObject); + + glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, &Data[0]); glBindFramebuffer(GL_FRAMEBUFFER, 0); + } static void @@ -348,6 +339,7 @@ Layer_UpdateBitmap(project_data *File, project_layer *Layer, memory *Memory, int } else { Bitmap_CopyToPointer(Bitmap->Data, DestBuffer, BytesPerPixel, UnpackedSize); TestGL_InitTexture(&BitmapInfo->Test, DestBuffer, Width, Height); + TestGL_MaskTexture(&BitmapInfo->TestM, DestBuffer, Width, Height); if (Layer->NumberOfMasks) { for (int i = 0; i < Layer->NumberOfMasks; i++) { @@ -367,6 +359,16 @@ Layer_UpdateBitmap(project_data *File, project_layer *Layer, memory *Memory, int } #else Bitmap_CopyToPointer(Bitmap->Data, DestBuffer, BytesPerPixel, UnpackedSize); + TestGL_UpdateTexture(&BitmapInfo->Test, DestBuffer, Width, Height, 0); + TestGL_UpdateTexture(&BitmapInfo->TestM, DestBuffer, Width, Height, 1); + + if (Layer->NumberOfMasks) { + for (int i = 0; i < Layer->NumberOfMasks; i++) { + mask *Mask = &Layer->Mask[i]; + if (Mask->IsClosed) + Mask_TriangulateAndRasterize(Memory, Layer, Mask); + } + } #endif } @@ -404,24 +406,24 @@ LoadTestFootage(project_data *File, project_state *State, memory *Memory) { void *SourceString = String_GenerateFromChar(Memory, "../asset/24.mp4"); Source_Generate(File, Memory, SourceString); + source *Source = &File->Source[0]; Layer_CreateFromSource(File, State, Memory, Source); SelectLayer(File->Layer[0], State, 0); property_channel *Property = &File->Layer[0]->x; - // for (int i = 0; i < 15; i++) - // ManualKeyframeInsertF(Property, Memory, i*2, i*2*100); - ManualKeyframeInsertF(Property, Memory, 1, 100); - ManualKeyframeInsertF(Property, Memory, 3, 300); - ManualKeyframeInsertF(Property, Memory, 23, 2300); - ManualKeyframeInsertF(Property, Memory, 5, 500); + // for (int i = 0; i < 16; i++) + // Keyframe_Insert(Property, Memory, i*2, i*2*100); + // Keyframe_Insert(Property, Memory, 1, 100); + // Keyframe_Insert(Property, Memory, 15, 1500); + // Keyframe_Insert(Property, Memory, 31, 3100); + + // History_Undo(Memory); + // History_Redo(Memory); + Property->IsToggled = true; - Property->IsGraphToggled = true; - Property->GraphLength = 150; - Property->GraphYOffset = (Property->GraphWindowHeight - Property->GraphLength)/2; // AddEffect(File->Layer[0], Memory, 3); - /* mask *Mask = &File->Layer[0]->Mask[0]; File->Layer[0]->NumberOfMasks = 1; Mask->Point[0].Pos = V2(200, 200); @@ -449,7 +451,7 @@ LoadTestFootage(project_data *File, project_state *State, memory *Memory) Mask->Point[4].HandleBezier = true; Mask->NumberOfPoints = 5; - */ + Mask->IsClosed = true; // if (!Source_Generate(File, Memory, "../asset/test.png")) // PostMsg(State, "File open fail..."); @@ -457,10 +459,10 @@ LoadTestFootage(project_data *File, project_state *State, memory *Memory) // PostMsg(State, "File open fail..."); // property_channel *Property = &File->Layer[0]->x; - // ManualKeyframeInsertF(Property, Memory, 1, 500); - // ManualKeyframeInsertF(Property, Memory, 30, 800); - // ManualKeyframeInsertF(Property, Memory, 15, 400); - // ManualKeyframeInsertF(Property, Memory, 20, 100); + // Keyframe_Insert(Property, Memory, 1, 500); + // Keyframe_Insert(Property, Memory, 30, 800); + // Keyframe_Insert(Property, Memory, 15, 400); + // Keyframe_Insert(Property, Memory, 20, 100); // Property->IsToggled = true; // Property->IsGraphToggled = true; // Property->GraphLength = 150; @@ -509,8 +511,8 @@ CreateDemoScene(project_data *File, memory *Memory) Layer2->y.CurrentValue.f = 720/2; Layer2->StartFrame = 0; Layer2->EndFrame = File->EndFrame; - ManualKeyframeInsertF(&Layer2->rotation, Memory, 2, 0); - ManualKeyframeInsertF(&Layer2->rotation, Memory, 50, 360); + Keyframe_Insert(&Layer2->rotation, Memory, 2, 0); + Keyframe_Insert(&Layer2->rotation, Memory, 50, 360); Layer2->rotation.IsToggled = true; Layer2->scale.IsToggled = true; project_layer *Layer3 = CreateSolidLayer(File, Memory, 157, 163, V4(1.0, 0.3, 0.2, 1.0)); @@ -519,9 +521,9 @@ CreateDemoScene(project_data *File, memory *Memory) Layer3->opacity.CurrentValue.f = 0.5f; Layer3->StartFrame = 0; Layer3->EndFrame = File->EndFrame; - ManualKeyframeInsertF(&Layer3->x, Memory, 2, Layer3->x.CurrentValue.f); - ManualKeyframeInsertF(&Layer3->x, Memory, 30, Layer3->x.CurrentValue.f+(1280/2)); - ManualKeyframeInsertF(&Layer3->x, Memory, 60, Layer3->x.CurrentValue.f+(1280/3)); + Keyframe_Insert(&Layer3->x, Memory, 2, Layer3->x.CurrentValue.f); + Keyframe_Insert(&Layer3->x, Memory, 30, Layer3->x.CurrentValue.f+(1280/2)); + Keyframe_Insert(&Layer3->x, Memory, 60, Layer3->x.CurrentValue.f+(1280/3)); Layer3->x.IsToggled = true; Layer3->y.IsToggled = true; #endif @@ -541,8 +543,8 @@ CreateGrid(project_data *File, memory *Memory) { Layer->opacity.CurrentValue.f = 0.25; Layer->StartFrame = 0; Layer->EndFrame = File->EndFrame; - ManualKeyframeInsertF(&Layer->rotation, Memory, i, 0); - ManualKeyframeInsertF(&Layer->rotation, Memory, 40+i, 360); + Keyframe_Insert(&Layer->rotation, Memory, i, 0); + Keyframe_Insert(&Layer->rotation, Memory, 40+i, 360); } } } diff --git a/effects.cpp b/effects.cpp index 0820cab..61b7729 100644 --- a/effects.cpp +++ b/effects.cpp @@ -251,7 +251,7 @@ GaussianBlur(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, prop uint8 *Data = (uint8 *)BitmapInfo->BitmapBuffer; glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, &Data[0]); - TestGL_InitTexture(&BitmapInfo->Test, Data, Width, Height); + TestGL_UpdateTexture(&BitmapInfo->Test, Data, Width, Height, 0); // glBindRenderbuffer(GL_RENDERBUFFER, Test->RBO); /* glUseProgram(TGL.ShaderProgram); diff --git a/functions.h b/functions.h index 39e4f8d..3d4184d 100644 --- a/functions.h +++ b/functions.h @@ -22,7 +22,7 @@ static cached_bitmap * AV_LoadVideoFrame(source *Source, memory *Memory, int32 T static cached_bitmap * Cache_CheckBitmap(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, int32 TimelineFrame); -static void TestGL_InitTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height); +static void TestGL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height, bool32 Multisample); static gl_effect TestGL_MaskInitVerts(mask Mask); static void TestGL_InitVerts(); static gl_vertex_shader TestGL_MaskUploadVerts(project_layer *Layer, mask *Mask); @@ -32,13 +32,20 @@ static v2 ImGui_ScreenPointToCompUV(ImVec2 ViewportMin, ImVec2 CompPos, ImVec2 C void Bezier_CubicCalcPoints(v2 p1, v2 p2, v2 p3, v2 p4, void *Data, uint32 *Increment); -static void Action_Change_Commit(memory *Memory, void *DataLocation, void *OriginalData, void *NewData, action_change_type ActionChange); -static void Action_Change_Commit_SwapBool(memory *Memory, bool32 *Bool); -static void Action_Entry_SetPointer(memory *Memory, void *Data); -static void Action_Entry_Commit(memory *Memory, action_entry_type Type, char *Name); -static void Action_Entry_End(memory *Memory); -static void Action_Undo(memory *Memory); -static void Action_Redo(memory *Memor); + +static void History_Undo(memory *Memory); +static void History_Redo(memory *Memory); + +static void History_Entry_Commit(memory *Memory, action_entry_type Type, char *Name); +static void History_Entry_End(memory *Memory); +static void History_Entry_SetPointer(memory *Memory, void *Data); + +static void History_Action_Change(memory *Memory, void *DataLocation, void *OriginalData, void *NewData, action_type ActionChange); +static void History_Action_Change_SwapBool(memory *Memory, bool32 *Bool); +static void History_Action_Change_Increment(memory *Memory, void *Data, action_type); +static void History_Action_Shift(memory *Memory, action_type ActionChange, void *DataAddress, int16 Direction, int16 Index); +static void History_Action_Undo(memory *Memory); +static void History_Action_Redo(memory *Memory); #if ARM static void NEON_RenderLayer(transform_info T, comp_buffer *Buffer, rectangle RenderRegion); diff --git a/gl_calls.cpp b/gl_calls.cpp index 68c2882..fcb7fd9 100644 --- a/gl_calls.cpp +++ b/gl_calls.cpp @@ -2,30 +2,30 @@ const char *DefaultVertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" "layout (location = 1) in vec2 aTexCoord;\n" "out vec2 TexCoord;\n" -"void main()\n" -"{\n" -" gl_Position = vec4(aPos, 1.0);\n" -" TexCoord = aTexCoord;\n" -"}\0"; -const char *MaskVertexShaderSource = "#version 330 core\n" -"layout (location = 0) in vec3 aPos;\n" -"layout (location = 1) in vec2 aTexCoord;\n" -"out vec2 TexCoord;\n" +"uniform int VertexMode;\n" "uniform vec3 CompDimensions;\n" "void main()\n" "{\n" -" gl_Position = vec4(vec2(aPos.x / CompDimensions.x, aPos.y / CompDimensions.y) * 2 - 1.0f, 0.0f, 1.0);\n" +" if (VertexMode == 0) {\n" +" gl_Position = vec4(aPos, 1.0);\n" +"} else {\n" +" gl_Position = vec4(vec2(aPos.x / CompDimensions.x, aPos.y / CompDimensions.y) * 2 - 1.0f, 0.0f, 1.0);\n" +"}\n" " TexCoord = aTexCoord;\n" "}\0"; const char *DefaultFragmentShaderSource = "#version 330 core\n" "out vec4 FragColor;\n" "in vec2 TexCoord;\n" "uniform sampler2D Texture;\n" +"uniform int FragmentMode;\n" "void main()\n" "{\n" -"vec4 ColTest = texture(Texture, TexCoord);\n" -"ColTest.r += 0.5f;\n" -"FragColor = ColTest;\n" +"vec4 Col = texture(Texture, TexCoord);\n" +" if (FragmentMode == 0) {\n" +" FragColor = Col;\n" +"} else {\n" +" FragColor = vec4(vec3(1.0f), Col.a);\n" +"}\n" "}\0"; #if 0 const char *fragmentShaderSource = "#version 330 core\n" @@ -117,32 +117,8 @@ static void TestGL_InitDefaultShader() { printf("Shader linkage fail:\n %s", infoLog); } - uint32 MaskVertexShader = glCreateShader(GL_VERTEX_SHADER); - - glShaderSource(MaskVertexShader, 1, &MaskVertexShaderSource, NULL); - glCompileShader(MaskVertexShader); - - glGetShaderiv(MaskVertexShader, GL_COMPILE_STATUS, &success); - if(!success) { - glGetProgramInfoLog(DefaultShaderProgram, 512, NULL, infoLog); - printf("Shader linkage fail:\n %s", infoLog); - } - - MaskShaderProgram = glCreateProgram(); - - glAttachShader(MaskShaderProgram, MaskVertexShader); - glAttachShader(MaskShaderProgram, DefaultFragmentShader); - glLinkProgram(MaskShaderProgram); - - glGetProgramiv(MaskShaderProgram, GL_LINK_STATUS, &success); - if(!success) { - glGetProgramInfoLog(MaskShaderProgram, 512, NULL, infoLog); - printf("Shader linkage fail:\n %s", infoLog); - } - // Default vertex shader is still needed to link to other effects. glDeleteShader(DefaultFragmentShader); - glDeleteShader(MaskVertexShader); } static void TestGL_InitDefaultVerts() { @@ -152,8 +128,6 @@ static void TestGL_InitDefaultVerts() { 1, 2, 3 }; - glEnable(GL_MULTISAMPLE); - // Indices! glGenVertexArrays(1, &DefaultVerts.VertexArrayObject); @@ -176,32 +150,57 @@ static void TestGL_InitDefaultVerts() { } void -TestGL_InitTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height) +TestGL_InitTexture(gl_effect_layer *Test) { + glGenFramebuffers(1, &Test->FramebufferObject); glGenTextures(1, &Test->Texture); - glBindTexture(GL_TEXTURE_2D, Test->Texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glGenRenderbuffers(1, &Test->Color_Renderbuffer); + glGenRenderbuffers(1, &Test->Stencil_Renderbuffer); + Test->Initialized = true; +} +void +TestGL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height, bool32 Multisample) +{ glViewport(0, 0, Width, Height); - glGenFramebuffers(1, &Test->FramebufferObject); + if (!Test->Initialized) { + TestGL_InitTexture(Test); + } - glGenRenderbuffers(1, &Test->Color_Renderbuffer); - glBindRenderbuffer(GL_RENDERBUFFER, Test->Color_Renderbuffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, Width, Height); + GLenum Target = GL_TEXTURE_2D; + if (Multisample) + Target = GL_TEXTURE_2D_MULTISAMPLE; + + glBindTexture(Target, Test->Texture); + glTexParameteri(Target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(Target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(Target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + if (Multisample) { + glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB, Width, Height, GL_TRUE); + glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); - GLuint Stencil_Renderbuffer = 0; - glGenRenderbuffers(1, &Stencil_Renderbuffer); - glBindRenderbuffer( GL_RENDERBUFFER, (GLuint)Stencil_Renderbuffer ); - glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, Width, Height ); + glBindRenderbuffer(GL_RENDERBUFFER, Test->Color_Renderbuffer); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, Width, Height); + + glBindRenderbuffer(GL_RENDERBUFFER, (GLuint)Test->Stencil_Renderbuffer ); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_STENCIL_INDEX8, Width, Height ); + } else { + glBindTexture(GL_TEXTURE_2D, 0); + + glBindRenderbuffer(GL_RENDERBUFFER, Test->Color_Renderbuffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, Width, Height); + + glBindRenderbuffer(GL_RENDERBUFFER, (GLuint)Test->Stencil_Renderbuffer ); + glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, Width, Height ); + } glBindFramebuffer(GL_FRAMEBUFFER, Test->FramebufferObject); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, Test->Color_Renderbuffer); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, Stencil_Renderbuffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, Test->Stencil_Renderbuffer); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { @@ -209,8 +208,8 @@ TestGL_InitTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Heigh Assert(0); } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, - GL_UNSIGNED_BYTE, Data); + // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, + // GL_UNSIGNED_BYTE, Data); glBindFramebuffer(GL_FRAMEBUFFER, 0); } diff --git a/keyframes.cpp b/keyframes.cpp index c9f7813..7fb7c13 100644 --- a/keyframes.cpp +++ b/keyframes.cpp @@ -81,25 +81,6 @@ CheckKeyframeSort(property_channel *Property, int32 Increment, int32 b) } static void -ShiftKeyframeIndex(property_channel *Property, int16 Increment, int16 StopAt) { - /* - if (Increment > 0) { - int16 i = Property->NumberOfTotalKeyframes - 1; - while (i > StopAt) { - Property->SortedIndex[i + Increment] = Property->SortedIndex[i]; - i--; - } - } else { - int16 i = StopAt; - while (i < Property->NumberOfTotalKeyframes - 1) { - Property->SortedIndex[i] = Property->SortedIndex[i + Increment]; - i++; - } - } - */ -} - -static void DeleteKeyframeFromMemory(property_channel *Property, int16 Increment, int16 StopAt) { if (Increment > 0) { int16 i = Property->NumberOfTotalKeyframes - 1; @@ -176,22 +157,6 @@ DeleteSelectedKeyframes(project_data *File, memory *Memory) } static void -CalculatePropertyMinMax(property_channel *Property) { - Property->LocalMaxVal = Property->MinVal; - Property->LocalMinVal = Property->MaxVal; - for (int16 i = 0; i < Property->NumberOfTotalKeyframes; i++) { - keyframe *Keyframe = KeyframeLookup(Property, i); - Property->LocalMinVal.f = Ceil(Property->LocalMinVal.f, Keyframe->Value.f); - Property->LocalMaxVal.f = Floor(Property->LocalMaxVal.f, Keyframe->Value.f); - } - if (Property->LocalMinVal.f == Property->LocalMaxVal.f) - { - Property->LocalMaxVal.f += 1; - } -} - - -static void IncrementKeyframes(property_channel *Property, int16 Increment) { /* @@ -262,78 +227,123 @@ ClampSurroundingKeyframeHandles(property_channel *Property, int16 b) { } - static void -ManualKeyframeInsertF(property_channel *Property, memory *Memory, int32 CurrentFrame, real32 Val) -{ - if (!(Property->NumberOfTotalKeyframes % MAX_KEYFRAMES_PER_BLOCK)) { - CreateKeyframeBlock(Property, Memory); +ShiftKeyframes(property_channel *Property, int16 Increment, int16 StopAt) { + if (Increment > 0) { + int16 i = Property->NumberOfTotalKeyframes - 1; + while (i >= StopAt) { + keyframe *NextKeyframe = KeyframeLookup(Property, i + Increment); + keyframe *CurrentKeyframe = KeyframeLookup(Property, i); + *NextKeyframe = *CurrentKeyframe; + i--; + } + } else { + int16 i = StopAt; + while (i <= Property->NumberOfTotalKeyframes - 1) { + keyframe *NextKeyframe = KeyframeLookup(Property, i - Increment); + keyframe *CurrentKeyframe = KeyframeLookup(Property, i); + *CurrentKeyframe = *NextKeyframe; + i++; + } } - keyframe *Keyframe = NULL; +} + +static uint32 +Keyframe_FindClosestIndex(property_channel *Property, int32 CurrentFrame, bool32 *Overlapping) +{ if (Property->NumberOfTotalKeyframes == 0) { - Keyframe = &Property->KeyframeBlock[0]->Keyframe[0]; - Property->NumberOfTotalKeyframes++; + *Overlapping = false; + return 0; } else { uint32 Index = Property->NumberOfTotalKeyframes; - bool32 Found = false; - while (!Found) { + for (;;) { keyframe *PreviousKeyframe = KeyframeLookup(Property, Index - 1); keyframe *NextKeyframe = KeyframeLookup(Property, Index + 1); if (PreviousKeyframe->FrameNumber < CurrentFrame) { - if (NextKeyframe->FrameNumber >= CurrentFrame || Index == Property->NumberOfTotalKeyframes) { + if (NextKeyframe->FrameNumber >= CurrentFrame) { keyframe *CurrentKeyframe = KeyframeLookup(Property, Index); - if (CurrentKeyframe->FrameNumber == CurrentFrame || Index == Property->NumberOfTotalKeyframes) { - Keyframe = CurrentKeyframe; - Property->NumberOfTotalKeyframes++; + if (CurrentKeyframe->FrameNumber == CurrentFrame) { + *Overlapping = true; + return Index; } else { if (CurrentKeyframe->FrameNumber > CurrentFrame) { - Keyframe = KeyframeLookup(Property, Index); + *Overlapping = false; + return Index; } else { - Keyframe = KeyframeLookup(Property, Index + 1); + *Overlapping = false; + return Index + 1; } } - Found = true; + } else if (Index == Property->NumberOfTotalKeyframes) { + *Overlapping = false; + return Index; } else { Index += (Property->NumberOfTotalKeyframes - Index) / 2; } // We can only progress from this first if statement if // NextKeyframe is valid, so we need to check for these conditions. } else if (Property->NumberOfTotalKeyframes == 1) { - Property->NumberOfTotalKeyframes++; - Keyframe = KeyframeLookup(Property, 0); - Found = true; + keyframe *Keyframe = KeyframeLookup(Property, 0); + *Overlapping = (Keyframe->FrameNumber == CurrentFrame); + Index = 0; + return Index; } else if (Property->NumberOfTotalKeyframes == 2) { - keyframe *FirstKeyframe = KeyframeLookup(Property, Index + 1); - if (FirstKeyframe->FrameNumber > CurrentFrame) - Keyframe = KeyframeLookup(Property, 0); - else - Keyframe = KeyframeLookup(Property, 1); - Property->NumberOfTotalKeyframes++; - Found = true; + // We know we're smaller than index 1, so we just need to compare 0. + keyframe *FirstKeyframe = KeyframeLookup(Property, 0); + Index = (FirstKeyframe->FrameNumber > CurrentFrame) ? 0 : 1; + keyframe *Keyframe = KeyframeLookup(Property, Index); + *Overlapping = (Keyframe->FrameNumber == CurrentFrame); + return Index; } else { Index = Index / 2; } } } - Assert(!(Keyframe == NULL)) +} + +static void +Keyframe_Insert(property_channel *Property, memory *Memory, int32 CurrentFrame, real32 Val) +{ + if (!(Property->NumberOfTotalKeyframes % MAX_KEYFRAMES_PER_BLOCK)) { + CreateKeyframeBlock(Property, Memory); + } + keyframe *Keyframe = NULL; + bool32 Overlapping = 0; + uint32 Index = Keyframe_FindClosestIndex(Property, CurrentFrame, &Overlapping); + Keyframe = KeyframeLookup(Property, Index); + if (Overlapping && Val == Keyframe->Value.f) + return; + if (!Overlapping) { + History_Entry_Commit(Memory, action_entry_default, "Insert keyframe"); + if (Index != Property->NumberOfTotalKeyframes) { + History_Action_Shift(Memory, action_type_shift_keyframe, Property, 1, Index); + ShiftKeyframes(Property, 1, Index); + } - Keyframe->FrameNumber = CurrentFrame; - Keyframe->Value.f = Val; - Keyframe->Type = bezier; - Keyframe->TangentLeft = V2(-1, 0); - Keyframe->TangentRight = V2(1, 0); - Keyframe->ImguiID = RandomGlobalIncrement++; - CalculatePropertyMinMax(Property); + History_Action_Change_Increment(Memory, &Property->NumberOfTotalKeyframes, action_type_change_u16); + History_Action_Change(Memory, &Keyframe->FrameNumber, &Keyframe->FrameNumber, &CurrentFrame, action_type_change_i32); + History_Action_Change_Increment(Memory, &RandomGlobalIncrement, action_type_change_u32); + History_Action_Change(Memory, &Keyframe->ImguiID, &Keyframe->ImguiID, &RandomGlobalIncrement, action_type_change_u32); + + Keyframe->Type = bezier; + Keyframe->TangentLeft = V2(-1, 0); + Keyframe->TangentRight = V2(1, 0); + } else { + History_Entry_Commit(Memory, action_entry_default, "Adjust keyframe value"); + } + History_Action_Change(Memory, &Keyframe->Value.f, &Keyframe->Value.f, &Val, action_type_change_r32); + // Keyframe->Value.f = Val; + + History_Entry_End(Memory); } static void CalculateKeyframesLinearly(uint16 CurrentFrame, struct property_channel *Property) { - /* - keyframe *FirstKeyframe = KeyframeLookupIndex(Property, 0); + keyframe *FirstKeyframe = KeyframeLookup(Property, 0); - keyframe *LastKeyframe = KeyframeLookupIndex(Property, Property->NumberOfTotalKeyframes - 1); + keyframe *LastKeyframe = KeyframeLookup(Property, Property->NumberOfTotalKeyframes - 1); if (Property->NumberOfTotalKeyframes == 0) { // do nothing } @@ -347,8 +357,8 @@ CalculateKeyframesLinearly(uint16 CurrentFrame, struct property_channel *Propert } else if (Property->NumberOfTotalKeyframes > 1) { for (int i = 0; i < (Property->NumberOfTotalKeyframes - 1); i++) { - keyframe *Keyframe = KeyframeLookupIndex(Property, i); - keyframe *NextKeyframe = KeyframeLookupIndex(Property, i+1); + keyframe *Keyframe = KeyframeLookup(Property, i); + keyframe *NextKeyframe = KeyframeLookup(Property, i+1); if (CurrentFrame >= Keyframe->FrameNumber && CurrentFrame <= NextKeyframe->FrameNumber) { @@ -386,5 +396,4 @@ CalculateKeyframesLinearly(uint16 CurrentFrame, struct property_channel *Propert } } } - */ } @@ -45,6 +45,7 @@ SDL_atomic_t CompletedEntries; static bool32 IsRendering = false; static instruction_mode InstructionMode = instruction_mode_scalar; static uint32 RandomGlobalIncrement = 0; +static bool32 test = 1; render_entry Entries[256]; @@ -230,7 +231,7 @@ int main(int argc, char *argv[]) { InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Strings, "Strings"); InitMemoryTable(&GlobalMemory, &Memory, (uint64)200 * 1024 * 1024, B_LayerBitmaps, "Layer buffer"); - InitMemoryTable(&GlobalMemory, &Memory, (uint64)600 * 1024 * 1024, B_LoadedBitmaps, "Loaded bitmap buffer"); + InitMemoryTable(&GlobalMemory, &Memory, (uint64)200 * 1024 * 1024, B_LoadedBitmaps, "Loaded bitmap buffer"); Memory.Scratch = AllocateMemory(&Memory, (uint64)64*1024*1024, B_LayerBitmaps); @@ -464,7 +465,7 @@ int main(int argc, char *argv[]) { #if DEBUG ImGui_DebugUndoTree(&File, &Memory); if (Debug.ToggleWindow) { - ImGui::ShowDemoWindow(); + // ImGui::ShowDemoWindow(); ImGui_DebugMemoryViewer(&File, &Memory); } #endif @@ -71,6 +71,18 @@ struct cached_bitmap { uint32 Frame; // What frame it is. }; +enum action_type { + action_type_change_u16, + action_type_change_i16, + action_type_change_u32, + action_type_change_i32, + action_type_change_r32, + action_type_change_u64, + action_type_change_ptr, + action_type_change_string, + action_type_shift_keyframe +}; + enum action_entry_type { action_entry_layerinit, action_entry_default @@ -183,23 +195,15 @@ float DefaultVertices[] = { struct gl_effect_layer { + bool32 Initialized; GLuint Texture; GLuint FramebufferObject; uint32 Color_Renderbuffer; + uint32 Stencil_Renderbuffer; }; static gl_vertex_shader GL_Vertices; -enum action_change_type { - action_change_u16, - action_change_i16, - action_change_u32, - action_change_i32, - action_change_r32, - action_change_u64, - action_change_ptr, - action_change_string, -}; union val { real32 f; @@ -239,16 +243,7 @@ struct property_channel { val ScrubVal; // increment when dragging on sliders, etc. var_type VarType; - // TODO(fox): Probably shouldn't store these in the file... - // UI - val LocalMaxVal; - val LocalMinVal; bool32 IsToggled; - bool32 IsGraphToggled; - real32 GraphLength; // represented in actual screen pixels - real32 GraphYOffset; - // The size of the window enclosing the graph - uint16 GraphWindowHeight; }; struct property_header @@ -260,7 +255,6 @@ struct property_header val MaxVal; }; - // Information about a particular file. enum source_type { @@ -298,6 +292,7 @@ struct layer_bitmap_info { int32 FrameOffset; // The "true" position of the layer, separate from StartFrame. Starts at zero and only gets incremented when the layer is moved. bool32 ToUpdate = 1; gl_effect_layer Test; + gl_effect_layer TestM; // TODO(fox): Find a better place to store this. Either give effects a more // fleshed-out API to add things to a struct like this or integrate into ImGui. @@ -541,6 +536,14 @@ enum focused_window focus_timeline }; +struct ui_graph { + property_channel *ChannelViewed; + real32 WindowYOffset = 300; + real32 UpperVal; + real32 LowerVal; + uint16 GraphWindowHeight; // The size of the window enclosing the graph +}; + struct ui { real32 TimelineSplit = 600; @@ -578,6 +581,9 @@ struct ui focused_window FocusedWindow; // Convenience for adding window-specific hotkeys. + ui_graph Graph[4]; + uint16 NumberOfGraphsEnabled; + bool32 TemporaryUpdateOverride; }; @@ -612,7 +618,7 @@ struct timeline_properties uint16 FramePadding; uint16 LayerPadding; uint16 TimelineCurrentFrame; - int16 TimelineCurrentLayer; + int16 TimelineCurrentLayer; // Signed as a shortcut for invalid on -1 uint16 InfoTimelineSplit; bool32 DrawTimeline; bool32 DrawEffectPanel; @@ -25,6 +25,25 @@ AllocateMemory(memory *Memory, uint64 Size, memory_table_list TableName) { return Address; } +// Returns the address and THEN advances +static void* +Memory_Advance(memory *Memory, uint64 Size, memory_table_list TableName) { + return AllocateMemory(Memory, Size, TableName); +} + +// Rewinds and THEN returns the address +static void* +Memory_Rewind(memory *Memory, uint64 Size, memory_table_list TableName) { + void *Address; + memory_table *Table = &Memory->Slot[TableName]; + if (Table->CurrentPosition - Size < 0) { + return NULL; + } + Table->CurrentPosition -= Size; + Address = (ptrsize *)((uint8 *)Table->Address + Table->CurrentPosition); + return Address; +} + // Returns 0-1 range wherever Pointer is in relation to StartingPointer to Size*Amount. static real32 Memory_NormalizedPosition(void *StartingPointer, uint32 Amount, uint32 Size, void *Pointer) diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp index 54fa9c1..ea2e314 100644 --- a/my_imgui_widgets.cpp +++ b/my_imgui_widgets.cpp @@ -43,6 +43,7 @@ ImGui_KeyframeDragging(project_data *File, project_state *State, ui *UI, propert // Cache.Frame[File.CurrentFrame].Cached = false; } } + /* if (Type != 0) { if (Type == 1) @@ -66,6 +67,7 @@ ImGui_KeyframeDragging(project_data *File, project_state *State, ui *UI, propert State->UpdateFrame = true; State->UpdateKeyframes = true; } + */ } } } @@ -85,10 +87,10 @@ ImGui_InteractSliderProperty(project_state *State, memory *Memory, property_chan if (ImGui::IsKeyPressed(ImGuiKey_Escape)) { Property->CurrentValue.f = State->InteractCache[0]; } else { - Action_Entry_Commit(Memory, action_entry_default, "Tranforms interact"); - Action_Change_Commit(Memory, &Property->CurrentValue.f, &State->InteractCache[0], - &Property->CurrentValue.f, action_change_r32); - Action_Entry_End(Memory); + History_Entry_Commit(Memory, action_entry_default, "Tranforms interact"); + History_Action_Change(Memory, &Property->CurrentValue.f, &State->InteractCache[0], + &Property->CurrentValue.f, action_type_change_r32); + History_Entry_End(Memory); } State->UpdateFrame = true; } @@ -230,7 +232,7 @@ ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory * property_channel *Property = &Layer->Property[h]; ImGui::PushID(Property); if (ImGui::Button("K")) - ManualKeyframeInsertF(Property, Memory, File->CurrentFrame, Property->CurrentValue.f); + Keyframe_Insert(Property, Memory, File->CurrentFrame, Property->CurrentValue.f); ImGui::SameLine(); ImGui_InteractSliderProperty(State, Memory, Property); ImGui::PopID(); @@ -484,18 +486,18 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, memory *Memory, } if (ImGui::IsItemActivated() && b == 0) { if (p == 0 && State->Pen.IsActive) { - Action_Entry_Commit(Memory, action_entry_default, "Close mask path"); - Action_Change_Commit_SwapBool(Memory, &State->Pen.IsActive); - Action_Change_Commit_SwapBool(Memory, &Mask->IsClosed); + History_Entry_Commit(Memory, action_entry_default, "Close mask path"); + History_Action_Change_SwapBool(Memory, &State->Pen.IsActive); + History_Action_Change_SwapBool(Memory, &Mask->IsClosed); // State->Pen.IsActive = false; // Mask->IsClosed = true; - Action_Entry_End(Memory); + History_Entry_End(Memory); } else if (io.KeyCtrl) { // TODO(fox): Mask delete! } else if (io.KeyAlt) { - Action_Entry_Commit(Memory, action_entry_default, "Switch handles on point"); - Action_Change_Commit_SwapBool(Memory, &Point0->HandleBezier); - Action_Entry_End(Memory); + History_Entry_Commit(Memory, action_entry_default, "Switch handles on point"); + History_Action_Change_SwapBool(Memory, &Point0->HandleBezier); + History_Entry_End(Memory); } Point0->IsSelected = true; } @@ -651,9 +653,9 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, memory *Memory, Mask->NumberOfPoints = 0; State->Pen.IsActive = false; } else { - Action_Entry_Commit(Memory, action_entry_default, "Path adding exited"); - Action_Change_Commit_SwapBool(Memory, &State->Pen.IsActive); - Action_Entry_End(Memory); + History_Entry_Commit(Memory, action_entry_default, "Path adding exited"); + History_Action_Change_SwapBool(Memory, &State->Pen.IsActive); + History_Entry_End(Memory); } IsDeactivated = false; // just in case escape and mouse release happen simultaneously } @@ -662,32 +664,32 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, memory *Memory, if (Mask->NumberOfPoints == 1) { uint16 PreviousNumberOfMasks = Layer->NumberOfMasks - 1; uint16 PreviousNumberOfPoints = Mask->NumberOfPoints - 1; - Action_Entry_Commit(Memory, action_entry_default, "Create mask"); - Action_Change_Commit(Memory, &Layer->NumberOfMasks, &PreviousNumberOfMasks, - &Layer->NumberOfMasks, action_change_u16); - Action_Change_Commit(Memory, &Mask->NumberOfPoints, &PreviousNumberOfPoints, - &Mask->NumberOfPoints, action_change_u16); - Action_Entry_End(Memory); + History_Entry_Commit(Memory, action_entry_default, "Create mask"); + History_Action_Change(Memory, &Layer->NumberOfMasks, &PreviousNumberOfMasks, + &Layer->NumberOfMasks, action_type_change_u16); + History_Action_Change(Memory, &Mask->NumberOfPoints, &PreviousNumberOfPoints, + &Mask->NumberOfPoints, action_type_change_u16); + History_Entry_End(Memory); } else { uint16 PreviousNumberOfPoints = Mask->NumberOfPoints - 1; uint16 Empty = 0; mask_point *CurrentPoint = &Mask->Point[Mask->NumberOfPoints-1]; - Action_Entry_Commit(Memory, action_entry_default, "Add point"); - Action_Change_Commit(Memory, &Mask->NumberOfPoints, &PreviousNumberOfPoints, - &Mask->NumberOfPoints, action_change_u16); - Action_Change_Commit(Memory, &CurrentPoint->Pos.x, &Empty, - &CurrentPoint->Pos.x, action_change_r32); - Action_Change_Commit(Memory, &CurrentPoint->Pos.y, &Empty, - &CurrentPoint->Pos.y, action_change_r32); - Action_Change_Commit(Memory, &CurrentPoint->TangentLeft.x, &Empty, - &CurrentPoint->TangentLeft.x, action_change_r32); - Action_Change_Commit(Memory, &CurrentPoint->TangentLeft.y, &Empty, - &CurrentPoint->TangentLeft.y, action_change_r32); - Action_Change_Commit(Memory, &CurrentPoint->TangentRight.x, &Empty, - &CurrentPoint->TangentRight.x, action_change_r32); - Action_Change_Commit(Memory, &CurrentPoint->TangentRight.y, &Empty, - &CurrentPoint->TangentRight.y, action_change_r32); - Action_Entry_End(Memory); + History_Entry_Commit(Memory, action_entry_default, "Add point"); + History_Action_Change(Memory, &Mask->NumberOfPoints, &PreviousNumberOfPoints, + &Mask->NumberOfPoints, action_type_change_u16); + History_Action_Change(Memory, &CurrentPoint->Pos.x, &Empty, + &CurrentPoint->Pos.x, action_type_change_r32); + History_Action_Change(Memory, &CurrentPoint->Pos.y, &Empty, + &CurrentPoint->Pos.y, action_type_change_r32); + History_Action_Change(Memory, &CurrentPoint->TangentLeft.x, &Empty, + &CurrentPoint->TangentLeft.x, action_type_change_r32); + History_Action_Change(Memory, &CurrentPoint->TangentLeft.y, &Empty, + &CurrentPoint->TangentLeft.y, action_type_change_r32); + History_Action_Change(Memory, &CurrentPoint->TangentRight.x, &Empty, + &CurrentPoint->TangentRight.x, action_type_change_r32); + History_Action_Change(Memory, &CurrentPoint->TangentRight.y, &Empty, + &CurrentPoint->TangentRight.y, action_type_change_r32); + History_Entry_End(Memory); } } if (State->Tool != tool_pen) { @@ -1107,21 +1109,13 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, real32 YInit = ImGui::GetCursorScreenPos().y; ImGui::SameLine(); if (ImGui::Button("K")) - ManualKeyframeInsertF(Property, Memory, File->CurrentFrame, Property->CurrentValue.f); + Keyframe_Insert(Property, Memory, File->CurrentFrame, Property->CurrentValue.f); ImGui::SameLine(); if (ImGui::Button("G")) { - Property->IsGraphToggled ^= 1; - // TODO(fox): Make system to init things like these automatically? - if (!Property->GraphLength) { - Property->GraphLength = 150; - Property->GraphYOffset = (Property->GraphWindowHeight - Property->GraphLength)/2; - } + UI->Graph[UI->NumberOfGraphsEnabled].ChannelViewed = Property; + UI->NumberOfGraphsEnabled++; } ImGui::SetCursorScreenPos(ImVec2(ImGui::GetCursorScreenPos().x, YInit)); - if (Property->IsGraphToggled) - { - ImGui::Dummy(ImVec2(5, Property->GraphWindowHeight)); - } ImGui::PopID(); } } @@ -1158,8 +1152,15 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImGui::SetCursorScreenPos(TimelineStartingPos); - ImGui::PushClipRect(TimelineAbsolutePos, TimelineAbsolutePos + TimelineSizeWithBorder, true); - draw_list->PushClipRect(TimelineAbsolutePos, TimelineAbsolutePos + TimelineSizeWithBorder, true); + if (UI->NumberOfGraphsEnabled) + { + ImVec2 Dim = ImVec2(TimelineAbsolutePos.x + TimelineSizeWithBorder.x, TimelineAbsolutePos.y + TimelineSizeWithBorder.y - UI->Graph[0].WindowYOffset); + ImGui::PushClipRect(TimelineAbsolutePos, Dim, true); + draw_list->PushClipRect(TimelineAbsolutePos, Dim, true); + } else { + ImGui::PushClipRect(TimelineAbsolutePos, TimelineAbsolutePos + TimelineSizeWithBorder, true); + draw_list->PushClipRect(TimelineAbsolutePos, TimelineAbsolutePos + TimelineSizeWithBorder, true); + } for (int i = File->NumberOfLayers - 1; i >= 0; i--) { @@ -1263,226 +1264,237 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImGui::SetCursorScreenPos(ImVec2(ImGui::GetCursorScreenPos().x, NextY)); - if (Property->IsGraphToggled) - { - uint16 GraphWindowHeight = File->Layer[i]->Property[a].GraphWindowHeight; - real32 GraphWindowLocalYMin = ImGui::GetCursorPosY(); - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - real32 ScreenY = NextY; - ImVec2 MinPos = ImVec2(TimelineAbsolutePos.x, ScreenY); - ImVec2 MaxPos = ImVec2(TimelineAbsolutePos.x + TimelineSizeWithBorder.x, ScreenY + GraphWindowHeight); - draw_list->AddRectFilled(MinPos, MaxPos, - IM_COL32(00, 00, 30, 65)); - - draw_list->PushClipRect(MinPos, MaxPos, true); - - ImVec2 LeftPos[2]; - ImVec2 MidPos[2]; - ImVec2 RightPos[2]; - ImU32 col = ImGui::GetColorU32(ImGuiCol_ScrollbarGrab); + ImGui::PopID(); + } + } - for (int b = 0; b < Property->NumberOfTotalKeyframes; b++) { - keyframe *Keyframe = KeyframeLookup(Property, b); - // int32 Index = KeyframeMemoryToIndex(Property, b); + ImGui::SetCursorPosY(ImGui::GetCursorPos().y - (ItemSpacing.y * UI->KeyframeSpacing / 2)); + ImGui::PopStyleVar(); - ImGui::PushID(Keyframe); + ImGui::PopID(); + } - real32 MinVal = Property->LocalMinVal.f; - real32 MaxVal = Property->LocalMaxVal.f; - // Normalized ratio between the smallest and largest value - real32 HandleYRatio = (Keyframe->Value.f - MaxVal) / (MaxVal - MinVal); - real32 HandleYRatio_L = (Keyframe->Value.f + Keyframe->TangentLeft.y - MaxVal) / (MaxVal - MinVal); - real32 HandleYRatio_R = (Keyframe->Value.f + Keyframe->TangentRight.y - MaxVal) / (MaxVal - MinVal); + // Timeline frame ticks - real32 LocalHandlePosX = UI->TimelineZoom*Keyframe->FrameNumber; - real32 LocalHandlePosX_L = LocalHandlePosX + UI->TimelineZoom*Keyframe->TangentLeft.x; - real32 LocalHandlePosX_R = LocalHandlePosX + UI->TimelineZoom*Keyframe->TangentRight.x; + ImGui::SetCursorScreenPos(TimelineStartingPos); + if (UI->TimelineZoom > 10) { + for (float x = 0; x < File->NumberOfFrames + 2; x += 1) { + uint32 LineColor = IM_COL32(200, 200, 200, 40); + ImVec2 Min = ImVec2(TimelineStartingPos.x + UI->TimelineZoom * x, TimelineStartingPos.y); + ImVec2 Max = ImVec2(Min.x + 2, WindowMaxAbs.y); + if (x == File->CurrentFrame) continue; + draw_list->AddLine(Min, Max, LineColor); + } + } - real32 HandlePosX = TimelineStartingPos.x + LocalHandlePosX - FontHeight*0.5; - real32 HandlePosX_L = TimelineStartingPos.x + LocalHandlePosX_L - FontHeight*0.5; - real32 HandlePosX_R = TimelineStartingPos.x + LocalHandlePosX_R - FontHeight*0.5; - real32 LocalHandlePosY = HandleYRatio * Property->GraphLength; - real32 LocalHandlePosY_L = HandleYRatio_L * Property->GraphLength; - real32 LocalHandlePosY_R = HandleYRatio_R * Property->GraphLength; + draw_list->PopClipRect(); + ImGui::PopClipRect(); - real32 HandlePosY = MinPos.y - LocalHandlePosY + Property->GraphYOffset; - real32 HandlePosY_L = MinPos.y - LocalHandlePosY_L + Property->GraphYOffset; - real32 HandlePosY_R = MinPos.y - LocalHandlePosY_R + Property->GraphYOffset; + // Graph window - ImVec2 HandlePos = ImVec2(HandlePosX, HandlePosY); - ImVec2 HandlePos_L = ImVec2(HandlePosX_L, HandlePosY_L); - ImVec2 HandlePos_R = ImVec2(HandlePosX_R, HandlePosY_R); + if (UI->NumberOfGraphsEnabled) + { + ui_graph Graph = UI->Graph[0]; - if (UI->BoxSelectActive && UI->BoxStart.y >= NextY) { - if (IsRectTouching(UI->BoxStart, UI->BoxEnd, HandlePos, HandlePos + KeyframeSize)) { - Keyframe->IsSelected = true; - State->RecentSelectionType = selection_keyframe; - } else if (!io.KeyShift) { - Keyframe->IsSelected = false; - } - } + ImGui::SetCursorScreenPos(ImVec2(ImGui::GetCursorScreenPos().x, + TimelineAbsolutePos.y + TimelineSizeWithBorder.y - Graph.WindowYOffset)); - ImGui::PushStyleColor(ImGuiCol_Button, col); + ImVec2 GraphMin = ImVec2(TimelineAbsolutePos.x, ImGui::GetCursorScreenPos().y); + ImVec2 GraphSize = ImVec2(TimelineSizeWithBorder.x, Graph.WindowYOffset); - ImGui::SetCursorScreenPos(ImVec2(HandlePosX - FontHeight*1.5, HandlePosY - FontHeight*1.5)); - ImGui::Text("%.02f", Keyframe->Value.f); + ImDrawList* draw_list = ImGui::GetWindowDrawList(); + draw_list->AddRectFilled(GraphMin, GraphMin + GraphSize, + IM_COL32(0, 0, 30, 50)); - ImGui::SetCursorScreenPos(ImVec2(HandlePosX - FontHeight*1.0, HandlePosY - FontHeight*1.0)); - ImGui::InvisibleButton("##keyframepoint", ImVec2(FontHeight*2, FontHeight*2), ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight); + // draw_list->PushClipRect(GraphMin, GraphMin + GraphSize, true); + // draw_list->PopClipRect(); - draw_list->AddRect(ImVec2(HandlePosX - FontHeight*0.5, HandlePosY - FontHeight*0.5), - ImVec2(HandlePosX + FontHeight*0.5, HandlePosY + FontHeight*0.5), - ImGui::GetColorU32(ImGuiCol_ButtonHovered)); + /* + ImVec2 LeftPos[2]; + ImVec2 MidPos[2]; + ImVec2 RightPos[2]; + ImU32 col = ImGui::GetColorU32(ImGuiCol_ScrollbarGrab); - ImGui_KeyframeDragging(File, State, UI, Property, b, io, 1); + for (int b = 0; b < Property->NumberOfTotalKeyframes; b++) { + keyframe *Keyframe = KeyframeLookup(Property, b); + // int32 Index = KeyframeMemoryToIndex(Property, b); - if (Keyframe->IsSelected && Keyframe->Type == bezier) { + ImGui::PushID(Keyframe); - ImGui::SetCursorScreenPos(ImVec2(HandlePosX_L, HandlePosY_L)); - draw_list->AddCircle(ImVec2(HandlePosX_L, HandlePosY_L), 2, col, 16, 1); - ImGui::Button("##keyframehandleleft", ImVec2(FontHeight, FontHeight)); + real32 MinVal = Property->LocalMinVal.f; + real32 MaxVal = Property->LocalMaxVal.f; - ImGui_KeyframeDragging(File, State, UI, Property, b, io, 2); + // Normalized ratio between the smallest and largest value + real32 HandleYRatio = (Keyframe->Value.f - MaxVal) / (MaxVal - MinVal); + real32 HandleYRatio_L = (Keyframe->Value.f + Keyframe->TangentLeft.y - MaxVal) / (MaxVal - MinVal); + real32 HandleYRatio_R = (Keyframe->Value.f + Keyframe->TangentRight.y - MaxVal) / (MaxVal - MinVal); - ImGui::SetCursorScreenPos(ImVec2(HandlePosX_R, HandlePosY_R)); - ImGui::Button("##keyframehandleright", ImVec2(FontHeight, FontHeight)); + real32 LocalHandlePosX = UI->TimelineZoom*Keyframe->FrameNumber; + real32 LocalHandlePosX_L = LocalHandlePosX + UI->TimelineZoom*Keyframe->TangentLeft.x; + real32 LocalHandlePosX_R = LocalHandlePosX + UI->TimelineZoom*Keyframe->TangentRight.x; - ImGui_KeyframeDragging(File, State, UI, Property, b, io, 3); + real32 HandlePosX = TimelineStartingPos.x + LocalHandlePosX - FontHeight*0.5; + real32 HandlePosX_L = TimelineStartingPos.x + LocalHandlePosX_L - FontHeight*0.5; + real32 HandlePosX_R = TimelineStartingPos.x + LocalHandlePosX_R - FontHeight*0.5; - draw_list->AddLine(MidPos[b & 1], RightPos[b & 1], col, 1.0f); - draw_list->AddLine(MidPos[b & 1], LeftPos[b & 1], col, 1.0f); - } + real32 LocalHandlePosY = HandleYRatio * Property->GraphLength; + real32 LocalHandlePosY_L = HandleYRatio_L * Property->GraphLength; + real32 LocalHandlePosY_R = HandleYRatio_R * Property->GraphLength; - ImGui::PopStyleColor(); + real32 HandlePosY = MinPos.y - LocalHandlePosY + Property->GraphYOffset; + real32 HandlePosY_L = MinPos.y - LocalHandlePosY_L + Property->GraphYOffset; + real32 HandlePosY_R = MinPos.y - LocalHandlePosY_R + Property->GraphYOffset; - ImGui::PopID(); - } + ImVec2 HandlePos = ImVec2(HandlePosX, HandlePosY); + ImVec2 HandlePos_L = ImVec2(HandlePosX_L, HandlePosY_L); + ImVec2 HandlePos_R = ImVec2(HandlePosX_R, HandlePosY_R); - // TODO(fox): Reformat this so it's all done in one loop. + if (UI->BoxSelectActive && UI->BoxStart.y >= NextY) { + if (IsRectTouching(UI->BoxStart, UI->BoxEnd, HandlePos, HandlePos + KeyframeSize)) { + Keyframe->IsSelected = true; + State->RecentSelectionType = selection_keyframe; + } else if (!io.KeyShift) { + Keyframe->IsSelected = false; + } + } - for (int b = 0; b < Property->NumberOfTotalKeyframes; b++) { - keyframe *Keyframe = KeyframeLookup(Property, b); + ImGui::PushStyleColor(ImGuiCol_Button, col); - real32 MinVal = Property->LocalMinVal.f; - real32 MaxVal = Property->LocalMaxVal.f; + ImGui::SetCursorScreenPos(ImVec2(HandlePosX - FontHeight*1.5, HandlePosY - FontHeight*1.5)); + ImGui::Text("%.02f", Keyframe->Value.f); - real32 HandleYRatio = (Keyframe->Value.f - MaxVal) / (MaxVal - MinVal); - real32 HandleYRatio_L = (Keyframe->Value.f + Keyframe->TangentLeft.y - MaxVal) / (MaxVal - MinVal); - real32 HandleYRatio_R = (Keyframe->Value.f + Keyframe->TangentRight.y - MaxVal) / (MaxVal - MinVal); + ImGui::SetCursorScreenPos(ImVec2(HandlePosX - FontHeight*1.0, HandlePosY - FontHeight*1.0)); + ImGui::InvisibleButton("##keyframepoint", ImVec2(FontHeight*2, FontHeight*2), ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight); - real32 LocalHandlePosX = UI->TimelineZoom*Keyframe->FrameNumber; - real32 LocalHandlePosX_L = LocalHandlePosX + UI->TimelineZoom*Keyframe->TangentLeft.x; - real32 LocalHandlePosX_R = LocalHandlePosX + UI->TimelineZoom*Keyframe->TangentRight.x; + draw_list->AddRect(ImVec2(HandlePosX - FontHeight*0.5, HandlePosY - FontHeight*0.5), + ImVec2(HandlePosX + FontHeight*0.5, HandlePosY + FontHeight*0.5), + ImGui::GetColorU32(ImGuiCol_ButtonHovered)); - real32 HandlePosX = TimelineStartingPos.x + LocalHandlePosX - FontHeight*0.5; - real32 HandlePosX_L = TimelineStartingPos.x + LocalHandlePosX_L - FontHeight*0.5; - real32 HandlePosX_R = TimelineStartingPos.x + LocalHandlePosX_R - FontHeight*0.5; + ImGui_KeyframeDragging(File, State, UI, Property, b, io, 1); - real32 LocalHandlePosY = HandleYRatio * Property->GraphLength; - real32 LocalHandlePosY_L = HandleYRatio_L * Property->GraphLength; - real32 LocalHandlePosY_R = HandleYRatio_R * Property->GraphLength; + if (Keyframe->IsSelected && Keyframe->Type == bezier) { - real32 HandlePosY = MinPos.y - LocalHandlePosY + Property->GraphYOffset; - real32 HandlePosY_L = MinPos.y - LocalHandlePosY_L + Property->GraphYOffset; - real32 HandlePosY_R = MinPos.y - LocalHandlePosY_R + Property->GraphYOffset; + ImGui::SetCursorScreenPos(ImVec2(HandlePosX_L, HandlePosY_L)); + draw_list->AddCircle(ImVec2(HandlePosX_L, HandlePosY_L), 2, col, 16, 1); + ImGui::Button("##keyframehandleleft", ImVec2(FontHeight, FontHeight)); - ImVec2 HandlePos = ImVec2(HandlePosX, HandlePosY); - ImVec2 HandlePos_L = ImVec2(HandlePosX_L, HandlePosY_L); - ImVec2 HandlePos_R = ImVec2(HandlePosX_R, HandlePosY_R); + ImGui_KeyframeDragging(File, State, UI, Property, b, io, 2); - MidPos[b & 1] = HandlePos; - LeftPos[b & 1] = HandlePos_L; - RightPos[b & 1] = HandlePos_R; + ImGui::SetCursorScreenPos(ImVec2(HandlePosX_R, HandlePosY_R)); + ImGui::Button("##keyframehandleright", ImVec2(FontHeight, FontHeight)); - if (b != 0) - { - if (b & 1) { - if (Keyframe->Type == linear) - draw_list->AddLine(MidPos[0], MidPos[1], col, 1.0f); - else if (Keyframe->Type == bezier) - draw_list->AddBezierCubic(MidPos[0], RightPos[0], LeftPos[1], MidPos[1], col, 1.0f, 8); - } else { - if (Keyframe->Type == linear) - draw_list->AddLine(MidPos[1], MidPos[0], col, 1.0f); - else if (Keyframe->Type == bezier) - draw_list->AddBezierCubic(MidPos[1], RightPos[1], LeftPos[0], MidPos[0], col, 1.0f, 8); - } - } - } - // Horiziontal value lines - - // uint32 LineColor = IM_COL32(200, 200, 200, 40); - // for (int i = 0; i < 10; i++) { - // real32 YPos = MinPos.y + (UI->TimelineZoom/2 * i) + 5; - // ImVec2 Min = ImVec2(TimelineStartingPos.x, YPos); - // ImVec2 Max = ImVec2(TimelineStartingPos.x + TimelineSize.x, YPos); - // draw_list->AddLine(Min, Max, LineColor); - // } + ImGui_KeyframeDragging(File, State, UI, Property, b, io, 3); - draw_list->PopClipRect(); + draw_list->AddLine(MidPos[b & 1], RightPos[b & 1], col, 1.0f); + draw_list->AddLine(MidPos[b & 1], LeftPos[b & 1], col, 1.0f); + } - // ImGui::SetCursorScreenPos(ImVec2(MinPos.x, MinPos.y)); - // ImGui::Button("##SplitMove", ImVec2(TimelineBorderPadding.x, SidebarSizeWithBorder.y)); - // if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1)) - // { - // UI->TimelineSplit += io.MouseDelta.x; - // } + ImGui::PopStyleColor(); - ImGui::SetCursorScreenPos(ImVec2(MinPos.x, MinPos.y)); - ImGui::InvisibleButton("AnimationCurves", ImVec2(TimelineSize.x - 20, GraphWindowHeight), ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight); - // NOTE(fox): I'm reusing this struct for the other - // channels, so I'm OR'ing it. Also persists across layers. - AnimationCurves.IsItemHovered |= ImGui::IsItemHovered(); - AnimationCurves.IsItemActive |= ImGui::IsItemActive(); - AnimationCurves.IsItemActivated |= ImGui::IsItemActivated(); - AnimationCurves.IsItemDeactivated |= ImGui::IsItemDeactivated(); - AnimationCurves.LeftClick |= ImGui::IsMouseDown(ImGuiMouseButton_Left); - AnimationCurves.RightClick |= ImGui::IsMouseDown(ImGuiMouseButton_Right); - - if (AnimationCurves.IsItemHovered && AnimationCurves.IsItemActivated && - ImGui::IsMouseDown(ImGuiMouseButton_Right)) { - real32 LocalMousePos = io.MousePos.y - MinPos.y - Property->GraphYOffset; - UI->TempZoomRatioGraph = LocalMousePos / Property->GraphLength; - } - // DebugWatchVar("LocalMousePos", &LocalMousePos, d_float); + ImGui::PopID(); + } - if (AnimationCurves.IsItemActive && ImGui::IsMouseDragging(ImGuiMouseButton_Right, -1)) - { - Property->GraphLength += io.MouseDelta.x; - Property->GraphYOffset -= io.MouseDelta.x*UI->TempZoomRatioGraph; - Property->GraphYOffset += io.MouseDelta.y; - } + // TODO(fox): Reformat this so it's all done in one loop. + + for (int b = 0; b < Property->NumberOfTotalKeyframes; b++) { + keyframe *Keyframe = KeyframeLookup(Property, b); + + real32 MinVal = Property->LocalMinVal.f; + real32 MaxVal = Property->LocalMaxVal.f; + + real32 HandleYRatio = (Keyframe->Value.f - MaxVal) / (MaxVal - MinVal); + real32 HandleYRatio_L = (Keyframe->Value.f + Keyframe->TangentLeft.y - MaxVal) / (MaxVal - MinVal); + real32 HandleYRatio_R = (Keyframe->Value.f + Keyframe->TangentRight.y - MaxVal) / (MaxVal - MinVal); + + real32 LocalHandlePosX = UI->TimelineZoom*Keyframe->FrameNumber; + real32 LocalHandlePosX_L = LocalHandlePosX + UI->TimelineZoom*Keyframe->TangentLeft.x; + real32 LocalHandlePosX_R = LocalHandlePosX + UI->TimelineZoom*Keyframe->TangentRight.x; + + real32 HandlePosX = TimelineStartingPos.x + LocalHandlePosX - FontHeight*0.5; + real32 HandlePosX_L = TimelineStartingPos.x + LocalHandlePosX_L - FontHeight*0.5; + real32 HandlePosX_R = TimelineStartingPos.x + LocalHandlePosX_R - FontHeight*0.5; + + real32 LocalHandlePosY = HandleYRatio * Property->GraphLength; + real32 LocalHandlePosY_L = HandleYRatio_L * Property->GraphLength; + real32 LocalHandlePosY_R = HandleYRatio_R * Property->GraphLength; + + real32 HandlePosY = MinPos.y - LocalHandlePosY + Property->GraphYOffset; + real32 HandlePosY_L = MinPos.y - LocalHandlePosY_L + Property->GraphYOffset; + real32 HandlePosY_R = MinPos.y - LocalHandlePosY_R + Property->GraphYOffset; + + ImVec2 HandlePos = ImVec2(HandlePosX, HandlePosY); + ImVec2 HandlePos_L = ImVec2(HandlePosX_L, HandlePosY_L); + ImVec2 HandlePos_R = ImVec2(HandlePosX_R, HandlePosY_R); + + MidPos[b & 1] = HandlePos; + LeftPos[b & 1] = HandlePos_L; + RightPos[b & 1] = HandlePos_R; + + if (b != 0) + { + if (b & 1) { + if (Keyframe->Type == linear) + draw_list->AddLine(MidPos[0], MidPos[1], col, 1.0f); + else if (Keyframe->Type == bezier) + draw_list->AddBezierCubic(MidPos[0], RightPos[0], LeftPos[1], MidPos[1], col, 1.0f, 8); + } else { + if (Keyframe->Type == linear) + draw_list->AddLine(MidPos[1], MidPos[0], col, 1.0f); + else if (Keyframe->Type == bezier) + draw_list->AddBezierCubic(MidPos[1], RightPos[1], LeftPos[0], MidPos[0], col, 1.0f, 8); } - ImGui::PopID(); } } + // Horiziontal value lines + + // uint32 LineColor = IM_COL32(200, 200, 200, 40); + // for (int i = 0; i < 10; i++) { + // real32 YPos = MinPos.y + (UI->TimelineZoom/2 * i) + 5; + // ImVec2 Min = ImVec2(TimelineStartingPos.x, YPos); + // ImVec2 Max = ImVec2(TimelineStartingPos.x + TimelineSize.x, YPos); + // draw_list->AddLine(Min, Max, LineColor); + // } - ImGui::SetCursorPosY(ImGui::GetCursorPos().y - (ItemSpacing.y * UI->KeyframeSpacing / 2)); - ImGui::PopStyleVar(); + draw_list->PopClipRect(); - ImGui::PopID(); - } + // ImGui::SetCursorScreenPos(ImVec2(MinPos.x, MinPos.y)); + // ImGui::Button("##SplitMove", ImVec2(TimelineBorderPadding.x, SidebarSizeWithBorder.y)); + // if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1)) + // { + // UI->TimelineSplit += io.MouseDelta.x; + // } - // Timeline frame ticks + ImGui::SetCursorScreenPos(ImVec2(MinPos.x, MinPos.y)); + ImGui::InvisibleButton("AnimationCurves", ImVec2(TimelineSize.x - 20, GraphWindowHeight), ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight); + // NOTE(fox): I'm reusing this struct for the other + // channels, so I'm OR'ing it. Also persists across layers. + AnimationCurves.IsItemHovered |= ImGui::IsItemHovered(); + AnimationCurves.IsItemActive |= ImGui::IsItemActive(); + AnimationCurves.IsItemActivated |= ImGui::IsItemActivated(); + AnimationCurves.IsItemDeactivated |= ImGui::IsItemDeactivated(); + AnimationCurves.LeftClick |= ImGui::IsMouseDown(ImGuiMouseButton_Left); + AnimationCurves.RightClick |= ImGui::IsMouseDown(ImGuiMouseButton_Right); + + if (AnimationCurves.IsItemHovered && AnimationCurves.IsItemActivated && + ImGui::IsMouseDown(ImGuiMouseButton_Right)) { + real32 LocalMousePos = io.MousePos.y - MinPos.y - Property->GraphYOffset; + UI->TempZoomRatioGraph = LocalMousePos / Property->GraphLength; + } + // DebugWatchVar("LocalMousePos", &LocalMousePos, d_float); - ImGui::SetCursorScreenPos(TimelineStartingPos); - if (UI->TimelineZoom > 10) { - for (float x = 0; x < File->NumberOfFrames + 2; x += 1) { - uint32 LineColor = IM_COL32(200, 200, 200, 40); - ImVec2 Min = ImVec2(TimelineStartingPos.x + UI->TimelineZoom * x, TimelineStartingPos.y); - ImVec2 Max = ImVec2(Min.x + 2, WindowMaxAbs.y); - if (x == File->CurrentFrame) continue; - draw_list->AddLine(Min, Max, LineColor); + if (AnimationCurves.IsItemActive && ImGui::IsMouseDragging(ImGuiMouseButton_Right, -1)) + { + Property->GraphLength += io.MouseDelta.x; + Property->GraphYOffset -= io.MouseDelta.x*UI->TempZoomRatioGraph; + Property->GraphYOffset += io.MouseDelta.y; } + */ } - draw_list->PopClipRect(); - ImGui::PopClipRect(); - // Playhead line uint32 LineColor = IM_COL32(200, 200, 200, 200); @@ -1596,9 +1608,9 @@ ImGui_ProcessInputs(project_data *File, project_state *State, comp_buffer *CompB if (ImGui::IsKeyPressed(ImGuiKey_Z)) { if (io.KeyCtrl && io.KeyShift) { - Action_Redo(Memory); + History_Redo(Memory); } else if (io.KeyCtrl) { - Action_Undo(Memory); + History_Undo(Memory); } State->UpdateFrame = true; State->UpdateKeyframes = true; @@ -1734,39 +1746,39 @@ ImGui_ProcessInputs(project_data *File, project_state *State, comp_buffer *CompB State->UpdateFrame = true; } if (ImGui::IsMouseDown(ImGuiMouseButton_Left)) { - Action_Entry_Commit(Memory, action_entry_default, "Tranforms interact"); + History_Entry_Commit(Memory, action_entry_default, "Tranforms interact"); switch (State->TransformsHotkeyInteract) { case sliding_position: { - Action_Change_Commit(Memory, &Layer->x.CurrentValue.f, &State->InteractCache[0], - &Layer->x.CurrentValue.f, action_change_r32); - Action_Change_Commit(Memory, &Layer->y.CurrentValue.f, &State->InteractCache[1], - &Layer->y.CurrentValue.f, action_change_r32); + History_Action_Change(Memory, &Layer->x.CurrentValue.f, &State->InteractCache[0], + &Layer->x.CurrentValue.f, action_type_change_r32); + History_Action_Change(Memory, &Layer->y.CurrentValue.f, &State->InteractCache[1], + &Layer->y.CurrentValue.f, action_type_change_r32); } break; case sliding_anchorpoint: { - Action_Change_Commit(Memory, &Layer->x.CurrentValue.f, &State->InteractCache[0], - &Layer->x.CurrentValue.f, action_change_r32); - Action_Change_Commit(Memory, &Layer->y.CurrentValue.f, &State->InteractCache[1], - &Layer->y.CurrentValue.f, action_change_r32); - Action_Change_Commit(Memory, &Layer->ax.CurrentValue.f, &State->InteractCache[2], - &Layer->ax.CurrentValue.f, action_change_r32); - Action_Change_Commit(Memory, &Layer->ay.CurrentValue.f, &State->InteractCache[3], - &Layer->ay.CurrentValue.f, action_change_r32); + History_Action_Change(Memory, &Layer->x.CurrentValue.f, &State->InteractCache[0], + &Layer->x.CurrentValue.f, action_type_change_r32); + History_Action_Change(Memory, &Layer->y.CurrentValue.f, &State->InteractCache[1], + &Layer->y.CurrentValue.f, action_type_change_r32); + History_Action_Change(Memory, &Layer->ax.CurrentValue.f, &State->InteractCache[2], + &Layer->ax.CurrentValue.f, action_type_change_r32); + History_Action_Change(Memory, &Layer->ay.CurrentValue.f, &State->InteractCache[3], + &Layer->ay.CurrentValue.f, action_type_change_r32); } break; case sliding_rotation: { - Action_Change_Commit(Memory, &Layer->rotation.CurrentValue.f, &State->InteractCache[0], - &Layer->rotation.CurrentValue.f, action_change_r32); + History_Action_Change(Memory, &Layer->rotation.CurrentValue.f, &State->InteractCache[0], + &Layer->rotation.CurrentValue.f, action_type_change_r32); } break; case sliding_scale: { - Action_Change_Commit(Memory, &Layer->scale.CurrentValue.f, &State->InteractCache[0], - &Layer->scale.CurrentValue.f, action_change_r32); + History_Action_Change(Memory, &Layer->scale.CurrentValue.f, &State->InteractCache[0], + &Layer->scale.CurrentValue.f, action_type_change_r32); } break; } - Action_Entry_End(Memory); + History_Entry_End(Memory); State->IsInteracting = false; } State->UpdateFrame = true; diff --git a/prenderer.cpp b/prenderer.cpp index 909fc4c..ccacbe8 100644 --- a/prenderer.cpp +++ b/prenderer.cpp @@ -355,6 +355,7 @@ AVX2_RenderLayer(transform_info T, comp_buffer *Buffer, rectangle RenderRegion) __m256 YAxisPY = _mm256_set1_ps(T.YAxisPY); __m256 LayerWidth = _mm256_set1_ps(T.LayerWidth); + __m256 LayerBoundsMaxX = _mm256_set1_ps(LayerBounds.Max.x); __m256i FullLayerWidth4i = _mm256_set1_epi32(T.FullLayerWidth*4); __m256i LayerWidthMinusOne = _mm256_set1_epi32(T.LayerWidth - 1); __m256i LayerHeightMinusOne = _mm256_set1_epi32(T.LayerHeight - 1); @@ -489,17 +490,23 @@ AVX2_RenderLayer(transform_info T, comp_buffer *Buffer, rectangle RenderRegion) __m256 Avg = _mm256_add_ps(_mm256_add_ps(_mm256_and_ps(LayerMask0, ZeroPoint25), _mm256_and_ps(LayerMask1, ZeroPoint25)), _mm256_add_ps(_mm256_and_ps(LayerMask2, ZeroPoint25), _mm256_and_ps(LayerMask3, ZeroPoint25))); + // Preventing overlap between threads for non-packed. One nice thing + // about packed is that the 4-padded bitmap means we can set up the + // boundaries so we don't have to check this ever. + __m256i TileBarrier = _mm256_cmp_ps(PixelX, LayerBoundsMaxX, 13); + // Zero - no points pass // One - all points pass; not an edge __m256i Mask = _mm256_cmp_ps(Avg, Zero, 14); __m256i NonEdge = _mm256_cmp_ps(Avg, One, 13); + __m256i TotalMask = _mm256_andnot_si256(TileBarrier, _mm256_and_si256(Mask, NonEdge)); - __m256 LayerMask = _mm256_and_ps(_mm256_and_ps(_mm256_cmp_ps(U, Zero, 13), _mm256_cmp_ps(U, One, 1)), - _mm256_and_ps(_mm256_cmp_ps(V, Zero, 13), _mm256_cmp_ps(V, One, 1))); + // __m256 LayerMask = _mm256_and_ps(_mm256_and_ps(_mm256_cmp_ps(U, Zero, 13), _mm256_cmp_ps(U, One, 1)), + // _mm256_and_ps(_mm256_cmp_ps(V, Zero, 13), _mm256_cmp_ps(V, One, 1))); // If all of the pixels are zeroed in the mask (aka fall outside // the UV lookup), we can skip the iteration. - if (_mm256_movemask_epi8(LayerMask)) + if (_mm256_movemask_epi8(TotalMask)) { __m256i EdgeMask = _mm256_andnot_si256(NonEdge, Mask); @@ -745,7 +752,7 @@ AVX2_RenderLayer(transform_info T, comp_buffer *Buffer, rectangle RenderRegion) _mm256_or_si256(R_Out, _mm256_slli_epi32(G_Out, 8)), _mm256_or_si256(_mm256_slli_epi32(B_Out, 16), _mm256_slli_epi32(A_Out, 24))); - _mm256_maskstore_epi32((int *)Pixel, LayerMask, OutputPixel); + _mm256_maskstore_epi32((int *)Pixel, TotalMask, OutputPixel); } #if PACKEDRGB PixelX = _mm256_add_ps(PixelX, Four); @@ -11,107 +11,177 @@ // when a layer's creation is undone), though they should be used only // when necessary. -// These get four things pushed together: the address of what's being -// changed, what type the data is, the original data, and the type again. -// The type is encoded twice so we always know how big the data is whether -// we're undoing or redoing. +// These get four things pushed together: what type the data is, address, the +// original data, and the type again. The type is encoded twice so we always +// know how big the data is whether we're undoing or redoing. // We need to encode data that's able to go from A -> B as well as B -> A. Thus // for the ints I encode the difference instead of just whatever the last value // was. Strings currently just stores both. -void Action_Change_Commit(memory *Memory, void *DataAddress, void *OriginalData, void *NewData, action_change_type ActionChange) +void History_Action_Change(memory *Memory, void *DataAddress, void *OriginalData, void *NewData, action_type ActionChange) { Memory->Action.Entry[Memory->Action.Index].NumberOfActions++; - void *UndoEntry = AllocateMemory(Memory, sizeof(void *), P_UndoBuffer); + void *Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer); + *(action_type *)Data = ActionChange; + void *UndoEntry = Memory_Advance(Memory, sizeof(void *), P_UndoBuffer); *(ptrsize *)UndoEntry = (ptrsize)DataAddress; - void *Data = AllocateMemory(Memory, sizeof(action_change_type), P_UndoBuffer); - *(action_change_type *)Data = ActionChange; switch (ActionChange) { - case action_change_u16: + case action_type_change_u16: { uint16 OriginalValue = *(uint16 *)OriginalData; uint16 NewValue = *(uint16 *)NewData; uint16 Difference = NewValue - OriginalValue; - void *Data = AllocateMemory(Memory, sizeof(uint16), P_UndoBuffer); + void *Data = Memory_Advance(Memory, sizeof(uint16), P_UndoBuffer); *(uint16 *)Data = Difference; *(uint16 *)DataAddress = *(uint16 *)NewData; } break; - case action_change_i16: + case action_type_change_i16: { int16 OriginalValue = *(int16 *)OriginalData; int16 NewValue = *(int16 *)NewData; int16 Difference = NewValue - OriginalValue; - void *Data = AllocateMemory(Memory, sizeof(int16), P_UndoBuffer); + void *Data = Memory_Advance(Memory, sizeof(int16), P_UndoBuffer); *(int16 *)Data = Difference; *(int16 *)DataAddress = *(int16 *)NewData; } break; - case action_change_u32: + case action_type_change_u32: { uint32 OriginalValue = *(uint32 *)OriginalData; uint32 NewValue = *(uint32 *)NewData; uint32 Difference = NewValue - OriginalValue; - void *Data = AllocateMemory(Memory, sizeof(uint32), P_UndoBuffer); + void *Data = Memory_Advance(Memory, sizeof(uint32), P_UndoBuffer); *(uint32 *)Data = Difference; *(uint32 *)DataAddress = *(uint32 *)NewData; } break; - case action_change_i32: + case action_type_change_i32: { int32 OriginalValue = *(int32 *)OriginalData; int32 NewValue = *(int32 *)NewData; int32 Difference = NewValue - OriginalValue; - void *Data = AllocateMemory(Memory, sizeof(int32), P_UndoBuffer); + void *Data = Memory_Advance(Memory, sizeof(int32), P_UndoBuffer); *(int32 *)Data = Difference; *(int32 *)DataAddress = *(int32 *)NewData; } break; - case action_change_r32: + case action_type_change_r32: { real32 OriginalValue = *(real32 *)OriginalData; real32 NewValue = *(real32 *)NewData; real32 Difference = NewValue - OriginalValue; - void *Data = AllocateMemory(Memory, sizeof(real32), P_UndoBuffer); + void *Data = Memory_Advance(Memory, sizeof(real32), P_UndoBuffer); *(real32 *)Data = Difference; *(real32 *)DataAddress = *(real32 *)NewData; } break; - case action_change_u64: + case action_type_change_u64: { uint64 OriginalValue = *(uint64 *)OriginalData; uint64 NewValue = *(uint64 *)NewData; uint64 Difference = NewValue - OriginalValue; - void *Data = AllocateMemory(Memory, sizeof(uint64), P_UndoBuffer); + void *Data = Memory_Advance(Memory, sizeof(uint64), P_UndoBuffer); *(uint64 *)Data = Difference; *(uint64 *)DataAddress = *(uint64 *)NewData; } break; - case action_change_ptr: + case action_type_change_ptr: { ptrsize OriginalValue = *(ptrsize *)OriginalData; ptrsize NewValue = *(ptrsize *)NewData; ptrsize Difference = NewValue - OriginalValue; - void *Data = AllocateMemory(Memory, sizeof(ptrsize), P_UndoBuffer); + void *Data = Memory_Advance(Memory, sizeof(ptrsize), P_UndoBuffer); *(ptrsize *)Data = Difference; *(ptrsize *)DataAddress = *(ptrsize *)NewData; } break; - case action_change_string: + case action_type_change_string: { - void *Data = AllocateMemory(Memory, STRING_SIZE, P_UndoBuffer); + void *Data = Memory_Advance(Memory, STRING_SIZE, P_UndoBuffer); CopyStrings(Data, OriginalData); - Data = AllocateMemory(Memory, STRING_SIZE, P_UndoBuffer); + Data = Memory_Advance(Memory, STRING_SIZE, P_UndoBuffer); CopyStrings(Data, NewData); CopyStrings(DataAddress, NewData); } break; + default: + { + Assert(0); + } + } - Data = AllocateMemory(Memory, sizeof(action_change_type), P_UndoBuffer); - *(action_change_type *)Data = ActionChange; + Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer); + *(action_type *)Data = ActionChange; } // Helper functions for common types of data changes. -void Action_Change_Commit_SwapBool(memory *Memory, bool32 *Bool) +void History_Action_Change_SwapBool(memory *Memory, bool32 *Bool) { bool32 OppositeBool = *Bool ^ 1; - Action_Change_Commit(Memory, Bool, Bool, &OppositeBool, action_change_i32); + History_Action_Change(Memory, Bool, Bool, &OppositeBool, action_type_change_i32); +} + +void History_Action_Change_Increment(memory *Memory, void *Data, action_type ActionChange) +{ + switch (ActionChange) + { + case action_type_change_u16: + { + uint16 DataPlusOne = (*(uint16 *)Data) + 1; + History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange); + } break; + case action_type_change_i16: + { + int16 DataPlusOne = (*(int16 *)Data) + 1; + History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange); + } break; + case action_type_change_u32: + { + uint32 DataPlusOne = (*(uint32 *)Data) + 1; + History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange); + } break; + case action_type_change_i32: + { + int32 DataPlusOne = (*(int32 *)Data) + 1; + History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange); + } break; + case action_type_change_r32: + { + real32 DataPlusOne = (*(real32 *)Data) + 1; + History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange); + } break; + case action_type_change_u64: + { + uint64 DataPlusOne = (*(uint64 *)Data) + 1; + History_Action_Change(Memory, Data, Data, &DataPlusOne, ActionChange); + } break; + default: + { + Assert(0); + } + } +} + +void History_Action_Shift(memory *Memory, action_type ActionChange, void *DataAddress, int16 Direction, int16 Index) +{ + Memory->Action.Entry[Memory->Action.Index].NumberOfActions++; + void *Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer); + *(action_type *)Data = ActionChange; + switch (ActionChange) + { + case action_type_shift_keyframe: + { + void *DataPropertyAddress = Memory_Advance(Memory, sizeof(void *), P_UndoBuffer); + *(ptrsize *)DataPropertyAddress = (ptrsize)DataAddress; + void *DataDirection = Memory_Advance(Memory, sizeof(int16), P_UndoBuffer); + *(ptrsize *)DataDirection = (ptrsize)Direction; + void *DataIndex = Memory_Advance(Memory, sizeof(int16), P_UndoBuffer); + *(ptrsize *)DataIndex = (ptrsize)Index; + } break; + default: + { + Assert(0); + } break; + } + Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer); + *(action_type *)Data = ActionChange; } // This is only called when we're certain the action is going to be taken. -void Action_Entry_Commit(memory *Memory, action_entry_type Type, char *Name) +void History_Entry_Commit(memory *Memory, action_entry_type Type, char *Name) { // We need to at least clear NumberOfActions in case this index is being reused. Memory->Action.Entry[Memory->Action.Index] = {}; @@ -125,147 +195,154 @@ void Action_Entry_Commit(memory *Memory, action_entry_type Type, char *Name) } } -void Action_Entry_SetPointer(memory *Memory, void *Data) +void History_Entry_SetPointer(memory *Memory, void *Data) { Memory->Action.Entry[Memory->Action.Index].ExtraPointer = Data; } -void Action_Entry_End(memory *Memory) +void History_Entry_End(memory *Memory) { Memory->Action.Index++; Memory->Action.NumberOfEntries++; } -// TODO(fox): Maybe take the extra lines to separate the incrementing of the -// address from the variable assignment to improve legibility. - // The pointer is unwinded. -void Action_Change_Undo(memory *Memory) { - memory_table *Table = &Memory->Slot[P_UndoBuffer]; - uint8 *LastPos = (uint8 *)Table->Address + Table->CurrentPosition; - action_change_type *ActionType = (action_change_type *)LastPos - 1; - uint8 *TableAddress; +void History_Action_Undo(memory *Memory) { + void *LastPos = Memory_Rewind(Memory, sizeof(action_type), P_UndoBuffer); + action_type *ActionType = (action_type *)LastPos; + switch (*ActionType) { - case action_change_u16: + case action_type_change_u16: + { + uint16 *Difference = (uint16 *)Memory_Rewind(Memory, sizeof(uint16), P_UndoBuffer); + void **Address = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer); + *(uint16 *)*Address -= *Difference; + } break; + case action_type_change_i16: { - uint16 *Difference = (uint16 *)ActionType - 1; - TableAddress = (uint8 *)Difference - sizeof(ptrsize) - sizeof(action_change_type); - void *Address = (void *)*(ptrsize *)TableAddress; - *(uint16 *)Address -= *Difference; + int16 *Difference = (int16 *)Memory_Rewind(Memory, sizeof(int16), P_UndoBuffer); + void **Address = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer); + *(int16 *)*Address -= *Difference; } break; - case action_change_i16: + case action_type_change_u32: { - int16 *Difference = (int16 *)ActionType - 1; - TableAddress = (uint8 *)Difference - sizeof(ptrsize) - sizeof(action_change_type); - void *Address = (void *)*(ptrsize *)TableAddress; - *(int16 *)Address -= *Difference; + uint32 *Difference = (uint32 *)Memory_Rewind(Memory, sizeof(uint32), P_UndoBuffer); + void **Address = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer); + *(uint32 *)*Address -= *Difference; } break; - case action_change_u32: + case action_type_change_i32: { - uint32 *Difference = (uint32 *)ActionType - 1; - TableAddress = (uint8 *)Difference - sizeof(ptrsize) - sizeof(action_change_type); - void *Address = (void *)*(ptrsize *)TableAddress; - *(uint32 *)Address -= *Difference; + int32 *Difference = (int32 *)Memory_Rewind(Memory, sizeof(int32), P_UndoBuffer); + void **Address = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer); + *(int32 *)*Address -= *Difference; } break; - case action_change_i32: + case action_type_change_r32: { - int32 *Difference = (int32 *)ActionType - 1; - TableAddress = (uint8 *)Difference - sizeof(ptrsize) - sizeof(action_change_type); - void *Address = (void *)*(ptrsize *)TableAddress; - *(int32 *)Address -= *Difference; + real32 *Difference = (real32 *)Memory_Rewind(Memory, sizeof(real32), P_UndoBuffer); + void **Address = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer); + *(real32 *)*Address -= *Difference; } break; - case action_change_r32: + case action_type_change_u64: { - real32 *Difference = (real32 *)ActionType - 1; - TableAddress = (uint8 *)Difference - sizeof(ptrsize) - sizeof(action_change_type); - void *Address = (void *)*(ptrsize *)TableAddress; - *(real32 *)Address -= *Difference; + uint64 *Difference = (uint64 *)Memory_Rewind(Memory, sizeof(uint64), P_UndoBuffer); + void **Address = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer); + *(uint64 *)*Address -= *Difference; } break; - case action_change_u64: + case action_type_change_ptr: { - uint64 *Difference = (uint64 *)ActionType - 1; - TableAddress = (uint8 *)Difference - sizeof(ptrsize) - sizeof(action_change_type); - void *Address = (void *)*(ptrsize *)TableAddress; - *(uint64 *)Address -= *Difference; + ptrsize *Difference = (ptrsize *)Memory_Rewind(Memory, sizeof(ptrsize), P_UndoBuffer); + void **Address = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer); + *(ptrsize *)*Address -= *Difference; + } break; + case action_type_change_string: + { + Assert(0); } break; - case action_change_ptr: + case action_type_shift_keyframe: { - ptrsize *Difference = (ptrsize *)ActionType - 1; - TableAddress = (uint8 *)Difference - sizeof(ptrsize) - sizeof(action_change_type); - void *Address = (void *)*(ptrsize *)TableAddress; - *(ptrsize *)Address -= *Difference; + void *DataIndex = Memory_Rewind(Memory, sizeof(int16), P_UndoBuffer); + void *DataDirection = Memory_Rewind(Memory, sizeof(int16), P_UndoBuffer); + void **DataPropertyAddress = (void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer); + ShiftKeyframes((property_channel *)*DataPropertyAddress, *(int16 *)DataDirection * -1, *(int16 *)DataIndex); } break; - case action_change_string: + default: { - TableAddress = 0x0; Assert(0); } break; } - Table->CurrentPosition = (TableAddress - (uint8 *)Table->Address); + void *EndPos = Memory_Rewind(Memory, sizeof(action_type), P_UndoBuffer); } // The pointer is rewinded. -void Action_Change_Redo(memory *Memory) { - memory_table *Table = &Memory->Slot[P_UndoBuffer]; - uint8 *LastPos = (uint8 *)Table->Address + Table->CurrentPosition; - void *Address = (void *)*(ptrsize *)LastPos; - action_change_type *ActionType = (action_change_type *)(LastPos + sizeof(void *)); - uint8 *TableAddress; +void History_Action_Redo(memory *Memory) { + void *LastPos = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer); + action_type *ActionType = (action_type *)LastPos; + switch (*ActionType) { - case action_change_u16: + case action_type_change_u16: + { + void **Address = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer); + uint16 *Difference = (uint16 *)Memory_Advance(Memory, sizeof(uint16), P_UndoBuffer); + *(uint16 *)*Address += *Difference; + } break; + case action_type_change_i16: { - uint16 *Difference = (uint16 *)(ActionType + 1); - TableAddress = (uint8 *)Difference + sizeof(uint16) + sizeof(action_change_type); - *(uint16 *)Address += *Difference; + void **Address = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer); + int16 *Difference = (int16 *)Memory_Advance(Memory, sizeof(int16), P_UndoBuffer); + *(int16 *)*Address += *Difference; } break; - case action_change_i16: + case action_type_change_u32: { - int16 *Difference = (int16 *)(ActionType + 1); - TableAddress = (uint8 *)Difference + sizeof(int16) + sizeof(action_change_type); - *(int16 *)Address += *Difference; + void **Address = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer); + uint32 *Difference = (uint32 *)Memory_Advance(Memory, sizeof(uint32), P_UndoBuffer); + *(uint32 *)*Address += *Difference; } break; - case action_change_u32: + case action_type_change_i32: { - uint32 *Difference = (uint32 *)(ActionType + 1); - TableAddress = (uint8 *)Difference + sizeof(uint32) + sizeof(action_change_type); - *(uint32 *)Address += *Difference; + void **Address = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer); + int32 *Difference = (int32 *)Memory_Advance(Memory, sizeof(int32), P_UndoBuffer); + *(int32 *)*Address += *Difference; } break; - case action_change_i32: + case action_type_change_r32: { - int32 *Difference = (int32 *)(ActionType + 1); - TableAddress = (uint8 *)Difference + sizeof(int32) + sizeof(action_change_type); - *(int32 *)Address += *Difference; + void **Address = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer); + real32 *Difference = (real32 *)Memory_Advance(Memory, sizeof(real32), P_UndoBuffer); + *(real32 *)*Address += *Difference; } break; - case action_change_r32: + case action_type_change_u64: { - real32 *Difference = (real32 *)(ActionType + 1); - TableAddress = (uint8 *)Difference + sizeof(real32) + sizeof(action_change_type); - *(real32 *)Address += *Difference; + void **Address = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer); + uint64 *Difference = (uint64 *)Memory_Advance(Memory, sizeof(uint64), P_UndoBuffer); + *(uint64 *)*Address += *Difference; } break; - case action_change_u64: + case action_type_change_ptr: { - uint64 *Difference = (uint64 *)(ActionType + 1); - TableAddress = (uint8 *)Difference + sizeof(uint64) + sizeof(action_change_type); - *(uint64 *)Address += *Difference; + void **Address = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer); + ptrsize *Difference = (ptrsize *)Memory_Advance(Memory, sizeof(ptrsize), P_UndoBuffer); + *(ptrsize *)*Address += *Difference; + } break; + case action_type_change_string: + { + Assert(0); } break; - case action_change_ptr: + case action_type_shift_keyframe: { - ptrsize *Difference = (ptrsize *)(ActionType + 1); - TableAddress = (uint8 *)Difference + sizeof(ptrsize) + sizeof(action_change_type); - *(ptrsize *)Address += *Difference; + void **DataPropertyAddress = (void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer); + void *DataDirection = Memory_Advance(Memory, sizeof(int16), P_UndoBuffer); + void *DataIndex = Memory_Advance(Memory, sizeof(int16), P_UndoBuffer); + ShiftKeyframes((property_channel *)*DataPropertyAddress, *(int16 *)DataDirection, *(int16 *)DataIndex); } break; - case action_change_string: + default: { - TableAddress = 0x0; Assert(0); } break; } - Table->CurrentPosition = (TableAddress - (uint8 *)Table->Address); + void *EndPos = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer); } -void Action_Undo(memory *Memory) { +void History_Undo(memory *Memory) { if (Memory->Action.Index != 0) { Memory->Action.Index--; action_entry Entry = Memory->Action.Entry[Memory->Action.Index]; @@ -281,11 +358,11 @@ void Action_Undo(memory *Memory) { } break; } for (int i = 0; i < Entry.NumberOfActions; i++) - Action_Change_Undo(Memory); + History_Action_Undo(Memory); } } -void Action_Redo(memory *Memory) { +void History_Redo(memory *Memory) { if (Memory->Action.Index != Memory->Action.NumberOfEntries) { action_entry Entry = Memory->Action.Entry[Memory->Action.Index]; switch (Entry.Type) @@ -298,7 +375,7 @@ void Action_Redo(memory *Memory) { } break; } for (int i = 0; i < Entry.NumberOfActions; i++) - Action_Change_Redo(Memory); + History_Action_Redo(Memory); Memory->Action.Index++; } } |