示例#1
0
    /// <summary>
    /// Finds a list of memberinfo objects that form a property path. Returns null if no matching path could be found.
    /// </summary>
    public static MemberInfo[] FindPropertyPath(Type startingPoint, string propertyPath)
    {
        string key = startingPoint.FullName + ":" + propertyPath;

        if (propertyPathCache.ContainsKey(key))
        {
            return(propertyPathCache [key]);
        }

        string[] propertyNames = propertyPath.Split('.');
        var      referenceType = startingPoint;

        MemberInfo[] result = new MemberInfo[propertyNames.Length];
        int          index  = 0;

        foreach (var propertyName in propertyNames)
        {
            var matches = referenceType.GetMember(propertyName, MemberTypes.Field | MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance);
            if (matches.Length == 1)
            {
                result[index] = matches[0];
                referenceType = UTInternalCall.GetMemberType(matches[0]);
            }
            else
            {
                result = null;
                break;
            }
            index++;
        }

        propertyPathCache.Add(key, result);
        return(result);
    }
示例#2
0
    /// <summary>
    /// Finds the components annotated with the given annotations. Components are instanciated and returned as keys
    /// of the result dictionary. The values of the result dictionary contain the respective annotations which identified
    /// the components.
    /// </summary>
    /// <returns>
    /// The components annotated with the given annotation type.
    /// </returns>
    /// <typeparam name='ExpectedType'>
    /// The expected type of the components.
    /// </typeparam>
    /// <typeparam name='AnnotationType'>
    /// The annotation identifying the components.
    /// </typeparam>
    public static Dictionary <ExpectedType, AnnotationType> FindComponentsAnnotatedWith <ExpectedType, AnnotationType> ()
    {
        Dictionary <ExpectedType, AnnotationType> result = new Dictionary <ExpectedType, AnnotationType> ();
        var referencedAssemblies = (Assembly[])UTInternalCall.GetStatic("UnityEditor.EditorAssemblies", "loadedAssemblies");

        foreach (var referencedAssembly in referencedAssemblies)
        {
            var allTypes = referencedAssembly.GetTypes();
            foreach (var theType in allTypes)
            {
                var attrs = theType.GetCustomAttributes(typeof(AnnotationType), false);
                if (attrs.Length == 1)
                {
                    if (!theType.IsSubclassOf(typeof(ExpectedType)) && theType.GetInterface(typeof(ExpectedType).Name) == null)
                    {
                        Debug.LogWarning("Class " + theType.FullName + " is not a subclass/implementation of " + typeof(ExpectedType).FullName + ". Ignoring it.");
                        continue;
                    }
                    ExpectedType theInstance = (ExpectedType)Activator.CreateInstance(theType);
                    result.Add(theInstance, (AnnotationType)attrs [0]);
                }
            }
        }
        return(result);
    }
