예제 #1
0
 public void UnregisterHLOD(HLOD hlod)
 {
     if (m_activeHLODs != null)
     {
         m_activeHLODs.Remove(hlod);
     }
 }
예제 #2
0
 public void RegisterHLOD(HLOD hlod)
 {
     if (m_activeHLODs == null)
     {
         m_activeHLODs     = new List <HLOD>();
         Camera.onPreCull += OnPreCull;
         RenderPipeline.beginCameraRendering += OnPreCull;
     }
     m_activeHLODs.Add(hlod);
 }
예제 #3
0
        public static HLOD Setup(GameObject root)
        {
            if (root.GetComponent <HLOD>() != null)
            {
                Debug.LogWarning("It has already been set.");
                return(null);
            }

            HLOD hlod = root.AddComponent <HLOD>();

            return(hlod);
        }
예제 #4
0
        public static IEnumerator Destroy(HLOD hlod)
        {
            var controller = hlod.GetComponent <HLODControllerBase>();

            if (controller == null)
            {
                yield break;
            }

            try
            {
                EditorUtility.DisplayProgressBar("Destroy HLOD", "Destrying HLOD files", 0.0f);
                var convertedPrefabObjects = hlod.ConvertedPrefabObjects;
                for (int i = 0; i < convertedPrefabObjects.Count; ++i)
                {
                    PrefabUtility.UnpackPrefabInstance(convertedPrefabObjects[i], PrefabUnpackMode.OutermostRoot,
                                                       InteractionMode.AutomatedAction);
                }

                var generatedObjects = hlod.GeneratedObjects;
                for (int i = 0; i < generatedObjects.Count; ++i)
                {
                    if (generatedObjects[i] == null)
                    {
                        continue;
                    }
                    var path = AssetDatabase.GetAssetPath(generatedObjects[i]);
                    if (string.IsNullOrEmpty(path) == false)
                    {
                        AssetDatabase.DeleteAsset(path);
                    }
                    else
                    {
                        //It means scene object.
                        //destory it.
                        Object.DestroyImmediate(generatedObjects[i]);
                    }

                    EditorUtility.DisplayProgressBar("Destroy HLOD", "Destrying HLOD files", (float)i / (float)generatedObjects.Count);
                }
                generatedObjects.Clear();

                Object.DestroyImmediate(controller);
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }

            EditorUtility.SetDirty(hlod.gameObject);
            EditorUtility.SetDirty(hlod);
        }
예제 #5
0
        static void OnSetup(MenuCommand command)
        {
            if (PrefabStageUtility.GetCurrentPrefabStage() == null ||
                PrefabStageUtility.GetCurrentPrefabStage().prefabContentsRoot == null)
            {
                Debug.LogError("Setup HLOD can only be used while prefab editing.");
                return;
            }

            GameObject root = PrefabStageUtility.GetCurrentPrefabStage().prefabContentsRoot;
            HLOD       hlod = HLODCreator.Setup(root);

            EditorSceneManager.MarkSceneDirty(root.scene);
        }
예제 #6
0
        public static IEnumerator Destroy(HLOD hlod)
        {
            var controller = hlod.GetComponent <ControllerBase>();

            if (controller == null)
            {
                yield break;
            }

            try
            {
                EditorUtility.DisplayProgressBar("Destory HLOD", "Destrying HLOD files", 0.0f);
                AssetDatabase.StartAssetEditing();

                var generatedObjects = hlod.GeneratedObjects;
                for (int i = 0; i < generatedObjects.Count; ++i)
                {
                    if (generatedObjects[i] == null)
                    {
                        continue;
                    }
                    var path = AssetDatabase.GetAssetPath(generatedObjects[i]);
                    if (string.IsNullOrEmpty(path) == false)
                    {
                        AssetDatabase.DeleteAsset(path);
                    }

                    EditorUtility.DisplayProgressBar("Destory HLOD", "Destrying HLOD files", (float)i / (float)generatedObjects.Count);
                }
                generatedObjects.Clear();

                Object.DestroyImmediate(controller);
            }
            finally
            {
                AssetDatabase.StopAssetEditing();
                EditorUtility.ClearProgressBar();
            }
        }
 static void OnGUI(HLOD hlod)
 {
 }
 public MaterialPreservingBatcher(HLOD hlod)
 {
     m_hlod = hlod;
 }
