🔧 Updated AvatarExporter to work with newer Unity versions

This commit is contained in:
Edgar 2023-08-10 10:55:06 +02:00
parent c28208dfa3
commit c1101e1b8b
No known key found for this signature in database
GPG key ID: 9AA5DDFFCBDCE46A
15 changed files with 1369 additions and 1204 deletions

View file

@ -1,4 +1,4 @@
// AvatarExporter.cs // AvatarExporter.cs
// //
// Created by David Back on 28 Nov 2018 // Created by David Back on 28 Nov 2018
// Copyright 2018 High Fidelity, Inc. // Copyright 2018 High Fidelity, Inc.
@ -6,21 +6,20 @@
// //
// Distributed under the Apache License, Version 2.0. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#if UNITY_EDITOR
using UnityEditor; using UnityEditor;
using UnityEditor.SceneManagement; using UnityEditor.SceneManagement;
using UnityEngine; using UnityEngine;
using UnityEngine.SceneManagement;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text.RegularExpressions; using System.Globalization;
class AvatarExporter : MonoBehaviour class AvatarExporter : MonoBehaviour
{ {
// update version number for every PR that changes this file, also set updated version in README file // update version number for every PR that changes this file, also set updated version in README file
static readonly string AVATAR_EXPORTER_VERSION = "0.5.0"; static readonly string AVATAR_EXPORTER_VERSION = "0.6.0";
static readonly float HIPS_MIN_Y_PERCENT_OF_HEIGHT = 0.03f; static readonly float HIPS_MIN_Y_PERCENT_OF_HEIGHT = 0.03f;
static readonly float BELOW_GROUND_THRESHOLD_PERCENT_OF_HEIGHT = -0.15f; static readonly float BELOW_GROUND_THRESHOLD_PERCENT_OF_HEIGHT = -0.15f;
@ -35,33 +34,8 @@ class AvatarExporter : MonoBehaviour
// TODO: use regex // TODO: use regex
static readonly string[] RECOMMENDED_UNITY_VERSIONS = new string[] { static readonly string[] RECOMMENDED_UNITY_VERSIONS = new string[] {
"2018.2.12f1", "2019.4.31f1", //Version currently used by VRChat
"2018.2.11f1", "2021.3.23f1" //Version currently used by ChilloutVR
"2018.2.10f1",
"2018.2.9f1",
"2018.2.8f1",
"2018.2.7f1",
"2018.2.6f1",
"2018.2.5f1",
"2018.2.4f1",
"2018.2.3f1",
"2018.2.2f1",
"2018.2.1f1",
"2018.2.0f2",
"2018.1.9f2",
"2018.1.8f1",
"2018.1.7f1",
"2018.1.6f1",
"2018.1.5f1",
"2018.1.4f1",
"2018.1.3f1",
"2018.1.2f1",
"2018.1.1f1",
"2018.1.0f2",
"2017.4.18f1",
"2017.4.17f1",
"2017.4.16f1",
"2017.4.15f1",
}; };
static readonly Dictionary<string, string> HUMANOID_TO_OVERTE_JOINT_NAME = new Dictionary<string, string> { static readonly Dictionary<string, string> HUMANOID_TO_OVERTE_JOINT_NAME = new Dictionary<string, string> {
@ -211,11 +185,9 @@ class AvatarExporter : MonoBehaviour
}; };
static readonly string STANDARD_SHADER = "Standard"; static readonly string STANDARD_SHADER = "Standard";
static readonly string STANDARD_ROUGHNESS_SHADER = "Standard (Roughness setup)";
static readonly string STANDARD_SPECULAR_SHADER = "Standard (Specular setup)"; static readonly string STANDARD_SPECULAR_SHADER = "Standard (Specular setup)";
static readonly string[] SUPPORTED_SHADERS = new string[] { static readonly string[] SUPPORTED_SHADERS = new string[] {
STANDARD_SHADER, STANDARD_SHADER,
STANDARD_ROUGHNESS_SHADER,
STANDARD_SPECULAR_SHADER, STANDARD_SPECULAR_SHADER,
}; };
@ -728,9 +700,13 @@ class AvatarExporter : MonoBehaviour
// write out core fields to top of fst file // write out core fields to top of fst file
try try
{ {
File.WriteAllText(exportFstPath, "exporterVersion = " + AVATAR_EXPORTER_VERSION + "\nname = " + projectName + File.WriteAllText(exportFstPath,
"\ntype = body+head\nscale = " + scale + "\nfilename = " + assetName + $"exporterVersion = {AVATAR_EXPORTER_VERSION}\n" +
".fbx\n" + "texdir = textures\n"); $"name = {projectName}\n" +
"type = body+head\n" +
$"scale = {scale.F()}\n" +
$"filename = {assetName}.fbx\n" +
"texdir = textures\n");
} }
catch catch
{ {
@ -745,7 +721,7 @@ class AvatarExporter : MonoBehaviour
if (userBoneInfo.Value.HasHumanMapping()) if (userBoneInfo.Value.HasHumanMapping())
{ {
string overteJointName = HUMANOID_TO_OVERTE_JOINT_NAME[userBoneInfo.Value.humanName]; string overteJointName = HUMANOID_TO_OVERTE_JOINT_NAME[userBoneInfo.Value.humanName];
File.AppendAllText(exportFstPath, "jointMap = " + overteJointName + " = " + removeTypeFromJointname(userBoneInfo.Key) + "\n"); File.AppendAllText(exportFstPath, $"jointMap = {overteJointName} = {removeTypeFromJointname(userBoneInfo.Key)}\n");
} }
} }
@ -795,8 +771,9 @@ class AvatarExporter : MonoBehaviour
// swap from left-handed (Unity) to right-handed (Overte) coordinates and write out joint rotation offset to fst // swap from left-handed (Unity) to right-handed (Overte) coordinates and write out joint rotation offset to fst
jointOffset = new Quaternion(-jointOffset.x, jointOffset.y, jointOffset.z, -jointOffset.w); jointOffset = new Quaternion(-jointOffset.x, jointOffset.y, jointOffset.z, -jointOffset.w);
File.AppendAllText(exportFstPath, "jointRotationOffset2 = " + removeTypeFromJointname(userBoneName) + " = (" + jointOffset.x + ", " + File.AppendAllText(exportFstPath,
jointOffset.y + ", " + jointOffset.z + ", " + jointOffset.w + ")\n"); $"jointRotationOffset2 = {removeTypeFromJointname(userBoneName)} = ({jointOffset.x.F()}, {jointOffset.y.F()}, {jointOffset.z.F()}, {jointOffset.w.F()})\n"
);
} }
// if there is any material data to save then write out all materials in JSON material format to the materialMap field // if there is any material data to save then write out all materials in JSON material format to the materialMap field
@ -824,11 +801,11 @@ class AvatarExporter : MonoBehaviour
File.AppendAllText(exportFstPath, "materialMap = " + materialJson); File.AppendAllText(exportFstPath, "materialMap = " + materialJson);
} }
if (SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows) /*if (SystemInfo.operatingSystemFamily == OperatingSystemFamily.Windows)
{ {
// open File Explorer to the project directory once finished // open File Explorer to the project directory once finished
System.Diagnostics.Process.Start("explorer.exe", "/select," + exportFstPath); System.Diagnostics.Process.Start("explorer.exe", "/select," + exportFstPath);
} }*/
return true; return true;
} }
@ -1021,10 +998,7 @@ class AvatarExporter : MonoBehaviour
case AvatarRule.RecommendedUnityVersion: case AvatarRule.RecommendedUnityVersion:
if (Array.IndexOf(RECOMMENDED_UNITY_VERSIONS, Application.unityVersion) == -1) if (Array.IndexOf(RECOMMENDED_UNITY_VERSIONS, Application.unityVersion) == -1)
{ {
failedAvatarRules.Add(avatarRule, "The current version of Unity is not one of the recommended Unity " + failedAvatarRules.Add(avatarRule, "The current version of Unity is not one of the recommended Unity versions.");
"versions. If you are using a version of Unity later than 2018.2.12f1, " +
"it is recommended to apply Enforce T-Pose under the Pose dropdown " +
"in Humanoid configuration.");
} }
break; break;
case AvatarRule.SingleRoot: case AvatarRule.SingleRoot:
@ -1738,8 +1712,7 @@ class ExportProjectWindow : EditorWindow
GUIStyle scaleInputStyle = new GUIStyle(textStyle); GUIStyle scaleInputStyle = new GUIStyle(textStyle);
scaleInputStyle.fixedWidth = SCALE_TEXT_WIDTH; scaleInputStyle.fixedWidth = SCALE_TEXT_WIDTH;
actualScale *= 100.0f; // convert to 100-based percentage for display purposes actualScale *= 100.0f; // convert to 100-based percentage for display purposes
string actualScaleStr = GUILayout.TextField(String.Format("{0:0.00}", actualScale), scaleInputStyle); string actualScaleStr = GUILayout.TextField($"{actualScale}", scaleInputStyle);
actualScaleStr = Regex.Replace(actualScaleStr, @"[^0-9.]", "");
actualScale = float.Parse(actualScaleStr); actualScale = float.Parse(actualScaleStr);
actualScale /= 100.0f; // convert back to 1.0-based percentage actualScale /= 100.0f; // convert back to 1.0-based percentage
SetAvatarScale(actualScale); SetAvatarScale(actualScale);
@ -1949,3 +1922,10 @@ class AvatarUtilities
return avatarBounds.max.y - avatarBounds.min.y; return avatarBounds.max.y - avatarBounds.min.y;
} }
} }
public static class ConverterExtensions
{
public static string F(this float x) => x.ToString("G", CultureInfo.InvariantCulture);
}
#endif

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e575c09e36785a9f39644b7b50ecdfcb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 60f00688eb8a9dd55b72d8a31d283a6b
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: be558e90af0d1a5409d6ea21baa98564
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -5,9 +5,10 @@ Material:
serializedVersion: 6 serializedVersion: 6
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Average m_Name: Average
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} m_Shader: {fileID: 10755, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords: m_ShaderKeywords:
m_LightmapFlags: 4 m_LightmapFlags: 4
m_EnableInstancingVariants: 0 m_EnableInstancingVariants: 0
@ -60,7 +61,7 @@ Material:
- _DetailNormalMapScale: 1 - _DetailNormalMapScale: 1
- _DstBlend: 0 - _DstBlend: 0
- _GlossMapScale: 1 - _GlossMapScale: 1
- _Glossiness: 0.5 - _Glossiness: 0
- _GlossyReflections: 1 - _GlossyReflections: 1
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 368c0c7376fcb82ebbd8e17fb78f1c5a
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -5,9 +5,10 @@ Material:
serializedVersion: 6 serializedVersion: 6
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Floor m_Name: Floor
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} m_Shader: {fileID: 10755, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords: m_ShaderKeywords:
m_LightmapFlags: 4 m_LightmapFlags: 4
m_EnableInstancingVariants: 0 m_EnableInstancingVariants: 0
@ -60,7 +61,7 @@ Material:
- _DetailNormalMapScale: 1 - _DetailNormalMapScale: 1
- _DstBlend: 0 - _DstBlend: 0
- _GlossMapScale: 1 - _GlossMapScale: 1
- _Glossiness: 0.5 - _Glossiness: 0
- _GlossyReflections: 1 - _GlossyReflections: 1
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 07fb3749e6aaf38278f894b2578a1e18
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -5,9 +5,10 @@ Material:
serializedVersion: 6 serializedVersion: 6
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Line m_Name: Line
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} m_Shader: {fileID: 10755, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords: m_ShaderKeywords:
m_LightmapFlags: 4 m_LightmapFlags: 4
m_EnableInstancingVariants: 0 m_EnableInstancingVariants: 0
@ -60,7 +61,7 @@ Material:
- _DetailNormalMapScale: 1 - _DetailNormalMapScale: 1
- _DstBlend: 0 - _DstBlend: 0
- _GlossMapScale: 1 - _GlossMapScale: 1
- _Glossiness: 0.5 - _Glossiness: 0
- _GlossyReflections: 1 - _GlossyReflections: 1
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c33b33e3c107f3ea1a85eddf1c8f1c75
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -5,9 +5,10 @@ Material:
serializedVersion: 6 serializedVersion: 6
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: ShortOrTall m_Name: ShortOrTall
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} m_Shader: {fileID: 10755, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords: m_ShaderKeywords:
m_LightmapFlags: 4 m_LightmapFlags: 4
m_EnableInstancingVariants: 0 m_EnableInstancingVariants: 0
@ -60,7 +61,7 @@ Material:
- _DetailNormalMapScale: 1 - _DetailNormalMapScale: 1
- _DstBlend: 0 - _DstBlend: 0
- _GlossMapScale: 1 - _GlossMapScale: 1
- _Glossiness: 0.5 - _Glossiness: 0
- _GlossyReflections: 1 - _GlossyReflections: 1
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 65b08c4f34a3221a695663ea1678966f
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -5,9 +5,10 @@ Material:
serializedVersion: 6 serializedVersion: 6
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInternal: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: TooShortOrTall m_Name: TooShortOrTall
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} m_Shader: {fileID: 10755, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords: m_ShaderKeywords:
m_LightmapFlags: 4 m_LightmapFlags: 4
m_EnableInstancingVariants: 0 m_EnableInstancingVariants: 0
@ -60,7 +61,7 @@ Material:
- _DetailNormalMapScale: 1 - _DetailNormalMapScale: 1
- _DstBlend: 0 - _DstBlend: 0
- _GlossMapScale: 1 - _GlossMapScale: 1
- _Glossiness: 0.5 - _Glossiness: 0
- _GlossyReflections: 1 - _GlossyReflections: 1
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 140bf42496a6f02fbabb80fe46b70e55
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant: