summaryrefslogtreecommitdiff
path: root/my_imgui_widgets.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'my_imgui_widgets.cpp')
-rw-r--r--my_imgui_widgets.cpp3328
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";