/// <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(); } } } }