예제 #9
0
        public override void OnInspectorGUI()
        {
            serializedObject.Update();
            EditorGUI.BeginChangeCheck();

            HLOD hlod = target as HLOD;

            if (hlod == null)
            {
                EditorGUILayout.LabelField("HLOD is null.");
                return;
            }

            isShowCommon = EditorGUILayout.BeginFoldoutHeaderGroup(isShowCommon, "Common");
            if (isShowCommon == true)
            {
                EditorGUILayout.PropertyField(m_ChunkSizeProperty);

                m_ChunkSizeProperty.floatValue = HLODUtils.GetChunkSizePropertyValue(m_ChunkSizeProperty.floatValue);

                var bounds = hlod.GetBounds();
                int depth  = m_splitter.CalculateTreeDepth(bounds, m_ChunkSizeProperty.floatValue);

                EditorGUILayout.LabelField($"The HLOD tree will be created with {depth} levels.");
                if (depth > 5)
                {
                    EditorGUILayout.LabelField($"Node Level Count greater than 5 may cause a frozen Editor.", Styles.RedTextColor);
                    EditorGUILayout.LabelField($"I recommend keeping the level under 5.", Styles.RedTextColor);
                }


                m_LODSlider.Draw();
                EditorGUILayout.PropertyField(m_MinObjectSizeProperty);
            }
            EditorGUILayout.EndFoldoutHeaderGroup();


            isShowSimplifier = EditorGUILayout.BeginFoldoutHeaderGroup(isShowSimplifier, "Simplifier");
            if (isShowSimplifier == true)
            {
                if (m_SimplifierTypes.Length > 0)
                {
                    int simplifierIndex = Math.Max(Array.IndexOf(m_SimplifierTypes, hlod.SimplifierType), 0);
                    simplifierIndex     = EditorGUILayout.Popup("Simplifier", simplifierIndex, m_SimplifierNames);
                    hlod.SimplifierType = m_SimplifierTypes[simplifierIndex];

                    var info = m_SimplifierTypes[simplifierIndex].GetMethod("OnGUI");
                    if (info != null)
                    {
                        if (info.IsStatic == true)
                        {
                            info.Invoke(null, new object[] { hlod.SimplifierOptions });
                        }
                    }
                }
                else
                {
                    EditorGUILayout.LabelField("Cannot find Simplifiers.");
                }
            }
            EditorGUILayout.EndFoldoutHeaderGroup();

            isShowBatcher = EditorGUILayout.BeginFoldoutHeaderGroup(isShowBatcher, "Batcher");
            if (isShowBatcher == true)
            {
                if (m_BatcherTypes.Length > 0)
                {
                    int batcherIndex = Math.Max(Array.IndexOf(m_BatcherTypes, hlod.BatcherType), 0);
                    batcherIndex     = EditorGUILayout.Popup("Batcher", batcherIndex, m_BatcherNames);
                    hlod.BatcherType = m_BatcherTypes[batcherIndex];

                    var info = m_BatcherTypes[batcherIndex].GetMethod("OnGUI");
                    if (info != null)
                    {
                        if (info.IsStatic == true)
                        {
                            info.Invoke(null, new object[] { hlod, isFirstOnGUI });
                        }
                    }
                }
                else
                {
                    EditorGUILayout.LabelField("Cannot find Batchers.");
                }
            }
            EditorGUILayout.EndFoldoutHeaderGroup();



            isShowStreaming = EditorGUILayout.BeginFoldoutHeaderGroup(isShowStreaming, "Streaming");
            if (isShowStreaming == true)
            {
                if (m_StreamingTypes.Length > 0)
                {
                    int streamingIndex = Math.Max(Array.IndexOf(m_StreamingTypes, hlod.StreamingType), 0);
                    streamingIndex     = EditorGUILayout.Popup("Streaming", streamingIndex, m_StreamingNames);
                    hlod.StreamingType = m_StreamingTypes[streamingIndex];

                    var info = m_StreamingTypes[streamingIndex].GetMethod("OnGUI");
                    if (info != null)
                    {
                        if (info.IsStatic == true)
                        {
                            info.Invoke(null, new object[] { hlod.StreamingOptions });
                        }
                    }
                }
                else
                {
                    EditorGUILayout.LabelField("Cannot find StreamingSetters.");
                }
            }
            EditorGUILayout.EndFoldoutHeaderGroup();


            GUIContent generateButton = Styles.GenerateButtonEnable;
            GUIContent destroyButton  = Styles.DestroyButtonNotExists;

            if (hlod.GetComponent <HLODControllerBase>() != null)
            {
                generateButton = Styles.GenerateButtonExists;
                destroyButton  = Styles.DestroyButtonEnable;
            }



            EditorGUILayout.Space();

            GUI.enabled = generateButton == Styles.GenerateButtonEnable;
            if (GUILayout.Button(generateButton))
            {
                CoroutineRunner.RunCoroutine(HLODCreator.Create(hlod));
            }

            GUI.enabled = destroyButton == Styles.DestroyButtonEnable;
            if (GUILayout.Button(destroyButton))
            {
                CoroutineRunner.RunCoroutine(HLODCreator.Destroy(hlod));
            }

            GUI.enabled = true;

            serializedObject.ApplyModifiedProperties();
            isFirstOnGUI = false;
        }
