From cdb9e1f7240cb0716b7d99df5e1fd7c3fc3407a8 Mon Sep 17 00:00:00 2001 From: Fox Caminiti Date: Mon, 5 Dec 2022 21:45:18 -0500 Subject: v2.2, color space + brush improvements --- main.cpp | 190 ++++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 127 insertions(+), 63 deletions(-) (limited to 'main.cpp') diff --git a/main.cpp b/main.cpp index a32598f..de14019 100644 --- a/main.cpp +++ b/main.cpp @@ -68,6 +68,8 @@ static uint64 BitmapBlockSize; static instruction_mode InstructionMode = instruction_mode_scalar; static uint32 RandomGlobalIncrement = 0; +uint32 BitmapFill = 0x00000001; + #if STABLE #include "lib/base64.c" #include @@ -103,7 +105,7 @@ Main_RenderUI(ImGuiIO io, ImVec4 clear_color, SDL_Window *window) } static void -Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI, SDL_Window *window, GLuint textureID) +Main_InputTest(project_data *File, project_state *State, memory *Memory, sorted_file Sorted, ui *UI, SDL_Window *window, GLuint textureID) { ImGuiIO& io = ImGui::GetIO(); SDL_Event event = {}; @@ -138,47 +140,14 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI, } if (!io.WantCaptureKeyboard) - ImGui_ProcessInputs(File, State, UI, Memory, io); - - sorted_file Sorted = File_Sort_Push(File, State, Memory); - - // These depend on sorting, so they can't be done in the ProcessInputs function: - if (State->HotkeyInput) { - switch (State->HotkeyInput) { - case hotkey_none: - { - Assert(0); - } break; - case hotkey_transform: - { - Interact_Transform_Begin(File, Memory, State, io.MousePos, Sorted.CompArray, Sorted.LayerArray); - } break; - case hotkey_copy: - { - Clipboard_Store(File, State, Memory, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyInfo, Sorted.PropertyArray); - } break; - case hotkey_paste: - { - Clipboard_Paste(File, State, Memory, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyArray); - } break; - case hotkey_togglechannels: - { - Project_ToggleAllChannels(File, State, Memory, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyInfo, Sorted.PropertyArray); - } break; - default: - { - Assert(0); - } break; - } - State->HotkeyInput = hotkey_none; - } - + ImGui_ProcessInputs(File, State, UI, Memory, io, Sorted); ImGui::DockSpaceOverViewport(); #if DEBUG if (Debug.ToggleWindow) { ImGui::ShowDemoWindow(); + ImGui_DebugRenderQueue(State); ImGui_DebugMemoryViewer(Memory, State); ImGui_DebugUndoTree(Memory, State); } @@ -199,8 +168,6 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI, ImGui_Menu(File, State, UI, Memory, io); ImGui_Popups(File, State, UI, Memory, io); - File_Sort_Pop(Memory, Sorted.Layer_SortSize, Sorted.Property_SortSize, Sorted.Source_SortSize); - #if DEBUG Debug.Temp = {}; #endif @@ -209,13 +176,15 @@ Main_InputTest(project_data *File, project_state *State, memory *Memory, ui *UI, } static void -Render_Main(void *Data, void *OutputBuffer, render_type RenderType, rectangle RenderRegion) +Render_Main(project_data *File, project_state *State, memory *Memory, sorted_file Sorted, ui *UI, SDL_Window *window, GLuint textureID, + void *Data, void *OutputBuffer, render_type RenderType, rectangle RenderRegion) { bool32 IsRendering = true; Renderer_Start(Data, OutputBuffer, RenderType, RenderRegion); while (IsRendering) { - - // Main_InputTest(File, State, &Memory, &UI); + Main_InputTest(File, State, Memory, Sorted, UI, window, textureID); + // ImGuiIO& io = ImGui::GetIO(); + // Main_RenderUI(io, ImVec4(0.45f, 0.55f, 0.60f, 1.00f), window); Renderer_Check(&IsRendering, RenderType); } } @@ -274,7 +243,7 @@ Layer_UpdateAllKeyframes(project_data *File, project_state *State, memory *Memor } static void * -Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io, +Render_Comp(project_data *File, project_state *State, memory *Memory, sorted_file Sorted, ui *UI, SDL_Window *window, GLuint textureID, ImGuiIO io, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray, uint32 CompIndex, int32 Frame_Current) { @@ -347,7 +316,7 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io BytesPerPixel = Source->BytesPerPixel; } else { block_composition *Precomp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, Layer->Block_Source_Index); - BitmapAddress = Render_Comp(File, State, Memory, io, SortedCompArray, SortedLayerArray, + BitmapAddress = Render_Comp(File, State, Memory, Sorted, UI, window, textureID, io, SortedCompArray, SortedLayerArray, SortedPropertyInfo, SortedPropertyArray, Layer->Block_Source_Index, (int32)Layer->time.CurrentValue); Width = Precomp->Width; Height = Precomp->Height; @@ -364,9 +333,9 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io // TODO(fox): Do all these extra precomputes really make a difference in the renderer? rectangle RenderRegion = { 0, 0, Width, Height }; direct_info Info = { (real32)Width, (real32)Height, (real32)BytesPerPixel, (real32)Width * BytesPerPixel, - Bitmap_ByteInfo(BytesPerPixel), blend_normal, - RenderRegion, State->Brush.TransientBitmap}; - Render_Main((void *)&Info, RenderAddress, render_type_notransform, State->Brush.CacheBounds); + Bitmap_ByteInfo(BytesPerPixel), UI->Color.a, blend_normal, + RenderRegion, State->Brush.TransientBitmap, 0, 0}; + Render_Main(File, State, Memory, Sorted, UI, window, textureID, (void *)&Info, RenderAddress, render_type_notransform, State->Brush.CacheBounds); } else if (Layer->Block_Effect_Count || Layer->Block_Mask_Count) { Layer_UpdateMasksEffects(State, Layer, Memory, RenderAddress, Width, Height, BytesPerPixel); } @@ -377,7 +346,7 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io T.SourceBuffer = RenderAddress; rectangle RenderRegion = {0, 0, Comp->Width, Comp->Height}; - Render_Main((void *)&T, CompBuffer, render_type_main, RenderRegion); + Render_Main(File, State, Memory, Sorted, UI, window, textureID, (void *)&T, CompBuffer, render_type_main, RenderRegion); Memory_PopScratch(Memory, ScratchSize); } } @@ -387,17 +356,57 @@ Render_Comp(project_data *File, project_state *State, memory *Memory, ImGuiIO io } static void -Main_Renderer(project_data *File, project_state *State, memory *Memory, SDL_Window *window, GLuint textureID, ImGuiIO io) +Render_Paint(project_data *File, project_state *State, memory *Memory, sorted_file Sorted, ui *UI, SDL_Window *window, GLuint textureID, ImGuiIO io, v2 LayerPos) { - block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, File->PrincipalCompIndex); + block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, State->Brush.LayerToPaint_Index); + layer_transforms T_Layer = Layer_GetTransforms(Layer); + block_source *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); + + brush_info B; + Brush_Info(&B, &State->Brush, Source, SourceBitmapAddress, LayerPos, UI->Color); + if (State->Brush.Size >= 128) { + Render_Main(File, State, Memory, Sorted, UI, window, textureID, (void *)&B, State->Brush.TransientBitmap, render_type_brush, B.LayerBounds); + } else { + PaintTest(B, State->Brush.TransientBitmap, B.LayerBounds); + } +} - sorted_file Sorted = File_Sort_Push(File, State, Memory); +static void +Render_Blit(project_data *File, project_state *State, memory *Memory, sorted_file Sorted, ui *UI, SDL_Window *window, GLuint textureID, ImGuiIO io, v2 LayerPos) +{ + block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, State->Brush.LayerToPaint_Index); + layer_transforms T_Layer = Layer_GetTransforms(Layer); + block_source *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); + rectangle RenderRegion = { 0, 0, Source->Width, Source->Height }; + direct_info Info = { (real32)Source->Width, (real32)Source->Height, (real32)Source->BytesPerPixel, (real32)Source->Width * Source->BytesPerPixel, + Bitmap_ByteInfo(Source->BytesPerPixel), UI->Color.a, blend_normal, + RenderRegion, State->Brush.TransientBitmap, 1, 0}; + Render_Main(File, State, Memory, Sorted, UI, window, textureID, (void *)&Info, SourceBitmapAddress, render_type_notransform_swap, State->Brush.CacheBounds); + uint64 BitmapSize = Source->Width * Source->Height * Source->BytesPerPixel; + History_Entry_Commit(Memory, "Paintbrush stroke"); + History_Action_BitmapPaint(Memory, BitmapSize, SourceBitmapAddress, State->Brush.TransientBitmap, Source->BytesPerPixel); + History_Entry_End(Memory); + State->Brush.LayerToPaint_Index = -1; + State->Brush.PrevPos = V2(-4000, -4000); + State->Brush.CacheBounds = { 99999, 99999, -99999, -99999 }; + State->Interact_Active = interact_type_none; + State->Interact_Modifier = 0; + State->UpdateFrame = true; +} - void *MainCompBuffer = Render_Comp(File, State, Memory, io, Sorted.CompArray, Sorted.LayerArray, - Sorted.PropertyInfo, Sorted.PropertyArray, File->PrincipalCompIndex, State->Frame_Current); +static void +Main_Renderer(project_data *File, project_state *State, memory *Memory, sorted_file Sorted, ui *UI, SDL_Window *window, GLuint textureID, ImGuiIO io) +{ + State->UpdateFrame = false; + State->UpdateKeyframes = false; - File_Sort_Pop(Memory, Sorted.Layer_SortSize, Sorted.Property_SortSize, Sorted.Source_SortSize); + block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, File->PrincipalCompIndex); + void *MainCompBuffer = Render_Comp(File, State, Memory, Sorted, UI, window, textureID, io, Sorted.CompArray, Sorted.LayerArray, + Sorted.PropertyInfo, Sorted.PropertyArray, File->PrincipalCompIndex, State->Frame_Current); + Bitmap_SRGBToLinear(MainCompBuffer, MainComp->Width, MainComp->Height, MainComp->BytesPerPixel, 0); glBindTexture(GL_TEXTURE_2D, textureID); int ByteFlag2 = (MainComp->BytesPerPixel == 4) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT; @@ -408,9 +417,6 @@ Main_Renderer(project_data *File, project_state *State, memory *Memory, SDL_Wind glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, MainComp->Width, MainComp->Height, GL_RGBA, ByteFlag2, MainCompBuffer); // TODO(fox): garbage collect AV state! - - State->UpdateFrame = false; - State->UpdateKeyframes = false; } int main(int argc, char *argv[]) { @@ -596,7 +602,7 @@ int main(int argc, char *argv[]) { // loaded from disk or memory. io.IniFilename = NULL; ImGui::LoadIniSettingsFromMemory(ImGuiPrefs); - // // ImGui::SaveIniSettingsToDisk("imgui.ini"); + // ImGui::SaveIniSettingsToDisk("imgui.ini"); ImGui::StyleColorsDark(); @@ -625,7 +631,7 @@ int main(int argc, char *argv[]) { #if DEBUG #if 1 - sprintf(State->DummyName, "test2"); + sprintf(State->DummyName, "test"); File_Open(File, State, &Memory, State->DummyName); State->UpdateFrame = true; State->MostRecentlySelectedLayer = 0; @@ -634,16 +640,54 @@ int main(int argc, char *argv[]) { while (State->IsRunning) { - // State->Interact_Active = interact_type_layer_move; - // State->Interact_Offset[1] = -3.0f; - #if STABLE if (State->CurlActive) { Curl_Main(File, State, &Memory, &MainHandle, &ProgHandle); } #endif - Main_InputTest(File, State, &Memory, &File->UI, window, textureID); + // NOTE(fox): These commands affect sorting, and should not be executed + // in any UI or the renderer. + if (State->HotkeyInput) { + switch (State->HotkeyInput) { + case hotkey_none: + { + Assert(0); + } break; + case hotkey_newpaintlayer: + { + Project_PaintLayer_New(File, State, &Memory); + } break; + case hotkey_newlayerfromsource: + { + Source_UICreateButton(File, State, &Memory); + State->UpdateKeyframes = true; + } break; + case hotkey_deletelayer: + { + Project_Layer_Delete(File, State, &Memory); + } break; + case hotkey_undo: + { + History_Undo(&Memory); + State->UpdateFrame = true; + } break; + case hotkey_redo: + { + History_Redo(&Memory); + State->UpdateFrame = true; + } break; + default: + { + Assert(0); + } break; + } + State->HotkeyInput = hotkey_none; + } + + sorted_file Sorted = File_Sort_Push(File, State, &Memory); + + Main_InputTest(File, State, &Memory, Sorted, &File->UI, window, textureID); if (State->IsPlaying) { block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(&Memory, F_Precomps, File->PrincipalCompIndex); @@ -653,8 +697,28 @@ int main(int argc, char *argv[]) { } if (State->UpdateFrame) { - Main_Renderer(File, State, &Memory, window, textureID, io); + State->Queue.CurrentIdx++; } + for (int i = 0; i < State->Queue.CurrentIdx; i++) { + render_queue_item Item = State->Queue.Item[i]; + State->Queue.Playhead = i; + if (Item.Type == 0) { + Main_Renderer(File, State, &Memory, Sorted, &File->UI, window, textureID, io); + } else if (Item.Type == 1) { + Assert(State->Interact_Active == interact_type_brush); + Render_Paint(File, State, &Memory, Sorted, &File->UI, window, textureID, io, Item.Pos); + } else if (Item.Type == 2) { + Assert(State->Interact_Active == interact_type_brush); + Render_Blit(File, State, &Memory, Sorted, &File->UI, window, textureID, io, Item.Pos); + } else { + Assert(0); + } + } + State->Queue.CurrentIdx = 0; + State->Queue.Playhead = 0; + Arbitrary_Zero((uint8 *)State->Queue.Item, sizeof(State->Queue.Item)); + + File_Sort_Pop(&Memory, Sorted.Layer_SortSize, Sorted.Property_SortSize, Sorted.Source_SortSize); Assert(Debug.ScratchState == 0); -- cgit v1.2.3