private static Vector2 GetWantedAnchorPosition(AnchoredJoint2D anchoredJoint2D, JointHelpers.AnchorBias bias,
                                                   Vector2 position)
    {
        var wheelJoint2D = (WheelJoint2D)anchoredJoint2D;

        var otherBias = JointHelpers.GetOppositeBias(bias);

        var worldAngle = wheelJoint2D.transform.eulerAngles.z + wheelJoint2D.suspension.angle;

        var slideRay = new Ray(JointHelpers.GetAnchorPosition(wheelJoint2D, otherBias),
                               Helpers2D.GetDirection(worldAngle));
        var wantedAnchorPosition = Helpers2D.ClosestPointToRay(slideRay, position);

        return(wantedAnchorPosition);
    }
Exemplo n.º 2
0
    private void DrawLinesAndDiscs(HingeJoint2D hingeJoint2D, AnchorInfo anchorInfo, JointHelpers.AnchorBias bias)
    {
        var center = JointHelpers.GetAnchorPosition(hingeJoint2D, bias);

        var scale      = editorSettings.anchorScale;
        var handleSize = HandleUtility.GetHandleSize(center) * scale;

        var mainBodyPosition      = GetTargetPosition(hingeJoint2D, JointHelpers.AnchorBias.Main);
        var connectedBodyPosition = GetTargetPosition(hingeJoint2D, JointHelpers.AnchorBias.Connected);

        var settings = SettingsHelper.GetOrCreate <HingeJoint2DSettings>(hingeJoint2D);

        if (bias == JointHelpers.AnchorBias.Main)
        {
            float angleToMain;

            if (Vector2.Distance(mainBodyPosition, center) > AnchorEpsilon)
            {
                angleToMain = Helpers2D.GetAngle(mainBodyPosition - center);
            }
            else
            {
                angleToMain = JointHelpers.GetTargetRotation(hingeJoint2D, JointHelpers.AnchorBias.Main);
            }

            using (new HandleColor(GetAdjustedColor(editorSettings.anchorsToMainBodyColor)))
            {
                Handles.DrawLine(center,
                                 center + Helpers2D.GetDirection(angleToMain + settings.mainAngleOffset) * handleSize);
            }
        }
        else if (bias == JointHelpers.AnchorBias.Connected)
        {
            if (hingeJoint2D.connectedBody)
            {
                float angleToConnected;

                if (Vector2.Distance(connectedBodyPosition, center) > AnchorEpsilon)
                {
                    angleToConnected = Helpers2D.GetAngle(connectedBodyPosition - center);
                }
                else
                {
                    angleToConnected = JointHelpers.GetTargetRotation(hingeJoint2D, JointHelpers.AnchorBias.Connected);
                }

                using (new HandleColor(GetAdjustedColor(editorSettings.anchorsToConnectedBodyColor)))
                {
                    Handles.DrawLine(center,
                                     center + Helpers2D.GetDirection(angleToConnected + settings.connectedAngleOffset) * handleSize);
                }
            }
            else
            {
                using (new HandleColor(GetAdjustedColor(editorSettings.anchorsToConnectedBodyColor)))
                {
                    Handles.DrawLine(center, center + Helpers2D.GetDirection(settings.connectedAngleOffset) * handleSize);
                }
            }
        }

        if (settings.showDiscs)
        {
            var sliderControlID = anchorInfo.GetControlID("slider");

            if (editorSettings.ringDisplayMode == JointEditorSettings.RingDisplayMode.Always ||
                (editorSettings.ringDisplayMode == JointEditorSettings.RingDisplayMode.Hover &&
                 //if nothing else is hot and we are being hovered, or the anchor's widgets are hot
                 ((GUIUtility.hotControl == 0 && HandleUtility.nearestControl == sliderControlID) ||
                  GUIUtility.hotControl == sliderControlID))
                )
            {
                using (new HandleColor(GetAdjustedColor(editorSettings.mainRingColor)))
                {
                    Handles.DrawWireDisc(center, Vector3.forward, Vector2.Distance(center, mainBodyPosition));
                }

                if (hingeJoint2D.connectedBody)
                {
                    using (new HandleColor((editorSettings.connectedRingColor))) {
                        Handles.DrawWireDisc(center, Vector3.forward,
                                             Vector2.Distance(center,
                                                              connectedBodyPosition));
                    }
                }
            }
        }

        HandleUtility.Repaint();
    }