예제 #10
0
 static void OnGUI(HLOD hlod, bool isFirst)
 {
 }
예제 #11
0
        public static void OnGUI(HLOD hlod)
        {
            EditorGUI.indentLevel += 1;
            dynamic batcherOptions = hlod.BatcherOptions;

            if (batcherOptions.PackTextureSize == null)
            {
                batcherOptions.PackTextureSize = 1024;
            }
            if (batcherOptions.LimitTextureSize == null)
            {
                batcherOptions.LimitTextureSize = 128;
            }
            if (batcherOptions.MaterialGUID == null)
            {
                batcherOptions.MaterialGUID = "";
            }
            if (batcherOptions.TextureInfoList == null)
            {
                batcherOptions.TextureInfoList = new List <TextureInfo>();
                batcherOptions.TextureInfoList.Add(new TextureInfo()
                {
                    InputName  = "_MainTex",
                    OutputName = "_MainTex",
                    Type       = PackingType.White
                });
            }

            if (batcherOptions.EnableTintColor == null)
            {
                batcherOptions.EnableTintColor = false;
            }
            if (batcherOptions.TintColorName == null)
            {
                batcherOptions.TintColorName = "";
            }

            batcherOptions.PackTextureSize  = EditorGUILayout.IntPopup("Pack texture size", batcherOptions.PackTextureSize, Styles.PackTextureSizeNames, Styles.PackTextureSizes);
            batcherOptions.LimitTextureSize = EditorGUILayout.IntPopup("Limit texture size", batcherOptions.LimitTextureSize, Styles.LimitTextureSizeNames, Styles.LimitTextureSizes);

            Material mat = null;

            string matGUID = batcherOptions.MaterialGUID;
            string path    = "";

            if (string.IsNullOrEmpty(matGUID) == false)
            {
                path = AssetDatabase.GUIDToAssetPath(matGUID);
                mat  = AssetDatabase.LoadAssetAtPath <Material>(path);
            }
            mat = EditorGUILayout.ObjectField("Material", mat, typeof(Material), false) as Material;
            if (mat == null)
            {
                mat = new Material(Shader.Find("Standard"));
            }

            path    = AssetDatabase.GetAssetPath(mat);
            matGUID = AssetDatabase.AssetPathToGUID(path);


            if (matGUID != batcherOptions.MaterialGUID)
            {
                batcherOptions.MaterialGUID = matGUID;
                outputTexturePropertyNames  = mat.GetTexturePropertyNames();
            }
            if (inputTexturePropertyNames == null)
            {
                inputTexturePropertyNames = GetAllMaterialTextureProperties(hlod.gameObject);
            }
            if (outputTexturePropertyNames == null)
            {
                outputTexturePropertyNames = mat.GetTexturePropertyNames();
            }

            //apply tint color
            batcherOptions.EnableTintColor =
                EditorGUILayout.Toggle("Enable tint color", batcherOptions.EnableTintColor);
            if (batcherOptions.EnableTintColor == true)
            {
                EditorGUI.indentLevel += 1;

                var           shader             = mat.shader;
                List <string> colorPropertyNames = new List <string>();
                int           propertyCount      = ShaderUtil.GetPropertyCount(shader);
                for (int i = 0; i < propertyCount; ++i)
                {
                    string name = ShaderUtil.GetPropertyName(shader, i);
                    if (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.Color)
                    {
                        colorPropertyNames.Add(name);
                    }
                }

                int index = colorPropertyNames.IndexOf(batcherOptions.TintColorName);
                index = EditorGUILayout.Popup("Tint color property", index, colorPropertyNames.ToArray());
                if (index >= 0)
                {
                    batcherOptions.TintColorName = colorPropertyNames[index];
                }
                else
                {
                    batcherOptions.TintColorName = "";
                }

                EditorGUI.indentLevel -= 1;
            }

            //ext textures
            EditorGUILayout.Space();
            EditorGUILayout.LabelField("Textures");
            EditorGUI.indentLevel += 1;
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel(" ");
            //EditorGUILayout.LabelField();
            EditorGUILayout.SelectableLabel("Input");
            EditorGUILayout.SelectableLabel("Output");
            EditorGUILayout.SelectableLabel("Type");
            EditorGUILayout.EndHorizontal();

            for (int i = 0; i < batcherOptions.TextureInfoList.Count; ++i)
            {
                TextureInfo info = batcherOptions.TextureInfoList[i];
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.PrefixLabel(" ");

                info.InputName  = StringPopup(info.InputName, inputTexturePropertyNames);
                info.OutputName = StringPopup(info.OutputName, outputTexturePropertyNames);
                info.Type       = (PackingType)EditorGUILayout.EnumPopup(info.Type);

                if (i == 0)
                {
                    GUI.enabled = false;
                }
                if (GUILayout.Button("x") == true)
                {
                    batcherOptions.TextureInfoList.RemoveAt(i);
                    i -= 1;
                }
                if (i == 0)
                {
                    GUI.enabled = true;
                }
                EditorGUILayout.EndHorizontal();
            }

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("New texture");
            addingTextureInfo.InputName =
                StringPopup(addingTextureInfo.InputName, inputTexturePropertyNames);
            addingTextureInfo.OutputName =
                StringPopup(addingTextureInfo.OutputName, outputTexturePropertyNames);
            addingTextureInfo.Type = (PackingType)EditorGUILayout.EnumPopup(addingTextureInfo.Type);
            if (GUILayout.Button("+") == true)
            {
                batcherOptions.TextureInfoList.Add(addingTextureInfo);
                addingTextureInfo = new TextureInfo();
            }

            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel(" ");
            if (GUILayout.Button("Update texture properties"))
            {
                //TODO: Need update automatically
                inputTexturePropertyNames = GetAllMaterialTextureProperties(hlod.gameObject);
            }
            EditorGUILayout.EndHorizontal();

            EditorGUI.indentLevel -= 1;
            EditorGUI.indentLevel -= 1;
        }
