Exemplo n.º 1
0
    /// <summary>
    /// Links a inspector-accessible field to the appropriate value, if possible.
    /// </summary>
    /// <param name="field">The field to set.</param>
    /// <param name="script">The script on which to set the field.</param>
    void RunAutolinking(FieldInfo field, MonoBehaviour script)
    {
        foreach (Attribute a in System.Attribute.GetCustomAttributes(field))
        {
            if (a is AutoLinkAttribute)
            {
                //do autolinking

                AutoLinkAttribute autolinkInfo = (AutoLinkAttribute)a;

                //check if autolinking is valid first
                if (checkExistingLinkValid(field, script, autolinkInfo))
                {
                    return;
                }

                Transform[] parentNodes;

                if (!String.IsNullOrEmpty(autolinkInfo.parentTag))
                {
                    //grab by tag first
                    if (autolinkInfo.parentTag != Tags.untagged)
                    {
                        parentNodes = Array.ConvertAll <GameObject, Transform>(GameObject.FindGameObjectsWithTag(autolinkInfo.parentTag), o => o.transform);
                    }
                    else
                    {
                        //we can't find untagged objects by tag, but we can compare to check if an object is untagged
                        parentNodes = (FindObjectsOfType(typeof(Transform)) as Transform[]).Where(t => t.CompareTag(autolinkInfo.parentTag)).ToArray();
                    }
                    if (!String.IsNullOrEmpty(autolinkInfo.parentName))
                    {
                        //filter by name
                        parentNodes = parentNodes.Where(t => t.name == autolinkInfo.parentName).ToArray();
                    }
                    if (!String.IsNullOrEmpty(autolinkInfo.childPath))
                    {
                        //map to children
                        parentNodes = Array.ConvertAll <Transform, Transform>(parentNodes, t => t.Find(autolinkInfo.childPath));
                        parentNodes = parentNodes.Where(t => t != null).ToArray(); //remove null values
                    }
                }
                else
                {
                    //check that the other two tags aren't empty first
                    if (String.IsNullOrEmpty(autolinkInfo.parentName))
                    {
                        if (String.IsNullOrEmpty(autolinkInfo.childPath))
                        {
                            //if every tag is empty, then we'll limit the search to the local transform
                            Component possibleMatch = script.GetComponentInChildren(field.FieldType);
                            if (possibleMatch != null)
                            {
                                field.SetValue(script, possibleMatch);
                                UnityEditor.EditorUtility.SetDirty(script);
                                return;
                            }
                            else
                            {
                                continue;
                            }
                        }
                        else
                        {
                            //if only the path is given, use the script's parent as the parent node
                            Transform parent = script.transform.Find(autolinkInfo.childPath);
                            if (parent != null)
                            {
                                Type type = field.FieldType;
                                UnityEngine.Object possibleMatch;
                                if (type == typeof(Transform))
                                {
                                    possibleMatch = parent;
                                }
                                else if (type == typeof(GameObject))
                                {
                                    possibleMatch = parent.gameObject;
                                }
                                else
                                {
                                    possibleMatch = parent.GetComponent(type);
                                }

                                if (possibleMatch != null)
                                {
                                    field.SetValue(script, possibleMatch);
                                    UnityEditor.EditorUtility.SetDirty(script);
                                    return;
                                }
                            }
                            continue;
                        }
                    }
                    else
                    {
                        //start with the universal set of all Transforms; there is no way to get the array of matching names, then filter by name
                        parentNodes = (FindObjectsOfType(typeof(Transform)) as Transform[]).Where(t => t.name == autolinkInfo.parentName).ToArray();
                        if (!String.IsNullOrEmpty(autolinkInfo.childPath))
                        {
                            //map to children
                            parentNodes = Array.ConvertAll <Transform, Transform>(parentNodes, t => t.Find(autolinkInfo.childPath));
                            parentNodes = parentNodes.Where(t => t != null).ToArray(); //remove null values
                        }
                    }
                }
                //use the parent nodes to try to find
                foreach (Transform t in parentNodes)
                {
                    Type type = field.FieldType;
                    UnityEngine.Object possibleMatch;
                    if (type == typeof(Transform))
                    {
                        possibleMatch = t;
                    }
                    else if (type == typeof(GameObject))
                    {
                        possibleMatch = t.gameObject;
                    }
                    else
                    {
                        possibleMatch = t.GetComponent(type);
                    }
                    if (possibleMatch != null)
                    {
                        field.SetValue(script, possibleMatch);
                        UnityEditor.EditorUtility.SetDirty(script);
                        return;
                    }
                }
            }
        }
        //if nothing gets autolinked, then the checkNull/Empty functionality will catch it
    }
