summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bezier.cpp77
-rw-r--r--createcalls.cpp28
-rw-r--r--effects.cpp1
-rw-r--r--effects.h2
-rw-r--r--functions.h4
-rw-r--r--gl_calls.cpp9
-rw-r--r--keyframes.cpp84
-rw-r--r--main.cpp9
-rw-r--r--main.h14
-rw-r--r--memory.cpp12
-rw-r--r--my_imgui_widgets.cpp61
-rw-r--r--undo.cpp177
12 files changed, 394 insertions, 84 deletions
diff --git a/bezier.cpp b/bezier.cpp
index f41bd06..e5f9bf9 100644
--- a/bezier.cpp
+++ b/bezier.cpp
@@ -177,15 +177,52 @@ Mask_PushPoint(mask *Mask, v2 Pos)
Mask->NumberOfPoints++;
}
-// Mask_DeletePoint(mask *Mask, uint32 p)
-// {
-// }
+static void
+Mask_ShiftPointers(mask *Mask, int16 Increment, int16 StopAt) {
+ if (Increment > 0) {
+ int16 i = Mask->NumberOfPoints - 1;
+ while (i >= StopAt) {
+ mask_point *CurrentPoint = &Mask->Point[i];
+ mask_point *NextPoint = &Mask->Point[i + Increment];
+ *NextPoint = *CurrentPoint;
+ i--;
+ }
+ } else {
+ int16 i = StopAt;
+ while (i <= Mask->NumberOfPoints - 1) {
+ mask_point *CurrentPoint = &Mask->Point[i];
+ mask_point *NextPoint = &Mask->Point[i - Increment];
+ *CurrentPoint = *NextPoint;
+ i++;
+ }
+ }
+}
+
+static void
+Mask_DeletePoint(memory *Memory, mask *Mask, uint16 Index)
+{
+ History_Entry_Commit(Memory, action_entry_default, "Delete keyframe");
+ mask_point *MaskPointIndex = &Mask->Point[Index];
+ History_Action_StoreData(Memory, MaskPointIndex, sizeof(mask_point));
+
+ History_Action_Change_Decrement(Memory, &Mask->NumberOfPoints, action_type_change_u16);
+ // History_Action_Shift(Memory, action_type_shift_bezier, Mask, -1, Index);
+ void *StartingAddress = &Mask->Point[0];
+ History_Action_Shift_2(Memory, StartingAddress, sizeof(mask_point), Mask->NumberOfPoints, -1, Index);
+ // Mask_ShiftPointers(Mask, -1, Index);
+ History_Entry_End(Memory);
+}
+// It's more useful to input the ratio here instead of the cursor position
+// since we have to use it to calculate the four new handle lengths (two on the
+// new point and one on each edge).
static void
-Mask_AddPointToCurve(mask *Mask, uint16 Index, real32 ratio)
+Mask_AddPointToCurve(memory *Memory, mask *Mask, uint16 Index, real32 ratio)
{
mask_point *Point0 = &Mask->Point[Index];
mask_point *Point1 = &Mask->Point[Index+1];
+ if (Index + 1 == Mask->NumberOfPoints)
+ Point1 = &Mask->Point[0];
v2 Point0_Pos_Right = Point0->Pos + Point0->TangentRight;
v2 Point1_Pos_Left = Point1->Pos + Point1->TangentLeft;
@@ -196,18 +233,32 @@ Mask_AddPointToCurve(mask *Mask, uint16 Index, real32 ratio)
v2 NewHandleRight = Line_RatioToPoint(Top_Half, Handle1_Half, ratio);
v2 NewPos = Line_RatioToPoint(NewHandleLeft, NewHandleRight, ratio);
- Point0->TangentRight = -(Point0->Pos - Handle0_Half);
- Point1->TangentLeft = -(Point1->Pos - Handle1_Half);
+ History_Entry_Commit(Memory, action_entry_default, "Add point to curve");
+
+ v2 NewPoint0Pos = -(Point0->Pos - Handle0_Half);
+ v2 NewPoint1Pos = -(Point1->Pos - Handle1_Half);
+ History_Action_Change_V2(Memory, &Point0->TangentRight, &Point0->TangentRight, &NewPoint0Pos);
+ History_Action_Change_V2(Memory, &Point1->TangentLeft, &Point1->TangentLeft, &NewPoint1Pos);
+
+ void *StartingAddress = &Mask->Point[0];
+ History_Action_Shift_2(Memory, StartingAddress, sizeof(mask_point), Mask->NumberOfPoints, 1, Index);
- for (int i = Mask->NumberOfPoints - 1; i > Index; i--) {
- Mask->Point[i+1] = Mask->Point[i];
- }
mask_point *PointToAdd = &Mask->Point[Index+1];
- PointToAdd->Pos = NewPos;
- PointToAdd->TangentLeft = -(NewPos - NewHandleLeft);
- PointToAdd->TangentRight = -(NewPos - NewHandleRight);
- Mask->NumberOfPoints++;
+ // NOTE(fox): The above shift duplicates the keyframe at Index into where
+ // we're writing, Index+1. I'm using the Change action (which is normally
+ // for changing values that already exist) on this intermediate keyframe
+ // slot to save having to write a bunch of special actions for shifting and
+ // adding new data.
+
+ History_Action_Change_V2(Memory, &PointToAdd->Pos, &PointToAdd->Pos, &NewPos);
+ v2 NewLeftPos = -(NewPos - NewHandleLeft);
+ v2 NewRightPos = -(NewPos - NewHandleRight);
+ History_Action_Change_V2(Memory, &PointToAdd->TangentLeft, &PointToAdd->TangentLeft, &NewLeftPos);
+ History_Action_Change_V2(Memory, &PointToAdd->TangentRight, &PointToAdd->TangentRight, &NewRightPos);
+
+ History_Action_Change_Increment(Memory, &Mask->NumberOfPoints, action_type_change_u16);
+ History_Entry_End(Memory);
}
static void
diff --git a/createcalls.cpp b/createcalls.cpp
index 193deee..b5be361 100644
--- a/createcalls.cpp
+++ b/createcalls.cpp
@@ -279,9 +279,9 @@ Layer_ScreenSpaceToLocal(project_layer *Layer, ui *UI, comp_buffer CompBuffer, I
static void
LoadTestFootage(project_data *File, project_state *State, memory *Memory)
{
- void *SourceString = String_GenerateFromChar(Memory, "../asset/24.mp4");
+ void *SourceString = String_GenerateFromChar(Memory, "../asset/a.jpg");
Source_Generate(File, Memory, SourceString);
- SourceString = String_GenerateFromChar(Memory, "../asset/a.jpg");
+ SourceString = String_GenerateFromChar(Memory, "../asset/24.mp4");
Source_Generate(File, Memory, SourceString);
SourceString = String_GenerateFromChar(Memory, "../asset/b.jpg");
Source_Generate(File, Memory, SourceString);
@@ -292,28 +292,30 @@ LoadTestFootage(project_data *File, project_state *State, memory *Memory)
Layer_CreateFromSource(File, State, Memory, &File->Source[0]);
SelectLayer(File->Layer[0], State, 0);
+ // AddEffect(File->Layer[0], Memory, 1);
// property_channel *Property = &File->Layer[0]->x;
// 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, 16, 1600);
// Keyframe_Insert(Property, Memory, 31, 3100);
+ // Keyframe_Delete(Property, Memory, 1);
// History_Undo(Memory);
// History_Redo(Memory);
- // Property->IsToggled = true;
+ // Property->IsToggled = true;
- // 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);
- Mask->Point[1].Pos = V2(200, 400);
- Mask->Point[2].Pos = V2(200, 520);
- Mask->Point[3].Pos = V2(1080, 520);
- Mask->Point[4].Pos = V2(1080, 200);
+ Mask->Point[1].Pos = V2(210, 400);
+ Mask->Point[2].Pos = V2(220, 520);
+ Mask->Point[3].Pos = V2(1380, 520);
+ Mask->Point[4].Pos = V2(1480, 200);
Mask->Point[0].TangentLeft = V2(-50, 0);
Mask->Point[1].TangentLeft = V2(-50, 0);
@@ -335,6 +337,16 @@ LoadTestFootage(project_data *File, project_state *State, memory *Memory)
Mask->NumberOfPoints = 5;
Mask->IsClosed = true;
+
+ Mask_DeletePoint(Memory, Mask, 1);
+
+ History_Undo(Memory);
+ // History_Redo(Memory);
+
+ Mask_AddPointToCurve(Memory, Mask, 1, 0.5);
+
+ History_Undo(Memory);
+ History_Redo(Memory);
*/
// if (!Source_Generate(File, Memory, "../asset/test.png"))
diff --git a/effects.cpp b/effects.cpp
index 2844d23..ee84c5b 100644
--- a/effects.cpp
+++ b/effects.cpp
@@ -132,6 +132,7 @@ AddEffect(project_layer *Layer, memory *Memory, uint16 EffectListIndex)
Effect->NumberOfProperties = EffectHeader.NumberOfProperties;
Effect->DisplayType = EffectHeader.DisplayType;
Effect->IsActive = true;
+ Effect->ImGuiID = RandomGlobalIncrement++;
for (int16 i = 0; i < Effect->NumberOfProperties; i++) {
Effect->Property[i].Name = EffectHeader.PropertyHeader[i].Name;
Effect->Property[i].CurrentValue = EffectHeader.PropertyHeader[i].Value;
diff --git a/effects.h b/effects.h
index d84bc25..793cadf 100644
--- a/effects.h
+++ b/effects.h
@@ -32,8 +32,10 @@ struct effect {
uint16 NumberOfProperties;
effect_display_type DisplayType;
property_channel Property[MAX_PROPERTIES_PER_EFFECT];
+ bool32 IsSelected = 0;
bool32 UIIsCollapsed = 0;
bool32 IsActive = 1;
+ uint32 ImGuiID;
};
diff --git a/functions.h b/functions.h
index 9b63832..044d877 100644
--- a/functions.h
+++ b/functions.h
@@ -44,8 +44,12 @@ 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_V2(memory *Memory, v2 *DataAddress, v2 *OriginalData, v2 *NewData);
static void History_Action_Change_Increment(memory *Memory, void *Data, action_type);
+static void History_Action_Change_Decrement(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_Shift_2(memory *Memory, void *StartingAddress, uint32 Size, uint16 NumberOf, int16 Direction, int16 Index);
+static void History_Action_StoreData(memory *Memory, void *DataAddress, uint64 ByteSize);
static void History_Action_Undo(memory *Memory);
static void History_Action_Redo(memory *Memory);
diff --git a/gl_calls.cpp b/gl_calls.cpp
index d791a9c..277b15b 100644
--- a/gl_calls.cpp
+++ b/gl_calls.cpp
@@ -179,10 +179,6 @@ GL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height,
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);
@@ -194,6 +190,10 @@ GL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height,
glBindRenderbuffer(GL_RENDERBUFFER, (GLuint)Test->Stencil_Renderbuffer );
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_STENCIL_INDEX8, Width, Height );
} else {
+ 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);
// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA,
// GL_UNSIGNED_BYTE, Data);
glBindTexture(GL_TEXTURE_2D, 0);
@@ -223,6 +223,7 @@ static void
GL_BindDefaultVertexArrays()
{
// Switch to main buffer
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, DefaultVerts.ElementBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, DefaultVerts.VertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(GL_DefaultVertices), GL_DefaultVertices, GL_STATIC_DRAW);
// position attribute
diff --git a/keyframes.cpp b/keyframes.cpp
index 7fb7c13..451f2b6 100644
--- a/keyframes.cpp
+++ b/keyframes.cpp
@@ -80,28 +80,6 @@ CheckKeyframeSort(property_channel *Property, int32 Increment, int32 b)
*/
}
-static void
-DeleteKeyframeFromMemory(property_channel *Property, int16 Increment, int16 StopAt) {
- if (Increment > 0) {
- int16 i = Property->NumberOfTotalKeyframes - 1;
- while (i > StopAt) {
- keyframe *CurrentKeyframe = KeyframeLookup(Property, i);
- keyframe *NextKeyframe = KeyframeLookup(Property, i + Increment);
- *NextKeyframe = *CurrentKeyframe;
- i--;
- }
- Property->NumberOfTotalKeyframes += Increment;
- } else {
- int16 i = StopAt;
- while (i < Property->NumberOfTotalKeyframes - 1) {
- keyframe *CurrentKeyframe = KeyframeLookup(Property, i);
- keyframe *NextKeyframe = KeyframeLookup(Property, i - Increment);
- *CurrentKeyframe = *NextKeyframe;
- i++;
- }
- Property->NumberOfTotalKeyframes += Increment;
- }
-}
static void
ResortPropertyChannel(property_channel *Property) {
@@ -130,6 +108,28 @@ ResortPropertyChannel(property_channel *Property) {
}
static void
+Keyframe_ShiftPointers(property_channel *Property, int16 Increment, int16 StopAt) {
+ if (Increment > 0) {
+ int16 i = Property->NumberOfTotalKeyframes - 1;
+ while (i >= StopAt) {
+ keyframe *CurrentKeyframe = KeyframeLookup(Property, i);
+ keyframe *NextKeyframe = KeyframeLookup(Property, i + Increment);
+ *NextKeyframe = *CurrentKeyframe;
+ i--;
+ }
+ } else {
+ int16 i = StopAt;
+ while (i <= Property->NumberOfTotalKeyframes - 1) {
+ keyframe *CurrentKeyframe = KeyframeLookup(Property, i);
+ keyframe *NextKeyframe = KeyframeLookup(Property, i - Increment);
+ *CurrentKeyframe = *NextKeyframe;
+ i++;
+ }
+ }
+}
+
+
+static void
DeleteSelectedKeyframes(project_data *File, memory *Memory)
{
for (int i = 0; i < File->NumberOfLayers; i++) {
@@ -148,7 +148,7 @@ DeleteSelectedKeyframes(project_data *File, memory *Memory)
Until = false;
}
}
- DeleteKeyframeFromMemory(Property, -ToShift, l);
+ Keyframe_ShiftPointers(Property, -ToShift, l);
}
}
ResortPropertyChannel(Property);
@@ -226,28 +226,6 @@ ClampSurroundingKeyframeHandles(property_channel *Property, int16 b) {
}
}
-
-static void
-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++;
- }
- }
-}
-
static uint32
Keyframe_FindClosestIndex(property_channel *Property, int32 CurrentFrame, bool32 *Overlapping)
{
@@ -301,6 +279,20 @@ Keyframe_FindClosestIndex(property_channel *Property, int32 CurrentFrame, bool32
}
}
+// NOTE(fox): Delete calls need to increment the total number before shifting!
+static void
+Keyframe_Delete(property_channel *Property, memory *Memory, uint32 Index)
+{
+ History_Entry_Commit(Memory, action_entry_default, "Delete keyframe");
+ keyframe *KeyframeIndex = KeyframeLookup(Property, Index);
+ History_Action_StoreData(Memory, KeyframeIndex, sizeof(keyframe));
+
+ History_Action_Change_Decrement(Memory, &Property->NumberOfTotalKeyframes, action_type_change_u16);
+ History_Action_Shift(Memory, action_type_shift_keyframe, Property, -1, Index);
+ Keyframe_ShiftPointers(Property, -1, Index);
+ History_Entry_End(Memory);
+}
+
static void
Keyframe_Insert(property_channel *Property, memory *Memory, int32 CurrentFrame, real32 Val)
{
@@ -317,7 +309,7 @@ Keyframe_Insert(property_channel *Property, memory *Memory, int32 CurrentFrame,
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_ShiftPointers(Property, 1, Index);
}
History_Action_Change_Increment(Memory, &Property->NumberOfTotalKeyframes, action_type_change_u16);
diff --git a/main.cpp b/main.cpp
index 85f1ed4..52cfae6 100644
--- a/main.cpp
+++ b/main.cpp
@@ -331,8 +331,11 @@ int main(int argc, char *argv[]) {
{
ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_DROPFILE) {
- printf("%s", event.drop.file);
- // AddSource(File, Memory, event.drop.file);
+ char *DropFile = event.drop.file;
+ // TODO(fox): Free failed strings if too many get created!
+ void *SourceString = String_GenerateFromChar(Memory, DropFile);
+ Source_Generate(File, Memory, SourceString);
+ SDL_free(DropFile);
}
if (event.type == SDL_QUIT)
State.IsRunning = false;
@@ -356,7 +359,7 @@ int main(int argc, char *argv[]) {
ImGui_EffectsPanel(&File, &State, &Memory, &UI, io);
- ImGui_PropertiesPanel(&File, &State, &UI, &Memory);
+ ImGui_PropertiesPanel(&File, &State, &UI, &Memory, io);
ImGui_Timeline(&File, &State, &Memory, &UI, io);
diff --git a/main.h b/main.h
index b0d1a1c..967354f 100644
--- a/main.h
+++ b/main.h
@@ -53,6 +53,14 @@ struct cached_bitmap {
uint32 Frame; // What frame it is.
};
+struct action_shift_data {
+ void *StartingAddress;
+ uint32 Size;
+ uint16 NumberOf;
+ uint16 Index;
+ int16 Direction;
+};
+
enum action_type {
action_type_change_u16,
action_type_change_i16,
@@ -62,7 +70,10 @@ enum action_type {
action_type_change_u64,
action_type_change_ptr,
action_type_change_string,
- action_type_shift_keyframe
+ action_type_shift_keyframe,
+ action_type_shift_bezier,
+ action_type_shift,
+ action_type_storedata
};
enum action_entry_type {
@@ -493,6 +504,7 @@ struct ui
real32 DraggingKeyframeThreshold;
real32 DraggingLayerThreshold;
real32 DraggingTimelineThreshold;
+ real32 DraggingEffectThreshold;
real32 KeyframeSpacing = 6;
ImVec2 BoxStart = ImVec2(0,0);
diff --git a/memory.cpp b/memory.cpp
index 2a9b29b..85c6610 100644
--- a/memory.cpp
+++ b/memory.cpp
@@ -25,6 +25,18 @@ AllocateMemory(memory *Memory, uint64 Size, memory_table_list TableName) {
return Address;
}
+// Returns the address without advancing
+static void*
+Memory_GetAddressAt(memory *Memory, uint64 Size, memory_table_list TableName) {
+ void *Address;
+ memory_table *Table = &Memory->Slot[TableName];
+ if (Table->CurrentPosition + Size > Table->Size) {
+ return NULL;
+ }
+ Address = (ptrsize *)((uint8 *)Table->Address + Table->CurrentPosition + Size);
+ return Address;
+}
+
// Returns the address and THEN advances
static void*
Memory_Advance(memory *Memory, uint64 Size, memory_table_list TableName) {
diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp
index ac0739e..1ef4d31 100644
--- a/my_imgui_widgets.cpp
+++ b/my_imgui_widgets.cpp
@@ -216,8 +216,10 @@ ImGui_DebugMemoryViewer(project_data *File, memory *Memory)
ImGui::End();
}
+static bool32 FU;
+
static void
-ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *Memory)
+ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io)
{
if (State->MostRecentlySelectedLayer > -1) {
project_layer *Layer = File->Layer[State->MostRecentlySelectedLayer];
@@ -238,20 +240,33 @@ ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *
}
for (int h = 0; h < Layer->NumberOfEffects; h++) {
effect *Effect = Layer->Effect[h];
- ImGui::PushID(Effect);
+ ImGui::PushID(Effect->ImGuiID);
+ if (FU && h == 0) {
+ int a = 0;
+ }
// this is stupid
if (Effect->IsActive)
ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetColorU32(ImGuiCol_ButtonHovered));
else
ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetColorU32(ImGuiCol_Button));
if (ImGui::Button("V")) {
- Effect->IsActive ^= 1;
+ History_Entry_Commit(Memory, action_entry_default, "Toggle effect");
+ History_Action_Change_SwapBool(Memory, &Effect->IsActive);
+ History_Entry_End(Memory);
State->UpdateFrame = true;
}
ImGui::SameLine();
ImGui::PopStyleColor();
ImGui::Button("R"); ImGui::SameLine();
- ImGui::Text(Effect->Name);
+ ImGui::Selectable(Effect->Name, Effect->IsSelected);
+ // NOTE(fox): The logic for effect dragging has to be after we've
+ // done the UI for the rest of the effect!
+ real32 Effect_Top = ImGui::GetCursorScreenPos().y;
+ bool32 IsHovered = ImGui::IsItemHovered();
+ bool32 IsActive = ImGui::IsItemActive();
+ bool32 IsActivated = ImGui::IsItemActivated();
+ bool32 IsDeactivated = ImGui::IsItemDeactivated();
+
if (Effect->DisplayType == standard) {
for (int i = 0; i < Effect->NumberOfProperties; i++) {
property_channel *Property = &Effect->Property[i];
@@ -355,6 +370,36 @@ ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *
ImGui::Button("K");
}
ImGui::PopID();
+
+ if (IsActive)
+ {
+ if (!Effect->IsSelected && IsActivated) {
+ Effect->IsSelected ^= 1;
+ }
+ if (ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1))
+ {
+ real32 Effect_Bottom = ImGui::GetCursorScreenPos().y;
+ real32 Effect_Length = Effect_Bottom - Effect_Top;
+ ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
+ UI->DraggingEffectThreshold += io.MouseDelta.y;
+ if (abs(UI->DraggingEffectThreshold) >= Effect_Length) {
+ int16 Increment = UI->DraggingEffectThreshold/Effect_Length;
+ effect *Effect = Layer->Effect[1];
+ Layer->Effect[1] = Layer->Effect[0];
+ Layer->Effect[0] = Effect;
+ // History_Entry_Commit(Memory, action_entry_default, "Change effect order");
+ // History_Entry_End(Memory);
+ FU = true;
+ UI->DraggingEffectThreshold += -1*Increment*Effect_Length;
+ State->UpdateFrame = true;
+ State->UpdateKeyframes = true;
+ }
+ }
+ }
+ if (FU) {
+ FU = false;
+ break;
+ }
}
} else {
char buf[256];
@@ -483,6 +528,10 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, memory *Memory,
if (ImGui::IsItemHovered()) {
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
}
+ if (ImGui::IsItemHovered() && ImGui::IsKeyPressed(ImGuiKey_Backspace)) {
+ Mask_DeletePoint(Memory, Mask, p);
+ State->UpdateFrame = true;
+ }
if (ImGui::IsItemActivated() && b == 0) {
if (p == 0 && State->Pen.IsActive) {
History_Entry_Commit(Memory, action_entry_default, "Close mask path");
@@ -491,8 +540,6 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, memory *Memory,
// State->Pen.IsActive = false;
// Mask->IsClosed = true;
History_Entry_End(Memory);
- } else if (io.KeyCtrl) {
- // TODO(fox): Mask delete!
} else if (io.KeyAlt) {
History_Entry_Commit(Memory, action_entry_default, "Switch handles on point");
History_Action_Change_SwapBool(Memory, &Point0->HandleBezier);
@@ -570,7 +617,7 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, memory *Memory,
if (ImGui::IsItemActivated() && io.KeyCtrl) {
v2 LayerPoint = Layer_ScreenSpaceToLocal(Layer, UI, CompBuffer, ViewportMin, io.MousePos);
real32 ratio = Bezier_CubicRatioOfPoint(Point0_Pos, Point0_Pos_Right, Point1_Pos_Left, Point1_Pos, LayerPoint);
- Mask_AddPointToCurve(Mask, p, ratio);
+ Mask_AddPointToCurve(Memory, Mask, p, ratio);
}
}
} else {
diff --git a/undo.cpp b/undo.cpp
index 6ebdfca..2306db9 100644
--- a/undo.cpp
+++ b/undo.cpp
@@ -114,6 +114,12 @@ void History_Action_Change_SwapBool(memory *Memory, bool32 *Bool)
History_Action_Change(Memory, Bool, Bool, &OppositeBool, action_type_change_i32);
}
+void History_Action_Change_V2(memory *Memory, v2 *DataAddress, v2 *OriginalData, v2 *NewData)
+{
+ History_Action_Change(Memory, (void *)&DataAddress->x, (void *)&OriginalData->x, (void *)&NewData->x, action_type_change_r32);
+ History_Action_Change(Memory, (void *)&DataAddress->y, (void *)&OriginalData->y, (void *)&NewData->y, action_type_change_r32);
+}
+
void History_Action_Change_Increment(memory *Memory, void *Data, action_type ActionChange)
{
switch (ActionChange)
@@ -155,6 +161,93 @@ void History_Action_Change_Increment(memory *Memory, void *Data, action_type Act
}
}
+void History_Action_Change_Decrement(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);
+ }
+ }
+}
+
+static void
+Arbitrary_ShiftData(action_shift_data ShiftData) {
+ int16 StopAt = ShiftData.Index;
+ if (ShiftData.Direction > 0) {
+ int16 i = ShiftData.NumberOf - 1;
+ while (i >= StopAt) {
+ uint8 *CurrentData = (uint8 *)ShiftData.StartingAddress + (ShiftData.Size * i);
+ uint8 *NextData = (uint8 *)ShiftData.StartingAddress + (ShiftData.Size * (i + ShiftData.Direction));
+ uint32 Bytes = 0;
+ while (Bytes < ShiftData.Size) {
+ *NextData++ = *CurrentData++;
+ Bytes++;
+ }
+ i--;
+ }
+ } else {
+ int16 i = StopAt;
+ while (i <= ShiftData.NumberOf - 1) {
+ uint8 *CurrentData = (uint8 *)ShiftData.StartingAddress + (ShiftData.Size * i);
+ uint8 *NextData = (uint8 *)ShiftData.StartingAddress + (ShiftData.Size * (i - ShiftData.Direction));
+ uint32 Bytes = 0;
+ while (Bytes < ShiftData.Size) {
+ *CurrentData++ = *NextData++;
+ Bytes++;
+ }
+ i++;
+ }
+ }
+}
+
+void History_Action_Shift_2(memory *Memory, void *StartingAddress, uint32 Size, uint16 NumberOf, int16 Direction, int16 Index)
+{
+ Memory->Action.Entry[Memory->Action.Index].NumberOfActions++;
+ void *Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
+ *(action_type *)Data = action_type_shift;
+ action_shift_data *ShiftData = (action_shift_data *)Memory_Advance(Memory, sizeof(action_shift_data), P_UndoBuffer);
+ ShiftData->StartingAddress = StartingAddress;
+ ShiftData->Size = Size;
+ ShiftData->NumberOf = NumberOf;
+ ShiftData->Index = Index;
+ ShiftData->Direction = Direction;
+ Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
+ *(action_type *)Data = action_type_shift;
+ Arbitrary_ShiftData(*ShiftData);
+}
+
void History_Action_Shift(memory *Memory, action_type ActionChange, void *DataAddress, int16 Direction, int16 Index)
{
Memory->Action.Entry[Memory->Action.Index].NumberOfActions++;
@@ -171,6 +264,15 @@ void History_Action_Shift(memory *Memory, action_type ActionChange, void *DataAd
void *DataIndex = Memory_Advance(Memory, sizeof(int16), P_UndoBuffer);
*(ptrsize *)DataIndex = (ptrsize)Index;
} break;
+ case action_type_shift_bezier:
+ {
+ 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);
@@ -180,6 +282,30 @@ void History_Action_Shift(memory *Memory, action_type ActionChange, void *DataAd
*(action_type *)Data = ActionChange;
}
+// Overwrite area with arbitrary-sized memory. Only use for creation/deletion,
+// not for value changes of things that already exist.
+void History_Action_StoreData(memory *Memory, void *DataAddress, uint64 ByteSize)
+{
+ Memory->Action.Entry[Memory->Action.Index].NumberOfActions++;
+ void *Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
+ *(action_type *)Data = action_type_storedata;
+ Data = Memory_Advance(Memory, sizeof(uint64), P_UndoBuffer);
+ *(uint64 *)Data = ByteSize;
+ Data = Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
+ *(ptrsize *)Data = (ptrsize)DataAddress;
+ uint64 i = 0;
+ while (i < ByteSize) {
+ void *DataIndex = Memory_Advance(Memory, 1, P_UndoBuffer);
+ *(uint8 *)DataIndex = *((uint8 *)DataAddress + i++);
+ }
+ Data = Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
+ *(ptrsize *)Data = (ptrsize)DataAddress;
+ Data = Memory_Advance(Memory, sizeof(uint64), P_UndoBuffer);
+ *(uint64 *)Data = ByteSize;
+ Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
+ *(action_type *)Data = action_type_storedata;
+}
+
// This is only called when we're certain the action is going to be taken.
void History_Entry_Commit(memory *Memory, action_entry_type Type, char *Name)
{
@@ -264,7 +390,33 @@ void History_Action_Undo(memory *Memory) {
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);
+ Keyframe_ShiftPointers((property_channel *)*DataPropertyAddress, *(int16 *)DataDirection * -1, *(int16 *)DataIndex);
+ } break;
+ case action_type_shift_bezier:
+ {
+ 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);
+ Mask_ShiftPointers((mask *)*DataPropertyAddress, *(int16 *)DataDirection * -1, *(int16 *)DataIndex);
+ } break;
+ case action_type_shift:
+ {
+ action_shift_data ShiftData = *(action_shift_data *)Memory_Rewind(Memory, sizeof(action_shift_data), P_UndoBuffer);
+ ShiftData.Direction *= -1;
+ Arbitrary_ShiftData(ShiftData);
+ } break;
+ case action_type_storedata:
+ {
+ uint64 *ByteSize = (uint64 *)Memory_Rewind(Memory, sizeof(uint64), P_UndoBuffer);
+ void *DataAddress = *(void **)Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer);
+ void *DataStart = Memory_Rewind(Memory, *ByteSize, P_UndoBuffer);
+ uint64 i = 0;
+ while (i < *ByteSize) {
+ void *DataIndex = Memory_GetAddressAt(Memory, i, P_UndoBuffer);
+ *((uint8 *)DataAddress + i++) = *(uint8 *)DataIndex;
+ }
+ DataStart = Memory_Rewind(Memory, sizeof(void *), P_UndoBuffer);
+ DataStart = Memory_Rewind(Memory, sizeof(uint64), P_UndoBuffer);
} break;
default:
{
@@ -332,7 +484,28 @@ void History_Action_Redo(memory *Memory) {
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);
+ Keyframe_ShiftPointers((property_channel *)*DataPropertyAddress, *(int16 *)DataDirection, *(int16 *)DataIndex);
+ } break;
+ case action_type_shift_bezier:
+ {
+ 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);
+ Mask_ShiftPointers((mask *)*DataPropertyAddress, *(int16 *)DataDirection, *(int16 *)DataIndex);
+ } break;
+ case action_type_shift:
+ {
+ action_shift_data ShiftData = *(action_shift_data *)Memory_Advance(Memory, sizeof(action_shift_data), P_UndoBuffer);
+ Arbitrary_ShiftData(ShiftData);
+ } break;
+ case action_type_storedata:
+ {
+ // NOTE(fox): Right now I'm only using this to overwrite data, so all we need to do is advance.
+ uint64 *ByteSize = (uint64 *)Memory_Advance(Memory, sizeof(uint64), P_UndoBuffer);
+ void *DataAddress = *(void **)Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
+ void *DataEnd = Memory_Advance(Memory, *ByteSize, P_UndoBuffer);
+ DataEnd = Memory_Advance(Memory, sizeof(void *), P_UndoBuffer);
+ DataEnd = Memory_Advance(Memory, sizeof(uint64), P_UndoBuffer);
} break;
default:
{