예제 #12
0
        public static IEnumerator Create(HLOD hlod)
        {
            try
            {
                Stopwatch sw = new Stopwatch();

                AssetDatabase.Refresh();
                AssetDatabase.SaveAssets();

                sw.Reset();
                sw.Start();

                hlod.ConvertedPrefabObjects.Clear();
                hlod.GeneratedObjects.Clear();

                Bounds bounds = hlod.GetBounds();

                List <GameObject> hlodTargets = ObjectUtils.HLODTargets(hlod.gameObject);
                ISpaceSplitter    spliter     = new QuadTreeSpaceSplitter(5.0f);
                SpaceNode         rootNode    = spliter.CreateSpaceTree(bounds, hlod.ChunkSize, hlod.transform.position, hlodTargets, progress =>
                {
                    EditorUtility.DisplayProgressBar("Bake HLOD", "Splitting space", progress * 0.25f);
                });

                if (hlodTargets.Count == 0)
                {
                    EditorUtility.DisplayDialog("Empty HLOD sources.",
                                                "There are no objects to be included in the HLOD.",
                                                "Ok");
                    yield break;
                }


                using (DisposableList <HLODBuildInfo> buildInfos = CreateBuildInfo(rootNode, hlod.MinObjectSize))
                {
                    if (buildInfos.Count == 0 || buildInfos[0].WorkingObjects.Count == 0)
                    {
                        EditorUtility.DisplayDialog("Empty HLOD sources.",
                                                    "There are no objects to be included in the HLOD.",
                                                    "Ok");
                        yield break;
                    }


                    Debug.Log("[HLOD] Splite space: " + sw.Elapsed.ToString("g"));
                    sw.Reset();
                    sw.Start();

                    ISimplifier simplifier = (ISimplifier)Activator.CreateInstance(hlod.SimplifierType,
                                                                                   new object[] { hlod.SimplifierOptions });
                    for (int i = 0; i < buildInfos.Count; ++i)
                    {
                        yield return(new BranchCoroutine(simplifier.Simplify(buildInfos[i])));
                    }

                    yield return(new WaitForBranches(progress =>
                    {
                        EditorUtility.DisplayProgressBar("Bake HLOD", "Simplify meshes",
                                                         0.25f + progress * 0.25f);
                    }));

                    Debug.Log("[HLOD] Simplify: " + sw.Elapsed.ToString("g"));
                    sw.Reset();
                    sw.Start();


                    using (IBatcher batcher =
                               (IBatcher)Activator.CreateInstance(hlod.BatcherType, new object[] { hlod.BatcherOptions }))
                    {
                        batcher.Batch(hlod.transform.position, buildInfos,
                                      progress =>
                        {
                            EditorUtility.DisplayProgressBar("Bake HLOD", "Generating combined static meshes.",
                                                             0.5f + progress * 0.25f);
                        });
                    }
                    Debug.Log("[HLOD] Batch: " + sw.Elapsed.ToString("g"));
                    sw.Reset();
                    sw.Start();


                    IStreamingBuilder builder =
                        (IStreamingBuilder)Activator.CreateInstance(hlod.StreamingType,
                                                                    new object[] { hlod, hlod.StreamingOptions });
                    builder.Build(rootNode, buildInfos, hlod.gameObject, hlod.CullDistance, hlod.LODDistance, false, true,
                                  progress =>
                    {
                        EditorUtility.DisplayProgressBar("Bake HLOD", "Storing results.",
                                                         0.75f + progress * 0.25f);
                    });
                    Debug.Log("[HLOD] Build: " + sw.Elapsed.ToString("g"));
                    sw.Reset();
                    sw.Start();

                    EditorUtility.SetDirty(hlod.gameObject);
                }
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }
        }
