diff --git a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/AvatarExporter.cs similarity index 67% rename from tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs rename to tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/AvatarExporter.cs index c25a962824..142e4ae35a 100644 --- a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter.cs +++ b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/AvatarExporter.cs @@ -6,15 +6,18 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -using UnityEngine; using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine; +using UnityEngine.SceneManagement; using System; -using System.IO; using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; class AvatarExporter : MonoBehaviour { // update version number for every PR that changes this file, also set updated version in README file - static readonly string AVATAR_EXPORTER_VERSION = "0.3.3"; + static readonly string AVATAR_EXPORTER_VERSION = "0.3.5"; static readonly float HIPS_GROUND_MIN_Y = 0.01f; static readonly float HIPS_SPINE_CHEST_MIN_SEPARATION = 0.001f; @@ -22,6 +25,9 @@ class AvatarExporter : MonoBehaviour { static readonly string EMPTY_WARNING_TEXT = "None"; static readonly string TEXTURES_DIRECTORY = "textures"; static readonly string DEFAULT_MATERIAL_NAME = "No Name"; + static readonly string HEIGHT_REFERENCE_PREFAB = "Assets/Editor/AvatarExporter/HeightReference.prefab"; + static readonly Vector3 PREVIEW_CAMERA_PIVOT = new Vector3(0.0f, 1.755f, 0.0f); + static readonly Vector3 PREVIEW_CAMERA_DIRECTION = new Vector3(0.0f, 0.0f, -1.0f); // TODO: use regex static readonly string[] RECOMMENDED_UNITY_VERSIONS = new string[] { @@ -298,18 +304,17 @@ class AvatarExporter : MonoBehaviour { if (!string.IsNullOrEmpty(occlusionMap)) { json += "\"occlusionMap\": \"" + occlusionMap + "\", "; } - json += "\"emissive\": [" + emissive.r + ", " + emissive.g + ", " + emissive.b + "] "; + json += "\"emissive\": [" + emissive.r + ", " + emissive.g + ", " + emissive.b + "]"; if (!string.IsNullOrEmpty(emissiveMap)) { - json += "\", emissiveMap\": \"" + emissiveMap + "\""; + json += ", \"emissiveMap\": \"" + emissiveMap + "\""; } - json += "} }"; + json += " } }"; return json; } } static string assetPath = ""; - static string assetName = ""; - + static string assetName = ""; static ModelImporter modelImporter; static HumanDescription humanDescription; @@ -317,12 +322,23 @@ class AvatarExporter : MonoBehaviour { static Dictionary humanoidToUserBoneMappings = new Dictionary(); static BoneTreeNode userBoneTree = new BoneTreeNode(); static Dictionary failedAvatarRules = new Dictionary(); + static string warnings = ""; static Dictionary textureDependencies = new Dictionary(); static Dictionary materialMappings = new Dictionary(); static Dictionary materialDatas = new Dictionary(); - static List materialAlternateStandardShader = new List(); - static Dictionary materialUnsupportedShader = new Dictionary(); + static List alternateStandardShaderMaterials = new List(); + static List unsupportedShaderMaterials = new List(); + + static Scene previewScene; + static string previousScene = ""; + static Vector3 previousScenePivot = Vector3.zero; + static Quaternion previousSceneRotation = Quaternion.identity; + static float previousSceneSize = 0.0f; + static bool previousSceneOrthographic = false; + static UnityEngine.Object avatarResource; + static GameObject avatarPreviewObject; + static GameObject heightReferenceObject; [MenuItem("High Fidelity/Export New Avatar")] static void ExportNewAvatar() { @@ -339,8 +355,8 @@ class AvatarExporter : MonoBehaviour { EditorUtility.DisplayDialog("About", "High Fidelity, Inc.\nAvatar Exporter\nVersion " + AVATAR_EXPORTER_VERSION, "Ok"); } - static void ExportSelectedAvatar(bool updateAvatar) { - // ensure everything is saved to file before exporting + static void ExportSelectedAvatar(bool updateExistingAvatar) { + // ensure everything is saved to file before doing anything AssetDatabase.SaveAssets(); string[] guids = Selection.assetGUIDs; @@ -364,6 +380,11 @@ class AvatarExporter : MonoBehaviour { " the Rig section of it's Inspector window.", "Ok"); return; } + + avatarResource = AssetDatabase.LoadAssetAtPath(assetPath, typeof(UnityEngine.Object)); + humanDescription = modelImporter.humanDescription; + + string textureWarnings = SetTextureDependencies(); // if the rig is optimized we should de-optimize it during the export process bool shouldDeoptimizeGameObjects = modelImporter.optimizeGameObjects; @@ -371,28 +392,23 @@ class AvatarExporter : MonoBehaviour { modelImporter.optimizeGameObjects = false; modelImporter.SaveAndReimport(); } - - humanDescription = modelImporter.humanDescription; - string textureWarnings = SetTextureDependencies(); + SetBoneAndMaterialInformation(); + if (shouldDeoptimizeGameObjects) { + // switch back to optimized game object in case it was originally optimized + modelImporter.optimizeGameObjects = true; + modelImporter.SaveAndReimport(); + } + // check if we should be substituting a bone for a missing UpperChest mapping AdjustUpperChestMapping(); // format resulting avatar rule failure strings // consider export-blocking avatar rules to be errors and show them in an error dialog, // and also include any other avatar rule failures plus texture warnings as warnings in the dialog - if (shouldDeoptimizeGameObjects) { - // switch back to optimized game object in case it was originally optimized - modelImporter.optimizeGameObjects = true; - modelImporter.SaveAndReimport(); - } - - // 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 plus texture warnings as warnings in the dialog string boneErrors = ""; - string warnings = ""; + warnings = ""; foreach (var failedAvatarRule in failedAvatarRules) { if (Array.IndexOf(EXPORT_BLOCKING_AVATAR_RULES, failedAvatarRule.Key) >= 0) { boneErrors += failedAvatarRule.Value + "\n\n"; @@ -400,15 +416,16 @@ class AvatarExporter : MonoBehaviour { warnings += failedAvatarRule.Value + "\n\n"; } } - foreach (string materialName in materialAlternateStandardShader) { - warnings += "The material " + materialName + " is not using the recommended variation of the Standard shader. " + - "We recommend you change it to Standard (Roughness setup) shader for improved performance.\n\n"; - } - foreach (var material in materialUnsupportedShader) { - warnings += "The material " + material.Key + " is using an unsupported shader " + material.Value + - ". Please change it to a Standard shader type.\n\n"; - } + + // add material and texture warnings after bone-related warnings + AddMaterialWarnings(); warnings += textureWarnings; + + // remove trailing newlines at the end of the warnings + if (!string.IsNullOrEmpty(warnings)) { + warnings = warnings.Substring(0, warnings.LastIndexOf("\n\n")); + } + 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(warnings)) { @@ -421,150 +438,157 @@ class AvatarExporter : MonoBehaviour { return; } + // since there are no errors we can now open the preview scene in place of the user's scene + if (!OpenPreviewScene()) { + return; + } + + // show None instead of blank warnings if there are no warnings in the export windows + if (string.IsNullOrEmpty(warnings)) { + warnings = EMPTY_WARNING_TEXT; + } + string documentsFolder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments); string hifiFolder = documentsFolder + "\\High Fidelity Projects"; - if (updateAvatar) { // Update Existing Avatar menu option - bool copyModelToExport = false; + if (updateExistingAvatar) { // Update Existing Avatar menu option + // open update existing project popup window including project to update, scale, and warnings + // default the initial file chooser location to HiFi projects folder in user documents folder + ExportProjectWindow window = ScriptableObject.CreateInstance(); string initialPath = Directory.Exists(hifiFolder) ? hifiFolder : documentsFolder; - - // open file explorer defaulting to hifi projects folder in user documents to select target fst to update - string exportFstPath = EditorUtility.OpenFilePanel("Select .fst to update", initialPath, "fst"); - if (exportFstPath.Length == 0) { // file selection cancelled - return; - } - exportFstPath = exportFstPath.Replace('/', '\\'); - - // lookup the project name field from the fst file to update - string projectName = ""; - try { - string[] lines = File.ReadAllLines(exportFstPath); - foreach (string line in lines) { - int separatorIndex = line.IndexOf("="); - if (separatorIndex >= 0) { - string key = line.Substring(0, separatorIndex).Trim(); - if (key == "name") { - projectName = line.Substring(separatorIndex + 1).Trim(); - break; - } - } - } - } catch { - EditorUtility.DisplayDialog("Error", "Failed to read from existing file " + exportFstPath + - ". Please check the file and try again.", "Ok"); - return; - } - - string exportModelPath = Path.GetDirectoryName(exportFstPath) + "\\" + assetName + ".fbx"; - if (File.Exists(exportModelPath)) { - // if the fbx in Unity Assets is newer than the fbx in the target export - // folder or vice-versa then ask to replace the older fbx with the newer fbx - DateTime assetModelWriteTime = File.GetLastWriteTime(assetPath); - DateTime targetModelWriteTime = File.GetLastWriteTime(exportModelPath); - if (assetModelWriteTime > targetModelWriteTime) { - int option = EditorUtility.DisplayDialogComplex("Error", "The " + assetName + - ".fbx model in the Unity Assets folder is newer than the " + exportModelPath + - " model.\n\nDo you want to replace the older .fbx with the newer .fbx?", - "Yes", "No", "Cancel"); - if (option == 2) { // Cancel - return; - } - copyModelToExport = option == 0; // Yes - } else if (assetModelWriteTime < targetModelWriteTime) { - int option = EditorUtility.DisplayDialogComplex("Error", "The " + exportModelPath + - " model is newer than the " + assetName + ".fbx model in the Unity Assets folder." + - "\n\nDo you want to replace the older .fbx with the newer .fbx and re-import it?", - "Yes", "No" , "Cancel"); - if (option == 2) { // Cancel - 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 - 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 - modelImporter = ModelImporter.GetAtPath(assetPath) as ModelImporter; - modelImporter.animationType = ModelImporterAnimationType.Human; - EditorUtility.SetDirty(modelImporter); - modelImporter.SaveAndReimport(); - - // redo parent names, joint mappings, and user bone positions due to the fbx change - // as well as re-check the avatar rules for failures - humanDescription = modelImporter.humanDescription; - SetBoneAndMaterialInformation(); - } - } - } else { - // if no matching fbx exists in the target export folder then ask to copy fbx over - int option = EditorUtility.DisplayDialogComplex("Error", "There is no existing " + exportModelPath + - " model.\n\nDo you want to copy over the " + assetName + - ".fbx model from the Unity Assets folder?", "Yes", "No", "Cancel"); - if (option == 2) { // Cancel - return; - } - copyModelToExport = option == 0; // Yes - } - - // copy asset fbx over deleting any existing fbx if we agreed to overwrite it - if (copyModelToExport) { - try { - File.Copy(assetPath, exportModelPath, true); - } catch { - EditorUtility.DisplayDialog("Error", "Failed to copy existing file " + assetPath + " to " + exportModelPath + - ". Please check the location and try again.", "Ok"); - return; - } - } - - // delete existing fst file since we will write a new file - // TODO: updating fst should only rewrite joint mappings and joint rotation offsets to existing file - try { - File.Delete(exportFstPath); - } catch { - EditorUtility.DisplayDialog("Error", "Failed to overwrite existing file " + exportFstPath + - ". Please check the file and try again.", "Ok"); - return; - } - - // write out a new fst file in place of the old file - if (!WriteFST(exportFstPath, projectName)) { - return; - } - - // copy any external texture files to the project's texture directory that are considered dependencies of the model - string texturesDirectory = GetTextureDirectory(exportFstPath); - if (!CopyExternalTextures(texturesDirectory)) { - return; - } - - // display success dialog with any avatar rule warnings - string successDialog = "Avatar successfully updated!"; - if (!string.IsNullOrEmpty(warnings)) { - successDialog += "\n\nWarnings:\n" + warnings; - } - EditorUtility.DisplayDialog("Success!", successDialog, "Ok"); + window.Init(initialPath, warnings, updateExistingAvatar, avatarPreviewObject, OnUpdateExistingProject, OnExportWindowClose); } else { // Export New Avatar menu option // create High Fidelity Projects folder in user documents folder if it doesn't exist if (!Directory.Exists(hifiFolder)) { Directory.CreateDirectory(hifiFolder); } - if (string.IsNullOrEmpty(warnings)) { - warnings = EMPTY_WARNING_TEXT; - } - - // open a popup window to enter new export project name and project location + // open export new project popup window including project name, project location, scale, and warnings + // default the initial project location path to the High Fidelity Projects folder above ExportProjectWindow window = ScriptableObject.CreateInstance(); - window.Init(hifiFolder, warnings, OnExportProjectWindowClose); + window.Init(hifiFolder, warnings, updateExistingAvatar, avatarPreviewObject, OnExportNewProject, OnExportWindowClose); } } - static void OnExportProjectWindowClose(string projectDirectory, string projectName, string warnings) { + static void OnUpdateExistingProject(string exportFstPath, string projectName, float scale) { + bool copyModelToExport = false; + + // lookup the project name field from the fst file to update + projectName = ""; + try { + string[] lines = File.ReadAllLines(exportFstPath); + foreach (string line in lines) { + int separatorIndex = line.IndexOf("="); + if (separatorIndex >= 0) { + string key = line.Substring(0, separatorIndex).Trim(); + if (key == "name") { + projectName = line.Substring(separatorIndex + 1).Trim(); + break; + } + } + } + } catch { + EditorUtility.DisplayDialog("Error", "Failed to read from existing file " + exportFstPath + + ". Please check the file and try again.", "Ok"); + return; + } + + string exportModelPath = Path.GetDirectoryName(exportFstPath) + "\\" + assetName + ".fbx"; + if (File.Exists(exportModelPath)) { + // if the fbx in Unity Assets is newer than the fbx in the target export + // folder or vice-versa then ask to replace the older fbx with the newer fbx + DateTime assetModelWriteTime = File.GetLastWriteTime(assetPath); + DateTime targetModelWriteTime = File.GetLastWriteTime(exportModelPath); + if (assetModelWriteTime > targetModelWriteTime) { + int option = EditorUtility.DisplayDialogComplex("Error", "The " + assetName + + ".fbx model in the Unity Assets folder is newer than the " + exportModelPath + + " model.\n\nDo you want to replace the older .fbx with the newer .fbx?", + "Yes", "No", "Cancel"); + if (option == 2) { // Cancel + return; + } + copyModelToExport = option == 0; // Yes + } else if (assetModelWriteTime < targetModelWriteTime) { + int option = EditorUtility.DisplayDialogComplex("Error", "The " + exportModelPath + + " model is newer than the " + assetName + ".fbx model in the Unity Assets folder." + + "\n\nDo you want to replace the older .fbx with the newer .fbx and re-import it?", + "Yes", "No" , "Cancel"); + if (option == 2) { // Cancel + 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 + 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 + modelImporter = ModelImporter.GetAtPath(assetPath) as ModelImporter; + modelImporter.animationType = ModelImporterAnimationType.Human; + EditorUtility.SetDirty(modelImporter); + modelImporter.SaveAndReimport(); + + // redo parent names, joint mappings, and user bone positions due to the fbx change + // as well as re-check the avatar rules for failures + humanDescription = modelImporter.humanDescription; + SetBoneAndMaterialInformation(); + } + } + } else { + // if no matching fbx exists in the target export folder then ask to copy fbx over + int option = EditorUtility.DisplayDialogComplex("Error", "There is no existing " + exportModelPath + + " model.\n\nDo you want to copy over the " + assetName + + ".fbx model from the Unity Assets folder?", "Yes", "No", "Cancel"); + if (option == 2) { // Cancel + return; + } + copyModelToExport = option == 0; // Yes + } + + // copy asset fbx over deleting any existing fbx if we agreed to overwrite it + if (copyModelToExport) { + try { + File.Copy(assetPath, exportModelPath, true); + } catch { + EditorUtility.DisplayDialog("Error", "Failed to copy existing file " + assetPath + " to " + exportModelPath + + ". Please check the location and try again.", "Ok"); + return; + } + } + + // delete existing fst file since we will write a new file + // TODO: updating fst should only rewrite joint mappings and joint rotation offsets to existing file + try { + File.Delete(exportFstPath); + } catch { + EditorUtility.DisplayDialog("Error", "Failed to overwrite existing file " + exportFstPath + + ". Please check the file and try again.", "Ok"); + return; + } + + // write out a new fst file in place of the old file + if (!WriteFST(exportFstPath, projectName, scale)) { + return; + } + + // copy any external texture files to the project's texture directory that are considered dependencies of the model + string texturesDirectory = GetTextureDirectory(exportFstPath); + if (!CopyExternalTextures(texturesDirectory)) { + return; + } + + // display success dialog with any avatar rule warnings + string successDialog = "Avatar successfully updated!"; + if (!string.IsNullOrEmpty(warnings)) { + successDialog += "\n\nWarnings:\n" + warnings; + } + EditorUtility.DisplayDialog("Success!", successDialog, "Ok"); + } + + static void OnExportNewProject(string projectDirectory, string projectName, float scale) { // copy the fbx from the Unity Assets folder to the project directory string exportModelPath = projectDirectory + assetName + ".fbx"; File.Copy(assetPath, exportModelPath); @@ -577,7 +601,7 @@ class AvatarExporter : MonoBehaviour { // write out the avatar.fst file to the project directory string exportFstPath = projectDirectory + "avatar.fst"; - if (!WriteFST(exportFstPath, projectName)) { + if (!WriteFST(exportFstPath, projectName, scale)) { return; } @@ -592,16 +616,27 @@ class AvatarExporter : MonoBehaviour { if (warnings != EMPTY_WARNING_TEXT) { successDialog += "Warnings:\n" + warnings; } - successDialog += "Note: If you are using any external textures with your model, " + + successDialog += "\n\nNote: If you are using any external textures with your model, " + "please ensure those textures are copied to " + texturesDirectory; EditorUtility.DisplayDialog("Success!", successDialog, "Ok"); } + + static void OnExportWindowClose() { + // close the preview avatar scene and go back to user's previous scene when export project windows close + ClosePreviewScene(); + } - static bool WriteFST(string exportFstPath, string projectName) { + // The High Fidelity FBX Serializer omits the colon based prefixes. This will make the jointnames compatible. + static string removeTypeFromJointname(string jointName) { + return jointName.Substring(jointName.IndexOf(':') + 1); + } + + static bool WriteFST(string exportFstPath, string projectName, float scale) { // write out core fields to top of fst file try { - File.WriteAllText(exportFstPath, "name = " + projectName + "\ntype = body+head\nscale = 1\nfilename = " + - assetName + ".fbx\n" + "texdir = textures\n"); + File.WriteAllText(exportFstPath, "exporterVersion = " + AVATAR_EXPORTER_VERSION + "\nname = " + projectName + + "\ntype = body+head\nscale = " + scale + "\nfilename = " + assetName + + ".fbx\n" + "texdir = textures\n"); } catch { EditorUtility.DisplayDialog("Error", "Failed to write file " + exportFstPath + ". Please check the location and try again.", "Ok"); @@ -612,7 +647,7 @@ class AvatarExporter : MonoBehaviour { foreach (var userBoneInfo in userBoneInfos) { if (userBoneInfo.Value.HasHumanMapping()) { string hifiJointName = HUMANOID_TO_HIFI_JOINT_NAME[userBoneInfo.Value.humanName]; - File.AppendAllText(exportFstPath, "jointMap = " + hifiJointName + " = " + userBoneInfo.Key + "\n"); + File.AppendAllText(exportFstPath, "jointMap = " + hifiJointName + " = " + removeTypeFromJointname(userBoneInfo.Key) + "\n"); } } @@ -653,7 +688,7 @@ class AvatarExporter : MonoBehaviour { // swap from left-handed (Unity) to right-handed (HiFi) coordinates and write out joint rotation offset to fst jointOffset = new Quaternion(-jointOffset.x, jointOffset.y, jointOffset.z, -jointOffset.w); - File.AppendAllText(exportFstPath, "jointRotationOffset2 = " + userBoneName + " = (" + jointOffset.x + ", " + + File.AppendAllText(exportFstPath, "jointRotationOffset2 = " + removeTypeFromJointname(userBoneName) + " = (" + jointOffset.x + ", " + jointOffset.y + ", " + jointOffset.z + ", " + jointOffset.w + ")\n"); } @@ -690,14 +725,13 @@ class AvatarExporter : MonoBehaviour { userBoneTree = new BoneTreeNode(); materialDatas.Clear(); - materialAlternateStandardShader.Clear(); - materialUnsupportedShader.Clear(); - + alternateStandardShaderMaterials.Clear(); + unsupportedShaderMaterials.Clear(); + SetMaterialMappings(); - - // instantiate a game object of the user avatar to traverse the bone tree to gather - // bone parents and positions as well as build a bone tree, then destroy it - UnityEngine.Object avatarResource = AssetDatabase.LoadAssetAtPath(assetPath, typeof(UnityEngine.Object)); + + // instantiate a game object of the user avatar to traverse the bone tree to gather + // bone parents and positions as well as build a bone tree, then destroy it GameObject assetGameObject = (GameObject)Instantiate(avatarResource); TraverseUserBoneTree(assetGameObject.transform); DestroyImmediate(assetGameObject); @@ -732,8 +766,8 @@ class AvatarExporter : MonoBehaviour { bool light = gameObject.GetComponent() != null; bool camera = gameObject.GetComponent() != null; - // if this is a mesh and the model is using external materials then store its material data to be exported - if (mesh && modelImporter.materialLocation == ModelImporterMaterialLocation.External) { + // if this is a mesh then store its material data to be exported if the material is mapped to an fbx material name + if (mesh) { Material[] materials = skinnedMeshRenderer != null ? skinnedMeshRenderer.sharedMaterials : meshRenderer.sharedMaterials; StoreMaterialData(materials); } else if (!light && !camera) { @@ -959,7 +993,8 @@ class AvatarExporter : MonoBehaviour { string userBoneName = ""; // avatar rule fails if bone is not mapped in Humanoid if (!humanoidToUserBoneMappings.TryGetValue(humanBoneName, out userBoneName)) { - failedAvatarRules.Add(avatarRule, "There is no " + humanBoneName + " bone mapped in Humanoid for the selected avatar."); + failedAvatarRules.Add(avatarRule, "There is no " + humanBoneName + + " bone mapped in Humanoid for the selected avatar."); } return userBoneName; } @@ -1072,11 +1107,11 @@ class AvatarExporter : MonoBehaviour { // don't store any material data for unsupported shader types if (Array.IndexOf(SUPPORTED_SHADERS, shaderName) == -1) { - if (!materialUnsupportedShader.ContainsKey(materialName)) { - materialUnsupportedShader.Add(materialName, shaderName); + if (!unsupportedShaderMaterials.Contains(materialName)) { + unsupportedShaderMaterials.Add(materialName); } continue; - } + } MaterialData materialData = new MaterialData(); materialData.albedo = material.GetColor("_Color"); @@ -1100,18 +1135,19 @@ class AvatarExporter : MonoBehaviour { // for non-roughness Standard shaders give a warning that is not the recommended Standard shader, // and invert smoothness for roughness if (shaderName == STANDARD_SHADER || shaderName == STANDARD_SPECULAR_SHADER) { - if (!materialAlternateStandardShader.Contains(materialName)) { - materialAlternateStandardShader.Add(materialName); + if (!alternateStandardShaderMaterials.Contains(materialName)) { + alternateStandardShaderMaterials.Add(materialName); } materialData.roughness = 1.0f - materialData.roughness; } - - // remap the material name from the Unity material name to the fbx material name that it overrides - if (materialMappings.ContainsKey(materialName)) { - materialName = materialMappings[materialName]; - } - if (!materialDatas.ContainsKey(materialName)) { - materialDatas.Add(materialName, materialData); + + // store the material data under each fbx material name that it overrides from the material mapping + foreach (var materialMapping in materialMappings) { + string fbxMaterialName = materialMapping.Key; + string unityMaterialName = materialMapping.Value; + if (unityMaterialName == materialName && !materialDatas.ContainsKey(fbxMaterialName)) { + materialDatas.Add(fbxMaterialName, materialData); + } } } } @@ -1136,20 +1172,110 @@ class AvatarExporter : MonoBehaviour { static void SetMaterialMappings() { materialMappings.Clear(); - // store the mappings from fbx material name to the Unity material name overriding it using external fbx mapping + // store the mappings from fbx material name to the Unity Material name that overrides it using external fbx mapping var objectMap = modelImporter.GetExternalObjectMap(); foreach (var mapping in objectMap) { var material = mapping.Value as UnityEngine.Material; if (material != null) { - materialMappings.Add(material.name, mapping.Key.name); + materialMappings.Add(mapping.Key.name, material.name); } } } + + static void AddMaterialWarnings() { + string alternateStandardShaders = ""; + string unsupportedShaders = ""; + // combine all material names for each material warning into a comma-separated string + foreach (string materialName in alternateStandardShaderMaterials) { + if (!string.IsNullOrEmpty(alternateStandardShaders)) { + alternateStandardShaders += ", "; + } + alternateStandardShaders += materialName; + } + foreach (string materialName in unsupportedShaderMaterials) { + if (!string.IsNullOrEmpty(unsupportedShaders)) { + unsupportedShaders += ", "; + } + unsupportedShaders += materialName; + } + if (alternateStandardShaderMaterials.Count > 1) { + warnings += "The materials " + alternateStandardShaders + " are not using the " + + "recommended variation of the Standard shader. We recommend you change " + + "them to Standard (Roughness setup) shader for improved performance.\n\n"; + } else if (alternateStandardShaderMaterials.Count == 1) { + warnings += "The material " + alternateStandardShaders + " is not using the " + + "recommended variation of the Standard shader. We recommend you change " + + "it to Standard (Roughness setup) shader for improved performance.\n\n"; + } + if (unsupportedShaderMaterials.Count > 1) { + warnings += "The materials " + unsupportedShaders + " are using an unsupported shader. " + + "Please change them to a Standard shader type.\n\n"; + } else if (unsupportedShaderMaterials.Count == 1) { + warnings += "The material " + unsupportedShaders + " is using an unsupported shader. " + + "Please change it to a Standard shader type.\n\n"; + } + } + + static bool OpenPreviewScene() { + // see if the user wants to save their current scene before opening preview avatar scene in place of user's scene + if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) { + return false; + } + + // store the user's current scene to re-open when done and open a new default scene in place of the user's scene + previousScene = EditorSceneManager.GetActiveScene().path; + previewScene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene); + + // instantiate a game object to preview the avatar and a game object for the height reference prefab at 0, 0, 0 + UnityEngine.Object heightReferenceResource = AssetDatabase.LoadAssetAtPath(HEIGHT_REFERENCE_PREFAB, typeof(UnityEngine.Object)); + avatarPreviewObject = (GameObject)Instantiate(avatarResource, Vector3.zero, Quaternion.identity); + heightReferenceObject = (GameObject)Instantiate(heightReferenceResource, Vector3.zero, Quaternion.identity); + + // store the camera pivot and rotation from the user's last scene to be restored later + // replace the camera pivot and rotation to point at the preview avatar object in the -Z direction (facing front of it) + var sceneView = SceneView.lastActiveSceneView; + if (sceneView != null) { + previousScenePivot = sceneView.pivot; + previousSceneRotation = sceneView.rotation; + previousSceneSize = sceneView.size; + previousSceneOrthographic = sceneView.orthographic; + sceneView.pivot = PREVIEW_CAMERA_PIVOT; + sceneView.rotation = Quaternion.LookRotation(PREVIEW_CAMERA_DIRECTION); + sceneView.orthographic = true; + sceneView.size = 5.0f; + } + + return true; + } + + static void ClosePreviewScene() { + // destroy the avatar and height reference game objects closing the scene + DestroyImmediate(avatarPreviewObject); + DestroyImmediate(heightReferenceObject); + + // re-open the scene the user had open before switching to the preview scene + if (!string.IsNullOrEmpty(previousScene)) { + EditorSceneManager.OpenScene(previousScene); + } + + // close the preview scene and flag it to be removed + EditorSceneManager.CloseScene(previewScene, true); + + // restore the camera pivot and rotation to the user's previous scene settings + var sceneView = SceneView.lastActiveSceneView; + if (sceneView != null) { + sceneView.pivot = previousScenePivot; + sceneView.rotation = previousSceneRotation; + sceneView.size = previousSceneSize; + sceneView.orthographic = previousSceneOrthographic; + } + } } class ExportProjectWindow : EditorWindow { const int WINDOW_WIDTH = 500; - const int WINDOW_HEIGHT = 460; + const int EXPORT_NEW_WINDOW_HEIGHT = 520; + const int UPDATE_EXISTING_WINDOW_HEIGHT = 465; const int BUTTON_FONT_SIZE = 16; const int LABEL_FONT_SIZE = 16; const int TEXT_FIELD_FONT_SIZE = 14; @@ -1157,28 +1283,62 @@ class ExportProjectWindow : EditorWindow { const int ERROR_FONT_SIZE = 12; const int WARNING_SCROLL_HEIGHT = 170; const string EMPTY_ERROR_TEXT = "None\n"; - + const int SLIDER_WIDTH = 340; + const int SCALE_TEXT_WIDTH = 60; + const float MIN_SCALE_SLIDER = 0.0f; + const float MAX_SCALE_SLIDER = 2.0f; + const int SLIDER_SCALE_EXPONENT = 10; + const float ACTUAL_SCALE_OFFSET = 1.0f; + const float DEFAULT_AVATAR_HEIGHT = 1.755f; + const float MAXIMUM_RECOMMENDED_HEIGHT = DEFAULT_AVATAR_HEIGHT * 1.5f; + const float MINIMUM_RECOMMENDED_HEIGHT = DEFAULT_AVATAR_HEIGHT * 0.25f; + readonly Color COLOR_YELLOW = Color.yellow; //new Color(0.9176f, 0.8274f, 0.0f); + readonly Color COLOR_BACKGROUND = new Color(0.5f, 0.5f, 0.5f); + + GameObject avatarPreviewObject; + bool updateExistingAvatar = false; string projectName = ""; string projectLocation = ""; + string initialProjectLocation = ""; string projectDirectory = ""; string errorText = EMPTY_ERROR_TEXT; - string warningText = ""; + string warningText = "\n"; Vector2 warningScrollPosition = new Vector2(0, 0); + string scaleWarningText = ""; + float sliderScale = 0.30103f; - public delegate void OnCloseDelegate(string projectDirectory, string projectName, string warnings); + public delegate void OnExportDelegate(string projectDirectory, string projectName, float scale); + OnExportDelegate onExportCallback; + + public delegate void OnCloseDelegate(); OnCloseDelegate onCloseCallback; - public void Init(string initialPath, string warnings, OnCloseDelegate closeCallback) { - minSize = new Vector2(WINDOW_WIDTH, WINDOW_HEIGHT); - maxSize = new Vector2(WINDOW_WIDTH, WINDOW_HEIGHT); - titleContent.text = "Export New Avatar"; - projectLocation = initialPath; + public void Init(string initialPath, string warnings, bool updateExisting, GameObject avatarObject, + OnExportDelegate exportCallback, OnCloseDelegate closeCallback) { + updateExistingAvatar = updateExisting; + float windowHeight = updateExistingAvatar ? UPDATE_EXISTING_WINDOW_HEIGHT : EXPORT_NEW_WINDOW_HEIGHT; + minSize = new Vector2(WINDOW_WIDTH, windowHeight); + maxSize = new Vector2(WINDOW_WIDTH, windowHeight); + avatarPreviewObject = avatarObject; + titleContent.text = updateExistingAvatar ? "Update Existing Avatar" : "Export New Avatar"; + initialProjectLocation = initialPath; + projectLocation = updateExistingAvatar ? "" : initialProjectLocation; warningText = warnings; + onExportCallback = exportCallback; onCloseCallback = closeCallback; + ShowUtility(); + + // if the avatar's starting height is outside of the recommended ranges, auto-adjust the scale to default height + float height = GetAvatarHeight(); + if (height < MINIMUM_RECOMMENDED_HEIGHT || height > MAXIMUM_RECOMMENDED_HEIGHT) { + float newScale = DEFAULT_AVATAR_HEIGHT / height; + SetAvatarScale(newScale); + scaleWarningText = "Avatar's scale automatically adjusted to be within the recommended range."; + } } - void OnGUI() { + void OnGUI() { // define UI styles for all GUI elements to be created GUIStyle buttonStyle = new GUIStyle(GUI.skin.button); buttonStyle.fontSize = BUTTON_FONT_SIZE; @@ -1192,35 +1352,82 @@ class ExportProjectWindow : EditorWindow { errorStyle.normal.textColor = Color.red; errorStyle.wordWrap = true; GUIStyle warningStyle = new GUIStyle(errorStyle); - warningStyle.normal.textColor = Color.yellow; + warningStyle.normal.textColor = COLOR_YELLOW; + GUIStyle sliderStyle = new GUIStyle(GUI.skin.horizontalSlider); + sliderStyle.fixedWidth = SLIDER_WIDTH; + GUIStyle sliderThumbStyle = new GUIStyle(GUI.skin.horizontalSliderThumb); + + // set the background for the window to a darker gray + Texture2D backgroundTexture = new Texture2D(1, 1, TextureFormat.RGBA32, false); + backgroundTexture.SetPixel(0, 0, COLOR_BACKGROUND); + backgroundTexture.Apply(); + GUI.DrawTexture(new Rect(0, 0, maxSize.x, maxSize.y), backgroundTexture, ScaleMode.StretchToFill); GUILayout.Space(10); - // Project name label and input text field - GUILayout.Label("Export project name:", labelStyle); - projectName = GUILayout.TextField(projectName, textStyle); + if (updateExistingAvatar) { + // Project file to update label and input text field + GUILayout.Label("Project file to update:", labelStyle); + projectLocation = GUILayout.TextField(projectLocation, textStyle); + } else { + // Project name label and input text field + GUILayout.Label("Export project name:", labelStyle); + projectName = GUILayout.TextField(projectName, textStyle); + + GUILayout.Space(10); + + // Project location label and input text field + GUILayout.Label("Export project location:", labelStyle); + projectLocation = GUILayout.TextField(projectLocation, textStyle); + } - GUILayout.Space(10); - - // Project location label and input text field - GUILayout.Label("Export project location:", labelStyle); - projectLocation = GUILayout.TextField(projectLocation, textStyle); - - // Browse button to open folder explorer that starts at project location path and then updates project location + // Browse button to open file/folder explorer and set project location if (GUILayout.Button("Browse", buttonStyle)) { - string result = EditorUtility.OpenFolderPanel("Select export location", projectLocation, ""); - if (result.Length > 0) { // folder selection not cancelled + string result = ""; + if (updateExistingAvatar) { + // open file explorer starting at hifi projects folder in user documents and select target fst to update + string initialPath = string.IsNullOrEmpty(projectLocation) ? initialProjectLocation : projectLocation; + result = EditorUtility.OpenFilePanel("Select .fst to update", initialPath, "fst"); + } else { + // open folder explorer starting at project location path and select folder to create project folder in + result = EditorUtility.OpenFolderPanel("Select export location", projectLocation, ""); + } + if (!string.IsNullOrEmpty(result)) { // file/folder selection not cancelled projectLocation = result.Replace('/', '\\'); } } - // Red error label text to display any file-related errors + // warning if scale is above/below recommended range or if scale was auto-adjusted initially + GUILayout.Label(scaleWarningText, warningStyle); + + // from left to right show scale label, scale slider itself, and scale value input with % value + // slider value itself is from 0.0 to 2.0, and actual scale is an exponent of it with an offset of 1 + // displayed scale is the actual scale value with 2 decimal places, and changing the displayed + // scale via keyboard does the inverse calculation to get the slider value via logarithm + GUILayout.BeginHorizontal(); + GUILayout.Label("Scale:", labelStyle); + sliderScale = GUILayout.HorizontalSlider(sliderScale, MIN_SCALE_SLIDER, MAX_SCALE_SLIDER, sliderStyle, sliderThumbStyle); + float actualScale = (Mathf.Pow(SLIDER_SCALE_EXPONENT, sliderScale) - ACTUAL_SCALE_OFFSET); + GUIStyle scaleInputStyle = new GUIStyle(textStyle); + scaleInputStyle.fixedWidth = SCALE_TEXT_WIDTH; + actualScale *= 100.0f; // convert to 100-based percentage for display purposes + string actualScaleStr = GUILayout.TextField(String.Format("{0:0.00}", actualScale), scaleInputStyle); + actualScaleStr = Regex.Replace(actualScaleStr, @"[^0-9.]", ""); + actualScale = float.Parse(actualScaleStr); + actualScale /= 100.0f; // convert back to 1.0-based percentage + SetAvatarScale(actualScale); + GUILayout.Label("%", labelStyle); + GUILayout.EndHorizontal(); + + GUILayout.Space(15); + + // red error label text to display any file-related errors GUILayout.Label("Error:", errorStyle); GUILayout.Label(errorText, errorStyle); GUILayout.Space(10); - // Yellow warning label text to display scrollable list of any bone-related warnings + // yellow warning label text to display scrollable list of any bone-related warnings GUILayout.Label("Warnings:", warningStyle); warningScrollPosition = GUILayout.BeginScrollView(warningScrollPosition, GUILayout.Width(WINDOW_WIDTH), GUILayout.Height(WARNING_SCROLL_HEIGHT)); @@ -1229,64 +1436,122 @@ class ExportProjectWindow : EditorWindow { GUILayout.Space(10); - // Export button which will verify project folder can actually be created + // export button will verify target project folder can actually be created (or target fst file is valid) // before closing popup window and calling back to initiate the export bool export = false; if (GUILayout.Button("Export", buttonStyle)) { export = true; if (!CheckForErrors(true)) { Close(); - onCloseCallback(projectDirectory, projectName, warningText); + onExportCallback(updateExistingAvatar ? projectLocation : projectDirectory, projectName, actualScale); } } - // Cancel button just closes the popup window without callback + // cancel button closes the popup window triggering the close callback to close the preview scene if (GUILayout.Button("Cancel", buttonStyle)) { Close(); } - // When either text field changes check for any errors if we didn't just check errors from clicking Export above + // when any value changes check for any errors and update scale warning if we are not exporting if (GUI.changed && !export) { CheckForErrors(false); + UpdateScaleWarning(); } } bool CheckForErrors(bool exporting) { errorText = EMPTY_ERROR_TEXT; // default to None if no errors found - projectDirectory = projectLocation + "\\" + projectName + "\\"; - if (projectName.Length > 0) { - // new project must have a unique folder name since the folder will be created for it - if (Directory.Exists(projectDirectory)) { - errorText = "A folder with the name " + projectName + - " already exists at that location.\nPlease choose a different project name or location."; + if (updateExistingAvatar) { + // if any text is set in the project file to update field verify that the file actually exists + if (projectLocation.Length > 0) { + if (!File.Exists(projectLocation)) { + errorText = "Please select a valid project file to update.\n"; + return true; + } + } else if (exporting) { + errorText = "Please select a project file to update.\n"; return true; } - } - if (projectLocation.Length > 0) { - // before clicking Export we can verify that the project location at least starts with a drive - if (!Char.IsLetter(projectLocation[0]) || projectLocation.Length == 1 || projectLocation[1] != ':') { - errorText = "Project location is invalid. Please choose a different project location.\n"; - return true; + } else { + projectDirectory = projectLocation + "\\" + projectName + "\\"; + if (projectName.Length > 0) { + // new project must have a unique folder name since the folder will be created for it + if (Directory.Exists(projectDirectory)) { + errorText = "A folder with the name " + projectName + + " already exists at that location.\nPlease choose a different project name or location."; + return true; + } } - } - if (exporting) { - // when exporting, project name and location must both be defined, and project location must - // be valid and accessible (we attempt to create the project folder at this time to verify this) - if (projectName.Length == 0) { - errorText = "Please define a project name.\n"; - return true; - } else if (projectLocation.Length == 0) { - errorText = "Please define a project location.\n"; - return true; - } else { - try { - Directory.CreateDirectory(projectDirectory); - } catch { + if (projectLocation.Length > 0) { + // before clicking Export we can verify that the project location at least starts with a drive + if (!Char.IsLetter(projectLocation[0]) || projectLocation.Length == 1 || projectLocation[1] != ':') { errorText = "Project location is invalid. Please choose a different project location.\n"; return true; } } - } + if (exporting) { + // when exporting, project name and location must both be defined, and project location must + // be valid and accessible (we attempt to create the project folder at this time to verify this) + if (projectName.Length == 0) { + errorText = "Please define a project name.\n"; + return true; + } else if (projectLocation.Length == 0) { + errorText = "Please define a project location.\n"; + return true; + } else { + try { + Directory.CreateDirectory(projectDirectory); + } catch { + errorText = "Project location is invalid. Please choose a different project location.\n"; + return true; + } + } + } + } + return false; } + + void UpdateScaleWarning() { + // called on any input changes + float height = GetAvatarHeight(); + if (height < MINIMUM_RECOMMENDED_HEIGHT) { + scaleWarningText = "The height of the avatar is below the recommended minimum."; + } else if (height > MAXIMUM_RECOMMENDED_HEIGHT) { + scaleWarningText = "The height of the avatar is above the recommended maximum."; + } else { + scaleWarningText = ""; + } + } + + float GetAvatarHeight() { + // height of an avatar model can be determined to be the max Y extents of the combined bounds for all its mesh renderers + Bounds bounds = new Bounds(); + var meshRenderers = avatarPreviewObject.GetComponentsInChildren(); + var skinnedMeshRenderers = avatarPreviewObject.GetComponentsInChildren(); + foreach (var renderer in meshRenderers) { + bounds.Encapsulate(renderer.bounds); + } + foreach (var renderer in skinnedMeshRenderers) { + bounds.Encapsulate(renderer.bounds); + } + return bounds.max.y; + } + + void SetAvatarScale(float actualScale) { + // set the new scale uniformly on the preview avatar's transform to show the resulting avatar size + avatarPreviewObject.transform.localScale = new Vector3(actualScale, actualScale, actualScale); + + // adjust slider scale value to match the new actual scale value + sliderScale = GetSliderScaleFromActualScale(actualScale); + } + + float GetSliderScaleFromActualScale(float actualScale) { + // since actual scale is an exponent of slider scale with an offset, do the logarithm operation to convert it back + return Mathf.Log(actualScale + ACTUAL_SCALE_OFFSET, SLIDER_SCALE_EXPONENT); + } + + void OnDestroy() { + onCloseCallback(); + } } diff --git a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/Average.mat b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/Average.mat new file mode 100644 index 0000000000..69421ca8e2 --- /dev/null +++ b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/Average.mat @@ -0,0 +1,76 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: Average + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.53309965, g: 0.8773585, b: 0.27727836, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/Floor.mat b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/Floor.mat new file mode 100644 index 0000000000..4c63832593 --- /dev/null +++ b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/Floor.mat @@ -0,0 +1,76 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: Floor + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/HeightReference.prefab b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/HeightReference.prefab new file mode 100644 index 0000000000..3a6b6b21fa --- /dev/null +++ b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/HeightReference.prefab @@ -0,0 +1,1393 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 0} + m_RootGameObject: {fileID: 1663253797283788} + m_IsPrefabAsset: 1 +--- !u!1 &1046656866020106 +GameObject: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 224386929081752724} + - component: {fileID: 222160789105267064} + - component: {fileID: 114930405832365464} + m_Layer: 5 + m_Name: TwoAndHalfMText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1098451480288840 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4735851023856772} + - component: {fileID: 33008877752475126} + - component: {fileID: 23983268565997994} + m_Layer: 0 + m_Name: HalfMLine + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1107359137501064 +GameObject: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 224352215517075892} + - component: {fileID: 222924084127982026} + - component: {fileID: 114523909969846714} + m_Layer: 5 + m_Name: TwoMText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1108041172082256 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 224494569551489322} + - component: {fileID: 223961774962398002} + - component: {fileID: 114011556853048752} + - component: {fileID: 114521005238033952} + m_Layer: 5 + m_Name: Canvas + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1165326825168616 +GameObject: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 224593141416602104} + - component: {fileID: 222331762946337184} + - component: {fileID: 114101794169638918} + m_Layer: 5 + m_Name: OneAndHalfMText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1182485492886750 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4302978871272126} + - component: {fileID: 33686989621546016} + - component: {fileID: 23982106336197490} + m_Layer: 0 + m_Name: TwoAndHalfMLine + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1365616260555366 +GameObject: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 224613908675679132} + - component: {fileID: 222421911825862480} + - component: {fileID: 114276838631099888} + m_Layer: 5 + m_Name: OneMText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1398639835840810 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4460037940915778} + - component: {fileID: 33999849812690240} + - component: {fileID: 23416265009837404} + m_Layer: 0 + m_Name: Floor + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1534720920953066 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4413776654278098} + - component: {fileID: 33291071156168694} + - component: {fileID: 23550720950256080} + m_Layer: 0 + m_Name: Average + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1594624973687270 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4908828994703896} + - component: {fileID: 33726300519449444} + - component: {fileID: 23824769923661608} + m_Layer: 0 + m_Name: Tall + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1663253797283788 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4466308008297536} + m_Layer: 0 + m_Name: HeightReference + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1684603522306818 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4359301733271006} + - component: {fileID: 33170278100239952} + - component: {fileID: 23463284742561382} + m_Layer: 0 + m_Name: TwoMLine + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1758516477546936 +GameObject: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 224093314116541246} + - component: {fileID: 222104353024021134} + - component: {fileID: 114198955202599194} + m_Layer: 5 + m_Name: HalfMText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1843086377652878 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4967607462495426} + - component: {fileID: 33458427168817864} + - component: {fileID: 23807848267690204} + m_Layer: 0 + m_Name: Short + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1845490813592506 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4990347338131576} + - component: {fileID: 108630196659418708} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1883639722740524 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4177433262325602} + - component: {fileID: 33418961761515394} + - component: {fileID: 23536779434871182} + m_Layer: 0 + m_Name: TooShort + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1885741171197356 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4718462335765420} + - component: {fileID: 33030310456480364} + - component: {fileID: 23105277758912132} + m_Layer: 0 + m_Name: TooTall + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1919147340747728 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4440944676647488} + - component: {fileID: 33820823812379558} + - component: {fileID: 23886085173153614} + m_Layer: 0 + m_Name: OneAndHalfMLine + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1985295559338180 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4498194399146796} + - component: {fileID: 33041053251399642} + - component: {fileID: 23936786851965954} + m_Layer: 0 + m_Name: OneMLine + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4177433262325602 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1883639722740524} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.219375, z: -1} + m_LocalScale: {x: 200, y: 0.43875, z: 1} + m_Children: [] + m_Father: {fileID: 4466308008297536} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4302978871272126 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1182485492886750} + m_LocalRotation: {x: 0.7071068, y: -0, z: -0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 2.5, z: -0.94} + m_LocalScale: {x: 200, y: 1.0000005, z: 0.0100000035} + m_Children: [] + m_Father: {fileID: 4466308008297536} + m_RootOrder: 12 + m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} +--- !u!4 &4359301733271006 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1684603522306818} + m_LocalRotation: {x: 0.7071068, y: -0, z: -0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 2, z: -0.94} + m_LocalScale: {x: 200, y: 1.0000005, z: 0.0100000035} + m_Children: [] + m_Father: {fileID: 4466308008297536} + m_RootOrder: 11 + m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} +--- !u!4 &4413776654278098 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1534720920953066} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 1.535625, z: -1} + m_LocalScale: {x: 200, y: 1.19375, z: 1} + m_Children: [] + m_Father: {fileID: 4466308008297536} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4440944676647488 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1919147340747728} + m_LocalRotation: {x: 0.7071068, y: -0, z: -0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 1.5, z: -0.94} + m_LocalScale: {x: 200, y: 1.0000005, z: 0.0100000035} + m_Children: [] + m_Father: {fileID: 4466308008297536} + m_RootOrder: 10 + m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} +--- !u!4 &4460037940915778 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1398639835840810} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: -50, z: -0.5} + m_LocalScale: {x: 200, y: 100, z: 2} + m_Children: [] + m_Father: {fileID: 4466308008297536} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4466308008297536 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1663253797283788} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4990347338131576} + - {fileID: 4460037940915778} + - {fileID: 4177433262325602} + - {fileID: 4967607462495426} + - {fileID: 4413776654278098} + - {fileID: 4908828994703896} + - {fileID: 4718462335765420} + - {fileID: 224494569551489322} + - {fileID: 4735851023856772} + - {fileID: 4498194399146796} + - {fileID: 4440944676647488} + - {fileID: 4359301733271006} + - {fileID: 4302978871272126} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4498194399146796 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1985295559338180} + m_LocalRotation: {x: 0.7071068, y: -0, z: -0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 1, z: -0.94} + m_LocalScale: {x: 200, y: 1.0000005, z: 0.0100000035} + m_Children: [] + m_Father: {fileID: 4466308008297536} + m_RootOrder: 9 + m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} +--- !u!4 &4718462335765420 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1885741171197356} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 502.6325, z: -1} + m_LocalScale: {x: 200, y: 1000, z: 1} + m_Children: [] + m_Father: {fileID: 4466308008297536} + m_RootOrder: 6 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4735851023856772 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1098451480288840} + m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 0.5, z: -0.94} + m_LocalScale: {x: 200, y: 1, z: 0.01} + m_Children: [] + m_Father: {fileID: 4466308008297536} + m_RootOrder: 8 + m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} +--- !u!4 &4908828994703896 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1594624973687270} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 2.3825, z: -1} + m_LocalScale: {x: 200, y: 0.5, z: 1} + m_Children: [] + m_Father: {fileID: 4466308008297536} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4967607462495426 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1843086377652878} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.68875, z: -1} + m_LocalScale: {x: 200, y: 0.5, z: 1} + m_Children: [] + m_Father: {fileID: 4466308008297536} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4990347338131576 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1845490813592506} + m_LocalRotation: {x: -0.11086535, y: -0.8745676, z: 0.40781754, w: -0.23775047} + m_LocalPosition: {x: 0, y: 3, z: 77.17} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4466308008297536} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 50.000004, y: -210.41699, z: 0} +--- !u!23 &23105277758912132 +MeshRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1885741171197356} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_Materials: + - {fileID: 2100000, guid: d07e04b46b88ae54e9f418c8645f1580, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &23416265009837404 +MeshRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1398639835840810} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_Materials: + - {fileID: 2100000, guid: 320b570da434d374985fe89d653ae75b, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &23463284742561382 +MeshRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1684603522306818} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_Materials: + - {fileID: 2100000, guid: d1133891b03286946b3b0c63c1a57d08, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &23536779434871182 +MeshRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1883639722740524} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_Materials: + - {fileID: 2100000, guid: d07e04b46b88ae54e9f418c8645f1580, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &23550720950256080 +MeshRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1534720920953066} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_Materials: + - {fileID: 2100000, guid: 722779087c41d074eb632820263fc661, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &23807848267690204 +MeshRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1843086377652878} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_Materials: + - {fileID: 2100000, guid: 1cd16d030e4890a4cab22d897ccfc8d8, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &23824769923661608 +MeshRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1594624973687270} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_Materials: + - {fileID: 2100000, guid: 1cd16d030e4890a4cab22d897ccfc8d8, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &23886085173153614 +MeshRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1919147340747728} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_Materials: + - {fileID: 2100000, guid: d1133891b03286946b3b0c63c1a57d08, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &23936786851965954 +MeshRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1985295559338180} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_Materials: + - {fileID: 2100000, guid: d1133891b03286946b3b0c63c1a57d08, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &23982106336197490 +MeshRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1182485492886750} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_Materials: + - {fileID: 2100000, guid: d1133891b03286946b3b0c63c1a57d08, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &23983268565997994 +MeshRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1098451480288840} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RenderingLayerMask: 4294967295 + m_Materials: + - {fileID: 2100000, guid: d1133891b03286946b3b0c63c1a57d08, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &33008877752475126 +MeshFilter: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1098451480288840} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!33 &33030310456480364 +MeshFilter: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1885741171197356} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!33 &33041053251399642 +MeshFilter: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1985295559338180} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!33 &33170278100239952 +MeshFilter: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1684603522306818} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!33 &33291071156168694 +MeshFilter: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1534720920953066} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!33 &33418961761515394 +MeshFilter: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1883639722740524} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!33 &33458427168817864 +MeshFilter: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1843086377652878} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!33 &33686989621546016 +MeshFilter: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1182485492886750} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!33 &33726300519449444 +MeshFilter: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1594624973687270} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!33 &33820823812379558 +MeshFilter: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1919147340747728} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!33 &33999849812690240 +MeshFilter: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1398639835840810} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!108 &108630196659418708 +Light: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1845490813592506} + m_Enabled: 1 + serializedVersion: 8 + m_Type: 1 + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_Intensity: 2 + m_Range: 10 + m_SpotAngle: 30 + m_CookieSize: 10 + m_Shadows: + m_Type: 0 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_Lightmapping: 1 + m_LightShadowCasterMode: 0 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!114 &114011556853048752 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1108041172082256} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!114 &114101794169638918 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1165326825168616} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 128 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 256 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: '1.5m + +' +--- !u!114 &114198955202599194 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1758516477546936} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 128 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 256 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: 0.5m +--- !u!114 &114276838631099888 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1365616260555366} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 128 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 256 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: '1.0m + +' +--- !u!114 &114521005238033952 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1108041172082256} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &114523909969846714 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1107359137501064} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 128 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 256 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: '2.0m + +' +--- !u!114 &114930405832365464 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1046656866020106} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 128 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 0 + m_MaxSize: 256 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: '2.5m + +' +--- !u!222 &222104353024021134 +CanvasRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1758516477546936} + m_CullTransparentMesh: 0 +--- !u!222 &222160789105267064 +CanvasRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1046656866020106} + m_CullTransparentMesh: 0 +--- !u!222 &222331762946337184 +CanvasRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1165326825168616} + m_CullTransparentMesh: 0 +--- !u!222 &222421911825862480 +CanvasRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1365616260555366} + m_CullTransparentMesh: 0 +--- !u!222 &222924084127982026 +CanvasRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1107359137501064} + m_CullTransparentMesh: 0 +--- !u!223 &223961774962398002 +Canvas: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1108041172082256} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 2 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &224093314116541246 +RectTransform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1758516477546936} + m_LocalRotation: {x: 0, y: 1, z: 0, w: 0} + m_LocalPosition: {x: 0, y: 0, z: -0.395} + m_LocalScale: {x: 0.001, y: 0.001, z: 0.001} + m_Children: [] + m_Father: {fileID: 224494569551489322} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -2, y: 0.55} + m_SizeDelta: {x: 300, y: 200} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!224 &224352215517075892 +RectTransform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1107359137501064} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: 0, y: 0, z: -0.395} + m_LocalScale: {x: 0.0009999999, y: 0.0009999999, z: 0.0009999999} + m_Children: [] + m_Father: {fileID: 224494569551489322} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -2, y: 2.05} + m_SizeDelta: {x: 300, y: 200} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!224 &224386929081752724 +RectTransform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1046656866020106} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: 0, y: 0, z: -0.395} + m_LocalScale: {x: 0.0009999999, y: 0.0009999999, z: 0.0009999999} + m_Children: [] + m_Father: {fileID: 224494569551489322} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -2, y: 2.55} + m_SizeDelta: {x: 300, y: 200} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!224 &224494569551489322 +RectTransform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1108041172082256} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 224093314116541246} + - {fileID: 224613908675679132} + - {fileID: 224593141416602104} + - {fileID: 224352215517075892} + - {fileID: 224386929081752724} + m_Father: {fileID: 4466308008297536} + m_RootOrder: 7 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 1000, y: 1000} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!224 &224593141416602104 +RectTransform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1165326825168616} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: 0, y: 0, z: -0.395} + m_LocalScale: {x: 0.0009999999, y: 0.0009999999, z: 0.0009999999} + m_Children: [] + m_Father: {fileID: 224494569551489322} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -2, y: 1.55} + m_SizeDelta: {x: 300, y: 200} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!224 &224613908675679132 +RectTransform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1365616260555366} + m_LocalRotation: {x: -0, y: 1, z: -0, w: 0} + m_LocalPosition: {x: 0, y: 0, z: -0.395} + m_LocalScale: {x: 0.0009999999, y: 0.0009999999, z: 0.0009999999} + m_Children: [] + m_Father: {fileID: 224494569551489322} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -2, y: 1.05} + m_SizeDelta: {x: 300, y: 200} + m_Pivot: {x: 0.5, y: 0.5} diff --git a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/Line.mat b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/Line.mat new file mode 100644 index 0000000000..2f9a048c63 --- /dev/null +++ b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/Line.mat @@ -0,0 +1,76 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: Line + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0, g: 0, b: 0, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/ShortOrTall.mat b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/ShortOrTall.mat new file mode 100644 index 0000000000..5543fef85e --- /dev/null +++ b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/ShortOrTall.mat @@ -0,0 +1,76 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: ShortOrTall + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.91758025, g: 0.9622642, b: 0.28595585, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/TooShortOrTall.mat b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/TooShortOrTall.mat new file mode 100644 index 0000000000..4851a64056 --- /dev/null +++ b/tools/unity-avatar-exporter/Assets/Editor/AvatarExporter/TooShortOrTall.mat @@ -0,0 +1,76 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: TooShortOrTall + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.9056604, g: 0.19223925, b: 0.19223925, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/tools/unity-avatar-exporter/Assets/README.txt b/tools/unity-avatar-exporter/Assets/README.txt index 402719b497..767c093800 100644 --- a/tools/unity-avatar-exporter/Assets/README.txt +++ b/tools/unity-avatar-exporter/Assets/README.txt @@ -1,6 +1,6 @@ High Fidelity, Inc. Avatar Exporter -Version 0.3.3 +Version 0.3.5 Note: It is recommended to use Unity versions between 2017.4.17f1 and 2018.2.12f1 for this Avatar Exporter. @@ -9,15 +9,16 @@ To create a new avatar project: 2. Select the .fbx avatar that you imported in step 1 in the Assets window, and in the Rig section of the Inspector window set the Animation Type to Humanoid and choose Apply. 3. With the .fbx avatar still selected in the Assets window, choose High Fidelity menu > Export New Avatar. 4. Select a name for your avatar project (this will be used to create a directory with that name), as well as the target location for your project folder. -5. Once it is exported, your project directory will open in File Explorer. +5. If necessary, adjust the scale for your avatar so that it's height is within the recommended range. +6. Once it is exported, you will receive a successfully exported dialog with any warnings, and your project directory will open in File Explorer. To update an existing avatar project: -1. Select the existing .fbx avatar in the Assets window that you would like to re-export. -2. Choose High Fidelity menu > Update Existing Avatar and browse to the .fst file you would like to update. +1. Select the existing .fbx avatar in the Assets window that you would like to re-export and choose High Fidelity menu > Update Existing Avatar +2. Select the .fst project file that you wish to update. 3. If the .fbx file in your Unity Assets folder is newer than the existing .fbx file in your selected avatar project or vice-versa, you will be prompted if you wish to replace the older file with the newer file before performing the update. -4. Once it is updated, your project directory will open in File Explorer. +4. Once it is updated, you will receive a successfully exported dialog with any warnings, and your project directory will open in File Explorer. * WARNING * If you are using any external textures as part of your .fbx model, be sure they are copied into the textures folder that is created in the project folder after exporting a new avatar. -For further details including troubleshooting tips, see the full documentation at https://docs.highfidelity.com/create-and-explore/avatars/create-avatars/unity-extension +For further details including troubleshooting tips, see the full documentation at https://docs.highfidelity.com/create-and-explore/avatars/create-avatars/unity-extension \ No newline at end of file diff --git a/tools/unity-avatar-exporter/avatarExporter.unitypackage b/tools/unity-avatar-exporter/avatarExporter.unitypackage index f7385e3831..ee3f6abe01 100644 Binary files a/tools/unity-avatar-exporter/avatarExporter.unitypackage and b/tools/unity-avatar-exporter/avatarExporter.unitypackage differ