Esempio n. 1
0
        public override void OnGUI(string searchContext)
        {
            DrawInfo();

            EditorGUILayout.Separator();
            EditorGUILayoutUtility.HorizontalLine(2f, 0.95f);

            for (int i = 0; i < m_settingsItems.Count; i++)
            {
                ISettingsItem settingsItem = m_settingsItems[i];

                EditorGUILayoutUtility.RichLabelField(string.Format("<b>{0}</b>", settingsItem.Name));

                using (new EditorGUI.IndentLevelScope())
                {
                    settingsItem.OnGUI();
                }

                if (i < m_settingsItems.Count - 1)
                {
                    EditorGUILayout.Separator();
                    EditorGUILayoutUtility.HorizontalLine(1f, 0.85f);
                }
            }
        }
Esempio n. 2
0
        public override void OnInspectorGUI()
        {
            serializedObject.Update();
            //Name
            EditorGUILayoutUtility.DrawHeader(Contents.nameLabel);
            EditorGUILayout.Space();

            //SpriteView
            EditorGUILayoutUtility.DrawHeader(Contents.spriteViewLabel);
            DoSpriteView();

            if (targets.Length == 1)
            {
                DoDirectionRangeGUI();
            }
            DoSpriteViewForeground();
            if (targets.Length == 1)
            {
                DoDirectionRange();
                DoRange();
            }
            ChangeVariable();
            EditorGUILayout.Space();

            //Sprites
            EditorGUILayoutUtility.DrawHeader(Contents.spritesLabel);
            ShowDirection();
            ShowSprites(currentAngle);
            serializedObject.ApplyModifiedProperties();


            if (GUI.Button(EditorGUILayout.GetControlRect(), "Convert To Animation"))
            {
                Export();
            }

            //Animator
            EditorGUI.BeginChangeCheck();
            AnimatorController newAnimator = EditorGUILayout.ObjectField("Current Animator", animator, typeof(AnimatorController), false) as AnimatorController;

            if (EditorGUI.EndChangeCheck())
            {
                RegisterUndo("Change Current Animator");
                animator = newAnimator;
                serializedObject.ApplyModifiedProperties();
            }
        }
Esempio n. 3
0
        private static void DrawInfo()
        {
            using (new GUIColorScope(new Color(0.6f, 0.6f, 0.6f)))
            {
                EditorGUILayoutUtility.RichLabelField("<b>Atlas Utility Library</b> by David Knopp");
                EditorGUILayout.LabelField(string.Format("Version {0}", Version.Full));
            }

            EditorGUILayout.BeginHorizontal(GUILayout.Width(300f));

            if (GUILayout.Button("View documentation"))
            {
                Application.OpenURL("https://david-knopp.github.io/Atlas/index.html");
            }

            if (GUILayout.Button("View on Github"))
            {
                Application.OpenURL("https://github.com/david-knopp/Atlas");
            }

            EditorGUILayout.EndHorizontal();
        }
Esempio n. 4
0
    private void OnGUI()
    {
        s = EditorGUILayoutUtility.Popup(s, ss);

        e = (eProperty)EditorGUILayoutUtility.RemarkEnumPopup(e);
    }
Esempio n. 5
0
    protected void OnGUI()
    {
        #region Event Link
        //EditorApplication.playModeStateChanged -= SaveLoadOpenedScenes;
        //EditorApplication.playModeStateChanged += SaveLoadOpenedScenes;
        #endregion Event Link

        #region Load Data
        string   searchPattern            = "*.unity";
        string[] filePaths                = Directory.GetFiles(_scenesFolderPath, searchPattern);
        EditorBuildSettingsScene[] scenes = null;
        scenes = EditorBuildSettings.scenes;
        List <string> scenePaths = scenes.Select(scene => scene.path).ToList();
        #endregion Load Data

        #region Display
        _scrollPos = GUILayout.BeginScrollView(_scrollPos);
        #region Play Mode
        GUILayout.Label("SCENE SELECTOR", EditorStyles.boldLabel);
        //SirenixEditorGUI.Title("SCENE SELECTOR", "", TextAlignment.Center, true);
        EditorGUILayout.Space();

        if (EditorApplication.isPlaying == false)
        {
            if (GUILayout.Button("Play", GUILayout.Height(50)))
            {
                EditorApplication.isPlaying = true;
            }
        }
        else
        {
            if (GUILayout.Button("Stop", GUILayout.Height(50)))
            {
                EditorApplication.isPlaying = false;
            }
        }

        _isAutoPlayModeEnabled = EditorGUILayout.Toggle("Auto Play Mode Enabled", _isAutoPlayModeEnabled);

        if (_isAutoPlayModeEnabled)
        {
            EditorApplication.playModeStateChanged -= SaveLoadOpenedScenes;
            EditorApplication.playModeStateChanged += SaveLoadOpenedScenes;
        }
        else
        {
            EditorApplication.playModeStateChanged -= SaveLoadOpenedScenes;
        }

        EditorGUILayout.Space();
        #endregion Play Mode

        #region Scenes In Build Settings
        EditorGUILayoutUtility.HorizontalLine();
        EditorGUILayout.Space();

        GUILayout.Label("SCENES IN BUILD SETTINGS", EditorStyles.boldLabel);
        //SirenixEditorGUI.Title("SCENES IN BUILD SETTINGS", "", TextAlignment.Center, true);

        for (int i = 0; i < scenes.Length; i++)
        {
            EditorGUILayout.BeginHorizontal();
            Scene scene = EditorSceneManager.GetSceneByPath(scenePaths[i]);
            if (!scene.isLoaded)
            {
                if (!scene.IsValid())
                {
                    GUI.backgroundColor = Color.grey;
                }
                else
                {
                    GUI.backgroundColor = Color.black;
                }
                if (GUILayout.Button(Path.GetFileNameWithoutExtension(scenePaths[i]), GUILayout.Height(40), GUILayout.Width(250)))
                {
                    EditorSceneManager.OpenScene(scenePaths[i], OpenSceneMode.AdditiveWithoutLoading);
                }
                GUI.backgroundColor = Color.grey;
                if (GUILayout.Button("Load", GUILayout.Height(40)))
                {
                    EditorSceneManager.OpenScene(scenePaths[i], OpenSceneMode.Additive);
                }
            }
            else
            {
                GUI.backgroundColor = Color.black;
                if (GUILayout.Button(Path.GetFileNameWithoutExtension(scenePaths[i]), GUILayout.Height(40), GUILayout.Width(250)))
                {
                }
                GUI.backgroundColor = Color.green;
                if (GUILayout.Button("Unload", GUILayout.Height(40)))
                {
                    EditorSceneManager.CloseScene(scene, false);
                }
            }

            //Display close scene load button
            if (scene.IsValid())
            {
                GUI.backgroundColor = Color.red;
                if (GUILayout.Button("X", GUILayout.Height(40), GUILayout.Width(40)))
                {
                    EditorSceneManager.CloseScene(scene, true);
                }
            }
            EditorGUILayout.EndHorizontal();
        }
        #endregion Scenes In Build Settings

        #region Scenes Not Build Settings
        EditorGUILayoutUtility.HorizontalLine();
        EditorGUILayout.Space();

        GUILayout.Label("SCENES NOT BUILD SETTINGS", EditorStyles.boldLabel);
        //SirenixEditorGUI.Title("SCENES NOT BUILD SETTINGS", "", TextAlignment.Center, true);

        for (int i = 0; i < filePaths.Length; i++)
        {
            if (scenePaths.Contains(filePaths[i]) == false)
            {
                EditorGUILayout.BeginHorizontal();
                Scene scene = EditorSceneManager.GetSceneByPath(filePaths[i]);
                if (!scene.isLoaded)
                {
                    if (!scene.IsValid())
                    {
                        GUI.backgroundColor = Color.grey;
                    }
                    else
                    {
                        GUI.backgroundColor = Color.black;
                    }
                    if (GUILayout.Button(Path.GetFileNameWithoutExtension(filePaths[i]), GUILayout.Height(40), GUILayout.Width(250)))
                    {
                        EditorSceneManager.OpenScene(filePaths[i], OpenSceneMode.AdditiveWithoutLoading);
                    }
                    GUI.backgroundColor = Color.grey;
                    if (GUILayout.Button("Load", GUILayout.Height(40)))
                    {
                        EditorSceneManager.OpenScene(filePaths[i], OpenSceneMode.Additive);
                    }
                }
                else
                {
                    GUI.backgroundColor = Color.black;
                    if (GUILayout.Button(Path.GetFileNameWithoutExtension(filePaths[i]), GUILayout.Height(40), GUILayout.Width(250)))
                    {
                    }
                    GUI.backgroundColor = Color.green;
                    if (GUILayout.Button("Unload", GUILayout.Height(40)))
                    {
                        EditorSceneManager.CloseScene(scene, false);
                    }
                }

                //Display close scene load button
                if (scene.IsValid())
                {
                    GUI.backgroundColor = Color.red;
                    if (GUILayout.Button("X", GUILayout.Height(40), GUILayout.Width(40)))
                    {
                        EditorSceneManager.CloseScene(scene, true);
                    }
                }
                EditorGUILayout.EndHorizontal();
            }
        }
        #endregion Scenes Not Build Settings
        GUILayout.EndScrollView();
        #endregion Display
    }
