private void HandleAnchorContext(int controlID, JointHelpers.AnchorBias bias, AnchoredJoint2D joint,
        Joint2DSettingsBase joint2DSettings, Vector2 anchorPosition,
        Rigidbody2D connectedBody)
    {
        EditorHelpers.ContextClick(controlID, () => {
            var menu = new GenericMenu();
            menu.AddDisabledItem(new GUIContent(joint.GetType()
                                                     .Name));
            menu.AddSeparator("");
            if (WantsLocking()) {
                menu.AddItem(new GUIContent("Lock Anchors", GetAnchorLockTooltip()),
                    joint2DSettings.lockAnchors, () => {
                        EditorHelpers.RecordUndo(
                            joint2DSettings.lockAnchors ? "Unlock Anchors" : "Lock Anchors", joint2DSettings,
                            joint);
                        if (!joint2DSettings.lockAnchors) {
                            ReAlignAnchors(joint, bias);
                        }
                        joint2DSettings.lockAnchors = !joint2DSettings.lockAnchors;
                        EditorUtility.SetDirty(joint2DSettings);
                        EditorUtility.SetDirty(joint);
                    });
            }
            {
                var otherBias = JointHelpers.GetOppositeBias(bias);
                var otherPosition = JointHelpers.GetAnchorPosition(joint, otherBias);
                if (Vector2.Distance(otherPosition, anchorPosition) <= AnchorEpsilon) {
                    menu.AddDisabledItem(new GUIContent("Bring other anchor here"));
                } else {
                    menu.AddItem(new GUIContent("Bring other anchor here"), false, () => {
                        EditorHelpers.RecordUndo("Move Joint Anchor", joint);
                        JointHelpers.SetWorldAnchorPosition(joint, anchorPosition, otherBias);
                        EditorUtility.SetDirty(joint);
                    });
                }
            }

            menu.AddItem(new GUIContent("Enable Collision",
                "Should rigid bodies connected with this joint collide?"), joint.enableCollision,
                () => {
                    EditorHelpers.RecordUndo("Move Joint Anchor", joint);
                    joint.enableCollision = !joint.enableCollision;
                    EditorUtility.SetDirty(joint);
                });

            menu.AddSeparator("");

            var itemCount = menu.GetItemCount();

            ExtraMenuItems(menu, joint);

            if (itemCount != menu.GetItemCount()) {
                menu.AddSeparator("");
            }

            if (connectedBody) {
                var connectedBodyName = connectedBody.name;
                var selectConnectedBodyContent = new GUIContent(string.Format("Select '{0}'", connectedBodyName));
                if (isCreatedByTarget) {
                    menu.AddDisabledItem(selectConnectedBodyContent);
                } else {
                    menu.AddItem(selectConnectedBodyContent, false,
                        () => { Selection.activeGameObject = connectedBody.gameObject; });
                }
                menu.AddItem(new GUIContent(string.Format("Move ownership to '{0}'", connectedBodyName)), false, () => {
                    var connectedObject = connectedBody.gameObject;

                    var cloneJoint =
                        Undo.AddComponent(connectedObject, joint.GetType()) as AnchoredJoint2D;
                    if (!cloneJoint) {
                        return;
                    }
                    EditorUtility.CopySerialized(joint, cloneJoint);
                    cloneJoint.connectedBody = joint.GetComponent<Rigidbody2D>();

                    JointHelpers.SetWorldAnchorPosition(cloneJoint,
                        JointHelpers.GetAnchorPosition(joint, JointHelpers.AnchorBias.Main),
                        JointHelpers.AnchorBias.Connected);
                    JointHelpers.SetWorldAnchorPosition(cloneJoint,
                        JointHelpers.GetAnchorPosition(joint, JointHelpers.AnchorBias.Connected),
                        JointHelpers.AnchorBias.Main);

                    var jointSettings = SettingsHelper.GetOrCreate(joint);
                    var cloneSettings =
                        Undo.AddComponent(connectedObject, jointSettings.GetType()) as Joint2DSettingsBase;

                    if (cloneSettings == null) {
                        return;
                    }
                    cloneSettings.hideFlags = HideFlags.HideInInspector;

                    EditorUtility.CopySerialized(jointSettings, cloneSettings);
                    cloneSettings.Setup(cloneJoint);

                    cloneSettings.SetOffset(JointHelpers.AnchorBias.Main,
                        jointSettings.GetOffset(JointHelpers.AnchorBias.Connected));
                    cloneSettings.SetOffset(JointHelpers.AnchorBias.Connected,
                        jointSettings.GetOffset(JointHelpers.AnchorBias.Main));

                    if (!Selection.Contains(connectedObject)) {
                        var selectedObjects = new List<Object>(Selection.objects) {connectedObject};

                        if (selectedObjects.Contains(joint.gameObject)) {
                            selectedObjects.Remove(joint.gameObject);
                        }

                        Selection.objects = selectedObjects.ToArray();
                    }

                    Undo.DestroyObjectImmediate(joint);

                    OwnershipMoved(cloneJoint);
                });
                menu.AddItem(new GUIContent("Disconnect from '" + connectedBodyName + "'"), false, () => {
                    var worldConnectedPosition = JointHelpers.GetConnectedAnchorPosition(joint);

                    using (new Modification("Disconnect from connected body", joint)) {
                        joint.connectedBody = null;
                        JointHelpers.SetWorldConnectedAnchorPosition(joint, worldConnectedPosition);
                    }
                });
            } else {
                menu.AddDisabledItem(new GUIContent("Select connected body"));
                menu.AddDisabledItem(new GUIContent("Move ownership to connected body"));
                menu.AddDisabledItem(new GUIContent("Disconnect from connected body"));
            }

            menu.AddItem(new GUIContent("Delete " + joint.GetType()
                                                         .Name), false,
                () => Undo.DestroyObjectImmediate(joint));
            menu.ShowAsContext();
        });
    }
    protected void HandleDragDrop(int controlID, AnchoredJoint2D joint, Joint2DSettingsBase joint2DSettings)
    {
        var current = Event.current;

        if (HandleUtility.nearestControl == controlID) {
            switch (current.GetTypeForControl(controlID)) {
                case EventType.DragPerform:
                    foreach (var o in DragAndDrop.objectReferences) {
                        var gameObject = o as GameObject;
                        if (gameObject == null) {
                            continue;
                        }
                        var go = gameObject;
                        var rigidbody2D = go.GetComponent<Rigidbody2D>();
                        if (go.Equals(joint.gameObject) || rigidbody2D == null || rigidbody2D == joint.connectedBody) {
                            continue;
                        }
                        var wantsLock = joint2DSettings.lockAnchors;

                        EditorHelpers.RecordUndo("Drag Onto Anchor", joint);
                        var connectedBodyPosition = JointHelpers.GetConnectedAnchorPosition(joint);

                        var previousConnectedBody = joint.connectedBody;
                        joint.connectedBody = rigidbody2D;

                        JointHelpers.SetWorldConnectedAnchorPosition(joint, connectedBodyPosition);

                        if (wantsLock) {
                            ReAlignAnchors(joint, JointHelpers.AnchorBias.Main);
                        }

                        if (isCreatedByTarget) {
                            EditorHelpers.SelectObject(rigidbody2D.gameObject, true);
                            Selection.objects = Selection.objects.Where(o1 => o1 != previousConnectedBody.gameObject)
                                                         .ToArray();
                        }

                        EditorUtility.SetDirty(joint);
                        DragAndDrop.AcceptDrag();
                        break;
                    }
                    break;
                case EventType.DragUpdated:
                    if (DragAndDrop.objectReferences.OfType<GameObject>()
                                   .Any(go => {
                                       var rigidbody2D = go.GetComponent<Rigidbody2D>();
                                       return !go.Equals(joint.gameObject) && rigidbody2D != null &&
                                              rigidbody2D != joint.connectedBody;
                                   })) {
                        DragAndDrop.visualMode = DragAndDropVisualMode.Link;
                        Event.current.Use();
                    }
                    break;
                case EventType.DragExited:
                    break;
            }
        }
    }