From d6e916319a050070c53eb283470a3fd4833392a0 Mon Sep 17 00:00:00 2001 From: Fox Caminiti Date: Fri, 27 Jan 2023 18:36:05 -0500 Subject: corner scaling --- src/imgui_ui.cpp | 2 - src/imgui_ui_viewport.cpp | 447 ++++++++++++++++------------------------------ src/include/all.h | 2 + src/include/my_math.h | 6 + src/layer.cpp | 55 +++--- src/main.cpp | 2 - src/prenderer.cpp | 9 +- 7 files changed, 191 insertions(+), 332 deletions(-) (limited to 'src') diff --git a/src/imgui_ui.cpp b/src/imgui_ui.cpp index 727514b..7c8adf9 100644 --- a/src/imgui_ui.cpp +++ b/src/imgui_ui.cpp @@ -11,8 +11,6 @@ ImGui_File(project_data *File, project_state *State, memory *Memory, ImGuiIO io, ImGui::Text("%s: %hu", "Layers", File->Layer_Count); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); - ImGui::SliderFloat("aaa", &aaa, -10, 10); - if (ImGui::IsKeyPressed(ImGuiKey_Backspace)) { // TODO(fox): Delete sources code! diff --git a/src/imgui_ui_viewport.cpp b/src/imgui_ui_viewport.cpp index 601b0f4..c846c7e 100644 --- a/src/imgui_ui_viewport.cpp +++ b/src/imgui_ui_viewport.cpp @@ -222,172 +222,6 @@ ImGui_Viewport_BrushUI(project_state *State, memory *Memory, ImVec2 ViewportMin, } } -#if 0 -static void -ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO &io, ImDrawList *draw_list, - v2 Min, v2 Max, ImVec2 ViewportMin, uint32 CompWidth, uint32 CompHeight, uint16 *SortedKeyframeArray) -{ - interact_transform *Interact = (interact_transform *)&State->Interact_Offset[0]; - - v2 InteractMin = Min; - v2 InteractMax = Max; - real32 Rad = 0; - real32 Scale = 1; - - - if (State->Interact_Active == interact_type_viewport_transform_gizmo) { - InteractMin = Interact->Min + Interact->Position; - InteractMax = Interact->Max + Interact->Position; - Rad = Interact->Radians; - Scale = Interact->Scale; - } - - v2 BoxLength = InteractMax - InteractMin; - v2 Center = InteractMax - (BoxLength/2); - - real32 Point0X = Center.x - InteractMin.x; - real32 Point0Y = Center.y - InteractMin.y; - - v2 XAxis = (Point0X * Scale)*V2(cos(Rad), sin(Rad)); - v2 YAxis = (Point0Y * -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; - - if (State->Interact_Active == interact_type_viewport_transform_gizmo) { - 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)(Rad / (PI / 180)), 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; - - bool32 OtherActions = ImGui::IsKeyDown(ImGuiKey_Z); - real32 FontSize = ImGui::GetFontSize() * 3; - real32 Delta = io.MouseDelta.x + io.MouseDelta.y; - - ImVec2 Screen_Center = IV2(Center)*CompScale + UI->CompPos; - - char *Buttons[] = { "##position", "##rotation", "##scale" }; - for (int i = 0; i < 3; i++) { - ImGui::SetCursorScreenPos(Screen_Center + ImVec2(i*FontSize, i*FontSize)); - ImGui::Button(Buttons[i], ImVec2(FontSize, FontSize)); - bool32 IsActivated = ImGui::IsItemActivated(); - bool32 IsActive = ImGui::IsItemActive(); - bool32 IsDeactivated = ImGui::IsItemDeactivated(); - if (IsActivated) { - State->Interact_Active = interact_type_viewport_transform_gizmo; - *Interact = {}; - Interact->Min = Min; - Interact->Max = Max; - } - if (IsActive && Delta != 0.0f) { - v2 Increase = V2(io.MousePos - io.MouseClickedPos[0]); - if (i == 0) { - Interact->Position = Increase; - } else if (i == 1) { - 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); - v2 SlopeDot = V2(BoxLength.x, BoxLength.y); - - real32 Slope_Mouse = LocalY/LocalX; - - real32 Slope_Corner = BoxLength.y / BoxLength.x; - real32 Slope_Flipped = -BoxLength.x / BoxLength.y; - real32 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; - } - } - } else if (i == 2) { - real32 StartX = (io.MouseClickedPos[0].x - UI->CompPos.x)/CompScale.x - InteractMin.x - (BoxLength.x/2); - real32 StartY = (io.MouseClickedPos[0].y - UI->CompPos.y)/CompScale.y - InteractMin.y - (BoxLength.y/2); - 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 Normalized = LocalX / StartX; - if (Normalized < 0.0f) - Normalized = 0.0f; - Interact->Scale = Normalized; - // printf("Local X: %.2f\n", Normalized); - } else { - Assert(0); - } - } - if (IsDeactivated) { - Assert(State->Interact_Active == interact_type_viewport_transform_gizmo); - 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 == 1) { - History_Action_Swap(Memory, F_Layers, sizeof(Layer->x.CurrentValue), &Layer->x.CurrentValue); - History_Action_Swap(Memory, F_Layers, sizeof(Layer->y.CurrentValue), &Layer->y.CurrentValue); - History_Action_Swap(Memory, F_Layers, sizeof(Layer->scale.CurrentValue), &Layer->scale.CurrentValue); - History_Action_Swap(Memory, F_Layers, 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; - *Interact = {}; - State->UpdateFrame = true; - } - } -} -#endif - static real32 T_AreaAtAngle(int PointCount, v2 *PointData, v2 Center, real32 Rotation, v2 *CurrentMin, v2 *CurrentMax) { @@ -448,7 +282,8 @@ T_FindBestFit(int PointCount, v2 *PointData, v2 *Center, v2 *NewCenter, v2 *Best static void ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Memory, ui *UI, ImGuiIO &io, ImDrawList *draw_list, - int *PointCount, v2 *PointData, ImVec2 ViewportMin, uint32 CompWidth, uint32 CompHeight, uint16 *SortedKeyframeArray) + int *PointCount, v2 *PointData, ImVec2 ViewportMin, uint32 CompWidth, uint32 CompHeight, + sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, uint16 *SortedKeyframeArray) { interact_transform *Interact = &State->Interact_Transform; @@ -458,7 +293,6 @@ ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Me real32 Rad2 = 0; real32 Scale = 1; - aaa += 0.02; if (Interact->Min.x == 0.0f) { T_FindBestFit(*PointCount, PointData, &Interact->OGCenter, &Interact->NewCenter, &Interact->Min, &Interact->Max, &Interact->RadianOffset); // Interact->RadianOffset += @@ -466,52 +300,62 @@ ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Me } if (Interact->Min.x != 0.0f) { - InteractMin = Interact->Min + Interact->Position; - InteractMax = Interact->Max + Interact->Position; + InteractMin = Interact->Min; + InteractMax = Interact->Max; Rad = Interact->RadianOffset; Rad2 = Interact->Radians; Scale = Interact->Scale; } real32 Angle = Interact->RadianOffset / (PI / 180); - DebugWatchVar("Rad", &Interact->Radians, d_float); - DebugWatchVar("bestangle", &Angle, d_float); + // DebugWatchVar("Rad", &Interact->Radians, d_float); + // DebugWatchVar("bestangle", &Angle, d_float); v2 BoxLength = InteractMax - InteractMin; v2 Center = Interact->OGCenter; - v2 PosL[4] = {}; - v2 PosS[4] = { InteractMin, V2(InteractMax.x, InteractMin.y), InteractMax, V2(InteractMin.x, InteractMax.y) }; + v2 PosL[8] = {}; + v2 PosS[8] = { InteractMin, V2(InteractMax.x, InteractMin.y), + InteractMax, V2(InteractMin.x, InteractMax.y), + InteractMin + V2(BoxLength.x * 0.5, 0), InteractMin + V2(0, BoxLength.y * 0.5), + InteractMax - V2(BoxLength.x * 0.5, 0), InteractMax - V2(0, BoxLength.y * 0.5) }; v2 LocalCenter = InteractMax - (BoxLength/2); + + // NOTE(fox): There's two transformations we need to do: the best-fit + // bounding box transformed from the center of the 0 degree bounding box, + // and then the Interactive rotation based on the center of the best-fit + // bounding box _at its new position_. v2 NewCenter = {}; { real32 Point0X = LocalCenter.x - Center.x; real32 Point0Y = LocalCenter.y - Center.y; - v2 XAxis = (Point0X * Scale)*V2(cos(Rad), sin(Rad)); - v2 YAxis = (Point0Y * Scale)*V2(sin(Rad), -cos(Rad)); + v2 XAxis = (Point0X * 1.0f)*V2(cos(Rad), sin(Rad)); + v2 YAxis = (Point0Y * 1.0f)*V2(sin(Rad), -cos(Rad)); v2 Pos = XAxis + YAxis; NewCenter.x = Center.x + Pos.x; NewCenter.y = Center.y + Pos.y; } - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 8; i++) { real32 Point0X = PosS[i].x - Center.x; real32 Point0Y = PosS[i].y - Center.y; - v2 XAxis = (Point0X * Scale)*V2(cos(Rad), sin(Rad)); - v2 YAxis = (Point0Y * Scale)*V2(sin(Rad), -cos(Rad)); + v2 XAxis = (Point0X * 1.0f)*V2(cos(Rad), sin(Rad)); + v2 YAxis = (Point0Y * 1.0f)*V2(sin(Rad), -cos(Rad)); v2 Pos = XAxis + YAxis; PosL[i].x = Center.x + Pos.x; PosL[i].y = Center.y + Pos.y; { Point0X = PosL[i].x - NewCenter.x; Point0Y = PosL[i].y - NewCenter.y; - XAxis = (Point0X * Scale)*V2(cos(Rad2), sin(Rad2)); + XAxis = (Point0X * Scale)*V2(cos(Rad2), sin(Rad2)); YAxis = (Point0Y * -Scale)*V2(sin(Rad2), -cos(Rad2)); v2 NewPos = XAxis + YAxis; PosL[i].x = NewCenter.x + NewPos.x; PosL[i].y = NewCenter.y + NewPos.y; + PosL[i].x += Interact->Position.x; + PosL[i].y += Interact->Position.y; } } @@ -523,6 +367,13 @@ ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Me P[2] = IV2(PosL[2])*CompScale + UI->CompPos; P[3] = IV2(PosL[3])*CompScale + UI->CompPos; + ImVec2 Mid_P[4]; + + Mid_P[0] = IV2(PosL[4])*CompScale + UI->CompPos; + Mid_P[1] = IV2(PosL[5])*CompScale + UI->CompPos; + Mid_P[2] = IV2(PosL[6])*CompScale + UI->CompPos; + Mid_P[3] = IV2(PosL[7])*CompScale + UI->CompPos; + ImU32 wcol = IM_COL32(0, 0, 255, 255); draw_list->AddLine(P[0], P[1], wcol, 2.0f); draw_list->AddLine(P[1], P[2], wcol, 2.0f); @@ -532,76 +383,24 @@ ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Me draw_list->AddLine(P[0], P[2], wcol, 1.0f); draw_list->AddLine(P[1], P[3], wcol, 1.0f); -#if 0 - { - ImU32 wcol = IM_COL32(0, 0, 255, 255); - v2 Min = V2(10000, 10000), Max = V2(-10000, -10000); - for (int i = 0; i < *PointCount; i++) { - v2 Pos = PointData[i]; - if (Pos.x < Min.x) { Min.x = Pos.x; } - if (Pos.y < Min.y) { Min.y = Pos.y; } - if (Pos.x > Max.x) { Max.x = Pos.x; } - if (Pos.y > Max.y) { Max.y = Pos.y; } - } - v2 Dimensions = Max - Min; - v2 Center = Min + Dimensions/2; - ImVec2 P[4] = { IV2(Min), ImVec2(Max.x, Min.y), IV2(Max), ImVec2(Min.x, Max.y) }; - P[0] = P[0]*CompScale + UI->CompPos; - P[1] = P[1]*CompScale + UI->CompPos; - P[2] = P[2]*CompScale + UI->CompPos; - P[3] = P[3]*CompScale + UI->CompPos; - ImVec2 C = IV2(Center)*CompScale + UI->CompPos; - draw_list->AddNgon(C, 10, wcol, 8, 9.0f); - /* - for (int i = 0; i < *PointCount; i++) { - v2 Pos = PointData[i]; - v2 XAxis = (Pos.x - Center.x) * V2(cos(Rad), sin(Rad)); - v2 YAxis = (Pos.y - Center.y) * V2(sin(Rad), -cos(Rad)); - Pos = XAxis + YAxis; - ImVec2 PosS = IV2(Pos)*CompScale + UI->CompPos; - draw_list->AddNgon(PosS, 10, wcol, 8, 9.0f); - }*/ - 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); - } - { - ImU32 wcol = IM_COL32(255, 0, 255, 255); - v2 Min = Interact->Min, Max = Interact->Max; - ImVec2 P[4] = { IV2(Min), ImVec2(Max.x, Min.y), IV2(Max), ImVec2(Min.x, Max.y) }; - P[0] = P[0]*CompScale + UI->CompPos; - P[1] = P[1]*CompScale + UI->CompPos; - P[2] = P[2]*CompScale + UI->CompPos; - P[3] = P[3]*CompScale + UI->CompPos; - ImVec2 C = IV2(Center)*CompScale + UI->CompPos; - draw_list->AddNgon(C, 10, wcol, 8, 9.0f); - 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); - } -#endif - - v2 XAxis2 = (BoxLength*CompScale.x)*V2(cos(Rad), sin(Rad)); - v2 YAxis2 = (BoxLength*CompScale.y)*V2(sin(Rad), -cos(Rad)); + layer_transforms BoxTransforms = { NewCenter.x, NewCenter.y, 0.5, 0.5, (real32)(Rad / (PI / 180)), Scale }; + v2 LayerPoint = Transform_ScreenSpaceToLocal(BoxTransforms, CompWidth, CompHeight, BoxLength.x, BoxLength.y, UI->CompPos, UI->CompZoom, ViewportMin, io.MousePos); - // 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)(Rad / (PI / 180)), Scale }; - v2 LayerPoint = Transform_ScreenSpaceToLocal(BoxTransforms, CompWidth, CompHeight, BoxLength.x, BoxLength.y, UI->CompPos, UI->CompZoom, ViewportMin, io.MousePos); + // for (int i = 0; i < 4; i++) { + // v2 Anchor = TransformPoint(BoxTransforms, BoxLength.x, BoxLength.y, BoxLength * Mid_Local[i]); + // Mid_P[i] = IV2(Anchor)*CompScale + UI->CompPos; + // } real32 U = LayerPoint.x / BoxLength.x; real32 V = LayerPoint.y / BoxLength.y; + DebugWatchVar("U", &U, d_float); + DebugWatchVar("V", &V, d_float); 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); @@ -612,29 +411,49 @@ ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Me ImGui::PopStyleColor(); if (ImGui::IsItemActivated() && !OtherActions) { + State->Interact_Active = interact_type_viewport_transform_gizmo; 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; + v2 Dir = {}; + if (i == 0) { + Dir = V2(-1, 1); + } else if (i == 1) { + Dir = V2(1, 1); + } else if (i == 2) { + Dir = V2(1, -1); + } else if (i == 3) { + Dir = V2(-1, -1); + } else { + Assert(0); } + + ImVec2 LengthVec = (io.MousePos - io.MouseClickedPos[0]) / CompScale; + real32 NegRad = -Rad; + v2 UnrotatedLengthVec = {}; + { + v2 XAxis = (LengthVec.x * 1.0f)*V2(cos(NegRad), sin(NegRad)); + v2 YAxis = (LengthVec.y * -1.0f)*V2(sin(NegRad), -cos(NegRad)); + v2 UnrotatedLengthVec = XAxis + YAxis; + } + + real32 Length = UnrotatedLengthVec.x * Dir.x; + DebugWatchVar("Len", &Length, d_float); + real32 BoxAxis = BoxLength.x; + Interact->Scale = 1.0f + Length / BoxAxis; + v2 MovePos = V2((Length / 2), -(Length / 2) * (BoxLength.y / BoxLength.x)); + v2 XAxis = (MovePos.x * Dir.x)*V2(cos(Rad), sin(Rad)); + v2 YAxis = (MovePos.y * Dir.y)*V2(sin(Rad), -cos(Rad)); + v2 Pos = XAxis + YAxis; + Interact->Position.x = Pos.x; + Interact->Position.y = Pos.y; } + 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. @@ -644,43 +463,67 @@ ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Me InBounds = true; } + uint32 Col[4] = { IM_COL32(255, 0, 0, 255), IM_COL32(0, 255, 0, 255), IM_COL32(0, 0, 255, 255), IM_COL32(255, 255, 255, 255) }; for (int i = 0; i < 4; i++) { ImGui::SetCursorScreenPos(P[i] - ScaleHandleSize/2); ImGui::PushID(i); ImGui::Button("##ScaleRotateCorners", ScaleHandleSize); if (ImGui::IsItemActivated() && !OtherActions) { - State->InteractTransformMode = 2; - // if (InBounds) - // State->InteractTransformMode = 1; - // else - // State->InteractTransformMode = 2; + if (InBounds) + State->InteractTransformMode = 1; + else + State->InteractTransformMode = 2; State->Interact_Active = interact_type_viewport_transform_gizmo; } // 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; + ImVec2 LengthVec = (io.MousePos - io.MouseClickedPos[0]) / CompScale; + real32 NegRad = -Rad; + v2 XAxis = (LengthVec.x * 1.0f)*V2(cos(NegRad), sin(NegRad)); + v2 YAxis = (LengthVec.y * -1.0f)*V2(sin(NegRad), -cos(NegRad)); + v2 UnrotatedLengthVec = XAxis + YAxis; + + v2 Dir = {}; + if (i == 0) { + Dir = V2(-1, 1); + } else if (i == 1) { + Dir = V2(1, 1); + } else if (i == 2) { + Dir = V2(1, -1); + } else if (i == 3) { + Dir = V2(-1, -1); + } else { + Assert(0); + } + + v2 Vector0 = V2(BoxLength.x, BoxLength.y); + real32 Dot = Inner(V2(-Vector0.y * Dir.x, Vector0.x * Dir.y), UnrotatedLengthVec); + bool32 Test = (Dot < 0.0f) ? 0 : 1; + + if (!Test) { + real32 Length = UnrotatedLengthVec.x * Dir.x; + real32 BoxAxis = BoxLength.x; + Interact->Scale = 1.0f + Length / BoxAxis; + v2 MovePos = V2((Length / 2), -(Length / 2) * (BoxLength.y / BoxLength.x)); + v2 XAxis = (MovePos.x * Dir.x)*V2(cos(Rad), sin(Rad)); + v2 YAxis = (MovePos.y * Dir.y)*V2(sin(Rad), -cos(Rad)); + v2 Pos = XAxis + YAxis; + Interact->Position.x = Pos.x; + Interact->Position.y = Pos.y; + } else { + real32 Mult = (i == 1 || i == 3) ? -1 : 1; + real32 Length = UnrotatedLengthVec.y * Mult * Dir.x; + real32 BoxAxis = BoxLength.y; + Interact->Scale = 1.0f + -Length / BoxAxis; + v2 MovePos = V2(-(Length / 2) * (BoxLength.x / BoxLength.y), (Length / 2)); + v2 XAxis = (MovePos.x * Dir.x)*V2(cos(Rad), sin(Rad)); + v2 YAxis = (MovePos.y * Dir.y)*V2(sin(Rad), -cos(Rad)); + v2 Pos = XAxis + YAxis; + Interact->Position.x = Pos.x; + Interact->Position.y = Pos.y; } } @@ -706,13 +549,16 @@ ImGui_Viewport_TransformUI2(project_data *File, project_state *State, memory *Me ImGui::PopID(); } - - if (InBounds && !io.KeyAlt) { - ImGui::SetCursorScreenPos(io.MousePos - ScaleHandleSize/2); - ImGui::Button("##mover", ScaleHandleSize); - if (!State->InteractTransformMode && ImGui::IsItemActivated() && !OtherActions) { - State->Interact_Active = interact_type_viewport_transform_gizmo; - State->InteractTransformMode = 3; + if (InBounds && !io.KeyAlt && !ImGui::IsKeyDown(ImGuiKey_Z) && !ImGui::IsKeyDown(ImGuiKey_ModShift)) { + v2 MouseLocalUV = ImGui_ScreenPointToCompUV(ViewportMin, UI->CompPos, UI->CompZoom, io.MousePos); + bool32 LayerHovered = Layer_TestForPoint(Memory, State, UI, SortedCompArray, SortedLayerArray, File->PrincipalCompIndex, MouseLocalUV); + if (LayerHovered) { + ImGui::SetCursorScreenPos(io.MousePos - ScaleHandleSize/2); + ImGui::Button("##mover", ScaleHandleSize); + if (!State->InteractTransformMode && ImGui::IsItemActivated() && !OtherActions) { + State->Interact_Active = interact_type_viewport_transform_gizmo; + State->InteractTransformMode = 3; + } } } @@ -1246,7 +1092,7 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, if (State->Interact_Active == interact_type_viewport_transform) { ImGui_Viewport_TransformUI(File, State, Memory, UI, io, draw_list, &State->Interact_Transform, ViewportMin, MainComp->Width, MainComp->Height, SortedKeyframeArray); } else { - ImGui_Viewport_TransformUI2(File, State, Memory, UI, io, draw_list, &PointCount, PointData, ViewportMin, MainComp->Width, MainComp->Height, SortedKeyframeArray); + ImGui_Viewport_TransformUI2(File, State, Memory, UI, io, draw_list, &PointCount, PointData, ViewportMin, MainComp->Width, MainComp->Height, SortedCompArray, SortedLayerArray, SortedKeyframeArray); } Memory_PopScratch(Memory, sizeof(v2) * 512); } @@ -1318,8 +1164,16 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, BoxMax.y > BoxMin.y) BoxMax.y = (MousePos.y > ClickedPos.y) ? MousePos.y : ClickedPos.y; if (io.MouseDelta.x || io.MouseDelta.y) { - if (State->Tool == tool_default && State->Interact_Active == interact_type_none) - State->Interact_Active = interact_type_viewport_selection; + if (State->Tool == tool_default && State->Interact_Active == interact_type_none) { + int32 Selection = Layer_TestSelection(Memory, State, UI, SortedCompArray, SortedLayerArray, File->PrincipalCompIndex); + if (!State->InteractTransformMode && Selection != -1) { + Layer_Select(Memory, State, Selection); + State->Interact_Active = interact_type_viewport_transform_gizmo; + State->InteractTransformMode = 3; + } else { + State->Interact_Active = interact_type_viewport_selection; + } + } if (State->Interact_Active == interact_type_viewport_selection) { Layer_DeselectAll(File, State, Memory); @@ -1341,14 +1195,14 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, (IsHovered && IsDeactivated && !io.KeyCtrl && !io.KeyAlt)) && !ImGui::IsMouseDown(ImGuiMouseButton_Right) && !ImGui::IsKeyDown(ImGuiKey_Z)) { - // Layer selection - if (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); - } + // Layer selection + if (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 (IsDeactivated && State->Interact_Active == interact_type_viewport_selection) { @@ -1518,6 +1372,7 @@ ImGui_Viewport(project_data *File, project_state *State, ui *UI, memory *Memory, State->Interact_Dup_Previous[1] = State->Interact_Offset[1]; State->Interact_Offset[0] = 0; State->Interact_Offset[1] = 0; + State->Interact_Transform = {}; History_Entry_End(Memory); } else { Assert(IsActive); diff --git a/src/include/all.h b/src/include/all.h index 9d7fe77..e2a2a2f 100644 --- a/src/include/all.h +++ b/src/include/all.h @@ -507,6 +507,8 @@ Transform_Recurse(project_state *State, memory *Memory, block_composition *MainC sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, real32 *MinX, real32 *MinY, real32 *MaxX, real32 *MaxY); +static bool32 +Layer_TestForPoint(memory *Memory, project_state *State, ui *UI, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, uint16 PrincipalIndex, v2 CompUV); static v2 TransformPoint(layer_transforms T, real32 Width, real32 Height, v2 Point); diff --git a/src/include/my_math.h b/src/include/my_math.h index 938ed3c..ed26bc8 100644 --- a/src/include/my_math.h +++ b/src/include/my_math.h @@ -576,6 +576,12 @@ Length(v2 A) return sqrt(Inner(A, A)); } +inline real32 +Length(ImVec2 A) +{ + return sqrt(Inner(A, A)); +} + inline uint32 Floor(uint32 A, uint32 B) { diff --git a/src/layer.cpp b/src/layer.cpp index 591487e..3686d75 100644 --- a/src/layer.cpp +++ b/src/layer.cpp @@ -370,6 +370,29 @@ Layer_TraverseForPoint(project_data *File, project_state *State, memory *Memory, return PointUV * V2(InnerWidth, InnerHeight); } +// TODO(fox): Precomps? +static bool32 +Layer_TestForPoint(memory *Memory, project_state *State, ui *UI, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, uint16 PrincipalIndex, v2 CompUV) +{ + block_composition *Comp = (block_composition *)Memory_Block_AddressAtIndex(Memory, F_Precomps, PrincipalIndex); + sorted_comp_array SortedCompStart = SortedCompArray[PrincipalIndex]; + sorted_layer_array *SortedLayerStart = Sorted_GetLayerStart(SortedLayerArray, SortedCompArray, PrincipalIndex); + for (int i = SortedCompStart.LayerCount - 1; i >= 0; i--) { + sorted_layer_array SortEntry = SortedLayerStart[i]; + uint32 Index_Physical = SortEntry.Block_Layer_Index; + block_layer *Layer = (block_layer *)Memory_Block_AddressAtIndex(Memory, F_Layers, Index_Physical); + int Width, Height; + Layer_GetDimensions(Memory, Layer, &Width, &Height); + layer_transforms T = Layer_GetTransforms(Layer); + v2 UV = T_CompUVToLayerUV(T, Comp->Width, Comp->Height, Width, Height, CompUV); + if (UV.x <= 1.0f && UV.x >= 0.0f && UV.y <= 1.0f && UV.y >= 0.0f && Layer->IsSelected) + { + return 1; + } + } + return 0; +} + // TODO(fox): Precomps? static int32 Layer_TestSelection(memory *Memory, project_state *State, ui *UI, sorted_comp_array *SortedCompArray, sorted_layer_array *SortedLayerArray, uint16 PrincipalIndex) @@ -513,6 +536,8 @@ Shape_TestBoxSelect(layer_transforms T, uint32 CompWidth, uint32 CompHeight, uin P0->x = Pos0.x; P0->y = Pos0.y; } +#endif +#if 1 nvg_point *P0 = &Point[PointCount-1]; nvg_point *P1 = &Point[0]; for (int i = 0; i < PointCount; i++) { @@ -526,32 +551,8 @@ Shape_TestBoxSelect(layer_transforms T, uint32 CompWidth, uint32 CompHeight, uin return true; P0 = P1++; } - return false; -#else - v2 *P0_B = &Box[3]; - v2 *P1_B = &Box[0]; - for (int x = 0; x < 4; x++) { - nvg_point *P0 = &Point[PointCount-1]; - v2 Pos0 = TransformPoint(T, ShapeWidth, ShapeHeight, V2(P0->x, P0->y)); - if (Pos0.x > Box[0].x && Pos0.x < Box[2].x && - Pos0.y > Box[0].y && Pos0.y < Box[2].y) - return true; - P0->x = Pos0.x; - P0->y = Pos0.y; - nvg_point *P1 = &Point[0]; - for (int i = 0; i < PointCount; i++) { - v2 Pos1 = TransformPoint(T, ShapeWidth, ShapeHeight, V2(P1->x, P1->y)); - if (Pos1.x > Box[0].x && Pos1.x < Box[2].x && - Pos1.y > Box[0].y && Pos1.y < Box[2].y) - return true; - if (Line_TestIntersect(P0->x, P0->y, P1->x, P1->y, P0_B->x, P0_B->y, P1_B->x, P1_B->y)) - return true; - P0 = P1++; - } - P0_B = P1_B++; - } - return false; #endif + return false; } static void @@ -575,8 +576,8 @@ Layer_TestBoxSelect(memory *Memory, project_state *State, ui *UI, sorted_comp_ar uint32 NumberOfVerts = NVG_FlattenPath(Memory, Shape, Layer->ShapeOpt, NVGPointData, State, T, Shape->Width, Shape->Height, Comp->Width, Comp->Height, 1, &ShapeMin, &ShapeMax); v2 Box[4] = { MinPos, V2(MinPos.x, MaxPos.y), MaxPos, V2(MaxPos.x, MinPos.y) }; - if (Shape_TestBoxSelect(T, Comp->Width, Comp->Height, Shape->Height, Shape->Width, Box, NVGPointData, NumberOfVerts)) { - Layer_Select(Memory, State, i); + if (Shape_TestBoxSelect(T, Comp->Width, Comp->Height, Shape->Width, Shape->Height, Box, NVGPointData, NumberOfVerts)) { + Layer_Select(Memory, State, Index_Physical); } Memory_PopScratch(Memory, sizeof(nvg_point) * 1024); diff --git a/src/main.cpp b/src/main.cpp index d1e992a..fd56316 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,8 +21,6 @@ uint32 BitmapFill = 0x00000001; #include #endif -static real32 aaa; - #if SPECIAL #else #include "memory.cpp" diff --git a/src/prenderer.cpp b/src/prenderer.cpp index 37fb113..53025b2 100644 --- a/src/prenderer.cpp +++ b/src/prenderer.cpp @@ -67,24 +67,23 @@ Transform_ApplyInteractive(interact_transform Interact, real32 *OutputX, real32 { v2 BoxLength = Interact.Max - Interact.Min; v2 Center = Interact.Max - (BoxLength/2); - if (Interact.RadianOffset != 0.0f && Interact.Radians != 0.0f) { + if (Interact.RadianOffset != 0.0f) { v2 LocalCenter = Interact.NewCenter; real32 Rad = Interact.RadianOffset; real32 Point0X = Center.x - Interact.OGCenter.x; real32 Point0Y = Center.y - Interact.OGCenter.y; - v2 XAxis = (Point0X * Interact.Scale)*V2(cos(Rad), sin(Rad)); - v2 YAxis = (Point0Y * Interact.Scale)*V2(sin(Rad), -cos(Rad)); + v2 XAxis = (Point0X * 1.0f)*V2(cos(Rad), sin(Rad)); + v2 YAxis = (Point0Y * 1.0f)*V2(sin(Rad), -cos(Rad)); Center = Interact.OGCenter + XAxis + YAxis; } - real32 Point0X = Center.x - *OutputX; real32 Point0Y = Center.y - *OutputY; real32 Rad = Interact.Radians; real32 Rotation = Rad / (PI / 180); - v2 XAxis = (Point0X * Interact.Scale)*V2(cos(Rad), sin(Rad)); + v2 XAxis = (Point0X * Interact.Scale)*V2(cos(Rad), sin(Rad)); v2 YAxis = (Point0Y * -Interact.Scale)*V2(sin(Rad), -cos(Rad)); real32 X0 = -XAxis.x - YAxis.x + Center.x; -- cgit v1.2.3