From 7cffcf221595a83f58d28c9207f1eec98dd5f298 Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 14 Feb 2019 16:09:48 -0800 Subject: [PATCH] error handling, warnings for duplicate textures --- .../Assets/Editor/AvatarExporter.cs | 166 +++++++++++------- .../avatarExporter.unitypackage | Bin 13314 -> 13655 bytes 2 files changed, 106 insertions(+), 60 deletions(-) diff --git a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs index 2d0148b25e..624b365c17 100644 --- a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs +++ b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs @@ -263,6 +263,7 @@ class AvatarExporter : MonoBehaviour { static string assetPath = ""; static string assetName = ""; static HumanDescription humanDescription; + static Dictionary dependencyTextures = new Dictionary(); [MenuItem("High Fidelity/Export New Avatar")] static void ExportNewAvatar() { @@ -304,51 +305,38 @@ class AvatarExporter : MonoBehaviour { humanDescription = modelImporter.humanDescription; SetUserBoneInformation(); + string textureWarnings = SetTextureDependencies(); + + // generate the list of bone rule failure strings for any bone rules that are not satisfied by this avatar + SetFailedBoneRules(); + + // check if we should be substituting a bone for a missing UpperChest mapping + AdjustUpperChestMapping(); // format resulting bone rule failure strings // consider export-blocking bone rules to be errors and show them in an error dialog, - // and also include any other bone rule failures as warnings in the dialog + // and also include any other bone rule failures plus texture warnings as warnings in the dialog string boneErrors = ""; - string boneWarnings = ""; + string warnings = ""; foreach (var failedBoneRule in failedBoneRules) { if (Array.IndexOf(EXPORT_BLOCKING_BONE_RULES, failedBoneRule.Key) >= 0) { boneErrors += failedBoneRule.Value + "\n\n"; } else { - boneWarnings += failedBoneRule.Value + "\n\n"; + warnings += failedBoneRule.Value + "\n\n"; } } + warnings += textureWarnings; if (!string.IsNullOrEmpty(boneErrors)) { // if there are both errors and warnings then warnings will be displayed with errors in the error dialog - if (!string.IsNullOrEmpty(boneWarnings)) { + if (!string.IsNullOrEmpty(warnings)) { boneErrors = "Errors:\n\n" + boneErrors; - boneErrors += "Warnings:\n\n" + boneWarnings; + boneErrors += "Warnings:\n\n" + warnings; } // remove ending newlines from the last rule failure string that was added above boneErrors = boneErrors.Substring(0, boneErrors.LastIndexOf("\n\n")); EditorUtility.DisplayDialog("Error", boneErrors, "Ok"); return; } - - if (!humanoidToUserBoneMappings.ContainsKey("UpperChest")) { - // if parent of Neck is not Chest then map the parent to UpperChest - string neckUserBone; - if (humanoidToUserBoneMappings.TryGetValue("Neck", out neckUserBone)) { - UserBoneInformation neckParentBoneInfo; - string neckParentUserBone = userBoneInfos[neckUserBone].parentName; - if (userBoneInfos.TryGetValue(neckParentUserBone, out neckParentBoneInfo) && !neckParentBoneInfo.HasHumanMapping()) { - neckParentBoneInfo.humanName = "UpperChest"; - humanoidToUserBoneMappings.Add("UpperChest", neckParentUserBone); - } - } - // if there is still no UpperChest bone but there is a Chest bone then we remap Chest to UpperChest - string chestUserBone; - if (!humanoidToUserBoneMappings.ContainsKey("UpperChest") && - humanoidToUserBoneMappings.TryGetValue("Chest", out chestUserBone)) { - userBoneInfos[chestUserBone].humanName = "UpperChest"; - humanoidToUserBoneMappings.Remove("Chest"); - humanoidToUserBoneMappings.Add("UpperChest", chestUserBone); - } - } string documentsFolder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments); string hifiFolder = documentsFolder + "\\High Fidelity Projects"; @@ -407,7 +395,13 @@ class AvatarExporter : MonoBehaviour { return; } else if (option == 0) { // Yes - copy model to Unity project // copy the fbx from the project folder to Unity Assets, overwriting the existing fbx, and re-import it - File.Copy(exportModelPath, assetPath, true); + try { + File.Copy(exportModelPath, assetPath, true); + } catch { + EditorUtility.DisplayDialog("Error", "Failed to copy existing file " + exportModelPath + " to " + assetPath + + ". Please check the location and try again.", "Ok"); + return; + } AssetDatabase.ImportAsset(assetPath); // set model to Humanoid animation type and force another refresh on it to process Humanoid @@ -455,12 +449,21 @@ class AvatarExporter : MonoBehaviour { } // write out a new fst file in place of the old file - WriteFST(exportFstPath, projectName); + if (!WriteFST(exportFstPath, projectName)) { + return; + } + + // copy any external texture files to the project's texture directory that are + // considered dependencies of the model, and overwrite any existing ones + string texturesDirectory = Path.GetDirectoryName(exportFstPath) + "\\textures"; + if (!CopyExternalTextures(texturesDirectory, true)) { + return; + } // display success dialog with any bone rule warnings string successDialog = "Avatar successfully updated!"; - if (!string.IsNullOrEmpty(boneWarnings)) { - successDialog += "\n\nWarnings:\n" + boneWarnings; + if (!string.IsNullOrEmpty(warnings)) { + successDialog += "\n\nWarnings:\n" + warnings; } EditorUtility.DisplayDialog("Success!", successDialog, "Ok"); } else { // Export New Avatar menu option @@ -469,33 +472,13 @@ class AvatarExporter : MonoBehaviour { Directory.CreateDirectory(hifiFolder); } - if (string.IsNullOrEmpty(boneWarnings)) { - boneWarnings = EMPTY_WARNING_TEXT; + if (string.IsNullOrEmpty(warnings)) { + warnings = EMPTY_WARNING_TEXT; } // open a popup window to enter new export project name and project location ExportProjectWindow window = ScriptableObject.CreateInstance(); - window.Init(hifiFolder, boneWarnings, OnExportProjectWindowClose); - } - } - - static void CopyExternalTextures(string texturesDirectory) { - List texturePaths = new List(); - - // build the list of all local asset paths for textures that Unity considers dependencies of the model - string[] dependencies = AssetDatabase.GetDependencies(assetPath); - foreach (string dependencyPath in dependencies) { - UnityEngine.Object textureObject = AssetDatabase.LoadAssetAtPath(dependencyPath, typeof(Texture2D)); - if (textureObject != null) { - texturePaths.Add(dependencyPath); - } - } - - // copy the found dependency textures from the local asset folder to the textures folder in the target export project - foreach (string texturePath in texturePaths) { - string textureName = Path.GetFileName(texturePath); - string targetPath = texturesDirectory + "\\" + textureName; - File.Copy(texturePath, targetPath); + window.Init(hifiFolder, warnings, OnExportProjectWindowClose); } } @@ -512,11 +495,15 @@ class AvatarExporter : MonoBehaviour { // write out the avatar.fst file to the project directory string exportFstPath = projectDirectory + "avatar.fst"; - WriteFST(exportFstPath, projectName); + if (!WriteFST(exportFstPath, projectName)) { + return; + } // copy any external texture files to the project's texture directory that are considered dependencies of the model texturesDirectory = texturesDirectory.Replace("\\\\", "\\"); - CopyExternalTextures(texturesDirectory); + if (!CopyExternalTextures(texturesDirectory, false)) { + return; + } // remove any double slashes in texture directory path, display success dialog with any // bone warnings previously mentioned, and suggest user to copy external textures over @@ -529,7 +516,7 @@ class AvatarExporter : MonoBehaviour { EditorUtility.DisplayDialog("Success!", successDialog, "Ok"); } - static void WriteFST(string exportFstPath, string projectName) { + static bool WriteFST(string exportFstPath, string projectName) { // write out core fields to top of fst file try { File.WriteAllText(exportFstPath, "name = " + projectName + "\ntype = body+head\nscale = 1\nfilename = " + @@ -537,7 +524,7 @@ class AvatarExporter : MonoBehaviour { } catch { EditorUtility.DisplayDialog("Error", "Failed to write file " + exportFstPath + ". Please check the location and try again.", "Ok"); - return; + return false; } // write out joint mappings to fst file @@ -596,6 +583,8 @@ class AvatarExporter : MonoBehaviour { // open File Explorer to the project directory once finished System.Diagnostics.Process.Start("explorer.exe", "/select," + exportFstPath); + + return true; } static void SetUserBoneInformation() { @@ -625,9 +614,6 @@ class AvatarExporter : MonoBehaviour { } } } - - // generate the list of bone rule failure strings for any bone rules that are not satisfied by this avatar - SetFailedBoneRules(); } static void TraverseUserBoneTree(Transform modelBone) { @@ -675,6 +661,29 @@ class AvatarExporter : MonoBehaviour { return result; } + static void AdjustUpperChestMapping() { + if (!humanoidToUserBoneMappings.ContainsKey("UpperChest")) { + // if parent of Neck is not Chest then map the parent to UpperChest + string neckUserBone; + if (humanoidToUserBoneMappings.TryGetValue("Neck", out neckUserBone)) { + UserBoneInformation neckParentBoneInfo; + string neckParentUserBone = userBoneInfos[neckUserBone].parentName; + if (userBoneInfos.TryGetValue(neckParentUserBone, out neckParentBoneInfo) && !neckParentBoneInfo.HasHumanMapping()) { + neckParentBoneInfo.humanName = "UpperChest"; + humanoidToUserBoneMappings.Add("UpperChest", neckParentUserBone); + } + } + // if there is still no UpperChest bone but there is a Chest bone then we remap Chest to UpperChest + string chestUserBone; + if (!humanoidToUserBoneMappings.ContainsKey("UpperChest") && + humanoidToUserBoneMappings.TryGetValue("Chest", out chestUserBone)) { + userBoneInfos[chestUserBone].humanName = "UpperChest"; + humanoidToUserBoneMappings.Remove("Chest"); + humanoidToUserBoneMappings.Add("UpperChest", chestUserBone); + } + } + } + static void SetFailedBoneRules() { failedBoneRules.Clear(); @@ -888,6 +897,43 @@ class AvatarExporter : MonoBehaviour { appendage + " (" + rightCount + ")."); } } + + static string SetTextureDependencies() { + string textureWarnings = ""; + dependencyTextures.Clear(); + + // build the list of all local asset paths for textures that Unity considers dependencies of the model + // for any textures that have duplicate names, return a string of duplicate name warnings + string[] dependencies = AssetDatabase.GetDependencies(assetPath); + foreach (string dependencyPath in dependencies) { + UnityEngine.Object textureObject = AssetDatabase.LoadAssetAtPath(dependencyPath, typeof(Texture2D)); + if (textureObject != null) { + string textureName = Path.GetFileName(dependencyPath); + if (dependencyTextures.ContainsKey(textureName)) { + textureWarnings += "There is more than one texture with the name " + textureName + ".\n\n"; + } else { + dependencyTextures.Add(textureName, dependencyPath); + } + } + } + + return textureWarnings; + } + + static bool CopyExternalTextures(string texturesDirectory, bool overwriteExisting) { + // copy the found dependency textures from the local asset folder to the textures folder in the target export project + foreach (var texture in dependencyTextures) { + string targetPath = texturesDirectory + "\\" + texture.Key; + try { + File.Copy(texture.Value, targetPath, overwriteExisting); + } catch { + EditorUtility.DisplayDialog("Error", "Failed to copy texture file " + texture.Value + " to " + targetPath + + ". Please check the location and try again.", "Ok"); + return false; + } + } + return true; + } } class ExportProjectWindow : EditorWindow { diff --git a/tools/unity-avatar-exporter/avatarExporter.unitypackage b/tools/unity-avatar-exporter/avatarExporter.unitypackage index 96a801496686bfb8536dc9fd97d65d8e68868791..3c331ce9e0b03e35850ca6138b53a5689e0e8db0 100644 GIT binary patch literal 13655 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