private string SerializeNode(BehaviorNodeControl node)
        {
            EditorCachedNode data = node.GetData();

            string id       = m_indexTable[node];;
            string position = string.Format("{0},{1}", node.Position.x, node.Position.y);
            string type     = data.type.ToString();
            string attribs  = "";
            string children = "";

            for (int i = 0; i < data.fields.Length; i++)
            {
                if (i > 0)
                {
                    attribs += " ";
                }

                attribs += SerializeAttribute(node, data.fields[i]);
            }

            if (node.m_outputs.Count > 0)
            {
                children = "outputs=\"";
            }

            for (int i = 0; i < node.m_outputs.Count; i++)
            {
                if (i > 0)
                {
                    children += ",";
                }

                children += m_indexTable[node.m_outputs[i]];
            }

            if (node.m_outputs.Count > 0)
            {
                children += "\"";
            }

            return(string.Format(NODE_TEMPLATE, id, position, type, attribs, children));;
        }
        private BehaviorNodeControl DeserializeNode(XmlNode xml, EditorNodeTypeCache typeCache, out string nodeId, out List <string> childIds)
        {
            childIds = new List <string>();

            nodeId = xml.Attributes["id"].InnerText;
            string type = xml.Attributes["type"].InnerText;

            string[] posStr   = xml.Attributes["position"].InnerText.Split(',');
            Vector2  position = new Vector2(float.Parse(posStr[0]), float.Parse(posStr[1]));

            if (xml.Attributes["outputs"] != null)
            {
                childIds.AddRange(xml.Attributes["outputs"].InnerText.Split(','));
            }

            bool             found = false;
            EditorCachedNode data  = default(EditorCachedNode);

            foreach (EditorCachedNode cachedType in typeCache.Cache)
            {
                if (cachedType.type.ToString() == type)
                {
                    found = true;
                    data  = cachedType;
                    break;
                }
            }

            if (!found)
            {
                return(null);
            }

            BehaviorNodeControl control = new BehaviorNodeControl(data);

            control.SetPosition(position);
            DeserializeFields(xml, data, control);

            return(control);
        }
        public BehaviorNodeControl(EditorCachedNode node)
        {
            m_fieldControls = new Dictionary <string, Control>();
            m_node          = node;

            int lines = 0;

            foreach (EditorCachedNodeField field in node.fields)
            {
                Control fieldControl = null;
                int     l            = 0;

                // Create fields per type
                if (field.type == typeof(int))
                {
                    fieldControl = AddChild(new IntField(default(int), field.name));
                    l            = 1;
                }
                else if (field.type == typeof(float))
                {
                    fieldControl = AddChild(new FloatField(default(float), field.name));
                    l            = 1;
                }
                else if (field.type == typeof(Vector2))
                {
                    fieldControl = AddChild(new Vector2Field(default(Vector2), field.name));
                    l            = 2;
                }
                else if (field.type == typeof(Vector3))
                {
                    fieldControl = AddChild(new Vector3Field(default(Vector3), field.name));
                    l            = 2;
                }
                else if (field.type == typeof(Vector4))
                {
                    fieldControl = AddChild(new Vector4Field(default(Vector4), field.name));
                    l            = 2;
                }
                else if (field.type == typeof(string))
                {
                    fieldControl = AddChild(new TextField("", field.name));
                    l            = 1;
                }
                else if (field.type == typeof(Rect))
                {
                    fieldControl = AddChild(new RectField(default(Rect), field.name));
                    l            = 3;
                }
                else if (field.type == typeof(Color))
                {
                    fieldControl = AddChild(new ColorField(default(Color), field.name));
                    l            = 1;
                }
                else if (field.type == typeof(Bounds))
                {
                    fieldControl = AddChild(new BoundsField(default(Bounds), field.name));
                    l            = 3;
                }
                else if (field.type.IsEnum)
                {
                    fieldControl = AddChild(new EnumDropdown((System.Enum)Activator.CreateInstance(field.type), field.name));
                    l            = 1;
                }
                else if (field.type == typeof(bool))
                {
                    fieldControl = AddChild(new Toggle(field.name, false, false));
                    l            = 1;
                }
                else if (field.type == typeof(GameObject))
                {
//                    fieldControl = AddChild(new ObjectField(typeof(GameObject), true, null, "Object Target"));
                    fieldControl = AddChild(new ObjectField(new Vector2(50, 50), new Vector2(50, 10), typeof(GameObject), true, null, "Object Target"));
                    l            = 1;
                }
                else
                {
                    Debug.LogWarning(string.Format("Unsupported field type `{0}({1})` encountered in node `{2}`", field.name, field.type, node.displayName));
                }

                if (fieldControl != null)
                {
                    m_fieldControls.Add(field.name, fieldControl);

                    fieldControl
                    .SetPosition(INNER_PADDING, HEADER_SIZE + LINE_SIZE * lines)
                    .SetSize(BOX_WIDTH - INNER_PADDING - INNER_PADDING, LINE_SIZE);

                    lines += l;
                }
            }

            if (m_node.nodeType != BehaviorTrees.BehaviorNodeAttribute.NodeType.Leaf)
            {
                lines++;    // Add extra line of padding at the bottom
            }

            m_canvas = (GraphicsCanvas)AddDecorator(new GraphicsCanvas());

            SetHeight(HEADER_SIZE + FOOTER_PADDING + LINE_SIZE * lines);

            // Create outputs
            m_outputs       = new List <BehaviorNodeControl>();
            m_outputButtons = new List <Button>();
            m_outputLines   = new List <BezierCurve>();

            UpdateOutputs();
        }
        private string GenerateNodeCode(BehaviorNodeControl node)
        {
            EditorCachedNode data = node.GetData();

            string s = "\n";

            s = string.Format("\t\t{0} {1} = new {0}( t );", data.type, m_indexTable[node]);

            foreach (EditorCachedNodeField field in data.fields)
            {
                if (node.m_fieldControls.ContainsKey(field.name))
                {
                    Control c = node.m_fieldControls[field.name];

                    if (field.type == typeof(int))
                    {
                        s += string.Format("\n\t\t{0}.{1} = {2};", m_indexTable[node], field.systemName, (c as IntField).Value);
                    }
                    else if (field.type == typeof(float))
                    {
                        s += string.Format("\n\t\t{0}.{1} = {2}f;", m_indexTable[node], field.systemName, (c as FloatField).Value);
                    }
                    else if (field.type == typeof(Vector2))
                    {
                        s += string.Format("\n\t\t{0}.{1} = new Vector2({2}f,{3}f);", m_indexTable[node], field.systemName, (c as Vector2Field).Value.x, (c as Vector2Field).Value.y);
                    }
                    else if (field.type == typeof(Vector3))
                    {
                        s += string.Format("\n\t\t{0}.{1} = new Vector3({2}f,{3}f,{4}f);", m_indexTable[node], field.systemName, (c as Vector3Field).Value.x, (c as Vector3Field).Value.y, (c as Vector3Field).Value.z);
                    }
                    else if (field.type == typeof(Vector4))
                    {
                        s += string.Format("\n\t\t{0}.{1} = new Vector4({2}f,{3}f,{4}f,{5}f);", m_indexTable[node], field.systemName, (c as Vector4Field).Value.x, (c as Vector4Field).Value.y, (c as Vector4Field).Value.z, (c as Vector4Field).Value.w);
                    }
                    else if (field.type == typeof(string))
                    {
                        s += string.Format("\n\t\t{0}.{1} = \"{2}\";", m_indexTable[node], field.systemName, (c as TextField).Value);
                    }
                    else if (field.type == typeof(Rect))
                    {
                        s += string.Format("\n\t\t{0}.{1} = new Rect({2}f,{3}f,{4}f,{5}f);", m_indexTable[node], field.systemName, (c as RectField).Value.xMin, (c as RectField).Value.yMin, (c as RectField).Value.width, (c as RectField).Value.height);
                    }
                    else if (field.type == typeof(Color))
                    {
                        s += string.Format("\n\t\t{0}.{1} = new Color({2},{3},{4},{5});", m_indexTable[node], field.systemName, (c as ColorField).Value.r, (c as ColorField).Value.g, (c as ColorField).Value.b, (c as ColorField).Value.a);
                    }
                    else if (field.type == typeof(Bounds))
                    {
                        s += string.Format("\n\t\t{0}.{1} = new Bounds( new Vector3({2}f,{3}f,{4}f),new Vector3({5}f,{6}f,{7}f));", m_indexTable[node], field.systemName, (c as BoundsField).Value.center.x, (c as BoundsField).Value.center.y, (c as BoundsField).Value.center.z, (c as BoundsField).Value.extents.x, (c as BoundsField).Value.extents.y, (c as BoundsField).Value.extents.z);
                    }
                    else if (field.type.IsEnum)
                    {
                        s += string.Format("\n\t\t{0}.{1} = {2}.{3};", m_indexTable[node], field.systemName, field.type.ToString().Replace("+", "."), (c as EnumDropdown).Value);
                    }
                    else if (field.type == typeof(bool))
                    {
                        s += string.Format("\n\t\t{0}.{1} = {2};", m_indexTable[node], field.systemName, (c as Toggle).Value.ToString().ToLowerInvariant());
                    }
                }
            }

            return(s);
        }
        public BehaviorNodeControl( EditorCachedNode node )
        {
            m_fieldControls = new Dictionary<string, Control>();
            m_node = node;            

            int     lines    = 0;

            foreach( EditorCachedNodeField field in node.fields )
            {
                Control fieldControl = null;
                int l = 0;

                // Create fields per type
                if ( field.type == typeof( int ) )
                {
                    fieldControl = AddChild( new IntField( default( int ), field.name ) );
                    l = 1;
                }
                else if ( field.type == typeof( float ) )
                {
                    fieldControl = AddChild( new FloatField( default( float ), field.name ) );
                    l = 1;
                }
                else if ( field.type == typeof( Vector2 ) )
                {
                    fieldControl = AddChild( new Vector2Field( default( Vector2 ), field.name ) );
                    l = 2;
                }
                else if ( field.type == typeof( Vector3 ) )
                {
                    fieldControl = AddChild( new Vector3Field( default( Vector3 ), field.name ) );
                    l = 2;
                }
                else if ( field.type == typeof( Vector4 ) )
                {
                    fieldControl = AddChild( new Vector4Field( default( Vector4 ), field.name ) );
                    l = 2;
                }
                else if ( field.type == typeof( string ) )
                {
                    fieldControl = AddChild( new TextField( "", field.name ) );
                    l = 1;
                }
                else if ( field.type == typeof( Rect ) )
                {
                    fieldControl = AddChild( new RectField( default( Rect ), field.name ) );
                    l = 3;
                }
                else if ( field.type == typeof( Color ) )
                {
                    fieldControl = AddChild( new ColorField( default( Color ), field.name ) );
                    l = 1;
                }
                else if ( field.type == typeof( Bounds ) )
                {
                    fieldControl = AddChild( new BoundsField( default( Bounds ), field.name ) );
                    l = 3;
                }
                else if ( field.type.IsEnum )
                {
                    fieldControl = AddChild( new EnumDropdown( ( System.Enum )Activator.CreateInstance( field.type ), field.name ) );
                    l = 1;
                }
                else if ( field.type == typeof( bool ) )
                {
                    fieldControl = AddChild( new Toggle( field.name, false, false ) );
                    l = 1;
                }
                else
                {
                    Debug.LogWarning( string.Format( "Unsupported field type `{0}({1})` encountered in node `{2}`", field.name, field.type, node.displayName ) );
                }

                if ( fieldControl != null )
                {
                    m_fieldControls.Add( field.name, fieldControl );

                    fieldControl
                    .SetPosition( INNER_PADDING, HEADER_SIZE + LINE_SIZE * lines )
                    .SetSize( BOX_WIDTH - INNER_PADDING - INNER_PADDING, LINE_SIZE );

                    lines += l;
                }
            }

            if ( m_node.nodeType != BehaviorTrees.BehaviorNodeAttribute.NodeType.Leaf )
            { 
                lines++;    // Add extra line of padding at the bottom
            }

            m_canvas = (GraphicsCanvas)AddDecorator( new GraphicsCanvas() );

            SetHeight( HEADER_SIZE + FOOTER_PADDING + LINE_SIZE * lines );

            // Create outputs
            m_outputs = new List<BehaviorNodeControl>();
            m_outputButtons = new List<Button>();
            m_outputLines   = new List<BezierCurve>();

            UpdateOutputs();
        }                
        private void DeserializeFields( XmlNode xml, EditorCachedNode data, BehaviorNodeControl control )
        {
            foreach( KeyValuePair< string, Control > kvp in control.m_fieldControls )
            {
                string fieldName  = kvp.Key;
                string systemName = "";
                Control c         = kvp.Value;

                bool found = false;
                EditorCachedNodeField field = default(EditorCachedNodeField);

                foreach( EditorCachedNodeField f in data.fields )
                {
                    if ( f.name == fieldName )
                    {
                        found = true;
                        field = f;
                        systemName = f.systemName;
                        break;
                    }
                }

                if ( !found )
                {
                    continue;
                }

                if ( xml.Attributes[ systemName ] == null )
                {
                    continue;
                }

                string sval = xml.Attributes[ systemName ].InnerText;

                if ( field.type == typeof( int ) )
                {
                    ( c as IntField ).Value = int.Parse( sval );
                }
                else if ( field.type == typeof( float ) )
                {
                    ( c as FloatField ).Value = float.Parse( sval );
                }
                else if ( field.type == typeof( Vector2 ) )
                {
                    string[] split = sval.Split( ',' );
                    ( c as Vector2Field ).Value = new Vector2( float.Parse( split[ 0 ] ), float.Parse( split[ 1 ] ) );                    
                }
                else if ( field.type == typeof( Vector3 ) )
                {
                    string[] split = sval.Split( ',' );
                    ( c as Vector3Field ).Value = new Vector3( float.Parse( split[ 0 ] ), float.Parse( split[ 1 ] ), float.Parse( split[ 2 ] ) );
                }
                else if ( field.type == typeof( Vector4 ) )
                {
                    string[] split = sval.Split( ',' );
                    ( c as Vector4Field ).Value = new Vector4( float.Parse( split[ 0 ] ), float.Parse( split[ 1 ] ), float.Parse( split[ 2 ] ), float.Parse( split[ 3 ] ) );
                }
                else if ( field.type == typeof( string ) )
                {
                    ( c as TextField ).Value = sval;
                }
                else if ( field.type == typeof( Rect ) )
                {
                    string[] split = sval.Split( ',' );
                    ( c as RectField ).Value = new Rect( float.Parse( split[ 0 ] ), float.Parse( split[ 1 ] ), float.Parse( split[ 2 ] ), float.Parse( split[ 3 ] ) );                    
                }
                else if ( field.type == typeof( Color ) )
                {
                    string[] split = sval.Split( ',' );
                    ( c as ColorField ).Value = new Color( float.Parse( split[ 0 ] ), float.Parse( split[ 1 ] ), float.Parse( split[ 2 ] ) );
                }
                else if ( field.type == typeof( Bounds ) )
                {
                    string[] split = sval.Split( ',' );
                    ( c as BoundsField ).Value = new Bounds( new Vector3( float.Parse( split[ 0 ] ), float.Parse( split[ 1 ] ), float.Parse( split[ 2 ] ) ),  new Vector3( float.Parse( split[ 3 ] ), float.Parse( split[ 4 ] ), float.Parse( split[ 5 ] ) ) );
                }
                else if ( field.type.IsEnum )
                {
                    System.Enum e = (System.Enum)System.Enum.Parse( field.type, sval );
                    ( c as EnumDropdown ).Value = e;
                }
                else if ( field.type == typeof( bool ) )
                {
                    ( c as Toggle ).Value = bool.Parse( sval );
                }
            }
        }
        private void DeserializeFields(XmlNode xml, EditorCachedNode data, BehaviorNodeControl control)
        {
            foreach (KeyValuePair <string, Control> kvp in control.m_fieldControls)
            {
                string  fieldName  = kvp.Key;
                string  systemName = "";
                Control c          = kvp.Value;

                bool found = false;
                EditorCachedNodeField field = default(EditorCachedNodeField);

                foreach (EditorCachedNodeField f in data.fields)
                {
                    if (f.name == fieldName)
                    {
                        found      = true;
                        field      = f;
                        systemName = f.systemName;
                        break;
                    }
                }

                if (!found)
                {
                    continue;
                }

                if (xml.Attributes[systemName] == null)
                {
                    continue;
                }

                string sval = xml.Attributes[systemName].InnerText;

                if (field.type == typeof(int))
                {
                    (c as IntField).Value = int.Parse(sval);
                }
                else if (field.type == typeof(float))
                {
                    (c as FloatField).Value = float.Parse(sval);
                }
                else if (field.type == typeof(Vector2))
                {
                    string[] split = sval.Split(',');
                    (c as Vector2Field).Value = new Vector2(float.Parse(split[0]), float.Parse(split[1]));
                }
                else if (field.type == typeof(Vector3))
                {
                    string[] split = sval.Split(',');
                    (c as Vector3Field).Value = new Vector3(float.Parse(split[0]), float.Parse(split[1]), float.Parse(split[2]));
                }
                else if (field.type == typeof(Vector4))
                {
                    string[] split = sval.Split(',');
                    (c as Vector4Field).Value = new Vector4(float.Parse(split[0]), float.Parse(split[1]), float.Parse(split[2]), float.Parse(split[3]));
                }
                else if (field.type == typeof(string))
                {
                    (c as TextField).Value = sval;
                }
                else if (field.type == typeof(Rect))
                {
                    string[] split = sval.Split(',');
                    (c as RectField).Value = new Rect(float.Parse(split[0]), float.Parse(split[1]), float.Parse(split[2]), float.Parse(split[3]));
                }
                else if (field.type == typeof(Color))
                {
                    string[] split = sval.Split(',');
                    (c as ColorField).Value = new Color(float.Parse(split[0]), float.Parse(split[1]), float.Parse(split[2]));
                }
                else if (field.type == typeof(Bounds))
                {
                    string[] split = sval.Split(',');
                    (c as BoundsField).Value = new Bounds(new Vector3(float.Parse(split[0]), float.Parse(split[1]), float.Parse(split[2])), new Vector3(float.Parse(split[3]), float.Parse(split[4]), float.Parse(split[5])));
                }
                else if (field.type.IsEnum)
                {
                    System.Enum e = (System.Enum)System.Enum.Parse(field.type, sval);
                    (c as EnumDropdown).Value = e;
                }
                else if (field.type == typeof(bool))
                {
                    (c as Toggle).Value = bool.Parse(sval);
                }
            }
        }