/// <summary> /// Finds the script node by the specified expression at the specified category and its children. /// </summary> private static ScriptData FindScriptData(CategoryData category, FindExpression findExpression) { foreach (ScriptData scriptData in category.Items) { if (findExpression(scriptData)) { return(scriptData); } if (scriptData is CategoryData) { ScriptData data = FindScriptData((CategoryData)scriptData, findExpression); if (data != null) { return(data); } } } return(null); }
/// <summary> /// Creates the category on the specified path from the specified category. /// </summary> private CategoryData CreateCategory(CategoryData baseCategory, string[] path, int level) { // end of path if (level >= path.Length) { return(baseCategory); } // try to find existing category foreach (ScriptData baseNode in baseCategory.Items) { CategoryData category = baseNode as CategoryData; // category found if (category != null && category.Name == path[level]) { // move to the next level return(CreateCategory(category, path, level + 1)); } } // create remaining category path CategoryData lastCategory = baseCategory; for (int i = level; i < path.Length; ++i) { // new category CategoryData newCategory = new CategoryData(); newCategory.Name = path[i]; // add new category to last category lastCategory.Items.Add(newCategory); // set new as last category lastCategory = newCategory; } return(lastCategory); }
/// <summary> /// Creates the tree representing all scripting nodes. /// </summary> /// <param name="treeNodes">Collection where to store scripting nodes.</param> /// <param name="category">The category of scripting nodes.</param> private void CreateTreeOfScriptingNodes(TreeNodeCollection treeNodes, CategoryData category) { foreach (ScriptData baseNode in category.Items) { // category CategoryData cat = baseNode as CategoryData; if (cat != null) { TreeNode newCategoryNode = new TreeNode(cat.Name) { Tag = null }; treeNodes.Add(newCategoryNode); CreateTreeOfScriptingNodes(newCategoryNode.Nodes, cat); continue; } // node NodeData node = baseNode as NodeData; if (node != null) { Node guiNode = (Node) new Node(null, node); treeNodes.Add(new TreeNode(guiNode.Name) { Tag = guiNode }); continue; } throw new Exception(); } }
/// <summary> /// Loads all scripting data and stores them sorted at the tree structure. /// </summary> private void CreateRoot() { root = new CategoryData(); bool isAction, isEvent; foreach (Type type in typeof(GameEngine.Scripting.ScriptNode).Assembly.GetTypes()) { isAction = isEvent = false; if (type.IsSubclassOf(typeof(GameEngine.Scripting.Actions.ActionNode))) { isAction = true; } else if (type.IsSubclassOf(typeof(GameEngine.Scripting.Events.EventNode))) { isEvent = true; } // get all subclasses from ActionNode or EventNode if ((isAction || isEvent) && !type.IsAbstract && type.IsPublic) { // script node (event or action) NodeData scriptNode = new NodeData(); scriptNode.Name = GetFriendlyName(type, type.Name); scriptNode.RealName = type.FullName; scriptNode.Description = GetDescription(type); scriptNode.Type = isAction ? NodeType.Action : NodeType.Event; // add script node to the correct category CreateCategory(root, GetCategory(type)).Items.Add(scriptNode); // get all public non-static fields from class foreach (FieldInfo fieldInfo in type.GetFields(BindingFlags.Public | BindingFlags.Instance)) { // variable socket is an array of generic class GameEngine.Variable<T> // or generic variable GameEngine.Variable<T> if ((fieldInfo.FieldType.IsArray && fieldInfo.FieldType.HasElementType && fieldInfo.FieldType.GetElementType().IsGenericType&& fieldInfo.FieldType.GetElementType().GetGenericTypeDefinition() == typeof(GameEngine.Scripting.Variable <>)) || (fieldInfo.FieldType.IsGenericType && fieldInfo.FieldType.GetGenericTypeDefinition() == typeof(GameEngine.Scripting.Variable <>))) { // get argument for GameEngine.Variable<T> Type[] arguments = fieldInfo.FieldType.IsArray ? fieldInfo.FieldType.GetElementType().GetGenericArguments() : fieldInfo.FieldType.GetGenericArguments(); if (arguments != null && arguments.Length == 1) { // try to get VariableSocketTypeAttribute GameEngine.Scripting.VariableSocketAttribute variableSocketAttribute = (GameEngine.Scripting.VariableSocketAttribute)Attribute.GetCustomAttribute(fieldInfo, typeof(GameEngine.Scripting.VariableSocketAttribute)); if (variableSocketAttribute != null) { // variable socket NodeSocketData variableSocket = new NodeSocketData(); variableSocket.Name = GetFriendlyName(fieldInfo, fieldInfo.Name); variableSocket.RealName = fieldInfo.Name; variableSocket.Description = GetDescription(fieldInfo); variableSocket.Type = variableSocketAttribute.Type == GameEngine.Scripting.VariableSocketType.In ? NodeSocketType.VariableIn : NodeSocketType.VariableOut; variableSocket.VariableType = VariableTypeHelper.FromType(arguments[0]); variableSocket.IsArray = fieldInfo.FieldType.IsArray; variableSocket.DefaultValue = GetDefaultValue(fieldInfo); variableSocket.Visible = variableSocketAttribute.Visible; variableSocket.CanBeEmpty = variableSocketAttribute.CanBeEmpty; // variable out socket must be an array if (variableSocket.Type == NodeSocketType.VariableOut && !variableSocket.IsArray) { continue; } scriptNode.Sockets.Add(variableSocket); } } } // signal out socket is ScriptSocketHandler delegate else if (fieldInfo.FieldType.IsSubclassOf(typeof(Delegate)) && fieldInfo.FieldType == typeof(GameEngine.Scripting.ScriptSocketHandler)) { // signal out socket NodeSocketData signalOutSocket = new NodeSocketData(); signalOutSocket.Name = GetFriendlyName(fieldInfo, fieldInfo.Name); signalOutSocket.RealName = fieldInfo.Name; signalOutSocket.Description = GetDescription(fieldInfo); signalOutSocket.Type = NodeSocketType.SignalOut; scriptNode.Sockets.Add(signalOutSocket); } } // get all public non-static method from class foreach (MethodInfo methodInfo in type.GetMethods(BindingFlags.Public | BindingFlags.Instance)) { // signal in socket is method with none parameter, returns void, // is defined in script node (event or action, not base classes) and it is not Update and Connect method (from event) if (methodInfo.GetParameters().Length == 0 && methodInfo.ReturnType == typeof(void) && methodInfo.Name != "Update" && methodInfo.Name != "Connect") { // signal in socket NodeSocketData signalInSocket = new NodeSocketData(); signalInSocket.Name = GetFriendlyName(methodInfo, methodInfo.Name); signalInSocket.RealName = methodInfo.Name; signalInSocket.Description = GetDescription(methodInfo); signalInSocket.Type = NodeSocketType.SignalIn; scriptNode.Sockets.Add(signalInSocket); } } } } SortCategory(root); }