internal void IncrementFrame(project_data *File, int16 Amount) { if ((File->CurrentFrame <= 0 && Amount < File->StartFrame) || (File->CurrentFrame >= File->EndFrame)) { File->CurrentFrame = 0; } else { File->CurrentFrame += Amount; } } internal pixel_buffer CreateBuffer(int Width, int Height, memory *Memory) { pixel_buffer Buffer = {}; Buffer.BytesPerPixel = 4; Buffer.OriginalBuffer = AllocateMemory(Memory, Width * Height * Buffer.BytesPerPixel, B_Scratch); Buffer.EffectBuffer = AllocateMemory(Memory, Width * Height * Buffer.BytesPerPixel, B_Scratch); Buffer.Width = Width; Buffer.Height = Height; #if PACKEDRGB Buffer.Pitch = Buffer.Width*Buffer.BytesPerPixel; #else Buffer.Pitch = Buffer.Width; // each row has only 1 byte, 8 bits, per pixel Buffer.Channel = Buffer.Width*Buffer.Height; #endif Buffer.ToUpdate = true; return Buffer; } internal void AddSource(project_data *File, memory *Memory, char *Path) { int16 a = File->NumberOfSources++; Assert(a < MAX_SOURCES); if (Path == NULL) { File->Source[a] = (char *)AllocateMemory(Memory, STRING_SIZE, F_Strings); } else { File->Source[a] = Path; } } internal pixel_buffer CreateDebugBitmap(int16 Width, int16 Height, memory *Memory) { pixel_buffer Raster = CreateBuffer(Width, Height, Memory); uint32 Channel = (Raster.Width * Raster.Height); uint8 inc = 0; uint8 incY = 0; for (uint32 Y = 0; Y < Raster.Height; Y+=1) { for (uint32 X = 0; X < Raster.Width; X+=1) { #if PACKEDRGB uint8 *Pix = ((uint8 *)Raster.OriginalBuffer + (Raster.Pitch*Y) + X*Raster.BytesPerPixel); uint32 *Pixel = (uint32 *)Pix; *Pixel = ( (X << 0) | (Y << 8) | (0xaa << 16) | (0xff << 24)); inc++; #else uint8 *Pix = ((uint8 *)Raster.OriginalBuffer + (Raster.Pitch*Y) + X); uint8 *Pix2 = ((uint8 *)Raster.OriginalBuffer + Channel + (Raster.Pitch*Y) + X); uint8 *Pix3 = ((uint8 *)Raster.OriginalBuffer + Channel*2 + (Raster.Pitch*Y) + X); uint8 *PixA = ((uint8 *)Raster.OriginalBuffer + Channel*3 + (Raster.Pitch*Y) + X); // if (X == 0 && Y == 1) { // *Pix++ = 0xaa; // inc++; // } else if (X == 0 && Y == 2) { // *Pix++ = 0xbb; // inc++; // } else if (X == 0 && Y == 3) { // *Pix++ = 0xcc; // inc++; // } else { *Pix++ = 16*inc++; *Pix2++ = 16*incY; *Pix3++ = 0xaa; *PixA++ = 0xff; // } #endif } incY++; } return Raster; } internal void ClearBuffer(pixel_buffer *Buffer) { 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) { *(uint32 *)Pixel++ = 0x00000000; } Row += Buffer->Pitch; } } #if PACKEDRGB internal void Unpack4x4Chunk(pixel_buffer *Buffer) { uint8 *Src = (uint8 *)Buffer->OriginalBuffer; uint8 *Temp = (uint8 *)Buffer->EffectBuffer; uint32 bytes = 0; for (uint32 Y = 0; Y < Buffer->Height; Y+=4) { uint8 *DPixel1 = Temp + Y*Buffer->Pitch; uint8 *DPixel2 = Temp + (Y+1)*Buffer->Pitch; uint8 *DPixel3 = Temp + (Y+2)*Buffer->Pitch; uint8 *DPixel4 = Temp + (Y+3)*Buffer->Pitch; for (uint32 X = 0; X < Buffer->Width; X+=4) { uint8 *Pixel1 = Src + bytes; uint8 *Pixel2 = Pixel1 + 4*Buffer->BytesPerPixel; uint8 *Pixel3 = Pixel1 + 4*Buffer->BytesPerPixel*2; uint8 *Pixel4 = Pixel1 + 4*Buffer->BytesPerPixel*3; __m128i Row1 = _mm_loadu_si128((__m128i *)Pixel1); __m128i Row2 = _mm_loadu_si128((__m128i *)Pixel2); __m128i Row3 = _mm_loadu_si128((__m128i *)Pixel3); __m128i Row4 = _mm_loadu_si128((__m128i *)Pixel4); _mm_storeu_si128((__m128i *)DPixel1, Row1); DPixel1 += 4*Buffer->BytesPerPixel; _mm_storeu_si128((__m128i *)DPixel2, Row2); DPixel2 += 4*Buffer->BytesPerPixel; _mm_storeu_si128((__m128i *)DPixel3, Row3); DPixel3 += 4*Buffer->BytesPerPixel; _mm_storeu_si128((__m128i *)DPixel4, Row4); DPixel4 += 4*Buffer->BytesPerPixel; bytes += 16*Buffer->BytesPerPixel; } } } internal void Store4x4Chunk(pixel_buffer *Buffer) { #if 1 uint8 *Src = (uint8 *)Buffer->OriginalBuffer; uint8 *Temp = (uint8 *)Buffer->EffectBuffer; for (uint32 Y = 0; Y+4 < Buffer->Height; Y+=4) { uint8 *DPixel = Temp + Y*Buffer->Pitch; for (uint32 X = 0; X < Buffer->Width; X+=4) { uint8 *Pixel1 = Src + Y*Buffer->Pitch + X*Buffer->BytesPerPixel; uint8 *Pixel2 = Pixel1 + Buffer->Pitch; uint8 *Pixel3 = Pixel1 + Buffer->Pitch*2; uint8 *Pixel4 = Pixel1 + Buffer->Pitch*3; // NOTE(fox): Remember this is RGB packed, so 128-bit registers hold 4 pixels. __m128i Row1 = _mm_loadu_si128((__m128i *)Pixel1); __m128i Row2 = _mm_loadu_si128((__m128i *)Pixel2); __m128i Row3 = _mm_loadu_si128((__m128i *)Pixel3); __m128i Row4 = _mm_loadu_si128((__m128i *)Pixel4); _mm_storeu_si128((__m128i *)DPixel, Row1); DPixel += 4*Buffer->BytesPerPixel; _mm_storeu_si128((__m128i *)DPixel, Row2); DPixel += 4*Buffer->BytesPerPixel; _mm_storeu_si128((__m128i *)DPixel, Row3); DPixel += 4*Buffer->BytesPerPixel; _mm_storeu_si128((__m128i *)DPixel, Row4); DPixel += 4*Buffer->BytesPerPixel; } // TODO(fox): Clear the last row if the buffer isn't divisible by 4. } #else for (uint32 Y = 0; Y < Buffer->Height; Y+=1) { uint8 *DPixel = Temp + Y*Buffer->Pitch; for (uint32 X = 0; X < Buffer->Width; X+=1) { uint32 XLookup = (X >> 2)*16 + (X % 4); uint32 YLookup = (Y >> 2)*(Buffer->Width*4) + (Y % 4)*4; uint32 PixelToSeek = XLookup + YLookup; uint32 Pixel = *(uint32 *)((uint8 *)Buffer->EffectBuffer + PixelToSeek*Buffer->BytesPerPixel); uint8 Xp = Pixel & 0xFF; uint8 Yp = (Pixel >> 8) & 0xFF; printf("X %u, Y %u, val: %i, %i\n", X, Y, Xp, Yp); } } __m256i PixelX0 = _mm256_setr_epi32(0, 1, 2, 3, 4, 5, 6, 7); __m256i FF = _mm256_set1_epi32(8); uint8 *Src = (uint8 *)Buffer->EffectBuffer; for (int i = 0; i < 16; i++) { _mm256_storeu_si256((__m256i *)Src, PixelX0); Src += 32; PixelX0 = _mm256_add_epi32(PixelX0, FF); } uint32 Width = 3; for (uint32 Y = 0; Y < 4*2; Y++) { for (uint32 X = 0; X < 4*3; X++) { uint32 XLookup = (X >> 2)*16 + (X % 4); uint32 YLookup = (Y >> 2)*(Width*16) + (Y % 4)*4; uint32 PixelToSeek = XLookup + YLookup; uint32 Pixel = *((uint8 *)Buffer->EffectBuffer + PixelToSeek*Buffer->BytesPerPixel); printf("X %u, Y %u, %i\n", X, Y, Pixel); } } Assert(0); #endif } #else internal void PackBitmapRGB(pixel_buffer *Buffer) { uint8 *Row = (uint8 *)Buffer->OriginalBuffer; uint8 *PackedRow = (uint8 *)Buffer->EffectBuffer; for (uint32 Y = 0; Y < Buffer->Height; Y++) { uint32 *Pixel = (uint32 *)PackedRow; for (uint32 X = 0; X < Buffer->Width; X++) { uint8 *ValR = (uint8 *)Row + X; // if (X > 16 && Y > 16) { // Assert(*ValR == 0); // } uint8 *ValG = ValR + Buffer->Channel; uint8 *ValB = ValR + Buffer->Channel*2; uint8 *ValA = ValR + Buffer->Channel*3; *Pixel = ( (*ValR << 0) | (*ValG << 8) | (*ValB << 16) | (*ValA << 24)); Pixel++; } Row += Buffer->Pitch; PackedRow += Buffer->Pitch*Buffer->BytesPerPixel; } } // TODO(fox): Libav only exports GBRA array frames for some reason; see if you // can mod the source if you end up not using packed RGB. internal void Libav_GBRAToRGBA(pixel_buffer *Raster) { uint8 *Row = ((uint8 *)Raster->OriginalBuffer); uint32 bytes = 0; __m128i Zero = _mm_setzero_si128(); while (bytes <= Raster->Height*Raster->Width) { uint8 *ChannelG = (uint8 *)Row + bytes; uint8 *ChannelB = (uint8 *)Row + bytes + Raster->Channel; uint8 *ChannelR = (uint8 *)Row + bytes + Raster->Channel*2; __m128i RegG = _mm_loadu_si128((__m128i *)ChannelG); __m128i RegB = _mm_loadu_si128((__m128i *)ChannelB); __m128i RegR = _mm_loadu_si128((__m128i *)ChannelR); _mm_storeu_si128((__m128i *)ChannelG, RegR); _mm_storeu_si128((__m128i *)ChannelB, RegG); _mm_storeu_si128((__m128i *)ChannelR, RegB); bytes += 16; } } #endif // 0 - original // 1 - effect // 2 - both internal void SSE_ClearBuffer(pixel_buffer *Raster, uint16 Which = 2) { uint8 *Row = ((uint8 *)Raster->OriginalBuffer); uint8 *Row2 = ((uint8 *)Raster->EffectBuffer); uint32 bytes = 0; __m128i Zero = _mm_setzero_si128(); while (bytes <= Raster->Height*Raster->Width*4) { if (Which == 2 || Which == 0) { uint8 *Pixel = (uint8 *)Row + bytes; _mm_storeu_si128((__m128i *)Pixel, Zero); } if (Which == 2 || Which == 1) { uint8 *Pixel2 = (uint8 *)Row2 + bytes; _mm_storeu_si128((__m128i *)Pixel2, Zero); } bytes += 16; } } // 0 - original -> effect // 1 - effect -> original internal void SSE_CopyToBuffer(pixel_buffer *Raster, uint16 Which) { uint8 *Row = ((uint8 *)Raster->OriginalBuffer); uint8 *Row2 = ((uint8 *)Raster->EffectBuffer); uint32 bytes = 0; while (bytes <= Raster->Height*Raster->Width*4) { uint8 *Pixel = (uint8 *)Row + bytes; uint8 *Pixel2 = (uint8 *)Row2 + bytes; if (Which == 0) { __m128i OutputPixel = _mm_loadu_si128((__m128i *)Pixel); _mm_storeu_si128((__m128i *)Pixel2, OutputPixel); } else { __m128i OutputPixel = _mm_loadu_si128((__m128i *)Pixel2); _mm_storeu_si128((__m128i *)Pixel, OutputPixel); } bytes += 16; } } internal void DebugFillSolid(pixel_buffer *Raster, v4 Color) { __m128i Col = _mm_set1_epi32(ColToUint32(Color)); uint8 *Row = ((uint8 *)Raster->OriginalBuffer); uint32 bytes = 0; while (bytes <= Raster->Height*Raster->Width*4) { uint8 *Pixel = (uint8 *)Row + bytes; _mm_storeu_si128((__m128i *)Pixel, Col); bytes += 16; } } internal void BitmapPackRGB(pixel_buffer *Buffer) { #if PACKEDRGB Buffer->Pitch = Buffer->Width*Buffer->BytesPerPixel; #else Buffer->Pitch = Buffer->Width; // each row has only 1 byte, 8 bits, per pixel Buffer->Channel = Buffer->Width*Buffer->Height; #endif #if PACKEDRGB Store4x4Chunk(Buffer); SSE_CopyToBuffer(Buffer, 1); SSE_ClearBuffer(Buffer, 1); #else Libav_GBRAToRGBA(Buffer); #endif } internal pixel_buffer LoadImage(memory *Memory, char *filename) { pixel_buffer Buffer = {}; Buffer.BytesPerPixel = 4; int n = 0; int h, w; Buffer.OriginalBuffer = stbi_load(filename, &w, &h, &n, 4); Buffer.EffectBuffer = AllocateMemory(Memory, w * h * Buffer.BytesPerPixel, B_Scratch); Buffer.Height = h; Buffer.Width = w; // printf("%s", stbi_failure_reason()); BitmapPackRGB(&Buffer); Buffer.ToUpdate = true; return Buffer; } internal pixel_buffer CreateSolidBitmap(memory *Memory, uint16 Height, uint16 Width, v4 Color) { pixel_buffer Buffer = {}; Buffer.BytesPerPixel = 4; Buffer.OriginalBuffer = AllocateMemory(Memory, Height * Width * Buffer.BytesPerPixel, B_Scratch); Buffer.EffectBuffer = AllocateMemory(Memory, Height * Width * Buffer.BytesPerPixel, B_Scratch); Buffer.Height = Height; Buffer.Width = Width; DebugFillSolid(&Buffer, Color); BitmapPackRGB(&Buffer); Buffer.ToUpdate = true; return Buffer; } internal void DrawHistogram(project_layer *Layer, pixel_buffer *UIBuffer, void *Scratch, memory *Memory, sdl_input Input, project_state *State, rectangle Box) { uint16 Padding = 20; //UI->LayerPadding / 5; uint16 Margin = 100; uint16 *Levels = (uint16 *)Scratch; uint16 *Mean = (Levels + 256*7); uint32 Color = 0; uint32 AltColor = ColToUint32(V4(0.1,0.1,0.1,1.0)); // this is a bad idea real32 *Zoom = (real32 *)(Levels + 256*6); if (*Zoom < 0.0f) *Zoom = 0.0f; uint16 *SelectedChannel = (uint16 *)(Levels + 256*6 + 3); if (*SelectedChannel == 0) { Color = ColToUint32(V4(0.6,0.6,0.6,1.0)); } else if (*SelectedChannel == 1) { Levels += 256; Color = ColToUint32(V4(0.6,0.0,0.0,1.0)); } else if (*SelectedChannel == 2) { Levels += 256*2; Color = ColToUint32(V4(0.0,0.6,0.0,1.0)); } else if (*SelectedChannel == 3) { Levels += 256*3; Color = ColToUint32(V4(0.0,0.0,0.6,1.0)); } else if (*SelectedChannel == 4) { Levels += 256*4; Color = ColToUint32(V4(0.9,0.9,0.9,1.0)); } /* if (TestRectangle(Box, Input.Mouse) && Input.MouseButton[0].IsDown) { State->ArbitrarySlide = 1; State->Sliding.RandomPointer = Zoom; } */ uint8 *Row = ((uint8 *)UIBuffer->OriginalBuffer + UIBuffer->BytesPerPixel + UIBuffer->Pitch); for (int Y = 0; Y > Box.Min.y; Y--) { uint32 *Pixel = (uint32 *)Row + Box.Min.x; for(int X = Box.Min.x; X < Box.Max.x; ++X) { real32 Span = (Box.Max.x - Box.Min.x) / 256.0f; int16 XLocal = (X - Box.Min.x) / Span; int16 YLocal = -(Y - Box.Max.y); if (*(Levels + XLocal) > (YLocal * RoundReal32ToInt32(*Zoom)) && XLocal < 256) *Pixel++ = Color; else *Pixel++ = AltColor; } Row -= UIBuffer->Pitch; } } internal void DebugBitmap(pixel_buffer *Raster) { #if 0 for (uint32 Y = 0; Y < Raster->Height; Y+=2) { for (uint32 X = 0; X < Raster->Width; X+=32) { for (uint32 pp = 0; pp < 4; pp++) { uint32 Increment = ((uint32)Raster->Width*Y*4) + X + pp*8; uint32 Increment2 = ((uint32)Raster->Width*(Y+1)*4) + X + pp*8; uint8 *TexPTR = ((uint8 *)Raster->OriginalBuffer + Increment); uint8 *TexPTR2 = ((uint8 *)Raster->OriginalBuffer + Increment2); uint8 *TexPTR3 = ((uint8 *)Raster->OriginalBuffer + Increment + 4); uint8 *TexPTR4 = ((uint8 *)Raster->OriginalBuffer + Increment2 + 4); if (pp == 0) { // *(uint32 *)TexPTR = 0x5f5e5d5c; // *(uint32 *)TexPTR2 = 0x4f4e4d4c; // *(uint32 *)TexPTR3 = 0x3f3e3d3c; // *(uint32 *)TexPTR4 = 0x2f2e2d2c; // *(uint32 *)TexPTR3 = 0xaaaaaaaa; // *(uint32 *)TexPTR4 = 0xaaaaaaaa; *(uint32 *)TexPTR = 0xcccaccc1; *(uint32 *)TexPTR2 = 0xdddaddd1; *(uint32 *)TexPTR3 = 0xeeeaeee1; *(uint32 *)TexPTR4 = 0xfffafff1; } else if (pp == 1) { // *(uint32 *)TexPTR = 0xb2a2b1a1; // *(uint32 *)TexPTR = 0xd2c2d1c1; // *(uint32 *)TexPTR3 = 0xbbaabbaa; // *(uint32 *)TexPTR4 = 0xddccddcc; *(uint32 *)TexPTR = 0xccccccc2; *(uint32 *)TexPTR2 = 0xddddddd2; *(uint32 *)TexPTR3 = 0xeeeeeee2; *(uint32 *)TexPTR4 = 0xfffffff2; } else if (pp == 2) { *(uint32 *)TexPTR = 0xccccccc3; *(uint32 *)TexPTR2 = 0xddddddd3; *(uint32 *)TexPTR3 = 0xeeeeeee3; *(uint32 *)TexPTR4 = 0xfffffff3; } else { *(uint32 *)TexPTR = 0xccccccc4; *(uint32 *)TexPTR2 = 0xddddddd4; *(uint32 *)TexPTR3 = 0xeeeeeee4; *(uint32 *)TexPTR4 = 0xfffffff4; } } } } #endif #if 0 uint32 Channel = (Raster->Width * Raster->Height)*4; for (uint32 Y = 0; Y < Raster->Height; Y+=2) { for (uint32 X = 0; X < Raster->Width; X+=2) { uint8 *TopL = ((uint8 *)Raster->OriginalBuffer + (Raster->Width*Y*4) + X); uint8 *TopL2 = ((uint8 *)Raster->OriginalBuffer + (Raster->Width*Y*4) + X + Channel); uint8 *TopL3 = ((uint8 *)Raster->OriginalBuffer + (Raster->Width*Y*4) + X + Channel*2); uint8 *TopR = TopL + 1; uint8 *TopR2 = TopL2 + 1; uint8 *TopR3 = TopL3 + 1; uint8 *BotL = ((uint8 *)Raster->OriginalBuffer + (Raster->Width*(Y+1)*4) + X); uint8 *BotL2 = ((uint8 *)Raster->OriginalBuffer + (Raster->Width*(Y+1)*4) + X + Channel); uint8 *BotL3 = ((uint8 *)Raster->OriginalBuffer + (Raster->Width*(Y+1)*4) + X + Channel*2); uint8 *BotR = BotL + 1; uint8 *BotR2 = BotL2 + 1; uint8 *BotR3 = BotL3 + 1; *TopL = 0xff; *TopL2 = 0x00; *TopL3 = 0x00; *TopR = 0xcc; *TopR2 = 0xff; *TopR3 = 0x00; *BotL = 0x55; *BotL2 = 0x00; *BotL3 = 0xff; *BotR = 0x00; *BotR2 = 0xff; *BotR3 = 0xff; } } #endif #if 1 uint32 Channel = (Raster->Width * Raster->Height); uint32 Width = 10; uint8 inc = 0; uint8 incY = 0; for (uint32 Y = 0; Y < Raster->Height; Y+=1) { for (uint32 X = 0; X < Width; X+=1) { uint8 *Pix = ((uint8 *)Raster->OriginalBuffer + (Raster->Pitch*Y) + X); uint8 *Pix2 = ((uint8 *)Raster->OriginalBuffer + Channel + (Raster->Pitch*Y) + X); // if (X == 0 && Y == 1) { // *Pix++ = 0xaa; // inc++; // } else if (X == 0 && Y == 2) { // *Pix++ = 0xbb; // inc++; // } else if (X == 0 && Y == 3) { // *Pix++ = 0xcc; // inc++; // } else { *Pix++ = inc++; *Pix2++ = incY; // } } incY++; } #endif for (uint32 Y = 0; Y < Raster->Height; Y+=2) { for (uint32 X = 0; X < Raster->Width; X+=32) { uint32 Channel = (Raster->Width * Raster->Height)*4; for (int16 i = 0; i < 4; i++) { uint32 Increment = (Raster->Width*Y*4) + X + Channel*i; uint32 Increment2 = (Raster->Width*(Y+1)*4) + X + Channel*i; uint8 *TexPTR = ((uint8 *)Raster->OriginalBuffer + Increment); uint8 *Pixel = ((uint8 *)Raster->EffectBuffer + Increment); uint8 *TexPTR2 = ((uint8 *)Raster->OriginalBuffer + Increment2); uint8 *Pixel2 = ((uint8 *)Raster->EffectBuffer + Increment2); __m256i T1 = _mm256_loadu_si256((__m256i *)TexPTR); __m256i T2 = _mm256_loadu_si256((__m256i *)TexPTR2); __m256i pp = _mm256_unpackhi_epi16(T1, T2); __m256i pp2 = _mm256_unpacklo_epi16(T1, T2); __m256i pp3 = _mm256_unpacklo_epi64(pp2, pp); __m256i pp4 = _mm256_unpackhi_epi64(pp2, pp); __m256i T4 = _mm256_permute2x128_si256(pp2, pp, 32); __m256i T5 = _mm256_permute2x128_si256(pp2, pp, 53); _mm256_storeu_si256((__m256i *)Pixel, T1); _mm256_storeu_si256((__m256i *)Pixel2, T2); } } } // _mm256_unpackhi_epi8 // for (int Y = 0; Y < Raster.Height; Y+=2) { // for (int X = 0; X < Raster.Width; X+=2) { // uint8 *Row = ((uint8 *)UIBuffer->OriginalBuffer + // } // } } internal property_channel InitFloatProperty(char *Name, real32 Val, real32 ScrubVal, real32 MinVal = PROPERTY_REAL_MIN, real32 MaxVal = PROPERTY_REAL_MAX) { property_channel Property = {}; Property.Name = Name; Property.CurrentValue.f = Val; Property.MinVal.f = MinVal; Property.MaxVal.f = MaxVal; Property.ScrubVal.f = ScrubVal; Property.VarType = type_real; Property.GraphWindowHeight = 300; return Property; } internal bool32 IsSupportedFile(source_type *Type, char *filename) { bool32 Result = 0; if (stbi_info(filename, NULL, NULL, NULL)) { *Type = source_image; Result = 1; } else if (TestAV(filename)) { *Type = source_video; Result = 1; } return Result; } internal void CreateRenderInfo(project_layer *Layer, memory *Memory, project_data File, source_type Type, char *filename) { if (Type == source_image) { Layer->RenderInfo = AllocateMemory(Memory, sizeof(image_source), P_SourceData); image_source *Source = (image_source *)Layer->RenderInfo; Source->Raster = LoadImage(Memory, filename); Layer->SourceType = source_image; Layer->x.CurrentValue.f = 1280/2; Layer->y.CurrentValue.f = 720/2; Layer->StartFrame = 0; Layer->EndFrame = File.EndFrame; } else if (Type == source_video) { Layer->RenderInfo = AllocateMemory(Memory, sizeof(video_source), P_SourceData); video_source *Source = (video_source *)Layer->RenderInfo; InitAV(filename, &Source->AV); Layer->SourceType = source_video; Source->VideoCurrentFrame = -1; int32 Width = Source->AV.VideoCodecContext->width; int32 Height = Source->AV.VideoCodecContext->height; Source->Raster = CreateBuffer(Width, Height, Memory); Layer->x.CurrentValue.f = 1280/2; Layer->y.CurrentValue.f = 720/2; Layer->StartFrame = 0; Layer->EndFrame = File.EndFrame; } else { Assert(0); } } internal void CreateKeyframeBlock(property_channel *Property, memory *Memory) { int16 a = Property->NumberOfKeyframeBlocks++; Assert(a < MAX_KEYFRAME_BLOCKS); Property->KeyframeBlock[a] = (keyframe_block *)AllocateMemory(Memory, sizeof(keyframe_block), F_Keyframes); } internal project_layer * CreateLayer(project_data *File, memory *Memory) { int16 a = File->NumberOfLayers++; Assert(a < MAX_LAYERS); File->Layer[a] = (project_layer *)AllocateMemory(Memory, sizeof(project_layer), F_Layers); File->Layer[a]->Name = (char *)AllocateMemory(Memory, 256, F_Strings); sprintf(File->Layer[a]->Name, "Layer %i", a); File->Layer[a]->x = InitFloatProperty("X Position", 0.0f, 1.0f); File->Layer[a]->y = InitFloatProperty("Y Position", 0.0f, 1.0f); File->Layer[a]->ax = InitFloatProperty("Anchor X", 0.5f, 0.005f); File->Layer[a]->ay = InitFloatProperty("Anchor Y", 0.5f, 0.005f); File->Layer[a]->scale = InitFloatProperty("Scale", 1.0f, 0.005f); File->Layer[a]->rotation = InitFloatProperty("Rotation", 0.0f, 1.0f); File->Layer[a]->opacity = InitFloatProperty("Opacity", 1.0f, 0.005f, 0.0f, 1.0f); File->Layer[a]->time = InitFloatProperty("Frame Number", 0.0f, 1.0f, 0, 100000); File->Layer[a]->EndFrame = File->NumberOfFrames; return File->Layer[a]; } internal void PostMsg(project_state *State, char *msg) { State->MsgTime = 120; State->Msg = msg; } internal void CreateLayerFromSource(project_data *File, project_state *State, memory *Memory, char *filename) { source_type Type = source_none; if (IsSupportedFile(&Type, filename)) { project_layer *Layer = CreateLayer(File, Memory); CreateRenderInfo(Layer, Memory, *File, Type, filename); State->UpdateFrame = true; State->DemoButton = true; } else { PostMsg(State, "File open fail..."); } } internal project_layer * CreateSolidLayer(project_data *File, memory *Memory, uint16 Width, uint16 Height, v4 Col) { project_layer *Layer = CreateLayer(File, Memory); Layer->RenderInfo = AllocateMemory(Memory, sizeof(image_source), P_SourceData); image_source *Source = (image_source *)Layer->RenderInfo; Source->Raster = CreateSolidBitmap(Memory, Width, Height, Col); Layer->SourceType = source_image; return Layer; } internal void CreateDemoScene(project_data *File, memory *Memory) { project_layer *Layer1 = CreateSolidLayer(File, Memory, 720, 1280, V4(0.0, 0.0, 0.0, 1.0)); Layer1->x.CurrentValue.f = 1280/2; Layer1->y.CurrentValue.f = 720/2; Layer1->StartFrame = 0; Layer1->EndFrame = File->EndFrame; project_layer *Layer2 = CreateSolidLayer(File, Memory, 500, 500, V4(0.0, 1.0, 0.4, 1.0)); Layer2->x.CurrentValue.f = 1280/2; Layer2->y.CurrentValue.f = 720/2; Layer2->StartFrame = 0; Layer2->EndFrame = File->EndFrame; ManualKeyframeInsertF(&Layer2->rotation, Memory, 2, 0); ManualKeyframeInsertF(&Layer2->rotation, Memory, 50, 360); Layer2->rotation.IsToggled = true; Layer2->scale.IsToggled = true; project_layer *Layer3 = CreateSolidLayer(File, Memory, 160, 160, V4(1.0, 0.3, 0.2, 1.0)); Layer3->x.CurrentValue.f = 1280/4; Layer3->y.CurrentValue.f = 720/4; Layer3->opacity.CurrentValue.f = 0.5f; Layer3->StartFrame = 0; Layer3->EndFrame = File->EndFrame; ManualKeyframeInsertF(&Layer3->x, Memory, 2, Layer3->x.CurrentValue.f); ManualKeyframeInsertF(&Layer3->x, Memory, 30, Layer3->x.CurrentValue.f+(1280/2)); ManualKeyframeInsertF(&Layer3->x, Memory, 60, Layer3->x.CurrentValue.f+(1280/3)); Layer3->x.IsToggled = true; Layer3->y.IsToggled = true; }