Exemplo n.º 3
0
    private static bool HandleMainLimits(HingeJoint2D hingeJoint2D, AnchorInfo anchorInfo, Color limitAreaColor,
                                         float limitDifference, Vector2 anchorPosition, float distanceFromCenter,
                                         float maxMainAngle, HingeJoint2DSettings settings, Color limitColor,
                                         float minMainAngle, Color angleWidgetColor, Color activeAngleColor,
                                         Color hoverAngleColor, float angleHandleSize, JointAngleLimits2D limits,
                                         float liveMainAngle)
    {
        var changed = false;

        using (new HandleColor(limitAreaColor)) {
            if (limitDifference > 360)
            {
                Handles.DrawSolidDisc(anchorPosition, Vector3.forward, distanceFromCenter);
            }
            else
            {
                Handles.DrawSolidArc(anchorPosition, Vector3.forward,
                                     Helpers2D.GetDirection(maxMainAngle + settings.mainAngleOffset),
                                     limitDifference, distanceFromCenter);
            }
        }
        using (new HandleColor(limitColor)) {
            Vector3 minMainEnd = anchorPosition +
                                 Helpers2D.GetDirection(minMainAngle + settings.mainAngleOffset) *
                                 distanceFromCenter;
            Handles.DrawLine(anchorPosition, minMainEnd);

            Vector3 maxMainEnd = anchorPosition +
                                 Helpers2D.GetDirection(maxMainAngle + settings.mainAngleOffset) *
                                 distanceFromCenter;
            Handles.DrawLine(anchorPosition, maxMainEnd);

            if (limitDifference > 360)
            {
                Handles.DrawWireDisc(anchorPosition, Vector3.forward, distanceFromCenter);
            }
            else
            {
                Handles.DrawWireArc(anchorPosition, Vector3.forward,
                                    Helpers2D.GetDirection(maxMainAngle + settings.mainAngleOffset),
                                    limitDifference, distanceFromCenter);
            }


            EditorGUI.BeginChangeCheck();
            using (
                HandleDrawerBase drawer = new HandleCircleDrawer(angleWidgetColor, activeAngleColor,
                                                                 hoverAngleColor)) {
                minMainAngle = EditorHelpers.AngleSlider(anchorInfo.GetControlID("lowerMainAngle"), drawer,
                                                         anchorPosition,
                                                         minMainAngle + settings.mainAngleOffset,
                                                         distanceFromCenter, angleHandleSize * HandleUtility.GetHandleSize(minMainEnd) / 64) -
                               settings.mainAngleOffset;
            }

            if (EditorGUI.EndChangeCheck())
            {
                EditorHelpers.RecordUndo("Change Angle Limits", hingeJoint2D);
                limits.min          = Handles.SnapValue(liveMainAngle - minMainAngle, editorSettings.snapAngle);
                hingeJoint2D.limits = limits;
                changed             = true;
            }

            EditorGUI.BeginChangeCheck();
            using (
                HandleDrawerBase drawer = new HandleCircleDrawer(angleWidgetColor,
                                                                 activeAngleColor, hoverAngleColor)) {
                maxMainAngle = EditorHelpers.AngleSlider(anchorInfo.GetControlID("upperMainAngle"), drawer,
                                                         anchorPosition,
                                                         maxMainAngle + settings.mainAngleOffset,
                                                         distanceFromCenter, angleHandleSize * HandleUtility.GetHandleSize(maxMainEnd) / 64) -
                               settings.mainAngleOffset;
            }

            if (EditorGUI.EndChangeCheck())
            {
                EditorHelpers.RecordUndo("Change Angle Limits", hingeJoint2D);
                limits.max          = Handles.SnapValue(liveMainAngle - maxMainAngle, editorSettings.snapAngle);
                hingeJoint2D.limits = limits;
                changed             = true;
            }
        }
        return(changed);
    }
