Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions Editor/Scripts/GLTFImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ private static void EnsureShadersAreLoaded()
[SerializeField] internal CameraImportOption _importCamera = CameraImportOption.ImportAndCameraDisabled;
[SerializeField] internal AnimationMethod _importAnimations = AnimationMethod.Mecanim;
[SerializeField] internal bool _mecanimHumanoidFlip = false;
[SerializeField] internal string _nonHumanoidRootNodeName;
[SerializeField] internal bool _addAnimatorComponent = false;
[SerializeField] internal bool _animationLoopTime = true;
[SerializeField] internal bool _animationLoopPose = false;
Expand Down Expand Up @@ -550,11 +551,17 @@ string GetUniqueName(string desiredName)
// }
// }

if (gltfScene && _importAnimations == AnimationMethod.MecanimHumanoid)
if (gltfScene)
{
var avatar = HumanoidSetup.AddAvatarToGameObject(gltfScene, _mecanimHumanoidFlip);
if (avatar)
ctx.AddObjectToAsset("avatar", avatar);
Avatar avatar = null;

if (_importAnimations == AnimationMethod.MecanimHumanoid)
avatar = HumanoidSetup.AddAvatarToGameObject(gltfScene, _mecanimHumanoidFlip);
else if (_importAnimations == AnimationMethod.Mecanim)
avatar = NonHumanoidSetup.AddAvatarToGameObject(gltfScene, false, _nonHumanoidRootNodeName);

if (avatar)
ctx.AddObjectToAsset("avatar", avatar);
}

var renderers = gltfScene ? gltfScene.GetComponentsInChildren<Renderer>(true) : Array.Empty<Renderer>();
Expand Down Expand Up @@ -946,6 +953,7 @@ private void CreateGLTFScene(GLTFImportContext context, out GameObject scene,
{
DataLoader = new FileLoader(Path.GetDirectoryName(projectFilePath)),
AnimationMethod = _importAnimations,
NonHumanoidRootNodeName = _nonHumanoidRootNodeName,
AnimationLoopTime = _animationLoopTime,
AnimationLoopPose = _animationLoopPose,
ImportContext = context,
Expand Down
8 changes: 8 additions & 0 deletions Editor/Scripts/GLTFImporterInspector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,14 @@ private void AnimationInspectorGUI()
EditorGUILayout.PropertyField(flip, new GUIContent("Flip Forward", "Some formats like VRM have a different forward direction for Avatars. Enable this option if the animation looks inverted."));
EditorGUI.indentLevel--;
}
else if (animationMethod.enumValueIndex == (int)AnimationMethod.Mecanim)
{
var rootNodeName = serializedObject.FindProperty(nameof(GLTFImporter._nonHumanoidRootNodeName));
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(rootNodeName, new GUIContent("Root Node Name", "Transform name of the root motion transform. If empty no root motion is defined and you must take care of avatar movement yourself."));
EditorGUILayout.HelpBox("Enter just the name of the root node; not its path in hierarchy.", MessageType.Info);
EditorGUI.indentLevel--;
}
if (hasAnimationData && anim.enumValueIndex > 0)
{
var loopTime = serializedObject.FindProperty(nameof(GLTFImporter._animationLoopTime));
Expand Down
27 changes: 27 additions & 0 deletions Editor/Scripts/Internal/HumanoidSetup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,31 @@ static void _OpenEditor(MenuCommand command)
}
#endif
}

//todo: XtroTheArctic: I don't know how to add a new script file to a local package. We can fix this during PR phase.
internal static class NonHumanoidSetup
{
internal static Avatar AddAvatarToGameObject(GameObject gameObject, bool flipForward, string RootNode)
{
var previousRotation = gameObject.transform.rotation;
if (flipForward)
gameObject.transform.rotation *= Quaternion.Euler(0, 180, 0);

Avatar avatar = AvatarBuilder.BuildGenericAvatar(gameObject, RootNode);
avatar.name = gameObject.name + "Avatar";

if (flipForward)
gameObject.transform.rotation = previousRotation;

if (!avatar.isValid || avatar.isHuman)
{
Object.DestroyImmediate(avatar);
return null;
}

var animator = gameObject.GetComponent<Animator>();
if (animator) animator.avatar = avatar;
return avatar;
}
}
}
3 changes: 2 additions & 1 deletion Runtime/Scripts/GLTFSceneImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public class ImportOptions
public AsyncCoroutineHelper AsyncCoroutineHelper = null;
public bool ThrowOnLowMemory = true;
public AnimationMethod AnimationMethod = AnimationMethod.Legacy;
public string NonHumanoidRootNodeName;
public bool AnimationLoopTime = true;
public bool AnimationLoopPose = false;
public DeduplicateOptions DeduplicateResources = DeduplicateOptions.None;
Expand Down Expand Up @@ -1392,7 +1393,7 @@ protected virtual async Task ConstructScene(GLTFScene scene, bool showSceneObj,
}
}

if (_options.AnimationMethod == AnimationMethod.MecanimHumanoid)
if (_options.AnimationMethod == AnimationMethod.MecanimHumanoid || _options.AnimationMethod == AnimationMethod.Mecanim && !string.IsNullOrEmpty(_options.NonHumanoidRootNodeName))
{
var animator = sceneObj.GetComponent<Animator>();
if (!animator) animator = sceneObj.AddComponent<Animator>();
Expand Down