using NUnit.Framework; using UnityEditor; using UnityEngine; public sealed class HumanoidAnimationFbxImportSettingsTests { [Test] public void ShouldProcessActorAnimationFbx() { Assert.That( HumanoidAnimationFbxImportSettings.ShouldProcessAsset( "Assets/Game/Art/Actor/Controller/Class/Caster/Standing Walk Forward.fbx"), Is.True); } [Test] public void ShouldNotProcessCityboySourceAvatar() { Assert.That( HumanoidAnimationFbxImportSettings.ShouldProcessAsset( HumanoidAnimationFbxImportSettings.CityboyAvatarPath), Is.False); } [Test] public void ShouldProcessActorFbxEvenWhenCustomClipAnimationsAreEmpty() { Assert.That( HumanoidAnimationFbxImportSettings.ShouldProcessAsset( "Assets/Game/Art/Actor/Controller/Class/Caster/Standing 2H Magic Area Attack 02.fbx"), Is.True); } [Test] public void ShouldNotProcessFbxOutsideActorFolder() { Assert.That( HumanoidAnimationFbxImportSettings.ShouldProcessAsset( "Assets/Res/cityboy_uv2/cityboy_uv2.fbx"), Is.False); } [Test] public void ShouldNotUseCityboyAvatarWhenFbxDoesNotContainCityboyHipBone() { Assert.That( HumanoidAnimationFbxImportSettings.ShouldUseCityboyAvatar( new byte[] { 72, 105, 112, 115 }), Is.False); } [Test] public void ShouldUseCityboyAvatarWhenFbxContainsCityboyHipBone() { Assert.That( HumanoidAnimationFbxImportSettings.ShouldUseCityboyAvatar( System.Text.Encoding.ASCII.GetBytes("Model::mixamorig:Hips")), Is.True); } [Test] public void ApplyClipSettingsUsesOriginalRotationAndBakesRotationAndY() { var clip = new ModelImporterClipAnimation { lockRootRotation = false, keepOriginalOrientation = false, lockRootHeightY = false }; ModelImporterClipAnimation updated = HumanoidAnimationFbxImportSettings.ApplyClipSettings(clip); Assert.That(updated.lockRootRotation, Is.True); Assert.That(updated.keepOriginalOrientation, Is.True); Assert.That(updated.lockRootHeightY, Is.True); } [Test] public void ApplyClipSettingsUpdatesEveryClipBeforeWriteback() { var clips = new[] { new ModelImporterClipAnimation { name = "Attack01" }, new ModelImporterClipAnimation { name = "Attack02" } }; ModelImporterClipAnimation[] updated = HumanoidAnimationFbxImportSettings.ApplyClipSettings(clips); Assert.That(updated, Has.Length.EqualTo(2)); Assert.That(updated[0].lockRootRotation, Is.True); Assert.That(updated[0].keepOriginalOrientation, Is.True); Assert.That(updated[0].lockRootHeightY, Is.True); Assert.That(updated[1].lockRootRotation, Is.True); Assert.That(updated[1].keepOriginalOrientation, Is.True); Assert.That(updated[1].lockRootHeightY, Is.True); } [Test] public void CreateClipAnimationFromTakeInfoUsesTakeFramesAndAppliesRootSettings() { var takeInfo = new TakeInfo { name = "mixamo.com", defaultClipName = "Standing 2H Magic Area Attack 02", startTime = 0f, stopTime = 4.5f, sampleRate = 30f }; ModelImporterClipAnimation clip = HumanoidAnimationFbxImportSettings.CreateClipAnimation(takeInfo); Assert.That(clip.name, Is.EqualTo("Standing 2H Magic Area Attack 02")); Assert.That(clip.takeName, Is.EqualTo("mixamo.com")); Assert.That(clip.firstFrame, Is.EqualTo(0f)); Assert.That(clip.lastFrame, Is.EqualTo(135f)); Assert.That(clip.lockRootRotation, Is.True); Assert.That(clip.keepOriginalOrientation, Is.True); Assert.That(clip.lockRootHeightY, Is.True); } [Test] public void CreateClipAnimationFromImportedClipUsesClipNameAndLength() { var importedClip = new AnimationClip { name = "Standing 2H Magic Area Attack 02", frameRate = 30f }; importedClip.SetCurve( string.Empty, typeof(Transform), "m_LocalPosition.x", new AnimationCurve(new Keyframe(0f, 0f), new Keyframe(4.5f, 0f))); ModelImporterClipAnimation clip = HumanoidAnimationFbxImportSettings.CreateClipAnimation(importedClip); Assert.That(clip.name, Is.EqualTo("Standing 2H Magic Area Attack 02")); Assert.That(clip.takeName, Is.EqualTo("Standing 2H Magic Area Attack 02")); Assert.That(clip.firstFrame, Is.EqualTo(0f)); Assert.That(clip.lastFrame, Is.EqualTo(135f)); Assert.That(clip.lockRootRotation, Is.True); Assert.That(clip.keepOriginalOrientation, Is.True); Assert.That(clip.lockRootHeightY, Is.True); } }