private static void RefreshSelection() { VoxNum = 0; QbNum = 0; FolderNum = 0; JsonNum = 0; // Fix Selection var fixedSelection = new List <KeyValuePair <Object, string> >(); for (int i = 0; i < Selection.objects.Length; i++) { fixedSelection.Add(new KeyValuePair <Object, string>( Selection.objects[i], AssetDatabase.GetAssetPath(Selection.objects[i])) ); } for (int i = 0; i < fixedSelection.Count; i++) { if (!fixedSelection[i].Key) { continue; } var pathI = fixedSelection[i].Value; for (int j = 0; j < fixedSelection.Count; j++) { if (i == j || !fixedSelection[j].Key) { continue; } var pathJ = fixedSelection[j].Value; if (Util.IsChildPathCompair(pathJ, pathI)) { fixedSelection[j] = new KeyValuePair <Object, string>(null, null); } } } // Get Task Map TaskMap.Clear(); for (int i = 0; i < fixedSelection.Count; i++) { if (!fixedSelection[i].Key) { continue; } var obj = fixedSelection[i].Key; var path = fixedSelection[i].Value; var ex = Util.GetExtension(path); if (AssetDatabase.IsValidFolder(path)) { FolderNum++; var files = Util.GetFilesIn(path, "*.vox", "*.qb", "*.json"); for (int j = 0; j < files.Length; j++) { var filePath = EditorUtil.RelativePath(files[j].FullName); var fileEx = Util.GetExtension(filePath); if (fileEx == ".vox" || fileEx == ".qb" || fileEx == ".json") { var fileObj = AssetDatabase.LoadAssetAtPath <Object>(filePath); if (fileObj && !TaskMap.ContainsKey(fileObj)) { TaskMap.Add(fileObj, new PathData() { Path = filePath, Extension = fileEx, Root = Util.GetParentPath(filePath.Substring(path.Length, filePath.Length - path.Length)), }); if (fileEx == ".vox") { VoxNum++; FixVoxIcon(fileObj); } else if (fileEx == ".qb") { QbNum++; FixQbIcon(fileObj); } else if (fileEx == ".json") { JsonNum++; FixJsonIcon(fileObj); } } } } } else if (ex == ".vox" || ex == ".qb" || ex == ".json") { if (!TaskMap.ContainsKey(obj)) { TaskMap.Add(obj, new PathData() { Path = path, Extension = ex, Root = "", }); if (ex == ".vox") { VoxNum++; FixVoxIcon(obj); } else if (ex == ".qb") { QbNum++; FixQbIcon(obj); } else if (ex == ".json") { JsonNum++; FixJsonIcon(obj); } } } } ObjNum = Selection.objects.Length; }
public static void CreateFileForResult(List <VoxelCore.Result> resultList, Shader shader, float scale) { TheShader = shader; ModelScale = scale; for (int index = 0; index < resultList.Count; index++) { var result = resultList[index]; bool lod = result.VoxelModels.Length > 1; bool isRig = !lod && result.IsRigged; int realLodNum = result.VoxelModels.Length; var root = new GameObject(result.FileName).transform; var meshs = new List <Mesh>(); var materialsMap = new Dictionary <Texture2D, Material>(); Transform[] lodRoots = new Transform[realLodNum]; for (int lodIndex = 0; lodIndex < realLodNum; lodIndex++) { var voxelModel = result.VoxelModels[lodIndex]; var model = CreateModelFrom(voxelModel.RootNode, root, ref meshs, ref materialsMap, isRig, result.WithAvatar); model.name = string.Format("Root{0}", lod ? "_lod " + lodIndex.ToString() : ""); lodRoots[lodIndex] = model; // Rig if (isRig) { Vector3 halfModelSize = voxelModel.ModelSize[0] * 0.5f; halfModelSize.x = Mathf.Floor(halfModelSize.x); halfModelSize.y = Mathf.Floor(halfModelSize.y); halfModelSize.z = Mathf.Floor(halfModelSize.z); var skinMR = model.GetComponent <SkinnedMeshRenderer>(); if (skinMR) { Vector3 rootBoneOffset = halfModelSize * ModelScale; var boneTFList = new List <Transform>(); if (voxelModel.RootBones != null) { for (int i = 0; i < voxelModel.RootBones.Length; i++) { var boneTF = CreateBoneTransform(voxelModel.RootBones[i], model, ref boneTFList); if (boneTF) { boneTF.localPosition -= rootBoneOffset; } } } skinMR.bones = boneTFList.ToArray(); skinMR.rootBone = model; // Bind Poses var poses = new Matrix4x4[boneTFList.Count]; for (int i = 0; i < boneTFList.Count; i++) { poses[i] = boneTFList[i].worldToLocalMatrix * model.localToWorldMatrix; } skinMR.sharedMesh.bindposes = poses; } // Foot Fix model.localPosition = (halfModelSize - voxelModel.FootPoints[lodIndex] + Vector3.up * 0.5f) * ModelScale; } } // Lod if (lod) { LODGroup group = root.gameObject.AddComponent <LODGroup>(); LOD[] lods = new LOD[realLodNum]; for (int i = 0; i < realLodNum; i++) { lods[i] = new LOD( i == realLodNum - 1 ? 0.001f : GetLodRant(result.VoxelModels[i].MaxModelBounds, i), lodRoots[i].GetComponentsInChildren <MeshRenderer>(true) ); } #if UNITY_5_0 || UNITY_5_1 || UNITY_4 group.SetLODS(lods); group.RecalculateBounds(); #else group.SetLODs(lods); group.RecalculateBounds(); #endif } // File string path = Util.CombinePaths(result.ExportRoot, result.ExportSubRoot, result.FileName + result.Extension); string parentPath = Util.FixPath(Util.CreateParent(path)); path = Util.FixPath(path); if (result.Extension == ".prefab") { Object prefab; if (Util.FileExists(path)) { prefab = AssetDatabase.LoadAssetAtPath <Object>(path); if (prefab as GameObject) { var group = (prefab as GameObject).GetComponent <LODGroup>(); if (group) { Object.DestroyImmediate(group, true); } } Object[] things = AssetDatabase.LoadAllAssetRepresentationsAtPath(path); foreach (Object o in things) { Object.DestroyImmediate(o, true); } } else { prefab = PrefabUtility.CreateEmptyPrefab(path); } if (prefab) { // Assets for (int i = 0; i < meshs.Count; i++) { meshs[i].name = GetIndexedName("Mesh", i, meshs.Count); AssetDatabase.AddObjectToAsset(meshs[i], path); } int currentIndex = 0; foreach (var textureMat in materialsMap) { textureMat.Key.name = GetIndexedName("Texture", currentIndex, materialsMap.Count); textureMat.Value.name = GetIndexedName("Material", currentIndex, materialsMap.Count); currentIndex++; AssetDatabase.AddObjectToAsset(textureMat.Key, path); AssetDatabase.AddObjectToAsset(textureMat.Value, path); } // Avatar if (isRig && result.WithAvatar) { var avatar = GetVoxelAvatarInRoot(root); if (avatar) { avatar.name = result.FileName; AssetDatabase.AddObjectToAsset(avatar, path); // Animator var ani = root.GetComponent <Animator>(); if (!ani) { ani = root.gameObject.AddComponent <Animator>(); } ani.avatar = avatar; } } // Prefab PrefabUtility.ReplacePrefab(root.gameObject, prefab, ReplacePrefabOptions.ReplaceNameBased); } } else // Obj { string objFolderPath = Util.CombinePaths(parentPath, result.FileName); string textureFolderPath = Util.CombinePaths(objFolderPath, "Textures"); Util.CreateFolder(objFolderPath); VoxelPostprocessor.TheShader = TheShader; // Assets var model = result.VoxelModels[0]; for (int modelIndex = 0; modelIndex < model.Meshs.Length; modelIndex++) { string modelIndexedName = GetIndexedName(result.FileName, modelIndex, model.Meshs.Length); string modelPathRoot = Util.CombinePaths(objFolderPath, modelIndexedName); // Texture string texturePath = Util.CombinePaths(textureFolderPath, modelIndexedName + ".png"); var texture = model.Textures[modelIndex]; Util.ByteToFile(texture.EncodeToPNG(), texturePath); VoxelPostprocessor.AddTexture(texturePath); // Meshs var uMesh = model.Meshs[modelIndex]; for (int i = 0; i < uMesh.Count; i++) { uMesh[i].name = GetIndexedName("Mesh", i, uMesh.Count); string obj = Util.GetObj(uMesh[i]); string objPath = GetIndexedName(modelPathRoot, i, uMesh.Count) + ".obj"; bool hasObjBefore = Util.FileExists(objPath); Util.Save(obj, objPath); VoxelPostprocessor.AddObj(objPath, texturePath); if (hasObjBefore) { AssetDatabase.ImportAsset(EditorUtil.RelativePath(objPath), ImportAssetOptions.ForceUpdate); } } } } Object.DestroyImmediate(root.gameObject, false); } AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate); AssetDatabase.SaveAssets(); Resources.UnloadUnusedAssets(); EditorApplication.delayCall += VoxelPostprocessor.ClearAsset; }
private static void DoTask(Task task) { if (TaskMap.Count == 0) { return; } if (PathExportMod == ExportMod.AskEverytime && !BrowseExportPath()) { return; } RefreshMergeSetting(); string failMessage = "[Voxel] Failed to create model for {0} model{1}."; int successedNum = 0; int failedNum = 0; int taskCount = TaskMap.Count; var resultList = new List <VoxelCore.Result>(); EditorUtil.ProgressBar("Creating", "Starting task...", 0f); EditorUtil.StartWatch(); ForAllSelection((pathData) => { try { string fileName = Util.GetNameWithoutExtension(pathData.Path); EditorUtil.ProgressBar("Creating", string.Format("[{1}/{2}] Creating {0}", fileName, successedNum + failedNum + 1, taskCount), (float)(successedNum + failedNum + 1) / (taskCount + 1)); VoxelData voxelData = null; switch (task) { case Task.Prefab: case Task.Lod: case Task.Obj: // Model voxelData = VoxelFile.GetVoxelData(Util.FileToByte(pathData.Path), pathData.Extension == ".vox"); if (pathData.Extension == ".vox" || pathData.Extension == ".qb") { var result = VoxelCore.CreateLodModel(voxelData, ModelScale, task == Task.Lod ? LodNum : 1, LightMapSupportMode); if (PathExportMod == ExportMod.OriginalPath) { result.ExportRoot = Util.GetParentPath(pathData.Path); result.ExportSubRoot = ""; } else { result.ExportRoot = ExportPath; result.ExportSubRoot = pathData.Root; } result.FileName = fileName; result.Extension = task == Task.Obj ? ".obj" : ".prefab"; result.IsRigged = false; result.WithAvatar = false; resultList.Add(result); } break; case Task.ToJson: if (pathData.Extension == ".vox" || pathData.Extension == ".qb") { // Voxel To Json voxelData = VoxelFile.GetVoxelData(Util.FileToByte(pathData.Path), pathData.Extension == ".vox"); var json = VoxelCore.VoxelToJson(voxelData); string path = PathExportMod == ExportMod.OriginalPath ? Util.ChangeExtension(pathData.Path, ".json") : Util.CombinePaths(ExportPath, pathData.Root, fileName + ".json"); Util.CreateParent(path); Util.Save(json, path); } break; case Task.ToVox: case Task.ToQb: // Json To Voxel string aimEx = task == Task.ToVox ? ".vox" : ".qb"; if (pathData.Extension == ".json") { voxelData = VoxelCore.JsonToVoxel(Util.Load(pathData.Path)); } else if (pathData.Extension == ".vox" || pathData.Extension == ".qb") { if (aimEx != pathData.Extension) { voxelData = VoxelFile.GetVoxelData(Util.FileToByte(pathData.Path), pathData.Extension == ".vox"); } } if (voxelData) { string aimPath = PathExportMod == ExportMod.OriginalPath ? Util.ChangeExtension(pathData.Path, aimEx) : Util.CombinePaths(ExportPath, pathData.Root, fileName + aimEx); Util.ByteToFile( VoxelFile.GetVoxelByte(voxelData, task == Task.ToVox), aimPath ); } break; } successedNum++; } catch (System.Exception ex) { failMessage += "\n" + ex.Message; failedNum++; } }); // File try { EditorVoxelCore.CreateFileForResult(resultList, TheShader, ModelScale); double taskTime = EditorUtil.StopWatchAndGetTime(); // Log Messages if (successedNum > 0) { string msg = string.Format("[Voxel] {0} model{1} created in {2}sec.", successedNum, (successedNum > 1 ? "s" : ""), taskTime.ToString("0.00")); if (LogMessage) { Debug.Log(msg); } if (ShowDialog) { EditorUtil.Dialog("Success", msg, "OK"); } } if (failedNum > 0) { string msg = string.Format(failMessage, failedNum.ToString(), (failedNum > 1 ? "s" : "")); if (LogMessage) { Debug.LogWarning(msg); } if (ShowDialog) { EditorUtil.Dialog("Warning", msg, "OK"); } } } catch (System.Exception ex) { Debug.LogError(ex.Message); } EditorUtil.ClearProgressBar(); }