Exemplo n.º 2
0
    /// <summary>
    /// Determines if an autolinked attribute has a valid link.
    /// </summary>
    /// <param name="field">The field to check.</param>
    /// <param name="script">The script on which to check the field.</param>
    /// <param name="autolinkInfo">The data included in the field's [AutoLink].</param>
    /// <returns><c>True</c> if the link is valid; otherwise, <c>False</c>.</returns>
    bool checkExistingLinkValid(FieldInfo field, MonoBehaviour script, AutoLinkAttribute autolinkInfo)
    {
        var value = field.GetValue(script);

        if (value == null || value.Equals(null)) //GameObjects being null aren't really null, so need to use equals as well
        {
            return(false);
        }

        Assert.IsTrue(value is Component || value is GameObject, "AutoLink can only link components");

        //if the value could be valid, we have to find the link between it and the parent

        if (String.IsNullOrEmpty(autolinkInfo.childPath))
        {
            //check if all three fields are empty first
            if (String.IsNullOrEmpty(autolinkInfo.parentTag) && String.IsNullOrEmpty(autolinkInfo.parentName))
            {
                //if so, then validation is trivial
                return(value.Equals(script.GetComponentInChildren(value.GetType())));
            }

            //if not we're at least dealing only with the local parent
            Transform valueTransfrom;
            Component testComponent = value as Component;
            if (testComponent != null)
            {
                valueTransfrom = testComponent.transform;
            }
            else
            {
                valueTransfrom = ((GameObject)value).transform;
            }
            if (!String.IsNullOrEmpty(autolinkInfo.parentName) && valueTransfrom.name != autolinkInfo.parentName)
            {
                return(false); //check parent name is the same
            }
            if (!String.IsNullOrEmpty(autolinkInfo.parentTag) && !valueTransfrom.CompareTag(autolinkInfo.parentTag))
            {
                return(false); //check parent tag is the same
            }
            return(true);
        }
        else
        {
            // else we need to traverse up the tree to find the parent
            //obtain transform
            Transform currentParent;
            Component testComponent = value as Component;
            if (testComponent != null)
            {
                currentParent = testComponent.transform;
            }
            else
            {
                currentParent = ((GameObject)value).transform;
            }
            String[] parentNames = autolinkInfo.childPath.Split(new char[] { '/' });
            for (int i = parentNames.Length - 1; i >= 0; i--) //iterate backwards, since it's a path down the hierarchy tree
            {
                if (parentNames[i] != currentParent.name)
                {
                    return(false);
                }
                currentParent = currentParent.parent;
            }

            //current parent should now be the parent node of the tree, if it is correct

            if (!String.IsNullOrEmpty(autolinkInfo.parentName))
            {
                if (!String.IsNullOrEmpty(autolinkInfo.parentTag) && !currentParent.CompareTag(autolinkInfo.parentTag))
                {
                    return(false);
                }
                return(currentParent.name == autolinkInfo.parentName);
            }
            else if (!String.IsNullOrEmpty(autolinkInfo.parentTag))
            {
                return(currentParent.CompareTag(autolinkInfo.parentTag));
            }
            else
            {
                //if only the path is given, parent node should be the same as script's parent
                return(currentParent.Equals(script.transform));
            }
        }
    }
Exemplo n.º 3
0
    /// <summary>
    /// Determines if an autolinked attribute has a valid link.
    /// </summary>
    /// <param name="field">The field to check.</param>
    /// <param name="script">The script on which to check the field.</param>
    /// <param name="autolinkInfo">The data included in the field's [AutoLink].</param>
    /// <returns><c>True</c> if the link is valid; otherwise, <c>False</c>.</returns>
    bool checkExistingLinkValid(FieldInfo field, MonoBehaviour script, AutoLinkAttribute autolinkInfo)
    {
        var value = field.GetValue(script);
        if (value == null || value.Equals(null)) //GameObjects being null aren't really null, so need to use equals as well
            return false;

        Assert.IsTrue(value is Component || value is GameObject, "AutoLink can only link components");

        //if the value could be valid, we have to find the link between it and the parent

        if (String.IsNullOrEmpty(autolinkInfo.childPath))
        {
            //check if all three fields are empty first
            if (String.IsNullOrEmpty(autolinkInfo.parentTag) && String.IsNullOrEmpty(autolinkInfo.parentName))
            {
                //if so, then validation is trivial
                return value.Equals(script.GetComponentInChildren(value.GetType()));
            }

            //if not we're at least dealing only with the local parent
            Transform valueTransfrom;
            Component testComponent = value as Component;
            if (testComponent != null)
                valueTransfrom = testComponent.transform;
            else
                valueTransfrom = ((GameObject)value).transform;
            if (!String.IsNullOrEmpty(autolinkInfo.parentName) && valueTransfrom.name != autolinkInfo.parentName)
                return false; //check parent name is the same
            if (!String.IsNullOrEmpty(autolinkInfo.parentTag) && !valueTransfrom.CompareTag(autolinkInfo.parentTag))
                return false; //check parent tag is the same
            return true;
        }
        else
        {
            // else we need to traverse up the tree to find the parent
            //obtain transform
            Transform currentParent;
            Component testComponent = value as Component;
            if (testComponent != null)
                currentParent = testComponent.transform;
            else
                currentParent = ((GameObject)value).transform;
            String[] parentNames = autolinkInfo.childPath.Split(new char[] {'/'});
            for (int i = parentNames.Length - 1; i >= 0; i--) //iterate backwards, since it's a path down the hierarchy tree
            {
                if (parentNames[i] != currentParent.name)
                    return false;
                currentParent = currentParent.parent;
            }

            //current parent should now be the parent node of the tree, if it is correct

            if (!String.IsNullOrEmpty(autolinkInfo.parentName))
            {
                if (!String.IsNullOrEmpty(autolinkInfo.parentTag) && !currentParent.CompareTag(autolinkInfo.parentTag))
                    return false;
                return currentParent.name == autolinkInfo.parentName;
            }
            else if (!String.IsNullOrEmpty(autolinkInfo.parentTag))
            {
                return currentParent.CompareTag(autolinkInfo.parentTag);
            }
            else
            {
                //if only the path is given, parent node should be the same as script's parent
                return currentParent.Equals(script.transform);
            }
        }
    }