Exemplo n.º 4
0
    protected override bool PostAnchorGUI(AnchoredJoint2D joint2D, AnchorInfo info, List <Vector2> otherAnchors,
                                          JointHelpers.AnchorBias bias)
    {
        var hingeJoint2D = joint2D as HingeJoint2D;

        if (hingeJoint2D == null)
        {
            return(false);
        }

        if (!hingeJoint2D.useLimits)
        {
            return(false);
        }

        var   showAngle    = false;
        float angle        = 0;
        float displayAngle = 0;

        float jointAngle;

        if (EditorApplication.isPlayingOrWillChangePlaymode || Application.isPlaying)
        {
            jointAngle = hingeJoint2D.jointAngle;
        }
        else
        {
            jointAngle = 0;
        }

        var startPosition = JointHelpers.GetAnchorPosition(hingeJoint2D, bias);

        var mainBodyPosition = GetTargetPosition(hingeJoint2D, JointHelpers.AnchorBias.Main);

        var mainBodyAngle = JointHelpers.AngleFromAnchor(startPosition, mainBodyPosition,
                                                         JointHelpers.GetTargetRotation(hingeJoint2D, JointHelpers.AnchorBias.Main));

        var connectedBodyPosition = GetTargetPosition(hingeJoint2D, JointHelpers.AnchorBias.Connected);

        float connectedBodyAngle;

        if (hingeJoint2D.connectedBody)
        {
            connectedBodyAngle = JointHelpers.AngleFromAnchor(startPosition, connectedBodyPosition,
                                                              JointHelpers.GetTargetRotation(hingeJoint2D, JointHelpers.AnchorBias.Connected));
        }
        else
        {
            connectedBodyAngle = 0;
        }

        var angleDiff = jointAngle - (connectedBodyAngle - mainBodyAngle);

        var liveMainAngle = connectedBodyAngle + angleDiff;

        var minMainAngle = liveMainAngle - hingeJoint2D.limits.min;
        var maxMainAngle = liveMainAngle - hingeJoint2D.limits.max;

        var labelText = "";

        float angleOffset = 0;

        var settings = SettingsHelper.GetOrCreate <HingeJoint2DSettings>(hingeJoint2D);

        if (EditorHelpers.IsWarm(info.GetControlID("lowerMainAngle")))
        {
            showAngle    = true;
            angle        = minMainAngle;
            displayAngle = hingeJoint2D.limits.min;
            labelText    = "Lower: ";
            angleOffset  = settings.mainAngleOffset;
        }
        else if (EditorHelpers.IsWarm(info.GetControlID("upperMainAngle")))
        {
            showAngle    = true;
            angle        = maxMainAngle;
            displayAngle = hingeJoint2D.limits.max;
            labelText    = "Upper: ";
            angleOffset  = settings.mainAngleOffset;
        }
        else if (EditorHelpers.IsWarm(info.GetControlID("lowerConnectedAngle")))
        {
            showAngle     = true;
            angle         = hingeJoint2D.limits.min;
            displayAngle  = angle;
            labelText     = "Lower: ";
            startPosition = JointHelpers.GetConnectedAnchorPosition(hingeJoint2D);
            angleOffset   = settings.connectedAngleOffset;
        }
        else if (EditorHelpers.IsWarm(info.GetControlID("upperConnectedAngle")))
        {
            showAngle     = true;
            angle         = hingeJoint2D.limits.max;
            labelText     = "Upper: ";
            displayAngle  = angle;
            startPosition = JointHelpers.GetConnectedAnchorPosition(hingeJoint2D);
            angleOffset   = settings.connectedAngleOffset;
        }

        LimitContext(hingeJoint2D, info.GetControlID("lowerMainAngle"), Limit.Min);
        LimitContext(hingeJoint2D, info.GetControlID("upperMainAngle"), Limit.Max);
        LimitContext(hingeJoint2D, info.GetControlID("lowerConnectedAngle"), Limit.Min);
        LimitContext(hingeJoint2D, info.GetControlID("upperConnectedAngle"), Limit.Max);

        if (showAngle)
        {
            var distanceFromCenter = GetAngleSliderRadius(startPosition);


            var anglePosition = startPosition + Helpers2D.GetDirection(angle + angleOffset) * distanceFromCenter;

            var labelContent = new GUIContent(labelText + "\n" + String.Format("{0:0.00}", displayAngle));

            var fontSize = HandleUtility.GetHandleSize(anglePosition) * (1f / 64f);

            var labelOffset = fontSize * EditorHelpers.FontWithBackgroundStyle.CalcSize(labelContent).y;

            EditorHelpers.OverlayLabel((Vector3)anglePosition + (Camera.current.transform.up * labelOffset),
                                       labelContent,
                                       EditorHelpers.FontWithBackgroundStyle);
        }
        return(false);
    }
