コード例 #1
0
        ///Refletion nodes on a type
        public static UnityEditor.GenericMenu AppendTypeReflectionNodesMenu(this FlowGraph graph, UnityEditor.GenericMenu menu, System.Type type, string baseCategory, Vector2 pos, Port sourcePort, object dropInstance)
        {
            if (!string.IsNullOrEmpty(baseCategory))
            {
                baseCategory += "/";
            }

            var typeCategory = baseCategory + type.FriendlyName();

            var icon = UserTypePrefs.GetTypeIcon(type);

            if (type.IsValueType && !type.IsPrimitive)
            {
                if (sourcePort == null || (sourcePort is ValueOutput && type.IsAssignableFrom(sourcePort.type)))
                {
                    var extractName = string.Format("Extract {0}", type.FriendlyName());
                    menu.AddItem(new GUIContent(typeCategory + "/" + extractName, icon, null), false, () => { graph.AddReflectedExtractorNode(type, pos, sourcePort, dropInstance); });
                }
            }

            if (sourcePort is ValueInput)
            {
                if (sourcePort.type == type)
                {
                    var portValue = (sourcePort as ValueInput).serializedValue;
                    menu.AddItem(new GUIContent("Make Constant Variable", icon, null), false, (o) => { graph.AddVariableGet((System.Type)o, null, pos, sourcePort, portValue); }, type);
                    menu.AddItem(new GUIContent("Make Linked Variable", icon, null), false, (o) =>
                    {
                        var bbVar = graph.blackboard.AddVariable(sourcePort.name, sourcePort.type);
                        graph.AddVariableGet((System.Type)o, bbVar.name, pos, sourcePort, portValue);
                    }, type);
                    menu.AddSeparator("/");
                }
            }


            //Constructors
            if (!type.IsAbstract && !type.IsInterface && !type.IsPrimitive && type != typeof(string))
            {
                foreach (var _c in type.RTGetConstructors())
                {
                    var c = _c;
                    if (!c.IsPublic || c.IsObsolete())
                    {
                        continue;
                    }

                    if (sourcePort is FlowInput || sourcePort is FlowOutput)
                    {
                        continue;
                    }

                    var parameters = c.GetParameters();
                    if (sourcePort is ValueOutput)
                    {
                        if (!parameters.Any(p => p.ParameterType.IsAssignableFrom(sourcePort.type)))
                        {
                            continue;
                        }
                    }

                    if (sourcePort is ValueInput)
                    {
                        if (!sourcePort.type.IsAssignableFrom(type))
                        {
                            continue;
                        }
                    }

                    var categoryName = typeCategory + "/" + "Constructors/";
                    var name         = categoryName + c.SignatureName();

                    if (typeof(Component).IsAssignableFrom(type))
                    {
                        if (type == typeof(Transform))
                        {
                            continue;
                        }
                        var stubType = typeof(AddComponent <>).MakeGenericType(type);
                        menu.AddItem(new GUIContent(name, icon, null), false, () => { graph.AddSimplexNode(stubType, pos, sourcePort, dropInstance); });
                        continue;
                    }

                    if (typeof(ScriptableObject).IsAssignableFrom(type))
                    {
                        var stubType = typeof(NewScriptableObject <>).MakeGenericType(type);
                        menu.AddItem(new GUIContent(name, icon, null), false, () => { graph.AddSimplexNode(stubType, pos, sourcePort, dropInstance); });
                        continue;
                    }

                    //exclude types like Mathf, Random, Time etc (they are not static)
                    if (!UserTypePrefs.functionalTypesBlacklist.Contains(type))
                    {
                        menu.AddItem(new GUIContent(name, icon, null), false, (o) => { graph.AddContructorNode((ConstructorInfo)o, pos, sourcePort, dropInstance); }, c);
                    }
                }
            }

            //Methods
            var methods = type.RTGetMethods().ToList();

            methods.AddRange(type.GetExtensionMethods());
            foreach (var _m in methods.OrderBy(_m => !_m.IsStatic).OrderBy(_m => _m.GetMethodSpecialType()).OrderBy(_m => _m.DeclaringType != type))
            {
                var m = _m;
                if (!m.IsPublic || m.IsObsolete())
                {
                    continue;
                }

                //convertions are handled automatically at a connection level
                if (m.Name == "op_Implicit" || m.Name == "op_Explicit")
                {
                    continue;
                }

                var isGeneric = m.IsGenericMethod && m.GetGenericArguments().Length == 1;
                if (isGeneric)
                {
                    if (sourcePort != null && sourcePort.IsValuePort())
                    {
                        if (m.CanBeMadeGenericWith(sourcePort.type))
                        {
                            m = m.MakeGenericMethod(sourcePort.type);
                        }
                        else
                        {
                            continue;
                        }
                    }
                }

                var parameters = m.GetParameters();
                if (sourcePort is ValueOutput)
                {
                    if (type != sourcePort.type || m.IsStatic)
                    {
                        if (!parameters.Any(p => p.ParameterType.IsAssignableFrom(sourcePort.type)))
                        {
                            continue;
                        }
                    }
                }

                if (sourcePort is ValueInput)
                {
                    if (!sourcePort.type.IsAssignableFrom(m.ReturnType) && !parameters.Any(p => p.IsOut && sourcePort.type.IsAssignableFrom(p.ParameterType)))
                    {
                        continue;
                    }
                }

                if (sourcePort is FlowInput || sourcePort is FlowOutput)
                {
                    if (m.ReturnType != typeof(void))
                    {
                        continue;
                    }
                }

                var categoryName  = typeCategory;
                var signatureName = m.SignatureName();
                var specialType   = m.GetMethodSpecialType();
                if (specialType == ReflectionTools.MethodType.Normal)
                {
                    categoryName += "/Methods/";
                }
                if (specialType == ReflectionTools.MethodType.PropertyAccessor)
                {
                    categoryName += "/Properties/";
                }
                if (specialType == ReflectionTools.MethodType.Operator)
                {
                    categoryName += "/Operators/";
                }
                if (specialType == ReflectionTools.MethodType.Event)
                {
                    categoryName += "/Events/";
                }

                //Unity Event special case
                if (typeof(UnityEventBase).IsAssignableFrom(m.ReturnType) && specialType == ReflectionTools.MethodType.PropertyAccessor)
                {
                    categoryName = typeCategory + "/Events/";
                }

                var isExtension = m.IsExtensionMethod();
                if (m.DeclaringType != type)
                {
                    categoryName += isExtension? "Extensions/" : "Inherited/";
                }
                var name = categoryName + signatureName;
                menu.AddItem(new GUIContent(name, icon, null), false, (o) => { graph.AddMethodNode((MethodInfo)o, pos, sourcePort, dropInstance); }, m);
            }

            //Fields
            foreach (var _f in type.RTGetFields())
            {
                var f = _f;
                if (!f.IsPublic || f.IsObsolete())
                {
                    continue;
                }

                var isReadOnly = f.IsReadOnly();
                var isConstant = f.IsConstant();

                if (sourcePort is ValueOutput)
                {
                    if (type != sourcePort.type || isConstant)
                    {
                        if (isReadOnly || !f.FieldType.IsAssignableFrom(sourcePort.type))
                        {
                            continue;
                        }
                    }
                }

                if (sourcePort is ValueInput)
                {
                    if (!sourcePort.type.IsAssignableFrom(f.FieldType))
                    {
                        continue;
                    }
                }

                var isUnityEvent = typeof(UnityEventBase).IsAssignableFrom(f.FieldType);
                var categoryName = typeCategory + (isUnityEvent? "/Events/" :  "/Fields/");
                if (f.DeclaringType != type)
                {
                    categoryName += "Inherited/";
                }

                //Unity Event
                if (isUnityEvent)
                {
                    menu.AddItem(new GUIContent(categoryName + f.Name + " (Auto Subscribe)", icon, null), false, (o) => { graph.AddUnityEventAutoCallbackNode((FieldInfo)o, pos, sourcePort, dropInstance); }, f);
                    menu.AddItem(new GUIContent(categoryName + f.Name + " (Get Reference)", icon, null), false, (o) => { graph.AddFieldGetNode((FieldInfo)o, pos, sourcePort, dropInstance); }, f);
                    continue;
                }

                var nameForGet = categoryName + (isConstant? "constant " + f.Name : "Get " + f.Name);
                menu.AddItem(new GUIContent(nameForGet, icon, null), false, (o) => { graph.AddFieldGetNode((FieldInfo)o, pos, sourcePort, dropInstance); }, f);

                if (!isReadOnly)
                {
                    var nameForSet = categoryName + "Set " + f.Name;
                    menu.AddItem(new GUIContent(nameForSet, icon, null), false, (o) => { graph.AddFieldSetNode((FieldInfo)o, pos, sourcePort, dropInstance); }, f);
                }
            }


            //C# Events
            foreach (var _info in type.RTGetEvents())
            {
                var info         = _info;
                var categoryName = typeCategory + "/Events/";
                menu.AddItem(new GUIContent(categoryName + info.Name + " (Auto Subscribe)", icon), false, (o) => { graph.AddCSharpEventAutoCallbackNode((EventInfo)o, pos, sourcePort, dropInstance); }, info);
                menu.AddItem(new GUIContent(categoryName + info.Name + " (Get Reference)", icon), false, (o) => { graph.AddCSharpGetNode((EventInfo)o, pos, sourcePort, dropInstance); }, info);
            }

            return(menu);
        }