diff options
Diffstat (limited to 'my_imgui_widgets.cpp')
-rw-r--r-- | my_imgui_widgets.cpp | 3328 |
1 files changed, 0 insertions, 3328 deletions
diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp deleted file mode 100644 index f267f67..0000000 --- a/my_imgui_widgets.cpp +++ /dev/null @@ -1,3328 +0,0 @@ -#include "my_imgui_internal_widgets.h" -#include "imgui_ops.h" - -#include "imgui_helper_widgets.cpp" - -static void -ImGui_PropertyInteract_Slider(project_state *State, memory *Memory, property_channel *Property, ImGuiIO &io, ImVec2 WindowMinAbs, ImVec2 WindowMaxAbs, memory_table_list Table) -{ - if (ImGui::IsItemActive()) { - State->UpdateFrame = true; - ImGui_WarpMouse(State, io.MousePos, WindowMinAbs, WindowMaxAbs, 1); - } - - if (ImGui::IsItemActivated()) { - State->Interact_Offset[0] = Property->CurrentValue; - State->Interact_Active = interact_type_slider_scrub; - } - if (ImGui::IsItemDeactivatedAfterEdit()) { - // Pressing Esc while dragging a slider conveniently stops the input in - // ImGui, so all we need to do is set it back: - if (ImGui::IsKeyPressed(ImGuiKey_Escape)) { - Property->CurrentValue = State->Interact_Offset[0]; - } else if (!Property->Keyframe_Count) { - History_Entry_Commit(Memory, "Property interact"); - real32 Temp = Property->CurrentValue; - Property->CurrentValue = State->Interact_Offset[0]; - History_Action_Swap(Memory, Table, sizeof(Property->CurrentValue), &Property->CurrentValue); - Property->CurrentValue = Temp; - History_Entry_End(Memory); - } - State->Interact_Active = interact_type_none; - State->UpdateFrame = true; - State->Warp_X = 0; - State->Warp_Y = 0; - } -} - -static void -ImGui_RGBAModeSwitch(project_state *State, memory *Memory, ImGuiIO io, uint32 *Channel) -{ - char *Names[5] = {"All", "R", "G", "B", "A" }; - if (ImGui::BeginListBox("RGB")) { - for (int i = 0; i < 5; i++) { - if (ImGui::Selectable(Names[i], (*Channel == i))) { - *Channel = i; - } - } - ImGui::EndListBox(); - } -} - -static void -ImGui_CurvesUI(project_state *State, memory *Memory, ImGuiIO io, block_effect *Effect, property_channel *PropertyStart, uint16 *SortedPointStart) -{ - - real32 Padding = ImGui::GetFontSize()*6; - ImVec2 ViewportMin = ImGui::GetCursorScreenPos() + Padding/6; - ImVec2 ViewportScale = ImGui::GetContentRegionAvail(); - ViewportScale.y = ViewportScale.x = ViewportScale.x - Padding; // square seems nice - ImVec2 ViewportMax = ViewportMin + ViewportScale; - - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - draw_list->AddRectFilled(ViewportMin, ViewportMax, IM_COL32(50, 50, 50, 255)); - draw_list->AddRect(ViewportMin, ViewportMax, IM_COL32(255, 255, 255, 255)); - - real32 PointSize = 40; - - ImU32 col = ImGui::GetColorU32(ImGuiCol_Text); - ImU32 col_light = ImGui::GetColorU32(ImGuiCol_TextDisabled); - - ImVec2 Point_ScreenPos[4]; - - // ocd? - draw_list->PushClipRect(ViewportMin + 2, ViewportMax - 2, true); - - for (real32 i = 0.25; i < 1.0; i += 0.25) { - ImVec2 Horizontal = ViewportMin + ViewportScale * ImVec2(0, i); - ImVec2 Vertical = ViewportMin + ViewportScale * ImVec2(i, 0); - draw_list->AddLine(Horizontal, Horizontal + ImVec2(ViewportScale.x, 0), col_light, 1.0f); - draw_list->AddLine(Vertical, Vertical + ImVec2(0, ViewportScale.y), col_light, 1.0f); - } - - draw_list->PopClipRect(); - - -#if 0 - real32 LUT[5][256] = {}; - - for (int a = 0; a < 5; a++) { - - int Num = (a == 0) ? *NumberOfPoints_Main : NumberOfPoints_Col->E[a-1]; - v2 *CurvePoint = (v2 *)(FileEffectAddress + (a * (sizeof(v2) * 10))); - - for (int i = 0; i < Num; i++) { - v2 Point_P1 = CurvePoint[i]; - v2 Point_P2 = CurvePoint[i + 1]; - v2 Point_P0 = (i != 0) ? CurvePoint[i - 1] : V2(0, 0); - v2 Point_P3 = (i != (Num - 2)) ? CurvePoint[i + 2] : V2(1, 1); - - v2 m1 = (Point_P2 - Point_P0) / (2 * Tau); - v2 m2 = (Point_P3 - Point_P1) / (2 * Tau); - - CurvesSolver(LUT[a], Point_P1, Point_P2, m1, m2, i); - } - - if (CurvePoint[0].x > 0.0f) { - real32 Count_Start = 0; - real32 Count_End = (CurvePoint[0].x * 255); - real32 Count = Count_Start; - while (Count < Count_End) { - LUT[a][(uint32)Count] = LUT[a][(uint32)Count_End]; - Count++; - } - } - - if (CurvePoint[Num-1].x < 1.0f) { - real32 Count_Start = (CurvePoint[Num-1].x * 255) - 0.5; - real32 Count_End = 255; - real32 Count = Count_Start; - while (Count < Count_End) { - LUT[a][(uint32)Count] = LUT[a][(uint32)Count_Start]; - Count++; - } - } - - for (int i = 0; i < Num; i++) { - if (CurvePoint[i].y == 1.0f) - LUT[a][255] = 1.0f; - } - } -#endif - - real32 *Num = &Effect->ExtraData[0]; - uint32 *SelectedChannel = (uint32 *)&Effect->ExtraData[5]; - - v2 Pos = {}; - bool32 AddPoint = 0; - - for (uint32 i = 0; i < *(uint32 *)Num; i += 1) { - - v2 Point_P1 = Effect_V2(Memory, Effect, SortedPointStart[i]); - v2 Point_P2 = Effect_V2(Memory, Effect, SortedPointStart[i + 1]); - v2 Point_P0 = (i != 0) ? Effect_V2(Memory, Effect, SortedPointStart[i - 1]) : V2(0, 0); - v2 Point_P3 = (i != (*Num - 2)) ? Effect_V2(Memory, Effect, SortedPointStart[i + 2]) : V2(1, 1); - - ImVec2 Point_P0_ScreenPos = ViewportMin + (ImVec2(Point_P0.x, 1.0f - Point_P0.y) * ViewportScale); - ImVec2 Point_P1_ScreenPos = ViewportMin + (ImVec2(Point_P1.x, 1.0f - Point_P1.y) * ViewportScale); - ImVec2 Point_P2_ScreenPos = ViewportMin + (ImVec2(Point_P2.x, 1.0f - Point_P2.y) * ViewportScale); - ImVec2 Point_P3_ScreenPos = ViewportMin + (ImVec2(Point_P3.x, 1.0f - Point_P3.y) * ViewportScale); - - ImGui::PushID(&PropertyStart[SortedPointStart[i]]); - - draw_list->AddNgon(Point_P1_ScreenPos, 2, col, 8, 5.0f); - - ImGui::SetCursorScreenPos(Point_P1_ScreenPos - ImVec2(PointSize/2, PointSize/2)); - ImGui::InvisibleButton("##point", ImVec2(PointSize, PointSize), ImGuiButtonFlags_MouseButtonLeft); - - if (ImGui::IsItemHovered()) { - ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); - } - - if (ImGui::IsItemActivated()) { - if (io.KeyCtrl && *Num != 2) { - property_channel *Property_X = Effect_Property(Memory, Effect, SortedPointStart[i]); - Property_X->Identifier = -1; - property_channel *Property_Y = Effect_Property(Memory, Effect, SortedPointStart[i]+1); - Property_Y->Identifier = -1; - Effect->ExtraData[*SelectedChannel]--; - } - } - - if (ImGui::IsItemActive()) { - property_channel *Property_X = Effect_Property(Memory, Effect, SortedPointStart[i]); - property_channel *Property_Y = Effect_Property(Memory, Effect, SortedPointStart[i]+1); - v2 Point = V2(((io.MousePos - ViewportMin) / ViewportScale)); - Point.y = 1.0f - Point.y; - Point.x = Normalize(Point.x); - Point.y = Normalize(Point.y); - Property_X->CurrentValue = Point.x; - Property_Y->CurrentValue = Point.y; - State->UpdateFrame = true; - } - - if (i == (*Num - 1)) { - ImGui::PopID(); - break; - } - - // Conversion from Catmull-Rom curves to Bezier curves for display, - // referencing https://pomax.github.io/bezierinfo/#catmullconv - - ImVec2 bez_m1 = (Point_P2_ScreenPos - Point_P0_ScreenPos) / (6 * Tau); - ImVec2 bez_m2 = (Point_P3_ScreenPos - Point_P1_ScreenPos) / (6 * Tau); - - ImVec2 Point_Bez[4]; - Point_Bez[0] = Point_P1_ScreenPos; - Point_Bez[1] = Point_P1_ScreenPos + bez_m1; - Point_Bez[2] = Point_P2_ScreenPos - bez_m2; - Point_Bez[3] = Point_P2_ScreenPos; - - draw_list->PushClipRect(ViewportMin, ViewportMax, true); - - draw_list->AddBezierCubic(Point_Bez[0], Point_Bez[1], Point_Bez[2], Point_Bez[3], col, 1.0f, 0); - - if (ImGui::BezierInteractive(Point_Bez[0], Point_Bez[1], Point_Bez[2], Point_Bez[3]) && - io.MousePos.x > (Point_P1_ScreenPos.x + PointSize/2) && - io.MousePos.x < (Point_P2_ScreenPos.x - PointSize/2)) - { - ImGui::SetCursorScreenPos(io.MousePos - ImVec2(5,5)); - ImGui::Button("pointclick", ImVec2(10, 10)); - if (ImGui::IsItemActivated()) { - Pos = V2(((io.MousePos - ViewportMin) / ViewportScale)); - Pos.y = 1.0f - Pos.y; - Pos.x = Normalize(Pos.x); - Pos.y = Normalize(Pos.y); - AddPoint = true; - } - } - - if (i == 0) - draw_list->AddLine(ImVec2(ViewportMin.x, Point_Bez[0].y), Point_Bez[0], col, 1.0f); - if (i == (*Num - 2)) - draw_list->AddLine(ImVec2(ViewportMax.x, Point_Bez[3].y), Point_Bez[3], col, 1.0f); - - draw_list->PopClipRect(); - -#if 0 - for (int x = 0; x < 256; x++) { - v2 Point = V2((real32)x/256, LUT[*ChannelIndex][x]); - ImVec2 Point_ScreenPos = ViewportMin + (ImVec2(Point.x, 1.0f - Point.y) * ViewportScale); - draw_list->AddNgon(Point_ScreenPos, 1, col, 8, 5.0f); - } -#endif - - draw_list->AddNgon(Point_P1_ScreenPos, 2, col, 8, 5.0f); - - - ImGui::PopID(); - } - - - if (AddPoint) { - int x = 0; - for (;;) { - property_channel *Property_X = Effect_Property(Memory, Effect, x); - if (Property_X->Identifier == -1) { - Property_X->CurrentValue = Pos.x; - Property_X->Identifier = *SelectedChannel; - property_channel *Property_Y = Effect_Property(Memory, Effect, x+1); - Assert(Property_Y->Identifier == -1); - Property_Y->CurrentValue = Pos.y; - Property_Y->Identifier = *SelectedChannel; - x = MAX_PROPERTIES_PER_EFFECT; - } - if (x > MAX_PROPERTIES_PER_EFFECT) - break; - x++; - } - Effect->ExtraData[*SelectedChannel]++; - AddPoint = false; - } - - // ImVec2 ButtonPos = ImGui::GetCursorScreenPos(); - ImGui::SetCursorScreenPos(ViewportMin); - - ImGui::InvisibleButton("canvas", ViewportScale, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight); - bool32 IsHovered = ImGui::IsItemHovered(); - bool32 IsActive = ImGui::IsItemActive(); - bool32 IsActivated = ImGui::IsItemActivated(); - bool32 IsDeactivated = ImGui::IsItemDeactivated(); - - ImVec2 EndPos = ImGui::GetCursorScreenPos(); - - ImGui::SetCursorScreenPos(ViewportMin + ImVec2(ViewportScale.x + 20, 0)); - ImGui_RGBAModeSwitch(State, Memory, io, SelectedChannel); - - ImGui::SetCursorScreenPos(EndPos); -} - -static void -ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io, - sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, - sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray) -{ - bool32 Display = 1; - block_layer *Layer = NULL; - sorted_layer *SortedLayer = NULL; - if (State->MostRecentlySelectedLayer > -1) { - Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, State->MostRecentlySelectedLayer, 0); - sorted_comp_info SortedCompInfo = SortedCompArray[Layer->Block_Composition_Index]; - sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, &SortedCompInfo, Layer->Block_Composition_Index); - SortedLayer = &SortedLayerInfo[State->MostRecentlySelectedLayer]; - if (!Layer->Occupied) - Display = 0; - } else { - Display = 0; - } - if (Display) { - block_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, Layer->Block_String_Index); - char buf[256]; - sprintf(buf, "Properties: %s###Properties", String->Char); - ImGui::Begin(buf); - if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) - State->FocusedWindow = focus_properties; - ImVec2 WindowSize = ImGui::GetWindowSize(); - ImVec2 WindowMinAbs = ImGui::GetWindowPos(); - ImVec2 WindowMaxAbs = WindowMinAbs + WindowSize; - ImGui::Text("Transform"); - - sorted_property_info *InfoLocation = SortedPropertyInfo + SortedLayer->SortedPropertyStart; - uint16 *ArrayLocation = SortedPropertyArray + SortedLayer->SortedKeyframeStart; - int h = 0, c = 0, p = 0; - property_channel *Property = NULL; - block_effect *Effect = NULL; - while (Layer_LoopChannels(State, Memory, &InfoLocation, &ArrayLocation, Layer, &Property, &Effect, &h, &c, &p)) - { - ImGui::PushID(Property); - if ((h - 1) < AmountOf(Layer->Property) && c == 0) { - if (ImGui::Button("K")) { - Property_AddKeyframe(Memory, F_Layers, Property, State->Frame_Current, ArrayLocation); - } - ImGui::SameLine(); -#if DEBUG - char size[64]; - sprintf(size, "%s, %i", DefaultChannel[h-1], Property->Keyframe_Count); - char *Name = size; -#else - char *Name = DefaultChannel[h-1]; -#endif - ImGui::DragScalar(Name, ImGuiDataType_Float, &Property->CurrentValue, Property->ScrubVal, &Property->MinVal, &Property->MaxVal, "%f"); - ImGui_PropertyInteract_Slider(State, Memory, Property, io, WindowMinAbs, WindowMaxAbs, F_Layers); - } else { - Assert(Effect); - header_effect *EffectHeader = Effect_EntryFromID(State, Effect->ID); - header_property ChannelHeader = State->Property[EffectHeader->PropertyStartIndex + c - 1]; -#if DEBUG - char size[64]; - sprintf(size, "%s, %i", ChannelHeader.Name, Property->Keyframe_Count); - char *Name = size; -#else - char *Name = ChannelHeader.Name; -#endif - if ((c - 1) == 0) { - ImGui::PushID(Effect->Index); -#if DEBUG - ImGui::Text("%s, %i", EffectHeader->Name, Effect->Index); -#else - ImGui::Text(EffectHeader->Name); -#endif - ImGui::PopID(); - } - if (EffectHeader->DisplayType == effect_display_type_standard) { - if (ChannelHeader.DisplayType == property_display_type_standard) { - if (ImGui::Button("K")) { - Property_AddKeyframe(Memory, F_Properties, Property, State->Frame_Current, ArrayLocation); - } - ImGui::SameLine(); - ImGui::DragScalar(Name, ImGuiDataType_Float, &Property->CurrentValue, Property->ScrubVal, &Property->MinVal, &Property->MaxVal, "%f"); - ImGui_PropertyInteract_Slider(State, Memory, Property, io, WindowMinAbs, WindowMaxAbs, F_Properties); - } else if (ChannelHeader.DisplayType == property_display_type_color) { - if (ImGui::Button("K")) { - Property_AddKeyframe(Memory, F_Properties, Property, State->Frame_Current, ArrayLocation); - } - ImGui::SameLine(); - ImGui::DragScalar(Name, ImGuiDataType_Float, &Property->CurrentValue, Property->ScrubVal, &Property->MinVal, &Property->MaxVal, "%f"); - ImGui_PropertyInteract_Slider(State, Memory, Property, io, WindowMinAbs, WindowMaxAbs, F_Properties); - // if (c == 3) { - // ImGui::ColorEdit4("col", Col, ImGuiColorEditFlags_Float); - // } - } else { - Assert(0); - } - } else if (EffectHeader->DisplayType == effect_display_type_curves) { -#if DEBUG - ImGui::Text("Points (RGBA): %.02f, Points (indiv): %.02f, %.02f, %.02f, %.02f", Effect->ExtraData[0], - Effect->ExtraData[1], Effect->ExtraData[2], Effect->ExtraData[3], Effect->ExtraData[4]); -#endif - if (Property->Identifier == -1) { - Effect_Curves_Init(Effect, Property); - } - uint16 SortedPointStart[MAX_PROPERTIES_PER_EFFECT/5]; - uint32 VisibleChannel = *(uint32 *)&Effect->ExtraData[5]; - Effect_Curves_Sort(Memory, Effect, SortedPointStart, VisibleChannel); - ImGui_CurvesUI(State, Memory, io, Effect, Property, SortedPointStart); - c = EffectHeader->Property_Count; // Causes this loop to only iterate once. - } else if (EffectHeader->DisplayType == effect_display_type_levels) { - ImGui::Text("Levels!"); - uint32 VisibleChannel = *(uint32 *)&Effect->ExtraData[0]; - real32 *P_Left = 0, *P_Mid = 0, *P_Right = 0; - if (VisibleChannel == 0) { - property_channel *Property0 = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[0]); - property_channel *Property1 = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[1]); - property_channel *Property2 = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[2]); - P_Left = &Property0->CurrentValue; - P_Mid = &Property1->CurrentValue; - P_Right = &Property2->CurrentValue; - } else { - property_channel *Property0 = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[3+(VisibleChannel-1)]); - property_channel *Property1 = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[7+(VisibleChannel-1)]); - property_channel *Property2 = (property_channel *)Memory_Block_AddressAtIndex(Memory, F_Properties, Effect->Block_Property_Index[11+(VisibleChannel-1)]); - P_Left = &Property0->CurrentValue; - P_Mid = &Property1->CurrentValue; - P_Right = &Property2->CurrentValue; - } - ImGui::SliderLevels("1", "2,", "3", (void *)P_Mid, (void *)P_Left, (void *)P_Right); - if (ImGui::IsItemActive()) { - State->UpdateFrame = true; - } - ImGui_RGBAModeSwitch(State, Memory, io, (uint32 *)&Effect->ExtraData[0]); - c = EffectHeader->Property_Count; - } else { - Assert(0); - } - } - ImGui::PopID(); - } -#if 0 - 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(); - 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); - // NOTE(fox): We might have to make a system for processing create/delete - // calls after the UI if things like the Count get incremented and invalid - // data is read. - if (ChannelHeader.DisplayType == property_display_type_standard) { - if (ImGui::Button("K")) { - uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, State->MostRecentlySelectedLayer, h); - Property_AddKeyframe(Memory, Property, State->Frame_Current, ArrayLocation); - } - ImGui::SameLine(); - ImGui::DragScalar(ChannelHeader.Name, ImGuiDataType_Float, &Property->CurrentValue, Property->ScrubVal, &Property->MinVal, &Property->MaxVal, "%f"); - ImGui_PropertyInteract_Slider(State, Memory, Property, io, WindowMinAbs, WindowMaxAbs, F_Properties); - } else if (ChannelHeader.DisplayType == property_display_type_color) { - header_property LastHeader = State->Property[EffectHeader->PropertyStartIndex + c + 3]; - Assert(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 | ImGuiColorEditFlags_NoInputs)) { - } - if (ImGui::IsItemActivated()) { - // State->Interact_Offset[0] = Property->CurrentValue; - // State->Interact_Offset[1] = Property1->CurrentValue; - // State->Interact_Offset[2] = Property2->CurrentValue; - // State->Interact_Offset[3] = Property3->CurrentValue; - State->Interact_Active = interact_type_slider_scrub; - } - if (ImGui::IsItemActive()) { - State->UpdateFrame = true; - Property->CurrentValue = Color[0]; - Property1->CurrentValue = Color[1]; - Property2->CurrentValue = Color[2]; - Property3->CurrentValue = Color[3]; - } - - if (ImGui::IsItemDeactivatedAfterEdit()) { - if (ImGui::IsKeyPressed(ImGuiKey_Escape)) { - Property->CurrentValue = State->Interact_Offset[0]; - } else if (!Property->Keyframe_Count) { - // History_Entry_Commit(Memory, "Property interact"); - // real32 Temp = Property->CurrentValue; - // Property->CurrentValue = State->Interact_Offset[0]; - // History_Action_Swap(Memory, Table, sizeof(Property->CurrentValue), &Property->CurrentValue); - // Property->CurrentValue = Temp; - // History_Entry_End(Memory); - } - State->Interact_Active = interact_type_none; - 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); - } - } -#endif - 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); - if (ImGui::IsItemActive()) { - State->UpdateFrame = true; - } - ImGui::DragScalar("Height", ImGuiDataType_U16, &Comp->Height); - if (ImGui::IsItemActive()) { - State->UpdateFrame = true; - } - } - ImGui::End(); - } else { - ImGui::Begin("Properties: empty###Properties"); - if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) - State->FocusedWindow = focus_properties; - ImGui::End(); - } -} - -#if DEBUG -static void -ImGui_DebugMemoryViewer(memory *Memory, project_state *State) -{ - ImGui::Begin("Memory viewer"); - - ImVec2 ViewportMin = ImGui::GetCursorScreenPos(); - ImVec2 ViewportScale = ImGui::GetContentRegionAvail(); - ImVec2 ViewportMax = ImVec2(ViewportMin.x + ViewportScale.x, ViewportMin.y + ViewportScale.y); - - // ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); - // ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); - - cache_entry *EntryArray = State->Render.Entry; - char *Type[4] = { "unassigned", "comp", "source", "layer" }; - uint32 Blocks_Total = Memory->Slot[B_CachedBitmaps].Size / BitmapBlockSize; - uint32 PerRow = sqrt(Blocks_Total); - real32 BlockSize = ViewportScale.x / PerRow; - for (int c = 0; c < Memory->EntryCount; c++) { - ImGui::PushID(c); - cache_entry Entry = EntryArray[c]; - uint32 BlockSpan; - if (c+1 != Memory->EntryCount) { - cache_entry NextEntry = EntryArray[c+1]; - BlockSpan = NextEntry.Block_StartIndex - Entry.Block_StartIndex; - } else { - BlockSpan = 1; - } - ImVec2 ButtonPos = ViewportMin + ImVec2((Entry.Block_StartIndex % PerRow) * BlockSize, BlockSize * (Entry.Block_StartIndex / PerRow)); - ImVec2 ButtonSize = ImVec2(BlockSpan * BlockSize, BlockSize); - ImGui::SetCursorScreenPos(ButtonPos); - char size[20]; - sprintf(size, "%lu##uimemoryblock", EntryArray[c].CycleTime); - if (ButtonPos.x + ButtonSize.x > ViewportMax.x) { - real32 ButtonSizeSplit = ViewportMax.x - ButtonPos.x; - ImGui::Button(size, ImVec2(ButtonSizeSplit, ButtonSize.y)); - ImVec2 ButtonPos2 = ImVec2(ViewportMin.x, ButtonPos.y + BlockSize); - ImGui::SetCursorScreenPos(ButtonPos2); - ImGui::Button("##uimemoryblockpad", ImVec2(ButtonSize.x - ButtonSizeSplit, ButtonSize.y)); - } else { - ImGui::Button(size, ButtonSize); - } - if (ImGui::IsItemHovered()) { - ImGui::BeginTooltip(); - ImGui::Text("Type - %s, Start - %i, Info - %i, %i", Type[EntryArray[c].Type], EntryArray[c].Block_StartIndex, EntryArray[c].TypeInfo, EntryArray[c].TypeInfo_Sub); - ImGui::EndTooltip(); - } - ImGui::PopID(); - } - // ImGui::PopStyleVar(2); - ImGui::End(); -} - -static void -ImGui_DebugRenderQueue(project_state *State) -{ - ImGui::Begin("debug_queue"); - for (int i = 0; i < State->Queue.CurrentIdx; i++) { - v2 Pos = State->Queue.Item[i].Pos; - char size[20]; - sprintf(size, "Type %i: %.2f, %.2f", State->Queue.Item[i].Type, Pos.x, Pos.y); - ImGui::MenuItem(size, NULL, (i == State->Queue.Playhead)); - } - ImGui::End(); -} - -static void -ImGui_DebugUndoTree(memory *Memory, project_state *State) -{ - ImGui::Begin("debug_undotree"); - for (int i = 0; i < Memory->History.NumberOfEntries; i++) { - history_entry Entry = Memory->History.Entry[i]; - bool32 CurrentPos = (i < Memory->History.EntryPlayhead); - ImGui::MenuItem(Entry.Name, NULL, CurrentPos); - } - ImGui::End(); -} -#endif - -static void -ImGui_File(project_data *File, project_state *State, memory *Memory, ImGuiIO io, - sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray) -{ - ImGui::Begin("Files"); - ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); - - if (ImGui::IsKeyPressed(ImGuiKey_Backspace)) { - - /* - uint64 SortSize = (sizeof(uint16) * File->Comp_Count); - void *SortedArray = Memory_PushScratch(Memory, SortSize); - uint16 *SelectedSourceIndex = (uint16 *)SortedArray; - int SelectedSourceCount = 0; - - int h = 0, c = 0, i = 0; - int SourceCount = File->Source_Count; - while (Block_Loop(Memory, F_Sources, SourceCount, &h, &c, &i)) { - block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, i); - if (Source->IsSelected) { - SelectedSourceIndex[SelectedSourceCount] = i; - SelectedSourceCount++; - } - } - - h = 0, c = 0, i = 0; - int LayerCount = File->Layer_Count; - while (Block_Loop(Memory, F_Layers, LayerCount, &h, &c, &i)) { - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); - for (int b = 0; b < SelectedSourceCount; b++) { - if (SelectedSourceIndex[b] == Layer->Block_Source_Index) { - } - } - } - - Memory_PopScratch(Memory, SortSize); - */ - - /* - bool32 CommitAction = 0; - while (Block_Loop(Memory, F_Sources, SourceCount, &h, &c, &i)) { - block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, i); - if (Source->IsSelected) { - if (!CommitAction) { - History_Entry_Commit(Memory, "Delete source"); - CommitAction = 1; - } - Source_Delete(File, Memory, i); - } - } - if (CommitAction) - History_Entry_End(Memory); - */ - } - - for (int c = 0; c < File->Comp_Count; c++) { - block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, c); - block_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, Comp->Name_String_Index); - ImGui::Text(String->Char); - } - int h = 0, c = 0, i = 0; - while (Block_Loop(Memory, F_Sources, File->Source_Count, &h, &c, &i)) { - block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, i); - block_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, Source->Path_String_Index); - ImGui::Selectable(String->Char, Source->IsSelected); - if (ImGui::IsItemClicked() || ImGui::IsItemClicked(ImGuiMouseButton_Right)) { - if (!io.KeyShift && !Source->IsSelected) { - Source_DeselectAll(File, Memory); - } - Source->IsSelected = 1; - } - ImGui::OpenPopupOnItemClick("sourcecontext", ImGuiPopupFlags_MouseButtonRight); - } - - if (ImGui::BeginPopup("sourcecontext")) { - if (ImGui::MenuItem("Create layer from source")) { - State->HotkeyInput = hotkey_newlayerfromsource; - } - ImGui::EndPopup(); - } - - // if (!ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) - // Source_DeselectAll(File, Memory); - -#if DEBUG - - for (int i = 0; i < Debug.Temp.WatchedProperties; i++) { - if (Debug.Temp.DebugPropertyType[i] == d_float) { - ImGui::Text("%s: %f", Debug.Temp.String[i], Debug.Temp.Val[i].f); - } else if (Debug.Temp.DebugPropertyType[i] == d_int) { - ImGui::Text("%s: %i", Debug.Temp.String[i], Debug.Temp.Val[i].i); - } else if (Debug.Temp.DebugPropertyType[i] == d_uint) { - ImGui::Text("%s: %u", Debug.Temp.String[i], Debug.Temp.Val[i].u); - } - } -#endif - ImGui::End(); -} - -#if STABLE -static void -ImGui_SD_Thumbnail(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io, - sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, uint16 *SourceArray, uint16 SourceCount) -{ - ImGui::Begin("SD gallery"); - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - ImVec2 ViewportMin = ImGui::GetCursorScreenPos(); - ImVec2 ViewportScale = ImGui::GetContentRegionAvail(); - ImVec2 ViewportMax = ImVec2(ViewportMin.x + ViewportScale.x, ViewportMin.y + ViewportScale.y); - if (!SourceCount || ViewportScale.x < 50) { - ImGui::End(); - return; - } - int test[16]; - int count = 0; - // draw_list->AddImage((void *)(intptr_t)textureID, ViewportMin, ViewportMax); - uint32 T_Height = 128; - real32 RowPercent = (real32)ViewportScale.x / T_Height; - uint32 PerRow = (uint32)RowPercent; - uint32 UI_Size = T_Height; - bool32 Active = false; - for (int i = 0; i < SourceCount; i++) { - int32 Y = i / PerRow; - int32 X = i % PerRow; - block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, SourceArray[i]); - // ImGui::Text("Count: %i", Source->RelativeTimestamp); - real32 Ratio = (real32)Source->Width / Source->Height; - uint32 T_Width = (uint32)(Ratio * T_Height); - if (Source->ThumbnailTex == 0) { - Source_DumpThumbnail(Memory, Source, T_Width, T_Height); - } - // draw_list->AddRect(ImgMin, ImgMax, IM_COL32(255, 255, 255, 64)); - ImVec2 ImgMin = ViewportMin + ImVec2(X * UI_Size, Y * UI_Size); - ImGui::SetCursorScreenPos(ImgMin); - real32 ClosestSpacing = 0.2; - bool32 Wide = (Source->Width > Source->Height); - // ImVec2 Min = (Wide) ? ImVec2(0,ClosestSpacing) : ImVec2(ClosestSpacing,0); - // ImVec2 Max = (Wide) ? ImVec2(1-ClosestSpacing,1) : ImVec2(1,1-ClosestSpacing); - ImVec2 Min(0.2, 0.2); - ImVec2 Max(0.8, 0.8); - ImGui::ImageButton((void *)(intptr_t)Source->ThumbnailTex, ImVec2(UI_Size, UI_Size), Min, Max, 12); - // ImGui::ImageButton(user_texture_id, & sizeconst ImVec2& = ImVec2(0, 0), = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1)); // <0 frame_padding uses default frame padding settings. 0 for no padding - // ImVec2 ImgMax = ImgMin + ImVec2(UI_Size * Ratio, UI_Size); - // ImGui::Button("##thumbnail", ImVec2(UI_Size, UI_Size)); - // draw_list->AddImage((void *)(intptr_t)Source->ThumbnailTex, ImgMin, ImgMax); - - if (ImGui::IsItemHovered()) { - State->PreviewSource = SourceArray[i]; - State->UpdateFrame = true; - Active = true; - block_source *Source1 = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, 1); - block_source *Source2 = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, 2); - block_source *Source0 = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, 0); - real32 a = 0; - } - - if (ImGui::IsItemClicked() || ImGui::IsItemClicked(ImGuiMouseButton_Right)) { - if (!io.KeyShift && !Source->IsSelected) { - Source_DeselectAll(File, Memory); - } - Source->IsSelected = 1; - } - ImGui::OpenPopupOnItemClick("temptosource", ImGuiPopupFlags_MouseButtonRight); - } - if (State->PreviewSource != -1 && !Active) { - State->PreviewSource = -1; - State->UpdateFrame = true; - } - if (ImGui::BeginPopup("temptosource")) { - if (ImGui::MenuItem("Create layer from source")) { - State->HotkeyInput = hotkey_newlayerfromsource; - } - ImGui::EndPopup(); - } - - ImGui::End(); -} - -static void -ImGui_SD_Prompt(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io, - sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray) -{ - sorted_comp_info *SortedCompInfo = &SortedCompArray[File->PrincipalCompIndex]; - sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, SortedCompArray,File->PrincipalCompIndex); - ImGui::Begin("SD prompt input"); - sd_state *SD = &File->UI.SD; - int Size = ImGui::GetFontSize(); - ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(200, 80, 0, 255)); - if (ImGui::Button("Generate!", ImVec2(Size*8, Size*2))) { - if (!State->CurlActive) { - if (SD->Mode) { - block_layer *Layer = NULL; - for (int i = SortedCompInfo->LayerCount - 1; i >= 0; i--) { - sorted_layer SortEntry = SortedLayerInfo[i]; - uint32 Index_Physical = SortEntry.Block_Layer_Index; - block_layer *TestLayer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical); - if (TestLayer->IsSelected) { - Layer = TestLayer; - break; - } - } - if (Layer) { - block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index); - void *BitmapAddress; - if (Source->Type == source_type_principal) { - block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index); - BitmapAddress = Memory_Block_AddressAtIndex(Memory, F_PrincipalBitmaps, Source->Bitmap_Index, 0); - } - else if (Source->Type == source_type_file) { - cache_entry *Entry = Memory_Cache_Search(State, Memory, cache_entry_type_source, Layer->Block_Source_Index, 0); - Assert(Entry->IsCached); - BitmapAddress = Memory_Block_Bitmap_AddressAtIndex(Memory, Entry->Block_StartIndex); - } - uint64 Size = Source->Width * Source->Height * Source->BytesPerPixel; - - int32 len = 0; - uint8 *PNGBitmap = stbi_write_png_to_mem((uint8 *)BitmapAddress, Source->Width * Source->BytesPerPixel, - Source->Width, Source->Height, Source->BytesPerPixel, &len); - Assert(PNGBitmap); - - uint64 EncodedEstimateSize = base64_encode_size((size_t)Size); - uint8 *EncodedOutput = (uint8 *)Memory_PushScratch(Memory, EncodedEstimateSize); - uint64 EncodedTrueSize = 0; - - base64_encode((uint8 *)PNGBitmap, len, EncodedOutput, (size_t *)&EncodedTrueSize); - Assert(EncodedOutput[EncodedTrueSize] == '\0'); - // printf("%s", EncodedOutput); - - STBIW_FREE(PNGBitmap); - - SD_AssembleJSON(SD, (char *)State->JSONPayload, EncodedOutput); - Memory_PopScratch(Memory, EncodedEstimateSize); - State->CurlActive = -1; - } - } else { - SD_AssembleJSON(SD, State->JSONPayload); - // SD_AssembleJSON(SD, (char *)State->Dump2); - State->CurlActive = -1; - } - } - } - ImGui::PopStyleColor(); - if (State->CurlActive) { - ImGui::SameLine(); - ImGui::Text("Est. time: %.1f sec, %.2f", State->SDTimeEstimate, State->SDPercentDone*100); - } - ImGui::InputText("Address", SD->ServerAddress, SD_LEN_ADDRESS); - if (SD->ServerAddress[0] == '\0' && SD->Prompt[0] == '\0') { - sprintf(SD->Prompt, "%s", "highres"); - sprintf(SD->NegPrompt, "%s", "nsfw, \ntext, \ncropped, \nworst quality, \nlow quality, \nnormal quality, \njpeg artifacts, \nsignature, \nwatermark"); - sprintf(SD->ServerAddress, "%s", "http://127.0.0.1:7860"); - } - if (ImGui::Selectable("txt2img", !SD->Mode)) - SD->Mode = 0; - if (ImGui::Selectable("img2img", SD->Mode)) - SD->Mode = 1; - ImGui::InputTextMultiline("Prompt", SD->Prompt, SD_LEN_PROMPT); - ImGui::InputTextMultiline("Negative prompt", SD->NegPrompt, SD_LEN_PROMPT); - ImGui::SliderInt("Steps", &SD->Steps, 0, 150); - ImGui::SliderInt("Width", &SD->Width, 64, 2048, "%i px"); - if (ImGui::IsItemDeactivatedAfterEdit()) { - SD->Width = SD->Width + (64 - (SD->Width % 64)); - } - ImGui::SliderInt("Height", &SD->Height, 64, 2048, "%i px"); - if (ImGui::IsItemDeactivatedAfterEdit()) { - SD->Height = SD->Height + (64 - (SD->Height % 64)); - } - ImGui::SliderFloat("CFG scale", &SD->CFG, 1, 30, "%.2f"); - if (SD->Mode) { - ImGui::SliderFloat("Denoising strength", &SD->DenoisingStrength, 0, 1, "%.2f"); - } - ImGui::SliderInt("Batch size", &SD->BatchSize, 1, 8, "%i"); - ImGui::InputInt("Seed", &SD->Seed); - ImGui::End(); -} -#endif - -static void -ImGui_ColorPanel(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io) -{ - ImGuiStyle& style = ImGui::GetStyle(); - - ImGui::Begin("Colors"); - - ImGuiColorEditFlags flags_primary = ImGuiColorEditFlags_AlphaPreview | - ImGuiColorEditFlags_Float; - ImGuiColorEditFlags flags_picker = ImGuiColorEditFlags_PickerHueBar | - ImGuiColorEditFlags_AlphaBar | - ImGuiColorEditFlags_NoSmallPreview | - ImGuiColorEditFlags_NoSidePreview | - ImGuiColorEditFlags_DisplayRGB | - ImGuiColorEditFlags_DisplayHSV | - ImGuiColorEditFlags_DisplayHex; - - // Dim window if it's not active so there's not a big saturation square in - // the corner of my vision while I'm editing. Personal preference. - real32 AlphaMult = (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) ? 1.0f : 0.3f; - ImGui::PushStyleVar(ImGuiStyleVar_Alpha, style.Alpha * AlphaMult); - - ImGui::ColorPicker4("##maincolorpicker", &UI->Color.r, flags_primary | flags_picker); - - ImGui::PopStyleVar(); - - if (ImGui::ColorButton("##primarycolor", *(ImVec4*)&UI->Color.r, flags_primary, ImVec2(20, 20))) - { - v4 Temp = UI->Color; - UI->Color = UI->AltColor; - UI->AltColor = Temp; - } - if (ImGui::ColorButton("##secondarycolor", *(ImVec4*)&UI->AltColor.r, flags_primary, ImVec2(20, 20))) - { - v4 Temp = UI->Color; - UI->Color = UI->AltColor; - UI->AltColor = Temp; - } - - if (State->Tool == tool_brush) { - real32 BrushSizeMin = 0; - real32 BrushSizeMax = 1024; - real32 BrushHardnessMin = 0.5; - real32 BrushHardnessMax = 100; - real32 BrushSpacingMin = 0.1; - real32 BrushSpacingMax = 100; - if (ImGui::DragScalar("Size", ImGuiDataType_Float, &State->Brush.Size, 1, &BrushSizeMin, &BrushSizeMax, "%.3f")) { - Brush_CalcBitmapAlphaFromSize(Memory, &State->Brush, 4); - State_BindBrushTexture(Memory, &State->Brush, 4); - } - if (ImGui::DragScalar("Hardness", ImGuiDataType_Float, &State->Brush.Hardness, 1, &BrushHardnessMin, &BrushHardnessMax, "%.3f", ImGuiSliderFlags_Logarithmic)) { - Brush_CalcBitmapAlphaFromSize(Memory, &State->Brush, 4); - State_BindBrushTexture(Memory, &State->Brush, 4); - } - if (ImGui::DragScalar("Spacing", ImGuiDataType_Float, &State->Brush.Spacing, 1, &BrushSpacingMin, &BrushSpacingMax, "%.3f", ImGuiSliderFlags_Logarithmic)) { - Brush_CalcBitmapAlphaFromSize(Memory, &State->Brush, 4); - State_BindBrushTexture(Memory, &State->Brush, 4); - } - ImGui::Button(BrushNames[State->Brush.Type]); - ImGui::OpenPopupOnItemClick("brush_picker", ImGuiPopupFlags_MouseButtonLeft); - if (ImGui::BeginPopup("brush_picker")) { - for (int16 b = 0; b < brush_amount; b++) { - if (ImGui::MenuItem(BrushNames[b], NULL, false, State->Brush.Type != b)) { - State->Brush.Type = (brush_type)b; - } - } - ImGui::EndPopup(); - } - } - - ImGui::End(); -} - -static void -ImGui_Toolbar(project_state *State, ImDrawList *draw_list) -{ - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); - // ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(50, 50, 50, 0)); - - real32 IconSize = ImGui::GetFontSize() * 4; - int ToolCount = (int)tool_count; - ImVec2 ButtonSize(IconSize, IconSize); - ImVec2 WindowSize(IconSize, IconSize * ToolCount); - ImGui::BeginChild("Toolbar", WindowSize, true, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar); - for (int i = 0; i < ToolCount; i++) { - ImGui::PushID(i); - // draw_list->AddImage((void *)(intptr_t)State->ToolIconTex[i], Min, Max); - if ((int)State->Tool == i) { - ImVec2 Min = ImGui::GetCursorScreenPos(); - ImVec2 Max = Min + ButtonSize; - draw_list->AddRectFilled(Min, Max, IM_COL32(255, 255, 255, 128)); - } - ImGui::Button(ToolName[i], ButtonSize); - if (ImGui::IsItemActivated()) { - State->Tool = (tool)i; - } - ImGui::PopID(); - } - ImGui::EndChild(); - - // ImGui::PopStyleColor(); - ImGui::PopStyleVar(2); -} - -static void -ImGui_RenderUIBrush(project_state *State, memory *Memory, ImVec2 ViewportMin, ImVec2 ViewportMax, ImVec2 CompZoom, ImGuiIO io, uint16 Width, uint16 Height) -{ - - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - if (State->Tool == tool_brush) { - - if (ImGui::IsKeyPressed(ImGuiKey_ModAlt, false)) { - State->Brush.UIPos = io.MousePos; - } - - ImVec2 CompScale = CompZoom / ImVec2(Width, Height); - ImVec2 BrushSize = CompScale * State->Brush.Size; - ImVec2 MinBounds = State->Brush.UIPos - BrushSize/2; - ImVec2 MaxBounds = MinBounds + BrushSize; - - // if (io.KeyCtrl) { - // ImGui::SetCursorScreenPos(State->Brush.UIPos); - // char buf[256]; - // sprintf(buf, "RGBA: %.1f, %.1f, %.1f, %.1f", State->Brush.Size, State->Brush.Hardness); - // } - - if (io.KeyAlt) { - draw_list->PushClipRect(ViewportMin, ViewportMax, true); - draw_list->AddImage((void *)(intptr_t)State->Brush.GLTexture, MinBounds, MaxBounds, ImVec2(0, 0), ImVec2(1, 1), 1); - draw_list->PopClipRect(); - ImGui::SetCursorScreenPos(State->Brush.UIPos); - char buf[256]; - sprintf(buf, "Size: %.1f, Hardness: %.1f", State->Brush.Size, State->Brush.Hardness); - ImGui::Text(buf); - if (io.MouseDelta.x || io.MouseDelta.y) { - ImVec2 Delta = io.MouseDelta; - State->Brush.Size += Delta.x; - State->Brush.Hardness += Delta.y*State->Brush.Hardness/100; - if (State->Brush.Size < 0) - State->Brush.Size = 0; - if (State->Brush.Size > 1024) - State->Brush.Size = 1024; - if (State->Brush.Hardness < 0.5) - State->Brush.Hardness = 0.5; - if (State->Brush.Hardness > 100) - State->Brush.Hardness = 100; - Brush_CalcBitmapAlphaFromSize(Memory, &State->Brush, 4); - State_BindBrushTexture(Memory, &State->Brush, 4); - } - } - } -} - -static void -ImGui_TransformUI(project_data *File, project_state *State, memory *Memory, ui *UI, ImDrawList *draw_list, ImGuiIO &io, - interact_transform *Interact, ImVec2 ViewportMin, uint32 CompWidth, uint32 CompHeight, uint16 *SortedPropertyArray) -{ - v2 InteractMin = Interact->Min + Interact->Position; - v2 InteractMax = Interact->Max + Interact->Position; - - v2 BoxLength = InteractMax - InteractMin; - v2 Center = InteractMax - (BoxLength/2); - - real32 Point0X = Center.x - InteractMin.x; - real32 Point0Y = Center.y - InteractMin.y; - - real32 Rad = Interact->Radians; - - v2 XAxis = (Point0X * Interact->Scale)*V2(cos(Rad), sin(Rad)); - v2 YAxis = (Point0Y * -Interact->Scale)*V2(sin(Rad), -cos(Rad)); - - // Points are clockwise starting from the top left. - real32 X0 = -XAxis.x - YAxis.x + Center.x; - real32 Y0 = -XAxis.y - YAxis.y + Center.y; - real32 X1 = X0 + XAxis.x*2; - real32 Y1 = Y0 + XAxis.y*2; - real32 X2 = X1 + YAxis.x*2; - real32 Y2 = Y1 + YAxis.y*2; - real32 X3 = X2 - XAxis.x*2; - real32 Y3 = Y2 - XAxis.y*2; - - // Midway points. - real32 Mid_X0 = X0 + XAxis.x; - real32 Mid_Y0 = Y0 + XAxis.y; - real32 Mid_X1 = X1 + YAxis.x; - real32 Mid_Y1 = Y1 + YAxis.y; - real32 Mid_X2 = X2 - XAxis.x; - real32 Mid_Y2 = Y2 - XAxis.y; - real32 Mid_X3 = X3 - YAxis.x; - real32 Mid_Y3 = Y3 - YAxis.y; - - ImVec2 CompScale = UI->CompZoom / ImVec2(CompWidth, CompHeight); - - ImVec2 P[4]; - P[0] = ImVec2(X0, Y0)*CompScale + UI->CompPos; - P[1] = ImVec2(X1, Y1)*CompScale + UI->CompPos; - P[2] = ImVec2(X2, Y2)*CompScale + UI->CompPos; - P[3] = ImVec2(X3, Y3)*CompScale + UI->CompPos; - - ImVec2 Mid_P[4]; - Mid_P[0] = ImVec2(Mid_X0, Mid_Y0)*CompScale + UI->CompPos; - Mid_P[1] = ImVec2(Mid_X1, Mid_Y1)*CompScale + UI->CompPos; - Mid_P[2] = ImVec2(Mid_X2, Mid_Y2)*CompScale + UI->CompPos; - Mid_P[3] = ImVec2(Mid_X3, Mid_Y3)*CompScale + UI->CompPos; - - ImU32 wcol = ImGui::GetColorU32(ImGuiCol_Text); - draw_list->AddLine(P[0], P[1], wcol, 2.0f); - draw_list->AddLine(P[1], P[2], wcol, 2.0f); - draw_list->AddLine(P[2], P[3], wcol, 2.0f); - draw_list->AddLine(P[3], P[0], wcol, 2.0f); - - v2 XAxis2 = (BoxLength*CompScale.x)*V2(cos(Rad), sin(Rad)); - v2 YAxis2 = (BoxLength*CompScale.y)*V2(sin(Rad), -cos(Rad)); - - v2 XAxisPerp = (1.0f / LengthSq(XAxis))*XAxis; - v2 YAxisPerp = (1.0f / LengthSq(YAxis))*YAxis; - - // real32 LocalX = ((io.MousePos.x - UI->CompPos.x) - Center.x) ; - // real32 LocalY = ((io.MousePos.y - UI->CompPos.y) - Center.y) ; - layer_transforms BoxTransforms = { Center.x, Center.y, 0.5, 0.5, (real32)(Interact->Radians / (PI / 180)), Interact->Scale }; - v2 LayerPoint = Transform_ScreenSpaceToLocal(BoxTransforms, CompWidth, CompHeight, BoxLength.x, BoxLength.y, UI->CompPos, UI->CompZoom, ViewportMin, io.MousePos); - - real32 U = LayerPoint.x / BoxLength.x; - real32 V = LayerPoint.y / BoxLength.y; - - ImVec2 ScaleHandleSize(50, 50); - - bool32 OtherActions = ImGui::IsKeyDown(ImGuiKey_Z); - - // First do the halfway scale points, since they don't need UVs considered: - for (int i = 0; i < 4; i++) { - ImGui::SetCursorScreenPos(Mid_P[i] - ScaleHandleSize/2); - ImGui::PushID(i); - - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::ColorConvertFloat4ToU32(ImVec4(0.6f, 0.0f, 0.3f, 1.0f))); - ImGui::Button("##ScaleMids", ScaleHandleSize); - ImGui::PopStyleColor(); - - if (ImGui::IsItemActivated() && !OtherActions) { - State->InteractTransformMode = 1; - } - - if (State->InteractTransformMode == 1 && ImGui::IsItemActive()) - { - uint32 side = i; - if (side == 0) { - Interact->Scale -= io.MouseDelta.y / BoxLength.y; - Interact->Position.y += io.MouseDelta.y / 2; - } else if (side == 1) { - Interact->Scale += io.MouseDelta.x / BoxLength.x; - Interact->Position.x += io.MouseDelta.x / 2; - } else if (side == 2) { - Interact->Scale += io.MouseDelta.y / BoxLength.y; - Interact->Position.y += io.MouseDelta.y / 2; - } else if (side == 3) { - Interact->Scale -= io.MouseDelta.x / BoxLength.x; - Interact->Position.x += io.MouseDelta.x / 2; - } - } - ImGui::PopID(); - } - - bool32 InBounds = false; - // Scale if cursor is on button within the UV, rotate if outside UV, and position if a non-button is dragged. - if (U >= 0.0f && U <= 1.0f && V >= 0.0f && V <= 1.0f) - { - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::ColorConvertFloat4ToU32(ImVec4(0.6f, 0.0f, 0.3f, 1.0f))); - InBounds = true; - } - - for (int i = 0; i < 4; i++) { - ImGui::SetCursorScreenPos(P[i] - ScaleHandleSize/2); - ImGui::PushID(i); - ImGui::Button("##ScaleRotateCorners", ScaleHandleSize); - - if (ImGui::IsItemActivated() && !OtherActions) { - if (InBounds) - State->InteractTransformMode = 1; - else - State->InteractTransformMode = 2; - } - - // Scale part - if (State->InteractTransformMode == 1 && ImGui::IsItemActive()) - { - // TODO(fox): Corner dragging scale only works in the X - // axis. Mostly feels right when dragged how you expect, - // but I'll fix it if someone complains. - uint32 side = i; - if (side == 0) { - Interact->Scale -= io.MouseDelta.x / BoxLength.x; - Interact->Position.x += io.MouseDelta.x / 2; - Interact->Position.y += io.MouseDelta.x*(BoxLength.y/BoxLength.x) / 2; - } else if (side == 1) { - Interact->Scale += io.MouseDelta.x / BoxLength.x; - Interact->Position.x += io.MouseDelta.x / 2; - Interact->Position.y -= io.MouseDelta.x*(BoxLength.y/BoxLength.x) / 2; - } else if (side == 2) { - Interact->Scale += io.MouseDelta.x / BoxLength.x; - Interact->Position.x += io.MouseDelta.x / 2; - Interact->Position.y += io.MouseDelta.x*(BoxLength.y/BoxLength.x) / 2; - } else if (side == 3) { - Interact->Scale -= io.MouseDelta.x / BoxLength.x; - Interact->Position.x += io.MouseDelta.x / 2; - Interact->Position.y -= io.MouseDelta.x*(BoxLength.y/BoxLength.x) / 2; - } - } - - // Rotation part - if (State->InteractTransformMode == 2 && ImGui::IsItemActive()) - { - real32 LocalX = (io.MousePos.x - UI->CompPos.x)/CompScale.x - InteractMin.x - (BoxLength.x/2); - real32 LocalY = (io.MousePos.y - UI->CompPos.y)/CompScale.y - InteractMin.y - (BoxLength.y/2); - - real32 Slope_Mouse = LocalY/LocalX; - real32 Slope_Corner = 0; - real32 Slope_Flipped = 0; - real32 Dot = 0; - - // TODO(fox) learn basic geometry to do this properly - - // We find the angle between the direction of whichever corner the - // mouse is grabbing (Slope_Corner) and the mouse's current - // position (Slope_Mouse) to get ExtraRadians. The calculation only - // works between -90 and 90, so I take the dot product of the - // opposite edge of the corner and add the extra degrees when it's negative. - - v2 SlopeDot = V2(BoxLength.x, BoxLength.y); - // top left clockwise - uint32 side = i; - if (side == 0) { - Slope_Corner = BoxLength.y / BoxLength.x; - Slope_Flipped = -BoxLength.x / BoxLength.y; - Dot = LocalX * -SlopeDot.x + LocalY * -SlopeDot.y; - } else if (side == 1) { - Slope_Corner = -BoxLength.y / BoxLength.x; - Slope_Flipped = BoxLength.x / BoxLength.y; - Dot = LocalX * SlopeDot.x + LocalY * -SlopeDot.y; - } else if (side == 2) { - Slope_Corner = BoxLength.y / BoxLength.x; - Slope_Flipped = -BoxLength.x / BoxLength.y; - Dot = LocalX * SlopeDot.x + LocalY * SlopeDot.y; - } else if (side == 3) { - Slope_Corner = -BoxLength.y / BoxLength.x; - Slope_Flipped = BoxLength.x / BoxLength.y; - Dot = LocalX * -SlopeDot.x + LocalY * SlopeDot.y; - } - - Interact->Radians = atan((Slope_Mouse - Slope_Corner) / (1 + Slope_Mouse * Slope_Corner)); - real32 ExtraRadians2 = atan((Slope_Mouse - Slope_Flipped) / (1 + Slope_Mouse * Slope_Flipped)); - - if (Dot < 0) { - if (Interact->Radians < 0) { - Interact->Radians = (90 * (PI / 180)) + ExtraRadians2; - } else { - Interact->Radians = (-90 * (PI / 180)) + ExtraRadians2; - } - } - } - - ImGui::PopID(); - } - - if (!State->InteractTransformMode && ImGui::IsMouseClicked(ImGuiMouseButton_Left) && InBounds && !OtherActions) - State->InteractTransformMode = 3; - - if (State->InteractTransformMode == 3) { - Interact->Position.x += (real32)io.MouseDelta.x/CompScale.x; - Interact->Position.y += (real32)io.MouseDelta.y/CompScale.y; - } - - if (State->InteractTransformMode) - { - if (io.MouseDelta.x || io.MouseDelta.y) - State->UpdateFrame = true; - if (!ImGui::IsMouseDown(ImGuiMouseButton_Left)) - State->InteractTransformMode = 0; - } - - if (ImGui::IsKeyPressed(ImGuiKey_Escape)) { - State->Interact_Active = interact_type_none; - State->Interact_Modifier = 0; - State->UpdateFrame = true; - } - - // Second condition so you don't have to reach for Enter. - if (ImGui::IsKeyPressed(ImGuiKey_Enter) || (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && io.KeyCtrl)) { - int h = 0, c = 0, i = 0; - if (!io.KeyCtrl) - History_Entry_Commit(Memory, "Transform layers"); - while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i)) { - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); - if (Layer->IsSelected == 1) { - if (io.KeyCtrl) { - layer_transforms T = Layer_GetTransforms(Layer); - Transform_ApplyInteractive(*(interact_transform *)&State->Interact_Offset[0], &T.x, &T.y, &T.rotation, &T.scale); - property_channel *Property[4] = { &Layer->x, &Layer->y, &Layer->rotation, &Layer->scale }; - real32 Val[4] = { T.x, T.y, T.rotation, T.scale }; - for (int a = 0; a < 4; a++) { - if (Property[a]->CurrentValue != Val[a]) { - History_Entry_Commit(Memory, "Add keyframe"); - bezier_point Point = { 1, {(real32)State->Frame_Current, Val[a], -1, 0, 1, 0}, interpolation_type_linear, 0, {0, 0, 0}, 0 }; - uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, State->MostRecentlySelectedLayer, h); - Bezier_Add(Memory, F_Layers, Property[a], Point, ArrayLocation); - History_Entry_End(Memory); - } - } - } else { - History_Action_Swap(Memory, F_File, sizeof(Layer->x.CurrentValue), &Layer->x.CurrentValue); - History_Action_Swap(Memory, F_File, sizeof(Layer->y.CurrentValue), &Layer->y.CurrentValue); - History_Action_Swap(Memory, F_File, sizeof(Layer->scale.CurrentValue), &Layer->scale.CurrentValue); - History_Action_Swap(Memory, F_File, sizeof(Layer->rotation.CurrentValue), &Layer->rotation.CurrentValue); - Transform_ApplyInteractive(*(interact_transform *)&State->Interact_Offset[0], &Layer->x.CurrentValue, &Layer->y.CurrentValue, &Layer->rotation.CurrentValue, &Layer->scale.CurrentValue); - } - } - } - if (!io.KeyCtrl) - History_Entry_End(Memory); - State->Interact_Active = interact_type_none; - State->Interact_Modifier = 0; - State->UpdateFrame = true; - } - - if (InBounds == true) { - ImGui::PopStyleColor(); - } - -} - -static void -ImGui_LayerViewportUI(project_state *State, memory *Memory, ui *UI, ImDrawList *draw_list, block_composition *MainComp, uint32 CompIndex, block_layer *ParentLayer[4], uint32 Recursions, - sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray) -{ - sorted_comp_info *SortedCompInfo = &SortedCompArray[CompIndex]; - sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, SortedCompArray, CompIndex); - ImU32 wcol = ImGui::GetColorU32(ImGuiCol_Text); - for (int i = 0; i < SortedCompInfo->LayerCount; i++) - { - sorted_layer SortEntry = SortedLayerInfo[i]; - uint32 Index_Physical = SortEntry.Block_Layer_Index; - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical); - if (Layer->IsPrecomp) { - ParentLayer[Recursions] = Layer; - ImGui_LayerViewportUI(State, Memory, UI, draw_list, MainComp, Layer->Block_Source_Index, ParentLayer, Recursions + 1, SortedCompArray, SortedLayerArray); - } - if (Layer->IsSelected) { - uint32 Width = 0, Height = 0; - if (!Layer->IsPrecomp) { - block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index); - Width = Source->Width; - Height = Source->Height; - } else { - block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, Layer->Block_Source_Index); - Width = Comp->Width; - Height = Comp->Height; - } - - v2 Point[5] = { V2(Width*Layer->ax.CurrentValue, Height*Layer->ay.CurrentValue), V2(0, 0), V2(Width, 0), V2(0, Height), V2(Width, Height) }; - - layer_transforms T = Layer_GetTransforms(Layer); - - if (State->Interact_Active == interact_type_viewport_transform && Layer->IsSelected == 1) { - Transform_ApplyInteractive(*(interact_transform *)&State->Interact_Offset[0], &T.x, &T.y, &T.rotation, &T.scale); - } - - v2 NewPos[5]; - for (int i = 0; i < 5; i++) { - NewPos[i] = TransformPoint(T, Width, Height, Point[i]); - } - - int i = 0; - while (i < Recursions) { - T = Layer_GetTransforms(ParentLayer[i]); - block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, ParentLayer[i]->Block_Source_Index); - Width = Comp->Width; - Height = Comp->Height; - for (int i = 0; i < 5; i++) { - NewPos[i] = TransformPoint(T, Width, Height, NewPos[i]); - } - i++; - } - - ImVec2 ScreenPoint[5]; - for (int i = 0; i < 5; i++) { - v2 CompUV = NewPos[i] / V2(MainComp->Width, MainComp->Height); - - ScreenPoint[i] = ImVec2(UI->CompPos.x + CompUV.x * UI->CompZoom.x, - UI->CompPos.y + CompUV.y * UI->CompZoom.y); - - } - if (State->Tool != tool_brush) { - ImU32 wcol2 = IM_COL32(10, 10, 10, 255); - draw_list->AddNgon(ScreenPoint[0], 10, wcol2, 8, 9.0f); - draw_list->AddNgon(ScreenPoint[0], 10, wcol, 8, 5.0f); - } - draw_list->AddLine(ScreenPoint[1], ScreenPoint[2], wcol, 2.0f); - draw_list->AddLine(ScreenPoint[2], ScreenPoint[4], wcol, 2.0f); - draw_list->AddLine(ScreenPoint[1], ScreenPoint[3], wcol, 2.0f); - draw_list->AddLine(ScreenPoint[3], ScreenPoint[4], wcol, 2.0f); - } - } -} - -static void -ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io, GLuint textureID, - sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, uint16 *SortedPropertyArray) -{ - bool open = true; - ImGui::Begin("Viewport", &open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - - if (ImGui::IsWindowHovered(ImGuiFocusedFlags_ChildWindows)) { - State->FocusedWindow = focus_viewport; - } - - block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, File->PrincipalCompIndex); - - ImVec2 ViewportMin = ImGui::GetCursorScreenPos(); - ImVec2 ViewportScale = ImGui::GetContentRegionAvail(); - ImVec2 ViewportMax = ImVec2(ViewportMin.x + ViewportScale.x, ViewportMin.y + ViewportScale.y); - - if (State->Initializing) { - UI->CompZoom = ImVec2(MainComp->Width, MainComp->Height); - UI->CompPos = ImVec2(ViewportMin.x + ((ViewportMax.x - ViewportMin.x)/2 - UI->CompZoom.x/2), - ViewportMin.y + ((ViewportMax.y - ViewportMin.y)/2 - UI->CompZoom.y/2)); - } - - ImVec2 CompPosMin = ImVec2(UI->CompPos.x, UI->CompPos.y); - ImVec2 CompPosMax = ImVec2(UI->CompPos.x + UI->CompZoom.x, UI->CompPos.y + UI->CompZoom.y); - - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - draw_list->AddRectFilled(ViewportMin, ViewportMax, IM_COL32(50, 50, 50, 255)); - draw_list->AddRect(ViewportMin, ViewportMax, IM_COL32(255, 255, 255, 255)); - draw_list->AddRect(CompPosMin, CompPosMax, IM_COL32(255, 255, 255, 55)); - - real32 FontSize = ImGui::GetFontSize(); - ImGui::SetCursorScreenPos(ImVec2(ViewportMax.x - FontSize*2, ViewportMin.y + ViewportScale.y - FontSize*3.0)); - ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 80)); - if (ImGui::Button("?")) - State->ImGuiPopups = popup_keybinds; - ImGui::PopStyleColor(); - - - // Actual composition texture - draw_list->PushClipRect(ViewportMin, ViewportMax, true); - draw_list->AddImage((void *)(intptr_t)textureID, CompPosMin, CompPosMax); - draw_list->PopClipRect(); - - // UI+interaction for layer - if (State->MostRecentlySelectedLayer > -1) - { - block_layer *ParentLayer[4]; - ImGui_LayerViewportUI(State, Memory, UI, draw_list, MainComp, File->PrincipalCompIndex, ParentLayer, 0, SortedCompArray, SortedLayerArray); - if (State->Interact_Active == interact_type_viewport_transform) { - ImGui_TransformUI(File, State, Memory, UI, draw_list, io, (interact_transform *)&State->Interact_Offset[0], ViewportMin, MainComp->Width, MainComp->Height, SortedPropertyArray); - } - } - - - - // Interactions for dragging and zooming - ImGui::SetCursorScreenPos(ViewportMin); - - ImGui::InvisibleButton("canvas", ViewportScale, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight); - bool32 IsHovered = ImGui::IsItemHovered(); -#if 1 - bool32 IsActive = ImGui::IsItemActive(); - bool32 IsActivated = ImGui::IsItemActivated(); - bool32 IsDeactivated = ImGui::IsItemDeactivated(); -#else - bool32 IsActive = ImGui::IsKeyDown(ImGuiKey_3); - bool32 IsActivated = ImGui::IsKeyPressed(ImGuiKey_3); - bool32 IsDeactivated = ImGui::IsKeyReleased(ImGuiKey_3); -#endif - - if (IsHovered && IsActivated && !ImGui::IsMouseDown(ImGuiMouseButton_Right)) - { - // Point to zoom in on if Z is held - State->TempZoomRatio = ImGui_ScreenPointToCompUV(ViewportMin, UI->CompPos, UI->CompZoom, io.MousePos); - - if (State->Tool == tool_brush && State->Interact_Active != interact_type_brush) { - sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, SortedCompArray, File->PrincipalCompIndex); - sorted_comp_info SortedCompInfo = SortedCompArray[File->PrincipalCompIndex]; - if (!io.KeyCtrl) { - int h = 0, c = 0, i = 0; - while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i)) - { - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); - if (!Layer->IsPrecomp) { - block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index); - if (Layer->IsSelected && Source->Type == source_type_principal) { - Assert(Source->BytesPerPixel == 4); - Arbitrary_Zero((uint8 *)State->Brush.TransientBitmap, 2048*2048*4); - State->Interact_Active = interact_type_brush; - State->Brush.LayerToPaint_Index = i; - break; - } - } - } - } - if (State->Brush.LayerToPaint_Index == -1) { - State->HotkeyInput = hotkey_newpaintlayer; - } - } - - // Layer selection - if (!ImGui::IsKeyDown(ImGuiKey_Z) && State->Tool == tool_default && State->Interact_Active == interact_type_none) { - int32 Selection = Layer_TestSelection(Memory, State, UI, SortedCompArray, SortedLayerArray, File->PrincipalCompIndex); - if (!io.KeyShift && State->Interact_Active == interact_type_none) - Layer_DeselectAll(File, State, Memory); - if (Selection != -1) - Layer_Select(Memory, State, Selection); - } - } - - /* - if (State->Interact_Active == interact_type_viewport_transform) { - interact_transform *Interact = (interact_transform *)&State->Interact_Offset[0]; - ImVec2 DragDelta = io.MousePos - Interact->OGPos; - Interact->Position = V2(DragDelta.x, DragDelta.y); - if (io.MouseDelta.x || io.MouseDelta.y) - State->UpdateFrame = true; - } - */ - - if (IsActive && ImGui::IsMouseDragging(ImGuiMouseButton_Right, -1.0f)) - { - UI->CompPos.x += io.MouseDelta.x; - UI->CompPos.y += io.MouseDelta.y; - } - - - bool32 OtherActions = ImGui::IsKeyDown(ImGuiKey_Z) || ImGui::IsMouseDown(ImGuiMouseButton_Right); - if (State->Tool == tool_brush && State->Interact_Active == interact_type_brush) { - Assert(State->Brush.LayerToPaint_Index != -1); - if (IsActive && !OtherActions) { - 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); - ImVec2 MouseDelta = io.MouseDelta; - real32 Delta = MouseDelta.x + MouseDelta.y; - v2 PrincipalCompUV = ImGui_ScreenPointToCompUV(ViewportMin, UI->CompPos, UI->CompZoom, io.MousePos); - v2 LayerPos = Layer_TraverseForPoint(File, State, Memory, PrincipalCompUV, SortedCompArray, SortedLayerArray); - if (IsActivated) { - RenderQueue_AddBrush(State, LayerPos); - } else if (Delta != 0.0f) { - v2 PrevPos = State->Brush.PrevPos; - v2 Delta = PrevPos - LayerPos; - real32 Dist = sqrt(LengthSq(Delta)); - if (Dist > State->Brush.Spacing) { - RenderQueue_AddBrush(State, LayerPos); - } - } - State->UpdateFrame = true; - } - - if (IsDeactivated) { - RenderQueue_AddBlit(State); - } - } - - if (ImGui::IsKeyDown(ImGuiKey_Z) && ImGui::IsWindowHovered()) { - if (IsActive) - ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); - else - ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); - } - - real32 Distance = 0; - if (IsActive) { - if (ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1.0f)) - Distance = io.MouseDelta.x + io.MouseDelta.y; - if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) - Distance = 200; - } - if (Distance && ImGui::IsKeyDown(ImGuiKey_Z)) - { - if (io.KeyShift) - Distance *= -1; - UI->CompZoom.x += (Distance)*(real32)MainComp->Width/MainComp->Height; - UI->CompZoom.y += (Distance); - UI->CompPos.x -= ((Distance)*(real32)MainComp->Width/MainComp->Height)*State->TempZoomRatio.x; - UI->CompPos.y -= Distance*State->TempZoomRatio.y; - } - - ImGui::SetCursorScreenPos(ImVec2(ViewportMin.x, ViewportMin.y + ViewportScale.y - FontSize*1.5)); - - ImGui::Text("%.1f", 100.0f * (UI->CompZoom.x / MainComp->Width)); - if (State->MsgTime > 0) { - ImGui::SameLine(); - ImGui::SetCursorPosX((ViewportScale.x / 5)*4); - ImGui::Text(State->Msg); - State->MsgTime--; - } - - ImGui::SetCursorScreenPos(ViewportMin); - ImGui_Toolbar(State, draw_list); - - ImGui_RenderUIBrush(State, Memory, ViewportMin, ViewportMax, UI->CompPos, io, MainComp->Width, MainComp->Height); - - ImGui::End(); - - /* - for (int i = 0; i < AmountOf(Layer->Property); i++) { - ImGui::PushID(i); - property_channel *Property = &Layer->Property[i]; - ImGui::DragScalar(Property->Name, ImGuiDataType_Float, &Property->CurrentValue, - Property->ScrubVal, &Property->MinVal, &Property->MaxVal, "%f"); - if (ImGui::IsItemActive()) - State->UpdateFrame = true; - ImGui::PopID(); - } - */ -} - -static void -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); - - real32 x = 0; - bool32 RightmostEdge = false; - real32 Increment = (real32)1 / MainComp.Frame_Count; - if (UI->TimelinePercentZoomed.x > 0.90) - Increment = (real32)MainComp.FPS / MainComp.Frame_Count; - else if (UI->TimelinePercentZoomed.x > 0.40) - Increment *= 2; - - while (!RightmostEdge) { - ImVec2 Min = ImVec2(TimelineAbsolutePos.x + TimelineMoveSize.x + x*TimelineZoomSize.x, TimelineAbsolutePos.y); - ImVec2 Max = ImVec2(Min.x + 2, TimelineAbsolutePos.y + TimelineSizeWithBorder.y); - if (Min.x < TimelineAbsolutePos.x + TimelineSizeWithBorder.x) { - draw_list->AddLine(Min, Max, LineColor); - char buf2[6]; - uint32 FrameNumber = (uint32)(x * MainComp.Frame_Count) % MainComp.FPS; - if (FrameNumber != 0) - sprintf(buf2, ":%.2i", FrameNumber); - else - sprintf(buf2, "%.2i:00", (uint32)(x * MainComp.Frame_Count) / MainComp.FPS); - draw_list->AddText(ImVec2(Min.x, TimelineAbsolutePos.y), IM_COL32(200, 200, 200, 130), buf2); - x += Increment; - if (x > 1.0f) - RightmostEdge = true; - } else { - RightmostEdge = true; - } - } - - 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; - State->Interact_Modifier = 0; - } -} - - -static void -ImGui_GraphInfo(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, - sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, - sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray) -{ - bool open = true; - ImGui::Begin("Graph info"); - - int h = 0, c = 0, i = 0; - while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i)) - { - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); - if (!Layer->IsSelected) - continue; - - block_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, Layer->Block_String_Index); - ImGui::Text(String->Char); - - ImGui::PushID(i); - for (int h = 0; h < AmountOf(Layer->Property); h++) { - property_channel *Property = &Layer->Property[h]; - if (Property->Block_Bezier_Count) { - sorted_property_info *InfoLocation = Property_GetSortedInfo(SortedPropertyInfo, i, h); - uint16 *ArrayLocation = Property_GetSortedArray(SortedPropertyArray, i, h); - ImGui::PushID(Property); - if (ImGui::Selectable(DefaultChannel[h], Property_IsGraphSelected(Memory, Property, ArrayLocation))) { - Property_DeselectAll(File, State, Memory, SortedCompArray, SortedLayerArray, SortedPropertyInfo, SortedPropertyArray); - for (int p = 0; p < Property->Keyframe_Count; p++) { - int k = ArrayLocation[p]; - bezier_point *Point = Bezier_LookupAddress(Memory, Property, k); - Point->IsSelected = true; - } - State->RecentSelectionType = selection_type_keyframe; - } - ImGui::PopID(); - } - } - - ImGui::PopID(); - } - - ImGui::End(); -} - -static void -ImGui_Timeline_DrawKeySheet(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, ImDrawList *draw_list, property_channel *Property, uint16 *ArrayLocation, - ImVec2 Increment, ImVec2 TimelineAbsolutePos, ImVec2 GraphPos, ImVec2 TimelineMoveSize, ImVec2 TimelineZoomSize, - ImVec2 TimelineSize, ImVec2 TimelineSizeWithBorder, real32 LayerIncrement, - sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray) -{ - ImGui::PushID(Property); - - for (int p = 0; p < Property->Keyframe_Count; p++) { - int k = ArrayLocation[p]; - bezier_point *PointAddress = Bezier_LookupAddress(Memory, Property, k); - - v2 PointPos[3]; - Bezier_EvaluateValue(State, PointAddress, PointPos); - - real32 LocalPos_Ratio_X = PointPos[0].x * Increment.x; - real32 Keyframe_ScreenPos_X = GraphPos.x + TimelineMoveSize.x + LocalPos_Ratio_X * TimelineZoomSize.x; - - ImVec2 Keyframe_ScreenPos(Keyframe_ScreenPos_X, GraphPos.y); - - if (State->BoxSelect) { - if (ImGui_TestBoxSelection_Point(Keyframe_ScreenPos, io, &PointAddress->IsSelected)) - State->RecentSelectionType = selection_type_keyframe; - } - - ImVec2 ButtonSize(16, 16); - - ImGui::PushID(p); - - ImU32 PointCol = (PointAddress->IsSelected) ? ImColor(0.8f, 0.5f, 0.0f, 1.0f) : ImColor(0.1f, 0.1f, 0.1f, 1.0f); - ImU32 LineCol = (PointAddress->IsSelected) ? ImColor(0.8f, 0.5f, 0.5f, 1.0f) : ImColor(0.4f, 0.4f, 0.4f, 1.0f); - ImGui::SetCursorScreenPos(Keyframe_ScreenPos - (ButtonSize * 0.5)); - ImGui::InvisibleButton("##keyframemover", ButtonSize, ImGuiMouseButton_Left); - bool32 IsHovered = ImGui::IsItemHovered(); - bool32 IsItemActive = ImGui::IsItemActive(); - bool32 IsItemActivated = ImGui::IsItemActivated(); - bool32 IsItemDeactivated = ImGui::IsItemDeactivated(); - bool32 LeftClick = ImGui::IsMouseDown(ImGuiMouseButton_Left); - bool32 RightClick = ImGui::IsMouseDown(ImGuiMouseButton_Right); - - if (IsHovered) { - PointCol = ImColor(1.0f, 0.8f, 0.8f, 1.0f); - ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); - } - - if (IsItemActivated) { - PointAddress->IsSelected = 1; - } - - if (IsItemActive) { - if (State->Interact_Active == interact_type_none) { - State->Interact_Offset[2] = io.MousePos.x; - State->Interact_Offset[3] = io.MousePos.y; - State->Interact_Active = interact_type_keyframe_move; - State->Interact_Modifier = 1; // X axis movement only - } else { - Assert(State->Interact_Active == interact_type_keyframe_move); - ImGui_WarpMouse(State, io.MousePos, TimelineAbsolutePos, TimelineAbsolutePos + TimelineSizeWithBorder, 1); - ImVec2 DragDelta = io.MousePos - ImVec2(State->Interact_Offset[2], State->Interact_Offset[3]); - DragDelta = DragDelta + (ImVec2(State->Warp_X, State->Warp_Y) * TimelineSize); - if (io.MouseDelta.x || io.MouseDelta.y) { - State->UpdateFrame = true; - } - if (State->Interact_Active == interact_type_keyframe_move) { - State->Interact_Offset[0] = (DragDelta.x / TimelineZoomSize.x) / Increment.x; - State->Interact_Offset[1] = DragDelta.y; - } - } - } - - if (IsItemDeactivated) { - Bezier_Commit(File, State, Memory, SortedCompArray, SortedLayerArray, SortedPropertyInfo, SortedPropertyArray); - } - - draw_list->AddCircleFilled(Keyframe_ScreenPos, 4, PointCol); - - ImGui::PopID(); - } - ImGui::PopID(); -} - -static void -ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, ImDrawList *draw_list, - ImVec2 Increment, ImVec2 TimelineAbsolutePos, ImVec2 TimelineMoveSize, ImVec2 TimelineZoomSize, - ImVec2 TimelineSize, ImVec2 TimelineSizeWithBorder, real32 LayerIncrement, - sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, - sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray) -{ - // I'm using the draw splitter here to be able to draw the dots on top of the graph lines. - State->Test.Split(draw_list, 2); - - for (int c = 0; c < File->Comp_Count; c++) { - sorted_comp_info SortedCompInfo = SortedCompArray[c]; - sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, &SortedCompInfo, c); - for (int i = 0; i < SortedCompInfo.LayerCount; i++) { - sorted_layer *SortedLayer = &SortedLayerInfo[i]; - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, SortedLayer->Block_Layer_Index); - if (!Layer->IsSelected) - continue; - - int32 Frame_Start = Layer->Frame_Start; - - ImGui::PushID(i); - - if ((State->Interact_Active == interact_type_keyframe_move || - State->Interact_Active == interact_type_keyframe_rotate || - State->Interact_Active == interact_type_keyframe_scale)) - { - ImGui_WarpMouse(State, io.MousePos, TimelineAbsolutePos, TimelineAbsolutePos + TimelineSizeWithBorder); - ImVec2 DragDelta = io.MousePos - ImVec2(State->Interact_Offset[2], State->Interact_Offset[3]); - DragDelta = DragDelta + (ImVec2(State->Warp_X, State->Warp_Y) * TimelineSize); - if (io.MouseDelta.x || io.MouseDelta.y) { - State->UpdateFrame = true; - } - if (State->Interact_Active == interact_type_keyframe_move) { - // The Y increment varies between graphs, so we have to do it in the Bezier_EvaluateValue call. - State->Interact_Offset[0] = (DragDelta.x / TimelineZoomSize.x) / Increment.x; - State->Interact_Offset[1] = DragDelta.y; - } else if (State->Interact_Active == interact_type_keyframe_scale) { - State->Interact_Offset[0] = (DragDelta.x / TimelineSizeWithBorder.x * UI->TimelinePercentZoomed.x) / Increment.x; - } else if (State->Interact_Active == interact_type_keyframe_rotate) { - State->Interact_Offset[0] = (DragDelta.x / TimelineZoomSize.x); - /* - real32 Slope_Old = (Keyframe_ScreenPos.y - State->Interact_Offset[3]) / (Keyframe_ScreenPos.x - State->Interact_Offset[2]); - real32 Slope_New = (Keyframe_ScreenPos.y - io.MousePos.y) / (Keyframe_ScreenPos.x - io.MousePos.x); - State->Interact_Offset[0] = atan((Slope_Old - Slope_New) / (1 + Slope_Old * Slope_New)); - */ - } - ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); - } - - sorted_property_info *InfoLocation = SortedPropertyInfo + SortedLayer->SortedPropertyStart; - uint16 *ArrayLocation = SortedPropertyArray + SortedLayer->SortedKeyframeStart; - int h1 = 0, c1 = 0, p = 0; - property_channel *Property = NULL; - while (Layer_LoopChannels(State, Memory, &InfoLocation, &ArrayLocation, Layer, &Property, NULL, &h1, &c1, &p)) - { - ImGui::PushID(Property); - if (Property->Block_Bezier_Count) { - real32 MinY, MaxY; - Property_MinMax_Y(Memory, State, Property, InfoLocation, &MinY, &MaxY, 0); - Assert(InfoLocation->MinYIndex < Property->Keyframe_Count); - Assert(InfoLocation->MaxYIndex < Property->Keyframe_Count); - Assert(MaxY >= MinY); - real32 Y_Increment = (MaxY - MinY) ? (1 / (MaxY - MinY)) : 0.5; - - real32 GraphScale = 0; - real32 GraphPos = 0; - if ((1 / Y_Increment) < 5) { - GraphScale = 0.2; - GraphPos = 0.3; - } else if ((1 / Y_Increment) > 700) { - GraphScale = 0.6; - GraphPos = 0.06; - } else { - GraphScale = 0.4; - GraphPos = 0.2; - } - - - real32 GraphMoveHeight = TimelineMoveSize.y + (TimelineZoomSize.y * GraphPos); - real32 GraphZoomHeight = TimelineZoomSize.y * GraphScale; - - bool32 IsGraphSelected = Property_IsGraphSelected(Memory, Property, ArrayLocation); - uint32 GraphCol = IsGraphSelected ? IM_COL32(255, 180, 150, 255) : IM_COL32(255, 255, 255, 70); - - bezier_point *PointAddress[2] = {}; - ImVec2 Keyframe_ScreenPos[6] = {}; - for (int p = 0; p < Property->Keyframe_Count; p++) { - int k = ArrayLocation[p]; - if (Property->Keyframe_Count == 1) - int b = 0; - int Idx = (p % 2); - int NewIdx = Idx * 3; - int OldIdx = (NewIdx == 3) ? 0 : 3; - PointAddress[Idx] = Bezier_LookupAddress(Memory, Property, k); - - v2 PointPos[3]; - Bezier_EvaluateValue(State, PointAddress[Idx], PointPos, GraphZoomHeight, Y_Increment); - - ImVec2 Keyframe_LocalPos[3] = { V2(PointPos[0]), V2(PointPos[0] + PointPos[1]), V2(PointPos[0] + PointPos[2]) }; - - ImVec2 Keyframe_LocalPos_Ratio[3]; - for (int b = 0; b < 3; b++) { - Keyframe_LocalPos_Ratio[b] = (Keyframe_LocalPos[b] - ImVec2(0, MinY)) * ImVec2(Increment.x, Y_Increment); - Keyframe_ScreenPos[NewIdx + b] = TimelineAbsolutePos + ImVec2(TimelineMoveSize.x, GraphMoveHeight) + ((ImVec2(1, -1) * Keyframe_LocalPos_Ratio[b] + ImVec2(0, 1)) * ImVec2(TimelineZoomSize.x, GraphZoomHeight)); - } - - if (State->BoxSelect) { - if (ImGui_TestBoxSelection_Point(Keyframe_ScreenPos[NewIdx], io, &PointAddress[Idx]->IsSelected)) - State->RecentSelectionType = selection_type_keyframe; - } - - State->Test.SetCurrentChannel(draw_list, 1); - - ImVec2 ButtonSize(16, 16); - - ImGui::PushID(k); - int Max = PointAddress[Idx]->IsSelected ? 2 : 0; - for (int b = Max; b >= 0; b--) { - ImU32 PointCol = ((PointAddress[Idx]->IsSelected - 1) == b) ? ImColor(0.8f, 0.5f, 0.0f, 1.0f) : ImColor(0.1f, 0.1f, 0.1f, 1.0f); - ImU32 LineCol = ((PointAddress[Idx]->IsSelected - 1) == b) ? ImColor(0.8f, 0.5f, 0.5f, 1.0f) : ImColor(0.4f, 0.4f, 0.4f, 1.0f); - ImGui::PushID(b); - ImGui::SetCursorScreenPos(Keyframe_ScreenPos[NewIdx + b] - (ButtonSize * 0.5)); - ImGui::InvisibleButton("##keyframemover", ButtonSize, ImGuiMouseButton_Left); - bool32 IsHovered = ImGui::IsItemHovered(); - bool32 IsItemActive = ImGui::IsItemActive(); - bool32 IsItemActivated = ImGui::IsItemActivated(); - bool32 IsItemDeactivated = ImGui::IsItemDeactivated(); - bool32 LeftClick = ImGui::IsMouseDown(ImGuiMouseButton_Left); - bool32 RightClick = ImGui::IsMouseDown(ImGuiMouseButton_Right); - - if (IsHovered) { - PointCol = ImColor(1.0f, 0.8f, 0.8f, 1.0f); - ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); - } - - if (IsItemActivated) { - PointAddress[Idx]->IsSelected = b+1; - } - - if (b != 0 && PointAddress[Idx]->IsSelected) - draw_list->AddLine(Keyframe_ScreenPos[NewIdx], Keyframe_ScreenPos[NewIdx + b], LineCol, 2.0f); - - if (b == 0) { - draw_list->AddCircleFilled(Keyframe_ScreenPos[NewIdx + b], 4, PointCol); - if (IsGraphSelected) { - char buf[8]; - sprintf(buf, "%.2f", Keyframe_LocalPos[0].y); - draw_list->AddText(Keyframe_ScreenPos[NewIdx + b], 0xFFFFFFFF, buf); - } - } else { - draw_list->AddCircle(Keyframe_ScreenPos[NewIdx + b], 6, PointCol, 0, 2); - } - - ImGui::PopID(); - } - ImGui::PopID(); - - State->Test.SetCurrentChannel(draw_list, 0); - - if (p != 0) { - if (PointAddress[0]->Type == interpolation_type_bezier && PointAddress[1]->Type == interpolation_type_bezier) { - draw_list->AddBezierCubic(Keyframe_ScreenPos[OldIdx], Keyframe_ScreenPos[OldIdx + 2], - Keyframe_ScreenPos[NewIdx + 1], Keyframe_ScreenPos[NewIdx], GraphCol, 1.0f, 0); - } else { - draw_list->AddLine(Keyframe_ScreenPos[0], Keyframe_ScreenPos[3], GraphCol, 1.0f); - } - } - } - } - ImGui::PopID(); - } - ImGui::PopID(); - } - } - State->Test.Merge(draw_list); -} - - -static void -ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, ImDrawList *draw_list, int16 RecursionIdx[MAX_PRECOMP_RECURSIONS], uint32 Recursions, - ImVec2 Increment, ImVec2 TimelineAbsolutePos, ImVec2 TimelineMoveSize, ImVec2 TimelineZoomSize, - ImVec2 TimelineSize, ImVec2 TimelineSizeWithBorder, real32 LayerIncrement, - sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray) -{ - uint16 CompIndex = 0; - if (RecursionIdx[Recursions] == -1) { - CompIndex = File->PrincipalCompIndex; - } else { - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, RecursionIdx[Recursions]); - CompIndex = Layer->Block_Source_Index; - } - block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, CompIndex); - sorted_comp_info SortedCompInfo = SortedCompArray[CompIndex]; - sorted_layer *SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, SortedCompArray, CompIndex); - - ImGui::PushID(CompIndex); - - // NOTE(fox): Layer sorting pre-calculates UI positioning, so the order layers are drawn is arbitrary. - real32 DisplayOffset = 0; - for (int i = SortedCompInfo.LayerCount - 1; i >= 0; i--) - { - sorted_layer SortEntry = SortedLayerInfo[i]; - uint32 Index_Physical = SortEntry.Block_Layer_Index; - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical); - - int32 Frame_Start = Layer->Frame_Start; - int32 Frame_End = Layer->Frame_End; - real32 Vertical_Offset = SortEntry.SortedOffset + DisplayOffset; - - Layer_Evaluate_Display(State, Memory, Layer, SortedPropertyInfo, SortedPropertyArray, SortedLayerArray, SortedCompArray, SortedLayerInfo, i, &DisplayOffset); - - if (Layer->IsSelected) - Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End); - - ImVec2 Layer_LocalPos = ImVec2(Frame_Start, Vertical_Offset); - ImVec2 Layer_LocalSize = ImVec2(Frame_End - Frame_Start, Layer->Vertical_Height); - - ImVec2 Layer_LocalPos_Ratio = (Layer_LocalPos * Increment); - ImVec2 Layer_LocalSize_Ratio = Layer_LocalSize * Increment; - ImVec2 Layer_ScreenPos_Min = TimelineAbsolutePos + TimelineMoveSize + (Layer_LocalPos_Ratio * TimelineZoomSize); - ImVec2 Layer_ScreenPos_Max = TimelineAbsolutePos + TimelineMoveSize + ((Layer_LocalPos_Ratio + Layer_LocalSize_Ratio) * TimelineZoomSize); - ImVec2 Layer_ScreenSize = Layer_ScreenPos_Max - Layer_ScreenPos_Min; - - // UI - - ImU32 LayerColor = 0; - ImU32 BorderColor = 0; - LayerColor = ImColor(UI->LayerColors[Layer->ColIndex]); - BorderColor = ImColor(0.2, 0.2, 0.2, 1.0f); - - draw_list->AddRectFilled(Layer_ScreenPos_Min, Layer_ScreenPos_Max, LayerColor); - draw_list->AddRect(Layer_ScreenPos_Min, Layer_ScreenPos_Max, BorderColor, 2); - block_string *String = (block_string *)Memory_Block_AddressAtIndex(Memory, F_Strings, Layer->Block_String_Index); - char buf[128]; -#if DEBUG - sprintf(buf, "%s, %i", String->Char, Index_Physical); -#else - sprintf(buf, "%s", String->Char); -#endif - if (UI->TimelinePercentZoomed.y <= 1.0f) - draw_list->AddText(Layer_ScreenPos_Min, 0xFFFFFFFF, buf); - - if (Layer->IsSelected == 1) { - draw_list->AddRectFilled(Layer_ScreenPos_Min, Layer_ScreenPos_Max, ImColor(0.25f, 0.25f, 0.25f, 0.5f), 2); - draw_list->AddRect(Layer_ScreenPos_Min, Layer_ScreenPos_Max, ImColor(1.0f, 1.0f, 1.0f, 0.5f), 2); - } else if (Layer->IsSelected == 2) { - // draw_list->AddRectFilled(Layer_ScreenPos_Min, Layer_ScreenPos_Max, ImColor(0.25f, 0.25f, 0.25f, 0.5f), 2); - draw_list->AddRect(Layer_ScreenPos_Min, Layer_ScreenPos_Max, ImColor(0.0f, 0.9f, 0.0f, 0.9f), 4); - } - - // - - // Main interaction - - ImGui::PushID(i); - if (State->TimelineMode == timeline_mode_default) { - - if (State->BoxSelect && State->TimelineMode == timeline_mode_default) { - bool32 Test = 0; - if (io.MouseClickedPos[0].y < io.MousePos.y) - Test = (Layer_ScreenPos_Min.y >= io.MouseClickedPos[0].y && Layer_ScreenPos_Min.y <= io.MousePos.y); - else - Test = (Layer_ScreenPos_Max.y <= io.MouseClickedPos[0].y && Layer_ScreenPos_Max.y >= io.MousePos.y); - - if (io.MouseClickedPos[0].x < io.MousePos.x) - Test &= (Layer_ScreenPos_Max.x >= io.MouseClickedPos[0].x && Layer_ScreenPos_Min.x <= io.MousePos.x); - else - Test &= (Layer_ScreenPos_Min.x <= io.MouseClickedPos[0].x && Layer_ScreenPos_Max.x >= io.MousePos.x); - - if (Test) { - if (!Layer->IsSelected) { - Layer_Select(Memory, State, Index_Physical); - } - } else if (!io.KeyShift) { - Layer->IsSelected = false; - } - } - - - ImVec2 ResizeSize = ImVec2(Increment.x * 0.45 * TimelineZoomSize.x, Layer_ScreenSize.y); - ImVec2 ResizePos[2] = { Layer_ScreenPos_Min, ImVec2(Layer_ScreenPos_Max.x - ResizeSize.x, Layer_ScreenPos_Min.y) }; - for (int b = 0; b < 2; b++) { - ImGui::PushID(b); - ImGui::SetCursorScreenPos(ResizePos[b]); - ImGui::Button("##layer_resize", ResizeSize); - - if (ImGui::IsItemHovered()) { - ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); - } - if (ImGui::IsItemActivated()) { - if (!Layer->IsSelected) { - if (!io.KeyShift) Layer_DeselectAll(File, State, Memory); - Layer_Select(Memory, State, Index_Physical); - } - } - if (ImGui::IsItemActive()) { - if (ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1)) { - Assert(Layer->IsSelected); - State->Interact_Active = interact_type_layer_timeadjust; - ImVec2 DragDelta = ImGui::GetMouseDragDelta(); - DragDelta = DragDelta + (ImVec2(State->Warp_X, State->Warp_Y) * TimelineSize); - - State->Interact_Offset[0] = (DragDelta.x / TimelineSizeWithBorder.x * UI->TimelinePercentZoomed.x) * Comp->Frame_Count; - State->Interact_Offset[1] = b; - } - } - if (ImGui::IsItemDeactivated()) { - if (State->Interact_Active == interact_type_layer_timeadjust) { - History_Entry_Commit(Memory, "Adjust layer timing"); - int h = 0, c = 0, i = 0; - while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i)) { - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); - if (Layer->IsSelected) { - // NOTE(fox): Some data on the tree could be saved here. - History_Action_Swap(Memory, F_File, sizeof(Layer->Frame_Start), &Layer->Frame_Start); - History_Action_Swap(Memory, F_File, sizeof(Layer->Frame_End), &Layer->Frame_End); - Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Layer->Frame_Start, &Layer->Frame_End); - } - } - History_Entry_End(Memory); - State->Interact_Active = interact_type_none; - State->Interact_Modifier = 0; - State->Interact_Offset[0] = 0; - State->Interact_Offset[1] = 0; - } - } - - ImGui::PopID(); - } - - ImGui::SetCursorScreenPos(Layer_ScreenPos_Min); - ImGui::InvisibleButton("##layer_mid", Layer_ScreenSize, ImGuiMouseButton_Left); - - if (ImGui::IsItemActivated()) { - if (!Layer->IsSelected) { - if (!io.KeyShift) Layer_DeselectAll(File, State, Memory); - Layer_Select(Memory, State, Index_Physical); - Layer_Select_RecurseUp(Memory, State, Index_Physical, RecursionIdx, Recursions); - } - } - - ImGui::OpenPopupOnItemClick("layerpopup", ImGuiPopupFlags_MouseButtonRight); - if (ImGui::BeginPopup("layerpopup")) { - if (ImGui::Selectable("Visible")) { - bool32 Commit = false; - 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) { - if (!Commit) { - History_Entry_Commit(Memory, "Toggle visibility"); - Commit = true; - } - History_Action_Swap(Memory, F_File, sizeof(Layer->IsVisible), &Layer->IsVisible); - Layer->IsVisible ^= 1; - } - } - if (Commit) { - History_Entry_End(Memory); - State->UpdateFrame = true; - } - } - if (ImGui::MenuItem("Pre-compose layer")) { - Precomp_UICreateButton(File, State, Memory, CompIndex, SortedCompInfo, SortedLayerInfo); - State->UpdateKeyframes = true; - } - if (ImGui::MenuItem("Duplicate layer")) { - Precomp_UIDuplicate(File, State, Memory, CompIndex, SortedCompInfo, SortedLayerInfo); - } - if (ImGui::MenuItem("Delete layer")) { - Precomp_UICreateButton(File, State, Memory, CompIndex, SortedCompInfo, SortedLayerInfo); - State->UpdateKeyframes = true; - } - if (ImGui::BeginMenu("Layer color")) - { - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); - for (int c = 0; c < AmountOf(UI->LayerColors); c++) { - ImGui::PushID(c); - ImGui::PushStyleColor(ImGuiCol_Button, UI->LayerColors[c]); - real32 Size = ImGui::GetFontSize() * 2; - ImVec2 ColSize(Size, Size); - 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(); - } - ImGui::PopStyleVar(); - ImGui::EndMenu(); - } - uint32 *item_current_idx = (uint32 *)&Layer->BlendMode; // 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(); - } - ImGui::EndPopup(); - } - - if (ImGui::IsItemActive()) { - if (ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1)) { - if (State->Interact_Active == interact_type_none) { - State->Interact_Active = interact_type_layer_move; - // TODO(fox): Selected layers inside precomps will have interactions doubled, - // so I'm forcing interaction to only be with members of the same precomp. - // Could be made more intuitive later. - Layer_RecursiveDeselect(Memory, SortedCompArray, SortedLayerArray, Layer->Block_Composition_Index, File->PrincipalCompIndex); - } - ImVec2 DragDelta = ImGui::GetMouseDragDelta(); - DragDelta = DragDelta + (ImVec2(State->Warp_X, State->Warp_Y) * TimelineSize); - - ImVec2 Offset_Old = ImVec2(State->Interact_Offset[0], State->Interact_Offset[1]); - ImVec2 Offset_New = (DragDelta / TimelineSizeWithBorder * UI->TimelinePercentZoomed) * ImVec2(Comp->Frame_Count, -LayerIncrement); - - // if (((int32)Offset_Old.x != (int32)Offset_New.x) || ((int32)Offset_Old.y != (int32)Offset_New.y)) - State->UpdateFrame = true; - - State->Interact_Offset[0] = Offset_New.x; - State->Interact_Offset[1] = Offset_New.y; - } - } - - if (ImGui::IsItemDeactivated()) { - if (State->Interact_Active == interact_type_layer_move) { - History_Entry_Commit(Memory, "Move layers"); - for (int i = 0; i < SortedCompInfo.LayerCount; i++) - { - sorted_layer SortEntry = SortedLayerInfo[i]; - uint32 Index_Physical = SortEntry.Block_Layer_Index; - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical); - // NOTE(fox): Some data on the tree could be saved here. - History_Action_Swap(Memory, F_File, sizeof(Layer->Vertical_Offset), &Layer->Vertical_Offset); - Layer->Vertical_Offset = SortEntry.SortedOffset; - if (Layer->IsSelected) { - History_Action_Swap(Memory, F_File, sizeof(Layer->Frame_Start), &Layer->Frame_Start); - History_Action_Swap(Memory, F_File, sizeof(Layer->Frame_End), &Layer->Frame_End); - Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Layer->Frame_Start, &Layer->Frame_End); - } - } - State->Interact_Active = interact_type_none; - State->Interact_Modifier = 0; - History_Entry_End(Memory); - } - } - - // Keyframe view - uint32 Channel = 0; - - sorted_property_info *InfoLocation = SortedPropertyInfo + SortedLayerInfo->SortedPropertyStart; - uint16 *ArrayLocation = SortedPropertyArray + SortedLayerInfo->SortedKeyframeStart; - int h = 0, c = 0, p = 0; - property_channel *Property = NULL; - block_effect *Effect = NULL; - while (Layer_LoopChannels(State, Memory, &InfoLocation, &ArrayLocation, Layer, &Property, &Effect, &h, &c, &p)) - { - if (Property->IsToggled) { - ImVec2 GraphMinPos = ImVec2(TimelineAbsolutePos.x, Layer_ScreenPos_Min.y + Layer_ScreenSize.y + (Layer_ScreenSize.y * Channel)); - ImVec2 GraphPos = GraphMinPos + ImVec2(0, Layer_ScreenSize.y); - ImVec2 GraphMinBounds = GraphMinPos + ImVec2(0, Layer_ScreenSize.y * 0.5); - ImVec2 GraphMaxBounds = GraphMinBounds + ImVec2(TimelineSizeWithBorder.x, Layer_ScreenSize.y); - uint32 col = (Channel % 2) ? IM_COL32(50, 50, 50, 255) : IM_COL32(50, 50, 50, 128); - draw_list->AddRectFilled(GraphMinBounds, GraphMaxBounds, col); - ImGui_Timeline_DrawKeySheet(File, State, Memory, UI, io, draw_list, Property, ArrayLocation, - Increment, TimelineAbsolutePos, GraphPos, TimelineMoveSize, TimelineZoomSize, - TimelineSize, TimelineSizeWithBorder, LayerIncrement, - SortedCompArray, SortedLayerArray, SortedPropertyInfo, SortedPropertyArray); - Channel++; - } - } - } - - // - - // Precomp recursion - - if (Layer->IsPrecomp && Layer->Precomp_Toggled) { - - sorted_layer *Precomp_SortedLayerInfo = Layer_GetSortedArray(SortedLayerArray, SortedCompArray, Layer->Block_Source_Index); - sorted_comp_info Precomp_SortedCompInfo = SortedCompArray[Layer->Block_Source_Index]; - - block_layer *Layer_Top = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Precomp_SortedLayerInfo[Precomp_SortedCompInfo.LayerCount - 1].Block_Layer_Index); - block_layer *Layer_Bottom = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Precomp_SortedLayerInfo[0].Block_Layer_Index); - real32 SmallestY = Layer_Top->Vertical_Offset; - real32 LargestY = Layer_Bottom->Vertical_Offset; - // Layer_Evaluate_Display(Layer_Top, SortedLayerArray, SortedCompArray, Precomp_SortedLayerInfo, Precomp_SortedCompInfo.LayerCount - 1, &SmallestY); - // Layer_Evaluate_Display(Layer_Bottom, SortedLayerArray, SortedCompArray, Precomp_SortedLayerInfo, 0, &LargestY); - real32 PrecompHeight = LargestY - SmallestY + 2; - - ImVec2 MinClipPos = ImVec2(Layer_ScreenPos_Min.x, Layer_ScreenPos_Max.y); - ImVec2 MaxClipPos = ImVec2(Layer_ScreenPos_Max.x, MinClipPos.y + (PrecompHeight * Increment.y * TimelineZoomSize.y)); - draw_list->AddRectFilled(MinClipPos, MaxClipPos, ImColor(0.2f, 0.2f, 0.2f, 1.0f)); - - - ImVec2 Layer_LocalPos_Screen = Layer_LocalPos_Ratio * TimelineZoomSize; - ImVec2 NestedTimelineAbsolutePos = TimelineAbsolutePos + Layer_LocalPos_Screen - ImVec2(0, SmallestY * Increment.y * TimelineZoomSize.y) + ImVec2(0, Layer_ScreenSize.y * 1.5); - - ImGui::PushClipRect(MinClipPos, MaxClipPos, true); - draw_list->PushClipRect(MinClipPos, MaxClipPos, true); - uint32 RecursionsCount = Recursions+1; - RecursionIdx[RecursionsCount] = Index_Physical; - ImGui_Timeline_DrawPrecomp(File, State, Memory, UI, io, draw_list, RecursionIdx, RecursionsCount, - Increment, NestedTimelineAbsolutePos, TimelineMoveSize, TimelineZoomSize, - TimelineSize, TimelineSizeWithBorder, LayerIncrement, - SortedCompArray, SortedLayerArray, SortedPropertyInfo, SortedPropertyArray); - draw_list->PopClipRect(); - ImGui::PopClipRect(); - - } - - // - - ImGui::PopID(); - } - - ImGui::PopID(); -} - -static void -ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, - sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray, sorted_property_info *SortedPropertyInfo, uint16 *SortedPropertyArray) -{ - ImVec2 FramePadding = ImGui::GetStyle().FramePadding; - ImVec2 ItemSpacing = ImGui::GetStyle().ItemSpacing; - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); // makes setting up the layout easier - ImGui::Begin("Timeline", NULL); - - if (ImGui::IsWindowHovered(ImGuiFocusedFlags_ChildWindows)) { - State->FocusedWindow = focus_timeline; - } - - // if (State->TimelineMode == timeline_mode_graph) - // ImGui_GraphInfo(File, State, Memory, UI, io, SortedPropertyInfo, SortedPropertyArray); - - real32 FontHeight = ImGui::GetFontSize(); - - ImVec2 WindowSize = ImGui::GetWindowSize(); - - if (WindowSize.x < 50 || WindowSize.y < 50) { - ImGui::PopStyleVar(2); - ImGui::End(); - return; - } - - block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, File->PrincipalCompIndex); - - ImVec2 WindowMinAbs = ImGui::GetWindowPos(); - ImVec2 WindowMaxAbs = WindowMinAbs + WindowSize; - - ImVec2 ButtonSize = ImVec2(FontHeight*2, FontHeight*2); - - ImVec2 TimelineBorderPadding = ImVec2(FontHeight, FontHeight); - - ImVec2 TimelineSize = ImVec2(WindowSize.x, WindowSize.y); - ImVec2 TimelineSizeWithBorder = TimelineSize - TimelineBorderPadding*2; - ImVec2 TimelineAbsolutePos = WindowMinAbs + TimelineBorderPadding; - - ImVec2 KeyframeSize = ImVec2(FontHeight, FontHeight); - - int32 FrameCount = MainComp->Frame_Count; - - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - draw_list->AddRectFilled(WindowMinAbs, WindowMaxAbs, - IM_COL32(255, 255, 255, 50)); - - - ImGui::BeginChild("Timeline", TimelineSize, true, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar); - - ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, ItemSpacing.y)); - - ImGui::PushClipRect(TimelineAbsolutePos, TimelineAbsolutePos + TimelineSizeWithBorder, true); - draw_list->PushClipRect(TimelineAbsolutePos, TimelineAbsolutePos + TimelineSizeWithBorder, true); - - real32 LayerIncrement = 40; - - ImVec2 Val_Min(0, 0); - ImVec2 Val_Max(40, LayerIncrement); - - // DebugWatchVar("Selection", &State->RecentSelectionType, d_int); - - // ImVec2 *ActivePercentZoomed = (UI->TimelineMode != timeline_mode_graph) ? &UI->TimelinePercentZoomed : &UI->GraphPercentZoomed; - // ImVec2 *ActivePercentOffset = (UI->TimelineMode != timeline_mode_graph) ? &UI->TimelinePercentOffset : &UI->GraphPercentOffset; - ImVec2 *ActivePercentZoomed = &UI->TimelinePercentZoomed; - ImVec2 *ActivePercentOffset = &UI->TimelinePercentOffset; - - if (ActivePercentZoomed->x == 0) { - *ActivePercentZoomed = ImVec2(1, 1); - } - - ImVec2 ActiveZoomSize = TimelineSizeWithBorder / *ActivePercentZoomed; - ImVec2 ActiveMoveSize = TimelineSizeWithBorder * *ActivePercentOffset / *ActivePercentZoomed; - - ImVec2 TimelineZoomSize = TimelineSizeWithBorder / UI->TimelinePercentZoomed; - ImVec2 TimelineMoveSize = TimelineSizeWithBorder * UI->TimelinePercentOffset / UI->TimelinePercentZoomed; - - // DebugWatchVar("TimelineY: ", &TimelineMoveSize.y, d_float); - - ImVec2 Increment = ImVec2((real32)1 / MainComp->Frame_Count, (real32)1 / LayerIncrement); - - ImGui_Timeline_BGElements(State, UI, draw_list, TimelineSizeWithBorder, TimelineAbsolutePos, *MainComp, TimelineZoomSize, TimelineMoveSize); - - int16 RecursionIdx[MAX_PRECOMP_RECURSIONS] = {}; - int32 Recursions = 0; - RecursionIdx[0] = -1; - ImGui_Timeline_DrawPrecomp(File, State, Memory, UI, io, draw_list, RecursionIdx, Recursions, - Increment, TimelineAbsolutePos, TimelineMoveSize, TimelineZoomSize, - TimelineSize, TimelineSizeWithBorder, LayerIncrement, - SortedCompArray, SortedLayerArray, SortedPropertyInfo, SortedPropertyArray); - - if (State->TimelineMode == timeline_mode_graph) { - - if (UI->GraphMoveSize.y == 0) { - UI->GraphZoomSize = ImVec2(1, UI->TimelinePercentZoomed.y ); - UI->GraphMoveSize = ImVec2(0, -UI->TimelinePercentOffset.y ); - } - - ImVec2 ZoomDifference = (UI->TimelinePercentZoomed / UI->GraphZoomSize); - ImVec2 MoveDifference = (UI->TimelinePercentOffset + (UI->GraphMoveSize)); - // DebugWatchVar("zoomdif: ", &ZoomDifference.y, d_float); - // DebugWatchVar("movedif: ", &MoveDifference.y, d_float); - ImVec2 GraphZoomSize = TimelineSizeWithBorder / ZoomDifference; - ImVec2 GraphMoveSize = TimelineSizeWithBorder * (MoveDifference) / UI->TimelinePercentZoomed; - // DebugWatchVar("zoomsize: ", &GraphZoomSize.y, d_float); - // DebugWatchVar("movesize: ", &GraphMoveSize.y, d_float); - - draw_list->AddRectFilled(WindowMinAbs, WindowMaxAbs, - IM_COL32(50, 50, 50, 230)); - ImGui_Timeline_DrawGraph(File, State, Memory, UI, io, draw_list, - Increment, TimelineAbsolutePos, GraphMoveSize, GraphZoomSize, - TimelineSize, TimelineSizeWithBorder, LayerIncrement, - SortedCompArray, SortedLayerArray, - SortedPropertyInfo, SortedPropertyArray); - } - - ImGui_Timeline_HorizontalIncrementDraw(State, UI, draw_list, TimelineSizeWithBorder, TimelineAbsolutePos, *MainComp, TimelineZoomSize, TimelineMoveSize); - - - ImVec2 MouseDelta = io.MouseDelta / TimelineSize; - - real32 BarHandleSize = FontHeight; - real32 BarThickness = 50; - real32 BarMinZoom = 0.01; - - real32 BarH_Pos = -TimelineSizeWithBorder.x * ActivePercentOffset->x; - real32 BarH_Size = TimelineSizeWithBorder.x / (1 / ActivePercentZoomed->x); - - // I use "UI" to denote the size/position after clipping the bar so that it - // doesn't go out of bounds and the handles are always selectable at the edges. - - real32 BarH_Offset = Max(BarH_Pos, 0); - - real32 BarH_SizeUI = (BarH_Size + BarH_Pos > TimelineSizeWithBorder.x) ? - TimelineSizeWithBorder.x - BarH_Pos : - BarH_Size + (BarH_Pos - BarH_Offset); - - if (BarH_Offset == 0 && BarH_SizeUI > TimelineSizeWithBorder.x) - BarH_SizeUI = TimelineSizeWithBorder.x; - - BarH_SizeUI = BarH_SizeUI - BarHandleSize*2; - - BarH_SizeUI = Max(BarH_SizeUI, FontHeight*4); - - BarH_Offset = Min(BarH_Offset, TimelineSize.x - BarH_SizeUI - BarHandleSize*4); - ImVec2 BarH_PosUI = TimelineAbsolutePos + ImVec2(BarH_Offset, TimelineSize.y - BarThickness); - bool32 BarHeld = false; - - ImGui::SetCursorScreenPos(BarH_PosUI); - ImGui::Button("##scrollbarleft", ImVec2(BarHandleSize, BarThickness)); - - if ((ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1))) - { - if ((ActivePercentZoomed->x - MouseDelta.x) > BarMinZoom) { - ActivePercentZoomed->x -= MouseDelta.x; - ActivePercentOffset->x -= MouseDelta.x; - } - BarHeld = true; - } - - ImGui::SetCursorScreenPos(BarH_PosUI + ImVec2(BarHandleSize, 0)); - ImGui::Button("##scrollbarhori", ImVec2(BarH_SizeUI, BarThickness)); - - if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1)) - { - ActivePercentOffset->x -= MouseDelta.x; - BarHeld = true; - } - - ImGui::SetCursorScreenPos(BarH_PosUI + ImVec2(BarHandleSize, 0) + ImVec2(BarH_SizeUI, 0)); - ImGui::Button("##scrollbarright", ImVec2(BarHandleSize, BarThickness)); - - if ((ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1))) - { - if ((ActivePercentZoomed->x + MouseDelta.x) > BarMinZoom) { - ActivePercentZoomed->x += MouseDelta.x; - } - BarHeld = true; - } - - if (BarHeld) { - ImGui_WarpMouse(State, io.MousePos, TimelineAbsolutePos, TimelineAbsolutePos + TimelineSizeWithBorder, 1); - } - - Assert(ActivePercentZoomed->x > BarMinZoom); - - real32 BarV_MaxSize = TimelineSizeWithBorder.y - BarThickness/2; - real32 BarV_Pos = -BarV_MaxSize * ActivePercentOffset->y; - real32 BarV_Size = BarV_MaxSize / (1 / ActivePercentZoomed->y); - BarV_Size = Max(BarV_Size, FontHeight*4); - - real32 BarV_Offset = Max(BarV_Pos, 0); - - real32 BarV_SizeUI = (BarV_Size + BarV_Pos > BarV_MaxSize) ? - BarV_MaxSize - BarV_Pos : - BarV_Size + (BarV_Pos - BarV_Offset); - - if (BarV_Offset == 0 && BarV_SizeUI > BarV_MaxSize) - BarV_SizeUI = BarV_MaxSize; - - BarV_SizeUI = BarV_SizeUI - BarHandleSize*2; - - BarV_SizeUI = Max(BarV_SizeUI, FontHeight*4); - - BarV_Offset = Min(BarV_Offset, BarV_MaxSize - BarV_SizeUI - BarHandleSize*4); - ImVec2 BarV_PosUI = TimelineAbsolutePos + ImVec2(TimelineSize.x - BarThickness, BarV_Offset); - BarHeld = false; - - ImGui::SetCursorScreenPos(BarV_PosUI); - ImGui::Button("##h-scrollbarleft", ImVec2(BarThickness, BarHandleSize)); - - if ((ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1))) - { - ActivePercentZoomed->y -= MouseDelta.y; - ActivePercentOffset->y -= MouseDelta.y; - BarHeld = true; - } - - ImGui::SetCursorScreenPos(BarV_PosUI + ImVec2(0, BarHandleSize)); - ImGui::Button("##h-scrollbar", ImVec2(BarThickness, BarV_SizeUI)); - - if (ImGui::IsItemHovered() && io.MouseWheel) - { - ActivePercentOffset->y -= io.MouseWheel/10; - } - - if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1)) - { - ActivePercentOffset->y -= MouseDelta.y; - BarHeld = true; - } - - ImGui::SetCursorScreenPos(BarV_PosUI + ImVec2(0, BarHandleSize) + ImVec2(0, BarV_SizeUI)); - ImGui::Button("##h-scrollbarright", ImVec2(BarThickness, BarHandleSize)); - - if ((ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1))) - { - ActivePercentZoomed->y += MouseDelta.y; - BarHeld = true; - } - - ActivePercentZoomed->y = Max(ActivePercentZoomed->y, 0.01); - - if (BarHeld) { - ImGui_WarpMouse(State, io.MousePos, TimelineAbsolutePos, TimelineAbsolutePos + TimelineSizeWithBorder, 2); - } - - ImGui::SetCursorScreenPos(TimelineAbsolutePos); - ImGui::InvisibleButton("TimelineMoving", TimelineSizeWithBorder, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight); - // ImGui::Button("TimelineMoving", TimelineSizeWithBorder); - bool32 IsHovered = ImGui::IsItemHovered(); - bool32 IsItemActive = ImGui::IsItemActive(); - bool32 IsItemActivated = ImGui::IsItemActivated(); - bool32 IsItemDeactivated = ImGui::IsItemDeactivated(); - bool32 LeftClick = ImGui::IsMouseDown(ImGuiMouseButton_Left); - bool32 RightClick = ImGui::IsMouseDown(ImGuiMouseButton_Right); - - if (IsHovered && io.MouseWheel) { - real32 Increment = 0.1; - bool32 Direction = (io.MouseWheel > 0) ? 1 : -1; - ImVec2 Offset = (io.MousePos - (TimelineAbsolutePos + ActiveMoveSize)) / ActiveZoomSize; - if (io.KeyShift) { - ActivePercentOffset->y += Increment*Direction; - } else if (io.KeyCtrl) { - ActivePercentOffset->x += Increment*Direction*0.3; - } else { - if (Direction == 1) { - *ActivePercentZoomed = *ActivePercentZoomed - (*ActivePercentZoomed * Increment); - *ActivePercentOffset = *ActivePercentOffset - ((*ActivePercentOffset * Increment) + Offset*Increment); - } else { - *ActivePercentOffset = ((*ActivePercentOffset + Offset*Increment) / (1.0f - Increment)); - *ActivePercentZoomed = (*ActivePercentZoomed / (1.0f - Increment)); - } - } - } - - if (LeftClick) { - if (IsItemActivated) { - if (!io.KeyShift && State->TimelineMode == timeline_mode_default) Layer_DeselectAll(File, State, Memory); - if (State->Interact_Active == interact_type_keyframe_move || - State->Interact_Active == interact_type_keyframe_rotate || - State->Interact_Active == interact_type_keyframe_scale) { - Bezier_Commit(File, State, Memory, SortedCompArray, SortedLayerArray, SortedPropertyInfo, SortedPropertyArray); - } - State->BoxSelect = true; - } - if (IsItemActive) { - Assert(State->BoxSelect); - draw_list->AddRectFilled(io.MouseClickedPos[0], io.MousePos, - IM_COL32(0, 0, 200, 50)); - } - } else { - State->Warp_X = 0; - State->Warp_Y = 0; - } - - if (IsItemDeactivated) { - State->BoxSelect = false; - } - - draw_list->PopClipRect(); - ImGui::PopClipRect(); - - ImGui::PopStyleVar(); - - - ImGui::EndChild(); - - ImGui::PopStyleVar(2); - - ImGui::End(); -} - -#include "keybinds.h" - -static void -ImGui_Key_GetUIInfo(key_entry KeyEntry, real32 KeySize, ImVec2 *Offset_ScreenPos, ImVec2 *KeyScreenSize) { - ImVec2 Extra(0, 0); - if (KeyEntry.Sector == 0) { - if (KeyEntry.Offset.x != 0) { - if (KeyEntry.Offset.y == 1) { - Extra.x += 0.5; - } - if (KeyEntry.Offset.y == 2) { - Extra.x += 0.75; - } - if (KeyEntry.Offset.y == 3) { - Extra.x += 1.5; - } - } - } - *Offset_ScreenPos = ImVec2(KeySize, KeySize) * (SectorOffset[KeyEntry.Sector] + Extra + KeyEntry.Offset); - *KeyScreenSize = (KeyEntry.WidthRatio > 0.0f) ? ImVec2(KeySize * KeyEntry.WidthRatio, KeySize) : ImVec2(KeySize, KeySize * -KeyEntry.WidthRatio); -} - -static void -ImGui_KeybindUI(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io) -{ - real32 KeySize = ImGui::GetFontSize()*2; - real32 KeyboardWidth = KeySize * 23.5; - real32 KeyboardHeight = KeySize * 7; - ImVec2 WindowSize = ImGui::GetWindowSize(); - ImVec2 WindowMinAbs = ImGui::GetWindowPos(); - ImVec2 WindowMaxAbs = WindowMinAbs + WindowSize; - ImVec2 KeyboardPos((WindowSize.x - KeyboardWidth) / 2, KeySize*2); - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - ImVec2 SectorOffset[4] = { ImVec2(0, 1.25), ImVec2(0,0), ImVec2(15.25, 1.25), ImVec2(19.5, 1.25) }; - - ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(190, 0, 50, 180)); - if (ImGui::Button("X")) - ImGui::CloseCurrentPopup(); - ImGui::PopStyleColor(); - - State->Split_KeybindUI.Split(draw_list, 2); - State->Split_KeybindUI.SetCurrentChannel(draw_list, 1); - - // keyboard - ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 180)); - for (int k = 0; k < AmountOf(KeyEntries); k++) { - key_entry KeyEntry = KeyEntries[k]; - ImVec2 Offset_ScreenPos(0,0); - ImVec2 KeyScreenSize(0,0); - ImGui_Key_GetUIInfo(KeyEntry, KeySize, &Offset_ScreenPos, &KeyScreenSize); - if (KeyEntry.Name[0] != '\0') { - ImGui::PushID(k); - ImGui::SetCursorScreenPos(WindowMinAbs + KeyboardPos + Offset_ScreenPos); - ImGui::Button(KeyEntry.Name, KeyScreenSize); - ImGui::PopID(); - } - } - ImGui::PopStyleColor(); - - State->Split_KeybindUI.SetCurrentChannel(draw_list, 0); - - // list - ImVec2 SubwindowMinPos(WindowMinAbs + KeyboardPos + ImVec2(0, KeyboardHeight + KeySize)); - ImVec2 SubwindowSize(KeyboardWidth, WindowSize.y - KeyboardHeight - KeySize*4); - ImGui::SetCursorScreenPos(SubwindowMinPos); - ImGui::BeginChild("Keybinds info", SubwindowSize); - key_mode CurrentKeyMode = (key_mode)9999; - for (int a = 0; a < AmountOf(ShortcutArray); a++) { - shortcut_entry ShortcutEntry = ShortcutArray[a]; - - // header info - if (CurrentKeyMode != ShortcutEntry.Mode) { - ImGui::Dummy(ImVec2(1, KeySize)); - CurrentKeyMode = ShortcutEntry.Mode; - ImVec2 Size = ImGui::CalcTextSize(KeyModeTitles[CurrentKeyMode]); - ImGui::SetCursorPosX(((SubwindowSize.x / 2) - (Size.x / 2))); - ImGui::Text(KeyModeTitles[CurrentKeyMode]); - ImGui::SetCursorPosX((SubwindowSize.x / 2) - (ImGui::CalcTextSize("-----").x / 2)); - ImGui::TextColored(ImColor(UI->LayerColors[CurrentKeyMode]), "-----"); - ImGui::Dummy(ImVec2(1, KeySize/4)); - while (ShortcutEntry.Key == ImGuiKey_None) { - ImVec2 Size = ImGui::CalcTextSize(ShortcutEntry.Name); - ImGui::SetCursorPosX(((SubwindowSize.x / 2) - (Size.x / 2))); - ImGui::Text(ShortcutEntry.Name); - a++; - ShortcutEntry = ShortcutArray[a]; - } - ImGui::Dummy(ImVec2(1, KeySize/2)); - } - - // shortcut text + key - Assert(ShortcutEntry.Key != ImGuiKey_None); - key_entry KeyEntry = KeyEntries[ShortcutEntry.Key - ImGuiKey_Tab]; - real32 Padding = KeySize; - ImGui::Dummy(ImVec2(Padding, 1)); - ImGui::SameLine(); - ImGui::Text(ShortcutEntry.Name); - ImGui::SameLine(); - char buf[64]; - if (ShortcutEntry.Mods == Mod_None) { - sprintf(buf, "%s", KeyEntry.Name); - } else if (ShortcutEntry.Mods == Mod_Shift) { - sprintf(buf, "%s", KeyEntry.ShiftName); - } else { - sprintf(buf, "%s + %s", KeyModText[ShortcutEntry.Mods], KeyEntry.Name); - } - ImVec2 Size = ImGui::CalcTextSize(buf); - ImGui::SetCursorPosX(SubwindowSize.x - Size.x - Padding*1.5); - ImGui::Text(buf); - - // indicator on keyboard - ImVec2 Offset_ScreenPos(0,0); - ImVec2 KeyScreenSize(0,0); - ImGui_Key_GetUIInfo(KeyEntry, KeySize, &Offset_ScreenPos, &KeyScreenSize); - real32 ModeSliverSize = KeySize / key_mode_count; - Offset_ScreenPos.x += (ShortcutEntry.Mode * ModeSliverSize); - KeyScreenSize = ImVec2(ModeSliverSize, KeyScreenSize.y); - ImVec2 MinPos = WindowMinAbs + KeyboardPos + Offset_ScreenPos; - draw_list->AddRectFilled(MinPos, MinPos + KeyScreenSize, UI->LayerColors[CurrentKeyMode]); - } - ImGui::EndChild(); - if (ImGui::IsKeyPressed(ImGuiKey_Escape)) { - ImGui::CloseCurrentPopup(); - } - ImGui::EndPopup(); - - State->Split_KeybindUI.Merge(draw_list); -} - -static void -ImGui_Popups(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io) -{ - switch (State->ImGuiPopups) - { - case popup_none: - { - } break; - case popup_saveas: - { - ImGui::OpenPopup("Save as"); - ImGui::SetKeyboardFocusHere(); - } break; - case popup_keybinds: - { - ImGui::OpenPopup("Keybinds"); - ImGui::SetKeyboardFocusHere(); - } break; - default: - { - Assert(0); - } - } - State->ImGuiPopups = popup_none; - - if (ImGui::BeginPopupModal("Save as")) { - ImGui::Text("Destination path..."); - ImGui::InputText("File", State->Filename, 512); - if (ImGui::Button("Save file")) { - ImGui::Text("Saving..."); - File_SaveAs(File, State, Memory, State->Filename); - ImGui::CloseCurrentPopup(); - } - if (ImGui::IsKeyPressed(ImGuiKey_Escape)) { - ImGui::CloseCurrentPopup(); - } - ImGui::EndPopup(); - } - if (ImGui::BeginPopupModal("Keybinds")) { - ImGui_KeybindUI(File, State, UI, Memory, io); - } -} - -static void -ImGui_ProcessInputs(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io, sorted_file Sorted) -{ - if (ImGui::IsKeyPressed(ImGuiKey_Q)) { - State->IsRunning = false; - } - if (ImGui::IsKeyPressed(ImGuiKey_W)) { - block_composition *MainComp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, File->PrincipalCompIndex); - State->Frame_Current = ((State->Frame_Current - 1) < 0) ? 0 : State->Frame_Current - 1; - State->UpdateFrame = true; - State->UpdateKeyframes = true; - } - if (ImGui::IsKeyPressed(ImGuiKey_E)) { - if (!io.KeyShift) { - 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; - State->UpdateFrame = true; - State->UpdateKeyframes = true; - } else { - State->Brush.EraseMode ^= 1; - } - } - if (ImGui::IsKeyPressed(ImGuiKey_U)) { - Project_ToggleAllChannels(File, State, Memory, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyInfo, Sorted.PropertyArray); - } - if (ImGui::IsKeyPressed(ImGuiKey_X)) { - if (State->TimelineMode == timeline_mode_graph && State->Interact_Active == interact_type_keyframe_move) { - if (State->Interact_Modifier != 1) - State->Interact_Modifier = 1; - else - State->Interact_Modifier = 0; - } else { - v4 Temp = UI->Color; - UI->Color = UI->AltColor; - UI->AltColor = Temp; - } - } - if (ImGui::IsKeyPressed(ImGuiKey_Y)) { - if (State->TimelineMode == timeline_mode_graph && State->Interact_Active == interact_type_keyframe_move) { - if (State->Interact_Modifier != 2) - State->Interact_Modifier = 2; - else - State->Interact_Modifier = 0; - } - } - if (ImGui::IsKeyPressed(ImGuiKey_V)) { - State->Tool = tool_default; - } - if (ImGui::IsKeyPressed(ImGuiKey_B)) { - State->Tool = tool_brush; - } - // NOTE(fox): File data not tracked on undo tree! - if (ImGui::IsKeyPressed(ImGuiKey_N)) { - if (io.KeyShift) { - 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; - } else { - 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)) { - State->TimelineMode = (State->TimelineMode == timeline_mode_default) ? timeline_mode_graph : timeline_mode_default; - UI->GraphZoomSize = ImVec2(0, 0); - UI->GraphMoveSize = ImVec2(0, 0); - } - if (!io.KeyCtrl) { - // NOTE(fox): Checking IsWindowHovered seems to be all we need to do to - // make per-window hotkeys work; setting it as the focused window causes - // problems with popups. - if (State->FocusedWindow == focus_timeline) { - if (State->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 (State->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 (State->FocusedWindow == focus_viewport) { - if (ImGui::IsKeyPressed(ImGuiKey_T)) { - Interact_Transform_Begin(File, Memory, State, io.MousePos, Sorted.CompArray, Sorted.LayerArray); - State->Tool = tool_default; - } - } - } - if (ImGui::IsKeyPressed(ImGuiKey_Escape)) { - if (State->Interact_Active == interact_type_keyframe_move || - State->Interact_Active == interact_type_keyframe_rotate || - State->Interact_Active == interact_type_keyframe_scale) { - State->Interact_Offset[0] = 0; - State->Interact_Offset[1] = 0; - State->Interact_Offset[2] = 0; - State->Interact_Offset[3] = 0; - State->Interact_Active = interact_type_none; - State->Interact_Modifier = 0; - State->UpdateFrame = true; - } - } - 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; - while (Block_Loop(Memory, F_Layers, File->Layer_Count, &h, &c, &i)) { - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); - if (Layer->IsSelected && Layer->IsPrecomp) { - Layer->Precomp_Toggled ^= 1; - } - } - } - - if (ImGui::IsKeyPressed(ImGuiKey_Delete)) - { - State->HotkeyInput = hotkey_deletelayer; - } - - if (io.KeyShift && ImGui::IsKeyPressed(ImGuiKey_Slash)) - { - State->ImGuiPopups = popup_keybinds; - } - -#if DEBUG - if (ImGui::IsKeyPressed(ImGuiKey_3)) - { - // State->ImGuiPopups = popup_keybinds; - Debug.DisableAlpha = 0; - State->UpdateFrame = true; - } - if (ImGui::IsKeyPressed(ImGuiKey_4)) - { - Debug.DisableAlpha = 1; - State->UpdateFrame = true; - } - if (ImGui::IsKeyPressed(ImGuiKey_5)) - { - Debug.DisableAlpha = 2; - State->UpdateFrame = true; - } - if (ImGui::IsKeyPressed(ImGuiKey_F)) - { - sprintf(State->DummyName, "test2"); - File_Open(File, State, Memory, State->DummyName); - State->UpdateFrame = true; - State->MostRecentlySelectedLayer = 0; - } - if (ImGui::IsKeyPressed(ImGuiKey_0)) - { - Debug.ReloadUI ^= 1; - } - if (ImGui::IsKeyPressed(ImGuiKey_1)) - { - Debug.ToggleWindow ^= 1; - } -#endif - - bool32 mod_key = io.ConfigMacOSXBehaviors ? io.KeySuper : io.KeyCtrl; - if (mod_key) { - if (ImGui::IsKeyPressed(ImGuiKey_S)) { - if (io.KeyShift) { - State->ImGuiPopups = popup_saveas; - } else { - if (State->Filename[0] == '\0') { - State->ImGuiPopups = popup_saveas; - } else { - File_SaveAs(File, State, Memory, State->Filename); - } - } - } - if (ImGui::IsKeyPressed(ImGuiKey_C)) { - Clipboard_Store(File, State, Memory, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyInfo, Sorted.PropertyArray); - } - if (ImGui::IsKeyPressed(ImGuiKey_V)) { - Clipboard_Paste(File, State, Memory, Sorted.CompArray, Sorted.LayerArray, Sorted.PropertyArray); - } - if (ImGui::IsKeyPressed(ImGuiKey_Z)) { - if (io.KeyShift) { - State->HotkeyInput = hotkey_redo; - } else { - State->HotkeyInput = hotkey_undo; - } - } - } -} - -static void -ImGui_Menu(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io) -{ - bool open = true; - ImGui::Begin("Menu", &open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_MenuBar); - if (ImGui::BeginMenuBar()) - { - if (ImGui::BeginMenu("File")) - { - if (ImGui::MenuItem("Save", "Ctrl+S")) - { - if (State->Filename[0] == '\0') - State->ImGuiPopups = popup_saveas; - else - File_SaveAs(File, State, Memory, State->Filename); - } - if (ImGui::MenuItem("Save as", "Ctrl+Shift+S")) - { - State->ImGuiPopups = popup_saveas; - } - if (ImGui::BeginMenu("Open file")) - { - ImGui::InputText("Filename", State->DummyName, 512); - if (ImGui::IsItemDeactivated() && ImGui::IsKeyPressed(ImGuiKey_Enter)) { - if (File_Open(File, State, Memory, State->DummyName)) { - State->UpdateFrame = true; - } else { - PostMsg(State, "File not found."); - } - } - ImGui::EndMenu(); - } - ImGui::EndMenu(); - } - if (ImGui::BeginMenu("Layer")) - { - if (ImGui::BeginMenu("Import source from file")) - { - ImGui::InputText("Path to image", State->DummyName2, 512); - if (ImGui::IsItemDeactivated() && ImGui::IsKeyPressed(ImGuiKey_Enter)) { - int SourceIndex = Source_Generate(File, State, Memory, (void *)State->DummyName2); - State->UpdateFrame = true; - } - ImGui::EndMenu(); - } - ImGui::EndMenu(); - } - if (ImGui::BeginMenu("Window")) - { -#if STABLE - if (ImGui::Selectable("Stable Diffusion tools", UI->StableEnabled)) - UI->StableEnabled ^= 1; - ImGui::EndMenu(); -#endif - } - ImGui::EndMenuBar(); - } - - ImGui::End(); -} - -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 < State->Playhead_Effect; i++) { - header_effect *EffectHeader = &State->Effect[i]; - if (State->filter.PassFilter(EffectHeader->Name)) { - if (EffectSel == p && State->MostRecentlySelectedLayer != -1) { - Effect_Add(File, State, 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) { - Effect_Add(File, State, Memory, i); - State->UpdateFrame = true; - } - } - p++; - } - } - ImGui::End(); -} - -static char ImGuiPrefs[] = "[Window][DockSpaceViewport_11111111]\n" -"Pos=0,0\n" -"Size=3840,2160\n" -"Collapsed=0\n" -"\n" -"[Window][Debug##Default]\n" -"Pos=122,442\n" -"Size=400,400\n" -"Collapsed=0\n" -"\n" -"[Window][Viewport]\n" -"Pos=443,34\n" -"Size=2872,1565\n" -"Collapsed=0\n" -"DockId=0x00000010,0\n" -"\n" -"[Window][###Properties]\n" -"Pos=0,34\n" -"Size=441,1565\n" -"Collapsed=0\n" -"DockId=0x0000000B,0\n" -"\n" -"[Window][Timeline]\n" -"Pos=0,1601\n" -"Size=3840,559\n" -"Collapsed=0\n" -"DockId=0x0000000A,0\n" -"\n" -"[Window][Dear ImGui Demo]\n" -"Pos=2677,34\n" -"Size=523,437\n" -"Collapsed=0\n" -"DockId=0x00000011,1\n" -"\n" -"[Window][Files]\n" -"Pos=3317,604\n" -"Size=523,743\n" -"Collapsed=0\n" -"DockId=0x00000007,0\n" -"\n" -"[Window][Effects list]\n" -"Pos=3317,1349\n" -"Size=523,250\n" -"Collapsed=0\n" -"DockId=0x00000008,0\n" -"\n" -"[Window][Graph editor]\n" -"Pos=0,949\n" -"Size=3200,526\n" -"Collapsed=0\n" -"DockId=0x00000009,0\n" -"\n" -"[Window][undotree]\n" -"Pos=2677,473\n" -"Size=523,572\n" -"Collapsed=0\n" -"DockId=0x00000007,2\n" -"\n" -"[Window][memoryviewer]\n" -"Pos=50,273\n" -"Size=800,200\n" -"Collapsed=0\n" -"\n" -"[Window][Example: Custom rendering]\n" -"Pos=758,789\n" -"Size=485,414\n" -"Collapsed=0\n" -"\n" -"[Window][Memory viewer]\n" -"Pos=2677,473\n" -"Size=523,572\n" -"Collapsed=0\n" -"DockId=0x00000007,1\n" -"\n" -"[Window][Graph info]\n" -"Pos=2838,1265\n" -"Size=235,353\n" -"Collapsed=0\n" -"\n" -"[Window][Properties]\n" -"Pos=0,34\n" -"Size=495,1056\n" -"Collapsed=0\n" -"DockId=0x0000000F,0\n" -"\n" -"[Window][Colors]\n" -"Pos=3317,34\n" -"Size=523,568\n" -"Collapsed=0\n" -"DockId=0x00000011,0\n" -"\n" -"[Window][Menu]\n" -"Pos=0,0\n" -"Size=3840,32\n" -"Collapsed=0\n" -"DockId=0x0000000D,0\n" -"\n" -"[Window][Stable Diffusion]\n" -"Pos=2206,684\n" -"Size=421,462\n" -"Collapsed=0\n" -"\n" -"[Window][SD prompt input]\n" -"Pos=2677,473\n" -"Size=523,541\n" -"Collapsed=0\n" -"DockId=0x00000007,2\n" -"\n" -"[Window][Example: Console]\n" -"Pos=747,851\n" -"Size=520,600\n" -"Collapsed=0\n" -"\n" -"[Window][SD gallery]\n" -"Pos=0,718\n" -"Size=441,557\n" -"Collapsed=0\n" -"DockId=0x0000000C,0\n" -"\n" -"[Window][Save as]\n" -"Pos=1782,1058\n" -"Size=300,116\n" -"Collapsed=0\n" -"\n" -"[Window][Keybinds]\n" -"Pos=1573,769\n" -"Size=750,639\n" -"Collapsed=0\n" -"\n" -"[Table][0x861D378E,3]\n" -"Column 0 Weight=1.0000\n" -"Column 1 Weight=1.0000\n" -"Column 2 Weight=1.0000\n" -"\n" -"[Table][0x1F146634,3]\n" -"RefScale=13\n" -"Column 0 Width=63\n" -"Column 1 Width=63\n" -"Column 2 Width=63\n" -"\n" -"[Table][0x64418101,3]\n" -"RefScale=13\n" -"Column 0 Width=63\n" -"Column 1 Width=63\n" -"Column 2 Width=63\n" -"\n" -"[Table][0xC9935533,3]\n" -"Column 0 Weight=1.0000\n" -"Column 1 Weight=1.0000\n" -"Column 2 Weight=1.0000\n" -"\n" -"[Docking][Data]\n" -"DockSpace ID=0x8B93E3BD Window=0xA787BDB4 Pos=0,0 Size=3840,2160 Split=Y Selected=0x13926F0B\n" -" DockNode ID=0x0000000D Parent=0x8B93E3BD SizeRef=3200,32 HiddenTabBar=1 Selected=0xA57AB2C6\n" -" DockNode ID=0x0000000E Parent=0x8B93E3BD SizeRef=3200,1299 Split=Y\n" -" DockNode ID=0x00000001 Parent=0x0000000E SizeRef=3200,1205 Split=X Selected=0x13926F0B\n" -" DockNode ID=0x00000003 Parent=0x00000001 SizeRef=441,1171 Split=Y Selected=0xDBB8CEFA\n" -" DockNode ID=0x0000000B Parent=0x00000003 SizeRef=521,425 Selected=0xDBB8CEFA\n" -" DockNode ID=0x0000000C Parent=0x00000003 SizeRef=521,347 Selected=0x56290987\n" -" DockNode ID=0x00000004 Parent=0x00000001 SizeRef=1690,1171 Split=X Selected=0x13926F0B\n" -" DockNode ID=0x00000005 Parent=0x00000004 SizeRef=1165,1171 Split=X Selected=0x13926F0B\n" -" DockNode ID=0x0000000F Parent=0x00000005 SizeRef=495,856 Selected=0x199AB496\n" -" DockNode ID=0x00000010 Parent=0x00000005 SizeRef=2199,856 CentralNode=1 Selected=0x13926F0B\n" -" DockNode ID=0x00000006 Parent=0x00000004 SizeRef=523,1171 Split=Y Selected=0x86FA2F90\n" -" DockNode ID=0x00000011 Parent=0x00000006 SizeRef=483,437 Selected=0xBF7DFDC9\n" -" DockNode ID=0x00000012 Parent=0x00000006 SizeRef=483,766 Split=Y Selected=0x59A2A092\n" -" DockNode ID=0x00000007 Parent=0x00000012 SizeRef=523,572 Selected=0x86FA2F90\n" -" DockNode ID=0x00000008 Parent=0x00000012 SizeRef=523,192 Selected=0x812F222D\n" -" DockNode ID=0x00000002 Parent=0x0000000E SizeRef=3200,559 Split=Y Selected=0x0F18B61B\n" -" DockNode ID=0x00000009 Parent=0x00000002 SizeRef=3250,526 Selected=0xA1F22F4D\n" -" DockNode ID=0x0000000A Parent=0x00000002 SizeRef=3250,323 HiddenTabBar=1 Selected=0x0F18B61B\n" -"\0"; |