Exemplo n.º 5
0
    private void LimitWidget(SliderJoint2D sliderJoint2D, AnchorInfo anchorInfo, JointHelpers.AnchorBias bias,
                             float worldAngle)
    {
        var anchorPosition = JointHelpers.GetAnchorPosition(sliderJoint2D, bias);

        var oppositeBias = JointHelpers.GetOppositeBias(bias);

        var oppositeAnchorPosition = JointHelpers.GetAnchorPosition(sliderJoint2D, oppositeBias);
        var direction = Helpers2D.GetDirection(worldAngle);

        if (bias == JointHelpers.AnchorBias.Connected)
        {
            direction *= -1f;
        }
        var delta = oppositeAnchorPosition - anchorPosition;

        var angleDiff = Mathf.DeltaAngle(Helpers2D.GetAngle(delta), worldAngle);

        Vector2 rotatedDelta = Helpers2D.Rotate(angleDiff) * delta;

        var wantedOppositeAnchorPosition  = anchorPosition + rotatedDelta;
        var wantedOppositeAnchorPosition2 = anchorPosition - rotatedDelta;

        var minLimitControlID = anchorInfo.GetControlID("minLimit");
        var maxLimitControlID = anchorInfo.GetControlID("maxLimit");

        LimitContext(sliderJoint2D, minLimitControlID, Limit.Min);
        LimitContext(sliderJoint2D, maxLimitControlID, Limit.Max);

        var limitColor = sliderJoint2D.limits.min > sliderJoint2D.limits.max
            ? editorSettings.incorrectLimitsColor
            : editorSettings.correctLimitsColor;

        if (isCreatedByTarget)
        {
            limitColor.a *= editorSettings.connectedJointTransparency;
        }

        using (new HandleColor(limitColor)) {
            Handles.DrawLine(anchorPosition + direction * sliderJoint2D.limits.min,
                             anchorPosition + direction * sliderJoint2D.limits.max);

            if (Event.current.type == EventType.repaint)
            {
                float fontSize;
                if (EditorHelpers.IsWarm(minLimitControlID) && DragAndDrop.objectReferences.Length == 0)
                {
                    var labelContent = new GUIContent(string.Format("Min: {0:0.00}", sliderJoint2D.limits.min));

                    var sliderPosition = anchorPosition + (direction) * (sliderJoint2D.limits.min);

                    fontSize = HandleUtility.GetHandleSize(sliderPosition) * ONE_OVER64;

                    var labelOffset = fontSize * EditorHelpers.FontWithBackgroundStyle.CalcSize(labelContent).y +
                                      fontSize * 20 *
                                      Mathf.Abs(Mathf.Cos(Mathf.Deg2Rad * Helpers2D.GetAngle(direction)));

                    EditorHelpers.OverlayLabel((Vector3)sliderPosition + (Camera.current.transform.up * labelOffset),
                                               labelContent, EditorHelpers.FontWithBackgroundStyle);
                }
                if (EditorHelpers.IsWarm(maxLimitControlID) && DragAndDrop.objectReferences.Length == 0)
                {
                    var labelContent = new GUIContent(string.Format("Max: {0:0.00}", sliderJoint2D.limits.max));

                    var sliderPosition = anchorPosition + (direction) * (sliderJoint2D.limits.max);

                    fontSize = HandleUtility.GetHandleSize(sliderPosition) * ONE_OVER64;

                    var labelOffset = fontSize * EditorHelpers.FontWithBackgroundStyle.CalcSize(labelContent).y +
                                      fontSize * 20 *
                                      Mathf.Abs(Mathf.Cos(Mathf.Deg2Rad * Helpers2D.GetAngle(direction)));

                    EditorHelpers.OverlayLabel((Vector3)sliderPosition + (Camera.current.transform.up * labelOffset),
                                               labelContent, EditorHelpers.FontWithBackgroundStyle);
                }
            }

            if (GUIUtility.hotControl == minLimitControlID ||
                GUIUtility.hotControl == maxLimitControlID)
            {
                using (
                    new HandleColor(new Color(1, 1, 1,
                                              0.25f * (isCreatedByTarget ? editorSettings.connectedJointTransparency : 1.0f)))) {
                    var handleSize = HandleUtility.GetHandleSize(wantedOppositeAnchorPosition) * ONE_OVER16;

                    Handles.DrawLine(wantedOppositeAnchorPosition - direction * handleSize,
                                     wantedOppositeAnchorPosition + direction * handleSize);
                    handleSize = HandleUtility.GetHandleSize(wantedOppositeAnchorPosition2) * ONE_OVER16;
                    Handles.DrawLine(wantedOppositeAnchorPosition2 - direction * handleSize,
                                     wantedOppositeAnchorPosition2 + direction * handleSize);
                    Handles.DrawWireArc(anchorPosition, Vector3.forward, wantedOppositeAnchorPosition, 360,
                                        Vector2.Distance(wantedOppositeAnchorPosition, anchorPosition));
                }
            }


            var actionKey = EditorGUI.actionKey;

            List <Vector2> snapList = null;
            if (actionKey)
            {
                snapList = new List <Vector2> {
                    anchorPosition,
                    wantedOppositeAnchorPosition,
                    wantedOppositeAnchorPosition2
                };
            }

            var minLimitColor = editorSettings.minLimitColor;
            var maxLimitColor = editorSettings.maxLimitColor;

            if (isCreatedByTarget)
            {
                minLimitColor.a *= editorSettings.connectedJointTransparency;
                maxLimitColor.a *= editorSettings.connectedJointTransparency;
            }

            using (new HandleColor(minLimitColor)) {
                DrawLimitSlider(sliderJoint2D, minLimitControlID, anchorPosition, direction, snapList, Limit.Min);
            }
            using (new HandleColor(maxLimitColor)) {
                DrawLimitSlider(sliderJoint2D, maxLimitControlID, anchorPosition, direction, snapList, Limit.Max);
            }
        }
    }
