public static void Show(SerializedProperty prop, List <MonoBehaviour> monos) { if (monos == null || monos.Count == 0 || prop == null) { return; } InterfacePicker picker = GetWindow <InterfacePicker>(true); picker._propertyPath = prop.propertyPath; picker._target = prop.serializedObject.targetObject; picker._monoInspectors?.ForEach((mi) => mi.Destroy()); picker._monoInspectors = new List <MonoInspector>(); picker.titleContent = new GUIContent(monos[0].gameObject.name); monos.ForEach((m) => picker._monoInspectors.Add(new MonoInspector(m))); picker.ShowUtility(); }
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { if (property.serializedObject.isEditingMultipleObjects) { return; } if (property.propertyType != SerializedPropertyType.ObjectReference) { EditorGUI.LabelField(position, label.text, "InterfaceType Attribute can only be used with MonoBehaviour Components."); return; } EditorGUI.BeginProperty(position, label, property); Type[] attTypes = GetInterfaceTypes(property); // Pick a specific component MonoBehaviour oldComponent = property.objectReferenceValue as MonoBehaviour; string oldComponentName = ""; GameObject temporaryGameObject = null; string attTypesName = GetTypesName(attTypes); if (Event.current.type == EventType.Repaint) { if (oldComponent == null) { temporaryGameObject = new GameObject("None (" + attTypesName + ")"); oldComponent = temporaryGameObject.AddComponent <InterfaceMono>(); } else { oldComponentName = oldComponent.name; oldComponent.name = oldComponentName + " (" + attTypesName + ")"; } } Component currentComponent = EditorGUI.ObjectField(position, label, oldComponent, typeof(Component), true) as Component; MonoBehaviour currentMono = currentComponent as MonoBehaviour; if (Event.current.type == EventType.Repaint) { if (temporaryGameObject != null) { GameObject.DestroyImmediate(temporaryGameObject); } else { oldComponent.name = oldComponentName; } } // If a component is assigned, make sure it is the interface we are looking for. if (currentMono != null) { // Make sure component is of the right interface if (!IsAssignableFromTypes(currentMono.GetType(), attTypes)) { // Component failed. Check game object. foreach (Type attType in attTypes) { currentMono = currentMono.gameObject.GetComponent(attType) as MonoBehaviour; if (currentMono == null) { break; } } } // Item failed test. Do not override old component if (currentMono == null) { if (oldComponent != null && !IsAssignableFromTypes(oldComponent.GetType(), attTypes)) { temporaryGameObject = new GameObject("None (" + attTypesName + ")"); MonoBehaviour temporaryComponent = temporaryGameObject.AddComponent <InterfaceMono>(); currentMono = EditorGUI.ObjectField(position, label, temporaryComponent, typeof(MonoBehaviour), true) as MonoBehaviour; GameObject.DestroyImmediate(temporaryGameObject); } } } else if (currentComponent is Transform) { // If assigned component is a Transform, this means a GameObject was dragged into the property field. // Find all matching components on the transform's GameObject and open the picker window. List <MonoBehaviour> monos = new List <MonoBehaviour>(); monos.AddRange(currentComponent.gameObject.GetComponents <MonoBehaviour>(). Where((mono) => IsAssignableFromTypes(mono.GetType(), attTypes))); if (monos.Count > 1) { EditorApplication.delayCall += () => InterfacePicker.Show(property, monos); } else { currentMono = monos.Count == 1 ? monos[0] : null; } } if (currentComponent == null || currentMono != null) { property.objectReferenceValue = currentMono; } EditorGUI.EndProperty(); }