public static float AngleFromAnchor(Vector2 anchorPosition, Vector2 targetPosition, float targetRotation)
    {
        float angle;

        if (Vector3.Distance(targetPosition, anchorPosition) > AnchorEpsilon)
        {
            Vector3 towardsTarget = (targetPosition - anchorPosition).normalized;

            angle = Helpers2D.GetAngle(towardsTarget);
        }
        else
        {
            angle = targetRotation;
        }
        return(angle);
    }
Example #2
0
    protected override void ReAlignAnchors(AnchoredJoint2D joint2D, JointHelpers.AnchorBias alignmentBias)
    {
        var sliderJoint2D = (SliderJoint2D)joint2D;

        //align the angle to the connected anchor
        var direction = JointHelpers.GetConnectedAnchorPosition(joint2D) -
                        JointHelpers.GetMainAnchorPosition(joint2D);

        if (direction.magnitude > AnchorEpsilon)
        {
            var wantedAngle = Helpers2D.GetAngle(direction);

            EditorHelpers.RecordUndo("Realign angle", sliderJoint2D);
            sliderJoint2D.angle = wantedAngle - sliderJoint2D.transform.eulerAngles.z;
        }
    }
Example #3
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();
    }
    private void DrawDistance(T jointWithDistance, AnchorInfo anchorInfo, JointHelpers.AnchorBias bias)
    {
        if (jointWithDistance == null)
        {
            return;
        }

        var otherBias = bias == JointHelpers.AnchorBias.Main
            ? JointHelpers.AnchorBias.Connected
            : JointHelpers.AnchorBias.Main;

        var anchorPosition      = JointHelpers.GetAnchorPosition(jointWithDistance, bias);
        var otherAnchorPosition = JointHelpers.GetAnchorPosition(jointWithDistance, otherBias);
        var diff = anchorPosition - otherAnchorPosition;

        if (diff.magnitude <= Mathf.Epsilon)
        {
            diff = Vector2.up * (bias == JointHelpers.AnchorBias.Connected ? 1 : -1);
        }
        var normalizedDiff = diff.normalized;

        JointHelpers.AnchorBias wantedBias;
        switch (GetSettings(jointWithDistance).anchorPriority)
        {
        case JointSettingsWithBias.AnchorPriority.Main:
            wantedBias = JointHelpers.AnchorBias.Main;
            break;

        case JointSettingsWithBias.AnchorPriority.Connected:
            wantedBias = JointHelpers.AnchorBias.Connected;
            break;

        default:
            throw new ArgumentOutOfRangeException();
        }

        if (bias == wantedBias && EditorGUI.actionKey && GUIUtility.hotControl == anchorInfo.GetControlID("slider"))
        {
            Handles.DrawWireDisc(otherAnchorPosition, Vector3.forward, GetDistance(jointWithDistance));
        }

        if (bias != wantedBias)
        {
            var distanceControlID = anchorInfo.GetControlID("distance");

            EditorGUI.BeginChangeCheck();

            float newDistance;
            using (
                new HandleColor(isCreatedByTarget
                    ? new Color(1, 1, 1, editorSettings.connectedJointTransparency)
                    : Color.white)) {
                newDistance = EditorHelpers.LineSlider(distanceControlID, otherAnchorPosition,
                                                       GetDistance(jointWithDistance), Helpers2D.GetAngle(normalizedDiff), 0.125f, true);

                EditorHelpers.DrawThickLine(anchorPosition, otherAnchorPosition + normalizedDiff * newDistance,
                                            Vector2.Distance(anchorPosition, otherAnchorPosition) > newDistance ? 2 : 1, true);
            }

            if (Event.current.type == EventType.repaint)
            {
                if (EditorHelpers.IsWarm(distanceControlID) && DragAndDrop.objectReferences.Length == 0)
                {
                    var labelContent =
                        new GUIContent(string.Format("Distance: {0:0.00}", GetDistance(jointWithDistance)));

                    var sliderPosition = otherAnchorPosition + normalizedDiff * GetDistance(jointWithDistance);

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

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

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


            if (EditorGUI.EndChangeCheck())
            {
                using (new Modification("Change Distance", jointWithDistance)) {
                    if (newDistance < 0)
                    {
                        SetDistance(jointWithDistance, 0f);
                    }
                    else
                    {
                        var distanceBetweenAnchors = Vector2.Distance(otherAnchorPosition, anchorPosition);
                        SetDistance(jointWithDistance,
                                    EditorGUI.actionKey && Mathf.Abs(newDistance - distanceBetweenAnchors) <
                                    HandleUtility.GetHandleSize(anchorPosition) * 0.125f
                                ? distanceBetweenAnchors
                                : newDistance);
                    }
                }
            }

            DistanceContext(jointWithDistance, distanceControlID);
        }
    }
Example #5
0
    private static void DrawLimitSlider(SliderJoint2D sliderJoint2D, int limitControlID, Vector2 anchorPosition,
                                        Vector2 direction, IEnumerable <Vector2> snapList, Limit limit)
    {
        EditorGUI.BeginChangeCheck();

        float val;
        var   limits2D = sliderJoint2D.limits;

        switch (limit)
        {
        case Limit.Min:
            val = limits2D.min;
            break;

        case Limit.Max:
            val = limits2D.max;
            break;

        default:
            throw new ArgumentOutOfRangeException("limit");
        }

        var newLimit = EditorHelpers.LineSlider(limitControlID, anchorPosition,
                                                val,
                                                Helpers2D.GetAngle(direction), 0.125f, false, limit == Limit.Min);

        if (!EditorGUI.EndChangeCheck())
        {
            return;
        }

        if (snapList != null)
        {
            var limitSnapList = new List <Vector2>(snapList);
            switch (limit)
            {
            case Limit.Min:
                limitSnapList.Add(anchorPosition + direction * limits2D.max);
                break;

            case Limit.Max:
                limitSnapList.Add(anchorPosition + direction * limits2D.min);
                break;

            default:
                throw new ArgumentOutOfRangeException("limit");
            }

            var limitGUIPosition =
                HandleUtility.WorldToGUIPoint(anchorPosition + direction * newLimit);

            foreach (
                var snapPosition in
                from snapPosition in limitSnapList
                let snapGUIPosition = HandleUtility.WorldToGUIPoint(snapPosition)
                                      where Vector2.Distance(limitGUIPosition, snapGUIPosition) < 10
                                      select snapPosition)
            {
                newLimit = Helpers2D.DistanceAlongLine(new Ray(anchorPosition, direction),
                                                       snapPosition);
            }
        }


        EditorHelpers.RecordUndo("Change slider limit", sliderJoint2D);
        switch (limit)
        {
        case Limit.Min:
            limits2D.min = newLimit;
            break;

        case Limit.Max:
            limits2D.max = newLimit;
            break;

        default:
            throw new ArgumentOutOfRangeException("limit");
        }
        sliderJoint2D.limits = limits2D;
    }
Example #6
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);
            }
        }
    }
Example #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);
    }