예제 #13
0
 public SimpleBatcher(HLOD hlod)
 {
     m_hlod = hlod;
 }
예제 #14
0
        public override void OnInspectorGUI()
        {
            serializedObject.Update();
            EditorGUI.BeginChangeCheck();

            HLOD hlod = target as HLOD;

            if (hlod == null)
            {
                EditorGUILayout.LabelField("HLOD is null.");
                return;
            }

            isShowCommon = EditorGUILayout.BeginFoldoutHeaderGroup(isShowCommon, "Common");
            if (isShowCommon == true)
            {
                EditorGUILayout.PropertyField(m_MinSizeProperty);

                m_LODSlider.Draw();
                EditorGUILayout.PropertyField(m_ThresholdSizeProperty);
            }
            EditorGUILayout.EndFoldoutHeaderGroup();


            isShowSimplifier = EditorGUILayout.BeginFoldoutHeaderGroup(isShowSimplifier, "Simplifier");
            if (isShowSimplifier == true)
            {
                if (m_SimplifierTypes.Length > 0)
                {
                    int simplifierIndex = Math.Max(Array.IndexOf(m_SimplifierTypes, hlod.SimplifierType), 0);
                    simplifierIndex     = EditorGUILayout.Popup("Simplifier", simplifierIndex, m_SimplifierNames);
                    hlod.SimplifierType = m_SimplifierTypes[simplifierIndex];

                    var info = m_SimplifierTypes[simplifierIndex].GetMethod("OnGUI");
                    if (info != null)
                    {
                        if (info.IsStatic == true)
                        {
                            info.Invoke(null, new object[] { hlod });
                        }
                    }
                }
                else
                {
                    EditorGUILayout.LabelField("Can not find Simplifiers.");
                }
            }
            EditorGUILayout.EndFoldoutHeaderGroup();

            isShowBatcher = EditorGUILayout.BeginFoldoutHeaderGroup(isShowBatcher, "Batcher");
            if (isShowBatcher == true)
            {
                if (m_BatcherTypes.Length > 0)
                {
                    int batcherIndex = Math.Max(Array.IndexOf(m_BatcherTypes, hlod.BatcherType), 0);
                    batcherIndex     = EditorGUILayout.Popup("Batcher", batcherIndex, m_BatcherNames);
                    hlod.BatcherType = m_BatcherTypes[batcherIndex];

                    var info = m_BatcherTypes[batcherIndex].GetMethod("OnGUI");
                    if (info != null)
                    {
                        if (info.IsStatic == true)
                        {
                            info.Invoke(null, new object[] { hlod });
                        }
                    }
                }
                else
                {
                    EditorGUILayout.LabelField("Can not find Batchers.");
                }
            }
            EditorGUILayout.EndFoldoutHeaderGroup();



            isShowStreaming = EditorGUILayout.BeginFoldoutHeaderGroup(isShowStreaming, "Streaming");
            if (isShowStreaming == true)
            {
                if (m_StreamingTypes.Length > 0)
                {
                    int streamingIndex = Math.Max(Array.IndexOf(m_StreamingTypes, hlod.StreamingType), 0);
                    streamingIndex     = EditorGUILayout.Popup("Streaming", streamingIndex, m_StreamingNames);
                    hlod.StreamingType = m_StreamingTypes[streamingIndex];

                    var info = m_StreamingTypes[streamingIndex].GetMethod("OnGUI");
                    if (info != null)
                    {
                        if (info.IsStatic == true)
                        {
                            info.Invoke(null, new object[] { hlod });
                        }
                    }
                }
                else
                {
                    EditorGUILayout.LabelField("Can not find StreamingSetters.");
                }
            }
            EditorGUILayout.EndFoldoutHeaderGroup();


            GUIContent generateButton = Styles.GenerateButtonEnable;
            GUIContent destroyButton  = Styles.DestroyButtonNotExists;

            if (PrefabStageUtility.GetCurrentPrefabStage() == null ||
                PrefabStageUtility.GetCurrentPrefabStage().prefabContentsRoot == null)
            {
                //generate is only allow in prefab mode.
                GUI.enabled    = false;
                generateButton = Styles.GenerateButtonDisable;
                destroyButton  = Styles.DestroyButtonDisable;
            }
            else if (hlod.GetComponent <ControllerBase>() != null)
            {
                generateButton = Styles.GenerateButtonExists;
                destroyButton  = Styles.DestroyButtonEnable;
            }



            EditorGUILayout.Space();

            GUI.enabled = generateButton == Styles.GenerateButtonEnable;
            if (GUILayout.Button(generateButton))
            {
                CoroutineRunner.RunCoroutine(HLODCreator.Create(hlod));
            }

            GUI.enabled = destroyButton == Styles.DestroyButtonEnable;
            if (GUILayout.Button(destroyButton))
            {
                CoroutineRunner.RunCoroutine(HLODCreator.Destroy(hlod));
            }

            GUI.enabled = true;

            serializedObject.ApplyModifiedProperties();
            if (EditorGUI.EndChangeCheck())
            {
                if (PrefabStageUtility.GetCurrentPrefabStage() != null)
                {
                    EditorSceneManager.MarkSceneDirty(PrefabStageUtility.GetCurrentPrefabStage().scene);
                }
            }
        }