示例#3
0
    /// <summary>
    /// Finds all visible assets of the given type.
    /// </summary>
    public static List <T> AllVisibleAssetsOfType <T> () where T : ScriptableObject
    {
        List <T> result = new List <T> ();

        object filteredHierarchy = CreateFilteredHierarchy();

#if UNITY_3_5
        UTInternalCall.Set(filteredHierarchy, "filter", typeof(T).Name);
        UTInternalCall.Set(filteredHierarchy, "searchMode", UTInternalCall.EnumValue("UnityEditor.FilteredHierarchy+SearchMode", "Type"));
#else
        var searchFilter = UTInternalCall.InvokeStatic("UnityEditor.SearchableEditorWindow", "CreateFilter", typeof(T).Name, UTInternalCall.EnumValue("UnityEditor.SearchableEditorWindow+SearchMode", "Type"));
        UTInternalCall.Set(filteredHierarchy, "searchFilter", searchFilter);
#endif
        var hierarchyProperty = UTInternalCall.InvokeStatic("UnityEditor.FilteredHierarchyProperty", "CreateHierarchyPropertyForFilter", filteredHierarchy);

        var emptyIntArray = new int[0];
        while ((bool)UTInternalCall.Invoke(hierarchyProperty, "Next", emptyIntArray))
        {
            var instanceId = (int)UTInternalCall.Get(hierarchyProperty, "instanceID");
            var path       = AssetDatabase.GetAssetPath(instanceId);
            T   t          = AssetDatabase.LoadAssetAtPath(path, typeof(T)) as T;
            if (t != null)
            {
                result.Add(t);
            }
        }

        return(result);
    }
    private void BuildMenu(GenericMenu menu, Type type, string itemVisiblePath, string itemInternalPath, bool addSelf, int depth, GenericMenu.MenuFunction2 function)
    {
        if (addSelf)
        {
            menu.AddItem(new GUIContent(itemVisiblePath + "/" + type.Name), false, function, itemInternalPath);
        }
        var members = UTComponentScanner.FindPublicWritableMembersOf(type);

        foreach (var memberInfo in members.MemberInfos)
        {
            var newInternalPath = string.IsNullOrEmpty(itemInternalPath) ? memberInfo.Name : itemInternalPath + "." + memberInfo.Name;
            var newVisiblePath  = string.IsNullOrEmpty(itemVisiblePath) ? memberInfo.Name : itemVisiblePath + "/" + memberInfo.Name;
            if (memberInfo.DeclaringType != typeof(Component))
            {
                var memberInfoType = UTInternalCall.GetMemberType(memberInfo);
                if (UTInternalCall.HasMembers(memberInfoType) && depth < 2)
                {
                    BuildMenu(menu, memberInfoType, newVisiblePath, newInternalPath, UTInternalCall.IsWritable(memberInfo), depth + 1, function);
                }
                else
                {
                    menu.AddItem(new GUIContent(newVisiblePath), false, function, newInternalPath);
                }
            }
        }
    }
    public void Render(UTFieldWrapper fieldWrapper)
    {
        Type baseType        = fieldWrapper.InspectorHint.baseType;
        var  compatibleTypes = UTComponentScanner.FindCompatibleTypes(baseType);

        var val          = (UTMemberInfo)fieldWrapper.Value;
        int currentIndex = -1;

        if (val != null)
        {
            currentIndex = Array.IndexOf(compatibleTypes.TypeNames, val.TypeName);
        }
        EditorGUILayout.BeginVertical();
        int newIndex = -1;

        if (fieldWrapper.Label != null)
        {
            newIndex = EditorGUILayout.Popup(fieldWrapper.Label, currentIndex, compatibleTypes.NicifiedTypeNames);
        }
        else
        {
            newIndex = EditorGUILayout.Popup(currentIndex, compatibleTypes.NicifiedTypeNames);
        }

        if (currentIndex != newIndex)
        {
            if (newIndex == -1)
            {
                fieldWrapper.Value = null;
                val = null;
            }
            else
            {
                var    type            = UTInternalCall.GetType(compatibleTypes.TypeNames [newIndex]);
                var    writableMembers = UTComponentScanner.FindPublicWritableMembersOf(type);
                string propertyPath    = null;
                if (writableMembers.MemberInfos.Length > 0)
                {
                    propertyPath = writableMembers.MemberInfos[0].Name;
                }
                val = new UTMemberInfo(type.FullName, propertyPath);
                fieldWrapper.Value = val;
            }
        }

        GUI.enabled = val != null && !string.IsNullOrEmpty(val.TypeName);
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.PrefixLabel(" ");
        if (GUILayout.Button(val.FieldPath, EditorStyles.popup))
        {
            var genericMenu = BuildMenu(val.Type, val.SetFieldPath);
            genericMenu.ShowAsContext();
        }
        EditorGUILayout.EndHorizontal();
        GUI.enabled = true;

        EditorGUILayout.EndVertical();
    }
