public static void FetchBehaviourNodes()
        {
            behaviourNodes = new Dictionary <Type, NodeTypeProperties>();

            IEnumerable <Type> behaviourTypes = AppDomain.CurrentDomain.GetAssemblies()
                                                .Where(asm => !asm.FullName.StartsWith("Unity") && !asm.FullName.Contains("Editor"))
                                                .Where(asm => !asm.FullName.StartsWith("BonsaiTestsAssembly")) // Ignore nodes from test suite.
                                                .SelectMany(asm => asm.GetTypes())
                                                .Where(t => t.IsSubclassOf(typeof(BTNode)) && !t.IsAbstract);

            foreach (Type type in behaviourTypes)
            {
                var nodeMeta = type.GetCustomAttribute <BTNodeAttribute>(false);

                // Default menu path if unspecified.
                string menuPath = "User/";

                // Service base class is abstract. For Service types, default to Service texture.
                string texName = typeof(BTService).IsAssignableFrom(type) ? "Service" : "Play";

                if (nodeMeta != null)
                {
                    if (!string.IsNullOrEmpty(nodeMeta.menuPath))
                    {
                        menuPath = nodeMeta.menuPath;
                    }

                    // Texxture names are optional. Use only if specified.
                    if (!string.IsNullOrEmpty(nodeMeta.texturePath))
                    {
                        texName = nodeMeta.texturePath;
                    }
                }

                // Only composites and decorators have outputs.
                bool hasOutput = !type.IsSubclassOf(typeof(Task));

                menuPath += type.Name;
                var prop = new NodeTypeProperties(menuPath, texName, hasOutput);

                behaviourNodes.Add(type, prop);
            }
        }
Esempio n. 2
0
        public static void FetchBehaviourNodes()
        {
            _behaviourNodes = new Dictionary <Type, NodeTypeProperties>();

            IEnumerable <Assembly> scriptAssemblies = AppDomain.CurrentDomain.GetAssemblies().
                                                      Where((Assembly assembly) => assembly.FullName.Contains("Assembly") &&
                                                            !assembly.FullName.Contains("Editor"));

            Type targetType = typeof(BehaviourNode);

            foreach (Assembly assembly in scriptAssemblies)
            {
                foreach (Type type in assembly.GetTypes()
                         .Where(T => T.IsClass &&
                                !T.IsAbstract &&
                                T.IsSubclassOf(targetType)))
                {
                    object[] nodeProperties = type.GetCustomAttributes(typeof(NodeEditorPropertiesAttribute), false);

                    // The attribute is to simply get custom data about the node.
                    // Like menu path and texture.
                    NodeEditorPropertiesAttribute attrib = null;
                    if (nodeProperties.Length > 0)
                    {
                        attrib = nodeProperties[0] as NodeEditorPropertiesAttribute;
                    }

                    string menuPath = "Uncategorized/";
                    string texName  = "Play";

                    if (attrib != null)
                    {
                        menuPath = attrib.menuPath;
                        texName  = attrib.textureName;
                    }

                    bool bCreateInput             = false;
                    bool bCreateOutput            = false;
                    bool bCanHaveMultipleChildren = false;

                    // Only action nodes have an input and no output.
                    if (type.IsSubclassOf(typeof(Task)))
                    {
                        bCreateInput = true;
                    }

                    // Composites and decorators have in and out.
                    else
                    {
                        bCreateInput  = true;
                        bCreateOutput = true;

                        // Only composites can have more than 1 child.
                        if (type.IsSubclassOf(typeof(Composite)))
                        {
                            bCanHaveMultipleChildren = true;
                        }
                    }

                    menuPath += type.Name;
                    var prop = new NodeTypeProperties(menuPath, texName, bCreateInput, bCreateOutput, bCanHaveMultipleChildren);

                    _behaviourNodes.Add(type, prop);
                }
            }
        }