summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFox Caminiti <fox@foxcam.net>2022-11-23 20:39:55 -0500
committerFox Caminiti <fox@foxcam.net>2022-11-23 20:39:55 -0500
commitfd315f15828b8537a48530c094ced845edc3a1d3 (patch)
treee4c028f1b33c7dfd8de24d2ad2331ef4547cc3d9
parent6799b157bae5654d77d0fc2685a1ef3e4a7d9f4c (diff)
effects reintroduction
-rw-r--r--createcalls.cpp87
-rw-r--r--effects.cpp665
-rw-r--r--effects_constructors.cpp107
-rw-r--r--effects_gl_shader.cpp57
-rw-r--r--effects_software.cpp216
-rw-r--r--functions.h4
-rw-r--r--gl_calls.cpp168
-rw-r--r--main.cpp152
-rw-r--r--main.h108
-rw-r--r--my_imgui_widgets.cpp300
-rw-r--r--prenderer.cpp1
-rw-r--r--strings.cpp53
12 files changed, 761 insertions, 1157 deletions
diff --git a/createcalls.cpp b/createcalls.cpp
index b6ce7e1..4d9ea1e 100644
--- a/createcalls.cpp
+++ b/createcalls.cpp
@@ -117,7 +117,16 @@ File_SaveAs(project_data *File, project_state *State, memory *Memory, char *File
return 1;
}
-
+static void
+Playhead_Increment(int32 *Frame_Current, int32 Frame_Start, int32 Frame_End, int32 Increment)
+{
+ *Frame_Current += Increment;
+ if (*Frame_Current >= Frame_End) {
+ *Frame_Current = Frame_Start;
+ }
+ // if (*Frame_Current < Frame_Start) {
+ // }
+}
static uint16
Source_Generate_Blank(project_data *File, project_state *State, memory *Memory, uint16 Width, uint16 Height, uint16 BytesPerPixel)
@@ -251,6 +260,10 @@ Bezier_Add(memory *Memory, property_channel *Property, bezier_point PointData)
}
}
+// static void
+// Property_InitFloat(char *Name, real32 Val, real32 ScrubVal, real32 MinVal = PROPERTY_REAL_MIN, real32 MaxVal = PROPERTY_REAL_MAX, bool32 AlwaysInteger = 0) {
+// {
+// }
static property_channel
Property_InitFloat(char *Name, real32 Val, real32 ScrubVal, real32 MinVal = PROPERTY_REAL_MIN, real32 MaxVal = PROPERTY_REAL_MAX, bool32 AlwaysInteger = 0) {
@@ -312,6 +325,78 @@ Layer_Interact_Evaluate(memory *Memory, project_state *State, uint16 Layer_Index
}
}
+static uint32
+Effect_Init(project_state *State, memory *Memory, uint32 EffectEntryIndex, int EffectCount)
+{
+ uint16 EffectAddressIndex = Memory_Block_AllocateNew(Memory, F_Effects);
+ block_effect *Effect = (block_effect *)Memory_Block_AddressAtIndex(Memory, F_Effects, EffectAddressIndex, 0);
+ Effect->Occupied = true;
+ header_effect *EffectHeader = &State->Effect[EffectEntryIndex];
+ String_Copy(Effect->ID, EffectHeader->ID, 8);
+ Effect->IsToggled = true;
+ Effect->Index = EffectCount;
+ for (int e = 0; e < EffectHeader->Property_Count; e++) {
+ Effect->Block_Property_Index[e] = Memory_Block_AllocateNew(Memory, F_Properties);
+ property_channel *Property = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[e], 0);
+ Property->Occupied = true;
+ header_property PropertyHeader = State->Property[EffectHeader->PropertyStartIndex + e];
+ Property->Name = PropertyHeader.Name;
+ Property->CurrentValue = PropertyHeader.DefaultValue;
+ Property->MinVal = PropertyHeader.MinVal;
+ Property->MaxVal = PropertyHeader.MaxVal;
+ }
+ return EffectAddressIndex;
+}
+
+
+static void
+Layer_UpdateMasksEffects(project_state *State, block_layer *Layer, memory *Memory, void *EffectBitmapAddress,
+ int Width, int Height, int BytesPerPixel)
+{
+ uint64 Size = Width*Height*BytesPerPixel;
+
+ // We need two of these: one with multisampling enabled and a
+ // non-multisampled one that we can blit to.
+ gl_effect_layer TestL = {};
+ gl_effect_layer TestM = {};
+
+ GL_UpdateTexture(&TestL, EffectBitmapAddress, Width, Height, BytesPerPixel, 0);
+ GL_UpdateTexture(&TestM, EffectBitmapAddress, Width, Height, BytesPerPixel, 1);
+
+ for (int i = 0; i < Layer->Block_Effect_Count; i++)
+ {
+ block_effect Effect = *(block_effect *)Memory_Block_AddressAtIndex(Memory, F_Effects, Layer->Block_Effect_Index[i]);
+ header_effect *EffectEntry = Effect_EntryFromID(State, Effect.ID);
+
+ if (Effect.IsToggled) {
+ real32 *Data = (real32 *)Memory_PushScratch(Memory, sizeof(real32) * 50);
+ for (int c = 0; c < EffectEntry->Property_Count; c++) {
+ property_channel *Property = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect.Block_Property_Index[c]);
+ Data[c] = Property->CurrentValue;
+ }
+ EffectEntry->func(Data, Width, Height, BytesPerPixel, EffectBitmapAddress, EffectEntry->GLShaderIndex);
+ Memory_PopScratch(Memory, sizeof(real32) * 50);
+ }
+ }
+ /*
+ if (Layer->NumberOfMasks) {
+ for (int i = 0; i < Layer->NumberOfMasks; i++) {
+ file_mask_header *MaskHeader = (file_mask_header *)((uint8 *)Layer + sizeof(file_layer) + MaskOffset);
+ if (MaskHeader->IsClosed && MaskHeader->IsToggled) {
+ mask_point *Point = (mask_point *)((uint8 *)MaskHeader + sizeof(file_mask_header));
+ Mask_TriangulateAndRasterize(TestM, TestL, Memory, MaskHeader, Point, Source->Width, Source->Height, Source->BytesPerPixel, EffectBitmapAddress);
+ }
+ }
+ Bitmap_StencilAlpha(SourceBitmapAddress, EffectBitmapAddress, Source->BytesPerPixel, Size);
+ }
+
+ Layer->OutputBitmapLocation = EffectBitmapAddress;
+ */
+
+ GL_DeleteHWBuffer(&TestL);
+ GL_DeleteHWBuffer(&TestM);
+}
+
static void
Layer_ToggleChannel(project_data *File, memory *Memory, int32 a)
{
diff --git a/effects.cpp b/effects.cpp
index ee84c5b..98d6984 100644
--- a/effects.cpp
+++ b/effects.cpp
@@ -1,666 +1,9 @@
-#include "effects.h"
-
#include "effects_software.cpp"
-//#include "effects_gl.cpp"
-
-static void Effect_GL_Levels(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]);
-static void Effect_GL_GaussianBlur(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[]);
static void
-Effect_DrawColor(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[])
-{
- Effect_Software_DrawColor(Source, BitmapInfo, Memory, Property);
-}
-
-static void
-Effect_Levels(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[])
-{
- if (!BitmapInfo->HistogramVals) {
- uint64 Size = Bitmap_CalcUnpackedBytes(Source->Info.Width, Source->Info.Height, Source->Info.BytesPerPixel);
- BitmapInfo->HistogramVals = AllocateMemory(Memory, (sizeof(uint32) * 5 * 256), P_MiscCache);
- Bitmap_CalcHistogram(BitmapInfo->HistogramVals, BitmapInfo->BitmapBuffer, Source->Info.BytesPerPixel, Size);
- }
- Assert(&BitmapInfo->Test);
-
- Effect_GL_Levels(Source, BitmapInfo, Memory, Property);
-}
-
-static void
-Effect_GaussianBlur(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[])
-{
- Effect_GL_GaussianBlur(Source, BitmapInfo, Memory, Property);
-#if 0
- real32 Radius = Property[0].CurrentValue.f;
-
- gl_effect_layer *Test = &BitmapInfo->Test;
- // glBindRenderbuffer(GL_RENDERBUFFER, Test->RBO);
- /*
- glUseProgram(TGL.ShaderProgram);
-
- int vertexColorLocation = glGetUniformLocation(TGL.ShaderProgram, "Radius");
- glUniform1f(vertexColorLocation, Radius + 1.60f);
- vertexColorLocation = glGetUniformLocation(TGL.ShaderProgram, "Direction");
- glUniform2f(vertexColorLocation, 1.0f, 0.0f);
- */
-
- glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
-
- glReadBuffer(GL_COLOR_ATTACHMENT0);
- uint16 Width = Source->Info.Width;
- uint16 Height = Source->Info.Height;
- uint8 *Data = (uint8 *)BitmapInfo->BitmapBuffer;
- glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, &Data[0]);
-
- GL_UpdateTexture(&BitmapInfo->Test, Data, Width, Height, 0);
- // glBindRenderbuffer(GL_RENDERBUFFER, Test->RBO);
- /*
- glUseProgram(TGL.ShaderProgram);
-
- vertexColorLocation = glGetUniformLocation(TGL.ShaderProgram, "Direction");
- glUniform2f(vertexColorLocation, 0.0f, 1.0f);
- */
- glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
- glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, &Data[0]);
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-#endif
-}
-
-#if 0
- {
- "Solid Color",
- &DrawColor, standard, {
- {"Color", {.col = V4(0.5f, 1.0f, 0.4f, 0.5f)}, color},
- }
- },
- {
- "Test Grid",
- &DrawGrid, standard, {
- {"Color 1", {.col = V4(0.5f, 1.0f, 0.4f, 1.0f)}, color},
- {"Color 2", {.col = V4(0.0f, 0.0f, 0.0f, 1.0f)}, color}
- }
- },
- {
- "Canny edges",
- &Canny, standard, {
- {"Blur Radius", {1.0f}, real},
- {"Threshold", {5.0f}, real},
- }
- },
- {
- "Levels",
- &Levels, levels, {
- {"Start point", {0.0f}, real},
- {"Mid point", {1.0f}, real},
- {"End point", {1.0f}, real},
- {"Start Col", {.col = V4(0.0f)}, color},
- {"Mid Col", {.col = V4(1.0f)}, color},
- {"End Col", {.col = V4(1.0f)}, color},
- }
- },
- {
- "Kernel",
- &SpacialFilter, standard, {
- {"V1", {-1.0f}, real},
- {"V2", {0.0f}, real},
- {"V3", {1.0f}, real},
- {"V4", {-2.0f}, real},
- {"V5", {0.0f}, real},
- {"V6", {2.0f}, real},
- {"V7", {-1.0f}, real},
- {"V8", {0.0f}, real},
- {"V9", {1.0f}, real},
- }
- },
- {
- "Invert",
- &Invert, 0, standard, {
- }
- }
-#endif
-
-static void
-AddEffect(project_layer *Layer, memory *Memory, uint16 EffectListIndex)
-{
- if (Layer == NULL)
- return;
- Layer->Effect[Layer->NumberOfEffects] = (effect *)AllocateMemory(Memory, sizeof(effect), F_Effects);
- effect *Effect = Layer->Effect[Layer->NumberOfEffects];
- effect_header EffectHeader = EffectList[EffectListIndex];
- Effect->Name = EffectHeader.Name;
- Effect->func = EffectHeader.func;
- Effect->NumberOfProperties = EffectHeader.NumberOfProperties;
- Effect->DisplayType = EffectHeader.DisplayType;
- Effect->IsActive = true;
- Effect->ImGuiID = RandomGlobalIncrement++;
- for (int16 i = 0; i < Effect->NumberOfProperties; i++) {
- Effect->Property[i].Name = EffectHeader.PropertyHeader[i].Name;
- Effect->Property[i].CurrentValue = EffectHeader.PropertyHeader[i].Value;
- Effect->Property[i].MinVal = EffectHeader.PropertyHeader[i].MinVal;
- Effect->Property[i].MaxVal = EffectHeader.PropertyHeader[i].MaxVal;
- Effect->Property[i].VarType = EffectHeader.PropertyHeader[i].VarType;
- }
- Layer->NumberOfEffects++;
-}
-
-#if 0
-
-static void
-DrawColor(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
-{
- v4 FloatColor = Property[0].CurrentValue.col;
- uint32 Color = ColToUint32(FloatColor);
-
- uint8 *Row = ((uint8 *)Buffer->EffectBuffer);
- v2 Origin = {(real32)Buffer->Width / 2.0f, (real32)Buffer->Height / 2.0f};
-
- real32 MaxLength = sqrt(LengthSq(Origin));
-
- for(int Y = 0;
- Y < Buffer->Height;
- ++Y)
- {
- uint32 *Pixel = (uint32 *)Row;
- for(int X = 0;
- X < Buffer->Width;
- ++X)
- {
- RenderAlpha(Pixel, Color);
- Pixel++;
- }
- Row += Buffer->Pitch;
- }
-}
-
-static void
-Invert(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
-{
- uint8 *Row = ((uint8 *)Buffer->EffectBuffer);
-
- for(int Y = 0;
- Y < Buffer->Height;
- ++Y)
- {
- uint32 *Pixel = (uint32 *)Row;
- for(int X = 0;
- X < Buffer->Width;
- ++X)
- {
- v4 col = Uint32ToCol8(*Pixel);
- col.r = 255 - col.r;
- col.g = 255 - col.g;
- col.b = 255 - col.b;
- *Pixel++ = Col8ToUint32(col);
- }
- Row += Buffer->Pitch;
- }
-}
-
-static void
-DrawGradient(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
-{
- v4 StartColor = Property[0].CurrentValue.col;
- v4 EndColor = Property[1].CurrentValue.col;
- real32 Alpha = Property[2].CurrentValue.f;
- uint8 *Row = ((uint8 *)Buffer->EffectBuffer +
- Buffer->BytesPerPixel +
- Buffer->Pitch);
- for(int Y = 0;
- Y < Buffer->Height;
- ++Y)
- {
- uint32 *Pixel = (uint32 *)Row;
- for(int X = 0;
- X < Buffer->Width;
- ++X)
- {
- real32 PlusAlpha = ((real32)X / Buffer->Width);
- v4 PL = V4(V3(PlusAlpha), 1.0f);
- v4 C1 = ClipV4((StartColor - PL));
- v4 C2 = ClipV4( (EndColor - (1 - PL) ) );
- v4 FloatColor = ClipV4( C1 + C2 );
-
- uint32 Color = ColToUint32(FloatColor);
- *(uint32 *)Pixel++ = Color;
- }
- Row += Buffer->Pitch;
- }
-}
-
-static void
-DrawGrid(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
-{
- v4 StartColor = Property[0].CurrentValue.col;
- v4 EndColor = Property[1].CurrentValue.col;
- uint32 Color1 = ColToUint32(StartColor);
- uint32 Color2 = ColToUint32(EndColor);
-
- uint8 *Row = ((uint8 *)Buffer->EffectBuffer);
- for(int Y = 0;
- Y < Buffer->Height;
- ++Y)
- {
- uint32 *Pixel = (uint32 *)Row;
- for(int X = 0;
- X < Buffer->Width;
- ++X)
- {
- if (X & 4 || Y & 4) {
- *(uint32 *)Pixel++ = Color1;
- } else {
- *(uint32 *)Pixel++ = Color2;
- }
- }
- Row += Buffer->Pitch;
- }
-}
-
-static real32
-KernLoop(pixel_buffer *Buffer, int16 Xp, int16 Yp, real32 Value[8])
+Effect_DrawColor(real32 *Data, int Width, int Height, int BytesPerPixel, void *EffectBitmapAddress, uint16 ShaderProgram)
{
- real32 P[9];
- uint8 *Row = ((uint8 *)Buffer->EffectBuffer +
- (Buffer->Pitch*Yp));
- Row -= Buffer->Pitch;
- int16 n = 0;
- for(int Y = 0;
- Y < 3;
- ++Y)
- {
- uint32 *Pixel = (uint32 *)Row + Xp;
- for(int X = 0;
- X < 3;
- ++X)
- {
- real32 BW = Uint32ToNormalizedBW(*Pixel);
- P[n] = BW * Value[n];
- Pixel++;
- n++;
- }
- Row += Buffer->Pitch;
- }
- real32 Sum = P[0] + P[1] + P[2] +
- P[3] + P[4] + P[5] +
- P[6] + P[7] + P[8] ;
- return Sum;
+ v4 Color = { Data[0], Data[1], Data[2], Data[3] };
+ blend_mode BlendMode = (blend_mode)Data[4];
+ Effect_Software_DrawColor(Width, Height, BytesPerPixel, EffectBitmapAddress, Color, BlendMode);
}
-
-static void
-SpacialFilter(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
-{
- real32 P[9];
- P[0] = Property[0].CurrentValue.f;
- P[1] = Property[1].CurrentValue.f;
- P[2] = Property[2].CurrentValue.f;
- P[3] = Property[3].CurrentValue.f;
- P[4] = Property[4].CurrentValue.f;
- P[5] = Property[5].CurrentValue.f;
- P[6] = Property[6].CurrentValue.f;
- P[7] = Property[7].CurrentValue.f;
- P[8] = Property[8].CurrentValue.f;
-
- if (!Buffer->Scratch) {
- Buffer->Scratch = (uint64 *)Memory->Address + Memory->CurrentPosition;
- Memory->CurrentPosition += Buffer->Width * Buffer->Height * Buffer->BytesPerPixel;
- }
-
- for(int Y = 1;
- Y < Buffer->Height - 1;
- ++Y)
- {
- for(int X = 1;
- X < Buffer->Width - 1;
- ++X)
- {
- real32 Sum = KernLoop(Buffer, X, Y, P);
- uint8 *FloatRow = ((uint8 *)Buffer->Scratch +
- Buffer->BytesPerPixel +
- Buffer->Pitch + (Buffer->Pitch*Y));
- real32 *FloatValue = (real32 *)FloatRow + X;
- *(real32 *)FloatValue++ = Sum;
- }
- }
- for(int Y = 1;
- Y < Buffer->Height - 1;
- ++Y)
- {
- for(int X = 1;
- X < Buffer->Width - 1;
- ++X)
- {
- uint8 *Row = ((uint8 *)Buffer->EffectBuffer +
- Buffer->BytesPerPixel +
- Buffer->Pitch + (Buffer->Pitch*Y));
- uint32 *Pixel = (uint32 *)Row + X;
- uint8 *RowR = ((uint8 *)Buffer->Scratch +
- Buffer->BytesPerPixel +
- Buffer->Pitch + (Buffer->Pitch*Y));
- real32 *PixelR = (real32 *)RowR + X;
- *(uint32 *)Pixel= ColToUint32(abs(*PixelR / 4.0f));
- PixelR++;
- }
- }
-}
-
-
-static void
-Gaussian(pixel_buffer *Buffer, void *FloatStorage, real32 Radius)
-{
- if (Radius < 1.0f)
- Radius = 1.0f;
- real32 Omega = Radius / 2;
- real32 Total = pow((Radius + Radius + 1), 2) / 2;
- int32 ColorPitch = Buffer->Pitch * 2;
-
- real32 P2 = 2*(Omega*Omega);
- for(int16 Y = Radius;
- Y < Buffer->Height - Radius;
- ++Y)
- {
- uint8 *Row = ((uint8 *)Buffer->EffectBuffer +
- Buffer->BytesPerPixel +
- Buffer->Pitch + Buffer->Pitch*(Y));
- for(int16 X = Radius;
- X < Buffer->Width - Radius;
- ++X)
- {
- uint32 *Pixel = (uint32 *)Row + X;
- v4 FloatCol = Uint32ToNormalizedCol(*Pixel);
- for(int16 Y2 = -Radius;
- Y2 <= Radius;
- ++Y2)
- {
- uint16 *TempRow = ((uint16 *)FloatStorage +
- Buffer->BytesPerPixel +
- ColorPitch + (ColorPitch*(Y + Y2)));
- for(int16 X2 = -Radius;
- X2 <= Radius;
- ++X2)
- {
- v4 *TempValue = (v4 *)TempRow + (X + X2);
- real32 P1 = ((X2 * X2) + (Y2 * Y2));
- real32 G = exp(-(P1/P2));
- *TempValue = *TempValue + (FloatCol*V4(G) / V4(Total));
- }
- }
- }
- }
- for(int Y = Radius;
- Y < Buffer->Height - Radius;
- ++Y)
- {
- for(int X = Radius;
- X < Buffer->Width - Radius;
- ++X)
- {
- uint8 *Row = ((uint8 *)Buffer->EffectBuffer +
- Buffer->BytesPerPixel +
- Buffer->Pitch + (Buffer->Pitch*Y));
- uint32 *Pixel = (uint32 *)Row + X;
- uint16 *TempRow = ((uint16 *)FloatStorage +
- Buffer->BytesPerPixel +
- ColorPitch + (ColorPitch*Y));
- v4 *TempValue = (v4 *)TempRow + X;
- TempValue->a = 1.0f;
- uint32 Color = ColToUint32(Clamp(0.0, *TempValue, 1.0));
- *Pixel = Color;
- *TempValue = {0};
- }
- }
-}
-
-static void
-Canny(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
-{
- real32 SH[9] = { -1, 0, 1,
- -2, 0, 2,
- -1, 0, 1 };
- real32 SV[9] = { -1, -2, -1,
- 0, 0, 0,
- 1, 2, 1 };
-
- real32 Radius = Property[0].CurrentValue.f;
- real32 Threshold = Property[1].CurrentValue.f / 100;
- real32 UpperThreshold = Threshold * 1.5;
- int32 ColorPitch = Buffer->Pitch * 2;
-
- if (!Buffer->Scratch) {
- Buffer->Scratch = (uint64 *)Memory->Address + Memory->CurrentPosition;
- // NOTE(fox): this buffer is four times as large to store four real32s
- Memory->CurrentPosition += Buffer->Width * Buffer->Height * Buffer->BytesPerPixel * 4;
- }
-
- Gaussian(Buffer, Buffer->Scratch, Radius);
-
- for(int Y = 1;
- Y < Buffer->Height - 1;
- ++Y)
- {
- uint16 *TempRow = ((uint16 *)Buffer->Scratch +
- Buffer->BytesPerPixel +
- ColorPitch + (ColorPitch*(Y)));
- for(int X = 1;
- X < Buffer->Width - 1;
- ++X)
- {
- real32 HSum = KernLoop(Buffer, X, Y, SH);
- real32 VSum = KernLoop(Buffer, X, Y, SV);
- real32 Mag = sqrt((HSum*HSum) + (VSum*VSum));
- real32 Angle = atan(VSum/HSum) * (180 / PI);
- v4 *TempValue = (v4 *)TempRow + (X);
- TempValue->r = Mag;
- TempValue->g = Angle;
- }
- }
- for(int Y = 1;
- Y < Buffer->Height - 1;
- ++Y)
- {
- uint16 *TempRow = ((uint16 *)Buffer->Scratch +
- Buffer->BytesPerPixel +
- ColorPitch + (ColorPitch*(Y)));
- uint16 *Row = ((uint16 *)Buffer->EffectBuffer +
- Buffer->BytesPerPixel +
- Buffer->Pitch + (Buffer->Pitch*Y));
- for(int X = 1;
- X < Buffer->Width - 1;
- ++X)
- {
- uint32 *Pixel = (uint32 *)Row + X;
- v4 *TempValue = (v4 *)TempRow + X;
- if (TempValue->g < 45 && TempValue->g > -45) {
- v4 *Mag1 = (v4 *)TempRow + X + 1;
- v4 *Mag2 = (v4 *)TempRow + X - 1;
- if (TempValue->r > Mag1->r && TempValue->r > Mag2->r)
- TempValue->b = 1;
- }
- if (TempValue->g < 90 && TempValue->g > 45) {
- v4 *Mag1 = (v4 *)(TempRow + ColorPitch) + X + 1;
- v4 *Mag2 = (v4 *)(TempRow - ColorPitch) + X - 1;
- if (TempValue->r > Mag1->r && TempValue->r > Mag2->r)
- TempValue->b = 1;
- }
- if (TempValue->g < -45 && TempValue->g > -90) {
- v4 *Mag1 = (v4 *)(TempRow - ColorPitch) + X + 1;
- v4 *Mag2 = (v4 *)(TempRow + ColorPitch) + X - 1;
- if (TempValue->r > Mag1->r && TempValue->r > Mag2->r)
- TempValue->b = 1;
- } else {
- v4 *Mag1 = (v4 *)(TempRow + ColorPitch) + X;
- v4 *Mag2 = (v4 *)(TempRow - ColorPitch) + X;
- if (TempValue->r > Mag1->r && TempValue->r > Mag2->r)
- TempValue->b = 1;
- }
- }
- for(int Y = 1;
- Y < Buffer->Height - 1;
- ++Y)
- {
- uint16 *TempRow = ((uint16 *)Buffer->Scratch +
- Buffer->BytesPerPixel +
- ColorPitch + (ColorPitch*(Y)));
- uint8 *Row = ((uint8 *)Buffer->EffectBuffer +
- Buffer->BytesPerPixel +
- Buffer->Pitch + (Buffer->Pitch*Y));
- for(int X = 1;
- X < Buffer->Width - 1;
- ++X)
- {
- uint32 *Pixel = (uint32 *)Row + X;
- v4 *TempValue = (v4 *)TempRow + (X);
- if (TempValue->b == 1) {
- if (TempValue->r > UpperThreshold)
- *Pixel = 0xFF0000FF;
- }
- else if (TempValue->r > Threshold)
- {
- bool32 pp = false;
- uint16 *TempRow2 = TempRow - ColorPitch;
- for(int Y2 = 0;
- Y2 < 3;
- ++Y2)
- {
- v4 *TempValue2 = (v4 *)TempRow + (X - 1);
- for(int X2 = 0;
- X2 < 3;
- ++X2)
- {
- if (TempValue2->r > UpperThreshold)
- pp = true;
- TempValue2++;
- }
- TempRow2 += ColorPitch;
- }
- if (pp)
- *Pixel = 0xFFFFFF00;
- }
- }
- }
- }
-}
-
-static void
-Levels(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
-{
- real32 Min = Property[0].CurrentValue.f;
- real32 Mid = Property[1].CurrentValue.f;
- real32 Max = Property[2].CurrentValue.f;
-
- v4 ColMin = Property[3].CurrentValue.col;
- v4 ColMid = Property[4].CurrentValue.col;
- v4 ColMax = Property[5].CurrentValue.col;
-
- if (!Property[0].Scratch) {
- Property[0].Scratch = (uint64 *)Memory->Address + Memory->CurrentPosition;
- Memory->CurrentPosition += Buffer->Width * Buffer->Height * Buffer->BytesPerPixel;
-
- uint16 *Levels = (uint16 *)Property[0].Scratch;
- uint8 *Row = ((uint8 *)Buffer->OriginalBuffer);
-
- for(int Y = 0;
- Y < Buffer->Height;
- ++Y)
- {
- uint32 *Pixel = (uint32 *)Row;
- for(int X = 0;
- X < Buffer->Width;
- ++X)
- {
- v4 Col = Uint32ToCol8(*Pixel);
- uint16 Global = (uint16)(RoundReal32ToUint32((Col.r + Col.g + Col.b)/3));
- *(Levels + Global) += 1;
- *(Levels + 256 + (uint16)Col.r) += 1;
- *(Levels + 256*2 + (uint16)Col.g) += 1;
- *(Levels + 256*3 + (uint16)Col.b) += 1;
- *(Levels + 256*4 + (uint16)Col.a) += 1;
- Pixel++;
- }
- Row += Buffer->Pitch;
- }
- }
-
-
- uint8 *Row = ((uint8 *)Buffer->EffectBuffer);
- for(int Y = 0;
- Y < Buffer->Height;
- ++Y)
- {
- uint32 *Pixel = (uint32 *)Row;
- for(int X = 0;
- X < Buffer->Width;
- ++X)
- {
- // individual channels
- v4 ColorI = powv4(Uint32ToNormalizedCol(*Pixel), ColMid);
- v4 ValI = 1.0f/(ColMax-ColMin) * (ColorI - ColMin);
-
- // global channel
- v4 ColorG = powv4(ValI, Mid);
- v4 ValG = 1.0f/(Max-Min) * (ColorG - Min);
-
- *Pixel++ = ColToUint32(Clamp(0.0f, ValG, 1.0f));
- }
- Row += Buffer->Pitch;
- }
-
-}
-
-static void
-GaussianBlur(pixel_buffer *Buffer, memory *Memory, property_channel Property[])
-{
- real32 Radius = Property[0].CurrentValue.f;
-
- if (!Buffer->Scratch) {
- Buffer->Scratch = (uint64 *)Memory->Address + Memory->CurrentPosition;
- Memory->CurrentPosition += Buffer->Width * Buffer->Height * Buffer->BytesPerPixel;
- }
-
- Gaussian(Buffer, Buffer->Scratch, Radius);
-}
-#endif
-
-// AVX2 effect example code
-/*
- __m256 Fraction255 = _mm256_set1_ps(1/255.0f);
- __m256 Real255 = _mm256_set1_ps(255);
- __m256 One = _mm256_set1_ps(1);
-
- __m256i FF = _mm256_set1_epi32(0xFF);
- __m256 ZeroReal = _mm256_set1_ps(0);
- __m256i Int255 = _mm256_set1_epi8((uint8)255);
-
- for (int16 Y = 0; Y < Source->Info.Height; Y += 2)
- {
- for (int16 X = 0; X < Source->Info.Width; X += 4)
- {
- uint32 XLookup = (X >> 2)*16 + (X % 4);
- uint32 YLookup = (Y >> 2)*(Source->Info.Width*4) + (Y % 4)*4;
- uint32 PixelToSeek = XLookup + YLookup;
- uint8 *Pixel = (uint8 *)BitmapInfo->BitmapBuffer + PixelToSeek*Source->Info.BytesPerPixel;
- __m256i DestPixel = _mm256_loadu_si256((const __m256i *)Pixel);
-
- __m256 R_Dest = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256( DestPixel, FF)), Fraction255);
- __m256 G_Dest = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256(_mm256_srli_epi32(DestPixel, 8), FF)), Fraction255);
- __m256 B_Dest = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256(_mm256_srli_epi32(DestPixel, 16), FF)), Fraction255);
- __m256i A_Out = _mm256_and_si256(_mm256_srli_epi32(DestPixel, 24), FF);
-
- __m256 R_Blend = R_Dest;
- __m256 G_Blend = G_Dest;
- __m256 B_Blend = B_Dest;
-
- R_Blend = _mm256_max_ps(_mm256_min_ps(One, R_Blend), ZeroReal);
- G_Blend = _mm256_max_ps(_mm256_min_ps(One, G_Blend), ZeroReal);
- B_Blend = _mm256_max_ps(_mm256_min_ps(One, B_Blend), ZeroReal);
-
- __m256i R_Out = _mm256_cvttps_epi32(_mm256_mul_ps(R_Blend, Real255));
- __m256i G_Out = _mm256_cvttps_epi32(_mm256_mul_ps(G_Blend, Real255));
- __m256i B_Out = _mm256_cvttps_epi32(_mm256_mul_ps(B_Blend, Real255));
-
- __m256i OutputPixel = _mm256_or_si256(
- _mm256_or_si256(R_Out, _mm256_slli_epi32(G_Out, 8)),
- _mm256_or_si256(_mm256_slli_epi32(B_Out, 16), _mm256_slli_epi32(A_Out, 24)));
-
- _mm256_storeu_si256((__m256i *)Pixel, OutputPixel);
- }
- }
-*/
diff --git a/effects_constructors.cpp b/effects_constructors.cpp
new file mode 100644
index 0000000..7f7038d
--- /dev/null
+++ b/effects_constructors.cpp
@@ -0,0 +1,107 @@
+static void
+Effect_AddEntry(project_state *State, char *Name, char *ID, void (*func)(real32 *, int, int, int, void *, uint16), const char *GL_Shader, effect_display_type DisplayType = effect_display_type_standard)
+{
+ header_effect *Effect = &State->Effect[State->Playhead_Effect];
+ Effect->Name = Name;
+ Effect->ID = ID;
+ Effect->func = func;
+ Effect->DisplayType = DisplayType;
+ Effect->PropertyStartIndex = State->Playhead_Property;
+ if (GL_Shader) {
+ Effect->GLShaderIndex = Effect_GL_InitShader(GL_Shader);
+ Effect->UseGL = true;
+ }
+}
+
+static void
+Effect_EndEntry(project_state *State)
+{
+ State->Playhead_Effect++;
+}
+
+static void
+Effect_AddProperty_Real(project_state *State, char *Name, real32 DefaultValue, real32 MinVal = -999999, real32 MaxVal = 999999)
+{
+ header_effect *Effect = &State->Effect[State->Playhead_Effect];
+ Effect->Property_Count++;
+ header_property *Property = &State->Property[State->Playhead_Property++];
+ Property->Name = Name;
+ Property->DefaultValue = DefaultValue;
+ Property->MinVal = MinVal;
+ Property->MaxVal = MaxVal;
+}
+
+static void
+Effect_AddProperty_Col(project_state *State, char *Name, v4 DefaultValue)
+{
+ Effect_AddProperty_Real(State, "r", DefaultValue.r, 0, 1);
+ Effect_AddProperty_Real(State, "g", DefaultValue.r, 0, 1);
+ Effect_AddProperty_Real(State, "b", DefaultValue.r, 0, 1);
+ Effect_AddProperty_Real(State, "a", DefaultValue.r, 0, 1);
+}
+
+static void
+Effect_AddProperty_Blendmode(project_state *State, char *Name, blend_mode DefaultValue)
+{
+ header_effect *Effect = &State->Effect[State->Playhead_Effect];
+ Effect->Property_Count++;
+ header_property *Property = &State->Property[State->Playhead_Property++];
+ Property->Name = Name;
+ Property->DefaultValue = DefaultValue;
+ Property->DisplayType = property_display_type_blendmode;
+}
+
+static header_effect*
+Effect_EntryFromID(project_state *State, char *ID)
+{
+ for (int i = 0; i < State->Playhead_Effect; i++) {
+ if (String_Compare(ID, State->Effect[i].ID, 8))
+ return &State->Effect[i];
+ }
+ Assert(0);
+ return &State->Effect[0];
+}
+
+static void
+Effect_InitEntries(project_state *State)
+{
+ /*
+ Effect_AddEntry(State, "Levels", "LVLS", &Effect_Levels, effect_display_type_levels);
+ // Levels
+ // min/max is handled by the UI
+ Effect_AddProperty_Real(State, "All start point", 0.0f);
+ Effect_AddProperty_Real(State, "All mid point", 1.0f);
+ Effect_AddProperty_Real(State, "All end point", 1.0f);
+ Effect_AddProperty_Col(State, "Channel start point", V4(0.0f));
+ Effect_AddProperty_Col(State, "Channel mid point", V4(1.0f));
+ Effect_AddProperty_Col(State, "Channel end point", V4(1.0f));
+ Effect_EndEntry(State);
+ */
+ // Curves
+ /*
+ Effect_AddEntry(State, "Curves", "REALCRVS", &NULL, NULL, effect_display_type_curves);
+ Effect_AddProperty_Real(State, "Selected channel", 0.0f);
+ Effect_AddProperty_Real(State, "Number of points (main)", 2.0f);
+ Effect_AddProperty_Col(State, "Number of points (individual)", V4(2.0f));
+ for (int i = 0; i < MAX_CURVESPOINTS*5/2; i++) {
+ v4 PointData = ((i % (MAX_CURVESPOINTS/2)) == 0) ? V4(0, 0, 1, 1) : V4(0);
+ Effect_AddProperty_Col(State, "PointData", PointData);
+ }
+ Effect_EndEntry(State);
+ */
+ // Solid color
+ Effect_AddEntry(State, "Solid color", "REALSCOL", Effect_DrawColor, GLShader_SolidColor);
+ Effect_AddProperty_Col(State, "Color", V4(0.3f, 0.2f, 0.6f, 1.0f));
+ Effect_AddProperty_Blendmode(State, "Blend mode", blend_softlight);
+ Effect_EndEntry(State);
+ /*
+ // Gaussian blur
+ Effect_AddEntry(State, "Gaussian blur", "REALGBLR", &Effect_GaussianBlur, GLShader_GaussianBlur);
+ Effect_AddProperty_Real(State, "Radius", 1.0f, 0.0f, 200.0f);
+ Effect_EndEntry(State);
+ // Test gradient
+ Effect_AddEntry(State, "Test gradient", "REALTGRD", &Effect_TestGradient, NULL);
+ Effect_AddProperty_Col(State, "Color", V4(0.3f, 0.2f, 0.6f, 1.0f));
+ Effect_EndEntry(State);
+ */
+}
diff --git a/effects_gl_shader.cpp b/effects_gl_shader.cpp
new file mode 100644
index 0000000..b2e1fc1
--- /dev/null
+++ b/effects_gl_shader.cpp
@@ -0,0 +1,57 @@
+const char *GLShader_Levels = "#version 330 core\n"
+"out vec4 FragColor;\n"
+"in vec2 TexCoord;\n"
+"uniform float Start;\n"
+"uniform float Mid;\n"
+"uniform float End;\n"
+"uniform vec4 StartCol;\n"
+"uniform vec4 MidCol;\n"
+"uniform vec4 EndCol;\n"
+"uniform sampler2D Texture;\n"
+"void main()\n"
+"{\n"
+"vec4 OutCol = texture(Texture, TexCoord);\n"
+// individual channels
+"vec4 ColorI = pow(OutCol, MidCol);\n"
+"vec4 ValI = 1.0f / (EndCol - StartCol) * (ColorI - StartCol);\n"
+// global channel (doesn't affect alpha)
+"vec4 ColorG = pow(ValI, vec4(Mid));\n"
+"vec4 ValG = 1.0f / (End - Start) * (ColorG - Start);\n"
+"ValG = vec4(ValG.rgb, ValI.a);\n"
+"FragColor = clamp(ValG, 0.0f, 1.0f);\n"
+"}\0";
+
+const char *GLShader_SolidColor = "#version 330 core\n"
+"out vec4 FragColor;\n"
+"in vec2 TexCoord;\n"
+"uniform vec4 Color;\n"
+"uniform sampler2D Texture;\n"
+"void main()\n"
+"{\n"
+"vec4 OutCol = texture(Texture, TexCoord);\n"
+"FragColor = Color*OutCol;\n"
+"}\0";
+
+const char *GLShader_GaussianBlur = "#version 330 core\n"
+"uniform float Radius;\n"
+"uniform vec2 Direction;\n"
+"uniform sampler2D Texture;\n"
+"out vec4 FragColor;\n"
+"in vec2 TexCoord;\n"
+"\n"
+"vec4 blur(sampler2D image, vec2 uv, vec2 resolution, vec2 direction) {\n"
+" vec4 color = vec4(0.0f);\n"
+" float Omega = Radius / 3;\n"
+" float Divisor = 2*Omega*Omega;\n"
+" float A2 = 1.0f / (Omega * sqrt(2*3.141592));\n"
+" for (float Span = -round(Radius); Span < round(Radius); Span++) {\n"
+" float Dividend = -Span * Span;\n"
+" float Multiplier = A2 * exp(Dividend/Divisor);\n"
+" vec2 Dir = Span*direction;\n"
+" color += texture(image, uv + (Dir / resolution)) * Multiplier;\n"
+" }\n"
+" return color;\n"
+"}\n"
+"void main(void) {\n"
+" FragColor = blur(Texture, TexCoord, vec2(1280, 720), Direction);\n"
+"}\0";
diff --git a/effects_software.cpp b/effects_software.cpp
index 06e8543..27023e6 100644
--- a/effects_software.cpp
+++ b/effects_software.cpp
@@ -1,177 +1,49 @@
+
static void
-Effect_Software_DrawColor(source *Source, layer_bitmap_info *BitmapInfo, memory *Memory, property_channel Property[])
+Effect_Software_DrawColor(int Width, int Height, int BytesPerPixel, void *EffectBitmapAddress, v4 Color, blend_mode BlendMode)
{
-#if ARM
-#else
- v4 FloatColor = Property[0].CurrentValue.col;
- blend_mode BlendMode = Property[1].CurrentValue.blendmode;
-
- __m256 ZeroReal = _mm256_set1_ps(0);
- __m256 ZeroPointFive = _mm256_set1_ps(0.5);
- __m256 One = _mm256_set1_ps(1);
- __m256 Two = _mm256_set1_ps(2);
-
- __m256 Fraction255 = _mm256_set1_ps(1/255.0f);
- __m256 Real255 = _mm256_set1_ps(255);
-
- __m256i FF = _mm256_set1_epi32(0xFF);
-
- __m256 Alpha = _mm256_set1_ps(FloatColor.a);
- __m256 AlphaInv = _mm256_set1_ps(1.0f - FloatColor.a);
-
- __m256 R_Col = _mm256_set1_ps(FloatColor.E[0]);
- __m256 R_Colx2 = _mm256_mul_ps(R_Col, Two);
- __m256 R_ColInv = _mm256_set1_ps(1.0f - FloatColor.E[0]);
-
- __m256 G_Col = _mm256_set1_ps(FloatColor.E[1]);
- __m256 G_Colx2 = _mm256_mul_ps(G_Col, Two);
- __m256 G_ColInv = _mm256_set1_ps(1.0f - FloatColor.E[1]);
-
- __m256 B_Col = _mm256_set1_ps(FloatColor.E[2]);
- __m256 B_Colx2 = _mm256_mul_ps(B_Col, Two);
- __m256 B_ColInv = _mm256_set1_ps(1.0f - FloatColor.E[2]);
-
- for (int16 Y = 0; Y < Source->Info.Height; Y += 2)
- {
- for (int16 X = 0; X < Source->Info.Width; X += 4)
- {
- uint32 XLookup = (X >> 2)*16 + (X % 4);
- uint32 YLookup = (Y >> 2)*(Source->Info.Width*4) + (Y % 4)*4;
- uint32 PixelToSeek = XLookup + YLookup;
- uint8 *Pixel = (uint8 *)BitmapInfo->BitmapBuffer + PixelToSeek*Source->Info.BytesPerPixel;
- __m256i DestPixel = _mm256_loadu_si256((const __m256i *)Pixel);
-
- // normalized values
- __m256 R_Dest = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256( DestPixel, FF)), Fraction255);
- __m256 G_Dest = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256(_mm256_srli_epi32(DestPixel, 8), FF)), Fraction255);
- __m256 B_Dest = _mm256_mul_ps(_mm256_cvtepi32_ps(_mm256_and_si256(_mm256_srli_epi32(DestPixel, 16), FF)), Fraction255);
- __m256i A_Out = _mm256_and_si256(_mm256_srli_epi32(DestPixel, 24), FF);
-
- __m256 R_Blend = R_Col;
- __m256 G_Blend = G_Col;
- __m256 B_Blend = B_Col;
- switch (BlendMode)
- {
- case blend_normal:
- {
- } break;
- case blend_multiply:
- {
- R_Blend = _mm256_mul_ps(R_Dest, R_Col);
- G_Blend = _mm256_mul_ps(G_Dest, G_Col);
- B_Blend = _mm256_mul_ps(B_Dest, B_Col);
- } break;
- case blend_colorburn:
- {
- R_Blend = _mm256_sub_ps(One, _mm256_div_ps(_mm256_sub_ps(One, R_Dest), R_Col));
- G_Blend = _mm256_sub_ps(One, _mm256_div_ps(_mm256_sub_ps(One, G_Dest), G_Col));
- B_Blend = _mm256_sub_ps(One, _mm256_div_ps(_mm256_sub_ps(One, B_Dest), B_Col));
- } break;
- case blend_linearburn:
- {
- R_Blend = _mm256_sub_ps(_mm256_add_ps(R_Dest, R_Col), One);
- G_Blend = _mm256_sub_ps(_mm256_add_ps(G_Dest, G_Col), One);
- B_Blend = _mm256_sub_ps(_mm256_add_ps(B_Dest, B_Col), One);
- } break;
- case blend_add:
- {
- R_Blend = _mm256_add_ps(R_Dest, R_Col);
- G_Blend = _mm256_add_ps(G_Dest, G_Col);
- B_Blend = _mm256_add_ps(B_Dest, B_Col);
- } break;
- case blend_screen:
- {
- R_Blend = _mm256_sub_ps(One, _mm256_mul_ps(_mm256_sub_ps(One, R_Dest), R_ColInv));
- G_Blend = _mm256_sub_ps(One, _mm256_mul_ps(_mm256_sub_ps(One, G_Dest), G_ColInv));
- B_Blend = _mm256_sub_ps(One, _mm256_mul_ps(_mm256_sub_ps(One, B_Dest), B_ColInv));
- } break;
- case blend_overlay:
- {
- __m256 R_Mask = _mm256_cmp_ps(R_Dest, ZeroPointFive, 1);
- __m256 G_Mask = _mm256_cmp_ps(G_Dest, ZeroPointFive, 1);
- __m256 B_Mask = _mm256_cmp_ps(B_Dest, ZeroPointFive, 1);
- __m256 R_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(R_Dest, R_Col));
- __m256 G_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(G_Dest, G_Col));
- __m256 B_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(B_Dest, B_Col));
- __m256 R_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, R_Dest), R_ColInv)));
- __m256 G_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, G_Dest), G_ColInv)));
- __m256 B_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, B_Dest), B_ColInv)));
- R_Blend = _mm256_blendv_ps(R_Upper, R_Lower, R_Mask);
- G_Blend = _mm256_blendv_ps(G_Upper, G_Lower, G_Mask);
- B_Blend = _mm256_blendv_ps(B_Upper, B_Lower, B_Mask);
- } break;
- case blend_softlight:
- {
- // using Pegtop's equation
- R_Blend = _mm256_add_ps(_mm256_mul_ps(_mm256_sub_ps(One, R_Colx2), _mm256_mul_ps(R_Dest, R_Dest)), _mm256_mul_ps(R_Colx2, R_Dest));
- G_Blend = _mm256_add_ps(_mm256_mul_ps(_mm256_sub_ps(One, G_Colx2), _mm256_mul_ps(G_Dest, G_Dest)), _mm256_mul_ps(G_Colx2, G_Dest));
- B_Blend = _mm256_add_ps(_mm256_mul_ps(_mm256_sub_ps(One, B_Colx2), _mm256_mul_ps(B_Dest, B_Dest)), _mm256_mul_ps(B_Colx2, B_Dest));
- } break;
- case blend_hardlight:
- {
- __m256 R_Mask = _mm256_cmp_ps(R_Dest, ZeroPointFive, 13);
- __m256 G_Mask = _mm256_cmp_ps(G_Dest, ZeroPointFive, 13);
- __m256 B_Mask = _mm256_cmp_ps(B_Dest, ZeroPointFive, 13);
- __m256 R_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(R_Dest, R_Col));
- __m256 G_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(G_Dest, G_Col));
- __m256 B_Lower = _mm256_mul_ps(Two, _mm256_mul_ps(B_Dest, B_Col));
- __m256 R_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, R_Dest), R_ColInv)));
- __m256 G_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, G_Dest), G_ColInv)));
- __m256 B_Upper = _mm256_sub_ps(One, _mm256_mul_ps(Two, _mm256_mul_ps(_mm256_sub_ps(One, B_Dest), B_ColInv)));
- R_Blend = _mm256_blendv_ps(R_Upper, R_Lower, R_Mask);
- G_Blend = _mm256_blendv_ps(G_Upper, G_Lower, G_Mask);
- B_Blend = _mm256_blendv_ps(B_Upper, B_Lower, B_Mask);
- } break;
- case blend_subtract:
- {
- R_Blend = _mm256_sub_ps(R_Dest, R_Col);
- G_Blend = _mm256_sub_ps(G_Dest, G_Col);
- B_Blend = _mm256_sub_ps(B_Dest, B_Col);
- } break;
- case blend_divide:
- {
- R_Blend = _mm256_div_ps(R_Dest, R_Col);
- G_Blend = _mm256_div_ps(G_Dest, G_Col);
- B_Blend = _mm256_div_ps(B_Dest, B_Col);
- } break;
- case blend_difference:
- {
- __m256 R_Lower = _mm256_sub_ps(R_Col, R_Dest);
- __m256 G_Lower = _mm256_sub_ps(G_Col, G_Dest);
- __m256 B_Lower = _mm256_sub_ps(B_Col, B_Dest);
- __m256 R_Upper = _mm256_sub_ps(R_Dest, R_Col);
- __m256 G_Upper = _mm256_sub_ps(G_Dest, G_Col);
- __m256 B_Upper = _mm256_sub_ps(B_Dest, B_Col);
- __m256 R_Mask = _mm256_cmp_ps(R_Lower, ZeroReal, 14);
- __m256 G_Mask = _mm256_cmp_ps(G_Lower, ZeroReal, 14);
- __m256 B_Mask = _mm256_cmp_ps(B_Lower, ZeroReal, 14);
- R_Blend = _mm256_blendv_ps(R_Upper, R_Lower, R_Mask);
- G_Blend = _mm256_blendv_ps(G_Upper, G_Lower, G_Mask);
- B_Blend = _mm256_blendv_ps(B_Upper, B_Lower, B_Mask);
- } break;
- }
-
- R_Blend = _mm256_add_ps(_mm256_mul_ps(R_Dest, AlphaInv),
- _mm256_mul_ps(R_Blend, Alpha));
- G_Blend = _mm256_add_ps(_mm256_mul_ps(G_Dest, AlphaInv),
- _mm256_mul_ps(G_Blend, Alpha));
- B_Blend = _mm256_add_ps(_mm256_mul_ps(B_Dest, AlphaInv),
- _mm256_mul_ps(B_Blend, Alpha));
-
- R_Blend = _mm256_max_ps(_mm256_min_ps(One, R_Blend), ZeroReal);
- G_Blend = _mm256_max_ps(_mm256_min_ps(One, G_Blend), ZeroReal);
- B_Blend = _mm256_max_ps(_mm256_min_ps(One, B_Blend), ZeroReal);
-
- __m256i R_Out = _mm256_cvttps_epi32(_mm256_mul_ps(R_Blend, Real255));
- __m256i G_Out = _mm256_cvttps_epi32(_mm256_mul_ps(G_Blend, Real255));
- __m256i B_Out = _mm256_cvttps_epi32(_mm256_mul_ps(B_Blend, Real255));
-
- __m256i OutputPixel = _mm256_or_si256(
- _mm256_or_si256(R_Out, _mm256_slli_epi32(G_Out, 8)),
- _mm256_or_si256(_mm256_slli_epi32(B_Out, 16), _mm256_slli_epi32(A_Out, 24)));
-
- _mm256_storeu_si256((__m256i *)Pixel, OutputPixel);
+ render_byte_info Bits = Bitmap_ByteInfo(BytesPerPixel);
+ rectangle RenderRegion = {0, 0, Width, Height};
+ transform_info T;
+ T.BlendMode = BlendMode;
+ for (int32 Y = RenderRegion.Min.y; Y < RenderRegion.Max.y; Y++) {
+ for (int32 X = RenderRegion.Min.x; X < RenderRegion.Max.x; X++) {
+ uint32 Offset = Y*Width*BytesPerPixel + X*BytesPerPixel;
+ uint8 *LayerPixel = (uint8 *)EffectBitmapAddress + Offset;
+
+ uint32 *R_DestAddress = (uint32 *)(LayerPixel + Bits.ByteOffset * 0);
+ uint32 *G_DestAddress = (uint32 *)(LayerPixel + Bits.ByteOffset * 1);
+ uint32 *B_DestAddress = (uint32 *)(LayerPixel + Bits.ByteOffset * 2);
+ uint32 *A_DestAddress = (uint32 *)(LayerPixel + Bits.ByteOffset * 3);
+
+ real32 R_Dest = (real32)(*R_DestAddress & Bits.MaskPixel) * Bits.Normalized;
+ real32 G_Dest = (real32)(*G_DestAddress & Bits.MaskPixel) * Bits.Normalized;
+ real32 B_Dest = (real32)(*B_DestAddress & Bits.MaskPixel) * Bits.Normalized;
+ real32 A_Dest = (real32)(*A_DestAddress & Bits.MaskPixel) * Bits.Normalized;
+
+ real32 R_Col = Color.r;
+ real32 G_Col = Color.g;
+ real32 B_Col = Color.b;
+ real32 A_Col = Color.a;
+
+ real32 LayerAlpha = A_Col * 1;
+
+ real32 R_Blend = R_Col;
+ real32 G_Blend = G_Col;
+ real32 B_Blend = B_Col;
+ real32 A_Blend = A_Col;
+
+ Fallback_Blend();
+
+ uint32 R_Out = (uint32)(Normalize(R_Blend) * Bits.Bits);
+ uint32 G_Out = (uint32)(Normalize(G_Blend) * Bits.Bits);
+ uint32 B_Out = (uint32)(Normalize(B_Blend) * Bits.Bits);
+ uint32 A_Out = (uint32)(Normalize(A_Blend) * Bits.Bits);
+
+ *R_DestAddress = (*R_DestAddress & ~Bits.MaskPixel) | R_Out;
+ *G_DestAddress = (*G_DestAddress & ~Bits.MaskPixel) | G_Out;
+ *B_DestAddress = (*B_DestAddress & ~Bits.MaskPixel) | B_Out;
+ *A_DestAddress = (*A_DestAddress & ~Bits.MaskPixel) | A_Out;
}
}
-#endif
}
diff --git a/functions.h b/functions.h
index aec2c54..9cd6c6a 100644
--- a/functions.h
+++ b/functions.h
@@ -8,6 +8,7 @@ static void Arbitrary_ShiftData(uint8 *Address_Start, uint8 *Address_End, uint64
static void Render_Main(void *Data, void *OutputBuffer, render_type RenderType, rectangle RenderRegion);
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);
static void Interact_Transform_Begin(project_data *File, memory *Memory, project_state *State, ImVec2 OGPos, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray);
@@ -21,6 +22,9 @@ 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 bezier_point * Bezier_LookupAddress(memory *Memory, property_channel *Property, uint16 Index, bool32 AssertExists = 1);
static void Bezier_EvaluateValue(project_state *State, bezier_point *PointAddress, v2 *Pos, real32 Y_Increment);
diff --git a/gl_calls.cpp b/gl_calls.cpp
index 6f760b6..277db2e 100644
--- a/gl_calls.cpp
+++ b/gl_calls.cpp
@@ -168,9 +168,8 @@ GL_GenAndBindTexture(GLuint *GLTexture, int Width, int Height, int BytesPerPixel
glTexImage2D(GL_TEXTURE_2D, 0, ByteFlag, Width, Height, 0, GL_RGBA, ByteFlag2, BufferAddress);
}
-#if 0
void
-GL_InitTexture(gl_effect_layer *Test)
+GL_InitHWBuffer(gl_effect_layer *Test)
{
glGenFramebuffers(1, &Test->FramebufferObject);
glGenTextures(1, &Test->Texture);
@@ -180,12 +179,22 @@ GL_InitTexture(gl_effect_layer *Test)
}
void
-GL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height, bool32 Multisample)
+GL_DeleteHWBuffer(gl_effect_layer *Test)
+{
+ glDeleteFramebuffers(1, &Test->FramebufferObject);
+ glDeleteTextures(1, &Test->Texture);
+ glDeleteRenderbuffers(1, &Test->Color_Renderbuffer);
+ glDeleteRenderbuffers(1, &Test->Stencil_Renderbuffer);
+ Test->Initialized = true;
+}
+
+void
+GL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height, uint16 BytesPerPixel, bool32 Multisample)
{
glViewport(0, 0, Width, Height);
if (!Test->Initialized) {
- GL_InitTexture(Test);
+ GL_InitHWBuffer(Test);
}
GLenum Target = GL_TEXTURE_2D;
@@ -194,15 +203,25 @@ GL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height,
glBindTexture(Target, Test->Texture);
+ int Depth = 0, StencilDepth = 0;
+ if (BytesPerPixel == 4) {
+ Depth = GL_RGBA8;
+ StencilDepth = GL_STENCIL_INDEX8;
+ } else if (BytesPerPixel == 8) {
+ Depth = GL_RGBA16;
+ StencilDepth = GL_STENCIL_INDEX16;
+ }
+
if (Multisample) {
// glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGB, Width, Height, GL_TRUE);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
glBindRenderbuffer(GL_RENDERBUFFER, Test->Color_Renderbuffer);
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, Width, Height);
+
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, Depth, Width, Height);
glBindRenderbuffer(GL_RENDERBUFFER, (GLuint)Test->Stencil_Renderbuffer );
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_STENCIL_INDEX8, Width, Height );
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, StencilDepth, Width, Height );
} else {
glTexParameteri(Target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(Target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -213,10 +232,10 @@ GL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height,
glBindTexture(GL_TEXTURE_2D, 0);
glBindRenderbuffer(GL_RENDERBUFFER, Test->Color_Renderbuffer);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, Width, Height);
+ glRenderbufferStorage(GL_RENDERBUFFER, Depth, Width, Height);
glBindRenderbuffer(GL_RENDERBUFFER, (GLuint)Test->Stencil_Renderbuffer );
- glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, Width, Height );
+ glRenderbufferStorage(GL_RENDERBUFFER, StencilDepth, Width, Height );
}
glBindFramebuffer(GL_FRAMEBUFFER, Test->FramebufferObject);
@@ -233,121 +252,9 @@ GL_UpdateTexture(gl_effect_layer *Test, void *Data, uint16 Width, uint16 Height,
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
-static void
-GL_BindDefaultVertexArrays()
-{
- glBindVertexArray(DefaultVerts.VertexArrayObject);
- // Switch to main buffer
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, DefaultVerts.ElementBufferObject);
- glBindBuffer(GL_ARRAY_BUFFER, DefaultVerts.VertexBufferObject);
- glBufferData(GL_ARRAY_BUFFER, sizeof(GL_DefaultVertices), GL_DefaultVertices, GL_STATIC_DRAW);
- // position attribute
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
- glEnableVertexAttribArray(0);
- // texture coordinate (note the last parameter's offset)
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
- glEnableVertexAttribArray(1);
-
-}
-
-static void
-GL_RasterizeShape(project_layer *Layer, mask *Mask)
-{
- gl_effect_layer Test = Layer->BitmapInfo.TestM;
- gl_effect_layer Test2 = Layer->BitmapInfo.Test;
- gl_vertex_shader VertData;
-
- uint32 Width = Layer->Source->Info.Width;
- uint32 Height = Layer->Source->Info.Height;
-
- uint8 *Data = (uint8 *)Layer->BitmapInfo.BitmapBuffer;
- glBindFramebuffer(GL_FRAMEBUFFER, Test.FramebufferObject);
-
- glEnable(GL_STENCIL_TEST);
- // glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-
- glStencilFunc(GL_ALWAYS, 0, 0xFF); // always write
- glStencilMask(0xff); // allow writing; ANDs any writes to the stencil buffer with this
-
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-
- glUseProgram(DefaultShaderProgram);
-
- int VertexMode = glGetUniformLocation(DefaultShaderProgram, "VertexMode");
- int FragmentMode = glGetUniformLocation(DefaultShaderProgram, "FragmentMode");
- glUniform1i(VertexMode, 1);
- glUniform1i(FragmentMode, 0);
-
- // secondary VBO
- glGenVertexArrays(1, &VertData.VertexArrayObject);
- glGenBuffers(1, &VertData.VertexBufferObject);
- glBindVertexArray(VertData.VertexArrayObject);
- glBindBuffer(GL_ARRAY_BUFFER, VertData.VertexBufferObject);
- glBufferData(GL_ARRAY_BUFFER, Mask->NumberOfVerts*3*sizeof(real32), Mask->TriangulatedPointCache, GL_STREAM_DRAW);
-
- // position attribute
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
- glEnableVertexAttribArray(0);
-
- int Scale = glGetUniformLocation(DefaultShaderProgram, "CompDimensions");
- glUniform3f(Scale, Width, Height, 0);
-
-
- glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP);
- glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP);
-
- glDisable(GL_CULL_FACE);
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, Mask->NumberOfVerts);
-
- // glEnable(GL_CULL_FACE);
-
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-
- glBindVertexArray(0);
-
- // glBindRenderbuffer(GL_RENDERBUFFER, Test.Color_Renderbuffer);
-
- VertexMode = glGetUniformLocation(DefaultShaderProgram, "VertexMode");
- FragmentMode = glGetUniformLocation(DefaultShaderProgram, "FragmentMode");
- glUniform1i(VertexMode, 0);
- glUniform1i(FragmentMode, 1);
-
- GL_BindDefaultVertexArrays();
-
- glStencilFunc(GL_NOTEQUAL, 0, 0xFF);
- glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
- glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_INT, 0);
-
- glDisable(GL_STENCIL_TEST);
- glStencilMask(0xFF);
- glStencilFunc(GL_ALWAYS, 0, 0xFF);
-
- glBindFramebuffer(GL_READ_FRAMEBUFFER, Test.FramebufferObject);
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, Test2.FramebufferObject);
- glBlitFramebuffer(0, 0, Width, Height, 0, 0, Width, Height,
- GL_COLOR_BUFFER_BIT, GL_NEAREST);
- glBindFramebuffer(GL_FRAMEBUFFER, Test2.FramebufferObject);
-
- glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, &Data[0]);
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
-}
-
static uint16
-Effect_GL_InitShader(int EffectIndex)
+Effect_GL_InitShader(const char *FragmentShaderEffectSource)
{
- uint16 *ShaderProgram = &GL_EffectShaderProgram[EffectIndex];
-
- // this is safe to do, riiight
- if (*ShaderProgram) {
- glUseProgram(*ShaderProgram);
- return *ShaderProgram;
- }
-
glShaderSource(DefaultVertexShader, 1, &DefaultVertexShaderSource, NULL);
glCompileShader(DefaultVertexShader);
@@ -363,7 +270,7 @@ Effect_GL_InitShader(int EffectIndex)
uint32 FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
- glShaderSource(FragmentShader, 1, &FragmentShaderEffectSource[EffectIndex], NULL);
+ glShaderSource(FragmentShader, 1, &FragmentShaderEffectSource, NULL);
glCompileShader(FragmentShader);
glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &success);
@@ -374,22 +281,21 @@ Effect_GL_InitShader(int EffectIndex)
printf("Fragment shader fail:\n %s", infoLog);
}
- *ShaderProgram = glCreateProgram();
+ uint16 ShaderProgram = glCreateProgram();
- glAttachShader(*ShaderProgram, DefaultVertexShader);
- glAttachShader(*ShaderProgram, FragmentShader);
- glLinkProgram(*ShaderProgram);
+ glAttachShader(ShaderProgram, DefaultVertexShader);
+ glAttachShader(ShaderProgram, FragmentShader);
+ glLinkProgram(ShaderProgram);
- glGetProgramiv(*ShaderProgram, GL_LINK_STATUS, &success);
+ glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &success);
if(!success) {
- glGetProgramInfoLog(*ShaderProgram, 512, NULL, infoLog);
+ glGetProgramInfoLog(ShaderProgram, 512, NULL, infoLog);
printf("Shader linkage fail:\n %s", infoLog);
}
glDeleteShader(FragmentShader);
- glUseProgram(*ShaderProgram);
+ glUseProgram(ShaderProgram);
- return *ShaderProgram;
+ return ShaderProgram;
}
-#endif
diff --git a/main.cpp b/main.cpp
index 9c05334..ddf1560 100644
--- a/main.cpp
+++ b/main.cpp
@@ -91,8 +91,10 @@ static uint32 RandomGlobalIncrement = 0;
#include "prenderer.cpp"
#include "gl_calls.cpp"
#include "bezier.cpp"
-#if 0
+#include "effects_gl_shader.cpp"
#include "effects.cpp"
+#include "effects_constructors.cpp"
+#if 0
#include "keyframes.cpp"
#include "layer.cpp"
#include "bitmap_calls.cpp"
@@ -182,16 +184,19 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI,
ImGui_DebugUndoTree(Memory, State);
}
-#if 0
if (State->Initializing == 3) {
Source_UICreateButton(File, State, Memory, Sorted.CompArray, Sorted.LayerArray);
- block_layer *Layera = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 2);
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 0);
+ Layer->Block_Effect_Index[0] = Effect_Init(State, Memory, 0, Layer->Block_Effect_Count);
+ Layer->Block_Effect_Count = 1;
+ }
+#if 0
// Layera->x.IsToggled = true;
// Layera->y.IsToggled = true;
- block_layer *Layerb = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 1);
+ // block_layer *Layerb = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 1);
// Layerb->x.IsToggled = true;
// Layerb->y.IsToggled = true;
- block_layer *Layerc = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 0);
+ // block_layer *Layerc = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 0);
// Layerc->x.IsToggled = true;
// Layerc->y.IsToggled = true;
// Layer_Select(Memory, State, 0);
@@ -272,6 +277,7 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI,
ImGui_File(File, State, Memory, io, Sorted.CompArray, Sorted.LayerArray);
ImGui_PropertiesPanel(File, State, UI, Memory, io);
ImGui_ColorPanel(File, State, UI, Memory, io);
+ ImGui_EffectsPanel(File, State, Memory, UI, io);
#if STABLE
ImGui_SD_Prompt(File, State, UI, Memory, io, Sorted.CompArray, Sorted.LayerArray);
ImGui_SD_Thumbnail(File, State, UI, Memory, io, Sorted.CompArray, Sorted.LayerArray, Sorted.SourceArray, Sorted.TempSourceCount);
@@ -299,6 +305,57 @@ Render_Main(void *Data, void *OutputBuffer, render_type RenderType, rectangle Re
}
}
+static void
+Layer_UpdateAllKeyframes(project_data *File, project_state *State, memory *Memory, block_layer *Layer, uint16 Index_Physical, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray, uint16 Frame_Current)
+{
+ int32 Offset = (State->Interact_Active == interact_type_keyframe_move) ? (int32)State->Interact_Offset[0] : 0;
+ for (int h = 0; h < AmountOf(Layer->Property); h++) {
+ property_channel *Property = &Layer->Property[h];
+ sorted_property_info *InfoLocation = Property_GetSortedInfo(SortedPropertyInfo, Index_Physical, h);
+ uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, Index_Physical, h);
+ if (Property->Block_Bezier_Count) {
+ real32 MinY, MaxY;
+ Property_MinMax_Y(Memory, State, Property, InfoLocation, &MinY, &MaxY);
+ real32 Y_Increment = 1 / (MaxY - MinY);
+ v2 FirstPointPos[3];
+ bezier_point *FirstPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[0]);
+ Bezier_EvaluateValue(State, FirstPointAddress, FirstPointPos);
+ v2 LastPointPos[3];
+ bezier_point *LastPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[Property->Keyframe_Count - 1]);
+ Bezier_EvaluateValue(State, LastPointAddress, LastPointPos);
+ if (FirstPointPos[0].x >= Frame_Current) {
+ Property->CurrentValue = FirstPointPos[0].y;
+ } else if (LastPointPos[0].x <= Frame_Current) {
+ Property->CurrentValue = LastPointPos[0].y;
+ } else {
+ int KeyframeIndex = 0;
+ for (;;) {
+ v2 PointPos[3];
+ bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex + 1]);
+ Bezier_EvaluateValue(State, PointAddress, PointPos, 1, Y_Increment);
+ if (PointPos[0].x >= Frame_Current)
+ break;
+ KeyframeIndex++;
+ }
+ v2 PointPos[3];
+ bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex]);
+ Bezier_EvaluateValue(State, PointAddress, PointPos, 1, Y_Increment);
+ v2 NextPointPos[3];
+ bezier_point *NextPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex + 1]);
+ Bezier_EvaluateValue(State, NextPointAddress, NextPointPos, 1, Y_Increment);
+ if (PointAddress->Type == interpolation_type_hold) {
+ Property->CurrentValue = PointPos[0].y;
+ } else if (PointAddress->Type == interpolation_type_linear && NextPointAddress->Type == interpolation_type_linear) {
+ real32 Ratio = (Frame_Current - PointPos[0].x) / (NextPointPos[0].x - PointPos[0].x);
+ Property->CurrentValue = PointPos[0].y + ((NextPointPos[0].y - PointPos[0].y) * Ratio);
+ } else {
+ Property->CurrentValue = Bezier_SolveYForX(PointPos[0], PointPos[0] + PointPos[2], NextPointPos[0] + NextPointPos[1], NextPointPos[0], Frame_Current);
+ }
+ }
+ }
+ }
+}
+
static void *
Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io,
sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray,
@@ -326,56 +383,12 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
Layer->Frame_End > Frame_Current && Layer->IsVisible)
{
if (State->UpdateKeyframes) {
- int32 Offset = (State->Interact_Active == interact_type_keyframe_move) ? (int32)State->Interact_Offset[0] : 0;
- for (int h = 0; h < AmountOf(Layer->Property); h++) {
- property_channel *Property = &Layer->Property[h];
- sorted_property_info *InfoLocation = Property_GetSortedInfo(SortedPropertyInfo, Index_Physical, h);
- uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, Index_Physical, h);
- if (Property->Block_Bezier_Count) {
- real32 MinY, MaxY;
- Property_MinMax_Y(Memory, State, Property, InfoLocation, &MinY, &MaxY);
- real32 Y_Increment = 1 / (MaxY - MinY);
- v2 FirstPointPos[3];
- bezier_point *FirstPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[0]);
- Bezier_EvaluateValue(State, FirstPointAddress, FirstPointPos);
- v2 LastPointPos[3];
- bezier_point *LastPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[Property->Keyframe_Count - 1]);
- Bezier_EvaluateValue(State, LastPointAddress, LastPointPos);
- if (FirstPointPos[0].x >= Frame_Current) {
- Property->CurrentValue = FirstPointPos[0].y;
- } else if (LastPointPos[0].x <= Frame_Current) {
- Property->CurrentValue = LastPointPos[0].y;
- } else {
- int KeyframeIndex = 0;
- for (;;) {
- v2 PointPos[3];
- bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex + 1]);
- Bezier_EvaluateValue(State, PointAddress, PointPos, 1, Y_Increment);
- if (PointPos[0].x >= Frame_Current)
- break;
- KeyframeIndex++;
- }
- v2 PointPos[3];
- bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex]);
- Bezier_EvaluateValue(State, PointAddress, PointPos, 1, Y_Increment);
- v2 NextPointPos[3];
- bezier_point *NextPointAddress = Bezier_LookupAddress(Memory, Property, ArrayLocation[KeyframeIndex + 1]);
- Bezier_EvaluateValue(State, NextPointAddress, NextPointPos, 1, Y_Increment);
- if (PointAddress->Type == interpolation_type_hold) {
- Property->CurrentValue = PointPos[0].y;
- } else if (PointAddress->Type == interpolation_type_linear && NextPointAddress->Type == interpolation_type_linear) {
- real32 Ratio = (Frame_Current - PointPos[0].x) / (NextPointPos[0].x - PointPos[0].x);
- Property->CurrentValue = PointPos[0].y + ((NextPointPos[0].y - PointPos[0].y) * Ratio);
- } else {
- Property->CurrentValue = Bezier_SolveYForX(PointPos[0], PointPos[0] + PointPos[2], NextPointPos[0] + NextPointPos[1], NextPointPos[0], Frame_Current);
- }
- }
- }
- }
+ Layer_UpdateAllKeyframes(File, State, Memory, Layer, Index_Physical, SortedPropertyInfo, SortedPropertyArray, Frame_Current);
}
layer_bitmap_state *BitmapState = &State->Render.Bitmap[Index_Physical];
void *BitmapAddress = NULL;
+ void *SecondSourceBitmap = NULL; // If there are effects or we're in interact_type_brush, we need to redirect to another scratch bitmap.
int Width = 0, Height = 0, BytesPerPixel = 0;
uint64 ScratchActive = 0;
if (!Layer->IsPrecomp) {
@@ -390,7 +403,7 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
Assert(Source->Type == source_type_principal);
void *SourceBitmapAddress = Memory_Block_AddressAtIndex(Memory, F_PrincipalBitmaps, Source->Bitmap_Index, 0);
ScratchActive = Source->Width * Source->Height * Source->BytesPerPixel;
- void *SecondSourceBitmap = Memory_PushScratch(Memory, ScratchActive);
+ SecondSourceBitmap = Memory_PushScratch(Memory, ScratchActive);
Memory_Copy((uint8 *)SecondSourceBitmap, (uint8 *)SourceBitmapAddress, ScratchActive);
// TODO(fox): Do all these extra precomputes really make a difference in the renderer?
rectangle RenderRegion = { 0, 0, Source->Width, Source->Height };
@@ -438,19 +451,21 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io
}
Assert(BitmapAddress);
- // for (int a = 0; a < Layer->Block_Mask_Count; a++) {
- // }
- // for (int a = 0; a < Layer->Block_Effect_Count; a++) {
- // }
-
- /*
- for (int h = 0; h < AmountOf(Layer->Property); h++) {
- property_channel *Property = &Layer->Property[h];
- if (Property->Keyframe_Count) {
- Property->CurrentValue = State->Frame_Current * 2;
+ if (Layer->Block_Effect_Count && !SecondSourceBitmap) {
+ block_source *Source;
+ if ((State->PreviewSource != -1) && Layer->IsSelected) {
+ Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, State->PreviewSource);
+ } else {
+ Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index);
}
+ void *SourceBitmapAddress = Memory_Block_AddressAtIndex(Memory, F_PrincipalBitmaps, Source->Bitmap_Index, 0);
+ ScratchActive = Source->Width * Source->Height * Source->BytesPerPixel;
+ SecondSourceBitmap = Memory_PushScratch(Memory, ScratchActive);
+ Memory_Copy((uint8 *)SecondSourceBitmap, (uint8 *)SourceBitmapAddress, ScratchActive);
+ BitmapAddress = SecondSourceBitmap;
}
- */
+
+ Layer_UpdateMasksEffects(State, Layer, Memory, BitmapAddress, Width, Height, BytesPerPixel);
Assert(Width);
Assert(Height);
@@ -526,6 +541,7 @@ int main(int argc, char *argv[]) {
Memory_InitTable(&GlobalMemory, &Memory, 1 * 1024 * 1024, F_Precomps, "Precomps", sizeof(block_composition));
Memory_InitTable(&GlobalMemory, &Memory, 2 * 1024 * 1024, F_Layers, "Layers", sizeof(block_layer));
Memory_InitTable(&GlobalMemory, &Memory, 1 * 1024 * 1024, F_Sources, "Sources", sizeof(block_source));
+ Memory_InitTable(&GlobalMemory, &Memory, 2 * 1024 * 1024, F_Effects, "Properties", sizeof(block_effect));
Memory_InitTable(&GlobalMemory, &Memory, 2 * 1024 * 1024, F_Properties, "Properties", sizeof(property_channel));
Memory_InitTable(&GlobalMemory, &Memory, 4 * 1024 * 1024, F_Bezier, "Bezier paths (keyframes, masks)", sizeof(block_bezier));
Memory_InitTable(&GlobalMemory, &Memory, 4 * 1024 * 1024, F_Strings, "Strings", sizeof(block_string));
@@ -587,13 +603,13 @@ int main(int argc, char *argv[]) {
File->Comp_Count = 1;
-#if 0
{
- uint16 SourceIndex = Source_Generate(File, State, &Memory, (void *)"../asset/hand/a.png");
+ uint16 SourceIndex = Source_Generate(File, State, &Memory, (void *)"../asset/a.jpg");
block_source *Source = (block_source *)Memory_Block_AddressAtIndex(&Memory, F_Sources, 0);
Source->IsSelected = true;
}
+#if 0
{
uint16 SourceIndex = Source_Generate(File, State, &Memory, (void *)"../asset/hand/b.jpg");
block_source *Source = (block_source *)Memory_Block_AddressAtIndex(&Memory, F_Sources, 1);
@@ -683,6 +699,8 @@ int main(int argc, char *argv[]) {
GL_InitDefaultShader();
GL_InitDefaultVerts();
+ Effect_InitEntries(State);
+
SDL_GL_MakeCurrent(window, gl_context);
SDL_Event Event;
@@ -717,7 +735,7 @@ int main(int argc, char *argv[]) {
Brush_CalcBitmapAlphaFromSize(&Memory, &State->Brush, 4);
State_BindBrushTexture(&Memory, &State->Brush, 4);
- File_Open(File, State, &Memory, "test");
+ // File_Open(File, State, &Memory, "test");
#if STABLE
curl_global_init(CURL_GLOBAL_ALL);
@@ -740,7 +758,7 @@ int main(int argc, char *argv[]) {
if (State->IsPlaying) {
block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(&Memory, F_Precomps, File->PrincipalCompIndex);
- State->Frame_Current = ((State->Frame_Current + 1) >= MainComp->Frame_Count) ? 0 : State->Frame_Current + 1;
+ Playhead_Increment(&State->Frame_Current, MainComp->Frame_Start, MainComp->Frame_End, 1);
State->UpdateFrame = true;
State->UpdateKeyframes = true;
}
diff --git a/main.h b/main.h
index 5b92039..ed74fa6 100644
--- a/main.h
+++ b/main.h
@@ -212,22 +212,22 @@ struct ui
bool32 IsPrimary;
ImU32 LayerColors[16] = {
- 0xff0000ff,
- 0xff00ff00,
- 0xffff0000,
- 0xff44546e,
- 0xff556780,
- 0xff5d7392,
- 0xff7e7b7e,
- 0xff828282,
- 0xff434344,
- 0xffAB8A71,
- 0xff3C5588,
- 0xff5B7193,
- 0xff728AAB,
- 0xff7C9AC3,
- 0xffA9A5A8,
- 0xffc0c0c0
+ 0xff8b1f1f,
+ 0xffc25909,
+ 0xff57c20a,
+ 0xff8ee6da,
+ 0xffa48fb7,
+ 0xffd14061,
+ 0xff38b683,
+ 0xff3fdbe5,
+ 0xffc9c9c9,
+ 0xff978489,
+ 0xfffaf5ab,
+ 0xff101010,
+ 0xffa024ca,
+ 0xfffae920,
+ 0xff208dfa,
+ 0xfffa2051
};
};
@@ -269,6 +269,7 @@ struct brush_state
enum interact_type
{
interact_type_none,
+ interact_type_timeline_scrub,
interact_type_layer_move,
interact_type_layer_timeadjust,
interact_type_viewport_transform,
@@ -304,8 +305,6 @@ struct interact_transform
uint32 TransformMode;
};
-
-
enum hotkey_input
{
hotkey_none,
@@ -314,6 +313,61 @@ enum hotkey_input
hotkey_paste
};
+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;
+ uint16 Index;
+ uint32 Block_Property_Index[MAX_PROPERTIES_PER_EFFECT];
+};
+
+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;
+};
+
struct project_state
{
bool32 UpdateKeyframes = 0;
@@ -337,6 +391,11 @@ struct project_state
real64 SDTimer;
#endif
+ header_effect Effect[128];
+ header_property Property[512];
+ uint16 Playhead_Effect;
+ uint16 Playhead_Property;
+
int32 PreviewLayer = -1;
int32 PreviewSource = -1;
@@ -435,15 +494,6 @@ struct block_source
source_type Type;
};
-struct property_header
-{
- char *Name;
- real32 DefaultVal;
- real32 MinVal;
- real32 MaxVal;
- bool32 AlwaysInteger;
-};
-
struct property_channel {
uint8 Occupied;
char *Name;
@@ -469,10 +519,10 @@ struct block_layer {
uint16 Block_String_Index;
uint16 Block_Composition_Index;
- uint16 Block_Mask_Index[MAX_EFFECTS];
+ uint16 Block_Mask_Index[MAX_MASKS];
uint16 Block_Mask_Count;
- uint16 Block_Effect_Index[MAX_MASKS];
+ uint16 Block_Effect_Index[MAX_EFFECTS];
uint16 Block_Effect_Count;
blend_mode BlendMode;
diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp
index 2ecdf9e..eaa7eb9 100644
--- a/my_imgui_widgets.cpp
+++ b/my_imgui_widgets.cpp
@@ -62,6 +62,55 @@ ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *
ImGui_InteractSliderProperty(State, Memory, Property);
ImGui::PopID();
}
+ for (int i = 0; i < Layer->Block_Effect_Count; i++)
+ {
+ block_effect Effect = *(block_effect *)Memory_Block_AddressAtIndex(Memory, F_Effects, Layer->Block_Effect_Index[i]);
+ header_effect *EffectHeader = Effect_EntryFromID(State, Effect.ID);
+ ImGui::PushID(Effect.Index);
+ ImGui::Text(EffectHeader->Name);
+ ImGui::PopID();
+ if (EffectHeader->DisplayType == effect_display_type_standard) {
+ for (int c = 0; c < EffectHeader->Property_Count; c++) {
+ header_property ChannelHeader = State->Property[EffectHeader->PropertyStartIndex + c];
+ property_channel *Property = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect.Block_Property_Index[c]);
+ ImGui::PushID(Property);
+ if (ChannelHeader.DisplayType == property_display_type_standard) {
+ ImGui_InteractSliderProperty(State, Memory, Property);
+ } else if (ChannelHeader.DisplayType == property_display_type_color) {
+ property_channel *Property1 = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect.Block_Property_Index[c+1]);
+ property_channel *Property2 = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect.Block_Property_Index[c+2]);
+ property_channel *Property3 = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect.Block_Property_Index[c+3]);
+ real32 *Color[4] = { &Property->CurrentValue, &Property1->CurrentValue, &Property2->CurrentValue, &Property3->CurrentValue };
+ if (ImGui::ColorEdit4("color", (real32 *)Color, ImGuiColorEditFlags_Float))
+ State->UpdateFrame = true;
+ c += 3;
+ } else if (ChannelHeader.DisplayType == property_display_type_blendmode) {
+ uint32 *item_current_idx = (uint32 *)&(Property->CurrentValue); // Here we store our selection data as an index.
+ if (ImGui::BeginListBox("Blend mode"))
+ {
+ for (int n = 0; n < IM_ARRAYSIZE(BlendmodeNames); n++)
+ {
+ const bool is_selected = (*item_current_idx == n);
+ if (ImGui::Selectable(BlendmodeNames[n], is_selected)) {
+ *item_current_idx = n;
+ State->UpdateFrame = true;
+ }
+
+ // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
+ if (is_selected)
+ ImGui::SetItemDefaultFocus();
+ }
+ ImGui::EndListBox();
+ }
+ } else {
+ Assert(0);
+ }
+ ImGui::PopID();
+ }
+ } else {
+ Assert(0);
+ }
+ }
if (Layer->IsPrecomp) {
block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, Layer->Block_Source_Index);
ImGui::DragScalar("Width", ImGuiDataType_U16, &Comp->Width);
@@ -1160,11 +1209,22 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory,
}
static void
-ImGui_TimelineHorizontalIncrementDraw(project_state *State, ui *UI, ImDrawList *draw_list, ImVec2 TimelineSizeWithBorder, ImVec2 TimelineAbsolutePos, block_composition MainComp,
+ImGui_Timeline_BGElements(project_state *State, ui *UI, ImDrawList *draw_list, ImVec2 TimelineSizeWithBorder, ImVec2 TimelineAbsolutePos, block_composition MainComp,
+ ImVec2 TimelineZoomSize, ImVec2 TimelineMoveSize)
+{
+ uint32 PreviewAreaColor = IM_COL32(128, 128, 128, 30);
+ ImVec2 Region_Min = ImVec2(TimelineAbsolutePos.x + TimelineMoveSize.x + ((real32)MainComp.Frame_Start / MainComp.Frame_Count)*TimelineZoomSize.x, TimelineAbsolutePos.y);
+ ImVec2 Region_Max = ImVec2(Region_Min.x + ((real32)(MainComp.Frame_End - MainComp.Frame_Start) / MainComp.Frame_Count)*TimelineZoomSize.x, Region_Min.y + TimelineSizeWithBorder.y);
+ draw_list->AddRectFilled(Region_Min, Region_Max, PreviewAreaColor);
+}
+
+static void
+ImGui_Timeline_HorizontalIncrementDraw(project_state *State, ui *UI, ImDrawList *draw_list, ImVec2 TimelineSizeWithBorder, ImVec2 TimelineAbsolutePos, block_composition MainComp,
ImVec2 TimelineZoomSize, ImVec2 TimelineMoveSize)
{
uint32 LineColor = IM_COL32(200, 200, 200, 40);
uint32 PlayheadColor = IM_COL32(000, 000, 200, 160);
+ uint32 PreviewAreaColor = IM_COL32(128, 128, 128, 60);
Assert(TimelineZoomSize.x > 0.0f);
@@ -1199,6 +1259,29 @@ ImGui_TimelineHorizontalIncrementDraw(project_state *State, ui *UI, ImDrawList *
ImVec2 Min = ImVec2(TimelineAbsolutePos.x + TimelineMoveSize.x + ((real32)State->Frame_Current / MainComp.Frame_Count)*TimelineZoomSize.x, TimelineAbsolutePos.y);
ImVec2 Max = ImVec2(Min.x + 2, TimelineAbsolutePos.y + TimelineSizeWithBorder.y);
draw_list->AddLine(Min, Max, PlayheadColor);
+
+ real32 Size = ImGui::GetFontSize() * 2;
+ ImGui::SetCursorScreenPos(Min - ImVec2(Size / 2, 0));
+ ImGui::Button("##playhead", ImVec2(Size, Size));
+ bool32 IsHovered = ImGui::IsItemHovered();
+ bool32 IsItemActive = ImGui::IsItemActive();
+ bool32 IsItemActivated = ImGui::IsItemActivated();
+ bool32 IsItemDeactivated = ImGui::IsItemDeactivated();
+ if (IsItemActivated) {
+ State->Interact_Active = interact_type_timeline_scrub;
+ State->Interact_Offset[0] = State->Frame_Current;
+ }
+ if (IsItemActive) {
+ ImVec2 DragDelta = ImGui::GetMouseDragDelta();
+ int32 NewCurrent = (int32)(State->Interact_Offset[0] + (DragDelta.x / TimelineZoomSize.x * MainComp.Frame_Count) + 0.5);
+ if (NewCurrent != State->Frame_Current) {
+ State->Frame_Current = NewCurrent;
+ State->UpdateFrame = true;
+ }
+ }
+ if (IsItemDeactivated) {
+ State->Interact_Active = interact_type_none;
+ }
}
@@ -1644,7 +1727,15 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem
ImGui::PushStyleColor(ImGuiCol_Button, UI->LayerColors[c]);
real32 Size = ImGui::GetFontSize() * 2;
ImVec2 ColSize(Size, Size);
- ImGui::Button("##test", ColSize);
+ if (ImGui::Button("##test", ColSize)) {
+ int h = 0, z = 0, i = 0;
+ while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &z, &i)) {
+ block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i);
+ if (Layer->IsSelected) {
+ Layer->ColIndex = c;
+ }
+ }
+ }
if ((c+1) % 4) { ImGui::SameLine(); }
ImGui::PopStyleColor();
ImGui::PopID();
@@ -1856,6 +1947,8 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI,
ImVec2 Increment = ImVec2((real32)1 / MainComp->Frame_Count, (real32)1 / LayerIncrement);
+ ImGui_Timeline_BGElements(State, UI, draw_list, TimelineSizeWithBorder, TimelineAbsolutePos, *MainComp, TimelineZoomSize, TimelineMoveSize);
+
ImGui_Timeline_DrawPrecomp(File, State, Memory, UI, io, draw_list, File->PrincipalCompIndex,
Increment, TimelineAbsolutePos, TimelineMoveSize, TimelineZoomSize,
TimelineSize, TimelineSizeWithBorder, LayerIncrement,
@@ -1884,7 +1977,7 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI,
TimelineSize, TimelineSizeWithBorder, LayerIncrement, SortedPropertyInfo, SortedPropertyArray);
}
- ImGui_TimelineHorizontalIncrementDraw(State, UI, draw_list, TimelineSizeWithBorder, TimelineAbsolutePos, *MainComp, TimelineZoomSize, TimelineMoveSize);
+ ImGui_Timeline_HorizontalIncrementDraw(State, UI, draw_list, TimelineSizeWithBorder, TimelineAbsolutePos, *MainComp, TimelineZoomSize, TimelineMoveSize);
ImVec2 MouseDelta = io.MouseDelta / TimelineSize;
@@ -2150,49 +2243,62 @@ ImGui_ProcessInputs(project_data *File, project_state *State, ui *UI, memory *Me
if (ImGui::IsKeyPressed(ImGuiKey_B)) {
State->Tool = tool_brush;
}
+ // NOTE(fox): File data not tracked on undo tree!
+ if (ImGui::IsKeyPressed(ImGuiKey_N)) {
+ block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, File->PrincipalCompIndex);
+ if (MainComp->Frame_Start < State->Frame_Current)
+ MainComp->Frame_End = State->Frame_Current;
+ }
+ if (ImGui::IsKeyPressed(ImGuiKey_B)) {
+ block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, File->PrincipalCompIndex);
+ if (MainComp->Frame_End > State->Frame_Current)
+ MainComp->Frame_Start = State->Frame_Current;
+ }
if (ImGui::IsKeyPressed(ImGuiKey_Tab)) {
UI->TimelineMode = (UI->TimelineMode == timeline_mode_default) ? timeline_mode_graph : timeline_mode_default;
UI->GraphZoomSize = ImVec2(0, 0);
UI->GraphMoveSize = ImVec2(0, 0);
}
- if (UI->FocusedWindow == focus_timeline) {
- if (UI->TimelineMode == timeline_mode_default) {
- if (ImGui::IsKeyPressed(ImGuiKey_G)) {
- Layer_ToggleChannel(File, Memory, 0);
- Layer_ToggleChannel(File, Memory, 1);
- } else if (ImGui::IsKeyPressed(ImGuiKey_A)) {
- Layer_ToggleChannel(File, Memory, 2);
- Layer_ToggleChannel(File, Memory, 3);
- } else if (ImGui::IsKeyPressed(ImGuiKey_R)) {
- Layer_ToggleChannel(File, Memory, 4);
- } else if (ImGui::IsKeyPressed(ImGuiKey_S)) {
- Layer_ToggleChannel(File, Memory, 5);
- } else if (ImGui::IsKeyPressed(ImGuiKey_T)) {
- if (io.KeyShift) {
- Layer_ToggleChannel(File, Memory, 6);
- } else {
- Layer_ToggleChannel(File, Memory, 7);
+ if (!io.KeyCtrl) {
+ if (UI->FocusedWindow == focus_timeline) {
+ if (UI->TimelineMode == timeline_mode_default) {
+ if (ImGui::IsKeyPressed(ImGuiKey_G)) {
+ Layer_ToggleChannel(File, Memory, 0);
+ Layer_ToggleChannel(File, Memory, 1);
+ } else if (ImGui::IsKeyPressed(ImGuiKey_A)) {
+ Layer_ToggleChannel(File, Memory, 2);
+ Layer_ToggleChannel(File, Memory, 3);
+ } else if (ImGui::IsKeyPressed(ImGuiKey_R)) {
+ Layer_ToggleChannel(File, Memory, 4);
+ } else if (ImGui::IsKeyPressed(ImGuiKey_S)) {
+ Layer_ToggleChannel(File, Memory, 5);
+ } else if (ImGui::IsKeyPressed(ImGuiKey_T)) {
+ if (io.KeyShift) {
+ Layer_ToggleChannel(File, Memory, 6);
+ } else {
+ Layer_ToggleChannel(File, Memory, 7);
+ }
+ }
+ } else if (UI->TimelineMode == timeline_mode_graph) {
+ if (ImGui::IsKeyPressed(ImGuiKey_G)) {
+ State->Interact_Offset[2] = io.MousePos.x;
+ State->Interact_Offset[3] = io.MousePos.y;
+ State->Interact_Active = interact_type_keyframe_move;
+ } else if (ImGui::IsKeyPressed(ImGuiKey_R)) {
+ // State->Interact_Offset[2] = io.MousePos.x;
+ // State->Interact_Offset[3] = io.MousePos.y;
+ // State->Interact_Active = interact_type_keyframe_rotate;
+ } else if (ImGui::IsKeyPressed(ImGuiKey_S)) {
+ State->Interact_Offset[2] = io.MousePos.x;
+ State->Interact_Offset[3] = io.MousePos.y;
+ State->Interact_Active = interact_type_keyframe_scale;
}
}
- } else if (UI->TimelineMode == timeline_mode_graph) {
- if (ImGui::IsKeyPressed(ImGuiKey_G)) {
- State->Interact_Offset[2] = io.MousePos.x;
- State->Interact_Offset[3] = io.MousePos.y;
- State->Interact_Active = interact_type_keyframe_move;
- } else if (ImGui::IsKeyPressed(ImGuiKey_R)) {
- // State->Interact_Offset[2] = io.MousePos.x;
- // State->Interact_Offset[3] = io.MousePos.y;
- // State->Interact_Active = interact_type_keyframe_rotate;
- } else if (ImGui::IsKeyPressed(ImGuiKey_S)) {
- State->Interact_Offset[2] = io.MousePos.x;
- State->Interact_Offset[3] = io.MousePos.y;
- State->Interact_Active = interact_type_keyframe_scale;
+ } else if (UI->FocusedWindow == focus_viewport) {
+ if (ImGui::IsKeyPressed(ImGuiKey_T)) {
+ State->HotkeyInput = hotkey_transform;
}
}
- } else if (UI->FocusedWindow == focus_viewport) {
- if (ImGui::IsKeyPressed(ImGuiKey_T)) {
- State->HotkeyInput = hotkey_transform;
- }
}
if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
if (State->Interact_Active == interact_type_keyframe_move ||
@@ -2206,8 +2312,11 @@ ImGui_ProcessInputs(project_data *File, project_state *State, ui *UI, memory *Me
State->UpdateFrame = true;
}
}
- if (ImGui::IsKeyPressed(ImGuiKey_Space)) {
- State->IsPlaying ^= 1;
+ if (ImGui::IsKeyPressed(ImGuiKey_Space) ) {
+ if (io.KeyShift) {
+ State->RerouteEffects = true;
+ } else { State->IsPlaying ^= 1;
+ }
}
if (ImGui::IsKeyPressed(ImGuiKey_2)) {
int h = 0, c = 0, i = 0;
@@ -2383,11 +2492,66 @@ ImGui_Menu(project_data *File, project_state *State, ui *UI, memory *Memory, ImG
}
static void
-ImGui_Popups(project_state *State, ui *UI, memory *Memory, ImGuiIO io)
+ImGui_EffectsPanel(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io)
{
+ ImGui::Begin("Effects list", NULL);
+ if (State->RerouteEffects) {
+ ImGui::SetKeyboardFocusHere();
+ State->RerouteEffects = 0;
+ }
+ int value_changed = ImGui::InputText("Effect name...", State->filter.InputBuf, IM_ARRAYSIZE(State->filter.InputBuf),
+ ImGuiInputTextFlags_CallbackCompletion, EffectConsoleCallback);
+
+ if (Hacko) {
+ if (!io.KeyShift)
+ EffectSel++;
+ else
+ EffectSel--;
+ Hacko = 0;
+ }
+ if (value_changed) {
+ State->filter.Build();
+ EffectSel = -1;
+ }
+ // Enter conveniently deactivates the InputText field
+ if (ImGui::IsItemDeactivated() && ImGui::IsKeyPressed(ImGuiKey_Enter)) {
+ int32 p = 0;
+ for (int32 i = 0; i < State->Playhead_Effect; i++) {
+ header_effect *EffectHeader = &State->Effect[i];
+ if (State->filter.PassFilter(EffectHeader->Name)) {
+ if (EffectSel == p && State->MostRecentlySelectedLayer != -1) {
+ Assert(0);
+ // AddEffect(File->Layer[State->MostRecentlySelectedLayer], Memory, i);
+ State->UpdateFrame = true;
+ }
+ p++;
+ }
+ }
+ EffectSel = -1;
+ }
+ int32 p = 0;
+ for (int32 i = 0; i < State->Playhead_Effect; i++) {
+ header_effect *EffectHeader = &State->Effect[i];
+ if (State->filter.PassFilter(EffectHeader->Name)) {
+ bool t = false;
+ if (EffectSel == p) {
+ t = true;
+ }
+ ImGui::Selectable(EffectHeader->Name, &t);
+ if (ImGui::IsItemClicked()) {
+ if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && State->MostRecentlySelectedLayer != -1) {
+ Assert(0);
+ State->UpdateFrame = true;
+ }
+ }
+ p++;
+ }
+ }
+ ImGui::End();
}
+
#if 0
real32 MaxVal_Y = -10000;
real32 MinVal_Y = 10000;
@@ -3698,62 +3862,6 @@ ImGui_SlidingLayer(project_layer *Layer, real32 *DraggingThreshold, real32 Delta
return Result;
}
-static void
-ImGui_EffectsPanel(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io)
-{
- ImGui::Begin("Effects list", NULL);
- if (State->RerouteEffects) {
- ImGui::SetKeyboardFocusHere();
- State->RerouteEffects = 0;
- }
- int value_changed = ImGui::InputText("Effect name...", State->filter.InputBuf, IM_ARRAYSIZE(State->filter.InputBuf),
- ImGuiInputTextFlags_CallbackCompletion, EffectConsoleCallback);
-
- if (Hacko) {
- if (!io.KeyShift)
- EffectSel++;
- else
- EffectSel--;
- Hacko = 0;
- }
- if (value_changed) {
- State->filter.Build();
- EffectSel = -1;
- }
- // Enter conveniently deactivates the InputText field
- if (ImGui::IsItemDeactivated() && ImGui::IsKeyPressed(ImGuiKey_Enter)) {
- int32 p = 0;
- for (int32 i = 0; i < AmountOf(EffectList); i++) {
- if (State->filter.PassFilter(EffectList[i].Name)) {
- if (EffectSel == p && State->MostRecentlySelectedLayer != -1) {
- AddEffect(File->Layer[State->MostRecentlySelectedLayer], Memory, i);
- State->UpdateFrame = true;
- }
- p++;
- }
- }
- EffectSel = -1;
- }
- int32 p = 0;
- for (int32 i = 0; i < AmountOf(EffectList); i++) {
- if (State->filter.PassFilter(EffectList[i].Name)) {
- bool t = false;
- if (EffectSel == p) {
- t = true;
- }
- ImGui::Selectable(EffectList[i].Name, &t);
- if (ImGui::IsItemClicked()) {
- if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && State->MostRecentlySelectedLayer != -1) {
- AddEffect(File->Layer[State->MostRecentlySelectedLayer], Memory, i);
- State->UpdateFrame = true;
- }
- }
- p++;
- }
- }
- ImGui::End();
-}
-
static char ImGuiPrefs[] = "[Window][DockSpaceViewport_11111111]"
diff --git a/prenderer.cpp b/prenderer.cpp
index 05442f9..929fd9b 100644
--- a/prenderer.cpp
+++ b/prenderer.cpp
@@ -581,6 +581,7 @@ Fallback_RenderDirect(direct_info T, void *OutputBuffer, rectangle RenderRegion)
real32 G_Blend = G_Col;
real32 B_Blend = B_Col;
real32 A_Blend = A_Col;
+
if (LayerAlpha != 1.0f || T.BlendMode != blend_normal) {
Fallback_Blend();
}
diff --git a/strings.cpp b/strings.cpp
index 0842576..d2acc03 100644
--- a/strings.cpp
+++ b/strings.cpp
@@ -37,3 +37,56 @@ String_AddToFile(memory *Memory, char *Char)
}
return FileIndex;
}
+
+static bool32
+String_Compare(char *String1, char *String2, uint32 Length)
+{
+ for (int i = 0; i < Length; i++) {
+ if (String1[i] != String2[i])
+ return 0;
+ }
+ return 1;
+}
+
+static uint32
+String_Length(char *Char)
+{
+ int32 i = 0;
+ while (Char[i] != '\0') {
+ i++;
+ }
+ return i;
+}
+
+static void
+String_Copy(char *String1, char *String2, uint32 Length)
+{
+ int32 i = 0;
+ while (i < Length) {
+ String1[i] = String2[i];
+ i++;
+ }
+}
+
+static void
+String_Append(char *String1, char *String2, uint32 Length)
+{
+ int32 i = 0;
+ while (String1[i] != '\0') {
+ String1[i] = String2[i];
+ }
+}
+
+static void
+String_PathToLayerName(char *Path, char *Dest)
+{
+ uint32 i = 0;
+ uint32 LastSlash = 0;
+ while (Path[i] != '\0') {
+ if (Path[i] == '/')
+ LastSlash = i;
+ i++;
+ }
+ for (int s = 0; s < i - LastSlash; s++)
+ Dest[s] = Path[s + LastSlash + 1];
+}