public void OnGUI()
        {
            this.CollectEditors();

            if (this.worlds.Count != ME.ECS.Worlds.registeredWorlds.Count)
            {
                this.worlds.Clear();
                foreach (var item in ME.ECS.Worlds.registeredWorlds)
                {
                    var worldEditor = new WorldEditor();
                    worldEditor.world = item;
                    this.worlds.Add(worldEditor);
                }
            }

            GUILayoutExt.Padding(6f, () => {
                GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
                {
                    GUILayout.BeginVertical(GUILayout.Width(400f), GUILayout.ExpandHeight(true));
                    GUILayout.Space(4f); // Unity GUI bug: we need to add 4px space when use GUILayout.Width() control
                    var world = this.DrawWorlds();
                    GUILayout.Space(4f); // Unity GUI bug: we need to add 4px space when use GUILayout.Width() control
                    GUILayout.EndVertical();

                    GUILayout.Space(4f);

                    GUILayout.BeginVertical(GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
                    this.DrawEntities(world);
                    GUILayout.EndVertical();
                }
                GUILayout.EndHorizontal();
            });
        }
Exemple #2
0
        public static void Box(float padding, float margin, System.Action onContent, GUIStyle style = null, params GUILayoutOption[] options)
        {
            GUILayoutExt.Padding(margin, () => {
                if (style == null)
                {
                    style = "GroupBox";
                }
                else
                {
                    style = new GUIStyle(style);
                }

                style.padding = new RectOffset();
                style.margin  = new RectOffset();

                GUILayout.BeginVertical(style, options);
                {
                    GUILayoutExt.Padding(padding, onContent);
                }
                GUILayout.EndVertical();
            }, options);
        }
Exemple #3
0
        public override void OnInspectorGUI()
        {
            var style = new GUIStyle(EditorStyles.toolbar);

            style.fixedHeight   = 0f;
            style.stretchHeight = true;

            var backStyle = new GUIStyle(EditorStyles.label);

            backStyle.normal.background = Texture2D.whiteTexture;

            var dataConfig = (ME.ECS.DataConfigs.DataConfig) this.target;

            if (DataConfigEditor.worldEditors.TryGetValue(this.target, out var worldEditor) == false)
            {
                worldEditor = new WorldsViewerEditor.WorldEditor();
                DataConfigEditor.worldEditors.Add(this.target, worldEditor);
            }

            GUILayoutExt.Padding(8f, () => {
                var usedComponents = new System.Collections.Generic.HashSet <System.Type>();

                var kz               = 0;
                var registries       = dataConfig.structComponents;
                var sortedRegistries = new System.Collections.Generic.SortedDictionary <int, Registry>(new WorldsViewerEditor.DuplicateKeyComparer <int>());
                for (int i = 0; i < registries.Length; ++i)
                {
                    var registry = registries[i];
                    if (registry == null)
                    {
                        continue;
                    }

                    var component = registry;
                    usedComponents.Add(component.GetType());

                    var editor = WorldsViewerEditor.GetEditor(component, out var order);
                    if (editor != null)
                    {
                        sortedRegistries.Add(order, new Registry()
                        {
                            index = i,
                            data  = component
                        });
                    }
                    else
                    {
                        sortedRegistries.Add(0, new Registry()
                        {
                            index = i,
                            data  = component
                        });
                    }
                }

                foreach (var registryKv in sortedRegistries)
                {
                    var registry  = registryKv.Value;
                    var component = registry.data;

                    var backColor       = GUI.backgroundColor;
                    GUI.backgroundColor = new Color(1f, 1f, 1f, kz++ % 2 == 0 ? 0f : 0.05f);

                    GUILayout.BeginVertical(backStyle);
                    {
                        GUI.backgroundColor = backColor;
                        var editor          = WorldsViewerEditor.GetEditor(component);
                        if (editor != null)
                        {
                            EditorGUI.BeginChangeCheck();
                            editor.OnDrawGUI();
                            if (EditorGUI.EndChangeCheck() == true)
                            {
                                component = editor.GetTarget <IStructComponent>();
                                dataConfig.structComponents[registry.index] = component;
                            }
                        }
                        else
                        {
                            var componentName = component.GetType().Name;
                            var fieldsCount   = GUILayoutExt.GetFieldsCount(component);
                            if (fieldsCount == 0)
                            {
                                EditorGUI.BeginDisabledGroup(true);
                                EditorGUILayout.Toggle(componentName, true);
                                EditorGUI.EndDisabledGroup();
                            }
                            else if (fieldsCount == 1)
                            {
                                var changed = GUILayoutExt.DrawFields(worldEditor, component, componentName);
                                if (changed == true)
                                {
                                    dataConfig.structComponents[registry.index] = component;
                                }
                            }
                            else
                            {
                                GUILayout.BeginHorizontal();
                                {
                                    GUILayout.Space(18f);
                                    GUILayout.BeginVertical();
                                    {
                                        var key     = "ME.ECS.WorldsViewerEditor.FoldoutTypes." + component.GetType().FullName;
                                        var foldout = EditorPrefs.GetBool(key, true);
                                        GUILayoutExt.FoldOut(ref foldout, componentName, () => {
                                            var changed = GUILayoutExt.DrawFields(worldEditor, component);
                                            if (changed == true)
                                            {
                                                dataConfig.structComponents[registry.index] = component;
                                            }
                                        });
                                        EditorPrefs.SetBool(key, foldout);
                                    }
                                    GUILayout.EndVertical();
                                }
                                GUILayout.EndHorizontal();
                            }
                        }
                    }
                    GUILayout.EndVertical();

                    GUILayoutExt.Separator();
                }

                GUILayoutExt.DrawAddComponentMenu(usedComponents, (addType, isUsed) => {
                    if (isUsed == true)
                    {
                        usedComponents.Remove(addType);
                        for (int i = 0; i < dataConfig.structComponents.Length; ++i)
                        {
                            if (dataConfig.structComponents[i].GetType() == addType)
                            {
                                var list = dataConfig.structComponents.ToList();
                                list.RemoveAt(i);
                                dataConfig.structComponents = list.ToArray();
                                dataConfig.OnScriptLoad();
                                break;
                            }
                        }
                    }
                    else
                    {
                        usedComponents.Add(addType);
                        System.Array.Resize(ref dataConfig.structComponents, dataConfig.structComponents.Length + 1);
                        dataConfig.structComponents[dataConfig.structComponents.Length - 1] = (IStructComponent)System.Activator.CreateInstance(addType);
                        dataConfig.OnScriptLoad();
                    }
                });
            });

            GUILayoutExt.Padding(8f, () => {
                var usedComponents = new System.Collections.Generic.HashSet <System.Type>();

                var kz               = 0;
                var registries       = dataConfig.components;
                var sortedRegistries = new System.Collections.Generic.SortedDictionary <int, RegistryComponent>(new WorldsViewerEditor.DuplicateKeyComparer <int>());
                for (int i = 0; i < registries.Length; ++i)
                {
                    var registry = registries[i];
                    if (registry == null)
                    {
                        continue;
                    }

                    var component = registry;
                    usedComponents.Add(component.GetType());

                    var editor = WorldsViewerEditor.GetEditor(component, out var order);
                    if (editor != null)
                    {
                        sortedRegistries.Add(order, new RegistryComponent()
                        {
                            index = i,
                            data  = component
                        });
                    }
                    else
                    {
                        sortedRegistries.Add(0, new RegistryComponent()
                        {
                            index = i,
                            data  = component
                        });
                    }
                }

                foreach (var registryKv in sortedRegistries)
                {
                    var registry  = registryKv.Value;
                    var component = registry.data;

                    var backColor       = GUI.backgroundColor;
                    GUI.backgroundColor = new Color(1f, 1f, 1f, kz++ % 2 == 0 ? 0f : 0.05f);

                    GUILayout.BeginVertical(backStyle);
                    {
                        GUI.backgroundColor = backColor;
                        var editor          = WorldsViewerEditor.GetEditor(component);
                        if (editor != null)
                        {
                            EditorGUI.BeginChangeCheck();
                            editor.OnDrawGUI();
                            if (EditorGUI.EndChangeCheck() == true)
                            {
                                component = editor.GetTarget <IComponent>();
                                dataConfig.components[registry.index] = component;
                            }
                        }
                        else
                        {
                            var componentName = component.GetType().Name;
                            var fieldsCount   = GUILayoutExt.GetFieldsCount(component);
                            if (fieldsCount == 0)
                            {
                                EditorGUI.BeginDisabledGroup(true);
                                EditorGUILayout.Toggle(componentName, true);
                                EditorGUI.EndDisabledGroup();
                            }
                            else if (fieldsCount == 1)
                            {
                                var changed = GUILayoutExt.DrawFields(worldEditor, component, componentName);
                                if (changed == true)
                                {
                                    dataConfig.components[registry.index] = component;
                                }
                            }
                            else
                            {
                                GUILayout.BeginHorizontal();
                                {
                                    GUILayout.Space(18f);
                                    GUILayout.BeginVertical();
                                    {
                                        var key     = "ME.ECS.WorldsViewerEditor.FoldoutTypes." + component.GetType().FullName;
                                        var foldout = EditorPrefs.GetBool(key, true);
                                        GUILayoutExt.FoldOut(ref foldout, componentName, () => {
                                            var changed = GUILayoutExt.DrawFields(worldEditor, component);
                                            if (changed == true)
                                            {
                                                dataConfig.components[registry.index] = component;
                                            }
                                        });
                                        EditorPrefs.SetBool(key, foldout);
                                    }
                                    GUILayout.EndVertical();
                                }
                                GUILayout.EndHorizontal();
                            }
                        }
                    }
                    GUILayout.EndVertical();

                    GUILayoutExt.Separator();
                }

                GUILayoutExt.DrawAddComponentMenu(usedComponents, (addType, isUsed) => {
                    if (isUsed == true)
                    {
                        usedComponents.Remove(addType);
                        for (int i = 0; i < dataConfig.components.Length; ++i)
                        {
                            if (dataConfig.components[i].GetType() == addType)
                            {
                                var list = dataConfig.components.ToList();
                                list.RemoveAt(i);
                                dataConfig.components = list.ToArray();
                                dataConfig.OnScriptLoad();
                                break;
                            }
                        }
                    }
                    else
                    {
                        usedComponents.Add(addType);
                        System.Array.Resize(ref dataConfig.components, dataConfig.components.Length + 1);
                        dataConfig.components[dataConfig.components.Length - 1] = (IComponent)System.Activator.CreateInstance(addType);
                        dataConfig.OnScriptLoad();
                    }
                }, drawRefComponents: true);
            });
        }
        private WorldEditor DrawWorlds()
        {
            WorldEditor selectedWorld = null;
            var         style         = EditorStyles.helpBox;

            this.scrollPosition = GUILayout.BeginScrollView(this.scrollPosition, style, GUILayout.ExpandHeight(true));
            {
                if (this.worlds.Count == 0)
                {
                    var centeredStyle = new GUIStyle(EditorStyles.centeredGreyMiniLabel);
                    centeredStyle.stretchHeight = true;
                    centeredStyle.richText      = true;
                    GUILayout.Label("This is runtime utility to view current running worlds.\nPress <b>Play</b> to start profiling.", centeredStyle);
                }
                else
                {
                    foreach (var worldEditor in this.worlds)
                    {
                        var systems         = worldEditor.GetSystems();
                        var modules         = worldEditor.GetModules();
                        var entitiesStorage = worldEditor.GetEntitiesStorage();
                        var filters         = worldEditor.GetFilters();
                        var world           = worldEditor.world;

                        GUILayoutExt.Padding(4f, () => {
                            GUILayoutExt.FoldOut(ref worldEditor.foldout, worldEditor.ToString() + " (Hash: " + worldEditor.world.GetStateHash() + ")", () => {
                                GUILayoutExt.Box(2f, 4f, () => {
                                    GUILayout.Label("Last Entity Id: " + worldEditor.world.GetLastEntityId().ToString());
                                    GUILayout.Label("State Tick: " + worldEditor.world.GetStateTick().ToString());
                                    GUILayout.Label("Tick: " + worldEditor.world.GetCurrentTick().ToString());
                                    GUILayout.Label("Tick Time: " + worldEditor.world.GetTickTime().ToString() + "ms.");
                                    GUILayout.Label("Time: " + ME.ECS.MathUtils.SecondsToString(worldEditor.world.GetTimeSinceStart()));
                                });

                                GUILayoutExt.FoldOut(ref worldEditor.foldoutSystems, "Systems (" + systems.Count.ToString() + ")", () => {
                                    var cellHeight = 25f;
                                    var padding    = 2f;
                                    var margin     = 1f;
                                    var col1       = 250f;
                                    var col2       = 50f;
                                    var col3       = 50f;
                                    var tableStyle = (GUIStyle)"Box";
                                    var dataStyle  = new GUIStyle(EditorStyles.label);
                                    GUILayoutExt.Padding(4f, () => {
                                        GUILayout.BeginHorizontal();
                                        {
                                            GUILayoutExt.Box(padding, margin, () => { GUILayoutExt.TableCaption("Caption", EditorStyles.miniBoldLabel); }, tableStyle,
                                                             GUILayout.Width(col1),
                                                             GUILayout.Height(cellHeight));
                                            GUILayoutExt.Box(padding, margin, () => { GUILayoutExt.TableCaption("Logic", EditorStyles.miniBoldLabel); }, tableStyle,
                                                             GUILayout.Width(col2),
                                                             GUILayout.Height(cellHeight));
                                            GUILayoutExt.Box(padding, margin, () => { GUILayoutExt.TableCaption("Visual", EditorStyles.miniBoldLabel); }, tableStyle,
                                                             GUILayout.Width(col3),
                                                             GUILayout.Height(cellHeight));
                                        }
                                        GUILayout.EndHorizontal();

                                        foreach (var system in systems)
                                        {
                                            GUILayout.BeginHorizontal();
                                            {
                                                GUILayoutExt.Box(padding, margin, () => { GUILayoutExt.TypeLabel(system.GetType()); }, tableStyle, GUILayout.Width(col1),
                                                                 GUILayout.Height(cellHeight));
                                            }
                                            { // Logic
                                                GUILayoutExt.Box(padding, margin, () => {
                                                    GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
                                                    GUILayout.FlexibleSpace();

                                                    var flag  = world.GetSystemState(system);
                                                    var state = (flag & ME.ECS.ModuleState.LogicInactive) == 0;
                                                    if (this.ToggleMethod(worldEditor, system, "AdvanceTick", ref state) == true)
                                                    {
                                                        world.SetSystemState(
                                                            system, state == false ? flag | ME.ECS.ModuleState.LogicInactive : flag & ~ME.ECS.ModuleState.LogicInactive);
                                                    }

                                                    GUILayout.FlexibleSpace();
                                                    GUILayout.EndHorizontal();
                                                }, tableStyle, GUILayout.Width(col2), GUILayout.Height(cellHeight));
                                            }
                                            { // Visual
                                                GUILayoutExt.Box(padding, margin, () => {
                                                    GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
                                                    GUILayout.FlexibleSpace();

                                                    var flag  = world.GetSystemState(system);
                                                    var state = (flag & ME.ECS.ModuleState.VisualInactive) == 0;
                                                    if (this.ToggleMethod(worldEditor, system, "Update", ref state) == true)
                                                    {
                                                        world.SetSystemState(
                                                            system, state == false ? flag | ME.ECS.ModuleState.VisualInactive : flag & ~ME.ECS.ModuleState.VisualInactive);
                                                    }

                                                    GUILayout.FlexibleSpace();
                                                    GUILayout.EndHorizontal();
                                                }, tableStyle, GUILayout.Width(col3), GUILayout.Height(cellHeight));
                                            }
                                            GUILayout.EndHorizontal();

                                            {
                                                GUILayoutExt.Box(padding, margin, () => {
                                                    /*if (system is IGUIEditor systemEditor) {
                                                     *
                                                     *  systemEditor.OnDrawGUI();
                                                     *
                                                     * }*/
                                                }, tableStyle, GUILayout.ExpandWidth(true));
                                                GUILayout.Space(2f);
                                            }
                                        }
                                    });
                                });

                                GUILayoutExt.FoldOut(ref worldEditor.foldoutModules, "Modules (" + modules.Count.ToString() + ")", () => {
                                    var cellHeight     = 25f;
                                    var padding        = 2f;
                                    var margin         = 1f;
                                    var col2           = 50f;
                                    var col3           = 50f;
                                    var tableStyle     = (GUIStyle)"Box";
                                    var dataStyle      = new GUIStyle(EditorStyles.label);
                                    dataStyle.richText = true;
                                    dataStyle.wordWrap = true;
                                    GUILayoutExt.Padding(4f, () => {
                                        GUILayout.BeginHorizontal();
                                        {
                                            GUILayoutExt.Box(padding, margin, () => { GUILayoutExt.TableCaption("Caption", EditorStyles.miniBoldLabel); }, tableStyle,
                                                             GUILayout.ExpandWidth(true),
                                                             GUILayout.Height(cellHeight));
                                            GUILayoutExt.Box(padding, margin, () => { GUILayoutExt.TableCaption("Logic", EditorStyles.miniBoldLabel); }, tableStyle,
                                                             GUILayout.Width(col2),
                                                             GUILayout.Height(cellHeight));
                                            GUILayoutExt.Box(padding, margin, () => { GUILayoutExt.TableCaption("Visual", EditorStyles.miniBoldLabel); }, tableStyle,
                                                             GUILayout.Width(col3),
                                                             GUILayout.Height(cellHeight));
                                            //GUILayoutExt.Box(2f, 1f, () => { GUILayoutExt.TableCaption("Info", EditorStyles.miniBoldLabel); }, tableStyle,
                                            //                 GUILayout.ExpandWidth(true), GUILayout.Height(cellHeight));
                                        }
                                        GUILayout.EndHorizontal();

                                        foreach (var module in modules)
                                        {
                                            GUILayout.BeginHorizontal();
                                            {
                                                GUILayoutExt.Box(padding, margin, () => { GUILayoutExt.TypeLabel(module.GetType()); }, tableStyle, GUILayout.ExpandWidth(true),
                                                                 GUILayout.Height(cellHeight));
                                            }
                                            { // Logic
                                                GUILayoutExt.Box(padding, margin, () => {
                                                    GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
                                                    GUILayout.FlexibleSpace();

                                                    var flag  = world.GetModuleState(module);
                                                    var state = (flag & ME.ECS.ModuleState.LogicInactive) == 0;
                                                    if (this.ToggleMethod(worldEditor, module, "AdvanceTick", ref state) == true)
                                                    {
                                                        world.SetModuleState(
                                                            module, state == false ? flag | ME.ECS.ModuleState.LogicInactive : flag & ~ME.ECS.ModuleState.LogicInactive);
                                                    }

                                                    GUILayout.FlexibleSpace();
                                                    GUILayout.EndHorizontal();
                                                }, tableStyle, GUILayout.Width(col2), GUILayout.Height(cellHeight));
                                            }
                                            { // Visual
                                                GUILayoutExt.Box(padding, margin, () => {
                                                    GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
                                                    GUILayout.FlexibleSpace();

                                                    var flag  = world.GetModuleState(module);
                                                    var state = (flag & ME.ECS.ModuleState.VisualInactive) == 0;
                                                    if (this.ToggleMethod(worldEditor, module, "Update", ref state) == true)
                                                    {
                                                        world.SetModuleState(
                                                            module, state == false ? flag | ME.ECS.ModuleState.VisualInactive : flag & ~ME.ECS.ModuleState.VisualInactive);
                                                    }

                                                    GUILayout.FlexibleSpace();
                                                    GUILayout.EndHorizontal();
                                                }, tableStyle, GUILayout.Width(col3), GUILayout.Height(cellHeight));
                                            }
                                            GUILayout.EndHorizontal();

                                            {
                                                GUILayoutExt.Box(padding, margin, () => {
                                                    var editor = this.GetEditor(module);
                                                    if (editor != null)
                                                    {
                                                        editor.OnDrawGUI();
                                                    }
                                                }, tableStyle, GUILayout.ExpandWidth(true));
                                                GUILayout.Space(2f);
                                            }
                                        }
                                    });
                                });

                                var entitiesCount = 0;
                                foreach (var entityStorage in entitiesStorage)
                                {
                                    if (entityStorage == null)
                                    {
                                        continue;
                                    }

                                    var storages = entityStorage.Cast <ME.ECS.IStorage>().ToList();
                                    foreach (var storage in storages)
                                    {
                                        if (storage == null)
                                        {
                                            continue;
                                        }

                                        entitiesCount += storage.Count;
                                    }
                                }

                                GUILayoutExt.FoldOut(ref worldEditor.foldoutEntitiesStorage, "Entities (" + entitiesCount.ToString() + ")", () => {
                                    var cellHeight = 25f;
                                    var padding    = 2f;
                                    var margin     = 1f;
                                    //var col1 = 80f;
                                    var tableStyle     = (GUIStyle)"Box";
                                    var dataStyle      = new GUIStyle(EditorStyles.label);
                                    dataStyle.richText = true;
                                    GUILayoutExt.Padding(4f, () => {
                                        GUILayout.BeginHorizontal();
                                        {
                                            /*GUILayoutExt.Box(padding, margin, () => { GUILayoutExt.TableCaption("Caption", EditorStyles.miniBoldLabel); }, tableStyle,
                                             *               GUILayout.Width(col1),
                                             *               GUILayout.Height(cellHeight));*/
                                            GUILayoutExt.Box(padding, margin, () => { GUILayoutExt.TableCaption("Data", EditorStyles.miniBoldLabel); }, tableStyle,
                                                             GUILayout.ExpandWidth(true), GUILayout.Height(cellHeight));
                                        }
                                        GUILayout.EndHorizontal();

                                        GUILayout.BeginVertical();
                                        foreach (var entityStorage in entitiesStorage)
                                        {
                                            if (entityStorage == null)
                                            {
                                                continue;
                                            }

                                            var storages = entityStorage.Cast <ME.ECS.IStorage>().ToList();
                                            foreach (var storage in storages)
                                            {
                                                if (storage == null)
                                                {
                                                    continue;
                                                }

                                                GUILayout.BeginHorizontal();
                                                {
                                                    GUILayoutExt.Box(
                                                        padding,
                                                        margin,
                                                        () => {
                                                        GUILayoutExt.TypeLabel(storage.GetType());
                                                        GUILayout.Label(storage.ToString(), dataStyle);
                                                    },
                                                        tableStyle,
                                                        GUILayout.ExpandWidth(true), GUILayout.Height(cellHeight));
                                                }
                                                GUILayout.EndHorizontal();
                                            }
                                        }
                                        GUILayout.EndVertical();
                                    });
                                });

                                var filtersCount = filters.Count;
                                GUILayoutExt.FoldOut(ref worldEditor.foldoutFilters, "Filters (" + filtersCount.ToString() + ")", () => {
                                    var cellHeight = 25f;
                                    var padding    = 2f;
                                    var margin     = 1f;
                                    //var col1 = 80f;
                                    var tableStyle     = (GUIStyle)"Box";
                                    var dataStyle      = new GUIStyle(EditorStyles.label);
                                    dataStyle.richText = true;
                                    GUILayoutExt.Padding(4f, () => {
                                        GUILayout.BeginHorizontal();
                                        {
                                            /*GUILayoutExt.Box(padding, margin, () => { GUILayoutExt.TableCaption("Caption", EditorStyles.miniBoldLabel); }, tableStyle,
                                             *               GUILayout.Width(col1),
                                             *               GUILayout.Height(cellHeight));*/
                                            GUILayoutExt.Box(padding, margin, () => { GUILayoutExt.TableCaption("Data", EditorStyles.miniBoldLabel); }, tableStyle,
                                                             GUILayout.ExpandWidth(true), GUILayout.Height(cellHeight));
                                        }
                                        GUILayout.EndHorizontal();

                                        GUILayout.BeginVertical();
                                        foreach (var filter in filters.GetData())
                                        {
                                            GUILayout.BeginHorizontal();
                                            {
                                                GUILayoutExt.Box(
                                                    padding,
                                                    margin,
                                                    () => {
                                                    GUILayoutExt.TypeLabel(filter.GetType());
                                                    GUILayout.Label(filter.ToString(), dataStyle);
                                                },
                                                    tableStyle,
                                                    GUILayout.ExpandWidth(true), GUILayout.Height(cellHeight));
                                            }
                                            GUILayout.EndHorizontal();
                                        }
                                        GUILayout.EndVertical();
                                    });
                                });
                            });

                            if (worldEditor.foldout == true)
                            {
                                selectedWorld = worldEditor;

                                // Fold in all others
                                foreach (var wEditor in this.worlds)
                                {
                                    if (wEditor != worldEditor)
                                    {
                                        wEditor.foldout = false;
                                    }
                                }
                            }
                        });

                        GUILayoutExt.Separator();
                    }
                }
            }
            GUILayout.EndScrollView();

            return(selectedWorld);
        }
Exemple #5
0
        public override void OnInspectorGUI()
        {
            var style = new GUIStyle(EditorStyles.toolbar);

            style.fixedHeight   = 0f;
            style.stretchHeight = true;

            var backStyle = new GUIStyle(EditorStyles.label);

            backStyle.normal.background = Texture2D.whiteTexture;

            var slice      = new ME.ECS.DataConfigs.DataConfigSlice();
            var isMultiple = false;

            if (this.targets.Length > 1)
            {
                slice      = ME.ECS.DataConfigs.DataConfigSlice.Distinct(this.targets.Cast <ME.ECS.DataConfigs.DataConfig>().ToArray());
                isMultiple = true;
            }
            else
            {
                var config = (ME.ECS.DataConfigs.DataConfig) this.target;
                slice = new ME.ECS.DataConfigs.DataConfigSlice()
                {
                    configs = new [] {
                        config
                    },
                    structComponentsDataTypeIds = config.structComponentsDataTypeIds,
                    componentsTypeIds           = config.componentsTypeIds
                };
            }

            var usedComponentsAll = new System.Collections.Generic.HashSet <System.Type>();

            foreach (var cfg in slice.configs)
            {
                var componentTypes = cfg.GetStructComponentTypes();
                foreach (var cType in componentTypes)
                {
                    if (usedComponentsAll.Contains(cType) == false)
                    {
                        usedComponentsAll.Add(cType);
                    }
                }

                if (DataConfigEditor.worldEditors.TryGetValue(cfg, out var worldEditor) == false)
                {
                    worldEditor = new WorldsViewerEditor.WorldEditor();
                    DataConfigEditor.worldEditors.Add(cfg, worldEditor);
                }
            }

            if (isMultiple == true)
            {
                GUILayoutExt.DrawHeader("The same components:");

                GUILayoutExt.Padding(8f, () => {
                    var kz = 0;
                    for (int i = 0; i < slice.structComponentsDataTypeIds.Length; ++i)
                    {
                        var typeId     = slice.structComponentsDataTypeIds[i];
                        var component  = slice.configs[0].GetByTypeId(typeId);
                        var components = slice.configs.Select(x => x.GetByTypeId(typeId)).ToArray();

                        var backColor       = GUI.backgroundColor;
                        GUI.backgroundColor = new Color(1f, 1f, 1f, kz++ % 2 == 0 ? 0f : 0.05f);

                        GUILayout.BeginVertical(backStyle);
                        {
                            GUI.backgroundColor = backColor;
                            var editor          = WorldsViewerEditor.GetEditor(components);
                            if (editor != null)
                            {
                                EditorGUI.BeginChangeCheck();
                                editor.OnDrawGUI();
                                if (EditorGUI.EndChangeCheck() == true)
                                {
                                    slice.Set(typeId, components);
                                    this.Save(slice.configs);
                                }
                            }
                            else
                            {
                                var componentName = GUILayoutExt.GetStringCamelCaseSpace(component.GetType().Name);
                                var fieldsCount   = GUILayoutExt.GetFieldsCount(component);
                                if (fieldsCount == 0)
                                {
                                    EditorGUI.BeginDisabledGroup(true);
                                    EditorGUILayout.Toggle(componentName, true);
                                    EditorGUI.EndDisabledGroup();
                                }
                                else if (fieldsCount == 1)
                                {
                                    var changed = GUILayoutExt.DrawFields(DataConfigEditor.multipleWorldEditor, components, componentName);
                                    if (changed == true)
                                    {
                                        slice.Set(typeId, components);
                                        this.Save(slice.configs);
                                    }
                                }
                                else
                                {
                                    GUILayout.BeginHorizontal();
                                    {
                                        GUILayout.Space(18f);
                                        GUILayout.BeginVertical();
                                        {
                                            var key     = "ME.ECS.WorldsViewerEditor.FoldoutTypes." + component.GetType().FullName;
                                            var foldout = EditorPrefs.GetBool(key, true);
                                            GUILayoutExt.FoldOut(ref foldout, componentName, () => {
                                                var changed = GUILayoutExt.DrawFields(DataConfigEditor.multipleWorldEditor, components);
                                                if (changed == true)
                                                {
                                                    slice.Set(typeId, components);
                                                    this.Save(slice.configs);
                                                }
                                            });
                                            EditorPrefs.SetBool(key, foldout);
                                        }
                                        GUILayout.EndVertical();
                                    }
                                    GUILayout.EndHorizontal();
                                }
                            }

                            GUILayoutExt.DrawComponentHelp(component.GetType());
                        }
                        GUILayout.EndVertical();

                        GUILayoutExt.Separator();
                    }
                });

                GUILayoutExt.DrawAddComponentMenu(usedComponentsAll, (addType, isUsed) => {
                    foreach (var dataConfigInner in slice.configs)
                    {
                        if (isUsed == true)
                        {
                            usedComponentsAll.Remove(addType);
                            for (int i = 0; i < dataConfigInner.structComponents.Length; ++i)
                            {
                                if (dataConfigInner.structComponents[i].GetType() == addType)
                                {
                                    var list = dataConfigInner.structComponents.ToList();
                                    list.RemoveAt(i);
                                    dataConfigInner.structComponents = list.ToArray();
                                    dataConfigInner.OnScriptLoad();
                                    this.Save(dataConfigInner);
                                    break;
                                }
                            }
                        }
                        else
                        {
                            usedComponentsAll.Add(addType);
                            System.Array.Resize(ref dataConfigInner.structComponents, dataConfigInner.structComponents.Length + 1);
                            dataConfigInner.structComponents[dataConfigInner.structComponents.Length - 1] = (IStructComponent)System.Activator.CreateInstance(addType);
                            dataConfigInner.OnScriptLoad();
                            this.Save(dataConfigInner);
                        }
                    }
                });

                return;
            }

            GUILayoutExt.Separator(6f);
            GUILayoutExt.DrawHeader("Add Struct Components:");
            GUILayoutExt.Separator();

            var dataConfig = (ME.ECS.DataConfigs.DataConfig) this.target;

            GUILayoutExt.Padding(8f, () => {
                var usedComponents = new System.Collections.Generic.HashSet <System.Type>();

                var kz               = 0;
                var registries       = dataConfig.structComponents;
                var sortedRegistries = new System.Collections.Generic.SortedDictionary <int, Registry>(new WorldsViewerEditor.DuplicateKeyComparer <int>());
                for (int i = 0; i < registries.Length; ++i)
                {
                    var registry = registries[i];
                    if (registry == null)
                    {
                        continue;
                    }

                    var component = registry;
                    usedComponents.Add(component.GetType());

                    var editor = WorldsViewerEditor.GetEditor(component, out var order);
                    if (editor != null)
                    {
                        sortedRegistries.Add(order, new Registry()
                        {
                            index = i,
                            data  = component
                        });
                    }
                    else
                    {
                        sortedRegistries.Add(0, new Registry()
                        {
                            index = i,
                            data  = component
                        });
                    }
                }

                foreach (var registryKv in sortedRegistries)
                {
                    var registry  = registryKv.Value;
                    var component = registry.data;

                    var backColor       = GUI.backgroundColor;
                    GUI.backgroundColor = new Color(1f, 1f, 1f, kz++ % 2 == 0 ? 0f : 0.05f);

                    GUILayout.BeginVertical(backStyle);
                    {
                        GUI.backgroundColor = backColor;
                        var editor          = WorldsViewerEditor.GetEditor(component);
                        if (editor != null)
                        {
                            EditorGUI.BeginChangeCheck();
                            editor.OnDrawGUI();
                            if (EditorGUI.EndChangeCheck() == true)
                            {
                                component = editor.GetTarget <IStructComponent>();
                                dataConfig.structComponents[registry.index] = component;
                                this.Save(dataConfig);
                            }
                        }
                        else
                        {
                            var componentName = GUILayoutExt.GetStringCamelCaseSpace(component.GetType().Name);
                            var fieldsCount   = GUILayoutExt.GetFieldsCount(component);
                            if (fieldsCount == 0)
                            {
                                EditorGUI.BeginDisabledGroup(true);
                                EditorGUILayout.Toggle(componentName, true);
                                EditorGUI.EndDisabledGroup();
                            }
                            else if (fieldsCount == 1)
                            {
                                var changed = GUILayoutExt.DrawFields(DataConfigEditor.multipleWorldEditor, component, componentName);
                                if (changed == true)
                                {
                                    dataConfig.structComponents[registry.index] = component;
                                    this.Save(dataConfig);
                                }
                            }
                            else
                            {
                                GUILayout.BeginHorizontal();
                                {
                                    GUILayout.Space(18f);
                                    GUILayout.BeginVertical();
                                    {
                                        var key     = "ME.ECS.WorldsViewerEditor.FoldoutTypes." + component.GetType().FullName;
                                        var foldout = EditorPrefs.GetBool(key, true);
                                        GUILayoutExt.FoldOut(ref foldout, componentName, () => {
                                            var changed = GUILayoutExt.DrawFields(DataConfigEditor.multipleWorldEditor, component);
                                            if (changed == true)
                                            {
                                                dataConfig.structComponents[registry.index] = component;
                                                this.Save(dataConfig);
                                            }
                                        });
                                        EditorPrefs.SetBool(key, foldout);
                                    }
                                    GUILayout.EndVertical();
                                }
                                GUILayout.EndHorizontal();
                            }
                        }

                        GUILayoutExt.DrawComponentHelp(component.GetType());
                        this.DrawComponentTemplatesUsage(dataConfig, component);
                    }
                    GUILayout.EndVertical();

                    GUILayoutExt.Separator();
                }

                GUILayoutExt.DrawAddComponentMenu(usedComponents, (addType, isUsed) => {
                    if (isUsed == true)
                    {
                        usedComponents.Remove(addType);
                        for (int i = 0; i < dataConfig.structComponents.Length; ++i)
                        {
                            if (dataConfig.structComponents[i].GetType() == addType)
                            {
                                var list = dataConfig.structComponents.ToList();
                                list.RemoveAt(i);
                                dataConfig.structComponents = list.ToArray();
                                dataConfig.OnScriptLoad();
                                this.Save(dataConfig);
                                break;
                            }
                        }
                    }
                    else
                    {
                        usedComponents.Add(addType);
                        System.Array.Resize(ref dataConfig.structComponents, dataConfig.structComponents.Length + 1);
                        dataConfig.structComponents[dataConfig.structComponents.Length - 1] = (IStructComponent)System.Activator.CreateInstance(addType);
                        dataConfig.OnScriptLoad();
                        this.Save(dataConfig);
                    }
                });
            });

            GUILayoutExt.Separator(6f);
            GUILayoutExt.DrawHeader("Add Managed Components:");
            GUILayoutExt.Separator();

            GUILayoutExt.Padding(8f, () => {
                var usedComponents = new System.Collections.Generic.HashSet <System.Type>();

                var kz               = 0;
                var registries       = dataConfig.components;
                var sortedRegistries = new System.Collections.Generic.SortedDictionary <int, RegistryComponent>(new WorldsViewerEditor.DuplicateKeyComparer <int>());
                for (int i = 0; i < registries.Length; ++i)
                {
                    var registry = registries[i];
                    if (registry == null)
                    {
                        continue;
                    }

                    var component = registry;
                    usedComponents.Add(component.GetType());

                    var editor = WorldsViewerEditor.GetEditor(component, out var order);
                    if (editor != null)
                    {
                        sortedRegistries.Add(order, new RegistryComponent()
                        {
                            index = i,
                            data  = component
                        });
                    }
                    else
                    {
                        sortedRegistries.Add(0, new RegistryComponent()
                        {
                            index = i,
                            data  = component
                        });
                    }
                }

                foreach (var registryKv in sortedRegistries)
                {
                    var registry  = registryKv.Value;
                    var component = registry.data;

                    var backColor       = GUI.backgroundColor;
                    GUI.backgroundColor = new Color(1f, 1f, 1f, kz++ % 2 == 0 ? 0f : 0.05f);

                    GUILayout.BeginVertical(backStyle);
                    {
                        GUI.backgroundColor = backColor;
                        var editor          = WorldsViewerEditor.GetEditor(component);
                        if (editor != null)
                        {
                            EditorGUI.BeginChangeCheck();
                            editor.OnDrawGUI();
                            if (EditorGUI.EndChangeCheck() == true)
                            {
                                component = editor.GetTarget <IComponent>();
                                dataConfig.components[registry.index] = component;
                                this.Save(dataConfig);
                            }
                        }
                        else
                        {
                            var componentName = component.GetType().Name;
                            var fieldsCount   = GUILayoutExt.GetFieldsCount(component);
                            if (fieldsCount == 0)
                            {
                                EditorGUI.BeginDisabledGroup(true);
                                EditorGUILayout.Toggle(componentName, true);
                                EditorGUI.EndDisabledGroup();
                            }
                            else if (fieldsCount == 1)
                            {
                                var changed = GUILayoutExt.DrawFields(DataConfigEditor.multipleWorldEditor, component, componentName);
                                if (changed == true)
                                {
                                    dataConfig.components[registry.index] = component;
                                    this.Save(dataConfig);
                                }
                            }
                            else
                            {
                                GUILayout.BeginHorizontal();
                                {
                                    GUILayout.Space(18f);
                                    GUILayout.BeginVertical();
                                    {
                                        var key     = "ME.ECS.WorldsViewerEditor.FoldoutTypes." + component.GetType().FullName;
                                        var foldout = EditorPrefs.GetBool(key, true);
                                        GUILayoutExt.FoldOut(ref foldout, componentName, () => {
                                            var changed = GUILayoutExt.DrawFields(DataConfigEditor.multipleWorldEditor, component);
                                            if (changed == true)
                                            {
                                                dataConfig.components[registry.index] = component;
                                                this.Save(dataConfig);
                                            }
                                        });
                                        EditorPrefs.SetBool(key, foldout);
                                    }
                                    GUILayout.EndVertical();
                                }
                                GUILayout.EndHorizontal();
                            }
                        }

                        GUILayoutExt.DrawComponentHelp(component.GetType());
                        this.DrawComponentTemplatesUsage(dataConfig, component);
                    }
                    GUILayout.EndVertical();

                    GUILayoutExt.Separator();
                }

                GUILayoutExt.DrawAddComponentMenu(usedComponents, (addType, isUsed) => {
                    if (isUsed == true)
                    {
                        usedComponents.Remove(addType);
                        for (int i = 0; i < dataConfig.components.Length; ++i)
                        {
                            if (dataConfig.components[i].GetType() == addType)
                            {
                                var list = dataConfig.components.ToList();
                                list.RemoveAt(i);
                                dataConfig.components = list.ToArray();
                                dataConfig.OnScriptLoad();
                                this.Save(dataConfig);
                                break;
                            }
                        }
                    }
                    else
                    {
                        usedComponents.Add(addType);
                        System.Array.Resize(ref dataConfig.components, dataConfig.components.Length + 1);
                        dataConfig.components[dataConfig.components.Length - 1] = (IComponent)System.Activator.CreateInstance(addType);
                        dataConfig.OnScriptLoad();
                        this.Save(dataConfig);
                    }
                }, drawRefComponents: true);
            });

            GUILayoutExt.Separator(6f);
            GUILayoutExt.DrawHeader("Remove Struct Components:");
            GUILayoutExt.Separator();

            // Remove struct components
            GUILayoutExt.Padding(8f, () => {
                var usedComponents = new System.Collections.Generic.HashSet <System.Type>();

                var kz         = 0;
                var registries = dataConfig.removeStructComponentsDataTypeIds;
                for (int i = 0; i < registries.Length; ++i)
                {
                    var registry = registries[i];
                    var type     = ComponentTypesRegistry.allTypeId.FirstOrDefault(x => x.Value == registry).Key;

                    if (type == null)
                    {
                        continue;
                    }

                    usedComponents.Add(type);

                    var backColor       = GUI.backgroundColor;
                    GUI.backgroundColor = new Color(1f, 1f, 1f, kz++ % 2 == 0 ? 0f : 0.05f);

                    GUILayout.BeginVertical(backStyle);
                    {
                        GUI.backgroundColor = backColor;
                        var componentName   = GUILayoutExt.GetStringCamelCaseSpace(type.Name);

                        EditorGUI.BeginDisabledGroup(true);
                        EditorGUILayout.Toggle(componentName, true);
                        EditorGUI.EndDisabledGroup();

                        GUILayoutExt.DrawComponentHelp(type);
                        this.DrawComponentTemplatesUsage(dataConfig, dataConfig.removeStructComponents[i]);
                    }
                    GUILayout.EndVertical();

                    GUILayoutExt.Separator();
                }

                GUILayoutExt.DrawAddComponentMenu(usedComponents, (addType, isUsed) => {
                    if (isUsed == true)
                    {
                        usedComponents.Remove(addType);
                        for (int i = 0; i < dataConfig.removeStructComponents.Length; ++i)
                        {
                            if (dataConfig.removeStructComponents[i].GetType() == addType)
                            {
                                var list = dataConfig.removeStructComponents.ToList();
                                list.RemoveAt(i);
                                dataConfig.removeStructComponents = list.ToArray();
                                dataConfig.OnScriptLoad();
                                this.Save(dataConfig);
                                break;
                            }
                        }
                    }
                    else
                    {
                        usedComponents.Add(addType);
                        System.Array.Resize(ref dataConfig.removeStructComponents, dataConfig.removeStructComponents.Length + 1);
                        dataConfig.removeStructComponents[dataConfig.removeStructComponents.Length - 1] = (IStructComponent)System.Activator.CreateInstance(addType);
                        dataConfig.OnScriptLoad();
                        this.Save(dataConfig);
                    }
                });
            });

            if ((dataConfig is ME.ECS.DataConfigs.DataConfigTemplate) == false)
            {
                this.DrawTemplates(dataConfig);
            }
        }
Exemple #6
0
        public override void OnInspectorGUI()
        {
            var dataConfig = (ME.ECS.DataConfigs.DataConfig) this.target;

            if (dataConfig is ME.ECS.DataConfigs.DataConfigTemplate == false)
            {
                foreach (var target in this.targets)
                {
                    var dc = (ME.ECS.DataConfigs.DataConfig)target;
                    if (dc.sharedGroupId == 0)
                    {
                        dc.sharedGroupId = ME.ECS.MathUtils.GetHash(AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(dc)));
                        this.Save(dc);
                    }
                }

                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                this.serializedObject.Update();
                var sharedIdLabelStyle = new GUIStyle(EditorStyles.miniBoldLabel);
                sharedIdLabelStyle.alignment = TextAnchor.MiddleRight;
                EditorGUILayout.LabelField("Shared ID:", sharedIdLabelStyle);
                EditorGUILayout.PropertyField(this.sharedGroupId, new GUIContent(string.Empty), GUILayout.Width(100f));
                this.serializedObject.ApplyModifiedProperties();
                GUILayout.EndHorizontal();
            }

            this.search = GUILayoutExt.SearchField("Search", this.search);

            {
                var style = new GUIStyle(EditorStyles.toolbar);
                style.fixedHeight   = 0f;
                style.stretchHeight = true;

                var backStyle = new GUIStyle(EditorStyles.label);
                backStyle.normal.background = Texture2D.whiteTexture;

                var slice      = new ME.ECS.DataConfigs.DataConfigSlice();
                var isMultiple = false;
                if (this.targets.Length > 1)
                {
                    slice      = ME.ECS.DataConfigs.DataConfigSlice.Distinct(this.targets.Cast <ME.ECS.DataConfigs.DataConfig>().ToArray());
                    isMultiple = true;
                }
                else
                {
                    var config = (ME.ECS.DataConfigs.DataConfig) this.target;
                    slice = new ME.ECS.DataConfigs.DataConfigSlice()
                    {
                        configs = new[] {
                            config
                        },
                        structComponentsTypes = config.structComponents.Where(x => x != null).Select(x => x.GetType()).ToArray(),
                    };
                }

                var usedComponentsAll = new System.Collections.Generic.HashSet <System.Type>();
                foreach (var cfg in slice.configs)
                {
                    var componentTypes = cfg.GetStructComponentTypes();
                    foreach (var cType in componentTypes)
                    {
                        if (usedComponentsAll.Contains(cType) == false)
                        {
                            usedComponentsAll.Add(cType);
                        }
                    }

                    if (DataConfigEditor.worldEditors.TryGetValue(cfg, out var worldEditor) == false)
                    {
                        worldEditor = new WorldsViewerEditor.WorldEditor();
                        DataConfigEditor.worldEditors.Add(cfg, worldEditor);
                    }
                }

                if (isMultiple == true)
                {
                    GUILayoutExt.DrawHeader("The Same Components:");

                    GUILayoutExt.Padding(4f, () => {
                        var kz = 0;
                        for (int i = 0; i < slice.structComponentsTypes.Length; ++i)
                        {
                            var type      = slice.structComponentsTypes[i];
                            var component = slice.configs[0].GetByType(slice.configs[0].structComponents, type);
                            if (GUILayoutExt.IsSearchValid(component, this.search) == false)
                            {
                                continue;
                            }
                            var components = slice.configs.Select(x => x.GetByType(x.structComponents, type)).ToArray();

                            var backColor       = GUI.backgroundColor;
                            GUI.backgroundColor = new Color(1f, 1f, 1f, kz++ % 2 == 0 ? 0f : 0.05f);

                            GUILayout.BeginVertical(backStyle);
                            {
                                GUI.backgroundColor = backColor;
                                var editor          = WorldsViewerEditor.GetEditor(components);
                                if (editor != null)
                                {
                                    EditorGUI.BeginChangeCheck();
                                    editor.OnDrawGUI();
                                    if (EditorGUI.EndChangeCheck() == true)
                                    {
                                        slice.Set(components);
                                        this.Save(slice.configs);
                                    }
                                }
                                else
                                {
                                    var componentName = GUILayoutExt.GetStringCamelCaseSpace(component.GetType().Name);
                                    var fieldsCount   = GUILayoutExt.GetFieldsCount(component);
                                    if (fieldsCount == 0)
                                    {
                                        EditorGUI.BeginDisabledGroup(true);
                                        EditorGUILayout.Toggle(componentName, true);
                                        EditorGUI.EndDisabledGroup();
                                    }
                                    else if (fieldsCount == 1)
                                    {
                                        var changed = GUILayoutExt.DrawFields(DataConfigEditor.multipleWorldEditor, components, componentName);
                                        if (changed == true)
                                        {
                                            slice.Set(components);
                                            this.Save(slice.configs);
                                        }
                                    }
                                    else
                                    {
                                        GUILayout.BeginHorizontal();
                                        {
                                            GUILayout.Space(18f);
                                            GUILayout.BeginVertical();
                                            {
                                                var key     = "ME.ECS.WorldsViewerEditor.FoldoutTypes." + component.GetType().FullName;
                                                var foldout = EditorPrefs.GetBool(key, true);
                                                GUILayoutExt.FoldOut(ref foldout, componentName, () => {
                                                    var changed = GUILayoutExt.DrawFields(DataConfigEditor.multipleWorldEditor, components);
                                                    if (changed == true)
                                                    {
                                                        slice.Set(components);
                                                        this.Save(slice.configs);
                                                    }
                                                });
                                                EditorPrefs.SetBool(key, foldout);
                                            }
                                            GUILayout.EndVertical();
                                        }
                                        GUILayout.EndHorizontal();
                                    }
                                }

                                GUILayoutExt.DrawComponentHelp(component.GetType());
                                this.DrawShared(component);
                            }
                            GUILayout.EndVertical();

                            GUILayoutExt.Separator();
                        }
                    });

                    GUILayoutExt.DrawAddComponentMenu(usedComponentsAll, (addType, isUsed) => {
                        foreach (var dataConfigInner in slice.configs)
                        {
                            if (isUsed == true)
                            {
                                this.OnRemoveComponent(addType);
                                usedComponentsAll.Remove(addType);
                                for (int i = 0; i < dataConfigInner.structComponents.Length; ++i)
                                {
                                    if (dataConfigInner.structComponents[i].GetType() == addType)
                                    {
                                        var list = dataConfigInner.structComponents.ToList();
                                        list.RemoveAt(i);
                                        dataConfigInner.structComponents = list.ToArray();
                                        //dataConfigInner.OnScriptLoad();
                                        this.Save(dataConfigInner);
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                usedComponentsAll.Add(addType);
                                System.Array.Resize(ref dataConfigInner.structComponents, dataConfigInner.structComponents.Length + 1);
                                dataConfigInner.structComponents[dataConfigInner.structComponents.Length - 1] = (IStructComponentBase)System.Activator.CreateInstance(addType);
                                //dataConfigInner.OnScriptLoad();
                                this.Save(dataConfigInner);
                                this.OnAddComponent(addType);
                            }
                        }
                    });

                    return;
                }

                GUILayoutExt.DrawHeader("Add Struct Components:");
                GUILayoutExt.Separator();

                GUILayoutExt.Padding(4f, () => {
                    var usedComponents = new System.Collections.Generic.HashSet <System.Type>();

                    this.serializedObject.Update();
                    if (GUILayoutExt.DrawFieldsSingle(this.search, this, DataConfigEditor.multipleWorldEditor, dataConfig.structComponents,
                                                      (index, component, prop) => {
                        GUILayout.BeginVertical();
                    },
                                                      (index, component, prop) => {
                        if (component == null)
                        {
                            return;
                        }

                        usedComponents.Add(component.GetType());

                        GUILayoutExt.DrawComponentHelp(component.GetType());
                        this.DrawComponentTemplatesUsage(dataConfig, component);
                        this.DrawShared(component);

                        GUILayout.EndVertical();

                        {
                            var lastRect = GUILayoutUtility.GetLastRect();
                            if (Event.current.type == EventType.ContextClick && lastRect.Contains(Event.current.mousePosition) == true)
                            {
                                var menu = new GenericMenu();
                                if (this.CanMove(dataConfig, index, index - 1) == true)
                                {
                                    menu.AddItem(new GUIContent("Move Up"), false, () => { this.MoveElement(dataConfig, index, index - 1); });
                                }
                                else
                                {
                                    menu.AddDisabledItem(new GUIContent("Move Up"));
                                }

                                if (this.CanMove(dataConfig, index, index + 1) == true)
                                {
                                    menu.AddItem(new GUIContent("Move Down"), false, () => { this.MoveElement(dataConfig, index, index + 1); });
                                }
                                else
                                {
                                    menu.AddDisabledItem(new GUIContent("Move Down"));
                                }

                                menu.AddItem(new GUIContent("Delete"), false, () => {
                                    var list = dataConfig.structComponents.ToList();
                                    this.OnRemoveComponent(list[index].GetType());
                                    list.RemoveAt(index);
                                    dataConfig.structComponents = list.ToArray();
                                    //dataConfig.OnScriptLoad();
                                    this.Save(dataConfig);
                                });

                                this.OnComponentMenu(menu, index);

                                menu.ShowAsContext();
                            }
                        }

                        GUILayoutExt.Separator();
                    }) == true)
                    {
                        this.serializedObject.ApplyModifiedProperties();
                        this.Save(dataConfig);
                    }

                    GUILayoutExt.DrawAddComponentMenu(usedComponents, (addType, isUsed) => {
                        if (isUsed == true)
                        {
                            this.OnRemoveComponent(addType);
                            usedComponents.Remove(addType);
                            for (int i = 0; i < dataConfig.structComponents.Length; ++i)
                            {
                                if (dataConfig.structComponents[i].GetType() == addType)
                                {
                                    var list = dataConfig.structComponents.ToList();
                                    list.RemoveAt(i);
                                    dataConfig.structComponents = list.ToArray();
                                    //dataConfig.OnScriptLoad();
                                    this.Save(dataConfig);
                                    break;
                                }
                            }
                        }
                        else
                        {
                            usedComponents.Add(addType);
                            System.Array.Resize(ref dataConfig.structComponents, dataConfig.structComponents.Length + 1);
                            dataConfig.structComponents[dataConfig.structComponents.Length - 1] = (IStructComponentBase)System.Activator.CreateInstance(addType);
                            //dataConfig.OnScriptLoad();
                            this.Save(dataConfig);
                            this.OnAddComponent(addType);
                        }
                    });
                });

                GUILayoutExt.DrawHeader("Remove Struct Components:");
                GUILayoutExt.Separator();

                // Remove struct components
                GUILayoutExt.Padding(4f, () => {
                    var usedComponents = new System.Collections.Generic.HashSet <System.Type>();

                    var kz         = 0;
                    var registries = dataConfig.removeStructComponents;
                    for (int i = 0; i < registries.Length; ++i)
                    {
                        var registry = registries[i];
                        if (GUILayoutExt.IsSearchValid(registry, this.search) == false)
                        {
                            continue;
                        }
                        var type = registry.GetType();

                        usedComponents.Add(type);

                        var backColor       = GUI.backgroundColor;
                        GUI.backgroundColor = new Color(1f, 1f, 1f, kz++ % 2 == 0 ? 0f : 0.05f);

                        GUILayout.BeginVertical(backStyle);
                        {
                            GUI.backgroundColor = backColor;
                            var componentName   = GUILayoutExt.GetStringCamelCaseSpace(type.Name);

                            EditorGUI.BeginDisabledGroup(true);
                            EditorGUILayout.Toggle(componentName, true);
                            EditorGUI.EndDisabledGroup();

                            GUILayoutExt.DrawComponentHelp(type);
                            this.DrawComponentTemplatesUsage(dataConfig, dataConfig.removeStructComponents[i]);
                        }
                        GUILayout.EndVertical();

                        GUILayoutExt.Separator();
                    }

                    GUILayoutExt.DrawAddComponentMenu(usedComponents, (addType, isUsed) => {
                        if (isUsed == true)
                        {
                            this.OnRemoveComponentFromRemoveList(addType);
                            usedComponents.Remove(addType);
                            for (int i = 0; i < dataConfig.removeStructComponents.Length; ++i)
                            {
                                if (dataConfig.removeStructComponents[i].GetType() == addType)
                                {
                                    var list = dataConfig.removeStructComponents.ToList();
                                    list.RemoveAt(i);
                                    dataConfig.removeStructComponents = list.ToArray();
                                    //dataConfig.OnScriptLoad();
                                    this.Save(dataConfig);
                                    break;
                                }
                            }
                        }
                        else
                        {
                            usedComponents.Add(addType);
                            System.Array.Resize(ref dataConfig.removeStructComponents, dataConfig.removeStructComponents.Length + 1);
                            dataConfig.removeStructComponents[dataConfig.removeStructComponents.Length - 1] = (IStructComponentBase)System.Activator.CreateInstance(addType);
                            //dataConfig.OnScriptLoad();
                            this.Save(dataConfig);
                            this.OnAddComponentFromRemoveList(addType);
                        }
                    });
                });

                if ((dataConfig is ME.ECS.DataConfigs.DataConfigTemplate) == false)
                {
                    this.DrawTemplates(dataConfig);
                }
            }
        }