public static void ConvertMapToUnityObjects(ConvertMapSettings lSettings) { s_Settings = lSettings; //EditorGUI.BeginChangeCheck(); if (s_Settings.UsingHDRPMaterials) { s_BaseColourMapID = Shader.PropertyToID("_BaseColorMap"); s_EmissionMapID = Shader.PropertyToID("_EmissiveColorMap"); s_EmissionColorID = Shader.PropertyToID("_EmissiveColor"); s_EmissionColorLDRID = Shader.PropertyToID("_EmissiveColor"); s_CutoffEnabledID = Shader.PropertyToID("_EmissiveColor"); s_CutoffAlphaID = Shader.PropertyToID("_AlphaCutoff"); } else { s_BaseColourMapID = Shader.PropertyToID("_MainTex"); s_EmissionMapID = Shader.PropertyToID("_EmissionMap"); s_EmissionColorID = Shader.PropertyToID("_EmissionColor"); s_CutoffEnabledID = Shader.PropertyToID("_EmissiveColor"); s_CutoffAlphaID = Shader.PropertyToID("_Cutoff"); } s_MaterialDic = new Dictionary <string, Material>(s_Settings.TexDefs.Textures.Length); s_MaterialList = new List <Material>(s_Settings.TexDefs.Textures.Length); QMapLevel[] lCurrentLevels = GameObject.FindObjectsOfType <QMapLevel>(); for (int i = 0; i < lCurrentLevels.Length; i++) { GameObject.DestroyImmediate(lCurrentLevels[i].gameObject); } GameObject lLevelObject = new GameObject(s_Settings.MapFile.name); QMapLevel lQMap = lLevelObject.AddComponent <QMapLevel>(); lQMap.EntDefs = s_Settings.EntDefs; lLevelObject.isStatic = true; LevelData lLevelData = MapParser.ParseMapToLevelData(s_Settings.MapFile); int lBrushCount = 0; int lTotalBrushes = 0; for (int i = 0; i < lLevelData.Entities.Length; i++) { lTotalBrushes += lLevelData.Entities[i].Brushes.Length; } List <UEntity> lUEnts = new List <UEntity>(lLevelData.Entities.Length); List <Vector3> lAllVerts = new List <Vector3>(10000); for (int i = 0; i < lLevelData.Entities.Length; i++) { List <Vector3> lEntityVerts = new List <Vector3>(1000); QEntity lQEnt = lLevelData.Entities[i]; EntDef lEntDef = s_Settings.EntDefs.GetDefinition(lQEnt.Classname); GameObject lEntGO = null; UEntity lUEnt = null; if (lEntDef.Classname == null) { lEntGO = new GameObject(i + " NULL Classname"); lUEnt = lEntGO.AddComponent <UEmptyEntity>(); } else if (lEntDef.ConvertedPrefab != null) { lEntGO = GameObject.Instantiate(lEntDef.ConvertedPrefab).gameObject; lEntGO.name = i + " " + lQEnt.Classname; lUEnt = lEntGO.GetComponent <UEntity>(); } else if (lEntDef.RuntimePrefab != null) { lEntGO = new GameObject(i + " " + lQEnt.Classname); lUEnt = lEntGO.AddComponent <UEntity>(); } else { lEntGO = new GameObject(i + " " + lQEnt.Classname); lUEnt = lEntGO.AddComponent <UEmptyEntity>(); } lUEnts.Add(lUEnt); lEntGO.isStatic = lEntDef.IsStatic; lEntGO.layer = lEntDef.EntLayer.LayerIndex; lEntGO.transform.parent = lLevelObject.transform; List <GameObject> lBrushes = new List <GameObject>(); List <ConvexMeshData> lConvexMeshDatas = new List <ConvexMeshData>(); for (int j = 0; j < lQEnt.Brushes.Length; j++) { QBrush lBrush = lQEnt.Brushes[j]; lBrushCount++; CMesh lCMesh = ClipMesh.CreateConvexPolyhedron(lBrush.Planes); List <Vector3> lBrushVertList = new List <Vector3>(); for (int v = 0; v < lCMesh.V.Length; v++) { if (lCMesh.V[v].Visible) { lBrushVertList.Add(lCMesh.V[v].Position); } } Vector3 lMin; Vector3 lMax; GetMinMax(lBrushVertList.ToArray(), out lMin, out lMax); Vector3 lSize = lMax - lMin; Vector3 lMidPointDelta = lMin + lSize * 0.5f; lCMesh = ClipMesh.CreateConvexPolyhedron(lBrush.Planes, lMidPointDelta, lSize + Vector3.one * 0.2f); lBrushVertList.Clear(); for (int v = 0; v < lCMesh.V.Length; v++) { if (lCMesh.V[v].Visible) { lBrushVertList.Add(lCMesh.V[v].Position); } } GetMinMax(lBrushVertList.ToArray(), out lMin, out lMax); lAllVerts.AddRange(lBrushVertList); lEntityVerts.AddRange(lBrushVertList); lSize = lMax - lMin; lMidPointDelta = lMin + lSize * 0.5f; UMeshData lMeshData = lCMesh.GetMeshInformation(lMidPointDelta); Texture[] lTextures = FetchTextures(lMeshData); UpdateMaterials(lTextures); UpdateMeshData(ref lMeshData, lTextures); lConvexMeshDatas.Add(new ConvexMeshData(lMeshData, lMidPointDelta)); Mesh[] lNewMeshes = UMeshCreator.ConvertToMeshes(lMeshData); #if UNITY_EDITOR if (s_Settings.AutoGenerateUV2s) { for (int m = 1; m < lNewMeshes.Length; m++) { UnwrapParam lParam = new UnwrapParam(); lParam.angleError = 0.05f; lParam.areaError = 0.05f; lParam.hardAngle = 85f; lParam.packMargin = 2f; Unwrapping.GenerateSecondaryUVSet(lNewMeshes[m], lParam); } } #endif if (lEntDef.HasCollider || lEntDef.HasMesh) { GameObject lColliderGO = new GameObject("Brush " + j); lBrushes.Add(lColliderGO); if (lEntDef.HasCollider) { lColliderGO.transform.position = lMidPointDelta; lColliderGO.transform.parent = lEntGO.transform; lColliderGO.isStatic = lEntDef.IsStatic; lColliderGO.layer = lEntDef.ColLayer.LayerIndex; MeshCollider lMCollider = lColliderGO.AddComponent <MeshCollider>(); lMCollider.sharedMesh = lNewMeshes[0]; lMCollider.convex = true; lMCollider.isTrigger = lEntDef.IsTrigger; //if (s_Settings.SaveLevelAsAsset) //AssetDatabase.CreateAsset(lNewMeshes[0], GetAssetPath(lEntGO.name, lColliderGO.name, lNewMeshes[0].name)); } if (lEntDef.HasMesh) { for (int m = 1; m < lNewMeshes.Length; m++) { GameObject lMeshGO = new GameObject("Mesh " + (m - 1)); lMeshGO.transform.position = lMidPointDelta; lMeshGO.transform.parent = lColliderGO.transform; lMeshGO.isStatic = lEntDef.IsStatic; lMeshGO.layer = lEntDef.MeshLayer.LayerIndex; MeshFilter lMFilter = lMeshGO.AddComponent <MeshFilter>(); MeshRenderer lMRender = lMeshGO.AddComponent <MeshRenderer>(); lMRender.sharedMaterial = s_MaterialDic[lTextures[m - 1].name]; lMRender.receiveShadows = true; lMRender.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; lMRender.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion; lMFilter.mesh = lNewMeshes[m]; //if (s_Settings.SaveLevelAsAsset) //AssetDatabase.CreateAsset(lNewMeshes[m], GetAssetPath(lEntGO.name, lColliderGO.name, lMeshGO.name, lNewMeshes[m].name)); /** * * Add Area Lights * **/ TexDef lTexDef; if (s_Settings.TexDefs.HasDefinition(lTextures[m - 1].name, out lTexDef) && lTexDef.HasAreaLight) { GameObject lAreaLightGO = new GameObject("AreaLight " + (m - 1)); lAreaLightGO.transform.position = lMidPointDelta; lAreaLightGO.transform.parent = lMeshGO.transform; lAreaLightGO.isStatic = lEntDef.IsStatic; //lAreaLightGO.layer = LayerMask.NameToLayer("AreaLight"); lAreaLightGO.AddComponent <DestroyObjectOnSpawn>(); MeshFilter lALMFilter = lAreaLightGO.AddComponent <MeshFilter>(); MeshRenderer lALMRender = lAreaLightGO.AddComponent <MeshRenderer>(); lALMRender.sharedMaterial = s_MaterialDic[lTextures[m - 1].name + "_AreaLightMAT"]; lALMRender.receiveShadows = false; lALMRender.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; lALMRender.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion; Mesh lAreaLightMesh = new Mesh(); FaceInfo[] lFaceInfos = lMeshData.MeshFaceInfos[m]; int lVertCount = 0; int lTriCount = 0; for (int f = 0; f < lFaceInfos.Length; f++) { lVertCount += lFaceInfos[f].Indices.Length; if (lFaceInfos[f].Indices.Length > 2) { lTriCount += lFaceInfos[f].Indices.Length - 2; } } int lTriIndex = 0; Vector3[] lNewVerts = new Vector3[lVertCount]; Vector3[] lNormals = new Vector3[lVertCount]; int[] lTriangles = new int[lTriCount * 3]; int[][] lNewIndices = new int[lFaceInfos.Length][]; int lVertIndex = 0; Vector3[] lPosVerts = lMeshData.PosVertices; Vector3[] lUVVerts = lMeshData.UVVertices; for (int f = 0; f < lFaceInfos.Length; f++) { FaceInfo lFaceInfo = lFaceInfos[f]; Plane lPlane = lFaceInfo.Plane; int[] lIndices = lFaceInfo.Indices; lNewIndices[f] = new int[lIndices.Length]; for (int v = 0; v < lIndices.Length; v++) { Vector3 lVertPos = lPosVerts[lIndices[v]]; Vector3 lVertUV = lUVVerts[lIndices[v]]; lNewVerts[lVertIndex] = (lVertPos * lTexDef.AreaSizeScale) - lPlane.Normal * lTexDef.AreaDisplacement; lNormals[lVertIndex] = -lPlane.Normal; lNewIndices[f][v] = lVertIndex; lVertIndex++; } for (int v = 0; v < lNewIndices[f].Length - 2; v++) { lTriangles[lTriIndex++] = lNewIndices[f][0]; lTriangles[lTriIndex++] = lNewIndices[f][v + 1]; lTriangles[lTriIndex++] = lNewIndices[f][v + 2]; } } lAreaLightMesh.vertices = lNewVerts; lAreaLightMesh.triangles = lTriangles; lAreaLightMesh.normals = lNormals; lAreaLightMesh.RecalculateTangents(); lAreaLightMesh.RecalculateBounds(); lAreaLightMesh.name = "Area Light Mesh"; #if UNITY_EDITOR Unwrapping.GenerateSecondaryUVSet(lAreaLightMesh); // TODO May be always needed #endif lALMFilter.mesh = lAreaLightMesh; //if (s_Settings.SaveLevelAsAsset) //AssetDatabase.CreateAsset(lAreaLightMesh, GetAssetPath(lEntGO.name, lColliderGO.name, lMeshGO.name, lAreaLightMesh.name)); } } } } } { List <Vector3> lConvexVertList = new List <Vector3>(); List <FaceInfo> lFaceList = new List <FaceInfo>(); int lIndexShift = 0; for (int c = 0; c < lConvexMeshDatas.Count; c++) { int lVertCount = lConvexMeshDatas[c].MeshData.PosVertices.Length; Vector3 lDeltaPos = lConvexMeshDatas[c].DeltaPos; for (int v = 0; v < lVertCount; v++) { lConvexVertList.Add(lConvexMeshDatas[c].MeshData.PosVertices[v] + lDeltaPos); } for (int f = 0; f < lConvexMeshDatas[c].MeshData.FaceInfos.Length; f++) { FaceInfo lInfo = lConvexMeshDatas[c].MeshData.FaceInfos[f]; for (int fi = 0; fi < lInfo.Indices.Length; fi++) { lInfo.Indices[fi] += lIndexShift; } lFaceList.Add(lInfo); } lIndexShift += lVertCount; } Vector3 lMin, lMax; GetMinMax(lConvexVertList.ToArray(), out lMin, out lMax); Vector3 lSize = lMax - lMin; Vector3 lMidPoint = lMin + lSize * 0.5f; for (int v = 0; v < lConvexVertList.Count; v++) { lConvexVertList[v] -= lMidPoint; } UMeshData lConvexData = new UMeshData(); lConvexData.PosVertices = lConvexData.UVVertices = lConvexVertList.ToArray(); lConvexData.MeshFaceInfos = new FaceInfo[1][]; lConvexData.MeshFaceInfos[0] = lFaceList.ToArray(); if (lEntDef.HasConvexCollider && lConvexMeshDatas.Count > 0) { Mesh[] lConvexMesh = UMeshCreator.ConvertToMeshes(lConvexData); //if (!AssetDatabase.IsValidFolder("Assets/" + s_Settings.MapFile.name)) //AssetDatabase.CreateFolder("Assets", s_Settings.MapFile.name); //AssetDatabase.CreateAsset(lConvexMesh[0], "Assets/" + s_Settings.MapFile.name + "/OriginalMesh.asset"); MeshCollider lMCollider = lUEnt.gameObject.AddComponent <MeshCollider>(); lMCollider.sharedMesh = lConvexMesh[0]; lMCollider.convex = true; lMCollider.isTrigger = lEntDef.IsConvexTrigger; //if (s_Settings.SaveLevelAsAsset) //AssetDatabase.CreateAsset(lConvexMesh[0], GetAssetPath(lEntGO.name, "CONVEX", lConvexMesh[0].name)); } if (lQEnt.Classname == "volume_enemy_spawn") { bool lWhat = true; } lUEnt.Extents = new Extents3D(lMidPoint, lSize); lUEnt.SetupEntity(lQEnt); Vector3 lValue; if (lUEnt.GetValue("origin", out lValue)) { lUEnt.transform.position = lValue; } else if (lBrushes.Count > 0) { for (int b = 0; b < lBrushes.Count; b++) { lBrushes[b].transform.localPosition = lBrushes[b].transform.position - lMidPoint; } lUEnt.transform.position = lMidPoint; } } } Vector3 lAllMin, lAllMax; GetMinMax(lAllVerts.ToArray(), out lAllMin, out lAllMax); Vector3 lAllSize = lAllMax - lAllMin; Vector3 lAllCenter = lAllMin + lAllSize * 0.5f; lQMap.Extents = new Extents3D(lAllCenter, lAllSize); //var lSO = new SerializedObject(lLevelObject); //if (lSO.ApplyModifiedProperties()) //{ // bool lBreakpoint = false; //} //if (s_Settings.SaveLevelAsAsset) //{ bool lSuccess; //for (int i = 0; i < s_MaterialList.Count; i++) //AssetDatabase.CreateAsset(s_MaterialList[i], "Assets/" + s_Settings.MapFile.name + "_MAT " + i + ".asset"); //PrefabUtility.SaveAsPrefabAsset(lLevelObject, "Assets/" + s_Settings.MapFile.name + ".prefab", out lSuccess); //AssetDatabase.Refresh(); //AssetDatabase.SaveAssets(); //} //if (EditorGUI.EndChangeCheck()) //{ // bool lBreakpoint = false; //} #if UNITY_EDITOR EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); #endif }
public static LevelData ParseMapToLevelData(TextAsset lMapFile) { s_State = ParseState.Body; s_LevelData = new LevelData(); List <QEntity> lEntities = new List <QEntity>(); { List <KeyValuePair <string, string> > lKeyValuePairs = new List <KeyValuePair <string, string> >(); List <QBrush> lBrushes = new List <QBrush>(); List <Plane> lPlanes = new List <Plane>(); QEntity lEnt = new QEntity(); QBrush lBrush = new QBrush(); string[] lLines = lMapFile.text.Split('\n'); for (int i = 0; i < lLines.Length; i++) { string lLine = lLines[i]; string[] lWords = lLine.Split(' '); if (s_State == ParseState.Body) /// Body Update { for (int j = 0; j < lWords.Length; j++) { string lWord = lWords[j]; if (lWord.Contains('{')) /// Open new Entity { s_State = ParseState.Entity; break; } } } else if (s_State == ParseState.Entity) /// Entity Update { for (int j = 0; j < lWords.Length; j++) { string lWord = lWords[j]; if (lWord.Contains('{')) /// Open New Brush { s_State = ParseState.Brush; break; } else if (lWord.Contains('}')) /// Add and Close Entity { lEnt.Brushes = lBrushes.ToArray(); lBrushes.Clear(); lEnt.KeyValuePairs = lKeyValuePairs.ToArray(); lKeyValuePairs.Clear(); for (int k = 0; k < lEnt.KeyValuePairs.Length; k++) { if (lEnt.KeyValuePairs[k].Key == CLASSNAME) { lEnt.Classname = lEnt.KeyValuePairs[k].Value; break; } } if (lEnt.Classname.Length > 0) { lEntities.Add(lEnt); } else { Debug.LogError(lEnt.ToString() + " doesn't have a classname!"); } lEnt = new QEntity(); s_State = ParseState.Body; break; } else if (j < lWords.Length - 1) /// Add Key-Value pair { string lKey = ""; string lValue = ""; int lState = 0; for (int k = 0; k < lLine.Length; k++) { char lChar = lLine[k]; if (lState == 0 && lChar == '\"') { lState = 1; } else if (lState == 1) { if (lChar == '\"') { lState = 2; } else { lKey = String.Concat(lKey, lChar); } } else if (lState == 2 && lChar == '\"') { lState = 3; } else if (lState == 3) { if (lChar == '\"') { lState = 4; break; } else { lValue = String.Concat(lValue, lChar); } } } if (lKey.Length > 0 && lValue.Length > 0) { bool lAddKeyValuePair = true; for (int k = 0; k < lKeyValuePairs.Count; k++) { if (lKeyValuePairs[k].Key == lKey) { lAddKeyValuePair = false; break; } } if (lAddKeyValuePair) { lKeyValuePairs.Add(new KeyValuePair <string, string>(lKey, lValue)); } } } } } else if (s_State == ParseState.Brush) // Brush Update { for (int j = 0; j < lWords.Length; j++) { string lWord = lWords[j]; if (lWord.Contains('}')) /// Add and Close Brush { if (lPlanes.Count > 3) { lBrush.Planes = lPlanes.ToArray(); lPlanes.Clear(); lBrushes.Add(lBrush); lBrush = new QBrush(); } s_State = ParseState.Entity; break; } else if (ContainsPlaneData(lWords, j)) /// Add Plane { float PX, PY, PZ, X1, Y1, Z1, X2, Y2, Z2; PX = float.Parse(lWords[j + 1]); PY = float.Parse(lWords[j + 2]); PZ = float.Parse(lWords[j + 3]); X1 = float.Parse(lWords[j + 6]); Y1 = float.Parse(lWords[j + 7]); Z1 = float.Parse(lWords[j + 8]); X2 = float.Parse(lWords[j + 11]); Y2 = float.Parse(lWords[j + 12]); Z2 = float.Parse(lWords[j + 13]); Vector3 lPos = new Vector3(PX, PY, PZ); Vector3 l1 = new Vector3(X1, Y1, Z1); Vector3 l2 = new Vector3(X2, Y2, Z2); l1 = (l1 - lPos).normalized; l2 = (l2 - lPos).normalized; float lTempY = lPos.y; lPos.y = lPos.z; lPos.z = lTempY; Vector3 lNormal = Vector3.Cross(l1, l2); lTempY = lNormal.y; lNormal.y = lNormal.z; lNormal.z = lTempY; lNormal.Normalize(); Plane lNewPlane = new Plane(lNormal, Vector3.Dot(lNormal, lPos * MAP_SCALE)); float OX, OY, SX, SY, A; OX = float.Parse(lWords[j + 16]); OY = float.Parse(lWords[j + 17]); A = float.Parse(lWords[j + 18]); SX = float.Parse(lWords[j + 19]); string lSYWord = lWords[j + 20]; lSYWord = lSYWord.Split('\r')[0]; SY = float.Parse(lSYWord); Vector2 lTexOffset = new Vector2(OX, OY); Vector2 lTexScale = new Vector2(SX, SY); float lTexAngle = A; lNewPlane.TextureData = new TextureData(lWords[j + 15]).SetValues(lTexOffset, lTexScale, lTexAngle); lPlanes.Add(lNewPlane); } } } } } s_LevelData.Entities = lEntities.ToArray(); for (int i = 0; i < s_LevelData.Entities.Length; i++) { QEntity lEnt = s_LevelData.Entities[i]; bool lBreak = false; for (int k = 0; k < lEnt.KeyValuePairs.Length; k++) { if (lEnt.KeyValuePairs[k].Key == CLASSNAME && lEnt.KeyValuePairs[k].Value == WORLDSPAWN) { s_LevelData.WorldSpawn = lEnt; lBreak = true; break; } } if (lBreak) { break; } } return(s_LevelData); }