summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFox Caminiti <fox@foxcam.net>2022-08-21 10:20:31 -0400
committerFox Caminiti <fox@foxcam.net>2022-08-21 10:20:31 -0400
commited51dab429e467fc144f0bfbed70a5291c8a0a27 (patch)
treef79fc3bb577ca996b49b34f1bad5bff4a40ce6a9
parent8c5f06c37f3c267ecd8f867cd49765c366b5f47c (diff)
multisampled gl masks
-rw-r--r--bezier.cpp6
-rw-r--r--createcalls.cpp140
-rw-r--r--effects.cpp2
-rw-r--r--functions.h23
-rw-r--r--gl_calls.cpp111
-rw-r--r--keyframes.cpp161
-rw-r--r--main.cpp5
-rw-r--r--main.h48
-rw-r--r--memory.cpp19
-rw-r--r--my_imgui_widgets.cpp492
-rw-r--r--prenderer.cpp15
-rw-r--r--undo.cpp315
12 files changed, 738 insertions, 599 deletions
diff --git a/bezier.cpp b/bezier.cpp
index 64b0780..63cc328 100644
--- a/bezier.cpp
+++ b/bezier.cpp
@@ -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
}
}
}
- */
}
diff --git a/main.cpp b/main.cpp
index 49187e4..c6ac662 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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
diff --git a/main.h b/main.h
index 3c7455a..122c380 100644
--- a/main.h
+++ b/main.h
@@ -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;
diff --git a/memory.cpp b/memory.cpp
index 7c08f91..2a9b29b 100644
--- a/memory.cpp
+++ b/memory.cpp
@@ -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);
diff --git a/undo.cpp b/undo.cpp
index 82a37ea..6ebdfca 100644
--- a/undo.cpp
+++ b/undo.cpp
@@ -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++;
}
}