#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(); mergeComponent.BlendTree = bt1; mergeComponent.PathMode = MergeAnimatorPathMode.Relative; CreateChild(c1, "a"); var c2 = CreateChild(root, "child2"); var mergeComponent2 = c2.AddComponent(); 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(); 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(); 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(); merge.animator = AnimationTestUtil.TestController(mergeName, motion); return merge; } } } #endif