Esempio n. 6
0
 public static void HorizontalLine(Vector2 margin) => EditorGUILayoutUtility.HorizontalLine(DEFAULT_COLOR, DEFAULT_LINE_HEIGHT, margin);
Esempio n. 7
0
 public static void HorizontalLine() => EditorGUILayoutUtility.HorizontalLine(DEFAULT_COLOR, DEFAULT_LINE_HEIGHT, DEFAULT_LINE_MARGIN);
Esempio n. 8
0
 public static void HorizontalLine(Color color) => EditorGUILayoutUtility.HorizontalLine(color, DEFAULT_LINE_HEIGHT, DEFAULT_LINE_MARGIN);
Esempio n. 9
0
 public static void HorizontalLine(float height) => EditorGUILayoutUtility.HorizontalLine(DEFAULT_COLOR, height, DEFAULT_LINE_MARGIN);
Esempio n. 10
0
 public static void HorizontalLine(float height, Vector2 margin) => EditorGUILayoutUtility.HorizontalLine(DEFAULT_COLOR, height, margin);
Esempio n. 11
0
 public static void HorizontalLine(Color color, Vector2 margin) => EditorGUILayoutUtility.HorizontalLine(color, DEFAULT_LINE_HEIGHT, margin);
Esempio n. 12
0
 public static void HorizontalLine(Color color, float height) => EditorGUILayoutUtility.HorizontalLine(color, height, DEFAULT_LINE_MARGIN);
