void ShowHeightmaps()
    {
        LandmassEditorUtilities editorUtilities = LandmassEditorUtilities.Instance;
        ImporterConfiguration   importCfg       = editorUtilities.ImportCfg;

        EGL.BeginVertical();
        {
            GUILayout.Label("The settings for processing heightmaps.");

            EGL.Separator();

            EGL.BeginVertical(GuiUtils.Skin.box);
            {
                GUILayout.Label("Postfix for heightmap files.");
                importCfg.HeightmapTag = EGL.TextField("Name postfix", importCfg.HeightmapTag);
            }
            EGL.EndVertical();

            EGL.Separator();

            EGL.BeginVertical(GuiUtils.Skin.box);
            {
                GUILayout.Label("Heightmap file specifications. Please use raw file\nwith x^2+1 dimensions.");
                importCfg.HeightmapExtention = EGL.TextField("File extention", importCfg.HeightmapExtention);
                importCfg.HeightmapFlipX     = EGL.Toggle("Mirror X", importCfg.HeightmapFlipX);
                importCfg.HeightmapFlipY     = EGL.Toggle("Mirror Y", importCfg.HeightmapFlipY);
                importCfg.HeightFormat       = (HeightfileFormat)EditorGUILayout.EnumPopup("Byte Format", importCfg.HeightFormat);
            }
            EGL.EndVertical();
        }
        EGL.EndVertical();
    }
    // Todo: Or get them from a selected terrain in the scene.
    void GetPrototypesFromSelectedTerrain()
    {
        LandmassEditorUtilities editorUtilities = LandmassEditorUtilities.Instance;

        TerrainData terrainData = null;

        // See if the selected object is a Terrain object. If so, get its terrainData.
        GameObject terrainObject = Selection.activeGameObject;

        if (terrainObject != null)
        {
            Terrain terrain = terrainObject.GetComponent <Terrain>();

            if (terrain != null)
            {
                terrainData = terrain.terrainData;
            }
        }
        else
        {
            // See if the selected object is a TerrainData asset
            terrainData = Selection.activeObject as TerrainData;
        }

        if (terrainData != null)
        {
            editorUtilities.SplatPrototypes.Clear();
            foreach (SplatPrototype prototype in terrainData.splatPrototypes)
            {
                editorUtilities.SplatPrototypes.Add(prototype);
            }
        }
    }
    void ShowSettings()
    {
        LandmassEditorUtilities editorUtilities = LandmassEditorUtilities.Instance;
        ImporterConfiguration   importCfg       = editorUtilities.ImportCfg;

        EGL.BeginVertical();
        {
            EGL.Separator();

            GUILayout.Label("LOD Levels");

            EGL.BeginVertical(GuiUtils.Skin.box);
            {
                if (importCfg.LodLevels.Count >= 4)
                {
                    GUI.enabled = false;
                }
                if (GUILayout.Button("Add LOD Level"))
                {
                    importCfg.LodLevels.Add(new LodLevel());
                    importCfg.IsDirty = true; // Todo: Nasty
                }
                GUI.enabled = true;

                // Show the list of LODS
                EGL.BeginVertical();
                {
                    _lodScrollPos = EGL.BeginScrollView(_lodScrollPos, GUILayout.MinHeight(96f), GUILayout.MaxHeight(Screen.height));
                    {
                        var removeThese = new List <LodLevel>();
                        int i           = 0;
                        foreach (LodLevel lod in importCfg.LodLevels)
                        {
                            if (ShowLodLevel(lod, i))
                            {
                                removeThese.Add(lod);
                                importCfg.IsDirty = true; // Nasty
                            }
                            i++;
                        }
                        foreach (LodLevel lod in removeThese)
                        {
                            importCfg.LodLevels.Remove(lod);
                        }
                    }
                    EGL.EndScrollView();
                }
                EGL.EndVertical();

                EGL.Space();

                GUILayout.Label("Control how many assets are processed in one go.");
                importCfg.BatchLimit = EGL.IntField("Batch limit", importCfg.BatchLimit);
                GUILayout.Label("Larger batches mean faster processing but require\nmore memory. Change this with care, or Unity's\nmemory might run out!");
            }
            EGL.EndVertical();
        }
        EGL.EndVertical();
    }
    void OnDestroy()
    {
        LandmassEditorUtilities editorUtilities = LandmassEditorUtilities.Instance;

        if (editorUtilities.ImportCfg.IsDirty)
        {
            if (EditorUtility.DisplayDialog("You have unsaved settings", "Do you want to save?", "Yes", "No"))
            {
                editorUtilities.SaveSettings();
            }
        }
    }
    void OnGUI()
    {
        LandmassEditorUtilities editorUtilities = LandmassEditorUtilities.Instance;

        if (editorUtilities == null)
        {
            GUILayout.Label("No running instance of LandmassImporter found");
            return;
        }

        if (editorUtilities.IsProcessing)
        {
            ShowProgressBar();
        }

        GUI.enabled = !editorUtilities.IsProcessing;

        EGL.BeginVertical();
        {
            EGL.Separator();

            _currentState = (MenuState)GUILayout.Toolbar((int)_currentState, menuTitles);

            EGL.BeginHorizontal();
            {
                _globalScrollPos = EGL.BeginScrollView(_globalScrollPos, GuiUtils.Skin.box);
                {
                    EGL.BeginVertical();
                    {
                        EGL.Separator();

                        _menus[_currentState]();
                        GUILayout.FlexibleSpace();

                        EGL.Separator();
                    }
                    EGL.EndVertical();
                }
                EGL.EndScrollView();
            }
            EGL.EndHorizontal();

            EGL.Separator();

            ShowSaveButtons();

            GUILayout.Space(16);
        }
        EGL.EndVertical();

        GUI.enabled = true;
    }
    void OnInspectorUpdate()
    {
        Repaint();

        LandmassEditorUtilities utils = LandmassEditorUtilities.Instance;

        while (_queuedCalls.Count > 0)
        {
            _queuedCalls.Dequeue()();
        }

        if (_doTiledImport)
        {
            utils.ImportFolderIntoScene(_tiledInputLodLevel, _taskProgressToken);
            _doTiledImport = false;
        }
    }
    void ShowTerrainSettings()
    {
        LandmassEditorUtilities editorUtilities = LandmassEditorUtilities.Instance;
        ImporterConfiguration   importCfg       = editorUtilities.ImportCfg;
        TerrainConfiguration    terrainStreamingConfiguration = importCfg.TerrainConfiguration;

        EGL.BeginVertical();
        {
            EGL.BeginVertical(GuiUtils.Skin.box);
            {
                if (GUILayout.Button("Apply to selected TerrainData assets"))
                {
                    QueueCall(editorUtilities.ApplyDimensionsToSelection);
                }
            }
            EGL.EndVertical();

            EGL.Separator();

            EGL.BeginVertical(GuiUtils.Skin.box);
            {
                GUILayout.Label("In-game terrain LOD settings.");
                terrainStreamingConfiguration.HeightmapPixelError = EGL.Slider("Pixel Error", terrainStreamingConfiguration.HeightmapPixelError, 1f, 200f);
                terrainStreamingConfiguration.BasemapDistance     = EGL.FloatField("Basemap Dist.", terrainStreamingConfiguration.BasemapDistance);
                terrainStreamingConfiguration.CastShadows         = EGL.Toggle("Cast Shadows", terrainStreamingConfiguration.CastShadows);
                EGL.Separator();
                terrainStreamingConfiguration.DetailObjectDistance    = EGL.Slider("Detail Distance", terrainStreamingConfiguration.DetailObjectDistance, 0f, 250f);
                terrainStreamingConfiguration.DetailObjectDensity     = EGL.Slider("Detail Density", terrainStreamingConfiguration.DetailObjectDensity, 0f, 1f);
                terrainStreamingConfiguration.TreeDistance            = EGL.Slider("Tree Distance", terrainStreamingConfiguration.TreeDistance, 0f, 2000f);
                terrainStreamingConfiguration.TreeBillboardDistance   = EGL.Slider("Billboard Start", terrainStreamingConfiguration.TreeBillboardDistance, 50f, 2000f);
                terrainStreamingConfiguration.TreeCrossFadeLength     = EGL.Slider("Fade Length", terrainStreamingConfiguration.TreeCrossFadeLength, 0f, 200f);
                terrainStreamingConfiguration.TreeMaximumFullLODCount = EGL.IntSlider("Max Mesh Trees", terrainStreamingConfiguration.TreeMaximumFullLODCount, 0, 500);
                EGL.Separator();

                if (GUILayout.Button("Apply to selected Scene assets"))
                {
                    QueueCall(editorUtilities.ApplyTerrainLODSettingsToSelection);
                }
            }
            EGL.EndVertical();
        }
        EGL.EndVertical();
    }
    void ShowSaveButtons()
    {
        LandmassEditorUtilities editorUtilities = LandmassEditorUtilities.Instance;
        ImporterConfiguration   importCfg       = editorUtilities.ImportCfg;

        EGL.BeginVertical();
        {
            EGL.BeginHorizontal();
            {
                EGL.Separator();

                if (GUILayout.Button("Save Settings"))
                {
                    editorUtilities.SaveSettings();
                }
                if (GUILayout.Button("Load Settings"))
                {
                    editorUtilities.LoadSettings();
                }
                GUI.enabled = true;

                EGL.Separator();
            }
            EGL.EndHorizontal();

            EGL.BeginHorizontal();
            {
                GUILayout.FlexibleSpace();
                if (importCfg.IsDirty)
                {
                    GUILayout.Label("You have unsaved settings.");
                }
                GUILayout.FlexibleSpace();
            }
            EGL.EndHorizontal();
        }
        EGL.EndVertical();
    }
    void ShowTreemaps()
    {
        LandmassEditorUtilities editorUtilities = LandmassEditorUtilities.Instance;
        ImporterConfiguration   importCfg       = editorUtilities.ImportCfg;

        EGL.BeginVertical();
        {
            GUILayout.Label("The settings for processing tree maps.");

            EGL.Separator();

            EGL.BeginVertical(GuiUtils.Skin.box);
            {
                GUILayout.Label("Postfix for treemap files.");
                importCfg.TreemapTag = EGL.TextField("Name postfix", importCfg.TreemapTag);
            }
            EGL.EndVertical();

            EGL.Separator();

            EGL.BeginVertical(GuiUtils.Skin.box);
            {
                GUILayout.Label("Treemap file specifications. Please use x^2.");
                importCfg.SplatmapExtention = EGL.TextField("File extention", importCfg.SplatmapExtention);
            }
            EGL.EndVertical();

            EGL.Separator();

            EGL.BeginVertical(GuiUtils.Skin.box);
            {
                GUILayout.Label("The prototypes to assign. (Current count: " + editorUtilities.TreePrototypes.Count + ")");

                EGL.Separator();

                EGL.BeginHorizontal();
                {
                    if (editorUtilities.TreePrototypes.Count >= 8)
                    {
                        GUI.enabled = false;
                    }
                    if (GUILayout.Button("Add Prototype"))
                    {
                        editorUtilities.TreePrototypes.Add(new TreePrototype());
                        importCfg.IsDirty = true; // Todo: Nasty
                    }
                    GUI.enabled = true;
                }
                EGL.EndHorizontal();

                // Show the list
                EGL.BeginVertical();
                {
                    _prototypeScrollPos = EGL.BeginScrollView(_prototypeScrollPos, GUILayout.MinHeight(96f), GUILayout.MaxHeight(Screen.height));
                    {
                        List <TreePrototype> removeThese = new List <TreePrototype>();
                        int i = 0;
                        foreach (TreePrototype prototype in editorUtilities.TreePrototypes)
                        {
                            if (ShowTreePrototype(prototype, i))
                            {
                                removeThese.Add(prototype);
                                importCfg.IsDirty = true; // Nasty
                            }
                            i++;
                        }
                        foreach (TreePrototype prototype in removeThese)
                        {
                            editorUtilities.TreePrototypes.Remove(prototype);
                        }
                    }
                    EGL.EndScrollView();
                }
                EGL.EndVertical();
            }
            EGL.EndVertical();
        }
        EGL.EndVertical();
    }
    void ShowDetailMaps()
    {
        LandmassEditorUtilities editorUtilities = LandmassEditorUtilities.Instance;
        ImporterConfiguration   importCfg       = editorUtilities.ImportCfg;

        EGL.BeginVertical();
        {
            GUILayout.Label("The settings for processing detail maps.");

            EGL.Separator();

            EGL.BeginVertical(GuiUtils.Skin.box);
            {
                GUILayout.Label("Postfix for detailmap files.");
                importCfg.SplatmapTag = EGL.TextField("Name postfix", importCfg.SplatmapTag);
            }
            EGL.EndVertical();

            EGL.Separator();

            EGL.BeginVertical(GuiUtils.Skin.box);
            {
                GUILayout.Label("Splatmap file specifications. Please use x^2.");
                importCfg.SplatmapExtention = EGL.TextField("File extention", importCfg.SplatmapExtention);
                importCfg.SplatmapFlipX     = EGL.Toggle("Mirror X", importCfg.SplatmapFlipX);
                importCfg.SplatmapFlipY     = EGL.Toggle("Mirror Y", importCfg.SplatmapFlipY);
            }
            EGL.EndVertical();

            EGL.Separator();

            EGL.BeginVertical(GuiUtils.Skin.box);
            {
                GUILayout.Label("The textures to assign. (Current count: " + editorUtilities.DetailPrototypes.Count + ")");

                EGL.Separator();

                EGL.BeginHorizontal();
                {
                    if (editorUtilities.DetailPrototypes.Count >= 8)
                    {
                        GUI.enabled = false;
                    }
                    if (GUILayout.Button("Add Prototype"))
                    {
                        editorUtilities.DetailPrototypes.Add(new DetailPrototype());
                        importCfg.IsDirty = true; // Todo: Nasty, because the above prototypes still need to be converted to a serializable format, which is not directly done here
                    }
                    GUI.enabled = true;
                }
                EGL.EndHorizontal();

                // Show the list
                EGL.BeginVertical();
                {
                    _prototypeScrollPos = EGL.BeginScrollView(_prototypeScrollPos, GUILayout.MinHeight(96f), GUILayout.MaxHeight(Screen.height));
                    {
                        List <DetailPrototype> removeThese = new List <DetailPrototype>();
                        int i = 0;
                        foreach (DetailPrototype prototype in editorUtilities.DetailPrototypes)
                        {
                            if (ShowDetailPrototype(prototype, i))
                            {
                                removeThese.Add(prototype);
                                importCfg.IsDirty = true; // Nasty
                            }
                            i++;
                        }
                        foreach (DetailPrototype prototype in removeThese)
                        {
                            editorUtilities.DetailPrototypes.Remove(prototype);
                        }
                    }
                    EGL.EndScrollView();
                }
                EGL.EndVertical();
            }
            EGL.EndVertical();
        }
        EGL.EndVertical();
    }
    void ShowSplatmaps()
    {
        LandmassEditorUtilities editorUtilities = LandmassEditorUtilities.Instance;
        ImporterConfiguration   importCfg       = editorUtilities.ImportCfg;

        EGL.BeginVertical();
        {
            GUILayout.Label("The settings for processing splatmaps.");

            EGL.Separator();

            EGL.BeginVertical(GuiUtils.Skin.box);
            {
                GUILayout.Label("Postfix for splatmap files.");
                importCfg.SplatmapTag = EGL.TextField("Name postfix", importCfg.SplatmapTag);
            }
            EGL.EndVertical();

            EGL.Separator();

            EGL.BeginVertical(GuiUtils.Skin.box);
            {
                GUILayout.Label("Splatmap file specifications. Please use x^2.");
                importCfg.SplatmapExtention = EGL.TextField("File extention", importCfg.SplatmapExtention);
                importCfg.SplatmapFlipX     = EGL.Toggle("Mirror X", importCfg.SplatmapFlipX);
                importCfg.SplatmapFlipY     = EGL.Toggle("Mirror Y", importCfg.SplatmapFlipY);
                importCfg.TrimEmptyChannels = EGL.Toggle("Trim empty", importCfg.TrimEmptyChannels);
                importCfg.NormalizationMode = (NormalizationMode)EditorGUILayout.EnumPopup("Normalize mode", importCfg.NormalizationMode);
            }
            EGL.EndVertical();

            EGL.Separator();

            EGL.BeginVertical(GuiUtils.Skin.box);
            {
                GUILayout.Label("The textures to assign. (Current count: " + editorUtilities.SplatPrototypes.Count + ")");

                EGL.Separator();

                EGL.BeginHorizontal();
                {
                    if (editorUtilities.SplatPrototypes.Count >= 8)
                    {
                        GUI.enabled = false;
                    }
                    if (GUILayout.Button("Add Prototype"))
                    {
                        editorUtilities.SplatPrototypes.Add(new SplatPrototype());
                        importCfg.IsDirty = true; // Todo: Nasty
                    }
                    GUI.enabled = true;

                    if (GUILayout.Button("Grab from Selected Terrain Object or Asset"))
                    {
                        GetPrototypesFromSelectedTerrain();
                        importCfg.IsDirty = true; // Todo: Nasty
                    }
                }
                EGL.EndHorizontal();

                // Show the list
                EGL.BeginVertical();
                {
                    _prototypeScrollPos = EGL.BeginScrollView(_prototypeScrollPos, GUILayout.MinHeight(96f), GUILayout.MaxHeight(Screen.height));
                    {
                        List <SplatPrototype> removeThese = new List <SplatPrototype>();
                        int i = 0;
                        foreach (SplatPrototype splatPrototype in editorUtilities.SplatPrototypes)
                        {
                            if (ShowSplatPrototype(splatPrototype, i))
                            {
                                removeThese.Add(splatPrototype);
                                importCfg.IsDirty = true; // Nasty
                            }
                            i++;
                        }
                        foreach (SplatPrototype splatPrototype in removeThese)
                        {
                            editorUtilities.SplatPrototypes.Remove(splatPrototype);
                        }
                    }
                    EGL.EndScrollView();
                }
                EGL.EndVertical();
            }
            EGL.EndVertical();
        }
        EGL.EndVertical();
    }