diff options
Diffstat (limited to 'my_imgui_widgets.cpp')
-rw-r--r-- | my_imgui_widgets.cpp | 1056 |
1 files changed, 916 insertions, 140 deletions
diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp index c5a4049..e1e9ffc 100644 --- a/my_imgui_widgets.cpp +++ b/my_imgui_widgets.cpp @@ -4,6 +4,72 @@ #include "imgui_helper_widgets.cpp" static void +ImGui_InteractSliderProperty(project_state *State, memory *Memory, property_channel *Property) +{ + ImGui::DragScalar(Property->Name, ImGuiDataType_Float, &Property->CurrentValue, + Property->ScrubVal, &Property->MinVal, &Property->MaxVal, "%f"); + /* + if (ImGui::IsItemActivated()) { + State->InteractCache[0] = Property->CurrentValue.f; + } + if (ImGui::IsItemActive()) { + State->UpdateFrame = true; + } + if (ImGui::IsItemDeactivatedAfterEdit()) { + if (ImGui::IsKeyPressed(ImGuiKey_Escape)) { + Property->CurrentValue.f = State->InteractCache[0]; + } else { + History_Entry_Commit(Memory, action_entry_default, "Tranforms interact"); + History_Action_Change(Memory, &Property->CurrentValue.f, &State->InteractCache[0], + &Property->CurrentValue.f, action_type_change_r32); + History_Entry_End(Memory); + } + State->UpdateFrame = true; + } + */ +} + +static void +ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io) +{ + bool32 Display = 1; + block_layer *Layer = NULL; + if (State->MostRecentlySelectedLayer > -1) { + Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 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)) + UI->FocusedWindow = focus_properties; + ImGui::Text("Transform"); + for (int h = 0; h < AmountOf(Layer->Property); h++) { + property_channel *Property = &Layer->Property[h]; + ImGui::PushID(Property); + ImGui::Button("K"); + // if (ImGui::Button("K")) + // Keyframe_Insert(Property, Memory, File->CurrentFrame, Property->CurrentValue.f); + ImGui::SameLine(); + ImGui_InteractSliderProperty(State, Memory, Property); + ImGui::PopID(); + } + ImGui::End(); + } else { + ImGui::Begin("Properties: empty###Properties"); + if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) + UI->FocusedWindow = focus_properties; + ImGui::End(); + } +} + +#if DEBUG +static void ImGui_DebugMemoryViewer(memory *Memory, project_state *State) { ImGui::Begin("Memory viewer"); @@ -53,23 +119,103 @@ ImGui_DebugMemoryViewer(memory *Memory, project_state *State) } static void -ImGui_File(project_data *File, project_state *State, memory *Memory, ImGuiIO io) +ImGui_DebugUndoTree(memory *Memory, project_state *State) +{ + ImGui::Begin("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::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) + Source_DeselectAll(File, Memory); + else 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); } - for (int c = 0; c < File->Source_Count; c++) { - block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, c); + 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::Text(String->Char); + 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")) { + Source_UICreateButton(File, State, Memory, SortedCompArray, SortedLayerArray); + } + ImGui::EndPopup(); } #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); @@ -84,7 +230,410 @@ ImGui_File(project_data *File, project_state *State, memory *Memory, ImGuiIO io) } static void -ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, ImGuiIO io, GLuint textureID) +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.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) +{ + 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, 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) { + UI->InteractTransformMode = 1; + } + + if (UI->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) + UI->InteractTransformMode = 1; + else + UI->InteractTransformMode = 2; + } + + // Scale part + if (UI->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 (UI->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 (!UI->InteractTransformMode && ImGui::IsMouseClicked(ImGuiMouseButton_Left) && InBounds && !OtherActions) + UI->InteractTransformMode = 3; + + if (UI->InteractTransformMode == 3) { + Interact->Position.x += (real32)io.MouseDelta.x/CompScale.x; + Interact->Position.y += (real32)io.MouseDelta.y/CompScale.y; + } + + if (UI->InteractTransformMode) + { + if (io.MouseDelta.x || io.MouseDelta.y) + State->UpdateFrame = true; + if (!ImGui::IsMouseDown(ImGuiMouseButton_Left)) + UI->InteractTransformMode = 0; + } + + if (ImGui::IsKeyPressed(ImGuiKey_Escape)) { + 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; + 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) { + 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); + } + } + History_Entry_End(Memory); + State->Interact_Active = interact_type_none; + State->UpdateFrame = true; + } + + if (InBounds == true) { + ImGui::PopStyleColor(); + } + +} + +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) { bool open = true; ImGui::Begin("Viewport", &open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); @@ -119,6 +668,42 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, draw_list->AddImage((void *)(intptr_t)textureID, CompPosMin, CompPosMax); draw_list->PopClipRect(); + ImU32 wcol = ImGui::GetColorU32(ImGuiCol_Text); + // UI+interaction for layer + if (State->MostRecentlySelectedLayer > -1) + { + 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) { + block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index); + + // Anchor point UI + v2 CenterPoint = V2(Source->Width*Layer->ax.CurrentValue, Source->Height*Layer->ay.CurrentValue); + ImVec2 ScreenAP = Layer_LocalToScreenSpace(State, Layer, UI, Source->Width, Source->Height, MainComp->Width, MainComp->Height, CenterPoint); + draw_list->AddNgon(ScreenAP, 20, wcol, 8, 10.0f); + + // Bounding box UI + ImVec2 P1 = Layer_LocalToScreenSpace(State, Layer, UI, Source->Width, Source->Height, MainComp->Width, MainComp->Height, V2(0, 0)); + ImVec2 P2 = Layer_LocalToScreenSpace(State, Layer, UI, Source->Width, Source->Height, MainComp->Width, MainComp->Height, V2(Source->Width, 0)); + ImVec2 P3 = Layer_LocalToScreenSpace(State, Layer, UI, Source->Width, Source->Height, MainComp->Width, MainComp->Height, V2(0, Source->Height)); + ImVec2 P4 = Layer_LocalToScreenSpace(State, Layer, UI, Source->Width, Source->Height, MainComp->Width, MainComp->Height, V2(Source->Width, Source->Height)); + draw_list->AddLine(P1, P2, wcol, 2.0f); + draw_list->AddLine(P2, P4, wcol, 2.0f); + draw_list->AddLine(P1, P3, wcol, 2.0f); + draw_list->AddLine(P3, P4, wcol, 2.0f); + + } + } + + 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); + } + } + + + // Interactions for dragging and zooming ImGui::SetCursorScreenPos(ViewportMin); @@ -133,29 +718,83 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, // Point to zoom in on if Z is held UI->TempZoomRatio = ImGui_ScreenPointToCompUV(ViewportMin, UI->CompPos, UI->CompZoom, io.MousePos); + if (State->Tool == tool_brush && File->Layer_Count != 2) { + State->Interact_Active = interact_type_newlayer_paint; + History_Entry_Commit(Memory,"Paint new layer"); + uint16 SourceIndex = Source_Generate_Blank(File, State, Memory, MainComp->Width, MainComp->Height, MainComp->BytesPerPixel); + Assert(0); + // Layer_CreateFromSource(File, State, Memory, SourceIndex, MainComp->Frame_End); + History_Entry_End(Memory); + } + // Layer selection - /* - if (!ImGui::IsKeyDown(ImGuiKey_Z) || !State->Pen.IsActive) { - for (int i = File.NumberOfLayers - 1; i >= 0; i--) { - project_layer *Layer = File.Layer[i]; - if (!io.KeyShift) DeselectAllLayers(&File, State); - v2 LayerUV = CompUVToLayerUV(Layer, &CompBuffer, UI->TempZoomRatio); - if (TestUV(LayerUV) && !Layer->IsSelected) - { - SelectLayer(Layer, State, i); - break; - } - } + 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(Memory, File->Layer_Count); + 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) { + if (IsActive && !OtherActions) { + block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, 0); + layer_transforms T_Layer = Layer_GetTransforms(Layer); + block_source *Source = (block_source *)Memory_Block_AddressAtIndex(Memory, F_Sources, Layer->Block_Source_Index); + void *SourceBitmapAddress = Memory_Block_AddressAtIndex(Memory, F_PrincipalBitmaps, Source->Bitmap_Index); + ImVec2 MouseDelta = io.MouseDelta; + real32 Delta = MouseDelta.x + MouseDelta.y; + if (Delta != 0.0f) { + real32 DeltaDistance = sqrt(MouseDelta.x * MouseDelta.x + MouseDelta.y * MouseDelta.y); + real32 DeltaSlope = MouseDelta.y / MouseDelta.x; + for (real32 i = 0; i < DeltaDistance; i += State->Brush.Spacing) { + ImVec2 MousePos; + if (State->Brush.Type == brush_normal) { + MousePos = io.MousePos - (MouseDelta * (i / DeltaDistance)); + } else if (State->Brush.Type == brush_wacky1) { + MousePos = io.MousePos + (io.MousePos * (i / MouseDelta)); + } else if (State->Brush.Type == brush_wacky2) { + MousePos = io.MousePos - (MouseDelta / (i / DeltaDistance)); + } else if (State->Brush.Type == brush_wacky3) { + MousePos = io.MousePos - (MouseDelta * (i / ImVec2(MouseDelta.y, MouseDelta.x))); + } else { + Assert(0); + } + v2 LayerPos = Transform_ScreenSpaceToLocal(T_Layer, MainComp->Width, MainComp->Height, Source->Width, Source->Height, *UI, ViewportMin, MousePos); + PaintTest(Memory, Source, &State->Brush, SourceBitmapAddress, LayerPos, 4, UI->Color); + } + } else if (IsActivated) { + ImVec2 MousePos = io.MousePos; + v2 LayerPos = Transform_ScreenSpaceToLocal(T_Layer, MainComp->Width, MainComp->Height, Source->Width, Source->Height, *UI, ViewportMin, MousePos); + PaintTest(Memory, Source, &State->Brush, SourceBitmapAddress, LayerPos, 4, UI->Color); + } + Memory_Cache_Invalidate(State, Memory, cache_entry_type_comp, Layer->Block_Composition_Index, 0); + State->UpdateFrame = true; + } + + if (IsDeactivated) { + State->Interact_Active = interact_type_none; + } + } + if (IsActive && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1.0f) && ImGui::IsKeyDown(ImGuiKey_Z)) { real32 Distance = io.MouseDelta.x + io.MouseDelta.y; @@ -175,8 +814,12 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, State->MsgTime--; } - ImGui::End(); + 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++) { @@ -192,10 +835,11 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, } static void -ImGui_TimelineHorizontalIncrementDraw(ui *UI, ImDrawList *draw_list, ImVec2 TimelineSizeWithBorder, ImVec2 TimelineAbsolutePos, block_composition MainComp, +ImGui_TimelineHorizontalIncrementDraw(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); Assert(TimelineZoomSize.x > 0.0f); @@ -226,6 +870,10 @@ ImGui_TimelineHorizontalIncrementDraw(ui *UI, ImDrawList *draw_list, ImVec2 Time 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); } @@ -235,16 +883,17 @@ ImGui_GraphInfo(project_data *File, project_state *State, memory *Memory, ui *UI bool open = true; ImGui::Begin("Graph info", &open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); - for (int a = 0; a < File->Layer_Count; a++) + 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, a); + 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(a); + ImGui::PushID(i); for (int h = 0; h < AmountOf(Layer->Property); h++) { property_channel *Property = &Layer->Property[h]; if (Property->Block_Bezier_Count) { @@ -267,9 +916,10 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor { UI->Test.Split(draw_list, 2); - for (int a = 0; a < File->Layer_Count; a++) + 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, a); + block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, i); if (!Layer->IsSelected) continue; @@ -285,7 +935,7 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor ImVec2 Layer_ScreenPos_Max = TimelineAbsolutePos + TimelineMoveSize + ((Layer_LocalPos_Ratio + Layer_LocalSize_Ratio) * TimelineZoomSize); ImVec2 Layer_ScreenSize = Layer_ScreenPos_Max - Layer_ScreenPos_Min; - ImGui::PushID(a); + ImGui::PushID(i); ImU32 col = IM_COL32(255, 255, 255, 255); @@ -304,6 +954,8 @@ ImGui_Timeline_DrawGraph(project_data *File, project_state *State, memory *Memor State->Interact_Active == interact_type_keyframe_rotate || State->Interact_Active == interact_type_keyframe_scale)) { + Assert(0); + // Memory_Cache_Invalidate(State, Memory, cache_entry_type_comp, Lay } for (int h = 0; h < AmountOf(Layer->Property); h++) { @@ -445,9 +1097,9 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem int32 Frame_Start = Layer->Frame_Start; int32 Frame_End = Layer->Frame_End; - real32 Vertical_Offset = Layer->Vertical_Offset; - if (Layer->IsSelected) - Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End, &Vertical_Offset); + real32 Vertical_Offset = SortEntry.SortedOffset; + // if (Layer->IsSelected) + // Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End, &Vertical_Offset); ImVec2 Layer_LocalPos = ImVec2(Frame_Start, Vertical_Offset); ImVec2 Layer_LocalSize = ImVec2(Frame_End - Frame_Start, Layer->Vertical_Height); @@ -489,8 +1141,7 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem if (ImGui::IsItemActivated()) { if (!Layer->IsSelected) { if (!io.KeyShift) Layer_DeselectAll(Memory, File->Layer_Count); - State->MostRecentlySelectedLayer = i; - Layer->IsSelected = true; + Layer_Select(Memory, State, Index_Physical); } } if (ImGui::IsItemActive()) { @@ -506,15 +1157,19 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem } if (ImGui::IsItemDeactivated()) { if (State->Interact_Active == interact_type_layer_timeadjust) { - for (int a = 0; a < File->Layer_Count; a++) { - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, a); - if (Layer->IsSelected) { - Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Layer->Frame_Start, &Layer->Frame_End, &Layer->Vertical_Offset); - } + Assert(0); + /* + 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_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Layer->Frame_Start, &Layer->Frame_End, &Layer->Vertical_Offset); + // } } State->Interact_Active = interact_type_none; State->Interact_Offset[0] = 0; State->Interact_Offset[1] = 0; + */ } } @@ -527,8 +1182,7 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem if (ImGui::IsItemActivated()) { if (!Layer->IsSelected) { if (!io.KeyShift) Layer_DeselectAll(Memory, File->Layer_Count); - State->MostRecentlySelectedLayer = i; - Layer->IsSelected = true; + Layer_Select(Memory, State, Index_Physical); } } @@ -544,32 +1198,32 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem ImVec2 DragDelta = ImGui::GetMouseDragDelta(); DragDelta = DragDelta + (ImVec2(UI->Warp_X, UI->Warp_Y) * TimelineSize); - State->Interact_Offset[0] = (DragDelta.x / TimelineSizeWithBorder.x * UI->TimelinePercentZoomed.x) * Comp->Frame_Count; - State->Interact_Offset[1] = (DragDelta.y / TimelineSizeWithBorder.y * UI->TimelinePercentZoomed.y) * LayerIncrement; + 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 (UI->DragDelta_Prev.x != 0) { - ImVec2 Offset_Old = (UI->DragDelta_Prev / TimelineSizeWithBorder * UI->TimelinePercentZoomed) * ImVec2(MainComp->Frame_Count, LayerIncrement); - if ((int32)State->Interact_Offset[1] != (int32)Offset_Old.y) - State->UpdateFrame = true; - } + // if (((int32)Offset_Old.x != (int32)Offset_New.x) || ((int32)Offset_Old.y != (int32)Offset_New.y)) + State->UpdateFrame = true; - UI->DragDelta_Prev = DragDelta; - */ + 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) { - for (int a = 0; a < File->Layer_Count; a++) { - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, a); + 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); if (Layer->IsSelected) { - Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Layer->Frame_Start, &Layer->Frame_End, &Layer->Vertical_Offset); + History_Action_Swap(Memory, F_File, sizeof(Layer->Vertical_Offset), &Layer->Vertical_Offset); + Layer->Vertical_Offset = SortEntry.SortedOffset; } } State->Interact_Active = interact_type_none; - State->Interact_Offset[0] = 0; - State->Interact_Offset[1] = 0; + History_Entry_End(Memory); } } ImGui::PopID(); @@ -588,9 +1242,9 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem int32 Frame_Start = Layer->Frame_Start; int32 Frame_End = Layer->Frame_End; - real32 Vertical_Offset = Layer->Vertical_Offset; - if (Layer->IsSelected) - Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End, &Vertical_Offset); + real32 Vertical_Offset = SortEntry.SortedOffset; + // if (Layer->IsSelected) + // Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End, &Vertical_Offset); ImVec2 Layer_LocalPos = ImVec2(Frame_Start, Vertical_Offset); ImVec2 Layer_LocalSize = ImVec2(Frame_End - Frame_Start, Layer->Vertical_Height); @@ -643,9 +1297,9 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem int32 Frame_Start = Layer->Frame_Start; int32 Frame_End = Layer->Frame_End; - real32 Vertical_Offset = Layer->Vertical_Offset; - if (Layer->IsSelected) - Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End, &Vertical_Offset); + real32 Vertical_Offset = SortEntry.SortedOffset; + // if (Layer->IsSelected) + // Layer_Interact_Evaluate(Memory, State, Index_Physical, SortedCompInfo, SortedLayerInfo, &Frame_Start, &Frame_End, &Vertical_Offset); ImVec2 Layer_LocalPos = ImVec2(Frame_Start, Vertical_Offset); ImVec2 Layer_LocalSize = ImVec2(Frame_End - Frame_Start, Layer->Vertical_Height); @@ -658,10 +1312,10 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem ImU32 LayerColor = 0; ImU32 BorderColor = 0; if (UI->TimelineMode == timeline_mode_graph) { - LayerColor = ImColor(Layer->Col[0], Layer->Col[1], Layer->Col[2], 0.2f); + LayerColor = ImColor(UI->LayerColors[Layer->ColIndex]); BorderColor = ImColor(0.3, 0.3, 0.3, 1.0f); } else { - LayerColor = ImColor(Layer->Col[0], Layer->Col[1], Layer->Col[2], 1.0f); + LayerColor = ImColor(UI->LayerColors[Layer->ColIndex]); BorderColor = ImColor(0.2, 0.2, 0.2, 1.0f); } @@ -680,7 +1334,7 @@ ImGui_Timeline_DrawPrecomp(project_data *File, project_state *State, memory *Mem } static void -ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io) +ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray) { if (UI->TimelineMode == timeline_mode_graph) ImGui_GraphInfo(File, State, Memory, UI, io); @@ -745,16 +1399,10 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, ImVec2 TimelineZoomSize = TimelineSizeWithBorder / UI->TimelinePercentZoomed; ImVec2 TimelineMoveSize = TimelineSizeWithBorder * UI->TimelinePercentOffset / UI->TimelinePercentZoomed; - ImGui_TimelineHorizontalIncrementDraw(UI, draw_list, TimelineSizeWithBorder, TimelineAbsolutePos, *MainComp, TimelineZoomSize, TimelineMoveSize); + ImGui_TimelineHorizontalIncrementDraw(State, UI, draw_list, TimelineSizeWithBorder, TimelineAbsolutePos, *MainComp, TimelineZoomSize, TimelineMoveSize); ImVec2 Increment = ImVec2((real32)1 / MainComp->Frame_Count, (real32)1 / LayerIncrement); - uint64 SortSize = (sizeof(sorted_comp_info) * File->Comp_Count) + (sizeof(sorted_layer) * File->Layer_Count); - void *SortedArray = Memory_PushScratch(Memory, SortSize); - Arbitrary_Zero((uint8 *)SortedArray, SortSize); - sorted_comp_info *SortedCompArray = (sorted_comp_info *)SortedArray; - sorted_layer *SortedLayerArray = (sorted_layer *)((uint8 *)SortedArray + (sizeof(sorted_comp_info) * File->Comp_Count)); - Layer_SortAll(Memory, SortedLayerArray, SortedCompArray, File->Layer_Count, File->Comp_Count); ImGui_Timeline_DrawPrecomp(File, State, Memory, UI, io, draw_list, File->PrincipalCompIndex, Increment, TimelineAbsolutePos, TimelineMoveSize, TimelineZoomSize, @@ -772,8 +1420,6 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, // Memory_PopScratch(Memory, Keyframe_SortSize); } - Memory_PopScratch(Memory, SortSize); - ImVec2 MouseDelta = io.MouseDelta / TimelineSize; real32 BarHandleSize = FontHeight; @@ -912,6 +1558,23 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, bool32 LeftClick = ImGui::IsMouseDown(ImGuiMouseButton_Left); bool32 RightClick = ImGui::IsMouseDown(ImGuiMouseButton_Right); + ImGui::OpenPopupOnItemClick("layercolor", ImGuiPopupFlags_MouseButtonRight); + if (ImGui::BeginPopup("layercolor")) { + 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); + ImGui::Button("##test", ColSize); + if ((c+1) % 4) { ImGui::SameLine(); } + ImGui::PopStyleColor(); + ImGui::PopID(); + } + ImGui::PopStyleVar(); + ImGui::EndPopup(); + } + if (IsHovered && io.MouseWheel) { real32 Increment = 0.1; bool32 Direction = (io.MouseWheel > 0) ? 1 : -1; @@ -936,8 +1599,9 @@ ImGui_Timeline(project_data *File, project_state *State, memory *Memory, ui *UI, if (State->Interact_Active == interact_type_keyframe_move || State->Interact_Active == interact_type_keyframe_rotate || State->Interact_Active == interact_type_keyframe_scale) { - for (int a = 0; a < File->Layer_Count; a++) { - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, a); + 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; for (int h = 0; h < AmountOf(Layer->Property); h++) { @@ -998,9 +1662,31 @@ ImGui_ProcessInputs(project_data *File, project_state *State, ui *UI, memory *Me if (ImGui::IsKeyPressed(ImGuiKey_Q)) { State->IsRunning = false; } - if (ImGui::IsKeyPressed(ImGuiKey_A)) { + 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; } + if (ImGui::IsKeyPressed(ImGuiKey_E)) { + 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; + } + if (ImGui::IsKeyPressed(ImGuiKey_X)) { + v4 Temp = UI->Color; + UI->Color = UI->AltColor; + UI->AltColor = Temp; + } + + if (ImGui::IsKeyPressed(ImGuiKey_V)) { + State->Tool = tool_default; + } + if (ImGui::IsKeyPressed(ImGuiKey_B)) { + State->Tool = tool_brush; + } + if (ImGui::IsKeyPressed(ImGuiKey_T)) { + Interact_Transform_Begin(File, Memory, State, io.MousePos); + } if (UI->TimelineMode == timeline_mode_graph) { if (ImGui::IsKeyPressed(ImGuiKey_G)) { State->Interact_Offset[2] = io.MousePos.x; @@ -1031,22 +1717,174 @@ ImGui_ProcessInputs(project_data *File, project_state *State, ui *UI, memory *Me State->IsPlaying ^= 1; } if (ImGui::IsKeyPressed(ImGuiKey_T)) { - for (int a = 0; a < File->Layer_Count; a++) { - block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, a); + 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)) + { + bool32 CommitAction = 0; + int 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); + if (Layer->IsSelected) { + if (!CommitAction) { + History_Entry_Commit(Memory, "Delete source"); + CommitAction = 1; + } + Layer_Delete(File, Memory, i); + } + } + if (CommitAction) { + History_Entry_End(Memory); + State->UpdateFrame = true; + State->MostRecentlySelectedLayer = -1; + } + } + #if DEBUG - if (ImGui::IsKeyPressed(ImGuiKey_W)) + 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->Context[0].Filename[0] == '\0') { + State->ImGuiPopups = popup_saveas; + } else { + if (File_SaveAs(State, Memory, 0, State->Context[0].Filename)) { + PostMsg(State, "File saved!"); + } else { + PostMsg(State, "File save failed..."); + } + } + } + } + if (ImGui::IsKeyPressed(ImGuiKey_N)) { + if (io.KeyShift) + State->ImGuiPopups = popup_newfile; + else + State->ImGuiPopups = popup_newlayer; + } + */ + if (ImGui::IsKeyPressed(ImGuiKey_Z)) { + if (io.KeyShift) { + History_Redo(Memory); + State->UpdateFrame = true; + } else { + History_Undo(Memory); + State->UpdateFrame = true; + } + } + } + +} + +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 (File_SaveAs(State, Memory, 0, State->Context[0].Filename)) { + if (0) { + PostMsg(State, "File saved!"); + } else { + PostMsg(State, "File save failed..."); + } + } + /* + if (ImGui::MenuItem("New project file", "Ctrl+Shift+N")) + { + State->ImGuiPopups = popup_newfile; + } + if (ImGui::BeginMenu("Open file")) + { + ImGui::InputText("Filename", State->DummyName, 512); + if (ImGui::IsItemDeactivated() && ImGui::IsKeyPressed(ImGuiKey_Enter)) { + File_Open(State, Memory, State->DummyName); + State->Context[Index].UpdateFrame = true; + } + ImGui::EndMenu(); + } + if (ImGui::MenuItem("Save as", "Ctrl+Shift+S")) + { + State->ImGuiPopups = popup_saveas; + } + */ + 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(); + } + /* + if (ImGui::MenuItem("New layer", "Ctrl+N")) + { + State->ImGuiPopups = popup_newlayer; + } + if (ImGui::BeginMenu("Layer from image path")) + { + ImGui::InputText("Path to image", State->DummyName2, 512); + if (ImGui::IsItemDeactivated() && ImGui::IsKeyPressed(ImGuiKey_Enter)) { + Layer_CreateFromFile(State, Memory, Index, State->DummyName2); + Layer_DeselectAll(State, File, &Context->UI); + layer_sorted Sorts = Layer_GetSortedList(State, File); + file_layer *Layer = (file_layer *)Sorts.Location[File->NumberOfLayers - 1]; + Layer_Select(Layer, &Context->UI, File->NumberOfLayers - 1); + State->Context[Index].UpdateFrame = true; + } + ImGui::EndMenu(); + } + if (ImGui::MenuItem("New adjustment layer", "Ctrl+Shift+Y")) + { + Layer_CreateAdjustment(State, Memory, Index); + } + if (ImGui::MenuItem("Duplicate layer", "Ctrl+Shift+Y")) + { + if (State->Context[Index].UI.MostRecentlySelectedLayer > -1) + Layer_Duplicate(State, Memory, Index, State->Context[Index].UI.MostRecentlySelectedLayer); + } + */ + ImGui::EndMenu(); + } + ImGui::EndMenuBar(); + } + + ImGui::End(); +} + +static void +ImGui_Popups(project_state *State, ui *UI, memory *Memory, ImGuiIO io) +{ } + #if 0 real32 MaxVal_Y = -10000; real32 MinVal_Y = 10000; @@ -1931,7 +2769,7 @@ ImGui_PropertiesPanel(project_data *File, project_state *State, ui *UI, memory * static void ImGui_Viewport(project_data File, project_state *State, ui *UI, memory *Memory, comp_buffer CompBuffer, - ImGuiIO io, GLuint textureID) + ImGuiIO io, GLuint textureID, sorted_comp_info *SortedCompArray, sorted_layer *SortedLayerArray) { bool open = true; ImGui::Begin("Viewport", &open, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); @@ -2358,68 +3196,6 @@ ImGui_SlidingLayer(project_layer *Layer, real32 *DraggingThreshold, real32 Delta } static void -ImGui_File(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io) -{ - ImGui::Begin("Files"); - ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); -#if DEBUG - if (State->DemoButton) { - if (ImGui::Button("Generate demo scene")) { - CreateDemoScene(File, State, Memory); - State->UpdateKeyframes = true; - State->UpdateFrame = true; - State->DemoButton = false; - } - } - if (State->GridButton) { - ImGui::SameLine(); - if (ImGui::Button("Generate square grid")) { - // CreateGrid(File, Memory); - State->UpdateKeyframes = true; - State->UpdateFrame = true; - State->GridButton = false; - } - } -#endif - ImGui::Text("Sources:"); - for (int i = 0; i < File->NumberOfSources; i++) { - bool32 Test = false; - if (File->SourceSelected == i) - Test = true; - ImGui::Selectable(File->Source[i].Path, Test); - if (ImGui::IsItemClicked()) - File->SourceSelected = i; - if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) - File->SourceSelected = i; - ImGui::OpenPopupOnItemClick("sourcecontext", ImGuiPopupFlags_MouseButtonRight); - } - if (ImGui::BeginPopup("sourcecontext")) { - if (ImGui::MenuItem("Create layer from source")) { - Layer_CreateFromSource(File, State, Memory, &File->Source[File->SourceSelected]); - } - ImGui::EndPopup(); - } - static char Input[1024]; - ImGui::InputTextWithHint("##sourceinput", "Input file path of source...", Input, STRING_SIZE); - if (ImGui::IsItemDeactivated() && ImGui::IsKeyPressed(ImGuiKey_Enter)) { - Source_Generate(File, State, Memory, Input); - } -#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); - } - } - Debug.Temp = {}; -#endif - ImGui::End(); -} - -static void ImGui_EffectsPanel(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO io) { ImGui::Begin("Effects list", NULL); |