예제 #15
0
        public static IEnumerator Create(HLOD hlod)
        {
            try
            {
                Stopwatch sw = new Stopwatch();

                AssetDatabase.Refresh();
                AssetDatabase.SaveAssets();

                sw.Reset();
                sw.Start();

                Bounds bounds = hlod.GetBounds();

                List <GameObject> hlodTargets = ObjectUtils.HLODTargets(hlod.gameObject);
                ISpaceSplitter    spliter     = new QuadTreeSpaceSplitter(hlod.transform.position, 5.0f, hlod.MinSize);
                SpaceNode         rootNode    = spliter.CreateSpaceTree(bounds, hlodTargets, progress =>
                {
                    EditorUtility.DisplayProgressBar("Bake HLOD", "Splitting space", progress * 0.25f);
                });

                List <HLODBuildInfo> buildInfos = CreateBuildInfo(rootNode, hlod.ThresholdSize);

                Debug.Log("[HLOD] Splite space: " + sw.Elapsed.ToString("g"));
                sw.Reset();
                sw.Start();

                ISimplifier simplifier = (ISimplifier)Activator.CreateInstance(hlod.SimplifierType, new object[] { hlod });
                for (int i = 0; i < buildInfos.Count; ++i)
                {
                    yield return(new BranchCoroutine(simplifier.Simplify(buildInfos[i])));
                }

                yield return(new WaitForBranches(progress =>
                {
                    EditorUtility.DisplayProgressBar("Bake HLOD", "Simplify meshes", 0.25f + progress * 0.25f);
                }));

                Debug.Log("[HLOD] Simplify: " + sw.Elapsed.ToString("g"));
                sw.Reset();
                sw.Start();


                IBatcher batcher = (IBatcher)Activator.CreateInstance(hlod.BatcherType, new object[] { hlod });
                batcher.Batch(buildInfos, progress =>
                {
                    EditorUtility.DisplayProgressBar("Bake HLOD", "Generating combined static meshes.", 0.5f + progress * 0.25f);
                });
                Debug.Log("[HLOD] Batch: " + sw.Elapsed.ToString("g"));
                sw.Reset();
                sw.Start();

                try
                {
                    AssetDatabase.StartAssetEditing();
                    IStreamingBuilder builder =
                        (IStreamingBuilder)Activator.CreateInstance(hlod.StreamingType, new object[] { hlod });
                    builder.Build(rootNode, buildInfos, progress =>
                    {
                        EditorUtility.DisplayProgressBar("Bake HLOD", "Storing results.", 0.75f + progress * 0.25f);
                    });
                    Debug.Log("[HLOD] Build: " + sw.Elapsed.ToString("g"));
                    sw.Reset();
                    sw.Start();
                }
                finally
                {
                    AssetDatabase.StopAssetEditing();
                    Debug.Log("[HLOD] Importing: " + sw.Elapsed.ToString("g"));
                }
            }
            finally
            {
                EditorUtility.ClearProgressBar();
            }
            //hlod.Root = rootNode;
        }