示例#6
0
 private static object CreateFilteredHierarchy()
 {
     if (filteredHierarchy == null)
     {
         filteredHierarchy = UTInternalCall.CreateInstance("UnityEditor.FilteredHierarchy", HierarchyType.Assets);
     }
     UTInternalCall.Invoke(filteredHierarchy, "ResultsChanged");
     return(filteredHierarchy);
 }
示例#7
0
    /// <summary>
    /// Evaluate the specified input and replaces all known placeholders. Placeholders can be written as
    /// $foo.bar or optionally $(foo.bar) in case the first notation is ambiguous.
    ///
    /// You can write arbitrary JavaScript expressions like:
    ///
    /// 2 + 2  (yields 4)
    /// '2' + '2' (yields '22')
    /// '2' == '2' (yields true)
    ///  etc..
    ///
    /// Please note that properties can have different types and casting/transformation is not performed
    /// automatically. E.g. If the property "foo" has the value "2" (as a string) $foo * 2 will yield "22"
    /// because it is a string. If you want to have the numeric value use parseInt($foo) * 2 (will yield 4).
    ///
    /// </summary>
    /// <param name='input'>
    /// The input string.
    /// </param>
    public object Evaluate(string input)
    {
        var replaced = Regex.Replace(input, PlaceholderRegexp, "context['$1']");

        try {
            // we call this via reflection because we cannot reference unityscript stuff directly
            return(UTInternalCall.InvokeStatic("UTEval", "Evaluate", replaced, this));
        } catch (Exception e) {
            throw new UTFailBuildException("Unparseable expression: '" + input + "' " + e.Message, null);              // no experiments.
        }
    }
示例#8
0
    public static void Init()
    {
        var window = EditorWindow.GetWindow <UTMainWindow> (
#if UTOMATE_DEMO
            "uTomate Demo",
#else
            "uTomate",
#endif
            UTInternalCall.GetType("UnityEditor.InspectorWindow"));

        window.minSize = new Vector2(400, 250);
    }
