void Header(string icon, string text)
    {
        GUILayout.BeginHorizontal(DEditorGUI.HeaderBackground, GUILayout.Height(DEditorGUI.HEADER_HEIGHT));

        DEditorGUI.IconButton(icon);
        GUILayout.Label(text);

        GUILayout.EndHorizontal();
    }
    /*void LanServers()
     * {
     *  GUIStyle s = new GUIStyle(GUIStyle.none);
     *  s.padding = new RectOffset(5, 5, 2, 2);
     *  GUILayout.BeginHorizontal(s);
     *
     *  var sessions = AscensionNetwork.isRunning ? AscensionNetwork.GetSessions() : new UdpKit.UdpSession[0];
     *
     *  Each<UdpKit.UdpSession>(sessions, MakeHeader("mc_name", "Name"), c => StatsLabel(c.HostName));
     *  Each<UdpKit.UdpSession>(sessions, MakeHeader("mc_ipaddress", "End Point"), c => StatsLabel(c.WanEndPoint));
     *
     *  //Each<UdpKit.UdpSession>(sessions, MakeHeader("mc_bubble", "User Data"), c => StatsLabel(c.Data ?? ""));
     *
     *  GUILayout.EndHorizontal();
     *  GUILayout.Space(4);
     * }*/

    Action MakeHeader(string icon, string text)
    {
        return(() => {
            GUILayout.BeginHorizontal();

            DEditorGUI.IconButton(icon);

            GUIStyle s = new GUIStyle(EditorStyles.miniLabel);
            s.padding = new RectOffset();
            s.margin = new RectOffset(5, 0, 3, 0);

            GUILayout.Label(text, s);

            GUILayout.EndHorizontal();
        });
    }
    void Footer()
    {
        GUILayout.BeginHorizontal();

        //var version = Assembly.GetExecutingAssembly().GetName().Version;

        GUILayout.Label(string.Format("{0} ({1})", version, Core.IsDebugMode ? "DEBUG" : "RELEASE"), EditorStyles.miniLabel);

        GUILayout.FlexibleSpace();

        PrefabDatabase db = PrefabDatabase.Instance;

        if (db.DatabaseMode == PrefabDatabaseMode.ManualScan)
        {
            if (DEditorGUI.IconButton("refresh"))
            {
                AscensionCompiler.UpdatePrefabsDatabase();
                Debug.Log("Upading prefab database...");
            }

            GUILayout.Space(8);
        }

        if (DEditorGUI.IconButton("code-emit"))
        {
            if (RuntimeSettings.Instance.compileAsDll)
            {
                AscensionDataAssemblyCompiler.Run();
            }
            else
            {
                AscensionDataAssemblyCompiler.CodeEmit();
            }

            Debug.Log("Compiling project... " + ProjectPath);
        }

        GUILayout.Space(8);

        if (DEditorGUI.IconButton("save-project"))
        {
            Save();
            Debug.Log("Saving project... " + ProjectPath);
        }

        GUILayout.EndHorizontal();
    }
    void EditProperty(AssetDefinition def, PropertyDefinition p, bool first, bool last)
    {
        BeginBackground();

        GUILayout.BeginHorizontal(DEditorGUI.HeaderBackground, GUILayout.Height(DEditorGUI.HEADER_HEIGHT));

        if ((Event.current.modifiers & EventModifiers.Control) == EventModifiers.Control)
        {
            if (DEditorGUI.IconButton("minus-editor"))
            {
                if (EditorUtility.DisplayDialog("Delete Property", string.Format("Do you want to delete '{0}' (Property)?", p.Name), "Yes", "No"))
                {
                    p.Deleted = true;
                }
            }
        }
        else
        {
            if (DEditorGUI.Toggle("arrow-down", "arrow-right", p.Expanded && (p.PropertyType.HasSettings || p.PropertyType.MecanimApplicable)))
            {
                p.Expanded = !p.Expanded;
            }
        }

        if (def is StateDefinition || def is ObjectDefinition)
        {
            p.Name = DEditorGUI.TextFieldOverlay(p.Name, p.Priority.ToString(), GUILayout.Width(181));

            switch (p.ReplicationMode)
            {
            case ReplicationMode.Everyone:
                DEditorGUI.Toggle("controller-plus", true);
                break;

            case ReplicationMode.EveryoneExceptController:
                DEditorGUI.Toggle("controller", false);
                break;

            case ReplicationMode.OnlyOwnerAndController:
                DEditorGUI.Toggle("controller-only", true);
                break;

            case ReplicationMode.LocalForEachPlayer:
                DEditorGUI.Toggle("owner-only", true);
                break;
            }
        }
        else
        {
            p.Name = EditorGUILayout.TextField(p.Name, GUILayout.Width(200));
        }

        DEditorGUI.SetTooltip("Name. The name of this property, has to be a valid C# property name.");

        // edit property type
        DEditorGUI.PropertyTypePopup(def, p);
        DEditorGUI.SetTooltip("Type. The type of this property.");

        EditorGUI.BeginDisabledGroup(def.SortOrder != SortOrder.Manual);

        if (DEditorGUI.IconButton("arrow-down", !last))
        {
            p.Adjust += 1;
        }

        if (DEditorGUI.IconButton("arrow-up", !first))
        {
            p.Adjust -= 1;
        }

        EditorGUI.EndDisabledGroup();
        EditorGUILayout.EndHorizontal();

        if (p.Controller)
        {
            p.ReplicationMode = ReplicationMode.Everyone;
            p.Controller      = false;
            Save();
        }

        if (p.Expanded)
        {
            GUILayout.Space(2);

            //DEditorGUI.WithLabel("Comment", () => {
            //  p.Comment = EditorGUILayout.TextField(p.Comment);
            //});

            if (def is StateDefinition || def is ObjectDefinition)
            {
                DEditorGUI.WithLabel("Replication", () =>
                {
                    p.Priority        = DEditorGUI.EditPriority(p.Priority, p.PropertyType.HasPriority);
                    p.ReplicationMode = (ReplicationMode)EditorGUILayout.EnumPopup(p.ReplicationMode);
                });
            }

            if (def is CommandDefinition)
            {
                if (p.PropertyType.CanSmoothCorrections && ((CommandDefinition)def).Result.Contains(p))
                {
                    DEditorGUI.WithLabel("Smooth Corrections", () =>
                    {
                        p.CommandAssetSettings.SmoothCorrection = EditorGUILayout.Toggle(p.CommandAssetSettings.SmoothCorrection);
                    });
                }
            }

            if (p.PropertyType.MecanimApplicable && (def is StateDefinition))
            {
                DEditorGUI.WithLabel("Mecanim", () =>
                {
                    EditorGUILayout.BeginHorizontal();

                    if (p.PropertyType is PropertyTypeFloat)
                    {
                        p.StateAssetSettings.MecanimMode = (MecanimMode)EditorGUILayout.EnumPopup(p.StateAssetSettings.MecanimMode);
                        EditorGUI.BeginDisabledGroup(p.StateAssetSettings.MecanimMode == MecanimMode.Disabled);

                        p.StateAssetSettings.MecanimDirection = (MecanimDirection)EditorGUILayout.EnumPopup(p.StateAssetSettings.MecanimDirection);

                        switch (p.StateAssetSettings.MecanimMode)
                        {
                        case MecanimMode.Parameter:
                            if (p.StateAssetSettings.MecanimDirection == MecanimDirection.UsingAscensionProperties)
                            {
                                p.StateAssetSettings.MecanimDamping = DEditorGUI.FloatFieldOverlay(p.StateAssetSettings.MecanimDamping, "Damping Time");
                            }

                            break;

                        case MecanimMode.LayerWeight:
                            p.StateAssetSettings.MecanimLayer = DEditorGUI.IntFieldOverlay(p.StateAssetSettings.MecanimLayer, "Layer Index");
                            break;
                        }

                        EditorGUI.EndDisabledGroup();
                    }
                    else
                    {
                        p.StateAssetSettings.MecanimMode = (MecanimMode)(int)EditorGUILayout.Popup((int)p.StateAssetSettings.MecanimMode, new string[] { "Disabled", "Parameter" });

                        EditorGUI.BeginDisabledGroup(p.StateAssetSettings.MecanimMode == MecanimMode.Disabled);
                        p.StateAssetSettings.MecanimDirection = (MecanimDirection)EditorGUILayout.EnumPopup(p.StateAssetSettings.MecanimDirection);

                        if (p.PropertyType is PropertyTypeTrigger)
                        {
                            p.StateAssetSettings.MecanimLayer = DEditorGUI.IntFieldOverlay(p.StateAssetSettings.MecanimLayer, "Layer Index");
                        }
                        EditorGUI.EndDisabledGroup();
                    }

                    EditorGUILayout.EndHorizontal();
                });
            }

            if (p.PropertyType.HasSettings)
            {
                PropertyEditorRegistry.GetEditor(p.PropertyType.GetType()).Edit(def, p);
            }
        }
        else
        {
            GUILayout.Space(2);
        }

        EditorGUILayout.EndVertical();
    }
    void EditHeader(AssetDefinition def)
    {
        var stateDef  = def as StateDefinition;
        var structDef = def as ObjectDefinition;
        var cmdDef    = def as CommandDefinition;
        var eventDef  = def as EventDefinition;

        GUILayout.BeginArea(new Rect(DEditorGUI.GLOBAL_INSET, DEditorGUI.GLOBAL_INSET, position.width - (DEditorGUI.GLOBAL_INSET * 2), DEditorGUI.HEADER_HEIGHT));
        GUILayout.BeginHorizontal(DEditorGUI.HeaderBackground, GUILayout.Height(DEditorGUI.HEADER_HEIGHT));

        if (def is StateDefinition)
        {
            DEditorGUI.IconButton("states");
        }
        if (def is ObjectDefinition)
        {
            DEditorGUI.IconButton("objects");
        }
        if (def is EventDefinition)
        {
            DEditorGUI.IconButton("events");
        }
        if (def is CommandDefinition)
        {
            DEditorGUI.IconButton("commands");
        }

        // edit asset name
        GUI.SetNextControlName("AscensionEditorName");
        def.Name = EditorGUILayout.TextField(def.Name);

        if (cmdDef != null)
        {
            if (GUILayout.Button("New Input", EditorStyles.miniButtonLeft, GUILayout.Width(75)))
            {
                cmdDef.Input.Add(CreateProperty(new PropertyCommandSettings()));
                Save();
            }

            if (GUILayout.Button("New Result", EditorStyles.miniButtonRight, GUILayout.Width(75)))
            {
                cmdDef.Result.Add(CreateProperty(new PropertyCommandSettings()));
                Save();
            }
        }
        else
        {
            if (GUILayout.Button("New Property", EditorStyles.miniButton, GUILayout.Width(150)))
            {
                if (stateDef != null)
                {
                    stateDef.Properties.Add(CreateProperty(new PropertyStateSettings()));
                    Save();
                }

                if (structDef != null)
                {
                    structDef.Properties.Add(CreateProperty(new PropertyStateSettings()));
                    Save();
                }

                if (eventDef != null)
                {
                    eventDef.Properties.Add(CreateProperty(new PropertyEventSettings()));
                    Save();
                }
            }
        }

        if (stateDef != null)
        {
            ExpandAllOrCollapseAll(stateDef.Properties);
        }
        if (structDef != null)
        {
            ExpandAllOrCollapseAll(structDef.Properties);
        }
        if (eventDef != null)
        {
            ExpandAllOrCollapseAll(eventDef.Properties);
        }
        if (cmdDef != null)
        {
            ExpandAllOrCollapseAll(cmdDef.Input, cmdDef.Result);
        }

        if (stateDef != null)
        {
            Duplicate(stateDef);
        }
        if (structDef != null)
        {
            Duplicate(structDef);
        }
        if (eventDef != null)
        {
            Duplicate(eventDef);
        }
        if (cmdDef != null)
        {
            Duplicate(cmdDef);
        }

        GUILayout.EndHorizontal();
        GUILayout.EndArea();
    }