public override void OnInspectorGUI() { base.OnInspectorGUI(); VoxModel model = target as VoxModel; if (targetModel == null || model != targetModel) { filePath = model.modelSource; targetModel = model; } GUILayout.BeginHorizontal(); GUILayout.Label("File:", GUILayout.ExpandWidth(false)); GUILayout.TextArea(filePath.Replace(Application.dataPath, "")); if (GUILayout.Button("Open file", GUILayout.ExpandWidth(false))) { filePath = EditorUtility.OpenFilePanel("Open model", EditorPrefs.GetString("LastVoxPath", Application.dataPath), "vox"); if (File.Exists(filePath)) { EditorPrefs.SetString("LastVoxPath", filePath); } } GUILayout.EndHorizontal(); if (filePath != string.Empty) { if (GUILayout.Button("Generate Model", GUILayout.ExpandWidth(false))) { MagicaVoxelParser parser = new MagicaVoxelParser(); model.modelSource = filePath; parser.LoadModel(filePath, model); EditorUtility.SetDirty(model); string path = AssetDatabase.GetAssetPath(model); string name = Path.GetFileNameWithoutExtension(path); Object[] subAssets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(model)); //load asset meshes List <Mesh> assetMeshes = new List <Mesh>(); for (int i = 0; i < subAssets.Length; i++) { if (subAssets[i] is Mesh) { assetMeshes.Add(subAssets[i] as Mesh); } } int max = model.meshes.Count; bool update = false; Mesh m, temp; for (int i = 0; i < max; i++) { //get mesh if (i < assetMeshes.Count) { update = false; m = assetMeshes[i]; if (m == null) { update = true; m = new Mesh(); } } else { m = new Mesh(); update = true; } //turn temp meshes into assets if (i < model.meshes.Count) { m.name = name + "_frame_" + i; temp = model.meshes[i]; m.Clear(); m.vertices = temp.vertices; m.colors = temp.colors; m.normals = temp.normals; m.triangles = temp.triangles; m.uv = Unwrapping.GeneratePerTriangleUV(m); Unwrapping.GenerateSecondaryUVSet(m); //new mesh if (update) { AssetDatabase.AddObjectToAsset(m, targetModel); } model.meshes[i] = m; } } //destroy un needed meshes for (int i = 0; i < subAssets.Length; i++) { m = subAssets[i] as Mesh; if (m != null) { if (model.meshes.Contains(m) == false) { DestroyImmediate(m, true); } } } EditorUtility.SetDirty(targetModel); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } } }
GameObject GenerateModel(VoxModel model, AssetImportContext ctx) { var parser = new MagicaVoxelParser(); parser.LoadModel(ctx.assetPath, model, s => EditorUtility.DisplayProgressBar("vox", s, 0)); var subAssets = new List <Object>(); ctx.GetObjects(subAssets); var assetMeshes = subAssets .Select(s => s as Mesh) .Where(s => s != null) .ToArray(); var updateOpaque = false; var updateTransparent = false; var uv3 = new List <Vector4>(); var assetIndex = 0; for (int i = 0; i < model.meshes.Count; i++) { for (int l = 0; l < model.meshes[i].LODs.Count; l++) { MeshSet m; //get mesh m.opaque = assetIndex < assetMeshes.Length ? assetMeshes[assetIndex++] : null; m.transparent = assetIndex < assetMeshes.Length ? assetMeshes[assetIndex++] : null; updateOpaque = m.opaque == null; if (updateOpaque) { m.opaque = new Mesh(); } updateTransparent = m.transparent == null; if (updateTransparent) { m.transparent = new Mesh(); } //turn temp meshes into assets EditorUtility.DisplayProgressBar("vox", $"asset: frame={i}/{model.meshes.Count}, lod={l}/{model.meshes[i].LODs.Count}", .5f + (.5f * i) / model.voxelFrames.Count); var frame = model.meshes[i].LODs[l]; BuildMesh(m.opaque, frame.opaque, $"{name}.{i}.{l}.opaque", uv3, model.Settings.OmitsUVUnwrapping); BuildMesh(m.transparent, frame.transparent, $"{name}.{i}.{l}.transparent", uv3, model.Settings.OmitsUVUnwrapping); //new mesh if (updateOpaque) { ctx.AddObjectToAsset(m.opaque.name, m.opaque); } if (updateTransparent) { ctx.AddObjectToAsset(m.transparent.name, m.transparent); } model.meshes[i].LODs[l] = m; } } var baseGO = ctx.mainObject as GameObject; if (baseGO == null) { baseGO = new GameObject(); ctx.AddObjectToAsset("main", baseGO); ctx.SetMainObject(baseGO); } var gos = Enumerable.Range(0, baseGO.transform.childCount) .Select(i => baseGO.transform.GetChild(i)) .Select(t => t.gameObject) .ToList(); var gosCount = gos.Count; for (int i = gosCount; i < model.meshes.Count; i++) { var target = new GameObject(); target.transform.SetParent(baseGO.transform); gos.Add(target.gameObject); } BuildLODGroups(model, gos); if (model.Settings.asSceneGraph) { var root = BuildSceneGraph(model, gos); DestroyImmediate(baseGO); baseGO = root; ctx.AddObjectToAsset("main", root); ctx.SetMainObject(root); } //destroy unneeded meshes var meshSetContained = model.meshes.SelectMany(x => x.LODs).ToArray(); foreach (var go in subAssets .Where(s => (s as Mesh) != null) .Where(s => !meshSetContained.Any(x => x.Contains(s as Mesh)))) { DestroyImmediate(go, true); } //DestroyImmediate(baseGO); return(baseGO); }
void GenerateModel(string filePath, VoxModel model, VoxModel targetModel) { var parser = new MagicaVoxelParser(); //model.modelSource = filePath; parser.LoadModel(filePath, model, s => EditorUtility.DisplayProgressBar("vox", s, 0)); EditorUtility.SetDirty(model); var path = AssetDatabase.GetAssetPath(model); var name = Path.GetFileNameWithoutExtension(path); var subAssets = AssetDatabase.LoadAllAssetsAtPath(AssetDatabase.GetAssetPath(model)); //load asset meshes var assetMeshes = subAssets .Select(s => s as Mesh) .Where(s => s != null) .ToArray(); var updateOpaque = false; var updateTransparent = false; var uv3 = new List <Vector4>(); var assetIndex = 0; for (int i = 0; i < model.meshes.Count; i++) { for (int l = 0; l < model.meshes[i].LODs.Count; l++) { MeshSet m; //get mesh m.opaque = assetIndex < assetMeshes.Length ? assetMeshes[assetIndex++] : null; m.transparent = assetIndex < assetMeshes.Length ? assetMeshes[assetIndex++] : null; updateOpaque = m.opaque == null; if (updateOpaque) { m.opaque = new Mesh(); } updateTransparent = m.transparent == null; if (updateTransparent) { m.transparent = new Mesh(); } //turn temp meshes into assets EditorUtility.DisplayProgressBar("vox", $"asset: frame={i}/{model.meshes.Count}, lod={l}/{model.meshes[i].LODs.Count}", .5f + (.5f * i) / model.voxelFrames.Count); var frame = model.meshes[i].LODs[l]; BuildMesh(m.opaque, frame.opaque, $"{name}.{i}.{l}.opaque", uv3, model.Settings.OmitsUVUnwrapping); BuildMesh(m.transparent, frame.transparent, $"{name}.{i}.{l}.transparent", uv3, model.Settings.OmitsUVUnwrapping); //new mesh if (updateOpaque) { AssetDatabase.AddObjectToAsset(m.opaque, targetModel); } if (updateTransparent) { AssetDatabase.AddObjectToAsset(m.transparent, targetModel); } model.meshes[i].LODs[l] = m; } } var baseGO = new GameObject(); var gos = Enumerable.Range(0, baseGO.transform.childCount) .Select(i => baseGO.transform.GetChild(i)) .Select(t => t.gameObject) .ToList(); var gosCount = gos.Count; for (int i = gosCount; i < model.meshes.Count; i++) { var target = new GameObject(); target.transform.SetParent(baseGO.transform); gos.Add(target.gameObject); } BuildLODGroups(model, gos); if (model.Settings.asSceneGraph) { var root = BuildSceneGraph(model, gos); DestroyImmediate(baseGO); baseGO = root; } //destroy unneeded meshes foreach (var go in subAssets .Where(s => (s as Mesh) != null) .Where(s => !model.meshes.SelectMany(x => x.LODs).Any(x => x.Contains(s as Mesh)))) { DestroyImmediate(go, true); } if (targetModel.prefab == null) { targetModel.prefab = PrefabUtility.CreatePrefab(path + ".prefab", new GameObject()); } PrefabUtility.ReplacePrefab(baseGO, targetModel.prefab, ReplacePrefabOptions.ReplaceNameBased); DestroyImmediate(baseGO); EditorUtility.SetDirty(targetModel); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); }