private Texture GetIcon(AutoPopulateAttribute autoPopulate, bool populated)
        {
            Texture foundIcon   = null;
            Texture missingIcon = null;

            switch (autoPopulate.Find)
            {
            case AutoPopulateAttribute.FindBehaviour.Self:
                foundIcon   = FindSelfIcon;
                missingIcon = MissingSelfIcon;
                break;

            case AutoPopulateAttribute.FindBehaviour.Children:
                foundIcon   = FindChildrenIcon;
                missingIcon = MissingChildrenIcon;
                break;

            case AutoPopulateAttribute.FindBehaviour.Parent:
                foundIcon   = FindParentsIcon;
                missingIcon = MissingParentsIcon;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
            if (populated)
            {
                return(foundIcon);
            }
            return(missingIcon);
        }
        private bool CanAutoPopulate(SerializedProperty property, AutoPopulateAttribute autoPopulate)
        {
            if (autoPopulate == null)
            {
                return(false);
            }
            if (property.isArray)
            {
                return(false); // Disable array support for now,
                // Unity doesn't call the drawer for the array, it calls it for the elements in the array :(
            }
            if (property.propertyPath.EndsWith("]"))
            {
                return(false); // as above, we use the ] char as a sign that Unity is trying to edit an array element
            }

            if (property.propertyType == SerializedPropertyType.ObjectReference)
            {
                return(true);
            }

            if (AutoPopulateUtils.IsInterfaceReference(property, fieldInfo.FieldType))
            {
                return(true);
            }

            return(false);
        }
        public static void AutoPopulate(SerializedObject so, bool forceRepopulate = false, IErrorReport report = null)
        {
            SerializedProperty prop = so.GetIterator();

            if (prop.hasChildren)
            {
                while (prop.Next(true))
                {
                    FieldInfo fieldInfo = PropertyUtils.GetFieldInfoFromProperty(prop);
                    if (fieldInfo != null)
                    {
                        AutoPopulateAttribute attribute = GetAutoPopulateAttribute(fieldInfo);
                        if (attribute != null)
                        {
                            bool needsPopulating = NeedsPopulating(prop, fieldInfo.FieldType);
                            if (forceRepopulate || needsPopulating)
                            {
                                if (report != null)
                                {
                                    report.Log(so.targetObject, "Repopulating {0}.{1}", so.targetObject.FullName(), prop.propertyPath);
                                }
                                PopulateValue(fieldInfo.FieldType, prop, attribute);
                            }
                            else
                            {
                                if (report != null)
                                {
                                    report.Log(so.targetObject, "Skipping {0}.{1}", so.targetObject.FullName(), prop.propertyPath);
                                }
                            }
                        }
                    }
                }
            }
        }
 private static AutoPopulateAttribute GetAutoPopulateAttribute(FieldInfo fieldInfo)
 {
     object[] attribs = fieldInfo.GetCustomAttributes(typeof(AutoPopulateAttribute), true);
     if (attribs != null && attribs.Length > 0)
     {
         AutoPopulateAttribute attribute = attribs[0] as AutoPopulateAttribute;
         return(attribute);
     }
     return(null);
 }
        private void ForceRepopulate(object data)
        {
            SerializedProperty property = data as SerializedProperty;

            AutoPopulateAttribute autoPopulate = attribute as AutoPopulateAttribute;

            if ((property != null) && (autoPopulate != null))
            {
                property.serializedObject.Update();
                AutoPopulateUtils.PopulateValue(fieldInfo.FieldType, property, autoPopulate);
                property.serializedObject.ApplyModifiedProperties();
            }
        }
        private void HandlePopup(Rect position, SerializedProperty property, AutoPopulateAttribute autoPopulate)
        {
            Event e = Event.current;

            if ((e.type == EventType.MouseUp) && (e.button == 1))
            {
                if (position.Contains(e.mousePosition))
                {
                    bool editable          = false;
                    bool canChangeEditable = false;

                    switch (autoPopulate.Editable)
                    {
                    case AutoPopulateAttribute.EditBehaviour.ReadOnlyUntilUserAction:
                        editable          = GetEditable(property, autoPopulate);
                        canChangeEditable = true;
                        break;

                    case AutoPopulateAttribute.EditBehaviour.Never:
                        editable          = false;
                        canChangeEditable = false;
                        break;

                    case AutoPopulateAttribute.EditBehaviour.Always:
                        editable          = true;
                        canChangeEditable = false;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }

                    GUI.FocusControl(null);
                    GenericMenu menu = new GenericMenu();

                    if (editable)
                    {
                        menu.AddItem(MakeReadonlyLabel, false, canChangeEditable ? MakeReadonly : (GenericMenu.MenuFunction2)null, property);
                    }
                    else
                    {
                        menu.AddItem(MakeEditableLabel, false, canChangeEditable ? MakeEditable : (GenericMenu.MenuFunction2)null, property);
                    }
                    menu.AddItem(ForceRepopulateLabel, false, ForceRepopulate, property);
                    menu.ShowAsContext();
                    e.Use();
                }
            }
        }
        public static Type GetSearchType(Type fieldType, AutoPopulateAttribute autoPopulate)
        {
            Type searchType = fieldType;

            Type interfaceType = InterfaceReferenceDrawer.GetInterfaceType(searchType);

            if (interfaceType != null)
            {
                searchType = interfaceType;
            }

            if (autoPopulate.TypeOverride != null)
            {
                searchType = autoPopulate.TypeOverride;
            }
            return(searchType);
        }
        private string GetTooltip(SerializedProperty property, AutoPopulateAttribute autoPopulate)
        {
            Type searchType;

            if (property.isArray)
            {
                searchType = AutoPopulateUtils.GetSearchType(fieldInfo.FieldType.GetElementType(), autoPopulate);
            }
            else
            {
                searchType = AutoPopulateUtils.GetSearchType(fieldInfo.FieldType, autoPopulate);
            }
            string relativeTo = "";

            if (autoPopulate.FindRelativeTo != null)
            {
                string componentName = autoPopulate.FindRelativeTo.Name;
                string componentArticle;
                if (IsVowel(componentName[0]))
                {
                    componentArticle = "an";
                }
                else
                {
                    componentArticle = "a";
                }

                relativeTo = string.Format(" on the first parent with {0} {1} component", componentArticle, autoPopulate.FindRelativeTo.Name);
            }
            switch (autoPopulate.Find)
            {
            case AutoPopulateAttribute.FindBehaviour.Self:
                return(string.Format("Auto-populated by calling gameObject.GetComponent({0}){1}", searchType.Name, relativeTo));

            case AutoPopulateAttribute.FindBehaviour.Children:
                return(string.Format("Auto-populated by calling gameObject.GetComponentInChildren({0}){1}", searchType.Name, relativeTo));

            case AutoPopulateAttribute.FindBehaviour.Parent:
                return(string.Format("Auto-populated by calling gameObject.GetComponentInParent({0}){1}", searchType.Name, relativeTo));

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            AutoPopulateAttribute autoPopulate = attribute as AutoPopulateAttribute;

            if (CanAutoPopulate(property, autoPopulate))
            {
                bool wasEnabled = GUI.enabled;
                GUI.enabled = GetEditable(property, autoPopulate);

                bool populated = false;

                if (AutoPopulateUtils.NeedsPopulating(property, fieldInfo.FieldType))
                {
                    populated = AutoPopulateUtils.PopulateValue(fieldInfo.FieldType, property, autoPopulate);
                }
                else
                {
                    populated = true;
                }

                GUIContent tweakedLabel = new GUIContent(label.text, GetIcon(autoPopulate, populated), GetTooltip(property, autoPopulate));

                if (AutoPopulateUtils.IsInterfaceReference(property, fieldInfo.FieldType))
                {
                    InterfaceReferenceDrawer.PropertyField(position, property, fieldInfo, tweakedLabel);
                }
                else
                {
                    EditorGUI.PropertyField(position, property, tweakedLabel);
                }

                GUI.enabled = wasEnabled;
                HandlePopup(position, property, autoPopulate);
            }
            else
            {
                GUIContent tweakedLabel = new GUIContent(label.text, ErrorIcon, GetErrorTooltip());
                EditorGUI.PropertyField(position, property, tweakedLabel);
            }
        }
        private bool GetEditable(SerializedProperty property, AutoPopulateAttribute autoPopulate)
        {
            bool editable = true;

            switch (autoPopulate.Editable)
            {
            case AutoPopulateAttribute.EditBehaviour.ReadOnlyUntilUserAction:
                editable = GetEditableInstance(property);
                break;

            case AutoPopulateAttribute.EditBehaviour.Never:
                editable = false;
                break;

            case AutoPopulateAttribute.EditBehaviour.Always:
                editable = true;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
            return(editable);
        }
Exemplo n.º 11
0
        private static bool PopulateValueSingle(Type fieldType, SerializedProperty property, AutoPopulateAttribute autoPopulate)
        {
            Object value      = null;
            Type   searchType = GetSearchType(fieldType, autoPopulate);

            foreach (Object targetObject in property.serializedObject.targetObjects)
            {
                MonoBehaviour behaviour = targetObject as MonoBehaviour;

                if (behaviour == null)
                {
                    XDebug.LogWarning(targetObject, "Couldn't find target behaviour on {0}.", targetObject);
                    continue;
                }

                SerializedObject   singleObject   = new SerializedObject(targetObject);
                SerializedProperty singleProperty = singleObject.FindProperty(property.propertyPath);

                if (singleProperty == null)
                {
                    XDebug.LogWarning(behaviour, "Couldn't find {0} property for {1}", property.propertyPath, behaviour);
                    continue;
                }

                Transform root = FindRoot(behaviour.gameObject, autoPopulate.FindRelativeTo);

                if (root == null)
                {
                    continue;
                }

                switch (autoPopulate.Find)
                {
                case AutoPopulateAttribute.FindBehaviour.Self:
                    value = FindObjectInSelf(root, searchType);
                    break;

                case AutoPopulateAttribute.FindBehaviour.Children:
                    value = FindObjectInChildren(root, searchType);
                    break;

                case AutoPopulateAttribute.FindBehaviour.Parent:
                    value = FindObjectInParent(root, searchType);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                SetValue(singleProperty, fieldType, value);
                singleObject.ApplyModifiedProperties();
            }

            if (value != null)
            {
                property.serializedObject.SetIsDifferentCacheDirty();
            }

            return(value != null);
        }
Exemplo n.º 12
0
        private static bool PopulateValueArray(Type fieldType, SerializedProperty property, AutoPopulateAttribute autoPopulate)
        {
            Object[] values      = null;
            Type     elementType = fieldType.GetElementType();
            Type     searchType  = GetSearchType(elementType, autoPopulate);

            foreach (Object targetObject in property.serializedObject.targetObjects)
            {
                MonoBehaviour behaviour = targetObject as MonoBehaviour;

                if (behaviour == null)
                {
                    XDebug.LogWarning(targetObject, "Couldn't find target behaviour on {0}.", targetObject);
                    continue;
                }

                SerializedObject   singleObject   = new SerializedObject(targetObject);
                SerializedProperty singleProperty = singleObject.FindProperty(property.propertyPath);

                if (singleProperty == null)
                {
                    XDebug.LogWarning(behaviour, "Couldn't find {0} property for {1}", property.propertyPath, behaviour);
                    continue;
                }

                Transform root = FindRoot(behaviour.gameObject, autoPopulate.FindRelativeTo);

                if (root == null)
                {
                    XDebug.LogWarning(behaviour, "Couldn't find root object for {0}.", behaviour.gameObject);
                    continue;
                }

                switch (autoPopulate.Find)
                {
                case AutoPopulateAttribute.FindBehaviour.Self:
                    values = FindObjectsInSelf(root, searchType);
                    break;

                case AutoPopulateAttribute.FindBehaviour.Children:
                    values = FindObjectsInChildren(root, searchType);
                    break;

                case AutoPopulateAttribute.FindBehaviour.Parent:
                    values = FindObjectsInParent(root, searchType);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                singleProperty.arraySize = values.Length;
                for (int i = 0; i < values.Length; i++)
                {
                    SerializedProperty element = singleProperty.GetArrayElementAtIndex(i);
                    SetValue(element, elementType, values[i]);
                    element.objectReferenceValue = values[i];
                }
                singleObject.ApplyModifiedProperties();
            }

            if (values != null && values.Length > 0)
            {
                property.serializedObject.SetIsDifferentCacheDirty();
            }

            return(values != null && values.Length > 0);
        }
Exemplo n.º 13
0
        public static bool PopulateValue(Type fieldType, SerializedProperty property, AutoPopulateAttribute autoPopulate)
        {
            bool populated = false;

            if (!property.hasMultipleDifferentValues)
            {
                if (property.isArray)
                {
                    populated = PopulateValueArray(fieldType, property, autoPopulate);
                }
                else if (property.propertyType == SerializedPropertyType.ObjectReference || IsInterfaceReference(property, fieldType))
                {
                    populated = PopulateValueSingle(fieldType, property, autoPopulate);
                }
            }
            return(populated);
        }