/// <summary>
        /// Util method for drawing a consistent constraints section.
        /// Use this method in a component inspector for linking to a constraint manager.
        /// </summary>
        /// <param name="gameObject">Game object the constraint manager is attached to.</param>
        /// <param name="managerEnabled">Serialized property for enabling the manager - needs to be of type bool.</param>
        /// <param name="managerRef">Serialized property of the constraint manager component link - needs to be type of ConstraintManager.</param>
        /// <param name="isExpanded">Flag for indicating if the constraint foldout was previously collapsed or expanded.</param>
        /// <returns>Current state of expanded or collapsed constraint foldout. Returns true if expanded / contents visible.</returns>
        static public bool DrawConstraintManagerFoldout(GameObject gameObject, SerializedProperty managerEnabled, SerializedProperty managerRef, bool isExpanded)
        {
            isExpanded = EditorGUILayout.Foldout(isExpanded, "Constraints", true);

            if (isExpanded)
            {
                EditorGUILayout.PropertyField(managerEnabled);
                GUI.enabled = managerEnabled.boolValue;
                // Make sure we're having at least one constraint manager available.
                // Usually this should be ensured by the component requirement. However
                // for components that had this requirement added after they were serialized
                // this won't work out of the box.
                gameObject.EnsureComponent <ConstraintManager>();
                var constraintManagers = gameObject.GetComponents <ConstraintManager>();

                int selected = 0;

                string[] options = new string[constraintManagers.Length];

                int manualSelectionCount = 0;
                for (int i = 0; i < constraintManagers.Length; ++i)
                {
                    var manager = constraintManagers[i];
                    if (managerRef.objectReferenceValue == manager)
                    {
                        selected = i;
                    }

                    // popups will only show unique elements
                    // in case of auto selection we don't care which one we're selecting as the behavior will be the same.
                    // in case of manual selection users might want to differentiate which constraintmanager they are referring to.
                    if (manager.AutoConstraintSelection == true)
                    {
                        options[i] = manager.GetType().Name + " (auto)";
                    }
                    else
                    {
                        manualSelectionCount++;
                        options[i] = manager.GetType().Name + " (manual " + manualSelectionCount + ")";
                    }
                }

                using (new EditorGUILayout.HorizontalScope())
                {
                    selected = EditorGUILayout.Popup("Constraint Manager", selected, options, GUILayout.ExpandWidth(true));
                    ConstraintManager selectedConstraintManager = constraintManagers[selected];
                    managerRef.objectReferenceValue = selectedConstraintManager;
                    if (GUILayout.Button("Go to component"))
                    {
                        EditorGUIUtility.PingObject(selectedConstraintManager);
                        Highlighter.Highlight("Inspector", $"ComponentId: {selectedConstraintManager.GetInstanceID()}");
                        EditorGUIUtility.ExitGUI();
                    }
                }

                GUI.enabled = true;
            }

            return(isExpanded);
        }
        public override void OnInspectorGUI()
        {
            if (target != null)
            {
                serializedObject.Update();

                // Help url
                InspectorUIUtility.RenderHelpURL(target.GetType());

                // Data section
                using (var check = new EditorGUI.ChangeCheckScope())
                {
                    EditorGUILayout.Space();

                    EditorGUILayout.HelpBox(autoConstraintSelection.boolValue == true ? autoMsg : manualMsg
                                            , UnityEditor.MessageType.Info);
                    EditorGUILayout.Space();

                    int tab = autoConstraintSelection.boolValue == true ? 0 : 1;
                    tab = GUILayout.Toolbar(tab, new string[] { "Auto Constraint Selection", "Manual Constraint Selection" });
                    EditorGUILayout.Space();
                    switch (tab)
                    {
                    case 0:
                        autoConstraintSelection.boolValue = true;
                        RenderAutoConstraintMenu();
                        break;

                    case 1:
                        bool oldAutoConstraintSelection = autoConstraintSelection.boolValue;
                        autoConstraintSelection.boolValue = false;
                        bool newAutoConstraintSelection = autoConstraintSelection.boolValue;

                        // manual constraint selection was enabled
                        if (newAutoConstraintSelection == false && oldAutoConstraintSelection != newAutoConstraintSelection)
                        {
                            // manual selection is active and manual list is empty -> auto populate with
                            // existing constraints so user has a base to work on
                            if (selectedConstraints.arraySize == 0)
                            {
                                var constraints = constraintManager.gameObject.GetComponents <TransformConstraint>();
                                foreach (var constraint in constraints)
                                {
                                    int currentId = selectedConstraints.arraySize;
                                    selectedConstraints.InsertArrayElementAtIndex(currentId);
                                    selectedConstraints.GetArrayElementAtIndex(currentId).objectReferenceValue = constraint;
                                }
                            }
                        }

                        RenderManualConstraintMenu();
                        break;
                    }

                    // we render the instance id of this component so our highlighting function can distinguish between
                    // the different instances of constraint manager - highlighting in the inspector is currently
                    // only available for string search which causes problems with multiple components of the same type
                    // attached to the same gameobject.
                    EditorGUILayout.Space();
                    EditorGUILayout.LabelField("ComponentId: " + constraintManager.GetInstanceID(), EditorStyles.miniLabel);

                    // deferred delete elements from array to not break unity layout
                    for (int i = indicesToRemove.Count - 1; i > -1; i--)
                    {
                        var currentArraySize = selectedConstraints.arraySize;
                        selectedConstraints.DeleteArrayElementAtIndex(indicesToRemove[i]);
                        if (currentArraySize == selectedConstraints.arraySize)
                        {
                            selectedConstraints.DeleteArrayElementAtIndex(indicesToRemove[i]);
                        }
                    }

                    indicesToRemove.Clear();

                    if (check.changed)
                    {
                        serializedObject.ApplyModifiedProperties();
                    }
                }
            }
        }