public IEnumerator CreateImpl() { try { using (m_queue = new JobQueue(8)) { Stopwatch sw = new Stopwatch(); AssetDatabase.Refresh(); AssetDatabase.SaveAssets(); sw.Reset(); sw.Start(); EditorUtility.DisplayProgressBar("Bake HLOD", "Initialize Bake", 0.0f); TerrainData data = m_hlod.TerrainData; m_size = data.size; m_heightmap = new Heightmap(data.heightmapResolution, data.heightmapResolution, data.size, data.GetHeights(0, 0, data.heightmapResolution, data.heightmapResolution)); string materialPath = AssetDatabase.GUIDToAssetPath(m_hlod.MaterialGUID); m_terrainMaterial = AssetDatabase.LoadAssetAtPath <Material>(materialPath); if (m_terrainMaterial == null) { m_terrainMaterial = new Material(Shader.Find("Standard")); } m_terrainMaterialInstanceId = m_terrainMaterial.GetInstanceID(); m_terrainMaterialName = m_terrainMaterial.name; using (m_alphamaps = new DisposableList <WorkingTexture>()) using (m_layers = new DisposableList <Layer>()) { for (int i = 0; i < data.alphamapTextures.Length; ++i) { m_alphamaps.Add(new WorkingTexture(Allocator.Persistent, data.alphamapTextures[i])); } for (int i = 0; i < data.terrainLayers.Length; ++i) { m_layers.Add(new Layer(data.terrainLayers[i])); } QuadTreeSpaceSplitter splitter = new QuadTreeSpaceSplitter(0.0f); SpaceNode rootNode = splitter.CreateSpaceTree(m_hlod.GetBounds(), m_hlod.ChunkSize * 2.0f, m_hlod.transform.position, null, progress => { }); EditorUtility.DisplayProgressBar("Bake HLOD", "Create mesh", 0.0f); using (DisposableList <HLODBuildInfo> buildInfos = CreateBuildInfo(data, rootNode)) { yield return(m_queue.WaitFinish()); //Write material & textures for (int i = 0; i < buildInfos.Count; ++i) { int curIndex = i; m_queue.EnqueueJob(() => { ISimplifier simplifier = (ISimplifier)Activator.CreateInstance(m_hlod.SimplifierType, new object[] { m_hlod.SimplifierOptions }); simplifier.SimplifyImmidiate(buildInfos[curIndex]); }); } EditorUtility.DisplayProgressBar("Bake HLOD", "Simplify meshes", 0.0f); yield return(m_queue.WaitFinish()); Debug.Log("[TerrainHLOD] Simplify: " + sw.Elapsed.ToString("g")); sw.Reset(); sw.Start(); EditorUtility.DisplayProgressBar("Bake HLOD", "Make border", 0.0f); for (int i = 0; i < buildInfos.Count; ++i) { HLODBuildInfo info = buildInfos[i]; m_queue.EnqueueJob(() => { for (int oi = 0; oi < info.WorkingObjects.Count; ++oi) { WorkingObject o = info.WorkingObjects[oi]; int borderVertexCount = m_hlod.BorderVertexCount * Mathf.RoundToInt(Mathf.Pow(2.0f, (float)info.Distances[oi])); using (WorkingMesh m = MakeBorder(o.Mesh, info.Heightmap, borderVertexCount)) { ReampUV(m, info.Heightmap); o.SetMesh(MakeFillHoleMesh(m)); } } }); } yield return(m_queue.WaitFinish()); Debug.Log("[TerrainHLOD] Make Border: " + sw.Elapsed.ToString("g")); sw.Reset(); sw.Start(); for (int i = 0; i < buildInfos.Count; ++i) { SpaceNode node = buildInfos[i].Target; HLODBuildInfo info = buildInfos[i]; if (node.HasChild() == false) { SpaceNode parent = node.ParentNode; node.ParentNode = null; GameObject go = new GameObject(buildInfos[i].Name); for (int wi = 0; wi < info.WorkingObjects.Count; ++wi) { WorkingObject wo = info.WorkingObjects[wi]; GameObject targetGO = null; if (wi == 0) { targetGO = go; } else { targetGO = new GameObject(wi.ToString()); targetGO.transform.SetParent(go.transform, false); } List <Material> materials = new List <Material>(); for (int mi = 0; mi < wo.Materials.Count; ++mi) { WorkingMaterial wm = wo.Materials[mi]; if (wm.NeedWrite() == false) { materials.Add(wm.ToMaterial()); continue; } Material mat = new Material(wm.ToMaterial()); string[] textureNames = wm.GetTextureNames(); for (int ti = 0; ti < textureNames.Length; ++ti) { WorkingTexture wt = wm.GetTexture(textureNames[ti]); Texture2D tex = wt.ToTexture(); tex.wrapMode = wt.WrapMode; mat.name = targetGO.name + "_Mat"; mat.SetTexture(textureNames[ti], tex); } mat.EnableKeyword("_NORMALMAP"); materials.Add(mat); } targetGO.AddComponent <MeshFilter>().sharedMesh = wo.Mesh.ToMesh(); targetGO.AddComponent <MeshRenderer>().sharedMaterials = materials.ToArray(); } go.transform.SetParent(m_hlod.transform, false); m_hlod.AddGeneratedResource(go); parent.Objects.Add(go); buildInfos.RemoveAt(i); i -= 1; } } //controller IStreamingBuilder builder = (IStreamingBuilder)Activator.CreateInstance(m_hlod.StreamingType, new object[] { m_hlod, m_hlod.StreamingOptions }); builder.Build(rootNode, buildInfos, m_hlod.gameObject, m_hlod.CullDistance, m_hlod.LODDistance, true, false, progress => { EditorUtility.DisplayProgressBar("Bake HLOD", "Storing results.", 0.75f + progress * 0.25f); }); Debug.Log("[TerrainHLOD] Build: " + sw.Elapsed.ToString("g")); } } EditorUtility.SetDirty(m_hlod.gameObject); } } finally { EditorUtility.ClearProgressBar(); GC.Collect(); } }
public override void OnInspectorGUI() { serializedObject.Update(); EditorGUI.BeginChangeCheck(); TerrainHLOD hlod = target as TerrainHLOD; if (hlod == null) { EditorGUILayout.LabelField("TerrainHLOD is null."); return; } isShowCommon = EditorGUILayout.BeginFoldoutHeaderGroup(isShowCommon, "Common"); if (isShowCommon == true) { EditorGUILayout.PropertyField(m_TerrainDataProperty, Styles.SourceText); EditorGUILayout.PropertyField(m_DestoryTerrainProperty, Styles.DestoryTerrainText); 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($"Use a value less than 5.", Styles.RedTextColor); } EditorGUILayout.PropertyField(m_BorderVertexCountProperty); m_LODSlider.Draw(); } 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("Can not find Simplifiers."); } } EditorGUILayout.EndFoldoutHeaderGroup(); isShowMaterial = EditorGUILayout.BeginFoldoutHeaderGroup(isShowMaterial, "Material"); if (isShowMaterial == true) { Material mat = null; string matGUID = hlod.MaterialGUID; if (string.IsNullOrEmpty(matGUID) == false) { string path = AssetDatabase.GUIDToAssetPath(matGUID); mat = AssetDatabase.LoadAssetAtPath <Material>(path); } mat = EditorGUILayout.ObjectField("Material", mat, typeof(Material), false) as Material; if (mat != null) { string path = AssetDatabase.GetAssetPath(mat); hlod.MaterialGUID = AssetDatabase.AssetPathToGUID(path); } matGUID = hlod.MaterialLowGUID; if (string.IsNullOrEmpty(matGUID) == false) { string path = AssetDatabase.GUIDToAssetPath(matGUID); mat = AssetDatabase.LoadAssetAtPath <Material>(path); } mat = EditorGUILayout.ObjectField("MaterialLow", mat, typeof(Material), false) as Material; if (mat != null) { string path = AssetDatabase.GetAssetPath(mat); hlod.MaterialLowGUID = AssetDatabase.AssetPathToGUID(path); } hlod.TextureSize = EditorGUILayout.IntPopup("Size", hlod.TextureSize, Styles.TextureSizeStrings, Styles.TextureSizes); //Output Property name //EditorGUILayout. if (mat == null) { mat = new Material(Shader.Find("Standard")); } string[] outputTexturePropertyNames = mat.GetTexturePropertyNames(); int index = 0; isShowTexturePropertices = EditorGUILayout.Foldout(isShowTexturePropertices, "Texture propertices"); if (isShowTexturePropertices == true) { EditorGUILayout.BeginHorizontal(); EditorGUILayout.Toggle(true, GUILayout.Width(20)); index = Array.IndexOf(outputTexturePropertyNames, hlod.AlbedoPropertyName); index = EditorGUILayout.Popup("Albedo", index, outputTexturePropertyNames); index = (index < 0) ? 0 : index; hlod.AlbedoPropertyName = outputTexturePropertyNames[index]; EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); hlod.UseNormal = EditorGUILayout.Toggle(hlod.UseNormal, GUILayout.Width(20)); index = Array.IndexOf(outputTexturePropertyNames, hlod.NormalPropertyName); index = EditorGUILayout.Popup("Normal", index, outputTexturePropertyNames); index = (index < 0) ? 0 : index; hlod.NormalPropertyName = outputTexturePropertyNames[index]; EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); hlod.UseMask = EditorGUILayout.Toggle(hlod.UseMask, GUILayout.Width(20)); index = Array.IndexOf(outputTexturePropertyNames, hlod.MaskPropertyName); index = EditorGUILayout.Popup("Mask", index, outputTexturePropertyNames); index = (index < 0) ? 0 : index; hlod.MaskPropertyName = outputTexturePropertyNames[index]; EditorGUILayout.EndHorizontal(); } } 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("Can not 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(TerrainHLODCreator.Create(hlod)); } GUI.enabled = destroyButton == Styles.DestroyButtonEnable; if (GUILayout.Button(destroyButton)) { CoroutineRunner.RunCoroutine(TerrainHLODCreator.Destroy(hlod)); } GUI.enabled = true; serializedObject.ApplyModifiedProperties(); }