modular-avatar/UnitTests~/Animation/MergeBlendTreeTest.cs

132 lines
5.7 KiB
C#

#if MA_VRCSDK3_AVATARS
using System;
using System.Linq;
using nadena.dev.modular_avatar.core;
using nadena.dev.modular_avatar.core.editor;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
using VRC.SDK3.Avatars.Components;
using AvatarProcessor = nadena.dev.ndmf.AvatarProcessor;
namespace modular_avatar_tests
{
public class MergeBlendTreeTest : TestBase
{
[Test]
public void SimpleMergeTest()
{
BlendTree bt1 = new BlendTree();
bt1.blendParameter = "abcd";
bt1.blendParameterY = "defg";
bt1.blendType = BlendTreeType.Simple1D;
bt1.AddChild(AnimationTestUtil.AnimationWithPath("a"));
BlendTree bt2 = new BlendTree();
bt2.blendParameter = "p1";
bt2.blendParameterY = "p2";
bt2.blendType = BlendTreeType.FreeformCartesian2D;
bt2.AddChild(AnimationTestUtil.AnimationWithPath("b"));
var root = CreateRoot("root");
var c1 = CreateChild(root, "child1");
var mergeComponent = c1.AddComponent<ModularAvatarMergeBlendTree>();
mergeComponent.BlendTree = bt1;
mergeComponent.PathMode = MergeAnimatorPathMode.Relative;
CreateChild(c1, "a");
var c2 = CreateChild(root, "child2");
var mergeComponent2 = c2.AddComponent<ModularAvatarMergeBlendTree>();
mergeComponent2.BlendTree = bt2;
mergeComponent2.PathMode = MergeAnimatorPathMode.Absolute;
CreateChild(c2, "b");
AvatarProcessor.ProcessAvatar(root);
var fxController = FindController(root, VRCAvatarDescriptor.AnimLayerType.FX).animatorController as AnimatorController;
var fx = findFxLayer(root, MergeBlendTreePass.BlendTreeLayerName);
Assert.AreSame(fxController.layers[0].stateMachine, fx.stateMachine);
Assert.AreEqual(1, fx.stateMachine.states.Length);
var motion = fx.stateMachine.states[0].state.motion as BlendTree;
Assert.AreEqual(BlendTreeType.Direct, motion.blendType);
Assert.AreEqual(2, motion.children.Length);
Assert.AreEqual(MergeBlendTreePass.ALWAYS_ONE, motion.children[0].directBlendParameter);
Assert.AreEqual(MergeBlendTreePass.ALWAYS_ONE, motion.children[1].directBlendParameter);
AnimationTestUtil.AssertAnimationHasPath(((BlendTree)motion.children[0].motion).children[0].motion as AnimationClip, "child1/a");
AnimationTestUtil.AssertAnimationHasPath(((BlendTree)motion.children[1].motion).children[0].motion as AnimationClip, "b");
Assert.IsTrue(fxController.parameters.Any(p =>
p.name == "abcd" && p.type == AnimatorControllerParameterType.Float));
Assert.IsFalse(fxController.parameters.Any(p =>
p.name == "defg" && p.type == AnimatorControllerParameterType.Float));
Assert.IsTrue(fxController.parameters.Any(p =>
p.name == "p1" && p.type == AnimatorControllerParameterType.Float));
Assert.IsTrue(fxController.parameters.Any(p =>
p.name == "p2" && p.type == AnimatorControllerParameterType.Float));
Assert.IsTrue(fxController.parameters.Any(p =>
p.name == MergeBlendTreePass.ALWAYS_ONE && p.type == AnimatorControllerParameterType.Float
&& Math.Abs(p.defaultFloat - 1.0f) < 0.0001f));
}
[Test]
public void AlternateRootTest()
{
BlendTree bt = new BlendTree();
bt.AddChild(AnimationTestUtil.AnimationWithPath("a"));
var root = CreateRoot("root");
var c1 = CreateChild(root, "child1");
var mergeComponent = c1.AddComponent<ModularAvatarMergeBlendTree>();
mergeComponent.BlendTree = bt;
mergeComponent.PathMode = MergeAnimatorPathMode.Relative;
mergeComponent.RelativePathRoot.referencePath = "child2";
CreateChild(c1, "a");
var c2 = CreateChild(root, "child2");
CreateChild(c2, "a");
AvatarProcessor.ProcessAvatar(root);
var fx = findFxLayer(root, MergeBlendTreePass.BlendTreeLayerName);
var motion = fx.stateMachine.states[0].state.motion as BlendTree;
AnimationTestUtil.AssertAnimationHasPath(((BlendTree)motion.children[0].motion).children[0].motion as AnimationClip, "child2/a");
}
[Test]
public void MergeOrderTest()
{
var root = CreateRoot("root");
var bt = new BlendTree();
var c1 = CreateChild(root, "child1");
var mergeComponent = c1.AddComponent<ModularAvatarMergeBlendTree>();
mergeComponent.BlendTree = bt;
TestMerge(root, "m1");
TestMerge(root, "m2").layerPriority = int.MinValue;
TestMerge(root, "m3").layerPriority = int.MaxValue;
AvatarProcessor.ProcessAvatar(root);
var layerNames = (FindController(root, VRCAvatarDescriptor.AnimLayerType.FX).animatorController as AnimatorController)
.layers.Select(l => l.name).ToArray();
Assert.AreEqual(new[] {MergeBlendTreePass.BlendTreeLayerName, "m2", "Eyes", "FaceMood", "m1", "m3"}, layerNames);
}
ModularAvatarMergeAnimator TestMerge(GameObject root, string mergeName, Motion motion = null)
{
var obj = CreateChild(root, mergeName);
var merge = obj.AddComponent<ModularAvatarMergeAnimator>();
merge.animator = AnimationTestUtil.TestController(mergeName, motion);
return merge;
}
}
}
#endif