Exemplo n.º 6
0
    protected override IEnumerable <Vector2> GetSnapPositions(AnchoredJoint2D joint2D, AnchorInfo anchorInfo, JointHelpers.AnchorBias bias, Vector2 anchorPosition)
    {
        var sliderJoint2D = (SliderJoint2D)joint2D;

        var lockAnchors            = SettingsHelper.GetOrCreate(sliderJoint2D).lockAnchors;
        var oppositeBias           = JointHelpers.GetOppositeBias(bias);
        var oppositeAnchorPosition = JointHelpers.GetAnchorPosition(sliderJoint2D, oppositeBias);

        var snapPositions = new List <Vector2>();

        Vector2[] targetPositions;

        if (joint2D.connectedBody)
        {
            targetPositions = new[] {
                GetTargetPosition(joint2D, JointHelpers.AnchorBias.Main),
                GetTargetPosition(joint2D, JointHelpers.AnchorBias.Connected)
            };
        }
        else
        {
            targetPositions = new[] {
                GetTargetPosition(joint2D, JointHelpers.AnchorBias.Main)
            };
        }

        if (sliderJoint2D.useLimits)
        {
            Ray slideRay;

            var min = sliderJoint2D.limits.min;
            var max = sliderJoint2D.limits.max;


            if (lockAnchors)
            {
                slideRay = new Ray(oppositeAnchorPosition,
                                   (anchorPosition - oppositeAnchorPosition).normalized);

                foreach (var targetPosition in targetPositions)
                {
                    if (Vector2.Distance(oppositeAnchorPosition, targetPosition) <= AnchorEpsilon)
                    {
                        continue;
                    }

                    var fromConnectedToTarget = new Ray(oppositeAnchorPosition,
                                                        (targetPosition - oppositeAnchorPosition).normalized);

                    var closestPointToRay = Helpers2D.ClosestPointToRay(fromConnectedToTarget, anchorPosition);

                    var ray = new Ray(oppositeAnchorPosition, (closestPointToRay - oppositeAnchorPosition).normalized);

                    Vector2 wantedMinPosition = ray.GetPoint(min);
                    Vector2 wantedMaxPosition = ray.GetPoint(max);

                    snapPositions.Add(wantedMinPosition);
                    snapPositions.Add(wantedMaxPosition);
                }
            }
            else
            {
                var worldAngle = sliderJoint2D.transform.eulerAngles.z + sliderJoint2D.angle;

                if (bias == JointHelpers.AnchorBias.Main)
                {
                    worldAngle += 180;
                }

                slideRay = new Ray(oppositeAnchorPosition,
                                   Helpers2D.GetDirection(worldAngle));
            }


            Vector2 minPos = slideRay.GetPoint(min);

            snapPositions.Add(minPos);


            Vector2 maxPos = slideRay.GetPoint(max);

            snapPositions.Add(maxPos);
        }

        if (lockAnchors)
        {
            //align onto the rays from either target towards the opposite bias
            foreach (var targetPosition in targetPositions)
            {
                if (Vector2.Distance(targetPosition, oppositeAnchorPosition) <= AnchorEpsilon)
                {
                    continue;
                }
                var fromConnectedToTarget = new Ray(oppositeAnchorPosition,
                                                    (targetPosition - oppositeAnchorPosition).normalized);

//                if (Helpers2D.DistanceToLine(fromConnectedToTarget, anchorPosition) < snapDistance)
                {
                    var closestPointToRay = Helpers2D.ClosestPointToRay(fromConnectedToTarget, anchorPosition);
                    snapPositions.Add(closestPointToRay);
                }
            }
        }

        if (!lockAnchors &&
            !(Vector2.Distance(JointHelpers.GetMainAnchorPosition(joint2D),
                               JointHelpers.GetConnectedAnchorPosition(joint2D)) <= AnchorEpsilon))
        {
            var wantedAnchorPosition = GetWantedAnchorPosition(sliderJoint2D, bias, anchorPosition);

            snapPositions.Add(wantedAnchorPosition);
        }

        return(snapPositions);
    }
