summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorFox Caminiti <fox@foxcam.net>2022-12-16 20:16:43 -0500
committerFox Caminiti <fox@foxcam.net>2022-12-16 20:16:43 -0500
commitbedd6906eabdd513042d6a178d4dc56a3a41d1d3 (patch)
tree2bcbd3e46ae61e583707a2ccc5b3f5cfeacb61a8 /src/include
parentcdb9e1f7240cb0716b7d99df5e1fd7c3fc3407a8 (diff)
v3, file/build organization
Diffstat (limited to 'src/include')
-rw-r--r--src/include/debug.h99
-rw-r--r--src/include/defines.h52
-rw-r--r--src/include/ffmpeg_backend.h37
-rw-r--r--src/include/functions.h90
-rw-r--r--src/include/gl_calls.h24
-rw-r--r--src/include/imgui_internal_widgets.h15
-rw-r--r--src/include/imgui_ops.h106
-rw-r--r--src/include/keybinds.h205
-rw-r--r--src/include/layer.h50
-rw-r--r--src/include/main.h686
-rw-r--r--src/include/memory.h71
-rw-r--r--src/include/my_math.h762
-rw-r--r--src/include/sharebuffer.h17
-rw-r--r--src/include/stable_diffusion.h33
-rw-r--r--src/include/structs.h5
-rw-r--r--src/include/undo.h2
16 files changed, 2254 insertions, 0 deletions
diff --git a/src/include/debug.h b/src/include/debug.h
new file mode 100644
index 0000000..6321679
--- /dev/null
+++ b/src/include/debug.h
@@ -0,0 +1,99 @@
+#if DEBUG
+
+static int32 *debugnull = NULL;
+#define Assert(Expression) if(!(Expression)) {*debugnull = 21;}
+
+enum valtype {
+ d_float,
+ d_uint,
+ d_int
+};
+
+union debugval {
+ real32 f;
+ uint32 u;
+ int32 i;
+};
+
+// things that get cleared every frame with the UI
+struct debug_temp
+{
+ valtype DebugPropertyType[16];
+ debugval Val[16];
+ char *String[16];
+ uint32 WatchedProperties;
+};
+
+struct project_debug
+{
+ debug_temp Temp;
+ bool32 ToggleWindow = 1;
+ bool32 ReloadUI = true;
+ bool32 NoThreading = 0;
+ bool32 DisableAlpha = 0;
+ uint64 PixelCountTransparent;
+ uint64 PixelCountRendered;
+ 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;
+
+static void
+DebugWatchVar(char *Name, void *Address, valtype Type) {
+ uint32 i = Debug.Temp.WatchedProperties;
+ Debug.Temp.String[i] = Name;
+ if (Type == d_float)
+ Debug.Temp.Val[i].f = *(real32 *)Address;
+ if (Type == d_uint)
+ Debug.Temp.Val[i].u = *(uint32 *)Address;
+ if (Type == d_int)
+ Debug.Temp.Val[i].i = *(int32 *)Address;
+ Debug.Temp.DebugPropertyType[i] = Type;
+ Debug.Temp.WatchedProperties++;
+}
+
+#else
+
+#define Assert(Expression)
+
+enum valtype {
+};
+
+union debugval {
+};
+
+struct debug_temp
+{
+};
+
+struct project_debug
+{
+};
+
+static void
+DebugWatchVar(char *Name, void *Address, valtype Type) {
+}
+
+static void
+DebugPrintMemoryUsage(memory Memory) {
+}
+#endif
+
+#ifdef PERF
+
+struct perf_stats
+{
+ uint64 PixelCountTransparent;
+ uint64 PixelCountRendered;
+ uint64 PixelCountChecked;
+};
+
+static uint64 Test;
+
+#endif
+
diff --git a/src/include/defines.h b/src/include/defines.h
new file mode 100644
index 0000000..8216f1c
--- /dev/null
+++ b/src/include/defines.h
@@ -0,0 +1,52 @@
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+
+typedef int64_t int64;
+typedef int32 bool32;
+
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+typedef uint64_t uint64;
+
+typedef float real32;
+typedef double real64;
+
+typedef uint64 ptrsize; // is there a compiler variable for 32 vs 64 bit like this?
+
+#define NORMALIZED_COL_MIN V4(0.0f, 0.0f, 0.0f, 0.0f)
+#define NORMALIZED_COL_MAX V4(1.0f, 1.0f, 1.0f, 1.0f)
+#define NORMALIZED_REAL_MIN { 0.0f }
+#define NORMALIZED_REAL_MAX { 1.0f }
+
+#define TESS_TOL 1.5f // Level of tesselation for bezier calculations; ImGui's default value
+
+// All of these MIN/MAX values are arbitrarily chosen; they can probably be
+// increased if the user requires it.
+
+#define PROPERTY_REAL_MAX 1000000
+#define PROPERTY_REAL_MIN -1000000
+
+#define MAX_LAYERS 2048
+#define MAX_EFFECTS 32
+#define MAX_SOURCES 1024
+#define MAX_COMPS 1024
+#define MAX_PRECOMP_RECURSIONS 4
+#define MAX_MASKS 8
+#define MAX_PROPERTIES_PER_EFFECT 80 // Kinda high since we want to support 8 xy points of Curves data across 5 channels.
+#define MAX_KEYFRAME_BLOCKS 64
+#define MAX_KEYFRAMES_PER_BLOCK 32 // max keyframes on a single channel is 2048
+
+#define MAX_SELECTED_PROPERTIES 16
+
+#define AmountOf(Array) sizeof((Array)) / sizeof((Array)[1])
+
+#if ARM
+#define GetCPUTime() 0
+#else
+#define GetCPUTime() __rdtsc()
+#endif
+
+static real32 Tau = 0.9; // tension
+
diff --git a/src/include/ffmpeg_backend.h b/src/include/ffmpeg_backend.h
new file mode 100644
index 0000000..717a33d
--- /dev/null
+++ b/src/include/ffmpeg_backend.h
@@ -0,0 +1,37 @@
+// NOTE(fox): Even though each layer has its own completely isolated AV
+// instance, it appears two layers with the same file still share something.
+// When the layers aren't at the same position in time, the playhead of one
+// layer gets misaligned every few frames and causes a manual seek back to the
+// position. Different files don't exhibit this behavior.
+
+struct av_stream_info {
+ uint32 Index;
+ AVCodecParameters *CodecParameters; // Used to supply info about the decoder.
+ const AVCodec* Codec;
+ AVStream *Stream; // Which stream, or channel, the video is in. Holds FPS info and is used to verify that the decoded packet belongs to this stream.
+ AVCodecContext *CodecContext;
+};
+
+
+struct av_info {
+ uint8 Occupied;
+
+ uint16 Block_Source_Index;
+
+ int LastFrameRendered; // Convenient to know this to only seek when we actually need to.
+ uint64 PreviousPTS; // PTS value of the previous frame, used to check timings in debug.
+
+ AVFormatContext *FileFormatContext; // Umbrella for everything else, seems to contain the playhead state
+
+ av_stream_info Video;
+ av_stream_info Audio;
+
+ AVPacket *Packet;
+ AVFrame *Frame;
+
+ uint32 FrameCount;
+ uint64 PTSDuration; // likely not always 100% accurate
+
+ SwsContext *RGBContext;
+};
+
diff --git a/src/include/functions.h b/src/include/functions.h
new file mode 100644
index 0000000..23d741e
--- /dev/null
+++ b/src/include/functions.h
@@ -0,0 +1,90 @@
+
+// Memory
+
+static void Memory_Copy(uint8 *Address_Write, uint8 *Address_Read, uint64 Size);
+static void Arbitrary_Zero(uint8 *Address_Write, uint64 Size);
+static void Arbitrary_SwapData(memory *Memory, uint8 *Address_0, uint8 *Address_1, uint64 Size);
+static void Arbitrary_ShiftData(uint8 *Address_Start, uint8 *Address_End, uint64 ShiftAmount, int32 Direction);
+
+
+// Rudimentary guess-until-correct solver for bezier curves, used to evaluate
+// the keyframe graph. Similar to the Catmull-Rom solver in CurvesSolver().
+
+static real32 Bezier_SolveYForX(v2 Point_P0, v2 Point_P1, v2 Point_P2, v2 Point_P3, real32 TargetX);
+static bezier_point * Bezier_LookupAddress(memory *Memory, property_channel *Property, uint16 Index, bool32 AssertExists = 1);
+static void Bezier_Interact_Evaluate(project_state *State, bezier_point *PointAddress, v2 *Pos, real32 GraphZoomHeight = 1, real32 Y_Increment = 1);
+// NOTE(fox): GraphZoomHeight and Y_Increment don't have to be specified if the Y value isn't needed, i.e. in Property_SortAll().
+static void Bezier_Add(memory *Memory, memory_table_list TableName, property_channel *Property, bezier_point PointData, uint16 *ArrayLocation);
+
+
+static void ImGui_ProcessInputs(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io, sorted_file Sorted);
+static void ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, sorted_property_array *SortedPropertyStart, uint16 *SortedKeyframeArray);
+static void ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io, GLuint textureID, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, uint16 *SortedKeyframeArray);
+static void ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, sorted_property_array *SortedPropertyStart, uint16 *SortedKeyframeArray);
+
+static void ImGui_File(project_data *File, project_state *State, memory *Memory, ImGuiIO io, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray);
+static void ImGui_EffectsPanel(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io);
+static void ImGui_ColorPanel(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io);
+
+static void ImGui_Menu(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io);
+static void ImGui_Popups(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io);
+static void ImGui_KeybindUI(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io);
+
+#if DEBUG
+static void ImGui_DebugMemoryViewer(memory *Memory, project_state *State);
+static void ImGui_DebugRenderQueue(project_state *State);
+static void ImGui_DebugUndoTree(memory *Memory, project_state *State);
+#endif
+#if SD
+static void ImGui_SD_Thumbnail(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, uint16 *SourceArray, uint16 SourceCount);
+static void ImGui_SD_Prompt(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray);
+#endif
+
+// Widgets not involving drawing UI.
+
+static v2 ImGui_ScreenPointToCompUV(ImVec2 ViewportMin, ImVec2 CompPos, ImVec2 CompZoom, ImVec2 MousePos);
+static void ImGui_WarpMouse(project_state *State, ImVec2 MousePos, ImVec2 Min, ImVec2 Max, int Direction = 3);
+static void ImGui_WarpMouseFinish(project_state *State, ImVec2 MousePos);
+static ImVec2 ImGui_Brush_CalcMousePos(project_state *State, ImGuiIO &io, ImVec2 MouseDelta, int32 i, real32 DeltaDistance, real32 DeltaSlope);
+static bool32 ImGui_TestBoxSelection_Point(ImVec2 Pos, ImGuiIO &io, bool32 *Test);
+
+
+static void
+Render_Main(project_data *File, project_state *State, memory *Memory, sorted_file Sorted, ui *UI, SDL_Window *window, GLuint textureID,
+ void *Data, void *OutputBuffer, render_type RenderType, rectangle RenderRegion);
+
+static void Effect_Curves_Init(block_effect *Effect, property_channel *Property);
+
+void AV_IsFileSupported(char *filename, bool32 *IsVideo, bool32 *HasAudio);
+
+static v2 T_CompUVToLayerUV(layer_transforms T, uint32 FileWidth, uint32 FileHeight, uint32 SourceWidth, uint32 SourceHeight, v2 CompUV);
+static header_effect* Effect_EntryFromID(project_state *State, char *ID);
+
+void Effect_Curves_Sort(memory *Memory, block_effect *Effect, uint16 *SortedPointStart, uint16 Which);
+inline v2 Effect_V2(memory *Memory, block_effect *Effect, int Offset);
+
+static void Interact_Transform_Begin(project_data *File, memory *Memory, project_state *State, ImVec2 OGPos, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray);
+
+static v2 Transform_ScreenSpaceToLocal(layer_transforms T, uint32 FileWidth, uint32 FileHeight, uint32 SourceWidth, uint32 SourceHeight, ImVec2 CompPos, ImVec2 CompZoom, ImVec2 ViewportMin, ImVec2 Point);
+static ImVec2 Layer_LocalToScreenSpace(project_state *State, memory *Memory, block_layer *Layer, ui *UI, uint32 PrincipalCompIndex, v2 Point);
+
+static v2 TransformPoint(layer_transforms T, real32 Width, real32 Height, v2 Point);
+
+static void Layer_GetDimensions(memory *Memory, block_layer *Layer, int *Width, int *Height);
+
+static void * Memory_PushScratch(memory *Memory, uint64 Size);
+
+static void Memory_PopScratch(memory *Memory, uint64 Size);
+
+void Bitmap_SwapData(uint8 *Address_0, uint8 *Address_1, uint64 Size, uint16 BytesPerPixel);
+void GL_DeleteHWBuffer(gl_effect_layer *Test);
+
+void GL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height, uint16 BytesPerPixel, bool32 Multisample);
+
+static void Transform_ApplyInteractive(interact_transform Interact, real32 *OutputX, real32 *OutputY, real32 *OutputRotation, real32 *OutputScale);
+
+static layer_transforms Layer_GetTransforms(block_layer *Layer);
+void GL_GenAndBindTexture(GLuint *GLTexture, int Width, int Height, int BytesPerPixel, void *BufferAddress);
+
+static real32 Bezier_SolveYForX(v2 Point_P0, v2 Point_P1, v2 Point_P2, v2 Point_P3, real32 X);
+
diff --git a/src/include/gl_calls.h b/src/include/gl_calls.h
new file mode 100644
index 0000000..fa0a00c
--- /dev/null
+++ b/src/include/gl_calls.h
@@ -0,0 +1,24 @@
+struct default_gl_vertex_object {
+ uint32 VertexArrayObject;
+ uint32 VertexBufferObject;
+ uint32 ElementBufferObject;
+};
+
+struct gl_vertex_shader {
+ uint32 VertexArrayObject;
+ uint32 VertexBufferObject;
+};
+
+static default_gl_vertex_object DefaultVerts;
+static gl_vertex_shader GL_DefaultVertexObjects;
+static uint32 DefaultVertexShader;
+static uint32 DefaultShaderProgram;
+static uint32 MaskShaderProgram;
+
+float GL_DefaultVertices[] = {
+ 1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
+ 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
+ -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
+ -1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
+};
+
diff --git a/src/include/imgui_internal_widgets.h b/src/include/imgui_internal_widgets.h
new file mode 100644
index 0000000..52fdc74
--- /dev/null
+++ b/src/include/imgui_internal_widgets.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <climits>
+
+#include <imgui.h>
+
+// NOTE(fox): Appending to the standard ImGui namespace so I don't have to convert all the functions to ImGui::Function()
+namespace ImGui {
+ IMGUI_API bool SliderLevels(const char* label, const char* label2, const char* label3, void* p_data, void* p_min, void* p_max);
+ IMGUI_API bool TestLine(ImVec2 P1, ImVec2 P2);
+ IMGUI_API bool BezierInteractive(ImVec2 p0, ImVec2 p1, ImVec2 p2, ImVec2 p3);
+ IMGUI_API bool LineInteractive(ImVec2 p0, ImVec2 p1);
+ IMGUI_API ImVec2 RatioToPoint(ImVec2 a, ImVec2 b, float ratio);
+}
+
diff --git a/src/include/imgui_ops.h b/src/include/imgui_ops.h
new file mode 100644
index 0000000..6089f94
--- /dev/null
+++ b/src/include/imgui_ops.h
@@ -0,0 +1,106 @@
+
+
+ImVec2 operator+(ImVec2 A, ImVec2 B)
+{
+ ImVec2 Result;
+
+ Result.x = A.x + B.x;
+ Result.y = A.y + B.y;
+
+ return Result;
+}
+
+ImVec2 operator+(ImVec2 A, int B)
+{
+ ImVec2 Result;
+
+ Result.x = A.x + B;
+ Result.y = A.y + B;
+
+ return Result;
+}
+
+ImVec2 operator-(ImVec2 A, int B)
+{
+ ImVec2 Result;
+
+ Result.x = A.x - B;
+ Result.y = A.y - B;
+
+ return Result;
+}
+
+ImVec2 operator-(ImVec2 A, ImVec2 B)
+{
+ ImVec2 Result;
+
+ Result.x = A.x - B.x;
+ Result.y = A.y - B.y;
+
+ return Result;
+}
+
+ImVec2 operator*(ImVec2 A, real32 B)
+{
+ ImVec2 Result;
+
+ Result.x = A.x * B;
+ Result.y = A.y * B;
+
+ return Result;
+}
+
+ImVec2 operator*(ImVec2 A, ImVec2 B)
+{
+ ImVec2 Result;
+
+ Result.x = A.x * B.x;
+ Result.y = A.y * B.y;
+
+ return Result;
+}
+
+ImVec2 operator/(ImVec2 A, ImVec2 B)
+{
+ ImVec2 Result;
+
+ Result.x = A.x / B.x;
+ Result.y = A.y / B.y;
+
+ return Result;
+}
+
+ImVec2 operator/(ImVec2 A, real32 B)
+{
+ ImVec2 Result;
+
+ Result.x = A.x / B;
+ Result.y = A.y / B;
+
+ return Result;
+}
+
+ImVec2 operator/(real32 A, ImVec2 B)
+{
+ ImVec2 Result;
+
+ Result.x = A / B.x;
+ Result.y = A / B.y;
+
+ return Result;
+}
+
+inline bool32
+IsRectTouching(ImVec2 Min1, ImVec2 Max1, ImVec2 Min2, ImVec2 Max2)
+{
+ bool32 Result = 0;
+ if ((Max1.x > Min2.x && Min1.x < Min2.x) &&
+ (Max1.y > Min2.y && Min1.y < Min2.y))
+ Result = 1;
+ // if (
+ // Result = 1;
+ // if (Min1.x > Min2.x)
+
+ return(Result);
+}
+
diff --git a/src/include/keybinds.h b/src/include/keybinds.h
new file mode 100644
index 0000000..3fe5f64
--- /dev/null
+++ b/src/include/keybinds.h
@@ -0,0 +1,205 @@
+enum key_mode {
+ key_mode_all,
+ key_mode_viewport,
+ key_mode_timeline,
+ key_mode_graph,
+ key_mode_brush,
+ key_mode_count,
+};
+
+enum key_mods {
+ Mod_None,
+ Mod_Ctrl,
+ Mod_Alt,
+ Mod_Shift,
+ Mod_CtrlShift
+};
+
+struct shortcut_entry {
+ ImGuiKey_ Key;
+ key_mods Mods;
+ key_mode Mode;
+ char *Name;
+};
+
+static shortcut_entry ShortcutArray[] {
+ { ImGuiKey_None, Mod_None, key_mode_all, "Many actions/modes are escapable with the Esc key." },
+ { ImGuiKey_None, Mod_None, key_mode_all, "Undo isn't fully implemented yet; beware crashes." },
+ { ImGuiKey_Q, Mod_None, key_mode_all, "Quit (instantly!)" },
+ { ImGuiKey_W, Mod_None, key_mode_all, "Step back one frame" },
+ { ImGuiKey_E, Mod_None, key_mode_all, "Step forward one frame" },
+ { ImGuiKey_V, Mod_None, key_mode_all, "Move tool" },
+ { ImGuiKey_B, Mod_None, key_mode_all, "Brush tool" },
+ { ImGuiKey_Space, Mod_None, key_mode_all, "Play scene" },
+ { ImGuiKey_Delete, Mod_None, key_mode_all, "Delete selection (WIP)" },
+ { ImGuiKey_S, Mod_Ctrl, key_mode_all, "Save" },
+ { ImGuiKey_S, Mod_CtrlShift, key_mode_all, "Save as" },
+ { ImGuiKey_C, Mod_Ctrl, key_mode_all, "Copy" },
+ { ImGuiKey_P, Mod_Ctrl, key_mode_all, "Paste" },
+ { ImGuiKey_Z, Mod_Ctrl, key_mode_all, "Undo" },
+ { ImGuiKey_Z, Mod_Ctrl, key_mode_all, "Redo" },
+ { ImGuiKey_Space, Mod_Shift, key_mode_all, "Focus effects search" },
+ { ImGuiKey_Slash, Mod_Shift, key_mode_all, "Open help" },
+
+ { ImGuiKey_None, Mod_None, key_mode_viewport, "Hold right click to pan." },
+ { ImGuiKey_None, Mod_None, key_mode_viewport, "Hold Z and drag left click to zoom." },
+ { ImGuiKey_None, Mod_None, key_mode_viewport, "Press Enter or ctrl+click to commit a transform." },
+ { ImGuiKey_T, Mod_None, key_mode_viewport, "Transform selected layers" },
+
+ { ImGuiKey_Tab, Mod_None, key_mode_timeline, "Switch between timeline and graph" },
+ { ImGuiKey_2, Mod_None, key_mode_timeline, "Toggle precomp view" },
+ { ImGuiKey_G, Mod_None, key_mode_timeline, "Toggle position keyframes" },
+ { ImGuiKey_A, Mod_None, key_mode_timeline, "Toggle anchor point keyframes" },
+ { ImGuiKey_R, Mod_None, key_mode_timeline, "Toggle roation keyframes" },
+ { ImGuiKey_S, Mod_None, key_mode_timeline, "Toggle scale keyframes" },
+ { ImGuiKey_T, Mod_None, key_mode_timeline, "Toggle time remapping keyframes" },
+ { ImGuiKey_T, Mod_Shift, key_mode_timeline, "Toggle opacity keyframes" },
+ { ImGuiKey_U, Mod_None, key_mode_timeline, "Toggle all active channels" },
+ { ImGuiKey_N, Mod_None, key_mode_timeline, "Mark frame start" },
+ { ImGuiKey_N, Mod_Shift, key_mode_timeline, "Mark frame end" },
+
+ { ImGuiKey_G, Mod_None, key_mode_graph, "Enter keyframe moving mode" },
+ { ImGuiKey_X, Mod_None, key_mode_graph, "Constrain to X axis" },
+ { ImGuiKey_Y, Mod_None, key_mode_graph, "Constrain to Y axis" },
+
+ { ImGuiKey_None, Mod_None, key_mode_brush, "Hold alt and drag to adjust size/hardness." },
+ { ImGuiKey_X, Mod_None, key_mode_brush, "Swap FG and BG colors" },
+};
+
+
+struct key_entry {
+ ImGuiKey_ KeyIndex;
+ char *Name;
+ char *ShiftName;
+ uint32 Sector;
+ ImVec2 Offset;
+ real32 WidthRatio;
+};
+
+// dumb typing exercise
+static key_entry KeyEntries[] {
+ { ImGuiKey_Tab, "Tab", "\0", 0, ImVec2(0, 1), 1.5f },
+ { ImGuiKey_LeftArrow, "<-", "\0", 2, ImVec2(0, 4), 1.0f },
+ { ImGuiKey_RightArrow, "->", "", 2, ImVec2(2, 4), 1.0f },
+ { ImGuiKey_UpArrow, "/\\", "", 2, ImVec2(1, 3), 1.0f },
+ { ImGuiKey_DownArrow, "\\/", "", 2, ImVec2(1, 4), 1.0f },
+ { ImGuiKey_PageUp, "Up", "", 2, ImVec2(2, 0), 1.0f },
+ { ImGuiKey_PageDown, "Dn", "", 2, ImVec2(2, 1), 1.0f },
+ { ImGuiKey_Home, "Home", "", 2, ImVec2(1, 0), 1.0f },
+ { ImGuiKey_End, "End", "", 2, ImVec2(1, 1), 1.0f },
+ { ImGuiKey_Insert, "Insert", "", 2, ImVec2(0, 0), 1.0f },
+ { ImGuiKey_Delete, "Delete", "", 2, ImVec2(0, 1), 1.0f },
+ { ImGuiKey_Backspace, "Backspace", "", 0, ImVec2(13, 0), 2.0f },
+ { ImGuiKey_Space, "Space", "", 0, ImVec2(3.75, 4), 6.5f },
+ { ImGuiKey_Enter, "Enter", "", 0, ImVec2(12, 2), 2.25f},
+ { ImGuiKey_Escape, "Esc", "", 1, ImVec2(0, 0), 1.0f },
+ { ImGuiKey_LeftCtrl, "Ctrl", "", 0, ImVec2(0, 4), 1.25f },
+ { ImGuiKey_LeftShift, "Shift", "", 0, ImVec2(0, 3), 2.5f },
+ { ImGuiKey_LeftAlt, "Alt", "", 0, ImVec2(1.25, 4), 1.25 },
+ { ImGuiKey_LeftSuper, "Sp", "", 0, ImVec2(2.5, 4), 1.25f },
+ { ImGuiKey_RightCtrl, "Ctrl", "", 0, ImVec2(13.75, 4), 1.25f },
+ { ImGuiKey_RightShift, "Shift", "", 0, ImVec2(11, 3), 2.5f },
+ { ImGuiKey_RightAlt, "Alt", "", 0, ImVec2(11.25, 4), 1.25 },
+ { ImGuiKey_RightSuper, "Sp", "", 0, ImVec2(10.25, 4), 1.0f },
+ { ImGuiKey_Menu, "Menu", "", 0, ImVec2(12.5, 4), 1.25 },
+ { ImGuiKey_0, "0", ")", 0, ImVec2(10, 0), 1.0f },
+ { ImGuiKey_1, "1", "!", 0, ImVec2(1, 0), 1.0f },
+ { ImGuiKey_2, "2", "@", 0, ImVec2(2, 0), 1.0f },
+ { ImGuiKey_3, "3", "$", 0, ImVec2(3, 0), 1.0f },
+ { ImGuiKey_4, "4", "%", 0, ImVec2(4, 0), 1.0f },
+ { ImGuiKey_5, "5", "%", 0, ImVec2(5, 0), 1.0f },
+ { ImGuiKey_6, "6", "^", 0, ImVec2(6, 0), 1.0f },
+ { ImGuiKey_7, "7", "&", 0, ImVec2(7, 0), 1.0f },
+ { ImGuiKey_8, "8", "*", 0, ImVec2(8, 0), 1.0f },
+ { ImGuiKey_9, "9", "(", 0, ImVec2(9, 0), 1.0f },
+ { ImGuiKey_A, "a", "A", 0, ImVec2(1, 2), 1.0f },
+ { ImGuiKey_B, "b", "B", 0, ImVec2(5, 3), 1.0f },
+ { ImGuiKey_C, "c", "C", 0, ImVec2(3, 3), 1.0f },
+ { ImGuiKey_D, "d", "D", 0, ImVec2(3, 2), 1.0f },
+ { ImGuiKey_E, "e", "E", 0, ImVec2(3, 1), 1.0f },
+ { ImGuiKey_F, "f", "F", 0, ImVec2(4, 2), 1.0f },
+ { ImGuiKey_G, "g", "G", 0, ImVec2(5, 2), 1.0f },
+ { ImGuiKey_H, "h", "H", 0, ImVec2(6, 2), 1.0f },
+ { ImGuiKey_I, "i", "I", 0, ImVec2(8, 1), 1.0f },
+ { ImGuiKey_J, "j", "J", 0, ImVec2(7, 2), 1.0f },
+ { ImGuiKey_K, "k", "K", 0, ImVec2(8, 2), 1.0f },
+ { ImGuiKey_L, "l", "L", 0, ImVec2(9, 2), 1.0f },
+ { ImGuiKey_M, "m", "M", 0, ImVec2(7, 3), 1.0f },
+ { ImGuiKey_N, "n", "N", 0, ImVec2(6, 3), 1.0f },
+ { ImGuiKey_O, "o", "O", 0, ImVec2(9, 1), 1.0f },
+ { ImGuiKey_P, "p", "P", 0, ImVec2(10, 1), 1.0f },
+ { ImGuiKey_Q, "q", "Q", 0, ImVec2(1, 1), 1.0f },
+ { ImGuiKey_R, "r", "R", 0, ImVec2(4, 1), 1.0f },
+ { ImGuiKey_S, "s", "S", 0, ImVec2(2, 2), 1.0f },
+ { ImGuiKey_T, "t", "T", 0, ImVec2(5, 1), 1.0f },
+ { ImGuiKey_U, "u", "U", 0, ImVec2(7, 1), 1.0f },
+ { ImGuiKey_V, "v", "V", 0, ImVec2(4, 3), 1.0f },
+ { ImGuiKey_W, "w", "W", 0, ImVec2(2, 1), 1.0f },
+ { ImGuiKey_X, "x", "X", 0, ImVec2(2, 3), 1.0f },
+ { ImGuiKey_Y, "y", "Y", 0, ImVec2(6, 1), 1.0f },
+ { ImGuiKey_Z, "z", "Z", 0, ImVec2(1, 3), 1.0f },
+ { ImGuiKey_F1, "F1", "", 1, ImVec2(2, 0), 1.0f },
+ { ImGuiKey_F2, "F2", "", 1, ImVec2(3, 0), 1.0f },
+ { ImGuiKey_F3, "F3", "", 1, ImVec2(4, 0), 1.0f },
+ { ImGuiKey_F4, "F4", "", 1, ImVec2(5, 0), 1.0f },
+ { ImGuiKey_F5, "F5", "", 1, ImVec2(6.5, 0), 1.0f },
+ { ImGuiKey_F6, "F6", "", 1, ImVec2(7.5, 0), 1.0f },
+ { ImGuiKey_F7, "F7", "", 1, ImVec2(8.5, 0), 1.0f },
+ { ImGuiKey_F8, "F8", "", 1, ImVec2(9.5, 0), 1.0f },
+ { ImGuiKey_F9, "F9", "", 1, ImVec2(11, 0), 1.0f },
+ { ImGuiKey_F10, "F10","", 1, ImVec2(12, 0), 1.0f },
+ { ImGuiKey_F11, "F11","", 1, ImVec2(13, 0), 1.0f },
+ { ImGuiKey_F12, "F12","", 1, ImVec2(14, 0), 1.0f },
+ { ImGuiKey_Apostrophe, "'", "\"", 0, ImVec2(11, 2), 1.0f },
+ { ImGuiKey_Comma, ",", "<", 0, ImVec2(8, 3), 1.0f },
+ { ImGuiKey_Minus, "-", "_", 0, ImVec2(11, 0), 1.0f},
+ { ImGuiKey_Period, ".", ">", 0, ImVec2(9, 3), 1.0f },
+ { ImGuiKey_Slash, "/", "?", 0, ImVec2(10, 3), 1.0f },
+ { ImGuiKey_Semicolon, ";", ":", 0, ImVec2(10, 2), 1.0f },
+ { ImGuiKey_Equal, "=", "+", 0, ImVec2(12, 0), 1.0f },
+ { ImGuiKey_LeftBracket, "[", "{", 0, ImVec2(11, 1), 1.0f },
+ { ImGuiKey_Backslash, "\\","|", 0, ImVec2(13, 1), 1.5f },
+ { ImGuiKey_RightBracket, "]", "}", 0, ImVec2(12, 1), 1.0f },
+ { ImGuiKey_GraveAccent, "`", "~", 0, ImVec2(0, 0), 1.0f },
+ { ImGuiKey_CapsLock, "Caps", "", 0, ImVec2(0, 2), 1.75f },
+ { ImGuiKey_ScrollLock, "\0", "", 0, ImVec2(0, 0), 1.0f }, // unused
+ { ImGuiKey_NumLock, "\0", "", 0, ImVec2(0, 0), 1.0f }, //
+ { ImGuiKey_PrintScreen, "\0", "", 0, ImVec2(0, 0), 1.0f }, //
+ { ImGuiKey_Pause, "\0", "", 0, ImVec2(0, 0), 1.0f }, //
+ { ImGuiKey_Keypad0, "0", "", 3, ImVec2(0, 4), 2.0f },
+ { ImGuiKey_Keypad1, "1", "", 3, ImVec2(0, 3), 1.0f },
+ { ImGuiKey_Keypad2, "2", "", 3, ImVec2(1, 3), 1.0f },
+ { ImGuiKey_Keypad3, "3", "", 3, ImVec2(2, 3), 1.0f },
+ { ImGuiKey_Keypad4, "4", "", 3, ImVec2(0, 2), 1.0f },
+ { ImGuiKey_Keypad5, "5", "", 3, ImVec2(1, 2), 1.0f },
+ { ImGuiKey_Keypad6, "6", "", 3, ImVec2(2, 2), 1.0f },
+ { ImGuiKey_Keypad7, "7", "", 3, ImVec2(0, 1), 1.0f },
+ { ImGuiKey_Keypad8, "8", "", 3, ImVec2(1, 1), 1.0f },
+ { ImGuiKey_Keypad9, "9", "", 3, ImVec2(2, 1), 1.0f },
+ { ImGuiKey_KeypadDecimal, ".", "", 3, ImVec2(2, 4), 1.0f },
+ { ImGuiKey_KeypadDivide, "/", "", 3, ImVec2(1, 0), 1.0f },
+ { ImGuiKey_KeypadMultiply, "*", "", 3, ImVec2(2, 0), 1.0f },
+ { ImGuiKey_KeypadSubtract, "-", "", 3, ImVec2(3, 0), 1.0f },
+ { ImGuiKey_KeypadAdd, "+", "", 3, ImVec2(3, 1), -2.0f }, // long keys!
+ { ImGuiKey_KeypadEnter, "Ent", "", 3, ImVec2(3, 3), -2.0f },
+ { ImGuiKey_KeypadEqual, "", "", 3, ImVec2(0, 0), 1.0f } // unused
+};
+
+static char *KeyModeTitles[] = {
+ "All",
+ "Viewport",
+ "Timeline",
+ "Graph",
+ "Brush"
+};
+
+static char *KeyModText[] = {
+ "ERROR",
+ "Ctrl",
+ "Alt",
+ "Shift",
+ "Ctrl + Shift"
+};
+
+static ImVec2 SectorOffset[4] = { ImVec2(0, 1.5), ImVec2(0, 0) , ImVec2(15.5, 1.5), ImVec2(19, 1.5) };
+
diff --git a/src/include/layer.h b/src/include/layer.h
new file mode 100644
index 0000000..85d980d
--- /dev/null
+++ b/src/include/layer.h
@@ -0,0 +1,50 @@
+static block_layer *
+Layer_Init(project_data *File, memory *Memory);
+
+static void
+Layer_Delete(project_data *File, project_state *State, memory *Memory, uint32 Index);
+
+static layer_transforms
+Layer_GetTransforms(block_layer *Layer);
+
+static int
+Layer_GetTopOffset(project_data *File, memory *Memory);
+
+static void
+Layer_UpdateMasksEffects(project_state *State, block_layer *Layer, memory *Memory, void *EffectBitmapAddress,
+ int Width, int Height, int BytesPerPixel);
+
+static void
+Layer_ToggleChannel(project_data *File, memory *Memory, int32 a);
+
+static void
+Layer_Select(memory *Memory, project_state *State, int32 i);
+
+static void
+Layer_Select_RecurseUp(memory *Memory, project_state *State, int32 i, int16 RecursionIdx[MAX_PRECOMP_RECURSIONS], uint32 Recursions);
+
+static void
+Layer_DeselectAll(project_data *File, project_state *State, memory *Memory);
+
+static bool32
+Layer_LoopChannels(project_state *State, memory *Memory, sorted_property_array **SortedProperty, uint16 **SortedKeyframe, block_layer *Layer,
+ property_channel **Property, block_effect **EffectOut, int *h, int *c, int *p);
+
+static void
+Layer_ToggleAllChannels(project_state *State, memory *Memory, block_layer *Layer,
+ sorted_comp_array *SortedCompStart, sorted_layer_array *SortedLayerStart,
+ sorted_property_array *SortedPropertyStart, uint16 *SortedKeyframeArray);
+
+static void
+Layer_Select_Traverse(uint16 PrincipalCompIndex, memory *Memory, project_state *State, int32 IndexToFind, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray,
+ int16 RecursionIdx[MAX_PRECOMP_RECURSIONS], int32 *Recursions);
+
+static v2
+Layer_TraverseForPoint(project_data *File, project_state *State, memory *Memory, v2 PrincipalCompUV, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray);
+
+static int32
+Layer_TestSelection(memory *Memory, project_state *State, ui *UI, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, uint16 PrincipalIndex);
+
+static void
+Layer_RecursiveDeselect(memory *Memory, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, uint16 TargetIndex, uint16 PrincipalIndex);
+
diff --git a/src/include/main.h b/src/include/main.h
new file mode 100644
index 0000000..3c7ff83
--- /dev/null
+++ b/src/include/main.h
@@ -0,0 +1,686 @@
+enum instruction_mode {
+ instruction_mode_scalar,
+#if ARM
+ instruction_mode_neon,
+#else
+ instruction_mode_sse,
+ instruction_mode_avx
+#endif
+};
+
+static char* BlendmodeNames[] = {
+ "Normal",
+ "Multiply",
+ "Color Burn",
+ "Linear Burn",
+ "Add",
+ "Screen",
+ "Overlay",
+ "Soft Light",
+ "Hard Light",
+ "Subtract",
+ "Divide",
+ "Difference"
+};
+
+enum blend_mode
+{
+ blend_normal,
+ blend_multiply,
+ blend_colorburn,
+ blend_linearburn,
+ blend_add,
+ blend_screen,
+ blend_overlay,
+ blend_softlight,
+ blend_hardlight,
+ blend_subtract,
+ blend_divide,
+ blend_difference
+};
+
+#define STRING_SIZE (1024 - sizeof(uint8)) // TODO(fox): Paths above STRING_SIZE length aren't handled properly.
+struct block_string {
+ uint8 Occupied;
+ char Char[STRING_SIZE];
+};
+
+struct bitmap_cache_status
+{
+ uint32 Block_End;
+};
+
+enum cache_entry_type
+{
+ cache_entry_type_assert,
+ cache_entry_type_comp,
+ cache_entry_type_source
+};
+
+struct cache_entry
+{
+ uint8 IsOccupied;
+ uint8 IsCached;
+ uint64 CycleTime;
+ uint32 Block_StartIndex;
+ enum cache_entry_type Type;
+ uint32 TypeInfo;
+ uint32 TypeInfo_Sub;
+};
+
+enum interpolation_type
+{
+ interpolation_type_linear,
+ interpolation_type_bezier,
+ interpolation_type_hold
+};
+
+struct bezier_point {
+ uint8 Occupied;
+ v2 Pos[3];
+ interpolation_type Type;
+ bool32 IsSelected;
+ uint8 PointSelect[3];
+ uint8 Color;
+};
+
+struct block_bezier {
+ uint8 Occupied;
+ bezier_point Point[MAX_KEYFRAMES_PER_BLOCK];
+};
+
+enum selection_type
+{
+ selection_type_none,
+ selection_type_layer,
+ selection_type_keyframe
+};
+
+struct clipboard_channel {
+ void *Name;
+ uint16 LayerOffset;
+ uint16 KeyframeCount;
+};
+
+struct clipboard_contents {
+ selection_type Type;
+ clipboard_channel Channel[16];
+ uint16 ChannelCount;
+};
+
+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 render_state
+{
+ struct layer_bitmap_state Bitmap[MAX_LAYERS];
+ cache_entry Entry[2048];
+};
+
+struct render_queue_item
+{
+ bool32 Type;
+ v2 Pos;
+};
+
+struct render_queue
+{
+ uint16 Playhead;
+ uint16 CurrentIdx;
+ render_queue_item Item[512];
+};
+
+enum focused_window
+{
+ focus_viewport,
+ focus_properties,
+ focus_timeline
+};
+
+struct sorted_property_array
+{
+ uint32 MinYIndex;
+ uint32 MaxYIndex;
+};
+
+struct sorted_comp_array
+{
+ uint32 LayerCount;
+ uint32 CurrentSortIndex; // Used intermediately in the sorting algorithm
+};
+
+struct sorted_layer_array
+{
+ uint16 Block_Layer_Index;
+ real32 SortedOffset;
+ uint16 Sorted_Effect_Index[MAX_EFFECTS];
+ uint16 SortedPropertyStart;
+ uint16 SortedKeyframeStart;
+};
+
+struct sorted_file
+{
+ sorted_comp_array *CompArray;
+ sorted_layer_array *LayerArray;
+ sorted_property_array *PropertyStart;
+ uint16 *PropertyArray;
+ uint16 *SourceArray; // sorted by 'recency,' wip for stablediffusion stuff
+ uint16 TempSourceCount;
+ uint64 Layer_SortSize;
+ uint64 Property_SortSize;
+ uint64 Source_SortSize;
+};
+
+enum timeline_mode
+{
+ timeline_mode_default,
+ timeline_mode_graph
+};
+
+struct pen_state {
+ bool32 IsActive;
+};
+
+struct brush_state
+{
+ ImVec2 UIPos; // Initial position when ctrl is held
+ real32 Size = 256; // Maxes at 1024 for now
+ real32 Hardness = 0.55f; // From 1 to 100
+ real32 Spacing = 1.0f;
+ bool32 EraseMode = 0;
+ GLuint GLTexture;
+ v2 PrevPos;
+ void *PaintBuffer;
+ void *TransientBitmap;
+ uint32 LayerToPaint_Index = -1;
+ rectangle CacheBounds = { 99999, 99999, -99999, -99999 };
+};
+
+enum interact_type
+{
+ interact_type_none,
+ interact_type_timeline_scrub,
+ interact_type_slider_scrub,
+ interact_type_layer_move,
+ interact_type_layer_timeadjust,
+ interact_type_viewport_transform,
+ interact_type_keyframe_move,
+ interact_type_keyframe_scale,
+ interact_type_keyframe_rotate,
+ interact_type_brush
+};
+
+char *ToolName[] {
+ "Move",
+ "Crop",
+ "Brush",
+ "Pen"
+};
+
+enum tool {
+ tool_default,
+ tool_crop,
+ tool_brush,
+ tool_pen,
+ tool_count
+};
+
+struct interact_transform
+{
+ v2 Min;
+ v2 Max;
+ real32 Radians;
+ v2 Position;
+ real32 Scale = 1.0f;
+ ImVec2 OGPos;
+ uint32 TransformMode;
+};
+
+enum hotkey_input
+{
+ hotkey_none,
+ hotkey_newpaintlayer,
+ hotkey_newlayerfromsource,
+ hotkey_deletelayer,
+ hotkey_undo,
+ hotkey_redo,
+};
+
+enum property_display_type
+{
+ property_display_type_standard,
+ property_display_type_blendmode,
+ property_display_type_color
+};
+
+struct header_property
+{
+ char *Name;
+ real32 DefaultValue;
+ property_display_type DisplayType;
+ real32 MinVal;
+ real32 MaxVal;
+ bool32 AlwaysInteger;
+
+};
+
+struct gl_effect_layer {
+ bool32 Initialized;
+ GLuint Texture;
+ GLuint FramebufferObject;
+ uint32 Color_Renderbuffer;
+ uint32 Stencil_Renderbuffer;
+};
+
+
+enum effect_display_type
+{
+ effect_display_type_standard,
+ effect_display_type_levels,
+ effect_display_type_curves
+};
+
+struct block_effect
+{
+ uint8 Occupied;
+ char ID[8];
+ bool32 IsToggled;
+ uint32 Block_Property_Index[MAX_PROPERTIES_PER_EFFECT];
+ real32 ExtraData[16];
+};
+
+struct header_effect
+{
+ char *Name;
+ char *ID; // Eight-letter string that's used in the actual file
+ void (*func)(real32 *, int, int, int, void *, uint16);
+ uint16 PropertyStartIndex;
+ uint16 Property_Count;
+ effect_display_type DisplayType;
+ bool32 UseGL;
+ uint32 GLShaderIndex;
+};
+
+enum imgui_popups
+{
+ popup_none,
+ popup_saveas,
+ popup_keybinds
+};
+
+struct project_state
+{
+ bool32 UpdateKeyframes = 0;
+ bool32 UpdateFrame = 1; // only refreshes frame; set UpdateKeyframes to update animation
+ bool32 DebugDisableCache = 1;
+ uint32 CachedFrameCount;
+
+ uint64 HotFramePerf = 0;
+
+ uint32 AVCount;
+
+ render_state Render;
+ render_queue Queue;
+
+ int32 Frame_Current;
+ tool Tool = tool_default;
+ // GLuint ToolIconTex[(int)tool_count];
+ pen_state Pen = {};
+ brush_state Brush;
+
+#if STABLE
+ int32 CurlActive = 0;
+ char JSONPayload[1024*1024*4];
+ real32 SDPercentDone;
+ real32 SDTimeEstimate;
+ real64 SDTimer;
+#endif
+
+ header_effect Effect[128];
+ header_property Property[512];
+ uint16 Playhead_Effect;
+ uint16 Playhead_Property;
+
+ int32 PreviewLayer = -1;
+ int32 PreviewSource = -1;
+
+ hotkey_input HotkeyInput;
+
+ void *Dump1;
+ void *Dump2;
+
+ char DummyName[512];
+ char DummyName2[512];
+
+ bool32 IsRunning = 1;
+ bool32 IsPlaying;
+ bool32 PlayAudio;
+ int32 FramePlayingCount;
+ bool32 FirstFrame = 1;
+ int32 AudioLayerIndex = -1;
+
+ void *ClipboardBuffer;
+ uint64 ClipboardSize;
+
+ int16 MostRecentlySelectedLayer = -1;
+
+ // NOTE(fox): Try to use this only where you actually need it (the
+ // ambiguous case of copying keyframes versus layers), since this state
+ // transfer will get buggy if you expand it to everything.
+ selection_type RecentSelectionType = selection_type_none;
+
+ interact_type Interact_Active;
+ int32 Interact_Modifier;
+ real32 Interact_Offset[12];
+ void *Interact_Address;
+
+ int32 Initializing = 3;
+
+ int32 MsgTime; // currently in "frames"
+ char *Msg;
+
+ imgui_popups ImGuiPopups;
+ char Filename[512];
+
+ ImGuiTextFilter filter; // This filter API is pretty ballin'.
+ bool32 RerouteEffects; // Allows shift+space hotkey to gain focus on the effects panel.
+
+ ImDrawListSplitter Test;
+ ImDrawListSplitter Split_KeybindUI;
+
+ int32 Warp_X = 0;
+ int32 Warp_Y = 0;
+ bool32 Warp_WantSetPos = false;
+ ImVec2 Warp_PositionToSet;
+ real32 Warp_PositionInitial;
+ int32 Warp_Direction;
+
+ uint32 InteractTransformMode; // Whether a drag on the Shift+T UI is scale (1), rotation (2), or position (3).
+
+ timeline_mode TimelineMode;
+
+ bool32 BoxSelect;
+
+ focused_window FocusedWindow; // Convenience for adding window-specific hotkeys.
+ bool32 SetFocus;
+ v2 TempZoomRatio = V2(1, 1);
+};
+
+// UI info that's saved to the file and is not part of the history tree
+struct ui
+{
+ ImVec2 CompZoom; // In screen pixels, not percentage.
+ ImVec2 CompPos;
+
+ // Under 1 is zoomed in!
+ ImVec2 TimelinePercentZoomed;
+ ImVec2 TimelinePercentOffset;
+
+ ImVec2 GraphZoomSize;
+ ImVec2 GraphMoveSize;
+
+ v4 Color = {1, 1, 1, 1};
+ v4 AltColor = {0, 0, 0, 1};
+ bool32 IsPrimary;
+
+#if STABLE
+ sd_state SD;
+ bool32 StableEnabled = 0;
+#endif
+
+ ImU32 LayerColors[16] = {
+ 0xff8b1f1f,
+ 0xffc25909,
+ 0xff57c20a,
+ 0xff8ee6da,
+ 0xffa48fb7,
+ 0xffd14061,
+ 0xff38b683,
+ 0xff3fdbe5,
+ 0xffc9c9c9,
+ 0xff978489,
+ 0xfffaf5ab,
+ 0xff101010,
+ 0xffa024ca,
+ 0xfffae920,
+ 0xff208dfa,
+ 0xfffa2051
+ };
+};
+
+
+struct project_data
+{
+ uint8 Occupied;
+ uint16 Layer_Count;
+ uint16 Source_Count;
+ uint16 Comp_Count;
+ uint16 PrincipalCompIndex;
+ ui UI;
+};
+
+struct block_composition
+{
+ uint8 Occupied;
+
+ uint16 Name_String_Index;
+
+ uint16 Width;
+ uint16 Height;
+ uint16 BytesPerPixel;
+ uint16 FPS;
+
+ uint32 Frame_Count;
+ int32 Frame_Start;
+ int32 Frame_End;
+};
+
+struct layer_transforms
+{
+ real32 x;
+ real32 y;
+ real32 ax;
+ real32 ay;
+ real32 rotation;
+ real32 scale;
+};
+
+enum source_type {
+ source_type_none,
+ source_type_principal,
+ source_type_principal_temp,
+ source_type_file
+};
+
+struct block_source
+{
+ uint8 Occupied;
+
+ bool32 IsSelected;
+
+ uint16 Path_String_Index;
+ uint16 Name_String_Index;
+
+ // Only used for type_principal
+ uint16 Bitmap_Index;
+
+ uint16 Width;
+ uint16 Height;
+ uint16 BytesPerPixel;
+
+ // LibAV specific
+ real32 FPS;
+ bool32 HasAudio;
+ bool32 HasVideo;
+
+ uint32 RelativeTimestamp;
+ GLuint ThumbnailTex;
+
+ source_type Type;
+};
+
+struct property_channel {
+ uint8 Occupied;
+ uint16 Block_Bezier_Index[MAX_KEYFRAME_BLOCKS];
+ uint16 Block_Bezier_Count;
+ uint16 Keyframe_Count;
+
+ int32 Identifier;
+
+ real32 CurrentValue;
+ real32 MaxVal;
+ real32 MinVal;
+ bool32 AlwaysInteger;
+ real32 ScrubVal; // increment when dragging on sliders, etc.
+
+ bool32 IsToggled;
+};
+
+char *DefaultChannel[] = { "X Position", "Y Position", "Anchor X", "Anchor Y",
+ "Rotation", "Scale", "Opacity", "Frame Number" };
+
+struct block_layer {
+ uint8 Occupied;
+
+ bool32 IsPrecomp;
+ bool32 Precomp_Toggled;
+ uint16 Block_Source_Index; // also used for precomp
+ uint16 Block_String_Index;
+ uint16 Block_Composition_Index;
+
+ uint16 Block_Mask_Index[MAX_MASKS];
+ uint16 Block_Mask_Count;
+
+ uint16 Block_Effect_Index[MAX_EFFECTS];
+ 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;
+ bool32 IsVisible;
+ bool32 IsAdjustment;
+
+ int32 Frame_Start;
+ int32 Frame_End;
+
+ real32 Vertical_Offset;
+ real32 Vertical_Height = 1;
+
+ uint16 ColIndex;
+};
+
+struct render_byte_info {
+ uint32 MaskPixel;
+ uint32 ByteOffset;
+ uint32 Bits;
+ real32 Normalized;
+};
+
+struct transform_info {
+ real32 XAxisPX;
+ real32 XAxisPY;
+ real32 YAxisPX;
+ real32 YAxisPY;
+
+ real32 LayerWidth;
+ real32 LayerHeight;
+ real32 LayerBytesPerPixel;
+ real32 LayerPitch;
+ render_byte_info LayerBits;
+
+ real32 BufferWidth;
+ real32 BufferHeight;
+ real32 BufferBytesPerPixel;
+ real32 BufferPitch;
+ render_byte_info BufferBits;
+
+ real32 LayerOpacity;
+ real32 OriginX;
+ real32 OriginY;
+ blend_mode BlendMode;
+
+ bool32 IsAdjustment;
+
+ rectangle ClipRect;
+ void *SourceBuffer;
+};
+
+struct direct_info {
+ real32 BufferWidth;
+ real32 BufferHeight;
+ real32 BufferBytesPerPixel;
+ real32 BufferPitch;
+ render_byte_info BufferBits;
+
+ real32 Opacity;
+
+ blend_mode BlendMode;
+ rectangle ClipRect;
+ void *SourceBuffer;
+
+ bool32 SwapActive;
+ bool32 OnlyBlendAlpha;
+};
+
+struct brush_info {
+ uint32 BrushLength;
+ rectangle LayerBounds;
+ uint32 LayerPitch;
+ uint32 BrushPitch;
+ int32 ExtraX;
+ int32 ExtraY;
+ render_byte_info LayerBits;
+ render_byte_info BrushBits;
+ int BytesPerPixel;
+ int SourceWidth;
+ int SourceBytesPerPixel;
+ void *SourceBuffer;
+ void *BrushBuffer;
+ real32 R_Brush;
+ real32 G_Brush;
+ real32 B_Brush;
+ real32 A_Brush;
+ bool32 EraseMode;
+ uint8 *BrushRow;
+};
+
+enum render_type {
+ render_type_main,
+ render_type_notransform,
+ render_type_notransform_swap,
+ render_type_brush
+};
+
+struct render_entry {
+ void *RenderData;
+ void *OutputBuffer;
+ render_type RenderType;
+ rectangle RenderRegion;
+};
+
diff --git a/src/include/memory.h b/src/include/memory.h
new file mode 100644
index 0000000..dab6ed4
--- /dev/null
+++ b/src/include/memory.h
@@ -0,0 +1,71 @@
+enum memory_table_list {
+
+ P_AVInfo,
+ P_UndoBuffer,
+ P_MiscCache,
+
+ F_File,
+ F_Precomps,
+ F_Layers,
+ F_Sources,
+ F_Properties,
+ F_Bezier,
+ F_Effects,
+ F_Strings,
+ F_PrincipalBitmaps,
+
+ B_Thumbnails,
+ B_ScratchSpace,
+ B_CacheEntries,
+ B_CachedBitmaps,
+};
+
+struct memory_table {
+ char *Name;
+ void *Address;
+ uint64 Size;
+ uint32 Block_ElementSize;
+};
+
+struct global_memory {
+ void *Address;
+ uint64 CurrentPosition;
+ uint64 Size;
+};
+
+enum history_action_type {
+ action_type_swap,
+ action_type_swap_bitmap,
+ action_type_shift
+};
+
+struct history_action {
+ memory_table_list TableName;
+ history_action_type Type;
+ uint64 Size;
+ uint64 ByteOffset;
+ uint64 ShiftAmount; // Only for type_shift
+ int16 Direction; // Only for type_shift
+};
+
+struct history_entry {
+ char *Name;
+ uint16 NumberOfActions;
+};
+
+struct history_entry_list {
+ history_entry Entry[256];
+ history_action Action[1024];
+ uint16 NumberOfEntries;
+ uint16 EntryPlayhead;
+};
+
+struct memory {
+ memory_table Slot[16];
+ history_entry_list History;
+ uint64 ScratchPos;
+ uint32 EntryCount;
+ bool32 IsFileSaved;
+ bool32 PurgeCache;
+};
+
diff --git a/src/include/my_math.h b/src/include/my_math.h
new file mode 100644
index 0000000..92d43b7
--- /dev/null
+++ b/src/include/my_math.h
@@ -0,0 +1,762 @@
+#define PI 3.141592653589793238
+
+union v2
+{
+ struct
+ {
+ real32 x, y;
+ };
+ real32 E[2];
+};
+
+union v2i
+{
+ struct
+ {
+ int32 x, y;
+ };
+ int32 E[2];
+};
+
+union v3
+{
+ struct
+ {
+ real32 r, g, b;
+ };
+ int32 E[3];
+};
+
+union v4
+{
+ struct
+ {
+ real32 r, g, b, a;
+ };
+ real32 E[4];
+};
+
+inline v2 V2(real32 x, real32 y)
+{
+ v2 Result;
+
+ Result.x = x;
+ Result.y = y;
+
+ return(Result);
+}
+
+inline v2 V2(real32 x)
+{
+ v2 Result;
+
+ Result.x = x;
+ Result.y = x;
+
+ return(Result);
+}
+
+inline v2 V2(ImVec2 A)
+{
+ v2 Result;
+
+ Result.x = A.x;
+ Result.y = A.y;
+
+ return(Result);
+}
+
+inline ImVec2 V2(v2 A)
+{
+ struct ImVec2 Result;
+
+ Result.x = A.x;
+ Result.y = A.y;
+
+ return(Result);
+}
+
+inline v2i V2i(int32 x, int32 y)
+{
+ v2i Result;
+
+ Result.x = x;
+ Result.y = y;
+
+ return(Result);
+}
+
+inline v3 V3(real32 a)
+{
+ v3 Result;
+
+ Result.r = a;
+ Result.g = a;
+ Result.b = a;
+
+ return(Result);
+}
+
+inline v4 V4(real32 r)
+{
+ v4 Result;
+
+ Result.r = r;
+ Result.g = r;
+ Result.b = r;
+ Result.a = r;
+
+ return(Result);
+}
+
+inline v4 powv4(v4 Col, real32 i)
+{
+ v4 Result;
+
+ Result.r = pow(Col.r, i);
+ Result.g = pow(Col.g, i);
+ Result.b = pow(Col.b, i);
+ Result.a = pow(Col.a, i);
+
+ return(Result);
+}
+
+inline v4 powv4(v4 Col, v4 i)
+{
+ v4 Result;
+
+ Result.r = pow(Col.r, i.r);
+ Result.g = pow(Col.g, i.g);
+ Result.b = pow(Col.b, i.b);
+ Result.a = pow(Col.a, i.a);
+
+ return(Result);
+}
+
+inline v4 V4(v3 r, real32 a)
+{
+ v4 Result;
+
+ Result.r = r.r;
+ Result.g = r.g;
+ Result.b = r.b;
+ Result.a = a;
+
+ return(Result);
+}
+
+inline v4 V4(real32 r, real32 g, real32 b, real32 a)
+{
+ v4 Result;
+
+ Result.r = r;
+ Result.g = g;
+ Result.b = b;
+ Result.a = a;
+
+ return(Result);
+}
+
+inline v4 ClipV4(v4 A)
+{
+ v4 Result;
+ if (A.r < 0.0f) {
+ Result.r = 0.0f;
+ } else if (A.r > 1.0f) {
+ Result.r = 1.0f;
+ } else {
+ Result.r = A.r;
+ }
+
+ if (A.g < 0.0f) {
+ Result.g = 0.0f;
+ } else if (A.g > 1.0f) {
+ Result.g = 1.0f;
+ } else {
+ Result.g = A.g;
+ }
+
+ if (A.b < 0.0f) {
+ Result.b = 0.0f;
+ } else if (A.b > 1.0f) {
+ Result.b = 1.0f;
+ } else {
+ Result.b = A.b;
+ }
+
+ if (A.a < 0.0f) {
+ Result.a = 0.0f;
+ } else if (A.a > 1.0f) {
+ Result.a = 1.0f;
+ } else {
+ Result.a = A.a;
+ }
+
+ return(Result);
+}
+
+
+v2i operator+(v2i A, v2i B)
+{
+ v2i Result;
+
+ Result.x = A.x + B.x;
+ Result.y = A.y + B.y;
+
+ return(Result);
+}
+
+v2 operator/(v2 A, real32 B)
+{
+ v2 Result;
+
+ Result.x = A.x / B;
+ Result.y = A.y / B;
+
+ return Result;
+}
+
+
+
+v4 operator+(v4 A, v4 B)
+{
+ v4 Result;
+
+ Result.r = A.r + B.r;
+ Result.g = A.g + B.g;
+ Result.b = A.b + B.b;
+ Result.a = A.a + B.a;
+
+ return(Result);
+}
+
+v4 operator-(v4 A, v4 B)
+{
+ v4 Result;
+
+ Result.r = A.r - B.r;
+ Result.g = A.g - B.g;
+ Result.b = A.b - B.b;
+ Result.a = A.a - B.a;
+
+ return(Result);
+}
+
+v4 operator-(real32 A, v4 B)
+{
+ v4 Result;
+
+ Result.r = A - B.r;
+ Result.g = A - B.g;
+ Result.b = A - B.b;
+ Result.a = A - B.a;
+
+ return(Result);
+}
+
+v4 operator-(v4 A, real32 B)
+{
+ v4 Result;
+
+ Result.r = A.r - B;
+ Result.g = A.g - B;
+ Result.b = A.b - B;
+ Result.a = A.a - B;
+
+ return(Result);
+}
+
+v4 operator*(v4 A, v4 B)
+{
+ v4 Result;
+
+ Result.r = A.r * B.r;
+ Result.g = A.g * B.g;
+ Result.b = A.b * B.b;
+ Result.a = A.a * B.a;
+
+ return(Result);
+}
+
+v4 operator/(v4 A, v4 B)
+{
+ v4 Result;
+
+ Result.r = A.r / B.r;
+ Result.g = A.g / B.g;
+ Result.b = A.b / B.b;
+ Result.a = A.a / B.a;
+
+ return(Result);
+}
+
+v4 operator/(real32 A, v4 B)
+{
+ v4 Result;
+
+ Result.r = A / B.r;
+ Result.g = A / B.g;
+ Result.b = A / B.b;
+ Result.a = A / B.a;
+
+ return(Result);
+}
+
+v4 operator*(v4 A, real32 B)
+{
+ v4 Result;
+
+ Result.r = A.r * B;
+ Result.g = A.g * B;
+ Result.b = A.b * B;
+ Result.a = A.a * B;
+
+ return(Result);
+}
+
+v4 operator*(real32 B, v4 A)
+{
+ v4 Result;
+
+ Result.r = A.r * B;
+ Result.g = A.g * B;
+ Result.b = A.b * B;
+ Result.a = A.a * B;
+
+ return(Result);
+}
+
+v2 operator-(v2 A, v2i B)
+{
+ v2 Result;
+
+ Result.x = A.x - (real32)B.x;
+ Result.y = A.y - (real32)B.y;
+
+ return(Result);
+}
+
+v2 operator/(v2 A, v2 B)
+{
+ v2 Result;
+
+ Result.x = A.x / B.x;
+ Result.y = A.y / B.y;
+
+ return(Result);
+}
+
+v2i operator-(v2i A, v2i B)
+{
+ v2i Result;
+
+ Result.x = A.x - B.x;
+ Result.y = A.y - B.y;
+
+ return(Result);
+}
+
+v2i operator-(v2i A, int16 B)
+{
+ v2i Result;
+
+ Result.x = A.x - B;
+ Result.y = A.y - B;
+
+ return(Result);
+}
+
+v2i operator+(v2i A, int16 B)
+{
+ v2i Result;
+
+ Result.x = A.x + B;
+ Result.y = A.y + B;
+
+ return(Result);
+}
+
+v2 operator*(real32 A, v2 B)
+{
+ v2 Result;
+
+ Result.x = A * B.x;
+ Result.y = A * B.y;
+
+ return(Result);
+}
+
+v2 operator*(v2 A, real32 B)
+{
+ v2 Result;
+
+ Result.x = A.x * B;
+ Result.y = A.y * B;
+
+ return(Result);
+}
+
+
+v2 operator-(v2 A, v2 B)
+{
+ v2 Result;
+
+ Result.x = A.x - B.x;
+ Result.y = A.y - B.y;
+
+ return(Result);
+}
+
+v2 operator-(v2 A, real32 B)
+{
+ v2 Result;
+
+ Result.x = A.x - B;
+ Result.y = A.y - B;
+
+ return(Result);
+}
+
+v2 operator-(v2 A)
+{
+ v2 Result;
+
+ Result.x = -A.x;
+ Result.y = -A.y;
+
+ return(Result);
+}
+
+v2 operator+(v2 A, v2 B)
+{
+ v2 Result;
+
+ Result.x = A.x + B.x;
+ Result.y = A.y + B.y;
+
+ return(Result);
+}
+
+v2 operator*(v2 A, v2 B)
+{
+ v2 Result;
+
+ Result.x = A.x * B.x;
+ Result.y = A.y * B.y;
+
+ return(Result);
+}
+
+struct rectangle
+{
+ v2i Min;
+ v2i Max;
+};
+
+inline real32
+Min(real32 A, real32 B)
+{
+ return (A > B) ? B : A;
+}
+
+inline real32
+Max(real32 A, real32 B)
+{
+ return (A > B) ? A : B;
+}
+
+inline bool32
+TestRectangle(rectangle Rect, v2i Test)
+{
+ bool32 Result = (Test.x > Rect.Min.x && Test.x < Rect.Max.x &&
+ Test.y > Rect.Min.y && Test.y < Rect.Max.y);
+ return(Result);
+}
+
+inline bool32
+TestRectangle(ImVec2 Min, ImVec2 Max, ImVec2 Test)
+{
+ bool32 Result = (Test.x > Min.x && Test.x < Max.x &&
+ Test.y > Min.y && Test.y < Max.y);
+ return(Result);
+}
+
+inline rectangle
+ClipRectangle(rectangle Rect, rectangle BoundRect)
+{
+ if(Rect.Min.x < BoundRect.Min.x)
+ {
+ Rect.Min.x = BoundRect.Min.x;
+ }
+ if(Rect.Min.y < BoundRect.Min.y)
+ {
+ Rect.Min.y = BoundRect.Min.y;
+ }
+ if(Rect.Max.x > BoundRect.Max.x)
+ {
+ Rect.Max.x = BoundRect.Max.x;
+ }
+ if(Rect.Max.y > BoundRect.Max.y)
+ {
+ Rect.Max.y = BoundRect.Max.y;
+ }
+ return(Rect);
+}
+
+inline rectangle
+VerifyMinMax(rectangle Rect)
+{
+ if(Rect.Min.x > Rect.Max.x)
+ {
+ int16 Temp = Rect.Max.x;
+ Rect.Max.x = Rect.Min.x;
+ Rect.Min.x = Temp;
+ }
+ if(Rect.Min.y > Rect.Max.y)
+ {
+ int16 Temp = Rect.Max.y;
+ Rect.Max.y = Rect.Min.y;
+ Rect.Min.y = Temp;
+ }
+ return(Rect);
+}
+
+inline int32
+RoundReal32ToInt32(real32 Real32)
+{
+ int32 Result = (int32)(Real32 + 0.5f);
+ return(Result);
+}
+
+inline uint32
+RoundReal32ToUint32(real32 Real32)
+{
+ uint32 Result = (uint32)(Real32 + 0.5f);
+ return(Result);
+}
+
+inline uint32
+ColToUint32(real32 B)
+{
+ uint32 Result = ((RoundReal32ToUint32(1 * 255.0f) << 24) |
+ (RoundReal32ToUint32(B * 255.0f) << 16) |
+ (RoundReal32ToUint32(B * 255.0f) << 8) |
+ (RoundReal32ToUint32(B * 255.0f) << 0));
+ return Result;
+}
+
+inline uint32
+ColToUint32(v4 Col)
+{
+ uint32 Result = ((RoundReal32ToUint32(Col.a * 255.0f) << 24) |
+ (RoundReal32ToUint32(Col.r * 255.0f) << 16) |
+ (RoundReal32ToUint32(Col.g * 255.0f) << 8) |
+ (RoundReal32ToUint32(Col.b * 255.0f) << 0));
+ return Result;
+}
+
+inline real32
+Square(real32 A)
+{
+ real32 Result = A * A;
+ return Result;
+}
+
+inline real32
+Inner(v2 A, v2 B)
+{
+ real32 Result = A.x * B.x + A.y * B.y;
+
+ return Result;
+}
+
+inline real32
+Inner(ImVec2 A, ImVec2 B)
+{
+ real32 Result = A.x * B.x + A.y * B.y;
+
+ return Result;
+}
+
+inline real32
+LengthSq(v2 A)
+{
+ real32 Result = Inner(A, A);
+ return Result;
+}
+
+inline uint32
+Floor(uint32 A, uint32 B)
+{
+ if (A < B) {
+ A = B;
+ }
+ return A;
+}
+
+inline uint32
+Ceil(uint32 A, uint32 B)
+{
+ if (A > B) {
+ A = B;
+ }
+ return A;
+}
+
+inline real32
+Floor(real32 A, real32 B)
+{
+ if (A < B) {
+ A = B;
+ }
+ return A;
+}
+
+inline real32
+Ceil(real32 A, real32 B)
+{
+ if (A > B) {
+ A = B;
+ }
+ return A;
+}
+
+inline bool32
+TestUV(v2 UV) {
+ return (UV.x <= 1.0f && UV.x >= 0.0f && UV.y <= 1.0f && UV.y >= 0.0f);
+}
+
+inline real32
+Clamp(real32 A, real32 B, real32 C)
+{
+ if (B < A) {
+ B = A;
+ }
+ if (B > C) {
+ B = C;
+ }
+ return B;
+}
+
+inline v4
+Clamp(real32 A, v4 B, real32 C)
+{
+ B.r = Clamp(A, B.r, C);
+ B.g = Clamp(A, B.g, C);
+ B.b = Clamp(A, B.b, C);
+ B.a = Clamp(A, B.a, C);
+ return B;
+}
+
+
+
+inline v4
+Lerp(v4 A, real32 t, v4 B)
+{
+ v4 Result = (1.0f - t)*A + t*B;
+
+ return Result;
+}
+
+inline v4
+Uint32ToCol(uint32 LayerPixel)
+{
+ uint8 A2 = (LayerPixel >> 24);
+ uint8 R2 = (LayerPixel >> 16);
+ uint8 G2 = (LayerPixel >> 8);
+ uint8 B2 = (LayerPixel >> 0);
+ v4 Color = {(real32)R2 / 255.0f,
+ (real32)G2 / 255.0f,
+ (real32)B2 / 255.0f,
+ (real32)A2 / 255.0f};
+ return Color;
+}
+
+inline v4
+Uint32ToCol8(uint32 LayerPixel)
+{
+ uint8 A2 = (LayerPixel >> 24);
+ uint8 B2 = (LayerPixel >> 16);
+ uint8 G2 = (LayerPixel >> 8);
+ uint8 R2 = (LayerPixel >> 0);
+ v4 Color = {(real32)R2,
+ (real32)G2,
+ (real32)B2,
+ (real32)A2};
+ return Color;
+}
+
+inline v4
+Uint32ToNormalizedCol(uint32 LayerPixel)
+{
+ uint8 A2 = (LayerPixel >> 24);
+ uint8 R2 = (LayerPixel >> 16);
+ uint8 G2 = (LayerPixel >> 8);
+ uint8 B2 = (LayerPixel >> 0);
+
+ real32 R = R2 / 255.0f;
+ real32 G = G2 / 255.0f;
+ real32 B = B2 / 255.0f;
+ real32 A = A2 / 255.0f;
+
+ v4 Result = {R,G,B,A};
+
+ return Result;
+}
+
+inline real32
+Uint32ToNormalizedBW(uint32 LayerPixel)
+{
+ uint8 R2 = (LayerPixel >> 16);
+ uint8 G2 = (LayerPixel >> 8);
+ uint8 B2 = (LayerPixel >> 0);
+
+ real32 R = R2 / 255.0f;
+ real32 G = G2 / 255.0f;
+ real32 B = B2 / 255.0f;
+
+ real32 Result = (R + G + B) / 3.0f;
+
+ return Result;
+}
+
+inline uint32
+Col8ToUint32(v4 P)
+{
+ uint8 A2 = P.a;
+ uint8 R2 = P.r;
+ uint8 G2 = P.g;
+ uint8 B2 = P.b;
+ uint32 Result = ((A2 << 24) |
+ (R2 << 16) |
+ (G2 << 8) |
+ (B2 << 0));
+ return Result;
+}
+
+
+inline uint8
+ClipAdd(uint8 a, uint8 b)
+{
+ uint8 Result = 0;
+ int16 exp = (int16)a + b;
+ if (exp > 255) {
+ Result = 255;
+ } else if (exp < 0) {
+ Result = 0;
+ } else {
+ Result = a + b;
+ }
+ return Result;
+}
+
+inline real32 Normalize(real32 A)
+{
+ if (A > 1) {
+ A = 1.0f;
+ } else if (A < 0.0f) {
+ A = 0.0f;
+ }
+ return A;
+}
+
diff --git a/src/include/sharebuffer.h b/src/include/sharebuffer.h
new file mode 100644
index 0000000..c25deb2
--- /dev/null
+++ b/src/include/sharebuffer.h
@@ -0,0 +1,17 @@
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define SHAREDMEMORY_SIZE ((uint64_t)20*1024*1024)
+
+struct SharedMemoryInfo {
+ sem_t sem1;
+ sem_t sem2;
+ int16_t shared_framenumber;
+ char BitmapData;
+};
+
diff --git a/src/include/stable_diffusion.h b/src/include/stable_diffusion.h
new file mode 100644
index 0000000..3335796
--- /dev/null
+++ b/src/include/stable_diffusion.h
@@ -0,0 +1,33 @@
+
+
+// curl -X POST -H 'Content-Type: application/json' -i 'http://127.0.0.1:7860/sdapi/v1/txt2img' --data '{
+// "prompt": "cute dinosaur sticker with polka dots",
+// "steps": 50,
+// "sampler_index": "DDIM"
+// }'
+
+#define SD_LEN_PROMPT 256
+#define SD_LEN_ADDRESS 128
+
+// struct sd_mode
+// {
+// sd_mode_txt2txt,
+// sd_mode_txt2img
+// }
+
+struct sd_state
+{
+ bool32 Mode = 1;
+ char Prompt[256];
+ char NegPrompt[256];
+ char ServerAddress[128];
+ int32 Steps = 10;
+ int32 Width = 512;
+ int32 Height = 512;
+ int32 SamplerIndex = 0;
+ real32 CFG = 7;
+ int32 BatchSize = 1;
+ real32 DenoisingStrength = 0.4;
+ int32 Seed = -1;
+};
+
diff --git a/src/include/structs.h b/src/include/structs.h
new file mode 100644
index 0000000..fbb97ed
--- /dev/null
+++ b/src/include/structs.h
@@ -0,0 +1,5 @@
+struct effect;
+
+struct action_entry;
+struct action_entries;
+
diff --git a/src/include/undo.h b/src/include/undo.h
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/src/include/undo.h
@@ -0,0 +1,2 @@
+
+