summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFox Caminiti <fox@foxcam.net>2022-10-06 14:30:48 -0400
committerFox Caminiti <fox@foxcam.net>2022-10-06 14:30:48 -0400
commit0b0aa3b06fac0bcdeb31d5e2211d1ba149531692 (patch)
tree91f0d9689151b7fb985de50b2c8b12ccd7a65440
parenta4c1e537b0cb2540535357d880e46f63b38c134f (diff)
GL renderer preparation
-rw-r--r--createcalls.cpp141
-rw-r--r--debug.h3
-rw-r--r--ffmpeg_backend.cpp3
-rw-r--r--functions.h5
-rw-r--r--gl_calls.cpp5
-rw-r--r--main.cpp166
-rw-r--r--main.h117
-rw-r--r--memory.cpp33
-rw-r--r--memory.h2
-rw-r--r--my_imgui_widgets.cpp28
-rw-r--r--strings.cpp6
-rw-r--r--threading.cpp12
-rw-r--r--undo.cpp745
13 files changed, 536 insertions, 730 deletions
diff --git a/createcalls.cpp b/createcalls.cpp
index 3bd13f8..2c2df61 100644
--- a/createcalls.cpp
+++ b/createcalls.cpp
@@ -1,29 +1,92 @@
+static void
+PostMsg(project_state *State, char *msg)
+{
+ State->MsgTime = 120;
+ State->Msg = msg;
+}
-static bool32
+static uint16
Source_Generate(project_data *File, project_state *State, memory *Memory, void *TempString)
{
Assert(File->Source_Count < MAX_SOURCES);
bool32 IsVideo = 0;
- if (AV_IsFileSupported((char *)Path, &IsVideo)) {
- block_source *Source =
- uint16 = String_AddToFile(Memory, (char *)TempString);
+ if (AV_IsFileSupported((char *)TempString, &IsVideo)) {
+ uint16 Index = Memory_Block_AllocateNew(Memory, F_Strings);
+ block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Index);
+ History_Entry_Commit(Memory, "Add source");
+ History_Action_Block_Swap(Memory, F_Sources, Source);
+
+ Source->Occupied = 1;
+ Source->Block_String_Index = String_AddToFile(Memory, (char *)TempString);
if (IsVideo)
Source->SourceType = source_type_video;
else
Source->SourceType = source_type_image;
- 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;
- History_Action_Change(Memory, &File->NumberOfSources, &File->NumberOfSources, &i, action_type_change_u16);
+
+ History_Action_Swap(Memory, F_File, sizeof(File->Source_Count), &File->Source_Count);
+ File->Source_Count++;
History_Entry_End(Memory);
- return 1;
+ return Index;
} else {
- void *Address = Memory_Rewind(Memory, STRING_SIZE, F_Strings);
PostMsg(State, "File not supported...");
}
- return 0;
+ return -1;
+}
+
+static property_channel
+Property_InitFloat(char *Name, real32 Val, real32 ScrubVal, real32 MinVal = PROPERTY_REAL_MIN, real32 MaxVal = PROPERTY_REAL_MAX) { property_channel Property = {};
+ Property.Name = Name;
+ Property.CurrentValue = Val;
+ Property.MinVal = MinVal;
+ Property.MaxVal = MaxVal;
+ Property.ScrubVal = ScrubVal;
+ return Property;
+}
+
+
+block_layer * Layer_Init(project_data *File, memory *Memory)
+{
+ block_layer *Layer = (block_layer *)Memory_Block_AllocateAddress(Memory, F_Layers);
+ History_Action_Block_Swap(Memory, F_Layers, Layer);
+
+ *Layer = {};
+ Layer->Occupied = 1;
+
+ Layer->Block_String_Index = Memory_Block_AllocateNew(Memory, F_Strings);
+ block_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, Layer->Block_String_Index);
+ sprintf(String->Char, "Layer %i", File->Layer_Count + 1); // CSbros...
+
+ Layer->x = Property_InitFloat("X Position", 0.0f, 1.0f);
+ Layer->y = Property_InitFloat("Y Position", 0.0f, 1.0f);
+ Layer->ax = Property_InitFloat("Anchor X", 0.5f, 0.005f);
+ Layer->ay = Property_InitFloat("Anchor Y", 0.5f, 0.005f);
+ Layer->scale = Property_InitFloat("Scale", 1.0f, 0.005f);
+ Layer->rotation = Property_InitFloat("Rotation", 0.0f, 1.0f);
+ Layer->opacity = Property_InitFloat("Opacity", 1.0f, 0.005f, 0.0f, 1.0f);
+ Layer->time = Property_InitFloat("Frame Number", 0.0f, 1.0f, 0, 100000);
+
+ History_Action_Swap(Memory, F_File, sizeof(File->Layer_Count), &File->Layer_Count);
+ File->Layer_Count++;
+
+ return Layer;
+}
+
+
+static void
+Layer_CreateFromSource(project_data *File, project_state *State, memory *Memory, uint16 SourceIndex, int32 Frame_End)
+{
+ if (File->Layer_Count + 1 > MAX_LAYERS) {
+ Assert(0);
+ }
+ History_Entry_Commit(Memory,"Add layer from source");
+ block_layer *Layer = Layer_Init(File, Memory);
+ Layer->Block_Source_Index = SourceIndex;
+ Layer->Frame_End = Frame_End;
+ History_Entry_End(Memory);
+
+ State->UpdateFrame = true;
}
#if 0
@@ -37,25 +100,6 @@ IncrementFrame(project_data *File, int16 Amount) {
}
static void
-PostMsg(project_state *State, char *msg)
-{
- State->MsgTime = 120;
- State->Msg = msg;
-}
-
-static property_channel
-InitFloatProperty(char *Name, real32 Val, real32 ScrubVal, real32 MinVal = PROPERTY_REAL_MIN, real32 MaxVal = PROPERTY_REAL_MAX) {
- property_channel Property = {};
- Property.Name = Name;
- Property.CurrentValue.f = Val;
- Property.MinVal.f = MinVal;
- Property.MaxVal.f = MaxVal;
- Property.ScrubVal.f = ScrubVal;
- Property.VarType = type_real;
- return Property;
-}
-
-static void
CreateKeyframeBlock(property_channel *Property, memory *Memory)
{
int16 a = Property->NumberOfKeyframeBlocks++;
@@ -72,43 +116,6 @@ void * Layer_AllocateBitmap(memory *Memory, uint16 Width, uint16 Height, uint16
return Address;
}
-project_layer * Layer_Init(project_data *File, memory *Memory)
-{
- int16 Index = File->NumberOfLayers;
- int16 NextIndex = File->NumberOfLayers + 1;
-
- // NOTE(fox): We don't have to record any values that get set here aside
- // 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.
- 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];
- *Layer = {};
- Layer->BitmapInfo.CurrentFrame = -1;
-
- History_Entry_SetPointer(Memory, &Layer->BitmapInfo.AVInfo);
-
- History_Entry_End(Memory);
-
- Layer->Name = (char *)AllocateMemory(Memory, STRING_SIZE, F_Strings);
- sprintf(Layer->Name, "Layer %i", NextIndex); // CSbros...
- Layer->x = InitFloatProperty("X Position", 0.0f, 1.0f);
- Layer->y = InitFloatProperty("Y Position", 0.0f, 1.0f);
- Layer->ax = InitFloatProperty("Anchor X", 0.5f, 0.005f);
- Layer->ay = InitFloatProperty("Anchor Y", 0.5f, 0.005f);
- Layer->scale = InitFloatProperty("Scale", 1.0f, 0.005f);
- Layer->rotation = InitFloatProperty("Rotation", 0.0f, 1.0f);
- Layer->opacity = InitFloatProperty("Opacity", 1.0f, 0.005f, 0.0f, 1.0f);
- Layer->time = InitFloatProperty("Frame Number", 0.0f, 1.0f, 0, 100000);
- Layer->EndFrame = File->NumberOfFrames;
-
- return Layer;
-}
-
static cached_bitmap *
Cache_CheckBitmap(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, int32 TimelineFrame)
{
diff --git a/debug.h b/debug.h
index 2514717..cac3d39 100644
--- a/debug.h
+++ b/debug.h
@@ -33,6 +33,9 @@ struct project_debug
uint64 PixelCountChecked;
// NOTE(fox): Pixel count isn't thread safe; don't use with multithreading!
uint64 LayerCycleCount[64];
+ uint32 UndoState = 0;
+ uint64 ScratchSize[6];
+ uint32 ScratchState = 0;
};
static project_debug Debug;
diff --git a/ffmpeg_backend.cpp b/ffmpeg_backend.cpp
index 34abf35..b986d7a 100644
--- a/ffmpeg_backend.cpp
+++ b/ffmpeg_backend.cpp
@@ -125,7 +125,8 @@ void AV_Init(block_source *Source, av_info *AV, memory *Memory)
// The two calls below theoretically shouldn't fail since we already tested them in IsFileSupported.
AV->FileFormatContext = avformat_alloc_context();
- err = avformat_open_input(&AV->FileFormatContext, Source->Path, NULL, NULL);;
+ char *Path = (char *)Memory_Block_AddressAtIndex(Memory, F_Strings, Source->Block_String_Index);
+ err = avformat_open_input(&AV->FileFormatContext, Path, NULL, NULL);;
if (err < 0) {
fprintf(stderr, "Libav error: (%s)\n", av_err2str(err));
Assert(0);
diff --git a/functions.h b/functions.h
index 1e044d1..88278fe 100644
--- a/functions.h
+++ b/functions.h
@@ -1,3 +1,6 @@
+static bool32 AV_IsFileSupported(char *filename, bool32 *IsVideo);
+
+# if 0
// Buffer management
@@ -16,7 +19,6 @@ static bool32 Source_Generate(project_data *File, project_state *State, memory *
// Libav (ffmpeg) backend for decoding video
-static bool32 AV_IsFileSupported(char *filename, bool32 *IsVideo);
static void AV_Init(char *filename, source *Source, memory *Memory); // Initializes all internal structs and calculates average PTS.
static cached_bitmap * AV_LoadVideoFrame(source *Source, memory *Memory, int32 TimelineFrame); // Loads video frame at TimelineFrame.
@@ -68,4 +70,5 @@ static bool32 CheckQueue(render_queue RenderInfo, uint16 Index);
static void Effect_DrawColor(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]);
static void Effect_Levels(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]);
static void Effect_GaussianBlur(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]);
+#endif
diff --git a/gl_calls.cpp b/gl_calls.cpp
index ba63fda..b08615a 100644
--- a/gl_calls.cpp
+++ b/gl_calls.cpp
@@ -78,8 +78,7 @@ const char *FragmentShaderEffectSource[] = {"",
};
-
-#include "effects_gl.cpp"
+// #include "effects_gl.cpp"
static void GL_InitDefaultShader() {
DefaultVertexShader = glCreateShader(GL_VERTEX_SHADER);
@@ -155,6 +154,7 @@ static void GL_InitDefaultVerts() {
glEnableVertexAttribArray(1);
}
+#if 0
void
GL_InitTexture(gl_effect_layer *Test)
{
@@ -378,3 +378,4 @@ Effect_GL_InitShader(int EffectIndex)
return *ShaderProgram;
}
+#endif
diff --git a/main.cpp b/main.cpp
index 9db6588..d0349fa 100644
--- a/main.cpp
+++ b/main.cpp
@@ -41,38 +41,40 @@
#include "main.h"
#include "debug.h"
-// #include "functions.h"
+#include "functions.h"
// #include "sharebuffer.h"
-SDL_atomic_t CurrentEntry;
-SDL_atomic_t QueuedEntries;
-SDL_atomic_t CompletedEntries;
+SDL_atomic_t Render_Interrupt;
+// SDL_atomic_t CurrentEntry;
+// 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];
-SDL_Thread *thread[8];
+// SDL_Thread *thread[8];
+SDL_Thread *MainRenderThread;
SDL_sem *Semaphore;
#include "memory.cpp"
+#include "undo.cpp"
#include "strings.cpp"
+#if THREADED
+#include "threading.cpp"
+#endif
#include "createcalls.cpp"
#include "ffmpeg_backend.cpp"
+#include "my_imgui_widgets.cpp"
+#include "gl_calls.cpp"
#if 0
#include "effects.cpp"
#include "keyframes.cpp"
#include "layer.cpp"
#include "bezier.cpp"
-#if THREADED
-#include "threading.cpp"
-#endif
#include "prenderer.cpp"
#include "bitmap_calls.cpp"
-#include "my_imgui_widgets.cpp"
-#include "gl_calls.cpp"
-#include "undo.cpp"
#endif
@@ -129,16 +131,17 @@ int main(int argc, char *argv[]) {
Memory_InitTable(&GlobalMemory, &Memory, 1 * 1024 * 1024, P_AVInfo, "Image/video headers");
Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, P_UndoBuffer, "Undo buffer");
- Memory_InitTable(&GlobalMemory, &Memory, 1 * 1024 * 1024, P_MiscCache, "Misc persistent");
+ Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, P_MiscCache, "Misc persistent");
Memory_InitTable(&GlobalMemory, &Memory, sizeof(project_data), F_File, "File", sizeof(project_data));
Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Precomps, "Precomps", sizeof(block_composition));
- // Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Layers, "Layers");
- Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Sources, "Sources", sizeof(block_source));
+ Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Layers, "Layers", sizeof(block_layer));
+ Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Sources, "Sources", sizeof(block_source));
// Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Effects, "Effects");
// Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Keyframes, "Keyframe blocks");
- Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Strings, "Strings");
+ Memory_InitTable(&GlobalMemory, &Memory, 10 * 1024 * 1024, F_Strings, "Strings", sizeof(block_string));
+ Memory_InitTable(&GlobalMemory, &Memory, (uint64)64 * 1024 * 1024, B_ScratchSpace, "Scratch");
// Memory_InitTable(&GlobalMemory, &Memory, (uint64)200 * 1024 * 1024, B_CachedBitmaps, "Cached bitmap buffer");
#if ARM
@@ -153,7 +156,10 @@ int main(int argc, char *argv[]) {
#endif
project_state *State = (project_state *)Memory.Slot[P_MiscCache].Address;
+ *State = {};
project_data *File = (project_data *)Memory_Block_AllocateAddress(&Memory, F_File);
+ *File = {};
+ File->Occupied = 1;
block_composition *MainComp = (block_composition *)Memory_Block_AllocateAddress(&Memory, F_Precomps);
MainComp->Width = 1280;
@@ -164,68 +170,22 @@ int main(int argc, char *argv[]) {
MainComp->Frame_Count = 48;
MainComp->Frame_End = 48;
- Source_Generate(File, State, Memory, "../asset/a.jpg");
-
-#if 0
-
-#if DEBUG
-
- LoadTestFootage(&File, &State, &Memory);
-
- // GDB and LLDB say this plain struct that's literally under 30 bytes is
- // incomplete in the layers unless I do this...
- layer_bitmap_info BitmapInfo;
- BitmapInfo.ToUpdate = 0;
- BitmapInfo.FrameOffset = 2;
- av_info BS = {};
- BS.PreviousPTS = 0;
- effect as = {};
-#endif
-
- uint16 BytesPerPixel = 4;
- comp_buffer CompBuffer = {};
- CompBuffer.Width = File.Width;
- CompBuffer.Height = File.Height;
- CompBuffer.BytesPerPixel = BytesPerPixel;
- CompBuffer.PackedBuffer = Layer_AllocateBitmap(&Memory, CompBuffer.Width, CompBuffer.Height, CompBuffer.BytesPerPixel);
- CompBuffer.UnpackedBuffer = Layer_AllocateBitmap(&Memory, CompBuffer.Width, CompBuffer.Height, CompBuffer.BytesPerPixel);
-
- ui UI = {};
-
- UI.Y_TimelinePercentZoomed = UI.Default_Y_TimelinePercentZoomed;
- UI.Y_TimelinePercentOffset = UI.Default_Y_TimelinePercentOffset;
-
- // shm_unlink("/testl");
- // int fd = shm_open("/testl", O_CREAT | O_EXCL | O_RDWR,
- // S_IRUSR | S_IWUSR);
- // if (fd == -1)
- // errExit("shm_open");
-
- // if (ftruncate(fd, SHAREDMEMORY_SIZE) == -1)
- // Assert(0);
+ {
+ uint16 SourceIndex = Source_Generate(File, State, &Memory, (void *)"../asset/a.jpg");
+ block_source *Source = (block_source *)Memory_Block_AddressAtIndex(&Memory, F_Sources, 0);
- // void *asda = mmap(NULL, SHAREDMEMORY_SIZE,
- // PROT_READ | PROT_WRITE,
- // MAP_SHARED, fd, 0);
- // SharedMemoryInfo *shmp = (SharedMemoryInfo *)asda;
+ Layer_CreateFromSource(File, State, &Memory, SourceIndex, MainComp->Frame_End);
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(&Memory, F_Layers, 0);
- // if (shmp == MAP_FAILED)
- // Assert(0);
+ History_Undo(&Memory);
+ History_Redo(&Memory);
+ }
- // if (sem_init(&shmp->sem1, 1, 0) == -1)
- // Assert(0);
- // if (sem_init(&shmp->sem2, 1, 0) == -1)
- // Assert(0);
+ State->Render.MainCompBuffer = (void *)((uint8 *)Memory.Slot[P_MiscCache].Address + sizeof(project_state));
SDL_Init(SDL_INIT_VIDEO);
- Semaphore = SDL_CreateSemaphore(0);
-
- render_queue RenderInfo = {};
- RenderInfo.File = &File;
- RenderInfo.State = &State;
- RenderInfo.CompBuffer = &CompBuffer;
-
+#if 0
#if THREADED
thread_info ThreadInfo[7];
@@ -236,8 +196,7 @@ int main(int argc, char *argv[]) {
thread[i] = SDL_CreateThread(TestThread, str, &ThreadInfo[i]);
}
#endif
- sdl_input Input;
- sdl_input OldInput;
+#endif
// Decide GL+GLSL versions
#if defined(IMGUI_IMPL_OPENGL_ES2)
@@ -322,22 +281,24 @@ int main(int argc, char *argv[]) {
ImGui_ImplSDL2_InitForOpenGL(window, gl_context);
ImGui_ImplOpenGL3_Init(glsl_version);
+ int64 i = 0;
+ while (i < MainComp->Width*MainComp->Height) {
+ *((uint32 *)State->Render.MainCompBuffer + i++) = 0xFF2F0000;
+ }
+
GLuint textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // This is required on WebGL for non power-of-two textures
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Same
-#if defined(GL_UNPACK_ROW_LENGTH) && !defined(__EMSCRIPTEN__)
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-#endif
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, CompBuffer.Width, CompBuffer.Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, CompBuffer.PackedBuffer);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, MainComp->Width, MainComp->Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, State->Render.MainCompBuffer);
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+ // Semaphore = SDL_CreateSemaphore(0);
+ // MainRenderThread = SDL_CreateThread(MainRenderer, "Main render thread", &State->Render);
- while (State.IsRunning)
+ while (State->IsRunning)
{
SDL_Event event;
while (SDL_PollEvent(&event))
@@ -345,19 +306,19 @@ int main(int argc, char *argv[]) {
ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_DROPFILE) {
char *DropFile = event.drop.file;
- Source_Generate(&File, &State, &Memory, DropFile);
+ Source_Generate(File, State, &Memory, DropFile);
SDL_free(DropFile);
}
if (event.type == SDL_QUIT)
- State.IsRunning = false;
+ State->IsRunning = false;
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
- State.IsRunning = false;
+ State->IsRunning = false;
}
- if (UI.WantSetPos) {
- ImGui::GetIO().WantSetMousePos = true;
- io.MousePos = UI.SetPos;
- }
+ // if (UI.WantSetPos) {
+ // ImGui::GetIO().WantSetMousePos = true;
+ // io.MousePos = UI.SetPos;
+ // }
ImGui_ImplOpenGL3_NewFrame();
@@ -365,17 +326,18 @@ int main(int argc, char *argv[]) {
ImGui::NewFrame();
- if (UI.WantSetPos) {
- ImGui_WrapMouseFinish(&UI, io.MousePos);
- io.MouseDelta = {};
- UI.WantSetPos = false;
- }
+ // if (UI.WantSetPos) {
+ // ImGui_WrapMouseFinish(&UI, io.MousePos);
+ // io.MouseDelta = {};
+ // UI.WantSetPos = false;
+ // }
+
+ ImGui::DockSpaceOverViewport();
+#if 0
if (!io.WantCaptureKeyboard)
ImGui_ProcessInputs(&File, &State, &CompBuffer, &Memory, &UI, io);
- ImGui::DockSpaceOverViewport();
-
ImGui_Viewport(File, &State, &UI, &Memory, CompBuffer, io, textureID);
ImGui_File(&File, &State, &Memory, &UI, io);
@@ -386,7 +348,12 @@ int main(int argc, char *argv[]) {
ImGui_Timeline(&File, &State, &Memory, &UI, io);
// ImGui_Graph(&File, &State, &Memory, &UI, io);
+#endif
+ ImGui_Viewport(MainComp, textureID);
+ ImGui::ShowDemoWindow();
+
+#if 0
#if DEBUG
ImGui_DebugUndoTree(&File, &Memory);
if (Debug.ToggleWindow) {
@@ -410,7 +377,9 @@ int main(int argc, char *argv[]) {
// Right now IsRendering does nothing. I have it here if we want to
// completely detatch the rendering updater onto its own thread so the
// UI never lags.
+#endif
+#if 0
if (State.UpdateFrame && !IsRendering) {
MainFunction(0, &Memory, &State, &File, &CompBuffer);
State.UpdateFrame = 0;
@@ -433,6 +402,7 @@ int main(int argc, char *argv[]) {
FinishRenderAndUpload(&State, &CompBuffer, textureID);
}
#endif
+#endif
ImGui::Render();
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
@@ -441,15 +411,15 @@ int main(int argc, char *argv[]) {
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
SDL_GL_SwapWindow(window);
}
- for (int i = 0; i < 7; i++) {
- SDL_DetachThread(thread[i]);
- }
+
+ // for (int i = 0; i < 7; i++) {
+ // SDL_DetachThread(thread[i]);
+ // }
// shm_unlink("/testl");
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
SDL_Quit();
-#endif
return 0;
}
diff --git a/main.h b/main.h
index 1c9a69b..8e29917 100644
--- a/main.h
+++ b/main.h
@@ -39,6 +39,10 @@ enum blend_mode
blend_difference
};
+struct block_string {
+ uint8 Occupied;
+ char Char[1024 - sizeof(uint8)];
+};
enum interpolation_type
{
@@ -59,12 +63,19 @@ struct block_bezier {
bezier_point Point[MAX_KEYFRAMES_PER_BLOCK];
};
+struct render_state
+{
+ void *MainCompBuffer;
+};
+
struct project_state
{
bool32 UpdateKeyframes = 1;
bool32 UpdateFrame = 1; // only refreshes frame; set UpdateKeyframes to update animation
bool32 DebugDisableCache = 1;
+ render_state Render;
+
// tool Tool = tool_default;
// pen_state Pen = {};
@@ -152,6 +163,58 @@ struct property_channel {
bool32 IsToggled;
};
+struct layer_bitmap_state {
+ // Image and video
+ bool32 ToUpdate = 1;
+
+ // GL state
+ // gl_effect_layer Test;
+ // gl_effect_layer TestM;
+
+ // Video state
+ int32 CurrentFrame = -1; // The last frame number rendered to the bitmap. -1 gurantees a load upon layer creation.
+ void *AVInfo; // Internal data containing current frame info
+};
+
+struct block_layer {
+ uint8 Occupied;
+
+ uint16 Block_String_Index;
+ uint16 Block_Source_Index;
+ uint16 Block_Composition_Index;
+
+ uint16 Block_Mask_Index[MAX_EFFECTS];
+ uint16 Block_Mask_Count;
+
+ uint16 Block_Effect_Index[MAX_MASKS];
+ uint16 Block_Effect_Count;
+
+ blend_mode BlendMode;
+
+ union
+ {
+ property_channel Property[8];
+ struct
+ {
+ property_channel x;
+ property_channel y;
+ property_channel ax;
+ property_channel ay;
+ property_channel rotation;
+ property_channel scale;
+ property_channel opacity;
+ property_channel time;
+ };
+ };
+
+ bool32 IsSelected;
+
+ int32 Frame_Offset;
+ int32 Frame_Start;
+ int32 Frame_End;
+
+ uint32 LayerColor;
+};
#if 0
@@ -170,20 +233,6 @@ struct gl_effect_layer {
uint32 Stencil_Renderbuffer;
};
-struct layer_bitmap_info {
- // Image and video
- void *BitmapBuffer; // Each layer has a persistent bitmap that the source data gets packed into.
- 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;
-
- // Video only
- int32 CurrentFrame = -1; // The last frame number rendered to the bitmap. -1 gurantees a load upon layer creation.
- void *AVInfo; // Internal data containing current frame info
-};
-
// Bitmaps from files are loaded into these temporary cache blocks.
@@ -234,46 +283,6 @@ struct mask {
uint32 NumberOfVerts;
};
-struct project_layer {
- char *Name;
- blend_mode BlendMode;
-
- union
- {
- property_channel Property[8];
- struct
- {
- property_channel x;
- property_channel y;
- property_channel ax;
- property_channel ay;
- property_channel rotation;
- property_channel scale;
- property_channel opacity;
- property_channel time;
- };
- };
-
- bool32 IsSelected;
-
- source *Source;
- layer_bitmap_info BitmapInfo;
-
- effect *Effect[MAX_EFFECTS];
- uint16 NumberOfEffects;
-
- mask Mask[MAX_MASKS];
- uint16 NumberOfMasks;
-
- int32 StartFrame;
- int32 EndFrame;
-
- uint32 LayerColor;
-
- // For rendering
- transform_info TransformInfo;
-};
-
struct main_sdl
{
diff --git a/memory.cpp b/memory.cpp
index 27ac266..f502eb2 100644
--- a/memory.cpp
+++ b/memory.cpp
@@ -30,7 +30,6 @@ Memory_Block_AllocateNew(memory *Memory, memory_table_list TableName)
Index++;
}
Memory_Zero(Address_Playhead, Table->Block_ElementSize);
- *Address_Playhead = 1;
return Index;
}
@@ -41,7 +40,6 @@ Memory_Block_AddressAtIndex(memory *Memory, memory_table_list TableName, uint32
memory_table *Table = &Memory->Slot[TableName];
Assert(Table->Block_ElementSize != 0);
uint8 *Address = (uint8 *)Table->Address + (Table->Block_ElementSize * Index);
- Assert(*Address == 1);
return (void *)Address;
}
@@ -49,7 +47,36 @@ static void *
Memory_Block_AllocateAddress(memory *Memory, memory_table_list TableName)
{
uint16 FileIndex = Memory_Block_AllocateNew(Memory, TableName);
- return Memory_Block_AddressAtIndex(Memory, F_File, FileIndex);
+ return Memory_Block_AddressAtIndex(Memory, TableName, FileIndex);
+}
+
+static void *
+Memory_PushScratch(memory *Memory, uint64 Size) {
+ memory_table *Table = &Memory->Slot[B_ScratchSpace];
+ uint8 *Address = ((uint8 *)Table->Address + Memory->ScratchPos);
+ Memory->ScratchPos += Size;
+#if DEBUG
+ Debug.ScratchSize[Debug.ScratchState] = Size;
+ Debug.ScratchState++;
+#endif
+ return (void *)Address;
+}
+
+static void
+Memory_PopScratch(memory *Memory, uint64 Size) {
+ memory_table *Table = &Memory->Slot[B_ScratchSpace];
+ Memory->ScratchPos -= Size;
+#if DEBUG
+ Debug.ScratchState--;
+ Assert(Debug.ScratchSize[Debug.ScratchState] == Size);
+#endif
+}
+
+static void *
+Memory_AddressAtOffset(memory *Memory, memory_table_list TableName, uint64 Offset)
+{
+ memory_table *Table = &Memory->Slot[TableName];
+ return (void *)((uint8 *)Table->Address + Offset);
}
#if 0
diff --git a/memory.h b/memory.h
index 47c737e..51b207a 100644
--- a/memory.h
+++ b/memory.h
@@ -14,6 +14,7 @@ enum memory_table_list {
F_Nodes,
F_Strings,
+ B_ScratchSpace,
B_CachedBitmaps,
};
@@ -59,6 +60,7 @@ struct history_entry_list {
struct memory {
memory_table Slot[16];
history_entry_list History;
+ uint64 ScratchPos;
bool32 IsFileSaved;
};
diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp
index a688283..e8159fe 100644
--- a/my_imgui_widgets.cpp
+++ b/my_imgui_widgets.cpp
@@ -2,6 +2,33 @@
#include "my_imgui_internal_widgets.h"
#include "imgui_ops.h"
+static void
+ImGui_Viewport(block_composition *MainComp, GLuint textureID)
+{
+ bool open = true;
+ ImGui::Begin("Viewport", &open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
+
+ ImVec2 ViewportMin = ImGui::GetCursorScreenPos();
+ ImVec2 ViewportScale = ImGui::GetContentRegionAvail();
+ ImVec2 ViewportMax = ImVec2(ViewportMin.x + ViewportScale.x, ViewportMin.y + ViewportScale.y);
+
+ ImDrawList* draw_list = ImGui::GetWindowDrawList();
+ draw_list->AddRectFilled(ViewportMin, ViewportMax, IM_COL32(50, 50, 50, 255));
+ draw_list->AddRect(ViewportMin, ViewportMax, IM_COL32(255, 255, 255, 255));
+
+ ImVec2 CompZoom(MainComp->Width, MainComp->Height);
+ ImVec2 CompPos = ViewportMin + (ViewportMax - ViewportMin)*0.5 - CompZoom*0.5;
+
+ // Actual composition texture
+ draw_list->PushClipRect(ViewportMin, ViewportMax, true);
+ draw_list->AddImage((void *)(intptr_t)textureID, ImVec2(CompPos.x, CompPos.y),
+ ImVec2(CompPos.x + CompZoom.x, CompPos.y + CompZoom.y));
+ draw_list->PopClipRect();
+
+ ImGui::End();
+}
+
+#if 0
// 0 for timeline keyframe, 1 for graph keyframe, 2 for left graph handle, 3 for right graph handle
static void
ImGui_KeyframeDragging(project_data *File, project_state *State, ui *UI, property_channel *Property, int32 b, ImGuiIO io, int16 Type)
@@ -2595,3 +2622,4 @@ static char ImGuiPrefs[] = "[Window][DockSpaceViewport_11111111]"
}
#endif
+#endif
diff --git a/strings.cpp b/strings.cpp
index b8560d1..ab410b2 100644
--- a/strings.cpp
+++ b/strings.cpp
@@ -27,10 +27,12 @@ static uint16
String_AddToFile(memory *Memory, char *Char)
{
uint16 FileIndex = Memory_Block_AllocateNew(Memory, F_Strings);
- void *Address = Memory_Block_AddressAtIndex(Memory, F_Strings, FileIndex);
+ block_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, FileIndex);
+ History_Action_Block_Swap(Memory, F_Strings, String);
+ String->Occupied = 1;
uint16 i = 0;
while (Char[i] != '\0') {
- *((char *)Address + i) = Char[i];
+ String->Char[i] = Char[i];
i++;
}
return FileIndex;
diff --git a/threading.cpp b/threading.cpp
index c1cfe5c..ff891a6 100644
--- a/threading.cpp
+++ b/threading.cpp
@@ -1,3 +1,14 @@
+
+static int
+MainRenderer(void *ptr)
+{
+ for(;;)
+ {
+ SDL_SemWait(Semaphore);
+ }
+}
+
+#if 0
static void
PushRect(rectangle RenderRegion)
{
@@ -44,3 +55,4 @@ TestThread(void *ptr)
}
}
}
+#endif
diff --git a/undo.cpp b/undo.cpp
index bb49772..a86e214 100644
--- a/undo.cpp
+++ b/undo.cpp
@@ -1,554 +1,295 @@
-// get ready for some MLG...
-
-// The undo system currently works in two layers: a lower-level structless
-// stack that records "actions" and a higher-level array of "entries" that
-// bundle actions together. An action can either record a single change to a
-// specific memory address or a shift of pointers. Entries are what the user
-// sees and can contain multiple actions (i.e. adding a source changes the
-// value of the string and the increment of how many sources there are).
-// Entries are allowed to call functions in case there's something that can't
-// be incorporated into this memory model (i.e. deallocating libav contexts
-// when a layer's creation is undone), though they should be used only
-// when necessary.
-
-// 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 History_Action_Change(memory *Memory, void *DataAddress, void *OriginalData, void *NewData, action_type ActionChange)
+void Arbitrary_WriteInto(uint8 *Address_Read, uint8 *Address_Write, uint64 Size)
{
- Memory->Action.Entry[Memory->Action.Index].NumberOfActions++;
- 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;
- switch (ActionChange)
- {
- case action_type_change_u16:
- {
- uint16 OriginalValue = *(uint16 *)OriginalData;
- uint16 NewValue = *(uint16 *)NewData;
- uint16 Difference = NewValue - OriginalValue;
- void *Data = Memory_Advance(Memory, sizeof(uint16), P_UndoBuffer);
- *(uint16 *)Data = Difference;
- *(uint16 *)DataAddress = *(uint16 *)NewData;
- } break;
- case action_type_change_i16:
- {
- int16 OriginalValue = *(int16 *)OriginalData;
- int16 NewValue = *(int16 *)NewData;
- int16 Difference = NewValue - OriginalValue;
- void *Data = Memory_Advance(Memory, sizeof(int16), P_UndoBuffer);
- *(int16 *)Data = Difference;
- *(int16 *)DataAddress = *(int16 *)NewData;
- } break;
- case action_type_change_u32:
- {
- uint32 OriginalValue = *(uint32 *)OriginalData;
- uint32 NewValue = *(uint32 *)NewData;
- uint32 Difference = NewValue - OriginalValue;
- void *Data = Memory_Advance(Memory, sizeof(uint32), P_UndoBuffer);
- *(uint32 *)Data = Difference;
- *(uint32 *)DataAddress = *(uint32 *)NewData;
- } break;
- case action_type_change_i32:
- {
- int32 OriginalValue = *(int32 *)OriginalData;
- int32 NewValue = *(int32 *)NewData;
- int32 Difference = NewValue - OriginalValue;
- void *Data = Memory_Advance(Memory, sizeof(int32), P_UndoBuffer);
- *(int32 *)Data = Difference;
- *(int32 *)DataAddress = *(int32 *)NewData;
- } break;
- case action_type_change_r32:
- {
- real32 OriginalValue = *(real32 *)OriginalData;
- real32 NewValue = *(real32 *)NewData;
- real32 Difference = NewValue - OriginalValue;
- void *Data = Memory_Advance(Memory, sizeof(real32), P_UndoBuffer);
- *(real32 *)Data = Difference;
- *(real32 *)DataAddress = *(real32 *)NewData;
- } break;
- case action_type_change_u64:
- {
- uint64 OriginalValue = *(uint64 *)OriginalData;
- uint64 NewValue = *(uint64 *)NewData;
- uint64 Difference = NewValue - OriginalValue;
- void *Data = Memory_Advance(Memory, sizeof(uint64), P_UndoBuffer);
- *(uint64 *)Data = Difference;
- *(uint64 *)DataAddress = *(uint64 *)NewData;
- } break;
- case action_type_change_ptr:
- {
- ptrsize OriginalValue = *(ptrsize *)OriginalData;
- ptrsize NewValue = *(ptrsize *)NewData;
- ptrsize Difference = NewValue - OriginalValue;
- void *Data = Memory_Advance(Memory, sizeof(ptrsize), P_UndoBuffer);
- *(ptrsize *)Data = Difference;
- *(ptrsize *)DataAddress = *(ptrsize *)NewData;
- } break;
- case action_type_change_string:
- {
- void *Data = Memory_Advance(Memory, STRING_SIZE, P_UndoBuffer);
- CopyStrings(Data, OriginalData);
- Data = Memory_Advance(Memory, STRING_SIZE, P_UndoBuffer);
- CopyStrings(Data, NewData);
- CopyStrings(DataAddress, NewData);
- } break;
- default:
- {
- Assert(0);
- }
-
+ uint64 i = 0;
+ while (i < Size) {
+ *(Address_Write + i) = *(Address_Read + i);
+ i++;
}
- Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
- *(action_type *)Data = ActionChange;
}
-// Helper functions for common types of data changes.
-void History_Action_Change_SwapBool(memory *Memory, bool32 *Bool)
+void Arbitrary_Zero(uint8 *Address_Write, uint64 Size)
{
- bool32 OppositeBool = *Bool ^ 1;
- History_Action_Change(Memory, Bool, Bool, &OppositeBool, action_type_change_i32);
+ uint64 i = 0;
+ while (i < Size) {
+ *(Address_Write + i) = 0;
+ i++;
+ }
}
-void History_Action_Change_V2(memory *Memory, v2 *DataAddress, v2 *OriginalData, v2 *NewData)
+void Arbitrary_SwapData(memory *Memory, uint8 *Address_0, uint8 *Address_1, uint64 Size)
{
- 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);
+ uint8 *Buffer_Scratch = (uint8 *)Memory_PushScratch(Memory, Size);
+ Arbitrary_WriteInto(Address_0, Buffer_Scratch, Size);
+ Arbitrary_WriteInto(Address_1, Address_0, Size);
+ Arbitrary_WriteInto(Buffer_Scratch, Address_1, Size);
+ Memory_PopScratch(Memory, Size);
}
-void History_Action_Change_Increment(memory *Memory, void *Data, action_type ActionChange)
+
+static void
+Arbitrary_ShiftData(uint8 *Address_Start, uint8 *Address_End, uint64 ShiftAmount, int32 Direction)
{
- 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);
+ if (Direction > 0) {
+ uint8 *AddressPlayhead = Address_End;
+ while ((ptrsize)AddressPlayhead >= (ptrsize)Address_Start) {
+ *(AddressPlayhead + ShiftAmount) = *AddressPlayhead;
+ AddressPlayhead--;
+ }
+ } else {
+ uint8 *AddressPlayhead = Address_Start;
+ while ((ptrsize)AddressPlayhead < (ptrsize)Address_End) {
+ *(AddressPlayhead - ShiftAmount) = *AddressPlayhead;
+ AddressPlayhead++;
}
}
}
-void History_Action_Change_Decrement(memory *Memory, void *Data, action_type ActionChange)
+struct history_info {
+ uint16 ActionCount_Total;
+ uint16 ActionCount_EndOfPlayhead;
+ uint16 ActionCount_Current;
+
+ uint64 ActionOffset_Total;
+ uint64 ActionOffset_EndOfPlayhead;
+ uint64 ActionOffset_Current;
+
+ uint64 EntrySize_Current;
+};
+
+static uint64
+History_GetActionSize(history_entry_list *History, int i, uint16 ActionCount_EndOfPlayhead)
+{
+ history_action *Action = &History->Action[i];
+ if (Action->Type == action_type_swap)
+ return Action->Size;
+ return 0;
+}
+
+// Returns information on the undo tree based on three points of data: the
+// total amount of entries, the location of the playhead, and whatever location
+// SampleIndex is set to, which should be either one minus playhead or the playhead.
+
+// I wrote this with the intent of precomputing things like the tree's total
+// size and the size of the current action, because calculating them in the
+// Action_Redo/Undo calls got extremely confusing.
+
+static history_info
+History_GetTreeInfo(history_entry_list *History, uint16 SampleIndex)
{
- switch (ActionChange)
+ history_info Info = {};
+
+ for (int i = 0; i < History->NumberOfEntries; i++)
{
- 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);
- }
+ history_entry *Entry = &History->Entry[i];
+ Info.ActionCount_Total += Entry->NumberOfActions;
+ if (i < History->EntryPlayhead)
+ Info.ActionCount_EndOfPlayhead += Entry->NumberOfActions;
+ if (i < SampleIndex)
+ Info.ActionCount_Current += Entry->NumberOfActions;
}
-}
-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++;
- }
+ for (int i = 0; i < Info.ActionCount_Total; i++)
+ {
+ uint64 Size = History_GetActionSize(History, i, Info.ActionCount_EndOfPlayhead);
+ Info.ActionOffset_Total += Size;
+ if (i < Info.ActionCount_EndOfPlayhead)
+ Info.ActionOffset_EndOfPlayhead += Size;
+
+ if (i < Info.ActionCount_Current)
+ Info.ActionOffset_Current += Size;
+ else if (i < Info.ActionCount_EndOfPlayhead) // Only increment the current size if i is between
+ Info.EntrySize_Current += Size; // the current count and playhead count!
}
+
+ return Info;
}
-void History_Action_Shift_2(memory *Memory, void *StartingAddress, uint32 Size, uint16 NumberOf, int16 Direction, int16 Index)
+void History_Action_Undo(memory *Memory, history_info Info, history_action *ActionPointer, uint64 Action_Offset)
{
- 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);
+ history_entry_list *History = &Memory->History;
+
+ // Only swap_bitmap should touch the data!
+ history_action Action = *ActionPointer;
+
+ uint8 *Address_HistoryTree_Start = (uint8 *)Memory_AddressAtOffset(Memory, P_UndoBuffer, Action_Offset);
+ uint8 *Address_HistoryTree_End = (uint8 *)Memory_AddressAtOffset(Memory, P_UndoBuffer, Info.ActionOffset_Total);
+ uint8 *Address_Data = (uint8 *)Memory_AddressAtOffset(Memory, Action.TableName, Action.ByteOffset);
+
+ if (Action.Type == action_type_swap) {
+ Arbitrary_SwapData(Memory, Address_HistoryTree_Start, Address_Data, Action.Size);
+ } else if (Action.Type == action_type_shift) {
+ // In order to shift back we have to start the address at where the
+ // shifted chunk is _now_, not when we called the function.
+ uint64 NewByteOffset = (Action.Direction > 0) ? Action.ByteOffset + Action.ShiftAmount : Action.ByteOffset - Action.ShiftAmount;
+ void *Address_Start = Memory_AddressAtOffset(Memory, Action.TableName, NewByteOffset);
+ uint8 *Address_End = (uint8 *)Address_Start + Action.Size;
+ // Direction also needs to be reversed.
+ int16 Direction = Action.Direction * -1;
+ Arbitrary_ShiftData((uint8 *)Address_Start, Address_End, Action.ShiftAmount, Direction);
+ } else {
+ 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;
- 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);
- } break;
+void History_Action_Redo(memory *Memory, history_info Info, history_action *ActionPointer, uint64 Action_Offset) {
+
+ history_entry_list *History = &Memory->History;
+
+ history_action Action = *ActionPointer;
+
+ uint8 *Address_HistoryTree_Start = (uint8 *)Memory_AddressAtOffset(Memory, P_UndoBuffer, Action_Offset);
+ uint8 *Address_HistoryTree_End = (uint8 *)Memory_AddressAtOffset(Memory, P_UndoBuffer, Info.ActionOffset_Total);
+ uint8 *Address_Data = (uint8 *)Memory_AddressAtOffset(Memory, Action.TableName, Action.ByteOffset);
+
+ if (Action.Type == action_type_swap) {
+ Arbitrary_SwapData(Memory, Address_HistoryTree_Start, Address_Data, Action.Size);
+ } else if (Action.Type == action_type_shift) {
+ void *Address_Start = Memory_AddressAtOffset(Memory, Action.TableName, Action.ByteOffset);
+ uint8 *Address_End = (uint8 *)Address_Start + Action.Size;
+ int16 Direction = Action.Direction;
+ Arbitrary_ShiftData((uint8 *)Address_Start, Address_End, Action.ShiftAmount, Direction);
+ } else {
+ Assert(0);
}
- Data = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
- *(action_type *)Data = ActionChange;
}
-// Overwrite area with arbitrary-sized memory. Only use if the previous data
-// doesn't need to be recorded, like pushing to the end of a stack.
-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++);
+void History_Undo(memory *Memory) {
+ history_entry_list *History = &Memory->History;
+ if (History->EntryPlayhead == 0) return;
+
+ // We want Current to represent the beginning of the current entry, so we
+ // subtract one from the playhead.
+ history_info Info = History_GetTreeInfo(History, History->EntryPlayhead - 1);
+ history_entry *Entry = &History->Entry[History->EntryPlayhead - 1];
+
+ // This puts us at the end of the current entry's offset.
+ uint64 ActionOffset_Stepback = Info.ActionOffset_Current + Info.EntrySize_Current;
+
+ for (int i = Entry->NumberOfActions - 1; i >= 0; i--) {
+ history_action *Action = &History->Action[Info.ActionCount_Current + i];
+
+ // We step backwards only if the action is currently storing data.
+ if (Action->Type != action_type_shift)
+ ActionOffset_Stepback -= Action->Size;
+
+ History_Action_Undo(Memory, Info, Action, ActionOffset_Stepback);
}
- 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;
+
+ History->EntryPlayhead--;
+
}
-// 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)
-{
- // We need to at least clear NumberOfActions in case this index is being reused.
- Memory->Action.Entry[Memory->Action.Index] = {};
- Memory->Action.Entry[Memory->Action.Index].Name = Name;
- Memory->Action.Entry[Memory->Action.Index].Type = Type;
- // Effectively deletes entries in front if we're beginning out of an undo.
- // It wouldn't be all that much more difficult to support branched undoing
- // now that I think about it... (would anyone use it though?)
- if (Memory->Action.Index != Memory->Action.NumberOfEntries) {
- Memory->Action.NumberOfEntries = Memory->Action.Index;
+void History_Redo(memory *Memory) {
+ history_entry_list *History = &Memory->History;
+ if (History->EntryPlayhead == History->NumberOfEntries) return;
+
+ // NOTE(fox): The third part of this function for recording the "current"
+ // action's size is only necessary for the undo call, so it's not correct on the redo.
+ history_info Info = History_GetTreeInfo(History, History->EntryPlayhead);
+ history_entry *Entry = &History->Entry[History->EntryPlayhead];
+
+ History->EntryPlayhead++;
+
+ uint64 ActionOffset_Stepforward = Info.ActionOffset_Current;
+
+ for (int i = 0; i < Entry->NumberOfActions; i++) {
+ history_action *Action = &History->Action[Info.ActionCount_Current + i];
+
+ History_Action_Redo(Memory, Info, Action, ActionOffset_Stepforward);
+
+ // We step forwards only if the action is currently storing data.
+ if (Action->Type != action_type_shift)
+ ActionOffset_Stepforward += Action->Size;
+
}
+
}
-void History_Entry_SetPointer(memory *Memory, void *Data)
+// This is only called when we're certain the action is going to be taken.
+void History_Entry_Commit(memory *Memory, char *Name)
{
- Memory->Action.Entry[Memory->Action.Index].ExtraPointer = Data;
+ history_entry_list *History = &Memory->History;
+ history_entry *Entry = &History->Entry[History->EntryPlayhead];
+ Entry->Name = Name;
+ Entry->NumberOfActions = 0;
+ // Effectively deletes entries in front if we're beginning out of an undo.
+ if (History->NumberOfEntries != History->EntryPlayhead)
+ History->NumberOfEntries = History->EntryPlayhead;
+ History->NumberOfEntries++;
+ History->EntryPlayhead++;
+ Memory->IsFileSaved = false;
+#if DEBUG
+ Assert(Debug.UndoState != 1);
+ Debug.UndoState = 1;
+#endif
}
void History_Entry_End(memory *Memory)
{
- Memory->Action.Index++;
- Memory->Action.NumberOfEntries++;
+ history_entry_list *History = &Memory->History;
+#if DEBUG
+ Debug.UndoState = 0;
+#endif
}
-// The pointer is unwinded.
-void History_Action_Undo(memory *Memory) {
- void *LastPos = Memory_Rewind(Memory, sizeof(action_type), P_UndoBuffer);
- action_type *ActionType = (action_type *)LastPos;
+// NOTE(fox): Shift is the only action that additionally changes the data after
+// the info is put on the tree, since it's always the same function used.
- switch (*ActionType)
+static void History_Action_Add(memory *Memory, history_action ActionData, void *ReferenceData = NULL)
+{
+ history_entry_list *History = &Memory->History;
+ history_entry *Entry = &History->Entry[History->EntryPlayhead - 1];
+
+ history_info Info = History_GetTreeInfo(History, History->EntryPlayhead - 1);
+
+ history_action *Action = &History->Action[Info.ActionCount_Total];
+ *Action = ActionData;
+
+ if (Action->Type == action_type_swap)
{
- 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:
- {
- 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_type_change_u32:
- {
- 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_type_change_i32:
- {
- 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_type_change_r32:
- {
- 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_type_change_u64:
- {
- 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_type_change_ptr:
- {
- 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_type_shift_keyframe:
- {
- 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);
- 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:
- {
- Assert(0);
- } break;
+ void *Address_HistoryTree = Memory_AddressAtOffset(Memory, P_UndoBuffer, Info.ActionOffset_Total);
+ void *Address_Data = Memory_AddressAtOffset(Memory, Action->TableName, Action->ByteOffset);
+ Arbitrary_WriteInto((uint8 *)Address_Data, (uint8 *)Address_HistoryTree, Action->Size);
+ } else if (Action->Type == action_type_shift)
+ {
+ void *Address_Start = Memory_AddressAtOffset(Memory, Action->TableName, Action->ByteOffset);
+ uint8 *Address_End = (uint8 *)Address_Start + Action->Size;
+ Arbitrary_ShiftData((uint8 *)Address_Start, Address_End, Action->ShiftAmount, Action->Direction);
}
- void *EndPos = Memory_Rewind(Memory, sizeof(action_type), P_UndoBuffer);
+
+ Entry->NumberOfActions++;
}
-// The pointer is rewinded.
-void History_Action_Redo(memory *Memory) {
- void *LastPos = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
- action_type *ActionType = (action_type *)LastPos;
+// Helper functions for different tables.
- switch (*ActionType)
- {
- 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:
- {
- 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_type_change_u32:
- {
- 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_type_change_i32:
- {
- 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_type_change_r32:
- {
- 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_type_change_u64:
- {
- 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_type_change_ptr:
- {
- 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_type_shift_keyframe:
- {
- 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);
- 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:
- {
- Assert(0);
- } break;
- }
- void *EndPos = Memory_Advance(Memory, sizeof(action_type), P_UndoBuffer);
+
+static void History_Action_Shift(memory *Memory, memory_table_list TableName,
+ void *Address0, void *Address1, uint64 Amount, int16 Direction)
+{
+ void *Address_Start = Memory->Slot[TableName].Address;
+ uint64 ByteOffset = (ptrsize)Address0 - (ptrsize)Address_Start;
+ uint64 Size = (ptrsize)Address1 - (ptrsize)Address0;
+
+ history_action Action = { TableName, action_type_shift, Size, ByteOffset, Amount, Direction };
+
+ History_Action_Add(Memory, Action);
}
-void History_Undo(memory *Memory) {
- if (Memory->Action.Index != 0) {
- Memory->Action.Index--;
- action_entry Entry = Memory->Action.Entry[Memory->Action.Index];
- switch (Entry.Type)
- {
- case action_entry_layerinit:
- {
- AV_Dealloc((av_info *)*(ptrsize *)Entry.ExtraPointer);
- *(ptrsize *)Entry.ExtraPointer = 0x0; // what actually dereferences the pointer
- } break;
- case action_entry_default:
- {
- } break;
- }
- for (int i = 0; i < Entry.NumberOfActions; i++)
- History_Action_Undo(Memory);
- }
+static void History_Action_Block_Swap(memory *Memory, memory_table_list TableName, void *Address_Data)
+{
+ void *Address_Start = Memory->Slot[TableName].Address;
+ uint64 Size = Memory->Slot[TableName].Block_ElementSize;
+ uint64 ByteOffset = (ptrsize)Address_Data - (ptrsize)Address_Start;
+ history_action Action = { TableName, action_type_swap, Size, ByteOffset, 0 };
+ History_Action_Add(Memory, Action);
}
-void History_Redo(memory *Memory) {
- if (Memory->Action.Index != Memory->Action.NumberOfEntries) {
- action_entry Entry = Memory->Action.Entry[Memory->Action.Index];
- switch (Entry.Type)
- {
- case action_entry_layerinit:
- {
- } break;
- case action_entry_default:
- {
- } break;
- }
- for (int i = 0; i < Entry.NumberOfActions; i++)
- History_Action_Redo(Memory);
- Memory->Action.Index++;
- }
+// Remember to dereference pointers if taking the sizeof() a variable, or else Size will be 8!
+
+static void History_Action_Swap(memory *Memory, memory_table_list TableName, uint64 Size, void *Address_Data)
+{
+ void *Address_Start = Memory->Slot[TableName].Address;
+ uint64 ByteOffset = (ptrsize)Address_Data - (ptrsize)Address_Start;
+ history_action Action = { TableName, action_type_swap, Size, ByteOffset, 0 };
+ History_Action_Add(Memory, Action);
}