From fd315f15828b8537a48530c094ced845edc3a1d3 Mon Sep 17 00:00:00 2001 From: Fox Caminiti Date: Wed, 23 Nov 2022 20:39:55 -0500 Subject: effects reintroduction --- createcalls.cpp | 87 ++++++- effects.cpp | 665 +---------------------------------------------- effects_constructors.cpp | 107 ++++++++ effects_gl_shader.cpp | 57 ++++ effects_software.cpp | 216 ++++----------- functions.h | 4 + gl_calls.cpp | 168 +++--------- main.cpp | 152 ++++++----- main.h | 108 +++++--- my_imgui_widgets.cpp | 300 ++++++++++++++------- prenderer.cpp | 1 + strings.cpp | 53 ++++ 12 files changed, 761 insertions(+), 1157 deletions(-) create mode 100644 effects_constructors.cpp create mode 100644 effects_gl_shader.cpp 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]; +} -- cgit v1.2.3