示例#9
0
    public static UTMemberListResult FindPublicWritableMembersOf(Type type)
    {
        if (memberListCache.ContainsKey(type))
        {
            return(memberListCache [type]);
        }

        var allMembers            = UTInternalCall.PublicMembersOf(type);
        UTMemberListResult result = new UTMemberListResult(Array.FindAll(allMembers, item => UTInternalCall.IsWritable(item)));

        memberListCache.Add(type, result);
        return(result);
    }
    public override IEnumerator Execute(UTContext context)
    {
        UDebug.LogWarning("This action is experimental and might break.", this);

        bool connError = (bool)UTInternalCall.InvokeStatic("UnityEditor.AssetServer", "HasConnectionError");

        if (connError)
        {
            throw new UTFailBuildException("Currently unable to connect to the asset server.", this);
        }

        UDebug.Log("Not working properly...");
        throw new UTFailBuildException("Not implemented.", this);

        /*
         * UDebug.Log("Starting update...");
         * Process process = new Process();
         * process.StartInfo.FileName = GetEditorExecutable();
         * process.StartInfo.Arguments = "-batchMode -assetServerUpdate " + string.Join(" ", new string[] {assetServerLocation, projectOnAssetServer, username, password});
         * process.StartInfo.RedirectStandardOutput = true;
         * process.StartInfo.UseShellExecute = false;
         * process.OutputDataReceived += (sender, args) => UDebug.Log("[Unity]"+ args.Data);
         * try {
         *      process.Start();
         *                      process.BeginOutputReadLine();
         * process.WaitForExit();
         * if (process.ExitCode != 0) {
         *      UDebug.LogError("Update failed.");
         *      return false;
         * }
         *
         * }
         * catch(Win32Exception e) {
         *      UDebug.LogError("Couldn't start process: " + e.Message);
         *      return false;
         * }
         * return true;*/
    }
    public override UTVisibilityDecision IsVisible(System.Reflection.FieldInfo fieldInfo)
    {
        if (fieldInfo.Name == "gameObject" || fieldInfo.Name == "property")
        {
            return(base.IsVisible(fieldInfo));
        }

        // only expression field if the type is not clear
        var self = (UTSetComponentPropertyAction)target;

        if (self.property.UseExpression || !self.property.Value.FullyDefined)
        {
            if (fieldInfo.Name == "objectPropertyValue")
            {
                return(UTVisibilityDecision.Visible);
            }
            return(UTVisibilityDecision.Invisible);
        }

        // only expression field if the property is not valid anymore
        var propertyPath = UTComponentScanner.FindPropertyPath(self.property.Value.Type, self.property.Value.FieldPath);

        if (propertyPath == null)
        {
            if (fieldInfo.Name == "objectPropertyValue")
            {
                return(UTVisibilityDecision.Visible);
            }
            return(UTVisibilityDecision.Invisible);
        }

        Type   propertyType = UTInternalCall.GetMemberType(propertyPath[propertyPath.Length - 1]);
        string expectedPropertyFieldName = "objectPropertyValue";

        if (typeof(string).IsAssignableFrom(propertyType))
        {
            expectedPropertyFieldName = "stringPropertyValue";
        }
        else if (typeof(bool).IsAssignableFrom(propertyType))
        {
            expectedPropertyFieldName = "boolPropertyValue";
        }
        else if (typeof(int).IsAssignableFrom(propertyType))
        {
            expectedPropertyFieldName = "intPropertyValue";
        }
        else if (typeof(float).IsAssignableFrom(propertyType))
        {
            expectedPropertyFieldName = "floatPropertyValue";
        }
        else if (typeof(Texture).IsAssignableFrom(propertyType))
        {
            expectedPropertyFieldName = "texturePropertyValue";
        }
        else if (typeof(Vector3).IsAssignableFrom(propertyType))
        {
            expectedPropertyFieldName = "vector3PropertyValue";
        }
        else if (typeof(Vector2).IsAssignableFrom(propertyType))
        {
            expectedPropertyFieldName = "vector2PropertyValue";
        }
        else if (typeof(Rect).IsAssignableFrom(propertyType))
        {
            expectedPropertyFieldName = "rectPropertyValue";
        }
        else if (typeof(Quaternion).IsAssignableFrom(propertyType))
        {
            expectedPropertyFieldName = "quaternionPropertyValue";
        }
        else if (typeof(Material).IsAssignableFrom(propertyType))
        {
            expectedPropertyFieldName = "materialPropertyValue";
        }
        else if (typeof(Color).IsAssignableFrom(propertyType))
        {
            expectedPropertyFieldName = "colorPropertyValue";
        }
        else if (typeof(GameObject).IsAssignableFrom(propertyType))
        {
            expectedPropertyFieldName = "gameObjectPropertyValue";
        }
        else if (typeof(UObject).IsAssignableFrom(propertyType))
        {
            expectedPropertyFieldName = "unityObjectPropertyValue";
        }

        if (fieldInfo.Name == expectedPropertyFieldName)
        {
            return(UTVisibilityDecision.Visible);
        }

        return(UTVisibilityDecision.Invisible);
    }
    public override IEnumerator Execute(UTContext context)
    {
        var theGameObject = gameObject.EvaluateIn(context);

        if (theGameObject == null)
        {
            throw new UTFailBuildException("You must specify the game object htat holds the component.", this);
        }

        var theProperty = property.EvaluateIn(context);

        if (theProperty == null || !theProperty.FullyDefined)
        {
            throw new UTFailBuildException("You must specify the component type and its property you want to change.", this);
        }

        var propertyPath = UTComponentScanner.FindPropertyPath(theProperty.Type, theProperty.FieldPath);

        if (propertyPath == null)
        {
            throw new UTFailBuildException("The component type or the property path is no longer valid.", this);
        }

        var theComponent = theGameObject.GetComponent(theProperty.Type);

        if (theComponent == null)
        {
            // nothing to do
            if (UTPreferences.DebugMode)
            {
                Debug.Log("Component " + theProperty.Type.Name + " not found at game object " + theGameObject, this);
            }
        }
        else
        {
            Type   propertyType = UTInternalCall.GetMemberType(propertyPath[propertyPath.Length - 1]);
            object propertyValue;
            if (typeof(string).IsAssignableFrom(propertyType))
            {
                propertyValue = stringPropertyValue.EvaluateIn(context);
            }
            else if (typeof(bool).IsAssignableFrom(propertyType))
            {
                propertyValue = boolPropertyValue.EvaluateIn(context);
            }
            else if (typeof(int).IsAssignableFrom(propertyType))
            {
                propertyValue = intPropertyValue.EvaluateIn(context);
            }
            else if (typeof(float).IsAssignableFrom(propertyType))
            {
                propertyValue = floatPropertyValue.EvaluateIn(context);
            }
            else if (typeof(Texture).IsAssignableFrom(propertyType))
            {
                propertyValue = texturePropertyValue.EvaluateIn(context);
            }
            else if (typeof(Vector3).IsAssignableFrom(propertyType))
            {
                propertyValue = vector3PropertyValue.EvaluateIn(context);
            }
            else if (typeof(Vector2).IsAssignableFrom(propertyType))
            {
                propertyValue = vector2PropertyValue.EvaluateIn(context);
            }
            else if (typeof(Rect).IsAssignableFrom(propertyType))
            {
                propertyValue = rectPropertyValue.EvaluateIn(context);
            }
            else if (typeof(Quaternion).IsAssignableFrom(propertyType))
            {
                propertyValue = quaternionPropertyValue.EvaluateIn(context);
            }
            else if (typeof(Material).IsAssignableFrom(propertyType))
            {
                propertyValue = materialPropertyValue.EvaluateIn(context);
            }
            else if (typeof(Color).IsAssignableFrom(propertyType))
            {
                propertyValue = colorPropertyValue.EvaluateIn(context);
            }
            else if (typeof(GameObject).IsAssignableFrom(propertyType))
            {
                propertyValue = gameObjectPropertyValue.EvaluateIn(context);
            }
            else if (typeof(UObject).IsAssignableFrom(propertyType))
            {
                propertyValue = unityObjectPropertyValue.EvaluateIn(context);
            }
            else
            {
                propertyValue = objectPropertyValue.EvaluateIn(context);
            }

            // TODO: we need a lot more validation here.
            // e.g. is the value assignable?

            // Tested with Vector3 -> BoxCollider:center
            // and float -> BoxCollider:center.y
            UTInternalCall.SetMemberValue(theComponent, propertyPath, propertyValue);
        }
        yield return("");
    }