Exemplo n.º 7
0
    protected void DrawAngleWidget(TJointType joint2D, int controlID)
    {
        var joint2DSettings = GetSettings(joint2D);

        var worldAngle = joint2D.transform.eulerAngles.z + GetAngle(joint2D);

        HandleDragDrop(controlID, joint2D, joint2DSettings);

        EditorGUI.BeginChangeCheck();

        JointHelpers.AnchorBias bias;

        if (joint2DSettings.anchorPriority == JointSettingsWithBias.AnchorPriority.Main)
        {
            bias = JointHelpers.AnchorBias.Main;
        }
        else
        {
            bias = JointHelpers.AnchorBias.Connected;
        }

        var oppositeBias = JointHelpers.GetOppositeBias(bias);

        var angleWidgetPosition = JointHelpers.GetAnchorPosition(joint2D, bias);
        var otherAnchorPosition = JointHelpers.GetAnchorPosition(joint2D, oppositeBias);

        var offsetToOther = otherAnchorPosition - angleWidgetPosition;

        var newAngle = LineAngleHandle(controlID, worldAngle, angleWidgetPosition, 0.5f, 2);

        var mousePosition = Event.current.mousePosition;

        EditorHelpers.ContextClick(controlID, () => {
            var menu = new GenericMenu();
            AddEditAngleMenuItem(joint2D, menu, mousePosition);
            menu.ShowAsContext();
        });

        if (!EditorGUI.EndChangeCheck())
        {
            return;
        }
        var snapped = false;

        if (EditorGUI.actionKey)
        {
            var handleSize = HandleUtility.GetHandleSize(angleWidgetPosition);

            var mousePosition2D = Helpers2D.GUIPointTo2DPosition(Event.current.mousePosition);

            var currentAngleRay = new Ray(angleWidgetPosition, Helpers2D.GetDirection(newAngle));

            var mousePositionProjectedToAngle = Helpers2D.ClosestPointToRay(currentAngleRay, mousePosition2D);

            var directionsToSnapTo = new List <Vector2> {
                (GetTargetPosition(joint2D, bias) - angleWidgetPosition).normalized
            };

            if (!joint2DSettings.lockAnchors)
            {
                directionsToSnapTo.Insert(0, offsetToOther.normalized);
            }

            if (joint2D.connectedBody)
            {
                directionsToSnapTo.Add(
                    (GetTargetPosition(joint2D, oppositeBias) - angleWidgetPosition)
                    .normalized);
            }

            foreach (var direction in directionsToSnapTo)
            {
                var rayTowardsDirection = new Ray(angleWidgetPosition, direction);

                var closestPointTowardsDirection = Helpers2D.ClosestPointToRay(rayTowardsDirection,
                                                                               mousePositionProjectedToAngle);

                if (Vector2.Distance(closestPointTowardsDirection, mousePositionProjectedToAngle) <
                    handleSize * 0.125f)
                {
                    var currentDirection           = Helpers2D.GetDirection(newAngle);
                    var closestPositionToDirection =
                        Helpers2D.ClosestPointToRay(rayTowardsDirection,
                                                    angleWidgetPosition + currentDirection);

                    snapped  = true;
                    newAngle = Helpers2D.GetAngle(closestPositionToDirection - angleWidgetPosition);

                    break;
                }
            }
        }

        var wantedAngle = newAngle - joint2D.transform.eulerAngles.z;

        if (!snapped)
        {
            wantedAngle = Handles.SnapValue(wantedAngle, editorSettings.snapAngle);
        }

        EditorHelpers.RecordUndo("Alter Angle", joint2D);

        if (joint2DSettings.lockAnchors)
        {
            var angleDelta = Mathf.DeltaAngle(GetAngle(joint2D), wantedAngle);

            JointHelpers.SetWorldAnchorPosition(joint2D,
                                                angleWidgetPosition + (Vector2)(Helpers2D.Rotate(angleDelta) * offsetToOther), oppositeBias);
        }

        SetAngle(joint2D, wantedAngle);
    }