summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFox Caminiti <fox@foxcam.net>2022-08-15 23:03:30 -0400
committerFox Caminiti <fox@foxcam.net>2022-08-15 23:03:30 -0400
commit04b7ccfd87d802e6b9a22b86c8d098979164b8ba (patch)
treeb155fbfb7d4b494bae79073161dfeb36dc8edc49
parent67898c6505c9180b5a5a31457f11d29b41fa91ba (diff)
undo started
-rw-r--r--bitmap_calls.cpp28
-rw-r--r--createcalls.cpp41
-rw-r--r--defines.h3
-rw-r--r--ffmpeg_backend.cpp1
-rw-r--r--functions.h6
-rw-r--r--keyframes.cpp86
-rw-r--r--main.cpp12
-rw-r--r--main.h27
-rw-r--r--memory.cpp10
-rw-r--r--my_imgui_widgets.cpp31
-rw-r--r--strings.cpp21
-rw-r--r--undo.cpp146
12 files changed, 325 insertions, 87 deletions
diff --git a/bitmap_calls.cpp b/bitmap_calls.cpp
index dd5c793..6425e6d 100644
--- a/bitmap_calls.cpp
+++ b/bitmap_calls.cpp
@@ -31,10 +31,17 @@ void Bitmap_ConvertPacking(void *Buffer, void *DestBuffer, uint16 Width, uint16
DPixel = Temp + Y*Width*4 + X*BytesPerPixel;
}
+#if ARM
+ if (InstructionMode == instruction_mode_neon) {
+ uint32x2x2_t Row = vld2_u32((uint32 *)Pixel);
+ vst2_u32((uint32 *)DPixel, Row);
+ X += 4;
+#else
if (InstructionMode == instruction_mode_sse || InstructionMode == instruction_mode_avx) {
__m128i Row = _mm_loadu_si128((__m128i *)Pixel);
_mm_storeu_si128((__m128i *)DPixel, Row);
X+=4;
+#endif
} else {
*(uint32 *)DPixel = *(uint32 *)Pixel;
X++;
@@ -101,8 +108,13 @@ static void
Bitmap_Clear(void *Buffer, uint16 Width, uint16 Height, uint16 BytesPerPixel)
{
uint8 *Row = (uint8 *)Buffer;
+#if ARM
+ uint32 Zero[4] = {0};
+ uint32x2x4_t Zero8 = vld4_dup_u32(Zero);
+#else
__m256i Zero8 = _mm256_setzero_si256();
__m128i Zero = _mm_setzero_si128();
+#endif
uint64 bytes = 0;
uint16 ByteOffset = Bitmap_CalcByteOffset(BytesPerPixel);
@@ -110,10 +122,15 @@ Bitmap_Clear(void *Buffer, uint16 Width, uint16 Height, uint16 BytesPerPixel)
while (bytes < TotalBytes) {
uint8 *Pixel = Row + bytes;
+#if ARM
+ if (InstructionMode == instruction_mode_neon) {
+ vst4_u32((uint32 *)Pixel, Zero8);
+#else
if (InstructionMode == instruction_mode_avx) {
_mm256_storeu_si256((__m256i *)Pixel, Zero8);
} else if (InstructionMode == instruction_mode_sse) {
_mm_storeu_si128((__m128i *)Pixel, Zero);
+#endif
} else {
*(uint32 *)Pixel = 0x00000000;
}
@@ -136,10 +153,15 @@ Bitmap_CalcPackedDimensions(uint16 Width, uint16 Height, uint16 *WidthP, uint16
static uint16
Bitmap_CalcByteOffset(uint16 BytesPerPixel) {
uint16 ByteOffset = BytesPerPixel;
+#if ARM
+ if (InstructionMode == instruction_mode_neon)
+ ByteOffset = 8*BytesPerPixel;
+#else
if (InstructionMode == instruction_mode_avx)
ByteOffset = 8*BytesPerPixel;
if (InstructionMode == instruction_mode_sse)
ByteOffset = 4*BytesPerPixel;
+#endif
return ByteOffset;
}
@@ -174,12 +196,18 @@ Bitmap_CopyToPointer(void *Input, void *Output, uint16 BytesPerPixel, uint64 Tot
int pp = 0;
uint8 *Pixel = (uint8 *)Row + bytes;
uint8 *Pixel2 = (uint8 *)Row2 + bytes;
+#if ARM
+ if (InstructionMode == instruction_mode_neon) {
+ uint32x2x4_t OutputPixel = vld4_u32((uint32 *)Pixel);
+ vst4_u32((uint32 *)Pixel2, OutputPixel);
+#else
if (InstructionMode == instruction_mode_avx) {
__m256i OutputPixel = _mm256_loadu_si256((__m256i *)Pixel);
_mm256_storeu_si256((__m256i *)Pixel2, OutputPixel);
} else if (InstructionMode == instruction_mode_sse) {
__m128i OutputPixel = _mm_loadu_si128((__m128i *)Pixel);
_mm_storeu_si128((__m128i *)Pixel2, OutputPixel);
+#endif
} else {
*(uint32 *)Pixel2 = *(uint32 *)Pixel;
}
diff --git a/createcalls.cpp b/createcalls.cpp
index 633a37a..4564d59 100644
--- a/createcalls.cpp
+++ b/createcalls.cpp
@@ -8,31 +8,35 @@ IncrementFrame(project_data *File, int16 Amount) {
}
static bool32
-Source_Generate(project_data *File, memory *Memory, char *Path)
+Source_Generate(project_data *File, memory *Memory, void *Path)
{
Assert(File->NumberOfSources < MAX_SOURCES);
source *Source = &File->Source[File->NumberOfSources];
bool32 Found = 0;
+ /*
+ // TODO(fox): Unbreak stbi!
int w, h;
if (stbi_info(Path, &w, &h, NULL)) {
- Source->Info.Width = w;
- Source->Info.Height = h;
Source->SourceType = source_type_image;
Found = true;
}
+ */
- if (!Found && AV_IsFileSupported(Path)) {
+ // TODO(fox): This cast won't work above STRING_MAX.
+ if (!Found && AV_IsFileSupported((char *)Path)) {
Source->SourceType = source_type_video;
Found = true;
}
if (Found) {
- Source->Info.BytesPerPixel = 4;
- Source->Path = Path;
- File->NumberOfSources++;
+ Action_Change_Commit(Memory, &Source->Path, &Path, action_change_ptr);
+ uint32 i = File->NumberOfSources + 1;
+ Action_Change_Commit(Memory, &File->NumberOfSources, &i, action_change_u16);
return 1;
+ } else {
+ // PostMsg(State, "File open fail...");
}
return 0;
@@ -133,7 +137,7 @@ project_layer * Layer_Init(project_data *File, memory *Memory)
File->Layer[a] = (project_layer *)AllocateMemory(Memory, sizeof(project_layer), F_Layers);
- File->Layer[a]->Name = (char *)AllocateMemory(Memory, 256, F_Strings);
+ File->Layer[a]->Name = (char *)AllocateMemory(Memory, STRING_SIZE, F_Strings);
sprintf(File->Layer[a]->Name, "Layer %i", a);
File->Layer[a]->x = InitFloatProperty("X Position", 0.0f, 1.0f);
File->Layer[a]->y = InitFloatProperty("Y Position", 0.0f, 1.0f);
@@ -386,14 +390,20 @@ Layer_ScreenSpaceToLocal(project_layer *Layer, ui *UI, comp_buffer CompBuffer, I
static void
LoadTestFootage(project_data *File, project_state *State, memory *Memory)
{
- if (!Source_Generate(File, Memory, "../asset/24.mp4"))
- PostMsg(State, "File open fail...");
- source *Source = &File->Source[0];
+ void *SourceString = String_GenerateFromChar(Memory, "../asset/24.mp4");
+ Source_Generate(File, Memory, SourceString);
Layer_CreateFromSource(File, State, Memory, Source);
+ Action_Undo(Memory);
+ Action_Undo(Memory);
+ Action_Redo(Memory);
+ Action_Redo(Memory);
+ Assert(0);
+ source *Source = &File->Source[0];
SelectLayer(File->Layer[0], State, 0);
// 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);
@@ -421,11 +431,12 @@ LoadTestFootage(project_data *File, project_state *State, memory *Memory)
Mask->Point[4].HandleBezier = true;
Mask->NumberOfPoints = 5;
+ */
// if (!Source_Generate(File, Memory, "../asset/test.png"))
// PostMsg(State, "File open fail...");
- if (!Source_Generate(File, Memory, "../asset/debug.png"))
- PostMsg(State, "File open fail...");
+ // if (!Source_Generate(File, Memory, "../asset/debug.png"))
+ // PostMsg(State, "File open fail...");
// property_channel *Property = &File->Layer[0]->x;
// ManualKeyframeInsertF(Property, Memory, 1, 500);
@@ -439,8 +450,8 @@ LoadTestFootage(project_data *File, project_state *State, memory *Memory)
// Layer_CreateFromSource(File, State, Memory, Source);
- if (!Source_Generate(File, Memory, "../asset/p.mp4"))
- PostMsg(State, "File open fail...");
+ // if (!Source_Generate(File, Memory, "../asset/p.mp4"))
+ // PostMsg(State, "File open fail...");
// source *Source2 = &File->Source[1];
// project_layer *Layer2 = Layer_Init(File, Memory);
// AV_Init(Source2, &Layer2->BitmapInfo, Memory);
diff --git a/defines.h b/defines.h
index e9a11de..b919afb 100644
--- a/defines.h
+++ b/defines.h
@@ -15,6 +15,9 @@ typedef uint64_t uint64;
typedef float real32;
typedef double real64;
+// is there a compiler variable for 32 vs 64 bit like this?
+typedef uint64 ptrsize;
+
#define NORMALIZED_COL_MIN { .col = V4(0.0f, 0.0f, 0.0f, 0.0f) }
#define NORMALIZED_COL_MAX { .col = V4(1.0f, 1.0f, 1.0f, 1.0f) }
#define NORMALIZED_REAL_MIN { 0.0f }
diff --git a/ffmpeg_backend.cpp b/ffmpeg_backend.cpp
index b3d5be8..f437285 100644
--- a/ffmpeg_backend.cpp
+++ b/ffmpeg_backend.cpp
@@ -173,6 +173,7 @@ void AV_Init(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory)
fprintf(stderr, "Libav error: (%s)\n", av_err2str(err));
}
+ Source->Info.BytesPerPixel = 4;
Source->Info.FPS = (real32)AV->VideoStream->r_frame_rate.num / AV->VideoStream->r_frame_rate.den;
Source->Info.Width = AV->VideoCodecContext->width;
Source->Info.Height = AV->VideoCodecContext->height;
diff --git a/functions.h b/functions.h
index 81f18ee..7f8f5d3 100644
--- a/functions.h
+++ b/functions.h
@@ -12,7 +12,7 @@ static uint64 Bitmap_CalcUnpackedBytes(uint16 Width, uint16 Height, uint16 Bytes
static void Bitmap_ConvertPacking(void *Buffer, void *DestBuffer, uint16 Width, uint16 Height, uint16 BytesPerPixel, uint16 Which);
static void Bitmap_CalcHistogram(void *Data, void *Input, uint16 BytesPerPixel, uint64 TotalBytes);
-static bool32 Source_Generate(project_data *File, memory *Memory, char *Path); // Fills out source info if the source is a supported file.
+static bool32 Source_Generate(project_data *File, memory *Memory, void *Path); // Fills out source info if the source is a supported file.
// Libav (ffmpeg) backend for decoding video
@@ -32,3 +32,7 @@ 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 *NewData, action_change_type ActionChange);
+static void Action_Undo(memory *Memory);
+static void Action_Redo(memory *Memor);
+
diff --git a/keyframes.cpp b/keyframes.cpp
index d2813a9..25c41c0 100644
--- a/keyframes.cpp
+++ b/keyframes.cpp
@@ -6,14 +6,6 @@ KeyframeLookupMemory(property_channel *Property, int16 i) {
}
static keyframe*
-KeyframeLookupIndex(property_channel *Property, int16 a) {
- int16 i = Property->SortedIndex[a];
- int16 b = i / MAX_KEYFRAMES_PER_BLOCK;
- int16 k = i - b*MAX_KEYFRAMES_PER_BLOCK;
- return &Property->KeyframeBlock[b]->Keyframe[k];
-}
-
-static keyframe*
PushKeyframe(property_channel *Property) {
int16 i = Property->NumberOfTotalKeyframes;
int16 b = i / MAX_KEYFRAMES_PER_BLOCK;
@@ -21,7 +13,6 @@ PushKeyframe(property_channel *Property) {
return &Property->KeyframeBlock[b]->Keyframe[k];
}
-// (extremely bad)
static temp_keyframe_list
GetSelectedKeyframes(project_data *File)
{
@@ -42,20 +33,6 @@ GetSelectedKeyframes(project_data *File)
return KeyframeList;
}
-static int32
-KeyframeMemoryToIndex(property_channel *Property, int32 a)
-{
- int32 Result = -1;
- for (int l = 0; l < Property->NumberOfTotalKeyframes; l++) {
- if (Property->SortedIndex[l] == a) {
- Result = l;
- break;
- }
- }
- Assert(Result > -1);
- return Result;
-}
-
static void
SelectKeyframe(project_data *File, project_layer *Layer, property_channel *Property, keyframe *Keyframe)
{
@@ -77,6 +54,7 @@ DeselectKeyframe(project_data *File, project_layer *Layer, property_channel *Pro
static void
CheckKeyframeSort(property_channel *Property, int32 Increment, int32 b)
{
+ /*
int32 i = KeyframeMemoryToIndex(Property, b);
if (Increment > 0) {
if (i+1 != Property->NumberOfTotalKeyframes) {
@@ -99,10 +77,12 @@ 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) {
@@ -116,6 +96,7 @@ ShiftKeyframeIndex(property_channel *Property, int16 Increment, int16 StopAt) {
i++;
}
}
+ */
}
static void
@@ -143,6 +124,7 @@ DeleteKeyframeFromMemory(property_channel *Property, int16 Increment, int16 Stop
static void
ResortPropertyChannel(property_channel *Property) {
+ /*
for (int16 i = 0; i < Property->NumberOfTotalKeyframes; i++)
{
Property->SortedIndex[i] = i;
@@ -163,6 +145,7 @@ ResortPropertyChannel(property_channel *Property) {
if (Swaps == 0)
break;
}
+ */
}
static void
@@ -211,10 +194,12 @@ CalculatePropertyMinMax(property_channel *Property) {
static void
IncrementKeyframes(property_channel *Property, int16 Increment)
{
+ /*
for (int i = 0; i < Property->NumberOfTotalKeyframes; i++) {
keyframe *Keyframe = KeyframeLookupIndex(Property, i);
Keyframe->FrameNumber += Increment;
}
+ */
}
static void
@@ -235,8 +220,8 @@ static void
ClampKeyframeHandles(property_channel *Property, int16 b, int16 dir) {
if (dir == 0) {
if (b > 0) {
- keyframe *Keyframe = KeyframeLookupIndex(Property, b - 1);
- keyframe *NextKeyframe = KeyframeLookupIndex(Property, b);
+ keyframe *Keyframe = KeyframeLookupMemory(Property, b - 1);
+ keyframe *NextKeyframe = KeyframeLookupMemory(Property, b);
real32 XSpan = NextKeyframe->FrameNumber - Keyframe->FrameNumber;
// TODO(fox): Fix this!
#if WINDOWS
@@ -251,8 +236,8 @@ ClampKeyframeHandles(property_channel *Property, int16 b, int16 dir) {
}
if (dir == 1) {
if (b < Property->NumberOfTotalKeyframes - 1) {
- keyframe *Keyframe = KeyframeLookupIndex(Property, b);
- keyframe *NextKeyframe = KeyframeLookupIndex(Property, b + 1);
+ keyframe *Keyframe = KeyframeLookupMemory(Property, b);
+ keyframe *NextKeyframe = KeyframeLookupMemory(Property, b + 1);
real32 XSpan = NextKeyframe->FrameNumber - Keyframe->FrameNumber;
if (Keyframe->TangentRight.x > XSpan)
Keyframe->TangentRight.x = XSpan;
@@ -281,55 +266,53 @@ 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);
}
keyframe *Keyframe = NULL;
if (Property->NumberOfTotalKeyframes == 0) {
Keyframe = &Property->KeyframeBlock[0]->Keyframe[0];
- Property->NumberOfTotalKeyframes++;
} else if (Property->NumberOfTotalKeyframes == 1) {
- Keyframe = &Property->KeyframeBlock[0]->Keyframe[0];
- if (CurrentFrame != Keyframe->FrameNumber) {
- if (CurrentFrame > Keyframe->FrameNumber) {
- Property->SortedIndex[1] = 1;
- } else {
- Property->SortedIndex[0] = 1;
- }
- Property->NumberOfTotalKeyframes++;
- }
- Keyframe = &Property->KeyframeBlock[0]->Keyframe[1];
- } else {
- keyframe *LastKeyframe = KeyframeLookupIndex(Property, Property->NumberOfTotalKeyframes-1);
- if (LastKeyframe->FrameNumber < CurrentFrame) {
- Property->SortedIndex[Property->NumberOfTotalKeyframes] = Property->NumberOfTotalKeyframes;
+ keyframe *FirstKeyframe = &Property->KeyframeBlock[0]->Keyframe[0];
+ if (CurrentFrame > FirstKeyframe->FrameNumber) {
+ Keyframe = &Property->KeyframeBlock[0]->Keyframe[1];
} else {
- for (int16 i = 0; i < Property->NumberOfTotalKeyframes; i++) {
- keyframe *CurrentKeyframe = KeyframeLookupIndex(Property, i);
- if (CurrentKeyframe->FrameNumber > CurrentFrame) {
- ShiftKeyframeIndex(Property, 1, i - 1);
- Property->SortedIndex[i] = Property->NumberOfTotalKeyframes;
- break;
- }
+ Keyframe = &Property->KeyframeBlock[0]->Keyframe[0];
+ }
+ } else {
+ uint32 Index = Property->NumberOfTotalKeyframes - 1;
+ bool32 Found = false;
+ while (!Found) {
+ keyframe *CurrentKeyframe = KeyframeLookupMemory(Property, Index);
+ if (CurrentKeyframe->FrameNumber < CurrentFrame) {
+ ShiftKeyframes(Property, 1, i - 1);
+ Found = true;
+ } else {
+ Index--;
}
}
Keyframe = PushKeyframe(Property);
- Property->NumberOfTotalKeyframes++;
}
+ if (Keyframe->FrameNumber != CurrentFrame)
+ Property->NumberOfTotalKeyframes++;
Assert(!(Keyframe == NULL))
+
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);
+ */
}
static void
CalculateKeyframesLinearly(uint16 CurrentFrame, struct property_channel *Property)
{
-
+ /*
keyframe *FirstKeyframe = KeyframeLookupIndex(Property, 0);
keyframe *LastKeyframe = KeyframeLookupIndex(Property, Property->NumberOfTotalKeyframes - 1);
@@ -385,4 +368,5 @@ CalculateKeyframesLinearly(uint16 CurrentFrame, struct property_channel *Propert
}
}
}
+ */
}
diff --git a/main.cpp b/main.cpp
index 2153ae6..ac4ddd1 100644
--- a/main.cpp
+++ b/main.cpp
@@ -51,6 +51,7 @@ SDL_atomic_t QueuedEntries;
SDL_atomic_t CompletedEntries;
static bool32 IsRendering = false;
static instruction_mode InstructionMode = instruction_mode_scalar;
+static uint32 RandomGlobalIncrement = 0;
render_entry Entries[256];
@@ -73,6 +74,7 @@ SDL_sem *Semaphore;
#include "createcalls.cpp"
#include "my_imgui_widgets.cpp"
#include "gl_calls.cpp"
+#include "undo.cpp"
static void
@@ -224,11 +226,10 @@ int main(int argc, char *argv[]) {
memory Memory = {};
- // TODO(fox): Make clean-up functions when these get deleted!
InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, P_AVInfo, "Image/video headers");
- InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, P_SourceBitmapTable, "Source bitmap tables");
InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, P_VectorPoints, "Vector Points");
+ InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, P_UndoBuffer, "Undo buffer");
InitMemoryTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, P_MiscCache, "Misc cache");
InitMemoryTable(&GlobalMemory, &Memory, 15 * 1024 * 1024, F_Layers, "Layers");
@@ -259,6 +260,10 @@ int main(int argc, char *argv[]) {
File.StartFrame = 0;
File.EndFrame = 65;
+ LoadTestFootage(&File, &State, &Memory);
+
+ Assert(0);
+
#if DEBUG
// GDB and LLDB say this plain struct that's literally under 30 bytes is
// incomplete in the layers unless I do this...
@@ -313,6 +318,7 @@ int main(int argc, char *argv[]) {
RenderInfo.File = &File;
RenderInfo.State = &State;
RenderInfo.CompBuffer = &CompBuffer;
+
#if THREADED
thread_info ThreadInfo[7];
@@ -383,8 +389,6 @@ int main(int argc, char *argv[]) {
TestGL_InitDefaultShader();
TestGL_InitDefaultVerts();
- LoadTestFootage(&File, &State, &Memory);
-
SDL_GL_MakeCurrent(window, gl_context);
SDL_Event Event;
diff --git a/main.h b/main.h
index e77042f..4e48fc5 100644
--- a/main.h
+++ b/main.h
@@ -29,10 +29,12 @@ enum memory_table_list {
// B = cached data, often cleared
P_AVInfo,
- P_SourceBitmapTable,
P_VectorPoints,
- P_MiscCache, // don't put this in final
+ P_UndoBuffer,
+ P_MiscCache,
+ // The structs that these four blocks correspond to (project_layer, effect,
+ // keyframe_block, char[STRING_SIZE]) are guranteed equal size.
F_Layers,
F_Effects,
F_Keyframes,
@@ -165,6 +167,17 @@ struct gl_effect_layer {
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;
v4 col;
@@ -180,6 +193,9 @@ struct keyframe {
// Probably should think of something smarter.
v2 TangentLeft;
v2 TangentRight;
+ // NOTE(fox): We need some sort of unique constant to give to ImGui in
+ // order for dragging to work.
+ uint32 ImguiID;
};
struct keyframe_block {
@@ -189,7 +205,6 @@ struct keyframe_block {
struct property_channel {
char *Name;
keyframe_block *KeyframeBlock[MAX_KEYFRAME_BLOCKS];
- uint16 SortedIndex[MAX_KEYFRAME_BLOCKS * MAX_KEYFRAMES_PER_BLOCK];
uint16 NumberOfKeyframeBlocks;
uint16 NumberOfSelectedKeyframes;
uint16 NumberOfTotalKeyframes;
@@ -299,8 +314,6 @@ struct effect {
bool32 IsActive = 1;
};
-
-
struct transform_info {
real32 XAxisPX;
real32 XAxisPY;
@@ -323,6 +336,7 @@ struct transform_info {
struct mask_point {
v2 Pos;
bool32 HandleBezier;
+ bool32 IsSelected;
v2 TangentLeft;
v2 TangentRight;
};
@@ -330,6 +344,7 @@ struct mask_point {
struct mask {
mask_point Point[16];
uint16 NumberOfPoints;
+ uint16 NumberOfSelectedPoints;
void *TriangulatedPointCache;
uint32 NumberOfVerts;
};
@@ -435,6 +450,8 @@ enum selection_type
selection_layer,
selection_effect,
selection_keyframe,
+ selection_maskpoint,
+ selection_source
};
enum tool {
diff --git a/memory.cpp b/memory.cpp
index dd581b7..7c08f91 100644
--- a/memory.cpp
+++ b/memory.cpp
@@ -1,12 +1,18 @@
+
static void
InitMemoryTable(global_memory *GlobalMemory, memory *Memory, uint64 Size, memory_table_list TableName, char *Name) {
memory_table *Table = &Memory->Slot[TableName];
Table->Name = Name;
- Table->Address = (uint64 *)((uint8 *)GlobalMemory->Address + GlobalMemory->CurrentPosition);
+ Table->Address = (ptrsize *)((uint8 *)GlobalMemory->Address + GlobalMemory->CurrentPosition);
Table->Size = Size;
GlobalMemory->CurrentPosition += Size;
}
+// NOTE(fox): Currently memory acts like simple stack that can only grow forwards.
+// Undos/deletes create "holes." Once someone undos/deletes enough to trigger
+// the limit or we start caring more about space, I'll revamp the system to
+// keep track of free holes and allow those to be returned.
+
static void*
AllocateMemory(memory *Memory, uint64 Size, memory_table_list TableName) {
void *Address;
@@ -14,7 +20,7 @@ AllocateMemory(memory *Memory, uint64 Size, memory_table_list TableName) {
if (Table->CurrentPosition + Size > Table->Size) {
return NULL;
}
- Address = (uint64 *)((uint8 *)Table->Address + Table->CurrentPosition);
+ Address = (ptrsize *)((uint8 *)Table->Address + Table->CurrentPosition);
Table->CurrentPosition += Size;
return Address;
}
diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp
index 4a4427c..d1d8d83 100644
--- a/my_imgui_widgets.cpp
+++ b/my_imgui_widgets.cpp
@@ -416,16 +416,19 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, comp_buffer Comp
// The handle itself
- draw_list->AddNgon(Point0_ScreenPos, 10, col, 8, 5.0f);
+ if (Point0->IsSelected) {
+ col = ImGui::GetColorU32(ImGuiCol_ButtonHovered);
+ draw_list->AddNgon(Point0_ScreenPos_Left, 10, col, 8, 5.0f);
+ draw_list->AddNgon(Point0_ScreenPos_Right, 10, col, 8, 5.0f);
+ draw_list->AddLine(Point0_ScreenPos, Point0_ScreenPos_Left, col, 2.0f);
+ draw_list->AddLine(Point0_ScreenPos, Point0_ScreenPos_Right, col, 2.0f);
+ }
- draw_list->AddNgon(Point0_ScreenPos_Left, 10, col, 8, 5.0f);
- draw_list->AddNgon(Point0_ScreenPos_Right, 10, col, 8, 5.0f);
- draw_list->AddLine(Point0_ScreenPos, Point0_ScreenPos_Left, col, 2.0f);
- draw_list->AddLine(Point0_ScreenPos, Point0_ScreenPos_Right, col, 2.0f);
+ draw_list->AddNgon(Point0_ScreenPos, 10, col, 8, 5.0f);
int max = 1;
- if (Point0->HandleBezier) {
+ if (Point0->HandleBezier && Point0->IsSelected) {
max = 3;
}
@@ -440,11 +443,14 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, comp_buffer Comp
ImGui::SetCursorScreenPos(Point0_ScreenPos_Right - ImVec2(PointSize/2, PointSize/2));
}
- ImGui::Button("##point", ImVec2(PointSize, PointSize));
+ ImGui::InvisibleButton("##point", ImVec2(PointSize, PointSize), ImGuiButtonFlags_MouseButtonLeft);
if (ImGui::IsItemHovered()) {
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
}
+ if (ImGui::IsItemActivated() && b == 0) {
+ Point0->IsSelected = 1;
+ }
if (ImGui::IsItemActive()) {
// TODO(fox): Combine this with the anchor point code.
ImVec2 MouseIncrement = io.MouseDelta * (ImVec2(CompBuffer.Width, CompBuffer.Height) / UI->CompZoom);
@@ -1258,7 +1264,7 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI,
// TODO(fox): Reformat this so it's all done in one loop.
for (int b = 0; b < Property->NumberOfTotalKeyframes; b++) {
- keyframe *Keyframe = KeyframeLookupIndex(Property, b);
+ keyframe *Keyframe = KeyframeLookupMemory(Property, b);
real32 MinVal = Property->LocalMinVal.f;
real32 MaxVal = Property->LocalMaxVal.f;
@@ -1533,7 +1539,14 @@ ImGui_ProcessInputs(project_data *File, project_state *State, comp_buffer *CompB
DeleteSelectedKeyframes(File, Memory);
State->UpdateKeyframes = true;
State->UpdateFrame = true;
- } break;
+ }
+ case selection_maskpoint:
+ {
+ }
+ case selection_source:
+ {
+ }
+ break;
}
}
diff --git a/strings.cpp b/strings.cpp
index c1b9c9f..6caedd0 100644
--- a/strings.cpp
+++ b/strings.cpp
@@ -13,3 +13,24 @@ EffectConsoleCallback(ImGuiInputTextCallbackData* data)
}
return 0;
}
+
+static void
+CopyStrings(void *Dest, void *Data)
+{
+ for (int i = 0; i < STRING_SIZE; i++)
+ {
+ *((char *)Dest + i) = *((char *)Data + i);
+ }
+}
+
+static void *
+String_GenerateFromChar(memory *Memory, char *Char)
+{
+ void *Address = AllocateMemory(Memory, STRING_SIZE, F_Strings);
+ uint16 i = 0;
+ while (Char[i] != '\0') {
+ *((char *)Address + i) = Char[i];
+ i++;
+ }
+ return Address;
+}
diff --git a/undo.cpp b/undo.cpp
new file mode 100644
index 0000000..7858f8d
--- /dev/null
+++ b/undo.cpp
@@ -0,0 +1,146 @@
+// get ready for some MLG...
+
+// 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.
+// 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 *OriginalData, void *NewData, action_change_type ActionChange)
+{
+ void *UndoEntry = AllocateMemory(Memory, sizeof(void *), P_UndoBuffer);
+ *(ptrsize *)UndoEntry = (ptrsize)OriginalData;
+ void *Data = AllocateMemory(Memory, sizeof(action_change_type), P_UndoBuffer);
+ *(action_change_type *)Data = ActionChange;
+ switch (ActionChange)
+ {
+ case action_change_u16:
+ {
+ uint16 OriginalValue = *(uint16 *)OriginalData;
+ uint16 NewValue = *(uint16 *)NewData;
+ uint16 Difference = NewValue - OriginalValue;
+ void *Data = AllocateMemory(Memory, sizeof(uint16), P_UndoBuffer);
+ *(uint16 *)Data = Difference;
+ *(uint16 *)OriginalData = *(uint16 *)NewData;
+ } break;
+ case action_change_i16:
+ {
+ int16 OriginalValue = *(int16 *)OriginalData;
+ int16 NewValue = *(int16 *)NewData;
+ int16 Difference = NewValue - OriginalValue;
+ void *Data = AllocateMemory(Memory, sizeof(int16), P_UndoBuffer);
+ *(int16 *)Data = Difference;
+ *(int16 *)OriginalData = *(int16 *)NewData;
+ } break;
+ case action_change_u32:
+ {
+ uint32 OriginalValue = *(uint32 *)OriginalData;
+ uint32 NewValue = *(uint32 *)NewData;
+ uint32 Difference = NewValue - OriginalValue;
+ void *Data = AllocateMemory(Memory, sizeof(uint32), P_UndoBuffer);
+ *(uint32 *)Data = Difference;
+ *(uint32 *)OriginalData = *(uint32 *)NewData;
+ } break;
+ case action_change_i32:
+ {
+ int32 OriginalValue = *(int32 *)OriginalData;
+ int32 NewValue = *(int32 *)NewData;
+ int32 Difference = NewValue - OriginalValue;
+ void *Data = AllocateMemory(Memory, sizeof(int32), P_UndoBuffer);
+ *(int32 *)Data = Difference;
+ *(int32 *)OriginalData = *(int32 *)NewData;
+ } break;
+ case action_change_r32:
+ {
+ real32 OriginalValue = *(real32 *)OriginalData;
+ real32 NewValue = *(real32 *)NewData;
+ real32 Difference = NewValue - OriginalValue;
+ void *Data = AllocateMemory(Memory, sizeof(real32), P_UndoBuffer);
+ *(real32 *)Data = Difference;
+ *(real32 *)OriginalData = *(real32 *)NewData;
+ } break;
+ case action_change_u64:
+ {
+ uint64 OriginalValue = *(uint64 *)OriginalData;
+ uint64 NewValue = *(uint64 *)NewData;
+ uint64 Difference = NewValue - OriginalValue;
+ void *Data = AllocateMemory(Memory, sizeof(uint64), P_UndoBuffer);
+ *(uint64 *)Data = Difference;
+ *(uint64 *)OriginalData = *(uint64 *)NewData;
+ } break;
+ case action_change_ptr:
+ {
+ ptrsize OriginalValue = *(ptrsize *)OriginalData;
+ ptrsize NewValue = *(ptrsize *)NewData;
+ ptrsize Difference = NewValue - OriginalValue;
+ void *Data = AllocateMemory(Memory, sizeof(ptrsize), P_UndoBuffer);
+ *(ptrsize *)Data = Difference;
+ *(ptrsize *)OriginalData = *(ptrsize *)NewData;
+ } break;
+ case action_change_string:
+ {
+ void *Data = AllocateMemory(Memory, STRING_SIZE, P_UndoBuffer);
+ CopyStrings(Data, OriginalData);
+ Data = AllocateMemory(Memory, STRING_SIZE, P_UndoBuffer);
+ CopyStrings(Data, NewData);
+ CopyStrings(OriginalData, NewData);
+ } break;
+ }
+ Data = AllocateMemory(Memory, sizeof(action_change_type), P_UndoBuffer);
+ *(action_change_type *)Data = ActionChange;
+}
+
+// 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_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;
+ switch (*ActionType)
+ {
+ case action_change_u16:
+ {
+ uint16 *Difference = (uint16 *)ActionType - 1;
+ TableAddress = (uint8 *)Difference - sizeof(ptrsize) - sizeof(action_change_type);
+ void *Address = (void *)*(ptrsize *)TableAddress;
+ *(uint16 *)Address -= *Difference;
+ } break;
+ case action_change_ptr:
+ {
+ ptrsize *Difference = (ptrsize *)ActionType - 1;
+ TableAddress = (uint8 *)Difference - sizeof(ptrsize) - sizeof(action_change_type);
+ void *Address = (void *)*(ptrsize *)TableAddress;
+ *(ptrsize *)Address -= *Difference;
+ } break;
+ }
+ Table->CurrentPosition = (TableAddress - (uint8 *)Table->Address);
+}
+
+// The pointer is rewinded.
+void Action_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;
+ switch (*ActionType)
+ {
+ case action_change_u16:
+ {
+ uint16 *Difference = (uint16 *)(ActionType + 1);
+ TableAddress = (uint8 *)Difference + sizeof(uint16) + sizeof(action_change_type);
+ *(uint16 *)Address += *Difference;
+ } break;
+ case action_change_ptr:
+ {
+ ptrsize *Difference = (ptrsize *)(ActionType + 1);
+ TableAddress = (uint8 *)Difference + sizeof(ptrsize) + sizeof(action_change_type);
+ *(ptrsize *)Address += *Difference;
+ } break;
+ }
+ Table->CurrentPosition = (TableAddress - (uint8 *)Table->Address);
+}