Esempio n. 13
0
    public override void OnInspectorGUI()
    {
        DrawDefaultInspector();
        if (Event.current.type == EventType.MouseMove)
        {
            Repaint();
        }
        else if (Event.current.type == EventType.MouseDown)
        {
            mouseDownEvent();
        }
        else if (Event.current.type == EventType.MouseDrag)
        {
            mouseDragEvent();
        }
        else if (Event.current.type == EventType.MouseUp)
        {
            mouseUpEvent();
        }

        EditorGUILayoutUtility.HorizontalLine(new Vector2(20f, 20f));
        EditorStyles.label.wordWrap = true;
        showInstructions            = EditorGUILayout.Foldout(showInstructions, "Instructions");
        if (showInstructions)
        {
            EditorGUILayout.LabelField("This tool is connects Unity to a Python-based server " +
                                       "that hosts a neural network trained to generate realistic looking heightmaps.");
            EditorGUILayout.LabelField("The output heightmaps are resolved at 128x128, but trained with 512x512 " +
                                       " heightmaps with a 3 arcsecond " +
                                       "resolution, which means that each pixel is 90m by 90m. Therefore, the returned heightmaps " +
                                       "are of size 46km x 46km and will have features of that size, making it not a great " +
                                       "tool if you aim to make a smaller terrain");
            EditorGUILayout.LabelField("First, ensure the python server is running. With 'python server_for_unity.py'");
            EditorGUILayout.LabelField("Next, click the 'connect' button in this tool. When you'd like to shut " +
                                       "the server down, click disconnect (required, otherwise the server will continue to run " +
                                       "after closing Unity)");
            EditorGUILayout.LabelField("The heightmap generation process uses two main components: " +
                                       "the style and the noise. The style guides the overall look of the current heightmap and " +
                                       "dictates key features like mountain ranges and canyons. The noise gives small perturbations " +
                                       "to the output from a specific style. Clicking 'new noise' and 'new style' will " +
                                       "give you a new noise or style to work with.");
            EditorGUILayout.LabelField("Every time a change is made, it is saved and can be reverted to by " +
                                       "using the 'iteration' slider.");
            GUILayout.Space(10);
            EditorGUILayout.LabelField("The main control over the neural network comes in the form of rules.");
            EditorGUILayout.LabelField("Rules allow the user to tell the neural network what kinds of output " +
                                       "we want. There rules are as follows:");
            EditorGUILayout.LabelField("Exact height: the network will try to match the exact height given to it");
            EditorGUILayout.LabelField("Raise: the network will try to maximize height in certain areas");
            EditorGUILayout.LabelField("Lower: the network will try to minimize height in certain areas");
            EditorGUILayout.LabelField("Ridges: the network will try to make this area more slanted/rigid");
            EditorGUILayout.LabelField("Smooth: the network will try to smooth out this area");
            EditorGUILayout.LabelField("Increase horizontal alignment: the network will try to make patterns " +
                                       "that follow a left-right pattern");
            EditorGUILayout.LabelField("Decrease horizontal alignment: the network will try to avoid patterns " +
                                       "that follow a left-right pattern");
            EditorGUILayout.LabelField("Increase vertical alignment: the network will try to make patterns " +
                                       "that follow an up-down pattern");
            EditorGUILayout.LabelField("Decrease vertical alignment: the network will try to make patterns " +
                                       "that follow an up-down pattern");
            EditorGUILayout.LabelField("These rules can be added by clicking the 'add rule' button, and then " +
                                       "selecting the rule desired with the dropdown. Then, the user can draw in the space above.");
            EditorGUILayout.LabelField("Drawing will draw with a brush diameter chosen with the brush size slider, and an " +
                                       "intensity of the intensity slider. The intensity determines how important it is for the " +
                                       "network to follow the rule in that location. High intensity (near 1) means we really want " +
                                       "the network to have this rule at this location, and low intensity means that it is not as " +
                                       "important. When intensity is 0 (default across the entire rule), the network won't try to " +
                                       "follow the rule at all in that spot. The only time intensity is something else is when Exact height is used, in " +
                                       "which case the network will try to match the exact heightmap drawn.");
            EditorGUILayout.LabelField("When drawing, only the rule selected (highlighted yellow) is updated. " +
                                       "A rule can be selected by clicking 'Select' next to it.");
            EditorGUILayout.LabelField("The color for different rules can be changed with the rule color.");
            EditorGUILayout.LabelField("Rules can be enabled or disabled by clicking the checkmark for " +
                                       "rule enabled.");

            EditorGUILayout.LabelField("When a desired ruleset is made, the user can click 'Train' to begin " +
                                       "the optimization process. The network will try to create a realistic heightmap " +
                                       "that follows the rules created. While it is training for 100 steps, the terrain " +
                                       "will be updated in realtime. Any iteration during training can be reverted to " +
                                       "by chosing the iteration using the slider.");
        }



        GUILayout.Space(10);
        showTipsAndTricks = EditorGUILayout.Foldout(showTipsAndTricks, "Tips and tricks");
        if (showTipsAndTricks)
        {
            EditorGUILayout.LabelField("1. Having too steep changes too close can make it difficult sometimes " +
                                       "for the network to optimize. Consider adding a buffer zone of 0 intensity between " +
                                       "large changes. For instance, if you'd like high elevation on the top and low elevation " +
                                       "on the bottom half, perhaps leave the middle third of the rule area with 0 intensity " +
                                       "so the network can be flexible in that area.");
            EditorGUILayout.LabelField("2. If the trained output heightmap doesn't match the rules close " +
                                       "enough for your liking you can click 'train' again.");
            EditorGUILayout.LabelField("3. If the output is close to what you like, try clicking " +
                                       "new noise to see small changes in your output");
            EditorGUILayout.LabelField("4. Use colormaps to give easy visualizations for rules you created. " +
                                       "For instance, use green for a rule to increase horizontal orientation, and red " +
                                       "to reduce horizontal orientation.");
            EditorGUILayout.LabelField("5. Avoid setting the resolution above 128. It will slow down performance.");
        }
        GUILayout.Space(10);
        showDebugging = EditorGUILayout.Foldout(showDebugging, "Debugging");
        if (showDebugging)
        {
            EditorGUILayout.LabelField("If the server seems unresponsive, check the python script. " +
                                       "If it is still alive, try clicking connect again in Unity and try your command again. " +
                                       "If that still doesn't work, you'll have to click connect, disconnect, and then start over again.");
        }

        EditorGUILayoutUtility.HorizontalLine(new Vector2(20f, 20f));

        HeightMapGenerator myScript = (HeightMapGenerator)target;

        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("Connect"))
        {
            connected = myScript.Connect();
        }

        if (GUILayout.Button("Disconnect"))
        {
            myScript.Disconnect();
            connected = false;
        }
        EditorGUILayout.EndHorizontal();

        if (Event.current.type == EventType.Repaint)
        {
            lastRect = GUILayoutUtility.GetLastRect();
        }
        if (lastRect != null)
        {
            currentWidth = lastRect.width;

            float rectWidth = currentWidth;
            if (rectWidth > maxRect)
            {
                rectWidth = maxRect;
            }

            GUILayout.Space(rectWidth + 2 * padding);
            float middle = lastRect.x + lastRect.width / 2;
            backgroundRect = new Rect(middle - rectWidth / 2,
                                      lastRect.y + lastRect.height + padding,
                                      rectWidth, rectWidth);

            if (lossTexture != null)
            {
                EditorGUI.DrawPreviewTexture(backgroundRect, lossTexture);
            }
        }


        EditorGUILayout.BeginHorizontal();
        GUILayout.Label("Brush size:");
        brushSize = EditorGUILayout.Slider(brushSize, 1, 50);
        GUILayout.Label("Brush intensity:");
        brushIntensity = EditorGUILayout.Slider(brushIntensity, 0.0f, 1.0f);
        EditorGUILayout.EndHorizontal();

        float wid = Screen.width * (1.0f / 6.0f);

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label("Rule number", GUILayout.Width(wid));
        GUILayout.Label("Rule enabled", GUILayout.Width(wid));
        GUILayout.Label("Rule", GUILayout.Width(wid));
        GUILayout.Label("Rule color", GUILayout.Width(wid));
        GUILayout.Label("", GUILayout.Width(wid));
        GUILayout.Label("", GUILayout.Width(wid));
        EditorGUILayout.EndHorizontal();

        //GUILayout.ExpandWidth (false);

        for (int i = 0; i < lossMasks.Count; i++)
        {
            if (lossIndSelected == i)
            {
                GUI.color           = Color.yellow;
                GUI.contentColor    = Color.yellow;
                GUI.backgroundColor = Color.yellow;
            }
            else
            {
                GUI.color           = Color.white;
                GUI.contentColor    = Color.white;
                GUI.backgroundColor = Color.white;
            }

            EditorGUILayout.BeginHorizontal();
            GUILayout.Label("" + i, GUILayout.Width(wid));
            lossEnabled[i]  = EditorGUILayout.Toggle("", lossEnabled[i], GUILayout.Width(wid));
            lossSelected[i] = EditorGUILayout.Popup("", lossSelected[i],
                                                    lossOptions, GUILayout.Width(wid));
            lossMaskColors[i] = EditorGUILayout.ColorField("", lossMaskColors[i], GUILayout.Width(wid));
            if (GUILayout.Button("Select"))
            {
                lossIndSelected = i;
            }
            if (GUILayout.Button("Remove"))
            {
                RemoveRule(i);
                i--;
            }
            GUILayout.Label("", GUILayout.Width(wid));
            EditorGUILayout.EndHorizontal();
        }
        GUI.color           = Color.white;
        GUI.contentColor    = Color.white;
        GUI.backgroundColor = Color.white;
        if (GUILayout.Button("Add rule"))
        {
            AddRule();
        }

        EditorGUI.BeginDisabledGroup(!connected);
        EditorGUI.BeginDisabledGroup(myScript.IsInProcess());
        if (GUILayout.Button("Train"))
        {
            if (atLeastOneStyleUnlocked())
            {
                myScript.setRequestFromMasks(masksToRequestStrings());
                EditorCoroutineUtility.StartCoroutine(myScript.GetHeightMapAsync(), this);
            }
            else
            {
                Debug.Log("Need at least one style unlocked to train");
            }
        }
        EditorGUILayout.BeginHorizontal();
        GUILayout.Label("Iteration:");
        int tempIterationChosen = EditorGUILayout.IntSlider(
            myScript.GetCurrentIteration(), 0, myScript.GetTotalIterations() - 1);

        if (tempIterationChosen != myScript.GetCurrentIteration())
        {
            EditorCoroutineUtility.StartCoroutine(myScript.SetCurrentIter(tempIterationChosen), this);
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayoutUtility.HorizontalLine(new Vector2(20f, 20f));

        wid = Screen.width * (1f / 3f);

        EditorGUILayout.BeginHorizontal();

        if (GUILayout.Button("New noise", GUILayout.Width(wid)))
        {
            EditorCoroutineUtility.StartCoroutine(myScript.GetNewNoise(), this);
        }
        if (GUILayout.Button("All new styles", GUILayout.Width(wid)))
        {
            EditorCoroutineUtility.StartCoroutine(myScript.GetAllNewStyles(), this);
        }

        /*
         * if(GUILayout.Button("New style"))
         * {
         *  EditorCoroutineUtility.StartCoroutine(myScript.GetNewStyle(), this);
         * }
         */
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label("Style size", GUILayout.Width(wid));
        GUILayout.Label("Get new random style", GUILayout.Width(wid));
        GUILayout.Label("Lock in training", GUILayout.Width(wid));
        EditorGUILayout.EndHorizontal();

        for (int i = 0; i < 6; i++)
        {
            EditorGUILayout.BeginHorizontal();
            int currSize = (int)(Mathf.Pow(2, 2 + i));
            GUILayout.Label(currSize + "x" + currSize + " style", GUILayout.Width(wid));
            if (GUILayout.Button("New style", GUILayout.Width(wid)))
            {
                EditorCoroutineUtility.StartCoroutine(myScript.GetNewStyle(i), this);
            }
            bool tempBool = EditorGUILayout.Toggle("", styleLocked[i], GUILayout.Width(wid));
            if (tempBool != styleLocked[i])
            {
                styleLocked[i] = tempBool;
                EditorCoroutineUtility.StartCoroutine(myScript.UpdateLockedStyles(styleLocked), this);
            }
            EditorGUILayout.EndHorizontal();
        }

        EditorGUILayout.BeginHorizontal();
        int tempHeightMapRes = EditorGUILayout.IntSlider(heightMapRes, 32, 1024);
        int exp = (int)(Mathf.Log(tempHeightMapRes, 2));

        heightMapRes = (int)(Mathf.Pow(2, exp));
        if (GUILayout.Button("Update resolution"))
        {
            myScript.SetHeightMapResolution(heightMapRes);
            EditorCoroutineUtility.StartCoroutine(myScript.UpdateHeightmapResolution(), this);
        }
        EditorGUILayout.EndHorizontal();

        EditorGUI.EndDisabledGroup();
        EditorGUI.EndDisabledGroup();

        Rect tempRect = GUILayoutUtility.GetLastRect();

        if (myScript.getTexture() != null)
        {
            Rect whereToDraw = new Rect();
            whereToDraw.x      = backgroundRect.x;
            whereToDraw.y      = tempRect.y + tempRect.height + padding;
            whereToDraw.width  = backgroundRect.width;
            whereToDraw.height = backgroundRect.width;
            GUILayout.Space(whereToDraw.height + 2 * padding);
            EditorGUI.DrawPreviewTexture(whereToDraw, myScript.getTexture());
        }
        lastBackgroundRect = backgroundRect;
        if (EditorApplication.timeSinceStartup > lastTextureUpdate + updateEvery)
        {
            updateLossTexture();
            lastTextureUpdate = (float)EditorApplication.timeSinceStartup;
        }
    }
        internal void DrawEditorGUI()
        {
            if (settings == null)
            {
                return;
            }

            GUILayout.BeginVertical();

            // Import Settings
            GUILayout.Label("Import Settings", EditorStyles.boldLabel);
            GUILayout.BeginHorizontal();
            GUILayout.Space(10);
            GUILayout.BeginVertical();

            // Excel Sheets Folder Path
            if (!string.IsNullOrEmpty(settings.ExcelWorkbookFilesFolderPath) && !Directory.Exists(settings.ExcelWorkbookFilesFolderPath))
            {
                settings.ExcelWorkbookFilesFolderPath = string.Empty;
            }

            settings.ExcelWorkbookFilesFolderPath = EditorGUILayoutUtility.FolderField(new GUIContent("Excel Workbook Files Folder Path",
                                                                                                      "The folder path where to locate excel workbook files."), settings.ExcelWorkbookFilesFolderPath, "Excel Workbook Files Folder Path", string.Empty, string.Empty, LabelWidth);

            // Metadata Persistent Store Path
            var metadataPersistentStoreAbsolutePath = EditorGUILayoutUtility.FolderField(new GUIContent("Metadata Persistent Store Path",
                                                                                                        "The folder path where to store metadata."), settings.MetadataPersistentStorePath, "Metadata Persistent Store Path", settings.MetadataPersistentStorePath, string.Empty, LabelWidth);

            if (EditorPath.IsAssetPath(metadataPersistentStoreAbsolutePath))
            {
                settings.MetadataPersistentStorePath = EditorPath.ConvertToAssetPath(metadataPersistentStoreAbsolutePath);
            }
            else
            {
                Debug.LogError("The 'Metadata Persistent Store Path' you choose is invalid path, please select the folder in the project!");
            }

            // Metadata Entity Scripts Store Path
            var entityScriptsStoreAbsolutePath = EditorGUILayoutUtility.FolderField(new GUIContent("Entity Scripts Store Path",
                                                                                                   "The folder path where to store metadata entity scripts."), settings.EntityScriptsStorePath, "Entity Scripts Store Path", settings.EntityScriptsStorePath, string.Empty, LabelWidth);

            if (EditorPath.IsAssetPath(entityScriptsStoreAbsolutePath))
            {
                settings.EntityScriptsStorePath = EditorPath.ConvertToAssetPath(entityScriptsStoreAbsolutePath);
            }
            else
            {
                Debug.LogError("The 'Entity Scripts Store Path' you choose is invalid path, please select the folder in the project!");
            }

            // Metadata Entity Namespace
            using (new EditorGUIFieldScope(LabelWidth))
            {
                settings.EntityScriptNamespace = EditorGUILayout.TextField(new GUIContent("Entity Script Namespace",
                                                                                          "The namespace of entity script."), settings.EntityScriptNamespace);
            }

            // Metadata Entity Property Comment Row Index
            using (new EditorGUIFieldScope(LabelWidth))
            {
                settings.EntityPropertyCommentRowIndex = EditorGUILayout.IntSlider(new GUIContent("Entity Property Comment Definition Row Index",
                                                                                                  "The row index of entity property comment definition."), settings.EntityPropertyCommentRowIndex, 0, MaxIntValue);
            }

            // Metadata Entity Property Type Row Index
            using (new EditorGUIFieldScope(LabelWidth))
            {
                settings.EntityPropertyTypeRowIndex = EditorGUILayout.IntSlider(new GUIContent("Entity Property Type Definition Row Index",
                                                                                               "The row index of entity property type definition."), settings.EntityPropertyTypeRowIndex, 0, MaxIntValue);
            }

            // Metadata Entity Property Name Row Index
            using (new EditorGUIFieldScope(LabelWidth))
            {
                settings.EntityPropertyNameRowIndex = EditorGUILayout.IntSlider(new GUIContent("Entity Property Name Definition Row Index",
                                                                                               "The row index of entity property name definition."), settings.EntityPropertyNameRowIndex, 0, MaxIntValue);
            }

            // Metadata Entity Property Value Starting Row Index
            using (new EditorGUIFieldScope(LabelWidth))
            {
                settings.EntityDataStartingRowIndex = EditorGUILayout.IntSlider(new GUIContent("Entity Data Starting Row Index",
                                                                                               "The row index and after will be entity data definitions."), settings.EntityDataStartingRowIndex, 0, MaxIntValue);
            }

            GUILayout.EndVertical();
            GUILayout.Space(10);
            GUILayout.EndHorizontal();

            GUILayout.Space(20);

            // Other Settings
            GUILayout.Label("Other Settings", EditorStyles.boldLabel);

            GUILayout.BeginHorizontal();
            GUILayout.Space(10);
            GUILayout.BeginVertical();

            // Data encryption/decryption
            using (new EditorGUIFieldScope(LabelWidth))
            {
                settings.DataEncryptionAndDecryption = EditorGUILayout.Toggle(new GUIContent("Data Encryption/Decryption",
                                                                                             "Generate database file with encryption, and load metadata with decryption."), settings.DataEncryptionAndDecryption);
            }

            GUILayout.EndVertical();
            GUILayout.Space(10);
            GUILayout.EndHorizontal();

            GUILayout.Space(20);

            using (new EditorGUIFieldScope(LabelWidth))
            {
                GUILayout.FlexibleSpace();
                if (GUILayout.Button("Build Metadata Assets", GUILayout.Width(LabelWidth), GUILayout.Height(25)))
                {
                    BuildAssets();
                    GUIUtility.ExitGUI();
                }
                GUILayout.FlexibleSpace();
            }

            GUILayout.Space(20);

            GUILayout.EndVertical();
        }