From f1e12e108869c560d92eb8803e4b5104c7d8f85d Mon Sep 17 00:00:00 2001 From: Fox Caminiti Date: Mon, 8 Aug 2022 17:12:52 -0400 Subject: mask improvements; pen tool added --- my_imgui_widgets.cpp | 228 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 147 insertions(+), 81 deletions(-) (limited to 'my_imgui_widgets.cpp') diff --git a/my_imgui_widgets.cpp b/my_imgui_widgets.cpp index cb981c2..6f785de 100644 --- a/my_imgui_widgets.cpp +++ b/my_imgui_widgets.cpp @@ -70,6 +70,17 @@ ImGui_KeyframeDragging(project_data *File, project_state *State, ui *UI, propert } } +// Returns a normalized UV position of the composition +static ImVec2 +ImGui_ScreenPointToCompUV(ImVec2 ViewportMin, ImVec2 CompPos, ImVec2 CompZoom, ImVec2 MousePos) +{ + ImVec2 LocalMousePos = MousePos - ViewportMin; + ImVec2 LocalCompPos = CompPos - ViewportMin; + ImVec2 MouseScreenUV = LocalMousePos - LocalCompPos; + ImVec2 Result = MouseScreenUV / CompZoom; + return Result; +} + static void ImGui_DebugMemoryViewer(project_data *File, memory *Memory) { @@ -331,6 +342,7 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, comp_buffer Comp UI->FocusedWindow = focus_viewport; // Primarily taken from the Custom Rendering section of the demo + ImVec2 ViewportMin = ImGui::GetCursorScreenPos(); ImVec2 ViewportScale = ImGui::GetContentRegionAvail(); ViewportScale.y -= ImGui::GetFontSize(); @@ -357,18 +369,20 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, comp_buffer Comp // UI+interaction for layer if (State->MostRecentlySelectedLayer > -1) { project_layer *Layer = File.Layer[State->MostRecentlySelectedLayer]; + source *Source = Layer->Source; - // Anchor point + // Anchor point UI ImVec2 AUV = ImVec2(Layer->x.CurrentValue.f / CompBuffer.Width, Layer->y.CurrentValue.f / CompBuffer.Height); ImVec2 ScreenAP = ImVec2(UI->CompPos.x + AUV.x * UI->CompZoom.x, UI->CompPos.y + AUV.y * UI->CompZoom.y); draw_list->AddNgon(ScreenAP, 20, ImGui::GetColorU32(ImGuiCol_ScrollbarGrab), 8, 10.0f); - // Mask points + // Mask UI if (Layer->NumberOfMasks) { for (int i = 0; i < Layer->NumberOfMasks; i++) { mask *Mask = &Layer->Mask[i]; ImGui::PushID(i); - source *Source = Layer->Source; + + real32 PointSize = 40; for (int p = 0; p < Mask->NumberOfPoints; p++) { @@ -397,6 +411,8 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, comp_buffer Comp ImU32 col = ImGui::GetColorU32(ImGuiCol_ScrollbarGrab); + // The handle itself + draw_list->AddNgon(Point0_ScreenPos, 10, col, 8, 5.0f); draw_list->AddNgon(Point0_ScreenPos_Left, 10, col, 8, 5.0f); draw_list->AddNgon(Point0_ScreenPos_Right, 10, col, 8, 5.0f); @@ -406,51 +422,6 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, comp_buffer Comp ImU32 col2 = ImGui::GetColorU32(ImGuiCol_Button); - - real32 PointSize = 40; - - - // Ratio of the point along the curve. See internal for more info. - float ratio; - - if (ImGui::BezierInteractive(Point0_ScreenPos, Point0_ScreenPos_Right, - Point1_ScreenPos_Left, Point1_ScreenPos, ratio)) - { - // Using a button like this may be kinda janky, but it gives us access - // to all of ButtonBehavior and the ID system without having to rewrite it. - ImGui::SetCursorScreenPos(io.MousePos - ImVec2(5,5)); - ImGui::Button("maskbezier", ImVec2(10, 10)); - - if(ImGui::IsItemHovered()) { - ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); - draw_list->AddNgon(io.MousePos, 2, col, 8, 5.0f); - ImVec2 RatioLeft = ImGui::RatioToPoint(Point0_ScreenPos, Point0_ScreenPos_Right, ratio); - ImVec2 RatioTop = ImGui::RatioToPoint(Point0_ScreenPos_Right, Point1_ScreenPos_Left, ratio); - ImVec2 RatioRight = ImGui::RatioToPoint(Point1_ScreenPos_Left, Point1_ScreenPos, ratio); - ImVec2 TangentLeft = ImGui::RatioToPoint(RatioLeft, RatioTop, ratio); - ImVec2 TangentRight = ImGui::RatioToPoint(RatioTop, RatioRight, ratio); - draw_list->AddLine(RatioLeft, RatioTop, col, 2.0f); - draw_list->AddLine(RatioRight, RatioTop, col, 2.0f); - draw_list->AddLine(TangentLeft, TangentRight, col, 2.0f); - } - if(ImGui::IsItemActivated() && io.KeyCtrl) { - ImVec2 Ratio0 = ImGui::RatioToPoint(Point0_Pos, Point0_Pos_Right, ratio); - ImVec2 RatioTop = ImGui::RatioToPoint(Point0_Pos_Right, Point1_Pos_Left, ratio); - ImVec2 Ratio1 = ImGui::RatioToPoint(Point1_Pos_Left, Point1_Pos, ratio); - ImVec2 TangentLeft = ImGui::RatioToPoint(Ratio0, RatioTop, ratio); - ImVec2 TangentRight = ImGui::RatioToPoint(RatioTop, Ratio1, ratio); - ImVec2 Point = ImGui::RatioToPoint(TangentLeft, TangentRight, ratio); - Mask_AddPoint(Mask, Point, Point - TangentLeft, Point - TangentRight, - Point0_Pos - Ratio0, Point1_Pos - Ratio1, p); - } - } - - DebugWatchVar("ratio", &ratio, d_float); - - // if (ImGui::TestLine(PointScreenPos[0], PointScreenPos[1])) { - // } - - // loops over point and handles for (int b = 0; b < 3; b++) { ImGui::PushID(b); @@ -496,6 +467,56 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, comp_buffer Comp } + // The bezier path + + if (Mask->NumberOfPoints == 1) { + ImGui::PopID(); + continue; + } + + // Ratio of the point along the curve. See internal for more info. + float ratio; + + if (ImGui::BezierInteractive(Point0_ScreenPos, Point0_ScreenPos_Right, + Point1_ScreenPos_Left, Point1_ScreenPos, ratio) && + State->Tool == tool_pen) + { + // Using a button like this may be kinda janky, but it gives us access + // to all of ButtonBehavior and the ID system without having to rewrite it. + ImGui::SetCursorScreenPos(io.MousePos - ImVec2(5,5)); + ImGui::Button("maskbezier", ImVec2(10, 10)); + + if(ImGui::IsItemHovered()) { + // ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); + draw_list->AddNgon(io.MousePos, 2, col, 8, 5.0f); + ImVec2 RatioLeft = ImGui::RatioToPoint(Point0_ScreenPos, Point0_ScreenPos_Right, ratio); + ImVec2 RatioTop = ImGui::RatioToPoint(Point0_ScreenPos_Right, Point1_ScreenPos_Left, ratio); + ImVec2 RatioRight = ImGui::RatioToPoint(Point1_ScreenPos_Left, Point1_ScreenPos, ratio); + ImVec2 TangentLeft = ImGui::RatioToPoint(RatioLeft, RatioTop, ratio); + ImVec2 TangentRight = ImGui::RatioToPoint(RatioTop, RatioRight, ratio); + draw_list->AddLine(RatioLeft, RatioTop, col, 2.0f); + draw_list->AddLine(RatioRight, RatioTop, col, 2.0f); + draw_list->AddLine(TangentLeft, TangentRight, col, 2.0f); + } + if(ImGui::IsItemActivated() && io.KeyCtrl) { + ImVec2 Ratio0 = ImGui::RatioToPoint(Point0_Pos, Point0_Pos_Right, ratio); + ImVec2 RatioTop = ImGui::RatioToPoint(Point0_Pos_Right, Point1_Pos_Left, ratio); + ImVec2 Ratio1 = ImGui::RatioToPoint(Point1_Pos_Left, Point1_Pos, ratio); + ImVec2 TangentLeft = ImGui::RatioToPoint(Ratio0, RatioTop, ratio); + ImVec2 TangentRight = ImGui::RatioToPoint(RatioTop, Ratio1, ratio); + ImVec2 Point = ImGui::RatioToPoint(TangentLeft, TangentRight, ratio); + Mask_AddPointToCurve(Mask, Point, Point - TangentLeft, Point - TangentRight, + Point0_Pos - Ratio0, Point1_Pos - Ratio1, p); + } + } + + // DebugWatchVar("ratio", &ratio, d_float); + + // if (ImGui::TestLine(PointScreenPos[0], PointScreenPos[1])) { + // } + + + ImGui::PopID(); } ImGui::PopID(); @@ -506,25 +527,73 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, comp_buffer Comp // Interactions for dragging and zooming ImGui::SetCursorScreenPos(ViewportMin); + real32 ButtonSize = 20; + + for (int t = 0; t < tool_count; t++) { + ImGui::PushID(t); + bool32 Selected = (State->Tool == t); + if (ImGui::Selectable("##tool", Selected, 0, ImVec2(ButtonSize, ButtonSize))) { + State->Tool = (tool)t; + } + ImGui::PopID(); + } + ImGui::InvisibleButton("canvas", ViewportScale, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight); bool32 IsHovered = ImGui::IsItemHovered(); bool32 IsActive = ImGui::IsItemActive(); bool32 IsActivated = ImGui::IsItemActivated(); + if (State->MostRecentlySelectedLayer > -1) + { + project_layer *Layer = File.Layer[State->MostRecentlySelectedLayer]; + if (IsActivated && ImGui::IsMouseDown(ImGuiMouseButton_Left)) { + if (State->Tool == tool_pen && !State->Pen.IsActive) { + State->Pen.IsActive = true; + Layer->NumberOfMasks++; + } + } + + if (State->Pen.IsActive && !ImGui::IsKeyDown(ImGuiKey_Z)) { + if (IsActivated) { + v2 CompUV = V2(ImGui_ScreenPointToCompUV(ViewportMin, UI->CompPos, UI->CompZoom, io.MousePos)); + v2 LayerUV = CompUVToLayerUV(Layer, &CompBuffer, CompUV); + v2 LayerPos = LayerUV * V2(Layer->Source->Info.Width, Layer->Source->Info.Height); + Mask_PushPoint(&Layer->Mask[Layer->NumberOfMasks-1], LayerPos); + } + if (IsActive) { + mask *Mask = &Layer->Mask[Layer->NumberOfMasks-1]; + mask_point *CurrentPoint = &Mask->Point[Mask->NumberOfPoints-1]; + v2 CompUV = V2(ImGui_ScreenPointToCompUV(ViewportMin, UI->CompPos, UI->CompZoom, io.MousePos)); + v2 LayerUV = CompUVToLayerUV(Layer, &CompBuffer, CompUV); + v2 LayerPos = LayerUV * V2(Layer->Source->Info.Width, Layer->Source->Info.Height); + v2 OffsetPos = CurrentPoint->Pos - LayerPos; + CurrentPoint->TangentRight = -OffsetPos; + CurrentPoint->TangentLeft = OffsetPos; + } + if (State->Tool != tool_pen) { + State->Pen.IsActive = false; + } + } + } + + if (IsHovered && IsActivated && ImGui::IsMouseDown(ImGuiMouseButton_Left)) + { + // Point to zoom in on if Z is held + UI->TempZoomRatio = V2(ImGui_ScreenPointToCompUV(ViewportMin, UI->CompPos, UI->CompZoom, io.MousePos)); + DebugWatchVar("MouseScreenUV", &UI->TempZoomRatio.x, d_float); + DebugWatchVar("MouseScreenUV", &UI->TempZoomRatio.y, d_float); - if (IsHovered && IsActivated && ImGui::IsMouseDown(ImGuiMouseButton_Left)) { - v2 LocalMousePos = (V2(io.MousePos) - V2(ViewportMin)); - v2 LocalCompPos = V2(UI->CompPos) - V2(ViewportMin); - v2 MouseScreenUV = LocalMousePos - LocalCompPos; - UI->TempZoomRatio = MouseScreenUV / V2(UI->CompZoom); // AKA actual normalized UV of comp - if (!ImGui::IsKeyDown(ImGuiKey_Z)) { + // Layer selection + if (!ImGui::IsKeyDown(ImGuiKey_Z) || !State->Pen.IsActive) { for (int i = File.NumberOfLayers - 1; i >= 0; i--) { - if (!io.KeyShift) DeselectAllLayers(&File, State); - if (TestPointInLayer(File.Layer[i], &CompBuffer, UI->TempZoomRatio) && !File.Layer[i]->IsSelected) - { - SelectLayer(File.Layer[i], State, i); - break; - } + 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; + } } } } @@ -535,14 +604,6 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, comp_buffer Comp UI->CompPos.y += io.MouseDelta.y; } - ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonMiddle); - if (ImGui::BeginPopup("context")) { - if (ImGui::MenuItem("Scalar", NULL, false, InstructionMode != instruction_mode_scalar)) { InstructionMode = instruction_mode_scalar; State->UpdateFrame = true; } - if (ImGui::MenuItem("SSE", NULL, false, InstructionMode != instruction_mode_sse)) { InstructionMode = instruction_mode_sse; State->UpdateFrame = true; } - if (ImGui::MenuItem("AVX2", NULL, false, InstructionMode != instruction_mode_avx)) { InstructionMode = instruction_mode_avx; State->UpdateFrame = true; } - ImGui::EndPopup(); - } - if (IsActive && ImGui::IsMouseDragging(ImGuiMouseButton_Left, -1.0f) && ImGui::IsKeyDown(ImGuiKey_Z)) { real32 Distance = io.MouseDelta.x + io.MouseDelta.y; @@ -560,6 +621,16 @@ ImGui_Viewport(project_data File, project_state *State, ui *UI, comp_buffer Comp State->MsgTime--; } + + ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonMiddle); + if (ImGui::BeginPopup("context")) { + if (ImGui::MenuItem("Scalar", NULL, false, InstructionMode != instruction_mode_scalar)) { InstructionMode = instruction_mode_scalar; State->UpdateFrame = true; } + if (ImGui::MenuItem("SSE", NULL, false, InstructionMode != instruction_mode_sse)) { InstructionMode = instruction_mode_sse; State->UpdateFrame = true; } + if (ImGui::MenuItem("AVX2", NULL, false, InstructionMode != instruction_mode_avx)) { InstructionMode = instruction_mode_avx; State->UpdateFrame = true; } + ImGui::EndPopup(); + } + + ImGui::End(); } @@ -644,16 +715,16 @@ ImGui_File(project_data *File, project_state *State, memory *Memory, ui *UI, ImG // // AddSource(File, State, Memory, Input); // } #if DEBUG - for (int i = 0; i < Debug.WatchedProperties; i++) { - if (Debug.DebugPropertyType[i] == d_float) { - ImGui::Text("%s: %f", Debug.String[i], Debug.Val[i].f); - } else if (Debug.DebugPropertyType[i] == d_int) { - ImGui::Text("%s: %i", Debug.String[i], Debug.Val[i].i); - } else if (Debug.DebugPropertyType[i] == d_uint) { - ImGui::Text("%s: %u", Debug.String[i], Debug.Val[i].u); + 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 = {}; + Debug.Temp = {}; #endif ImGui::End(); } @@ -1451,11 +1522,6 @@ ImGui_ProcessInputs(project_data *File, project_state *State, comp_buffer *CompB { SwitchBool(Debug.ToggleWindow); } - if (ImGui::IsKeyPressed(ImGuiKey_M)) - { - Debug.Markers[Debug.MarkerIndex] = File->CurrentFrame; - Debug.MarkerIndex++; - } #endif bool32 Ended = ImGui::IsMouseDown(ImGuiMouseButton_Left); -- cgit v1.2.3