From 6eb915c129fc90c6f4c82ae097dd6ffad5239efc Mon Sep 17 00:00:00 2001 From: chai Date: Mon, 25 Jan 2021 14:28:30 +0800 Subject: +scripts --- Client/Assets/Scripts/Scene/EnverinmentSetting.cs | 675 ++++++++++++++++++++++ 1 file changed, 675 insertions(+) create mode 100644 Client/Assets/Scripts/Scene/EnverinmentSetting.cs (limited to 'Client/Assets/Scripts/Scene/EnverinmentSetting.cs') diff --git a/Client/Assets/Scripts/Scene/EnverinmentSetting.cs b/Client/Assets/Scripts/Scene/EnverinmentSetting.cs new file mode 100644 index 00000000..cd7c3014 --- /dev/null +++ b/Client/Assets/Scripts/Scene/EnverinmentSetting.cs @@ -0,0 +1,675 @@ +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using System; +using XUtliPoolLib; +#if UNITY_EDITOR +using UnityEditor; +using UnityEngine.SceneManagement; +using UnityEditor.SceneManagement; +using XEditor; +using System.IO; +#endif + +[ExecuteInEditMode] +public class EnverinmentSetting : MonoBehaviour, IEnvSetting +{ + [Serializable] + public class EnvLightMapData + { + [SerializeField] + public string lightmapFarPath; + //[SerializeField] + //public string lightmapNearPath; + [System.NonSerialized] + public Texture2D lightmapFar; + //[System.NonSerialized] + //public Texture2D lightmapNear; + } + + [Serializable] + public class EnvInfo + { + [SerializeField] + public bool fog = true; + [SerializeField] + public Color fogColor; + [SerializeField] + public FogMode fogMode = FogMode.Linear; + [SerializeField] + [Range(0f, 1f)] + public float fogDensity; + [SerializeField] + public float fogStartDistance; + [SerializeField] + public float fogEndDistance; + [SerializeField] + public string skyboxPath; + [SerializeField] + public Color ambientLight; + [SerializeField] + public GameObject decorate; + + [SerializeField] + public List lightmapDatas; + + [SerializeField] + public byte terrainLightmapIndex; + + [System.NonSerialized] + public Material skybox; + //public int lightmapDataSize = 0; + + //public Material skybox + //{ + // get; + // set; + //} + } + [SerializeField] + public List envs; + [SerializeField] + public Material terrainMat; + [System.NonSerialized] + private int currentIndex = -1; + [System.NonSerialized] + public EnvInfo currentEnvInfo; + +#if UNITY_EDITOR + [System.NonSerialized] + private EnvInfo backup = new EnvInfo(); + [System.NonSerialized] + private LightmapData[] normaLightMaps; + private bool dynamicLoadLightMap = false; + private GameObject terrainGo = null; + private RenderTexture terrainRT = null; + [System.NonSerialized] + public SceneConfig sceneConfig = null; + [System.NonSerialized] + public int selectBlockIndex = -1; + [System.NonSerialized] + public SceneConfig.LodArea editLodArea = null; + + string sceneFolder = ""; + List vertexList = new List(); + List indexList = new List(); + List uvList = new List(); + float heithMapWidthScale; + float heightMapLengthScale; + float widthPerBlockLod0; + float lengthPerBlockLod0; + float uvPerBlockLod0; +#endif + void Awake() + { + if (Application.isPlaying) + XUpdater.XShell.singleton.MonoObjectRegister("EnvSet", this); +#if UNITY_EDITOR + + if (terrainMat != null || envs != null && envs.Count > 1) + { + dynamicLoadLightMap = true; + } + else + { + backup.fog = RenderSettings.fog; + backup.fogColor = RenderSettings.fogColor; + backup.fogMode = RenderSettings.fogMode; + backup.fogDensity = RenderSettings.fogDensity; + backup.fogStartDistance = RenderSettings.fogStartDistance; + backup.fogEndDistance = RenderSettings.fogEndDistance; + backup.skybox = RenderSettings.skybox; + backup.ambientLight = RenderSettings.ambientLight; + normaLightMaps = LightmapSettings.lightmaps; + } + + if (envs != null) + { + for (int i = 0; i < envs.Count; ++i) + { + EnvInfo ei = envs[i]; + if (ei.lightmapDatas != null) + { + for (int j = 0; j < ei.lightmapDatas.Count; ++j) + { + EnvLightMapData eld = ei.lightmapDatas[j]; + if (!string.IsNullOrEmpty(eld.lightmapFarPath)) + { + eld.lightmapFar = XResourceLoaderMgr.singleton.GetSharedResource(eld.lightmapFarPath, ".exr"); + } + } + } + } + } + EnableSetting(0); +#endif + } + public void EnableSetting(int indexList) + { + if (envs != null && + indexList >= 0 && + indexList < envs.Count && + currentIndex != indexList) + { + currentIndex = indexList; + EnvInfo ei = envs[indexList]; + RenderSettings.fog = ei.fog; + RenderSettings.fogColor = ei.fogColor; + RenderSettings.fogMode = ei.fogMode; + RenderSettings.fogDensity = ei.fogDensity; + RenderSettings.fogStartDistance = ei.fogStartDistance; + RenderSettings.fogEndDistance = ei.fogEndDistance; + +#if !UNITY_EDITOR + if (currentEnvInfo != null) + { + XResourceLoaderMgr.SafeDestroyShareResource(ei.skyboxPath, ref currentEnvInfo.skybox); + if (currentEnvInfo.decorate != null) + { + currentEnvInfo.decorate.SetActive(false); + } + if (currentEnvInfo.lightmapDatas != null) + { + for (int i = 0, length = currentEnvInfo.lightmapDatas.Count; i < length; i++) + { + EnvLightMapData elmd = currentEnvInfo.lightmapDatas[i]; + XResourceLoaderMgr.singleton.UnSafeDestroyShareResource(elmd.lightmapFarPath, ".exr", elmd.lightmapFar); + elmd.lightmapFar = null; + } + } + } +#endif + ei.skybox = XResourceLoaderMgr.singleton.GetSharedResource(ei.skyboxPath, ".mat"); + if (ei.skybox != null) + RenderSettings.skybox = ei.skybox; + RenderSettings.ambientLight = ei.ambientLight; + + if (ei.lightmapDatas != null && ei.lightmapDatas.Count > 0) + { + LightmapData[] lightmaps = new LightmapData[ei.lightmapDatas.Count]; + for (int i = 0, length = lightmaps.Length; i < length; i++) + { + LightmapData ld = new LightmapData(); + lightmaps[i] = ld; + EnvLightMapData elmd = ei.lightmapDatas[i]; + if (!string.IsNullOrEmpty(elmd.lightmapFarPath)) + { + elmd.lightmapFar = XResourceLoaderMgr.singleton.GetSharedResource(elmd.lightmapFarPath, ".exr"); + ld.lightmapColor = elmd.lightmapFar; + } + } + LightmapSettings.lightmaps = lightmaps; + if (ei.decorate != null) + { + ei.decorate.SetActive(true); + } + if (terrainMat != null && ei.terrainLightmapIndex >= 0 && ei.terrainLightmapIndex < lightmaps.Length) + { + Shader.SetGlobalTexture("_TerrainLightMap", lightmaps[ei.terrainLightmapIndex].lightmapColor); + } + } + currentEnvInfo = ei; + + for (int i = 0; i < envs.Count; ++i) + { + if (i != indexList) + { + EnvInfo oterhEI = envs[i]; + if (oterhEI.decorate != null) + { + oterhEI.decorate.SetActive(false); + } + } + } + } + } + +#if UNITY_EDITOR + + [MenuItem(@"GameObject/Scene/TerrainEditor", false, 0)] + private static void EditTerrain() + { + GameObject envGo = GameObject.Find("Environment"); + if (envGo == null) + { + envGo = new GameObject("Environment"); + } + EnverinmentSetting es = envGo.GetComponent(); + if (es == null) + { + GameObject cameraGo = GameObject.Find("Main Camera"); + if (cameraGo != null) + { + es = cameraGo.GetComponent(); + if (es != null) + { + UnityEditorInternal.ComponentUtility.CopyComponent(es); + UnityEditorInternal.ComponentUtility.PasteComponentAsNew(envGo); + UnityEngine.Object.DestroyImmediate(es); + } + } + } + if(es==null) + { + es = envGo.AddComponent(); + } + + } + + public void PrepareTerrain() + { + //terrain + Terrain terrain = Terrain.activeTerrain; + UnityEngine.SceneManagement.Scene s = EditorSceneManager.GetActiveScene(); + sceneFolder = AssetModify.GetFolder(s.path); + if (terrain == null) + { + string terrainPrefabPath = AssetModify.MakeAssetPathWithFolder(sceneFolder, s.name + "_Terrain", "prefab"); + GameObject go = AssetDatabase.LoadAssetAtPath(terrainPrefabPath); + if (go != null) + { + terrainGo = GameObject.Instantiate(go); + terrainGo.name = "Terrain"; + terrain = Terrain.activeTerrain; + } + } + else + { + terrainGo = terrain.gameObject; + } + if (terrain != null) + { + TerrainData td = terrain.terrainData; + Vector3 size = td.size; + float width = td.size.x; + float length = td.size.z; + + heithMapWidthScale = td.heightmapWidth / width; + heightMapLengthScale = td.heightmapHeight / length; + + int widthVertexCount = td.heightmapWidth - 1; + int lengthVertexCount = td.heightmapHeight - 1; + widthPerBlockLod0 = width / (float)widthVertexCount; + lengthPerBlockLod0 = length / (float)lengthVertexCount; + uvPerBlockLod0 = 1.0f / (float)widthVertexCount; + + bool needExportAlphamap = false; + Texture2D[] alphaMap = td.alphamapTextures; + if (alphaMap != null) + { + for (int i = 0; i < alphaMap.Length; ++i) + { + string filePath = string.Format("{0}/{1}_{2}.png", sceneFolder, s.name, i); + if(!File.Exists(filePath)) + { + needExportAlphamap = true; + break; + } + } + } + if(needExportAlphamap) + { + ExportAlphaMap(); + } + + string matPath = AssetModify.MakeAssetPathWithFolder(sceneFolder, s.name, "mat"); + terrainMat = AssetDatabase.LoadAssetAtPath(matPath); + if (terrainMat == null) + { + terrainMat = new Material(Shader.Find("Custom/Scene/CustomTerrainDiffuse")); + terrainMat.name = s.name; + terrainMat = AssetModify.CreateOrReplaceAsset(terrainMat, AssetModify.MakeAssetPathWithFolder(sceneFolder, terrainMat.name, "mat")); + } + string controlTexPath = string.Format("{0}/{1}_0.png", sceneFolder, s.name); + Texture controlTex = AssetDatabase.LoadAssetAtPath(controlTexPath); + terrainMat.SetTexture("_Control", controlTex); + SplatPrototype[] splatTexs = td.splatPrototypes; + if (splatTexs != null) + { + for (int i = 0; i < splatTexs.Length; ++i) + { + SplatPrototype sp = splatTexs[i]; + string texName = string.Format("_Splat{0}", i); + terrainMat.SetTexture(texName, sp.texture); + terrainMat.SetTextureScale(texName, new Vector2(width / sp.tileSize.x, length / sp.tileSize.y)); + } + } + } + if (terrainGo != null) + { + terrainGo.transform.parent = this.transform; + } + + + //config + Transform terrainConfigTran = this.transform.Find("SceneConfig"); + if (terrainConfigTran == null) + { + string terrainConfigPath = string.Format("{0}/{1}_SceneConfig.prefab", sceneFolder, s.name); + GameObject terrainConfigGO = AssetDatabase.LoadAssetAtPath(terrainConfigPath); + if (terrainConfigGO != null) + { + terrainConfigGO = GameObject.Instantiate(terrainConfigGO); + terrainConfigGO.name = "SceneConfig"; + sceneConfig = terrainConfigGO.GetComponent(); + } + if (sceneConfig == null) + { + terrainConfigGO = new GameObject("SceneConfig"); + sceneConfig = terrainConfigGO.AddComponent(); + sceneConfig.terrainBlock = 4; + AssetModify.CreateOrReplacePrefab(terrainConfigGO, terrainConfigPath); + } + } + else + { + GameObject terrainConfigGO = terrainConfigTran.gameObject; + sceneConfig = terrainConfigGO.GetComponent(); + } + if (sceneConfig != null) + { + if (terrain.lightmapIndex >= 0) + { + sceneConfig.terrainLightmapScaleOffset = terrain.lightmapScaleOffset; + } + int blockCount = sceneConfig.terrainBlock * sceneConfig.terrainBlock; + if (sceneConfig.terrainMeshInfo == null || sceneConfig.terrainMeshInfo.Length != blockCount) + { + sceneConfig.terrainMeshInfo = new SceneConfig.TerrainMeshInfo[blockCount]; + for (int i = 0; i < sceneConfig.terrainMeshInfo.Length; ++i) + { + sceneConfig.terrainMeshInfo[i] = new SceneConfig.TerrainMeshInfo(widthPerBlockLod0, lengthPerBlockLod0, i, sceneConfig.terrainBlock); + } + } + sceneConfig.transform.parent = this.transform; + } + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + } + private void ExportTerrainBlendTex(TerrainData td, List texs) + { + float[,,] map = td.GetAlphamaps(0, 0, td.alphamapWidth, td.alphamapHeight); + int layerCount = map.GetLength(2); + if (layerCount == 0) + return; + + for (int i = 0; i < layerCount; i += 4) + { + texs.Add(new Texture2D(td.alphamapWidth, td.alphamapHeight, TextureFormat.ARGB32, false)); + } + int maxLayCount = texs.Count * 4; + float[] colorValue = new float[maxLayCount]; + for (int y = 0; y < td.alphamapHeight; y++) + { + for (int x = 0; x < td.alphamapWidth; x++) + { + for (int i = 0; i < colorValue.Length; ++i) + { + + if (i < layerCount) + { + colorValue[i] = map[y, x, i]; + } + else + { + colorValue[i] = 0.0f; + } + } + int indexList = 0; + for (int i = 0; i < layerCount; i += 4) + { + Color c = new Color(colorValue[i], colorValue[i + 1], colorValue[i + 2], colorValue[i + 3]); + texs[indexList++].SetPixel(x, y, c); + } + + } + } + for (int i = 0; i < texs.Count; ++i) + { + if (texs[i] != null) + texs[i].Apply(); + } + } + public void ExportAlphaMap() + { + Terrain terrain = Terrain.activeTerrain; + if(terrain!=null) + { + UnityEngine.SceneManagement.Scene s = EditorSceneManager.GetActiveScene(); + TerrainData td = terrain.terrainData; + List texs = new List(); + ExportTerrainBlendTex(td, texs); + for (int i = 0; i < texs.Count; ++i) + { + if (texs[i] != null) + { + byte[] bytes = texs[i].EncodeToPNG(); + string filePath = string.Format("{0}/{1}_{2}.png", sceneFolder, s.name, i); + File.WriteAllBytes(filePath, bytes); + } + } + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + } + + } + + private void GenerateBlockMesh(TerrainData td, int terrainIndex, string sceneName, int i, int j) + { + SceneConfig.TerrainMeshInfo tmi = sceneConfig.terrainMeshInfo[terrainIndex]; + string terrainMeshName = string.Format("{0}_terrain_{1}", sceneName, terrainIndex); + string terrainMehsPath = string.Format("{0}/{1}.asset", sceneFolder, terrainMeshName); + Transform tran = this.transform.Find(terrainMeshName); + if (tran != null) + { + GameObject.DestroyImmediate(tran.gameObject); + } + if (File.Exists(terrainMehsPath)) + { + AssetDatabase.DeleteAsset(terrainMehsPath); + } + if (!tmi.enable) + { + return; + } + int lod = (int)Math.Pow(2, tmi.lod); + float widthPerBlock = lod * widthPerBlockLod0; + float lengthPerBlock = lod * lengthPerBlockLod0; + float uvPerBlock = lod * uvPerBlockLod0; + vertexList.Clear(); + indexList.Clear(); + uvList.Clear(); + int xVertexCount = 32 / lod; + int zVertexCount = 32 / lod; + int startX = i * xVertexCount; + int startZ = j * zVertexCount; + int endX = startX + xVertexCount; + int endZ = startZ + zVertexCount; + for (int z = startZ; z < endZ + 1; ++z) + { + for (int x = startX; x < endX + 1; ++x) + { + float currentX = x * widthPerBlock; + float currentY = z * lengthPerBlock; + Vector3 p = new Vector3(currentX, 0, currentY); + p.y = td.GetHeight((int)(p.x * heithMapWidthScale), (int)(p.z * heightMapLengthScale)); + vertexList.Add(p); + Vector2 uv = new Vector2(x * uvPerBlock, z * uvPerBlock); + uvList.Add(uv); + if (x > startX && z > startZ) + { + int lastVertexIndex = (xVertexCount + 1) * (z - startZ - 1) + x - startX; + int curcentVertexIndex = vertexList.Count - 1; + indexList.Add(lastVertexIndex - 1); indexList.Add(curcentVertexIndex); indexList.Add(lastVertexIndex); + indexList.Add(lastVertexIndex - 1); indexList.Add(curcentVertexIndex - 1); indexList.Add(curcentVertexIndex); + } + } + } + Mesh terrainMesh = new Mesh(); + terrainMesh.name = terrainMeshName; + terrainMesh.vertices = vertexList.ToArray(); + terrainMesh.triangles = indexList.ToArray(); + terrainMesh.uv = uvList.ToArray(); + terrainMesh.uv2 = null; + MeshUtility.SetMeshCompression(terrainMesh, ModelImporterMeshCompression.Medium); + MeshUtility.Optimize(terrainMesh); + terrainMesh.UploadMeshData(true); + + + Mesh mesh = AssetModify.CreateOrReplaceAsset(terrainMesh, terrainMehsPath); + GameObject terrainMeshGo = null; + Transform meshTran = this.transform.Find(terrainMesh.name); + + if (meshTran != null) + { + terrainMeshGo = meshTran.gameObject; + } + else + { + terrainMeshGo = new GameObject(terrainMesh.name); + terrainMeshGo.layer = 9; + } + terrainMeshGo.transform.position = terrainGo.transform.position; + terrainMeshGo.transform.parent = this.transform; + MeshFilter mf = terrainMeshGo.GetComponent(); + if (mf == null) + { + mf = terrainMeshGo.AddComponent(); + } + mf.sharedMesh = mesh; + MeshRenderer mr = terrainMeshGo.GetComponent(); + if (mr == null) + { + mr = terrainMeshGo.AddComponent(); + } + AssetModify.ProcessRender(mr, false); + terrainMat.SetVector("_LightMap_ST", sceneConfig.terrainLightmapScaleOffset); + mr.sharedMaterial = terrainMat; + + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + + } + public void ConvertTerrainBlock() + { + Terrain terrain = Terrain.activeTerrain; + if (terrain != null) + { + TerrainData td = terrain.terrainData; + + UnityEngine.SceneManagement.Scene s = EditorSceneManager.GetActiveScene(); + int i = selectBlockIndex % sceneConfig.terrainBlock; + int j = selectBlockIndex / sceneConfig.terrainBlock; + GenerateBlockMesh(td, selectBlockIndex, s.name, i, j); + } + } + public void ConvertTerrain() + { + Terrain terrain = Terrain.activeTerrain; + if (terrain != null) + { + TerrainData td = terrain.terrainData; + + + UnityEngine.SceneManagement.Scene s = EditorSceneManager.GetActiveScene(); + + for (int j = 0; j < sceneConfig.terrainBlock; ++j) + { + for (int i = 0; i < sceneConfig.terrainBlock; ++i) + { + int terrainIndex = j * sceneConfig.terrainBlock + i; + GenerateBlockMesh(td, terrainIndex, s.name, i, j); + } + } + } + } + public void EndConvertTerrain() + { + selectBlockIndex = -1; + UnityEngine.SceneManagement.Scene s = EditorSceneManager.GetActiveScene(); + if (terrainGo != null) + { + string terrainPath = string.Format("{0}/{1}_Terrain.prefab", sceneFolder, s.name); + AssetModify.CreateOrReplacePrefab(terrainGo, terrainPath); + GameObject.DestroyImmediate(terrainGo); + terrainGo = null; + } + if (sceneConfig != null) + { + string sceneConfigPath = string.Format("{0}/{1}_SceneConfig.prefab", sceneFolder, s.name); + AssetModify.CreateOrReplacePrefab(sceneConfig.gameObject, sceneConfigPath); + GameObject.DestroyImmediate(sceneConfig.gameObject); + sceneConfig = null; + } + if (terrainRT != null) + { + terrainRT.Release(); + terrainRT = null; + } + } + public void ResetEnv() + { + if (dynamicLoadLightMap) + { + EnableSetting(0); + } + else + { + RenderSettings.fog = backup.fog; + RenderSettings.fogColor = backup.fogColor; + RenderSettings.fogMode = backup.fogMode; + RenderSettings.fogDensity = backup.fogDensity; + RenderSettings.fogStartDistance = backup.fogStartDistance; + RenderSettings.fogEndDistance = backup.fogEndDistance; + RenderSettings.skybox = backup.skybox; + RenderSettings.ambientLight = backup.ambientLight; + LightmapSettings.lightmaps = normaLightMaps; + currentIndex = -1; + } + + } + public void UseCurrentLightMapSetting(int indexList) + { + if (envs != null && + indexList >= 0 && + indexList < envs.Count) + { + UnityEngine.SceneManagement.Scene s = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene(); + EnvInfo ei = envs[indexList]; + ei.fog = RenderSettings.fog; + ei.fogColor = RenderSettings.fogColor; + ei.fogMode = RenderSettings.fogMode; + ei.fogDensity = RenderSettings.fogDensity; + ei.fogStartDistance = RenderSettings.fogStartDistance; + ei.fogEndDistance = RenderSettings.fogEndDistance; + ei.skybox = RenderSettings.skybox; + LightmapData[] lightmaps = LightmapSettings.lightmaps; + if (lightmaps != null && lightmaps.Length > 0) + { + ei.lightmapDatas = new List(); + for (int i = 0; i < lightmaps.Length; ++i) + { + LightmapData ld = lightmaps[i]; + string dir = string.Format("Assets/Resources/Scene/{0}", s.name); + if (!System.IO.Directory.Exists(dir)) + { + System.IO.Directory.CreateDirectory(dir); + } + string targetPath = string.Format("{0}/{1}.exr", dir, ld.lightmapColor.name); + string srcPath = UnityEditor.AssetDatabase.GetAssetPath(ld.lightmapColor); + UnityEditor.AssetDatabase.CopyAsset(srcPath, targetPath); + EnvLightMapData eld = new EnvLightMapData(); + eld.lightmapFarPath = string.Format("Scene/{0}/{1}", s.name, ld.lightmapColor.name); + eld.lightmapFar = ld.lightmapColor; + ei.lightmapDatas.Add(eld); + } + } + } + } + + private void Update() + { + } +#endif + +} -- cgit v1.1-26-g67d0