Skip to content

Commit

Permalink
add animation rename test
Browse files Browse the repository at this point in the history
  • Loading branch information
enitimeago committed May 26, 2024
1 parent 5f8aed5 commit aa66936
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
using System.Linq;
using enitimeago.NonDestructiveMMD.vendor;
using nadena.dev.ndmf;
using UnityEditor.Animations;
using UnityEngine;
using VRC.SDK3.Avatars.Components;
using L = enitimeago.NonDestructiveMMD.Localization;

namespace enitimeago.NonDestructiveMMD
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
using System.Linq;
using System.Runtime.InteropServices;
using enitimeago.NonDestructiveMMD;
using enitimeago.NonDestructiveMMD.vendor;
using nadena.dev.ndmf;
using NUnit.Framework;
using UnityEditor;
using UnityEngine;
using VRC.SDK3.Avatars.Components;

public class RemoveFaceForMmdPassTests : TestBase
public class RenameFaceForMmdPassTests : TestBase
{
[Test]
public void RunPass_NoComponent_DoesNothing()
Expand All @@ -20,7 +19,7 @@ public void RunPass_NoComponent_DoesNothing()

pass.Execute(avatar);

var faceObject = avatar.GetComponent<VRCAvatarDescriptor>().VisemeSkinnedMesh.gameObject;
var faceObject = buildContext.AvatarDescriptor.VisemeSkinnedMesh.gameObject;
Assert.AreEqual("Face", faceObject.name);
}

Expand All @@ -35,11 +34,11 @@ public void RunPass_WithFaceObject_RenamesFace()
var newObject = new GameObject();
newObject.transform.parent = avatar.transform;
var removeFaceForMmdComponent = newObject.AddComponent<RenameFaceForMmdComponent>();
removeFaceForMmdComponent.faceObject = avatar.GetComponent<VRCAvatarDescriptor>().VisemeSkinnedMesh.gameObject;
removeFaceForMmdComponent.faceObject = buildContext.AvatarDescriptor.VisemeSkinnedMesh.gameObject;

pass.Execute(avatar);

var faceObject = avatar.GetComponent<VRCAvatarDescriptor>().VisemeSkinnedMesh.gameObject;
var faceObject = buildContext.AvatarDescriptor.VisemeSkinnedMesh.gameObject;
Assert.AreEqual("Body", faceObject.name);
}

Expand All @@ -51,21 +50,45 @@ public void RunPass_WithFaceAndBodyObjects_RenamesFaceAndBody()
var buildContext = new BuildContext(avatar, null);
buildContext.ActivateExtensionContext<AnimationServicesContext>();
AnimationUtil.CloneAllControllers(buildContext);
var newMesh = Object.Instantiate(avatar.GetComponent<VRCAvatarDescriptor>().VisemeSkinnedMesh.gameObject);
var newMesh = Object.Instantiate(buildContext.AvatarDescriptor.VisemeSkinnedMesh.gameObject);
newMesh.name = "Body";
newMesh.transform.parent = avatar.transform;
var newObject = new GameObject();
newObject.transform.parent = avatar.transform;
var removeFaceForMmdComponent = newObject.AddComponent<RenameFaceForMmdComponent>();
removeFaceForMmdComponent.faceObject = avatar.GetComponent<VRCAvatarDescriptor>().VisemeSkinnedMesh.gameObject;
removeFaceForMmdComponent.faceObject = buildContext.AvatarDescriptor.VisemeSkinnedMesh.gameObject;

pass.Execute(avatar);

var faceObject = avatar.GetComponent<VRCAvatarDescriptor>().VisemeSkinnedMesh.gameObject;
var faceObject = buildContext.AvatarDescriptor.VisemeSkinnedMesh.gameObject;
var bodyObject = avatar.GetComponentsInChildren<SkinnedMeshRenderer>().Where(smr => smr.gameObject.name != "Body").First();
Assert.AreEqual("Body", faceObject.name);
Assert.AreEqual("Body__ORIGINAL", bodyObject.name);
}

