public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { if (value.GetType() == typeof(string)) { string val = (string)value; SEGM segment = (SEGM)context.Instance; if (segment.Owner != null) { return(segment.Owner.Materials.Find(mat => mat.Name.Equals(val))); } else { return(base.ConvertFrom(context, culture, value)); } } else { return(base.ConvertFrom(context, culture, value)); } }
public static GameObject ImportMSH(string path) { FileInfo mshFile = new FileInfo(path); if (mshFile.Exists) { MSH msh; try { msh = MSH.LoadFromFile(mshFile.FullName); } catch { return(null); } string fileName = mshFile.Name.Replace(".msh", ""); if (CREATE_ASSETS && File.Exists("Assets/Resources/Prefabs/" + WORLD + fileName + ".prefab")) { return(UnityEngine.Object.Instantiate(Resources.Load("Prefabs/" + WORLD + fileName)) as GameObject); } if (!Directory.Exists(ASSET_PATH + "/Resources/Prefabs") && CREATE_ASSETS) { AssetDatabase.CreateFolder(@"Assets\Resources", "Prefabs"); } GameObject rootObj = new GameObject(fileName); foreach (MODL mdl in msh.Models) { if (CREATE_ASSETS && !Directory.Exists(@"Assets\Resources\Meshes\" + fileName)) { AssetDatabase.CreateFolder(@"Assets\Resources\Meshes", fileName); } if (!Array.Exists(LEGAL_TYPES, t => t == mdl.Type)) { continue; } if (!Array.Exists(LEGAL_MODELS, t => t == mdl.Tag)) { continue; } if (mdl.Geometry == null || mdl.Geometry.Segments.Count == 0) { continue; } GameObject modelObj = new GameObject(mdl.Name); modelObj.transform.SetParent(rootObj.transform); modelObj.transform.position = Vector2Unity(mdl.Translation); modelObj.transform.rotation = Quaternion.Euler(Vector2Unity(mdl.Rotation)); modelObj.transform.localScale = Vector2Unity(mdl.Scale); List <Vector3> vertices = new List <Vector3>(); List <Vector3> normals = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <Material> materials = new List <Material>(); //each segment contains its own list of triangles List <int>[] triangles = new List <int> [mdl.Geometry.Segments.Count]; //since each Segment acts as its own object (vertices, normals, triangles...) and we want to //merge all vertices into one array (as Unity expects it) but preserve our Segment Materials, //we have to set a sub mesh for each Segment, containing a list of vertex indices (of the now global vertex list). //so we have to store a offset int vertexOffset = 0; Mesh mesh = new Mesh(); mesh.name = mdl.Name; mesh.subMeshCount = mdl.Geometry.Segments.Count; Debug.Log("Sub Mesh Count set to: " + mesh.subMeshCount); for (int si = 0; si < mdl.Geometry.Segments.Count; si++) { Debug.Log("Segment No: " + si); SEGM segm = mdl.Geometry.Segments[si]; triangles[si] = new List <int>(); foreach (Vertex vert in segm.Vertices) { vertices.Add(new Vector3(-vert.position.X, vert.position.Y, vert.position.Z)); normals.Add(new Vector3(vert.normal.X, vert.normal.Y, vert.normal.Z)); uvs.Add(new Vector2(vert.uvCoordinate.X, vert.uvCoordinate.Y)); } for (int pi = 0; pi < segm.Polygons.Length; pi++) { Polygon poly = segm.Polygons[pi]; int triCount = 0; List <int> tris = new List <int>(); //in MSH, polygons are defined as triangle strips. //since unity expects just triangles, we have to strip them ourselfs for (int vi = 0; vi < poly.VertexIndices.Count; vi++) { if (triCount == 3) { vi -= 2; triCount = 0; } tris.Add(poly.VertexIndices[vi] + vertexOffset); triCount++; } //triangles are listed CW CCW CW CCW... bool flip = true; for (int j = 0; j < tris.Count; j += 3) { if (flip) { int tmp = tris[j]; tris[j] = tris[j + 2]; tris[j + 2] = tmp; } flip = !flip; } triangles[si].AddRange(tris); } //Add Segment Material to overall Material List if (DEFAULT_MATERIAL != null) { materials.Add(ChangeMaterial(segm.Material, new Material(DEFAULT_MATERIAL))); } else { materials.Add(Material2Unity(segm.Material)); } //don't forget to increase our vertex offset vertexOffset += segm.Vertices.Length; } mesh.vertices = vertices.ToArray(); mesh.normals = normals.ToArray(); mesh.uv = uvs.ToArray(); //set triangles AFTER vertices to avoid out of bounds errors for (int si = 0; si < triangles.Length; si++) { mesh.SetTriangles(triangles[si], si); } //Interpret Common and Lowrez as Geometry if (mdl.Tag == ModelTag.Common || mdl.Tag == ModelTag.Lowrez) { MeshFilter filter = modelObj.AddComponent <MeshFilter>(); filter.mesh = mesh; MeshRenderer renderer = modelObj.AddComponent <MeshRenderer>(); renderer.materials = materials.ToArray(); } //and everything else as collision / trigger else { MeshCollider collider = modelObj.AddComponent <MeshCollider>(); collider.sharedMesh = mesh; if (mdl.Tag != ModelTag.Collision && mdl.Tag != ModelTag.VehicleCollision) { collider.convex = true; collider.isTrigger = true; } } if (CREATE_ASSETS && !File.Exists(@"Assets\Resources\Meshes\" + fileName + @"\" + mdl.Name)) { AssetDatabase.CreateAsset(mesh, @"Assets\Resources\Meshes\" + fileName + @"\" + mdl.Name); } } if (CREATE_ASSETS && !File.Exists("Assets/Resources/Prefabs/" + WORLD + fileName + ".prefab")) { if (!Directory.Exists("Assets/Resources/Prefabs/" + WORLD)) { Directory.CreateDirectory("Assets/Resources/Prefabs/" + WORLD); } PrefabUtility.CreatePrefab("Assets/Resources/Prefabs/" + WORLD + fileName + ".prefab", rootObj, ReplacePrefabOptions.ConnectToPrefab); } return(rootObj); } return(null); }
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) { SEGM segment = (SEGM)context.Instance; return(new StandardValuesCollection(segment.Owner.Materials)); }
public static GameObject ImportMSH(string path, string[] additionalTextureSearchPaths = null, bool bCheckEditorExistence = false) { if (string.IsNullOrEmpty(path)) { Debug.LogError("Tried to call ImportMSH with an empty path!"); return(null); } if (PrefabMap.TryGetValue(path, out GameObject prefab)) { GameObject instance = PrefabUtility.InstantiatePrefab(prefab) as GameObject; return(instance); } FileInfo mshFile = new FileInfo(path); if (mshFile.Exists) { MSH msh; try { msh = MSH.LoadFromFile(mshFile.FullName); } catch { return(null); } string fileName = mshFile.Name.Replace(".msh", ""); if (CREATE_ASSETS) { if (!AssetDatabase.IsValidFolder("Assets" + MODELS_FOLDER)) { AssetDatabase.CreateFolder("Assets", MODELS_FOLDER.Remove(0, 1)); } if (!AssetDatabase.IsValidFolder("Assets" + MODELS_FOLDER + "/" + fileName)) { AssetDatabase.CreateFolder("Assets" + MODELS_FOLDER, fileName); } if (!AssetDatabase.IsValidFolder("Assets" + MODELS_FOLDER + "/" + fileName + "/MeshData")) { AssetDatabase.CreateFolder("Assets" + MODELS_FOLDER + "/" + fileName, "MeshData"); } } GameObject rootObj = new GameObject(fileName); Dictionary <MODL, GameObject> alreadyLoaded = new Dictionary <MODL, GameObject>(); GameObject LoadMODL(MODL mdl, GameObject currentParent) { if (mdl == null) { Debug.LogError("MODL was NULL!"); return(null); } if (currentParent == null) { Debug.LogError("currentParent was NULL!"); return(null); } if (alreadyLoaded.TryGetValue(mdl, out GameObject obj)) { return(obj); } GameObject modelObj = new GameObject(mdl.Name); if (mdl.Parent != null) { modelObj.transform.SetParent(LoadMODL(mdl.Parent, modelObj).transform); } else { modelObj.transform.SetParent(currentParent.transform); } modelObj.transform.position = Vector2Unity(mdl.Translation); modelObj.transform.rotation = Quaternion.Euler(Vector2Unity(mdl.Rotation)); modelObj.transform.localScale = Vector2Unity(mdl.Scale); if (!Array.Exists(LEGAL_TYPES, t => t == mdl.Type)) { return(modelObj); } if (!Array.Exists(LEGAL_MODELS, t => t == mdl.Tag)) { return(modelObj); } if (mdl.Geometry == null || mdl.Geometry.Segments == null) { return(modelObj); } // TODO: use arrays instead of lists List <Vector3> vertices = new List <Vector3>(); List <Vector3> normals = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <Material> materials = new List <Material>(); //each segment contains its own list of triangles List <int>[] triangles = new List <int> [mdl.Geometry.Segments.Count]; //since each Segment acts as its own object (vertices, normals, triangles...) and we want to //merge all vertices into one array (as Unity expects it) but preserve our Segment Materials, //we have to set a sub mesh for each Segment, containing a list of vertex indices (of the now global vertex list). //so we have to store an offset int vertexOffset = 0; Mesh mesh = new Mesh(); mesh.name = mdl.Name; mesh.subMeshCount = mdl.Geometry.Segments.Count; //Debug.Log("Sub Mesh Count set to: " + mesh.subMeshCount); for (int si = 0; si < mdl.Geometry.Segments.Count; si++) { //Debug.Log("Segment No: " + si); SEGM segm = mdl.Geometry.Segments[si]; triangles[si] = new List <int>(); foreach (Vertex vert in segm.Vertices) { vertices.Add(new Vector3(-vert.position.X, vert.position.Y, vert.position.Z)); normals.Add(new Vector3(vert.normal.X, vert.normal.Y, vert.normal.Z)); uvs.Add(new Vector2(vert.uvCoordinate.X, vert.uvCoordinate.Y)); } for (int pi = 0; pi < segm.Polygons.Length; pi++) { Polygon poly = segm.Polygons[pi]; int triCount = 0; List <int> tris = new List <int>(); //in MSH, polygons are defined as triangle strips. //since unity expects just triangles, we have to strip them ourselfs for (int vi = 0; vi < poly.VertexIndices.Count; vi++) { if (triCount == 3) { vi -= 2; triCount = 0; } tris.Add(poly.VertexIndices[vi] + vertexOffset); triCount++; } //triangles are listed CW CCW CW CCW... bool flip = true; for (int j = 0; j < tris.Count; j += 3) { if (flip) { int tmp = tris[j]; tris[j] = tris[j + 2]; tris[j + 2] = tmp; } flip = !flip; } triangles[si].AddRange(tris); } string[] textureDirs = new string[1] { mshFile.Directory.FullName }; if (additionalTextureSearchPaths != null) { textureDirs = new string[additionalTextureSearchPaths.Length + 1]; additionalTextureSearchPaths[0] = mshFile.Directory.FullName; Array.Copy(additionalTextureSearchPaths, 0, textureDirs, 1, additionalTextureSearchPaths.Length); } //Add Segment Material to overall Material List materials.Add(Material2Unity(textureDirs, fileName, segm.Material, DEFAULT_MATERIAL)); //don't forget to increase our vertex offset vertexOffset += segm.Vertices.Length; } mesh.vertices = vertices.ToArray(); mesh.normals = normals.ToArray(); mesh.uv = uvs.ToArray(); //set triangles AFTER vertices to avoid out of bounds errors for (int si = 0; si < triangles.Length; si++) { mesh.SetTriangles(triangles[si], si); } //Interpret Common and Lowrez as Geometry if (mdl.Tag == ModelTag.Common || mdl.Tag == ModelTag.Lowrez) { MeshFilter filter = modelObj.AddComponent <MeshFilter>(); filter.mesh = mesh; MeshRenderer renderer = modelObj.AddComponent <MeshRenderer>(); renderer.materials = materials.ToArray(); renderer.sharedMaterials = materials.ToArray(); } //and everything else as collision / trigger else { MeshCollider collider = modelObj.AddComponent <MeshCollider>(); collider.sharedMesh = mesh; if (mdl.Tag != ModelTag.Collision && mdl.Tag != ModelTag.VehicleCollision) { collider.convex = true; collider.isTrigger = true; } } if (CREATE_ASSETS) { AssetDatabase.CreateAsset(mesh, "Assets" + MODELS_FOLDER + "/" + fileName + "/MeshData/" + mesh.name + ".unitymesh"); } alreadyLoaded.Add(mdl, modelObj); return(modelObj); } foreach (MODL mdl in msh.Models) { LoadMODL(mdl, rootObj); } if (CREATE_ASSETS) { string prefabPath = "Assets" + MODELS_FOLDER + "/" + fileName + "/" + fileName + ".prefab"; GameObject newPrefab = PrefabUtility.SaveAsPrefabAssetAndConnect(rootObj, prefabPath, InteractionMode.AutomatedAction); PrefabUtility.ApplyPrefabInstance(rootObj, InteractionMode.AutomatedAction); PrefabMap.Add(path, newPrefab); } return(rootObj); } return(null); }