static string GetMethodSignatureString(BTTask task)
        {
            var parameterArray = task.i_parameters;
            // expected method signature
            string sign = "void" + " " + task.taskName + "(";

            if (parameterArray != null)
            {
                for (int p = 0; p < parameterArray.Length; ++p)
                {
                    sign += " " + parameterArray[p].GetType().ToString();

                    sign += " p" + p.ToString();

                    if (p + 1 < parameterArray.Length)
                    {
                        sign += ",";
                    }
                }
                sign += " ";
            }
            sign += ")";
            sign  = sign.Replace("System.Single", "float");
            sign  = sign.Replace("System.Int32", "int");
            sign  = sign.Replace("System.Boolean", "bool");
            sign  = sign.Replace("System.String", "string");
            return(sign);
        }
        static bool Locate(BehaviourTree behaviourTree, BTTask task, out string path, out int line)
        {
            bool found = false;

            path = null;
            line = 0;
            var program = behaviourTree.program;

            for (int c = 0; c < program.codemaps.Length; c++)
            {
                var cm = program.codemaps[c];
                for (int i = 0; i < cm.nodes.Length; i++)
                {
                    if (cm.nodes[i] == task)
                    {
                        path  = behaviourTree.btSources[c].url;
                        line  = cm.substringLocations[i].line;
                        found = true;
                        break;
                    }
                }

                if (found)
                {
                    break;
                }
            }

            return(found);
        }
        private void GUI_token(GUIStyle style, BTNode node, BTLTokenizer.Token token)
        {
            var label = token.content.Replace("\t", "   ");

            if (clickedTask != null && clickedTaskFade < Time.realtimeSinceStartup)
            {
                clickedTask = null;
            }


#if UNITY_EDITOR
            var task = node as BTTask;

            if (task != null && task.boundState != BoundState.Bound)
            {
                style = BTLSyntaxHighlight.style_failed;
            }

            if (task != null && task.boundState == BoundState.Bound && token.type == BTLTokenizer.TokenType.Word)
            {
                if (GUILayout.Button(label, style) && Event.current.button == 0)
                {
                    if (clickedTask == task)
                    {
                        GUIBTScript.OpenScript(task.boundObject as MonoBehaviour, task.boundMember);
                    }

                    clickedTask     = task;
                    clickedTaskFade = Time.realtimeSinceStartup + 0.5f;
                }
            }
            else
            {
                GUILayout.Label(label, style);
            }
#else
            GUILayout.Label(label, style);
#endif
        }
 void InitRendering()
 {
     clickedTask     = null;
     clickedTaskFade = Time.realtimeSinceStartup - 1.0f;
 }
        public bool IsMatch(BTTask task)
        {
            if (task.name != memberInfo.Name)
            {
                return(false);
            }

            bool itIs = true;



            var method   = memberInfo as MethodInfo;
            var field    = memberInfo as FieldInfo;
            var property = memberInfo as PropertyInfo;


            if (method != null)
            {
                var thisTypes  = parameterTypes;
                var otherTypes = task.parameterTypes;
                if (thisTypes.Length == otherTypes.Length)
                {
                    for (int i = 0; i < thisTypes.Length; i++)
                    {
                        if (thisTypes[i].IsEnum && otherTypes[i] == typeof(EnumParameter))
                        {
                            EnumParameter enumParameter = (EnumParameter)task.parameters[i];
                            itIs = enumParameter.Matches(thisTypes[i]);
                        }
                        else
                        if (thisTypes[i] != otherTypes[i])
                        {
                            itIs = false;
                            break;
                        }
                    }
                }
                else
                {
                    itIs = false;
                }
            }
            else
            if (field != null)
            {
                if (field.FieldType != typeof(bool))
                {
                    itIs = false;
                }
            }
            else
            {
                if (field != null && property.PropertyType != typeof(bool))
                {
                    if (property.PropertyType != typeof(bool))
                    {
                        itIs = false;
                    }
                }
            }

            return(itIs);
        }
        static BTTree[] Build(BTLParser.Node[] trees, out CodeMap codemap, bool createCodeMap)
        {
            var           codeMapDict = new Dictionary <BTNode, SubstringLocation>();
            List <BTTree> roots       = new List <BTTree>();

            BTTree root = null;
            // Get all nodes
            var parseNodes = BTLParser.GetNodes(trees);

            var nodeID = new Dictionary <BTLParser.Node, int>();

            for (int i = 0; i < parseNodes.Length; ++i)
            {
                nodeID[parseNodes[i]] = i;
            }


            // create nodes
            var nodes = new BTNode[parseNodes.Length];

            foreach (var n in parseNodes)
            {
                int id = nodeID[n];

                switch (n.token.type)
                {
                case TokenType.Tree:
                    var newRoot = new BTTree();

                    if (n.parameters.Count > 0)
                    {
                        newRoot.name = n.parsedParameters[0] as string;
                    }

                    nodes[id] = newRoot;
                    root      = newRoot;
                    roots.Add(root);

                    break;

                case TokenType.TreeProxy:
                    var rootProxy = new BTTreeProxy();

                    if (n.parameters.Count > 0)
                    {
                        rootProxy.name = n.parsedParameters[0] as string;
                    }

                    nodes[id] = rootProxy;

                    break;


                case TokenType.Value:
                case TokenType.Word:

                    var task = new BTTask();
                    task.taskName = n.token.content.Trim();

                    nodes[id] = task;

                    break;

                case TokenType.Mute:
                    nodes[id] = new BTMute();
                    break;

                case TokenType.Not:
                    nodes[id] = new BTNot();
                    break;

                case TokenType.Repeat:
                    nodes[id] = new BTRepeat();
                    break;

                case TokenType.Fallback:        nodes[id] = new BTFallback(); break;

                case TokenType.Sequence:        nodes[id] = new BTSequence(); break;

                case TokenType.Parallel:        nodes[id] = new BTParallel(); break;

                case TokenType.While:   nodes[id] = new BTWhile(); break;

                case TokenType.Race: nodes[id] = new BTRace(); break;

                case TokenType.Random: nodes[id] = new BTRandom(); break;
                }



                if (nodes[id] != null)
                {
                    nodes[id].i_parameters = n.parsedParameters;
                }

                if (nodes[id] != null)
                {
                    var loc = new SubstringLocation();
                    loc.line   = n.token.line;
                    loc.start  = n.token.substring_start;
                    loc.length = n.token.substring_length;

                    if (n.parameters.Count > 0)
                    {
                        loc.length = n.parseLength;
                    }

                    codeMapDict[nodes[id]] = loc;
                }
            }


            // parenting
            foreach (var n in parseNodes)
            {
                int pid    = nodeID[n];
                var parent = nodes[pid];
                if (parent != null)
                {
                    foreach (var c in n.children)
                    {
                        int cid   = nodeID[c];
                        var child = nodes[cid];
                        if (child != null)
                        {
                            parent.AddChild(child);
                        }
                    }
                }
            }

            if (roots.Count > 0)
            {
                root = roots[0];
            }

            if (createCodeMap)
            {
                codemap = new CodeMap(codeMapDict);
            }
            else
            {
                codemap = null;
            }


            return(roots.ToArray());
        }
        static bool Bind(BTTask task, TaskImplementation implementation)
        {
            bool bindingSucceeded = false;

            var member          = implementation.memberInfo;
            var taskImplementer = implementation.target;

            MethodInfo   method   = member as MethodInfo;
            FieldInfo    field    = member as FieldInfo;
            PropertyInfo property = member as PropertyInfo;

            System.Action taskAction = null;
            if (method != null)
            {
                object[] parameters       = new object[task.i_parameters.Length];
                var      methodParameters = method.GetParameters();
                for (int i = 0; i < parameters.Length; i++)
                {
                    var enumParameter = task.i_parameters[i] as EnumParameter;
                    if (enumParameter != null)
                    {
                        parameters[i] = enumParameter.Parse(methodParameters[i].ParameterType);
                    }
                    else
                    {
                        parameters[i] = task.i_parameters[i];
                    }
                }

                if (method.ReturnType == typeof(void))
                {
                    if (parameters.Length > 0)
                    {
                        taskAction = () => method.Invoke(taskImplementer, parameters);
                    }
                    else
                    {
                        taskAction = System.Delegate.CreateDelegate(typeof(System.Action), taskImplementer, method) as System.Action;
                    }
                }

                if (method.ReturnType == typeof(bool))
                {
                    if (parameters.Length > 0)
                    {
                        taskAction = () => Task.current.Complete((bool)method.Invoke(taskImplementer, parameters));
                    }
                    else
                    {
                        var del = System.Delegate.CreateDelegate(typeof(System.Func <bool>), taskImplementer, method) as System.Func <bool>;
                        taskAction = () => Task.current.Complete(del());
                    }
                }
            }

            if (field != null)
            {
                taskAction = () => Task.current.Complete((bool)field.GetValue(taskImplementer));
            }

            if (property != null)
            {
                taskAction = () => Task.current.Complete((bool)property.GetValue(taskImplementer, null));
            }

            if (taskAction != null)
            {
                task.m_boundObject = taskImplementer;
                task.m_boundMember = member;
                task.m_taskAction  = taskAction;
                task.m_boundState  = BoundState.Bound;

                bindingSucceeded = true;
            }

            return(bindingSucceeded);
        }