// TODO: add a test, which in its arrange part adds an animation that references the "Face" gameobject, and in the assert part checks that this animation references "Body" isntead
[Test]
public void RunPass_WithFaceObjectAndAnimation_UpdatesAnimationReference()
{
var pass = new RenameFaceForMmdPass();
var clip = new AnimationClip();
clip.SetCurve("Face", typeof(GameObject), "m_IsActive", AnimationCurve.Constant(0, 1, 0));
var avatar = CreateAvatarWithFaceNameAndSingleMotion("Face", clip);
var buildContext = new BuildContext(avatar, null);
buildContext.ActivateExtensionContext<AnimationServicesContext>();
var newMesh = Object.Instantiate(buildContext.AvatarDescriptor.VisemeSkinnedMesh.gameObject);
newMesh.name = "Body";
newMesh.transform.parent = avatar.transform;
var newObject = new GameObject();
newObject.transform.parent = avatar.transform;
var removeFaceForMmdComponent = newObject.AddComponent<RenameFaceForMmdComponent>();
removeFaceForMmdComponent.faceObject = buildContext.AvatarDescriptor.VisemeSkinnedMesh.gameObject;

pass.Execute(avatar);
buildContext.DeactivateExtensionContext<AnimationServicesContext>();

var modifiedClip = FindMotionFromCreatedAvatar(buildContext) as AnimationClip;
var bindings = AnimationUtility.GetCurveBindings(modifiedClip);
Assert.IsFalse(bindings.Any(binding => binding.path == "Face"));
Assert.IsTrue(bindings.Any(binding => binding.path == "Body"));
}
}
58 changes: 55 additions & 3 deletions Packages/enitimeago.non-destructive-mmd/Tests/TestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using nadena.dev.ndmf.ui;
using NUnit.Framework;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
using VRC.SDK3.Avatars.Components;

Expand Down Expand Up @@ -49,9 +50,10 @@ protected GameObject CreateAvatarWithFaceNameAndFX(string faceName)
{
var avatarRootObject = CreateAvatarWithFaceName(faceName);
var vrcAvatarDescriptor = avatarRootObject.GetComponent<VRCAvatarDescriptor>();
string path = AssetDatabase.GUIDToAssetPath(FXGuid);
var animatorController = AssetDatabase.LoadAssetAtPath<RuntimeAnimatorController>(path);
Debug.Log(animatorController);

string animatorPath = AssetDatabase.GUIDToAssetPath(FXGuid);
var animatorController = AssetDatabase.LoadAssetAtPath<RuntimeAnimatorController>(animatorPath);

var customAnimLayer = new VRCAvatarDescriptor.CustomAnimLayer
{
type = VRCAvatarDescriptor.AnimLayerType.FX,
Expand All @@ -61,4 +63,54 @@ protected GameObject CreateAvatarWithFaceNameAndFX(string faceName)
vrcAvatarDescriptor.specialAnimationLayers = new VRCAvatarDescriptor.CustomAnimLayer[0];
return avatarRootObject;
}

protected GameObject CreateAvatarWithFaceNameAndSingleMotion(string faceName, Motion motion)
{
var avatarRootObject = CreateAvatarWithFaceName(faceName);
var vrcAvatarDescriptor = avatarRootObject.GetComponent<VRCAvatarDescriptor>();

var animatorController = new AnimatorController();
var animatorStateMachine = new AnimatorStateMachine();
var animatorState = new AnimatorState
{
name = "Open",
motion = motion
};
animatorStateMachine.states = new[]
{
new ChildAnimatorState()
{
state = animatorState
}
};
animatorStateMachine.defaultState = animatorState;

animatorController.layers = new[]
{
new AnimatorControllerLayer
{
blendingMode = AnimatorLayerBlendingMode.Override,
defaultWeight = 1,
name = "Left Hand",
stateMachine = animatorStateMachine
}
};

var customAnimLayer = new VRCAvatarDescriptor.CustomAnimLayer
{
type = VRCAvatarDescriptor.AnimLayerType.FX,
animatorController = animatorController
};
vrcAvatarDescriptor.baseAnimationLayers = new VRCAvatarDescriptor.CustomAnimLayer[] { customAnimLayer };
vrcAvatarDescriptor.specialAnimationLayers = new VRCAvatarDescriptor.CustomAnimLayer[0];
return avatarRootObject;
}

protected Motion FindMotionFromCreatedAvatar(BuildContext buildContext)
{
var animatorController = buildContext.AvatarDescriptor.baseAnimationLayers.First(layer => layer.type == VRCAvatarDescriptor.AnimLayerType.FX).animatorController as AnimatorController;
var animatorControllerLayer = animatorController.layers.Where(layer => layer.name == "Left Hand").First();
var animatorState = animatorControllerLayer.stateMachine.states.Where(state => state.state.name == "Open").First().state;
return animatorState.motion;
}
}

0 comments on commit aa66936

Please sign in to comment.