示例#13
0
 /// <summary>
 /// Hides the async progress bar.
 /// </summary>
 public static void ClearAsyncProgressBar()
 {
     UTInternalCall.InvokeStatic("UnityEditor.AsyncProgressBar", "Clear");
 }
示例#14
0
 /// <summary>
 /// Shows an async progress bar in the lower right corner of Unity's window (like the one shown when
 /// rendering lightmaps).
 /// </summary>
 /// <param name='text'>
 /// Text to show.
 /// </param>
 /// <param name='progress'>
 /// Progress to show (anything between 0f and 1f)
 /// </param>
 public static void ShowAsyncProgressBar(string text, float progress)
 {
     UTInternalCall.InvokeStatic("UnityEditor.AsyncProgressBar", "Display", text, progress);
 }
示例#15
0
 /// <summary>
 /// Clears Unity's console.
 /// </summary>
 public static void ClearConsole()
 {
     UTInternalCall.InvokeStatic("UnityEditorInternal.LogEntries", "Clear");
 }
示例#16
0
 /// <summary>
 /// Checks if the build pipeline supports the given build target.
 /// </summary>
 public static bool IsBuildTargetSupported(BuildTarget target)
 {
     return((bool)UTInternalCall.InvokeStatic("UnityEditor.BuildPipeline", "IsBuildTargetSupported", target));
 }