diff --git a/Assets/_ModularAvatar/EditModeTests/ActiveAnimationRetargeterTests/ActiveAnimationRetargeterTests.cs b/Assets/_ModularAvatar/EditModeTests/ActiveAnimationRetargeterTests/ActiveAnimationRetargeterTests.cs index 9f0db65c..176ca900 100644 --- a/Assets/_ModularAvatar/EditModeTests/ActiveAnimationRetargeterTests/ActiveAnimationRetargeterTests.cs +++ b/Assets/_ModularAvatar/EditModeTests/ActiveAnimationRetargeterTests/ActiveAnimationRetargeterTests.cs @@ -9,15 +9,15 @@ using VRC.SDK3.Avatars.Components; public class ActiveAnimationRetargeterTests : TestBase { [Test] - public void SimpleRetarget() { + public void SimpleRetarget() + { var avatar = CreatePrefab("SimpleRetarget.prefab"); var descriptor = avatar.GetComponent(); // initialize context var buildContext = new BuildContext(descriptor); - var pathMappings = buildContext.PluginBuildContext.ActivateExtensionContext(); - new MergeAnimatorProcessor().OnPreprocessAvatar(avatar, buildContext); // we need this for AnimationDatabase - buildContext.AnimationDatabase.Bootstrap(descriptor); + var pathMappings = buildContext.PluginBuildContext.ActivateExtensionContext() + .PathMappings; // get game objects var changedChild = avatar.transform.Find("Toggled/Child"); diff --git a/Assets/_ModularAvatar/EditModeTests/Animation/MiscAnimationTests.cs b/Assets/_ModularAvatar/EditModeTests/Animation/MiscAnimationTests.cs index 736c63d2..7b77394d 100644 --- a/Assets/_ModularAvatar/EditModeTests/Animation/MiscAnimationTests.cs +++ b/Assets/_ModularAvatar/EditModeTests/Animation/MiscAnimationTests.cs @@ -12,8 +12,8 @@ namespace modular_avatar_tests { var prefab = CreatePrefab("HighQualityCurvesSettingPreserved.prefab"); var context = new BuildContext(prefab, null); - context.ActivateExtensionContext(); - context.DeactivateExtensionContext(); + context.ActivateExtensionContext(); + context.DeactivateExtensionContext(); var layer = findFxLayer(prefab, "Base Layer"); diff --git a/Assets/_ModularAvatar/EditModeTests/Animation/TrackObjectRenamesContextTests.cs b/Assets/_ModularAvatar/EditModeTests/Animation/TrackObjectRenamesContextTests.cs index 80a39b99..21243ee7 100644 --- a/Assets/_ModularAvatar/EditModeTests/Animation/TrackObjectRenamesContextTests.cs +++ b/Assets/_ModularAvatar/EditModeTests/Animation/TrackObjectRenamesContextTests.cs @@ -18,7 +18,7 @@ namespace modular_avatar_tests var av = CreateRoot("root"); var bc = CreateContext(av); - var toc = new TrackObjectRenamesContext(); + var toc = new AnimationServicesContext(); toc.OnActivate(bc); toc.OnDeactivate(bc); @@ -31,12 +31,12 @@ namespace modular_avatar_tests var root = CreateRoot("root"); var a = CreateChild(root, "a"); - var toc = new TrackObjectRenamesContext(); + var toc = new AnimationServicesContext(); toc.OnActivate(CreateContext(root)); - Assert.AreEqual("a", toc.MapPath("a")); + Assert.AreEqual("a", toc.PathMappings.MapPath("a")); a.name = "b"; - toc.ClearCache(); - Assert.AreEqual("b", toc.MapPath("a")); + toc.PathMappings.ClearCache(); + Assert.AreEqual("b", toc.PathMappings.MapPath("a")); } [Test] @@ -46,13 +46,13 @@ namespace modular_avatar_tests var a = CreateChild(root, "a"); var b = CreateChild(root, "b"); - var toc = new TrackObjectRenamesContext(); + var toc = new AnimationServicesContext(); toc.OnActivate(CreateContext(root)); - Assert.AreEqual("a", toc.MapPath("a")); + Assert.AreEqual("a", toc.PathMappings.MapPath("a")); a.transform.parent = b.transform; - toc.ClearCache(); - Assert.AreEqual("b/a", toc.MapPath("a")); + toc.PathMappings.ClearCache(); + Assert.AreEqual("b/a", toc.PathMappings.MapPath("a")); } [Test] @@ -63,14 +63,14 @@ namespace modular_avatar_tests var b = CreateChild(a, "b"); var c = CreateChild(b, "c"); - var toc = new TrackObjectRenamesContext(); + var toc = new AnimationServicesContext(); toc.OnActivate(CreateContext(root)); - toc.MarkRemoved(b); + toc.PathMappings.MarkRemoved(b); c.transform.parent = a.transform; UnityObject.DestroyImmediate(b); - Assert.AreEqual("a/c", toc.MapPath("a/b/c")); + Assert.AreEqual("a/c", toc.PathMappings.MapPath("a/b/c")); } [Test] @@ -82,14 +82,14 @@ namespace modular_avatar_tests var c = CreateChild(b, "c"); var d = CreateChild(c, "d"); - var toc = new TrackObjectRenamesContext(); + var toc = new AnimationServicesContext(); toc.OnActivate(CreateContext(root)); - toc.MarkTransformLookthrough(b); - toc.MarkTransformLookthrough(c); - Assert.AreEqual("a/b/c", toc.MapPath("a/b/c")); - Assert.AreEqual("a", toc.MapPath("a/b/c", true)); - Assert.AreEqual("a/b/c/d", toc.MapPath("a/b/c/d", true)); + toc.PathMappings.MarkTransformLookthrough(b); + toc.PathMappings.MarkTransformLookthrough(c); + Assert.AreEqual("a/b/c", toc.PathMappings.MapPath("a/b/c")); + Assert.AreEqual("a", toc.PathMappings.MapPath("a/b/c", true)); + Assert.AreEqual("a/b/c/d", toc.PathMappings.MapPath("a/b/c/d", true)); } [Test] @@ -105,10 +105,10 @@ namespace modular_avatar_tests var oldIk = descriptor.specialAnimationLayers.First(l => l.type == VRCAvatarDescriptor.AnimLayerType.IKPose); - var toc = new TrackObjectRenamesContext(); + var toc = new AnimationServicesContext(); var buildContext = CreateContext(root); toc.OnActivate(buildContext); - toc.MarkTransformLookthrough(child); + toc.PathMappings.MarkTransformLookthrough(child); parent.name = "p2"; diff --git a/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests.meta b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests.meta new file mode 100644 index 00000000..f713f943 --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 86c4fb6ff802457990f035f4dd663ffe +timeCreated: 1696062676 \ No newline at end of file diff --git a/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BSTAnimation.anim b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BSTAnimation.anim new file mode 100644 index 00000000..7e0acdd1 --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BSTAnimation.anim @@ -0,0 +1,278 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!74 &7400000 +AnimationClip: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: BSTAnimation + serializedVersion: 6 + m_Legacy: 0 + m_Compressed: 0 + m_UseHighQualityCurve: 1 + m_RotationCurves: [] + m_CompressedRotationCurves: [] + m_EulerCurves: [] + m_PositionCurves: [] + m_ScaleCurves: [] + m_FloatCurves: + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.1 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: blendShape.shape_0 + path: BaseMesh + classID: 137 + script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.2 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: blendShape.shape_1 + path: BaseMesh + classID: 137 + script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.3 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: blendShape.shape_0_local + path: BaseMesh + classID: 137 + script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.4 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: blendShape.missing_mesh_shape + path: BaseMesh + classID: 137 + script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.5 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: blendShape.missing_mesh_shape_2 + path: BaseMesh + classID: 137 + script: {fileID: 0} + m_PPtrCurves: [] + m_SampleRate: 60 + m_WrapMode: 0 + m_Bounds: + m_Center: {x: 0, y: 0, z: 0} + m_Extent: {x: 0, y: 0, z: 0} + m_ClipBindingConstant: + genericBindings: + - serializedVersion: 2 + path: 2670104718 + attribute: 1052778082 + script: {fileID: 0} + typeID: 137 + customType: 20 + isPPtrCurve: 0 + - serializedVersion: 2 + path: 2670104718 + attribute: 1237790452 + script: {fileID: 0} + typeID: 137 + customType: 20 + isPPtrCurve: 0 + - serializedVersion: 2 + path: 2670104718 + attribute: 3283797338 + script: {fileID: 0} + typeID: 137 + customType: 20 + isPPtrCurve: 0 + - serializedVersion: 2 + path: 2670104718 + attribute: 2937375684 + script: {fileID: 0} + typeID: 137 + customType: 20 + isPPtrCurve: 0 + - serializedVersion: 2 + path: 2670104718 + attribute: 386770050 + script: {fileID: 0} + typeID: 137 + customType: 20 + isPPtrCurve: 0 + pptrCurveMapping: [] + m_AnimationClipSettings: + serializedVersion: 2 + m_AdditiveReferencePoseClip: {fileID: 0} + m_AdditiveReferencePoseTime: 0 + m_StartTime: 0 + m_StopTime: 0 + m_OrientationOffsetY: 0 + m_Level: 0 + m_CycleOffset: 0 + m_HasAdditiveReferencePose: 0 + m_LoopTime: 0 + m_LoopBlend: 0 + m_LoopBlendOrientation: 0 + m_LoopBlendPositionY: 0 + m_LoopBlendPositionXZ: 0 + m_KeepOriginalOrientation: 0 + m_KeepOriginalPositionY: 1 + m_KeepOriginalPositionXZ: 0 + m_HeightFromFeet: 0 + m_Mirror: 0 + m_EditorCurves: + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.1 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: blendShape.shape_0 + path: BaseMesh + classID: 137 + script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.2 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: blendShape.shape_1 + path: BaseMesh + classID: 137 + script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.3 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: blendShape.shape_0_local + path: BaseMesh + classID: 137 + script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.4 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: blendShape.missing_mesh_shape + path: BaseMesh + classID: 137 + script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.5 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: blendShape.missing_mesh_shape_2 + path: BaseMesh + classID: 137 + script: {fileID: 0} + m_EulerEditorCurves: [] + m_HasGenericRootTransform: 0 + m_HasMotionFloatCurves: 0 + m_Events: [] diff --git a/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BSTAnimation.anim.meta b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BSTAnimation.anim.meta new file mode 100644 index 00000000..08df7f93 --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BSTAnimation.anim.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cc4f9e571dfd17546918cebf2097b2ed +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 7400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncIntegrationTest.cs b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncIntegrationTest.cs new file mode 100644 index 00000000..e95d217f --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncIntegrationTest.cs @@ -0,0 +1,41 @@ +using System.Collections.Immutable; +using System.Linq; +using modular_avatar_tests; +using nadena.dev.modular_avatar.animation; +using nadena.dev.ndmf; +using NUnit.Framework; +using UnityEditor; + +namespace modular_avatar_tests +{ + public class BlendshapeSyncIntegrationTest : TestBase + { + [Test] + public void IntegrationTest_BlendshapeSync() + { + var root = CreatePrefab("BlendshapeSyncIntegrationTest.prefab"); + + AvatarProcessor.ProcessAvatar(root); + + var clip = findFxClip(root, "Base Layer"); + + var bindings = AnimationUtility.GetCurveBindings(clip) + .Select(binding => + { + var constantKey = AnimationUtility.GetEditorCurve(clip, binding).keys[0].value; + return (binding.path, binding.propertyName, constantKey); + }).ToImmutableHashSet(); + + Assert.True(bindings.Contains(("BaseMesh", "blendShape.shape_0", 0.1f))); + Assert.True(bindings.Contains(("BaseMesh", "blendShape.shape_0_local", 0.3f))); + Assert.True(bindings.Contains(("BaseMesh", "blendShape.shape_1", 0.2f))); + Assert.True(bindings.Contains(("BaseMesh", "blendShape.missing_mesh_shape", 0.4f))); + Assert.True(bindings.Contains(("BaseMesh", "blendShape.missing_mesh_shape_2", 0.5f))); + + Assert.True(bindings.Contains(("SyncedMesh", "blendShape.shape_0_local", 0.1f))); + Assert.True(bindings.Contains(("SyncedMesh", "blendShape.shape_1", 0.2f))); + + Assert.AreEqual(bindings.Count, 7); + } + } +} \ No newline at end of file diff --git a/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncIntegrationTest.cs.meta b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncIntegrationTest.cs.meta new file mode 100644 index 00000000..18126f8c --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncIntegrationTest.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8d7e117ac456499596ff775b10aa3876 +timeCreated: 1696062881 \ No newline at end of file diff --git a/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncIntegrationTest.prefab b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncIntegrationTest.prefab new file mode 100644 index 00000000..55b1bb32 --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncIntegrationTest.prefab @@ -0,0 +1,584 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &3825275463613500755 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3825275463613500751} + - component: {fileID: 3825275463613500750} + - component: {fileID: 3825275463613500753} + - component: {fileID: 3825275463613500752} + m_Layer: 0 + m_Name: BlendshapeSyncIntegrationTest + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &3825275463613500751 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3825275463613500755} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.023681391, y: 1.0559628, z: -0.6872994} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 3646968714803193661} + - {fileID: 3646968713996568948} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!95 &3825275463613500750 +Animator: + serializedVersion: 3 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3825275463613500755} + m_Enabled: 1 + m_Avatar: {fileID: 0} + m_Controller: {fileID: 9100000, guid: 1be58bb091803cb488c7005def284caa, type: 2} + m_CullingMode: 0 + m_UpdateMode: 0 + m_ApplyRootMotion: 0 + m_LinearVelocityBlending: 0 + m_WarningMessage: + m_HasTransformHierarchy: 1 + m_AllowConstantClipSamplingOptimization: 1 + m_KeepAnimatorControllerStateOnDisable: 0 +--- !u!114 &3825275463613500753 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3825275463613500755} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 542108242, guid: 67cc4cb7839cd3741b63733d5adf0442, type: 3} + m_Name: + m_EditorClassIdentifier: + Name: + ViewPosition: {x: 0, y: 1.6, z: 0.2} + Animations: 0 + ScaleIPD: 1 + lipSync: 0 + lipSyncJawBone: {fileID: 0} + lipSyncJawClosed: {x: 0, y: 0, z: 0, w: 1} + lipSyncJawOpen: {x: 0, y: 0, z: 0, w: 1} + VisemeSkinnedMesh: {fileID: 0} + MouthOpenBlendShapeName: Facial_Blends.Jaw_Down + VisemeBlendShapes: [] + unityVersion: + portraitCameraPositionOffset: {x: 0, y: 0, z: 0} + portraitCameraRotationOffset: {x: 0, y: 1, z: 0, w: -0.00000004371139} + networkIDs: [] + customExpressions: 0 + expressionsMenu: {fileID: 0} + expressionParameters: {fileID: 0} + enableEyeLook: 0 + customEyeLookSettings: + eyeMovement: + confidence: 0.5 + excitement: 0.5 + leftEye: {fileID: 0} + rightEye: {fileID: 0} + eyesLookingStraight: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyesLookingUp: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyesLookingDown: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyesLookingLeft: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyesLookingRight: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyelidType: 0 + upperLeftEyelid: {fileID: 0} + upperRightEyelid: {fileID: 0} + lowerLeftEyelid: {fileID: 0} + lowerRightEyelid: {fileID: 0} + eyelidsDefault: + upper: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + lower: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyelidsClosed: + upper: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + lower: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyelidsLookingUp: + upper: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + lower: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyelidsLookingDown: + upper: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + lower: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyelidsSkinnedMesh: {fileID: 0} + eyelidsBlendshapes: + customizeAnimationLayers: 1 + baseAnimationLayers: + - isEnabled: 0 + type: 0 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + - isEnabled: 0 + type: 4 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + - isEnabled: 0 + type: 5 + animatorController: {fileID: 9100000, guid: 1be58bb091803cb488c7005def284caa, + type: 2} + mask: {fileID: 0} + isDefault: 0 + specialAnimationLayers: + - isEnabled: 0 + type: 6 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + - isEnabled: 0 + type: 7 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + - isEnabled: 0 + type: 8 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + AnimationPreset: {fileID: 0} + animationHashSet: [] + autoFootsteps: 1 + autoLocomotion: 1 + collider_head: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_torso: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_footR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_footL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_handR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_handL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerIndexL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerMiddleL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerRingL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerLittleL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerIndexR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerMiddleR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerRingR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerLittleR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} +--- !u!114 &3825275463613500752 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3825275463613500755} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1427037861, guid: 4ecd63eff847044b68db9453ce219299, type: 3} + m_Name: + m_EditorClassIdentifier: + launchedFromSDKPipeline: 0 + completedSDKPipeline: 0 + blueprintId: + contentType: 0 + assetBundleUnityVersion: + fallbackStatus: 0 +--- !u!114 &3825275463971368602 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4167925416990528462} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6fd7cab7d93b403280f2f9da978d8a4f, type: 3} + m_Name: + m_EditorClassIdentifier: + Bindings: + - ReferenceMesh: + referencePath: BaseMesh + Blendshape: shape_0 + LocalBlendshape: shape_0_local + - ReferenceMesh: + referencePath: BaseMesh + Blendshape: shape_1 + LocalBlendshape: shape_1 + - ReferenceMesh: + referencePath: MissingMesh + Blendshape: missing_mesh_shape + LocalBlendshape: missing_mesh_shape + - ReferenceMesh: + referencePath: + Blendshape: missing_mesh_shape_2 + LocalBlendshape: missing_mesh_shape_2 +--- !u!1001 &3825275463173128406 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 3825275463613500751} + m_Modifications: + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_RootOrder + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalScale.x + value: 0.1 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalScale.y + value: 0.1 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalScale.z + value: 0.1 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalPosition.x + value: -0.023681391 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalPosition.y + value: -1.0559628 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.6872994 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalRotation.w + value: 0.7071067 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalRotation.x + value: -0.7071068 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -3887185075125053422, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_DirtyAABB + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -3887185075125053422, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_AABB.m_Extent.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: -3887185075125053422, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_AABB.m_Extent.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: -3887185075125053422, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_AABB.m_Extent.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 919132149155446097, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_Name + value: BaseMesh + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 14ac2ad30c5d3444ca37f76cea5a7047, type: 3} +--- !u!4 &3646968714803193661 stripped +Transform: + m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + m_PrefabInstance: {fileID: 3825275463173128406} + m_PrefabAsset: {fileID: 0} +--- !u!1001 &3825275463971368607 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 3825275463613500751} + m_Modifications: + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_RootOrder + value: 1 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalScale.x + value: 0.1 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalScale.y + value: 0.1 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalScale.z + value: 0.1 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalPosition.x + value: -0.023681391 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalPosition.y + value: -1.0559628 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.6872994 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalRotation.w + value: 0.7071067 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalRotation.x + value: -0.7071068 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -3887185075125053422, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_DirtyAABB + value: 0 + objectReference: {fileID: 0} + - target: {fileID: -3887185075125053422, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_AABB.m_Extent.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: -3887185075125053422, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_AABB.m_Extent.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: -3887185075125053422, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_AABB.m_Extent.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: -3887185075125053422, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_BlendShapeWeights.Array.size + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 919132149155446097, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + propertyPath: m_Name + value: SyncedMesh + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 14ac2ad30c5d3444ca37f76cea5a7047, type: 3} +--- !u!1 &4167925416990528462 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 919132149155446097, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + m_PrefabInstance: {fileID: 3825275463971368607} + m_PrefabAsset: {fileID: 0} +--- !u!4 &3646968713996568948 stripped +Transform: + m_CorrespondingSourceObject: {fileID: -8679921383154817045, guid: 14ac2ad30c5d3444ca37f76cea5a7047, + type: 3} + m_PrefabInstance: {fileID: 3825275463971368607} + m_PrefabAsset: {fileID: 0} diff --git a/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncIntegrationTest.prefab.meta b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncIntegrationTest.prefab.meta new file mode 100644 index 00000000..3db35c7c --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncIntegrationTest.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: de3f4b692075ea940a363d048dd49d9a +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncTestAnimator.controller b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncTestAnimator.controller new file mode 100644 index 00000000..ab759f50 --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncTestAnimator.controller @@ -0,0 +1,72 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!91 &9100000 +AnimatorController: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: BlendshapeSyncTestAnimator + serializedVersion: 5 + m_AnimatorParameters: [] + m_AnimatorLayers: + - serializedVersion: 5 + m_Name: Base Layer + m_StateMachine: {fileID: 6361318802971715810} + m_Mask: {fileID: 0} + m_Motions: [] + m_Behaviours: [] + m_BlendingMode: 0 + m_SyncedLayerIndex: -1 + m_DefaultWeight: 0 + m_IKPass: 0 + m_SyncedLayerAffectsTiming: 0 + m_Controller: {fileID: 9100000} +--- !u!1102 &4455402730181834275 +AnimatorState: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: BSTAnimation + m_Speed: 1 + m_CycleOffset: 0 + m_Transitions: [] + m_StateMachineBehaviours: [] + m_Position: {x: 50, y: 50, z: 0} + m_IKOnFeet: 0 + m_WriteDefaultValues: 1 + m_Mirror: 0 + m_SpeedParameterActive: 0 + m_MirrorParameterActive: 0 + m_CycleOffsetParameterActive: 0 + m_TimeParameterActive: 0 + m_Motion: {fileID: 7400000, guid: cc4f9e571dfd17546918cebf2097b2ed, type: 2} + m_Tag: + m_SpeedParameter: + m_MirrorParameter: + m_CycleOffsetParameter: + m_TimeParameter: +--- !u!1107 &6361318802971715810 +AnimatorStateMachine: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Base Layer + m_ChildStates: + - serializedVersion: 1 + m_State: {fileID: 4455402730181834275} + m_Position: {x: 640.24945, y: 141.47957, z: 0} + m_ChildStateMachines: [] + m_AnyStateTransitions: [] + m_EntryTransitions: [] + m_StateMachineTransitions: {} + m_StateMachineBehaviours: [] + m_AnyStatePosition: {x: 50, y: 20, z: 0} + m_EntryPosition: {x: 50, y: 120, z: 0} + m_ExitPosition: {x: 800, y: 120, z: 0} + m_ParentStateMachinePosition: {x: 800, y: 20, z: 0} + m_DefaultState: {fileID: 4455402730181834275} diff --git a/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncTestAnimator.controller.meta b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncTestAnimator.controller.meta new file mode 100644 index 00000000..c1e3e9da --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/BlendshapeSyncTestAnimator.controller.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1be58bb091803cb488c7005def284caa +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 9100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/blendshape_sync_test_mesh.fbx b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/blendshape_sync_test_mesh.fbx new file mode 100644 index 00000000..586885bd Binary files /dev/null and b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/blendshape_sync_test_mesh.fbx differ diff --git a/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/blendshape_sync_test_mesh.fbx.meta b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/blendshape_sync_test_mesh.fbx.meta new file mode 100644 index 00000000..2b228f3d --- /dev/null +++ b/Assets/_ModularAvatar/EditModeTests/BlendshapeSyncTests/blendshape_sync_test_mesh.fbx.meta @@ -0,0 +1,97 @@ +fileFormatVersion: 2 +guid: 14ac2ad30c5d3444ca37f76cea5a7047 +ModelImporter: + serializedVersion: 19301 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 1 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 1 + optimizeGameObjects: 0 + motionNodeName: + rigImportErrors: + rigImportWarnings: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 1 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: [] + isReadable: 0 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + useSRGBMaterialColor: 1 + sortHierarchyByName: 1 + importVisibility: 1 + importBlendShapes: 1 + importCameras: 1 + importLights: 1 + fileIdsGeneration: 2 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + keepQuads: 0 + weldVertices: 1 + preserveHierarchy: 0 + skinWeightsMode: 0 + maxBonesPerVertex: 4 + minBoneWeight: 0.001 + meshOptimizationFlags: -1 + indexFormat: 0 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVPackMargin: 4 + useFileScale: 1 + tangentSpace: + normalSmoothAngle: 60 + normalImportMode: 0 + tangentImportMode: 3 + normalCalculationMode: 4 + legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0 + blendShapeNormalImportMode: 1 + normalSmoothingSource: 0 + referencedClips: [] + importAnimation: 1 + humanDescription: + serializedVersion: 3 + human: [] + skeleton: [] + armTwist: 0.5 + foreArmTwist: 0.5 + upperLegTwist: 0.5 + legTwist: 0.5 + armStretch: 0.05 + legStretch: 0.05 + feetSpacing: 0 + globalScale: 1 + rootMotionBoneName: + hasTranslationDoF: 0 + hasExtraRoot: 0 + skeletonHasParents: 1 + lastHumanDescriptionAvatarSource: {instanceID: 0} + autoGenerateAvatarMappingIfUnspecified: 1 + animationType: 2 + humanoidOversampling: 1 + avatarSetup: 0 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/_ModularAvatar/EditModeTests/MergeArmatureTests/MultiLevelMergeTest.cs b/Assets/_ModularAvatar/EditModeTests/MergeArmatureTests/MultiLevelMergeTest.cs index 832d8308..6ab29424 100644 --- a/Assets/_ModularAvatar/EditModeTests/MergeArmatureTests/MultiLevelMergeTest.cs +++ b/Assets/_ModularAvatar/EditModeTests/MergeArmatureTests/MultiLevelMergeTest.cs @@ -55,7 +55,7 @@ namespace modular_avatar_tests.MergeArmatureTests nadena.dev.ndmf.BuildContext context = new nadena.dev.ndmf.BuildContext(root.GetComponent(), null); context.ActivateExtensionContext(); - context.ActivateExtensionContext(typeof(TrackObjectRenamesContext)); + context.ActivateExtensionContext(); new MergeArmatureHook().OnPreprocessAvatar(context, root); Assert.IsTrue(bone.GetComponentInChildren() != null); @@ -83,7 +83,7 @@ namespace modular_avatar_tests.MergeArmatureTests nadena.dev.ndmf.BuildContext context = new nadena.dev.ndmf.BuildContext(root.GetComponent(), null); context.ActivateExtensionContext(); - context.ActivateExtensionContext(typeof(TrackObjectRenamesContext)); + context.ActivateExtensionContext(); new MergeArmatureHook().OnPreprocessAvatar(context, root); Assert.IsTrue(m_bone == null); // destroyed by retargeting pass @@ -107,7 +107,7 @@ namespace modular_avatar_tests.MergeArmatureTests nadena.dev.ndmf.BuildContext context = new nadena.dev.ndmf.BuildContext(root.GetComponent(), null); context.ActivateExtensionContext(); - context.ActivateExtensionContext(typeof(TrackObjectRenamesContext)); + context.ActivateExtensionContext(); new MergeArmatureHook().OnPreprocessAvatar(context, root); Assert.IsTrue(m_bone == null); // destroyed by retargeting pass diff --git a/Assets/_ModularAvatar/EditModeTests/ReplaceObject/ReplaceObjectTests.cs b/Assets/_ModularAvatar/EditModeTests/ReplaceObject/ReplaceObjectTests.cs index 98da7713..b123a3ba 100644 --- a/Assets/_ModularAvatar/EditModeTests/ReplaceObject/ReplaceObjectTests.cs +++ b/Assets/_ModularAvatar/EditModeTests/ReplaceObject/ReplaceObjectTests.cs @@ -11,13 +11,13 @@ namespace modular_avatar_tests.ReplaceObject { public class ReplaceObjectTests : TestBase { - private TrackObjectRenamesContext pathMappings; + private PathMappings pathMappings; void Process(GameObject root) { var avDesc = root.GetComponent(); var buildContext = new nadena.dev.ndmf.BuildContext(avDesc, null); - pathMappings = buildContext.ActivateExtensionContext(); + pathMappings = buildContext.ActivateExtensionContext().PathMappings; new ReplaceObjectPass(buildContext).Process(); } diff --git a/Assets/_ModularAvatar/EditModeTests/RetargetMeshesTest.cs b/Assets/_ModularAvatar/EditModeTests/RetargetMeshesTest.cs index 4481deb9..11f36e03 100644 --- a/Assets/_ModularAvatar/EditModeTests/RetargetMeshesTest.cs +++ b/Assets/_ModularAvatar/EditModeTests/RetargetMeshesTest.cs @@ -23,13 +23,13 @@ namespace modular_avatar_tests var build_context = new nadena.dev.ndmf.BuildContext(root.GetComponent(), null); - var torc = new TrackObjectRenamesContext(); + var torc = new AnimationServicesContext(); torc.OnActivate(build_context); var bonedb = new BoneDatabase(); bonedb.AddMergedBone(b.transform); - new RetargetMeshes().OnPreprocessAvatar(root, bonedb, torc); + new RetargetMeshes().OnPreprocessAvatar(root, bonedb, torc.PathMappings); Assert.AreEqual(a.transform, skinnedMeshRenderer.rootBone); } @@ -50,13 +50,13 @@ namespace modular_avatar_tests var build_context = new nadena.dev.ndmf.BuildContext(root.GetComponent(), null); - var torc = new TrackObjectRenamesContext(); + var torc = new AnimationServicesContext(); torc.OnActivate(build_context); var bonedb = new BoneDatabase(); bonedb.AddMergedBone(b.transform); - new RetargetMeshes().OnPreprocessAvatar(root, bonedb, torc); + new RetargetMeshes().OnPreprocessAvatar(root, bonedb, torc.PathMappings); Assert.AreEqual(a.transform, skinnedMeshRenderer.rootBone); Assert.AreEqual(new Bounds(new Vector3(0, 0, 0), new Vector3(2, 2, 2)), diff --git a/Assets/_ModularAvatar/EditModeTests/WorldFixedObjectTest/WorldFixedObjectTest.cs b/Assets/_ModularAvatar/EditModeTests/WorldFixedObjectTest/WorldFixedObjectTest.cs index 1c54bf1d..bded98ff 100644 --- a/Assets/_ModularAvatar/EditModeTests/WorldFixedObjectTest/WorldFixedObjectTest.cs +++ b/Assets/_ModularAvatar/EditModeTests/WorldFixedObjectTest/WorldFixedObjectTest.cs @@ -14,10 +14,10 @@ public class WorldFixedObjectTest : TestBase var descriptor = avatar.GetComponent(); var fixedObject = avatar.transform.Find("FixedObject"); - + // initialize context var buildContext = new BuildContext(descriptor); - buildContext.PluginBuildContext.ActivateExtensionContext(); + buildContext.PluginBuildContext.ActivateExtensionContext(); new WorldFixedObjectProcessor(descriptor).Process(buildContext); @@ -32,7 +32,7 @@ public class WorldFixedObjectTest : TestBase Assert.That(movedFixedObject, Is.Not.Null); Assert.That(movedFixedObject, Is.EqualTo(fixedObject)); } - + [Test] public void NestedTest() { @@ -41,10 +41,10 @@ public class WorldFixedObjectTest : TestBase var fixedObject = avatar.transform.Find("FixedObject"); var nestedFixed = avatar.transform.Find("FixedObject/NestedFixed"); - + // initialize context var buildContext = new BuildContext(descriptor); - buildContext.PluginBuildContext.ActivateExtensionContext(); + buildContext.PluginBuildContext.ActivateExtensionContext(); new WorldFixedObjectProcessor(descriptor).Process(buildContext); @@ -64,4 +64,4 @@ public class WorldFixedObjectTest : TestBase Assert.That(nestedFixedObject, Is.Not.Null); Assert.That(nestedFixedObject, Is.EqualTo(nestedFixed)); } -} +} \ No newline at end of file diff --git a/Packages/nadena.dev.modular-avatar/Editor/ActiveAnimationRetargeter.cs b/Packages/nadena.dev.modular-avatar/Editor/ActiveAnimationRetargeter.cs index 0fbad44e..21d82fda 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/ActiveAnimationRetargeter.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/ActiveAnimationRetargeter.cs @@ -16,7 +16,7 @@ namespace nadena.dev.modular_avatar.core.editor { private readonly BuildContext _context; private readonly BoneDatabase _boneDatabase; - private readonly TrackObjectRenamesContext _pathMappings; + private readonly PathMappings _pathMappings; private readonly List _intermediateObjs = new List(); /// @@ -55,7 +55,7 @@ namespace nadena.dev.modular_avatar.core.editor { _context = context; _boneDatabase = boneDatabase; - _pathMappings = context.PluginBuildContext.Extension(); + _pathMappings = context.PluginBuildContext.Extension().PathMappings; while (root != null && root.GetComponent() == null) { @@ -74,7 +74,7 @@ namespace nadena.dev.modular_avatar.core.editor Created = new List(), }); } - + root = root.parent; } @@ -132,7 +132,7 @@ namespace nadena.dev.modular_avatar.core.editor foreach (var holder in _context.AnimationDatabase.ClipsForPath(path)) { - if (!Util.IsTemporaryAsset(holder.CurrentClip)) + if (!_context.PluginBuildContext.IsTemporaryAsset(holder.CurrentClip)) { holder.CurrentClip = Object.Instantiate(holder.CurrentClip); } @@ -152,7 +152,7 @@ namespace nadena.dev.modular_avatar.core.editor } } } - + private AnimationCurve GetActiveBinding(AnimationClip clip, string path) { return AnimationUtility.GetEditorCurve(clip, diff --git a/Packages/nadena.dev.modular-avatar/Editor/AnimationDatabase.cs b/Packages/nadena.dev.modular-avatar/Editor/Animation/AnimationDatabase.cs similarity index 76% rename from Packages/nadena.dev.modular-avatar/Editor/AnimationDatabase.cs rename to Packages/nadena.dev.modular-avatar/Editor/Animation/AnimationDatabase.cs index 97c580a2..29ccd92b 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/AnimationDatabase.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/Animation/AnimationDatabase.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Data.Odbc; +using nadena.dev.modular_avatar.core.editor; using nadena.dev.modular_avatar.editor.ErrorReporting; using UnityEditor; using UnityEditor.Animations; @@ -8,28 +10,66 @@ using UnityEngine; using VRC.SDK3.Avatars.Components; using Object = UnityEngine.Object; -namespace nadena.dev.modular_avatar.core.editor +namespace nadena.dev.modular_avatar.animation { + /// + /// The animation database records the set of all clips which are used in the avatar, and which paths they + /// manipulate. + /// internal class AnimationDatabase { internal class ClipHolder { - internal Motion CurrentClip; + private readonly AnimationDatabase ParentDatabase; + + private Motion _currentClip; + + internal Motion CurrentClip + { + get + { + ParentDatabase.InvalidateCaches(); + return _currentClip; + } + set + { + ParentDatabase.InvalidateCaches(); + _currentClip = value; + } + } + internal Motion OriginalClip { get; } internal readonly bool IsProxyAnimation; - internal ClipHolder(Motion clip) + internal ClipHolder(AnimationDatabase parentDatabase, Motion clip) { + ParentDatabase = parentDatabase; CurrentClip = OriginalClip = clip; IsProxyAnimation = clip != null && Util.IsProxyAnimation(clip); } + + /// + /// Returns the current clip without invalidating caches. Do not modify this clip without taking extra + /// steps to invalidate caches on the AnimationDatabase. + /// + /// + internal Motion GetCurrentClipUnsafe() + { + return _currentClip; + } } + private ndmf.BuildContext _context; + private List _clipCommitActions = new List(); private List _clips = new List(); - private Dictionary> _pathToClip = - new Dictionary>(); + private Dictionary> _pathToClip = null; + + internal AnimationDatabase() + { + Debug.Log("Creating animation database"); + } internal void Commit() { @@ -64,8 +104,14 @@ namespace nadena.dev.modular_avatar.core.editor } } - internal void Bootstrap(VRCAvatarDescriptor avatarDescriptor) + internal void OnActivate(ndmf.BuildContext context) { + _context = context; + + AnimationUtil.CloneAllControllers(context); + + var avatarDescriptor = context.AvatarDescriptor; + foreach (var layer in avatarDescriptor.baseAnimationLayers) { BootstrapLayer(layer); @@ -78,7 +124,8 @@ namespace nadena.dev.modular_avatar.core.editor void BootstrapLayer(VRCAvatarDescriptor.CustomAnimLayer layer) { - if (!layer.isDefault && layer.animatorController is AnimatorController ac && Util.IsTemporaryAsset(ac)) + if (!layer.isDefault && layer.animatorController is AnimatorController ac && + context.IsTemporaryAsset(ac)) { BuildReport.ReportingObject(ac, () => { @@ -108,7 +155,7 @@ namespace nadena.dev.modular_avatar.core.editor if (state.motion == null) return; var clipHolder = RegisterMotion(state.motion, state, processClip, _originalToHolder); - if (!Util.IsTemporaryAsset(state.motion)) + if (!_context.IsTemporaryAsset(state.motion)) { // Protect the original animations from mutations by creating temporary clones; in the case of a proxy // animation, we'll restore the original in a later pass @@ -139,6 +186,8 @@ namespace nadena.dev.modular_avatar.core.editor /// internal ImmutableArray ClipsForPath(string path) { + HydrateCaches(); + if (_pathToClip.TryGetValue(path, out var clips)) { return clips.ToImmutableArray(); @@ -158,7 +207,7 @@ namespace nadena.dev.modular_avatar.core.editor { if (motion == null) { - return new ClipHolder(null); + return new ClipHolder(this, null); } if (originalToHolder.TryGetValue(motion, out var holder)) @@ -166,13 +215,14 @@ namespace nadena.dev.modular_avatar.core.editor return holder; } + InvalidateCaches(); + switch (motion) { case AnimationClip clip: { - holder = new ClipHolder(clip); + holder = new ClipHolder(this, clip); processClip(holder); - recordPaths(holder); _clips.Add(holder); break; } @@ -187,9 +237,26 @@ namespace nadena.dev.modular_avatar.core.editor return holder; } + private void InvalidateCaches() + { + _pathToClip = null; + } + + private void HydrateCaches() + { + if (_pathToClip == null) + { + _pathToClip = new Dictionary>(); + foreach (var clip in _clips) + { + recordPaths(clip); + } + } + } + private void recordPaths(ClipHolder holder) { - var clip = holder.CurrentClip as AnimationClip; + var clip = holder.GetCurrentClipUnsafe() as AnimationClip; foreach (var binding in AnimationUtility.GetCurveBindings(clip)) { @@ -222,12 +289,12 @@ namespace nadena.dev.modular_avatar.core.editor Dictionary originalToHolder ) { - if (!Util.IsTemporaryAsset(tree)) + if (!_context.IsTemporaryAsset(tree)) { throw new Exception("Blendtree must be a temporary asset"); } - var treeHolder = new ClipHolder(tree); + var treeHolder = new ClipHolder(this, tree); var children = tree.children; var holders = new ClipHolder[children.Length]; diff --git a/Packages/nadena.dev.modular-avatar/Editor/AnimationDatabase.cs.meta b/Packages/nadena.dev.modular-avatar/Editor/Animation/AnimationDatabase.cs.meta similarity index 100% rename from Packages/nadena.dev.modular-avatar/Editor/AnimationDatabase.cs.meta rename to Packages/nadena.dev.modular-avatar/Editor/Animation/AnimationDatabase.cs.meta diff --git a/Packages/nadena.dev.modular-avatar/Editor/Animation/AnimationServicesContext.cs b/Packages/nadena.dev.modular-avatar/Editor/Animation/AnimationServicesContext.cs new file mode 100644 index 00000000..961f4260 --- /dev/null +++ b/Packages/nadena.dev.modular-avatar/Editor/Animation/AnimationServicesContext.cs @@ -0,0 +1,69 @@ +using System; +using nadena.dev.ndmf; + +namespace nadena.dev.modular_avatar.animation +{ + /// + /// This extension context amortizes a number of animation-related processing steps - notably, + /// collecting the set of all animation clips from the animators, and committing changes to them + /// in a deferred manner. + /// + /// Restrictions: While this context is active, any changes to clips must be done by editing them via + /// ClipHolders in the AnimationDatabase. Any newly added clips must be registered in the AnimationDatabase, + /// and any new references to clips require setting appropriate ClipCommitActions. + /// + /// New references to objects created in clips must use paths obtained from the + /// ObjectRenameTracker.GetObjectIdentifier method. + /// + internal sealed class AnimationServicesContext : IExtensionContext + { + private AnimationDatabase _animationDatabase; + private PathMappings _pathMappings; + + public void OnActivate(BuildContext context) + { + _animationDatabase = new AnimationDatabase(); + _animationDatabase.OnActivate(context); + + _pathMappings = new PathMappings(); + _pathMappings.OnActivate(context, _animationDatabase); + } + + public void OnDeactivate(BuildContext context) + { + _pathMappings.OnDeactivate(context); + _animationDatabase.Commit(); + + _pathMappings = null; + _animationDatabase = null; + } + + public AnimationDatabase AnimationDatabase + { + get + { + if (_animationDatabase == null) + { + throw new InvalidOperationException( + "AnimationDatabase is not available outside of the AnimationServicesContext"); + } + + return _animationDatabase; + } + } + + public PathMappings PathMappings + { + get + { + if (_pathMappings == null) + { + throw new InvalidOperationException( + "ObjectRenameTracker is not available outside of the AnimationServicesContext"); + } + + return _pathMappings; + } + } + } +} \ No newline at end of file diff --git a/Packages/nadena.dev.modular-avatar/Editor/Animation/AnimationServicesContext.cs.meta b/Packages/nadena.dev.modular-avatar/Editor/Animation/AnimationServicesContext.cs.meta new file mode 100644 index 00000000..8eefb71b --- /dev/null +++ b/Packages/nadena.dev.modular-avatar/Editor/Animation/AnimationServicesContext.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c2c26040d44d4dacb838aceced3b3e52 +timeCreated: 1696063949 \ No newline at end of file diff --git a/Packages/nadena.dev.modular-avatar/Editor/Animation/AnimatorCombiner.cs b/Packages/nadena.dev.modular-avatar/Editor/Animation/AnimatorCombiner.cs index 156973d0..a9a73071 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/Animation/AnimatorCombiner.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/Animation/AnimatorCombiner.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; using System.Linq; +using nadena.dev.modular_avatar.core.editor; using UnityEditor; using UnityEditor.Animations; using UnityEngine; @@ -67,7 +68,7 @@ namespace nadena.dev.modular_avatar.animation if (!EditorUtility.IsPersistent(assetContainer) || string.IsNullOrEmpty(AssetDatabase.GetAssetPath(assetContainer))) { - Debug.Log("Nonpersistent asset container: " + assetContainer.name); + // Debug.Log("Nonpersistent asset container: " + assetContainer.name); } else { diff --git a/Packages/nadena.dev.modular-avatar/Editor/Animation/IOnCommitObjectRenames.cs b/Packages/nadena.dev.modular-avatar/Editor/Animation/IOnCommitObjectRenames.cs index b7578946..a8a832f0 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/Animation/IOnCommitObjectRenames.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/Animation/IOnCommitObjectRenames.cs @@ -12,6 +12,6 @@ namespace nadena.dev.modular_avatar.animation /// internal interface IOnCommitObjectRenames { - void OnCommitObjectRenames(BuildContext buildContext, TrackObjectRenamesContext renameContext); + void OnCommitObjectRenames(BuildContext buildContext, PathMappings renameContext); } } \ No newline at end of file diff --git a/Packages/nadena.dev.modular-avatar/Editor/Animation/TrackObjectRenamesContext.cs b/Packages/nadena.dev.modular-avatar/Editor/Animation/PathMappings.cs similarity index 69% rename from Packages/nadena.dev.modular-avatar/Editor/Animation/TrackObjectRenamesContext.cs rename to Packages/nadena.dev.modular-avatar/Editor/Animation/PathMappings.cs index 1992f432..b44f570f 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/Animation/TrackObjectRenamesContext.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/Animation/PathMappings.cs @@ -1,15 +1,12 @@ #region -using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using nadena.dev.ndmf; using nadena.dev.ndmf.util; using UnityEditor; -using UnityEditor.Animations; using UnityEngine; -using VRC.SDK3.Avatars.Components; using Object = UnityEngine.Object; #endregion @@ -27,8 +24,10 @@ namespace nadena.dev.modular_avatar.animation /// Users of this context need to be aware that, when creating new curves (or otherwise introducing new motions, /// use context.ObjectPath to obtain a suitable path for the target objects). /// - internal sealed class TrackObjectRenamesContext : IExtensionContext + internal sealed class PathMappings { + private AnimationDatabase _animationDatabase; + private Dictionary> _objectToOriginalPaths = new Dictionary>(); @@ -36,8 +35,9 @@ namespace nadena.dev.modular_avatar.animation private ImmutableDictionary _originalPathToMappedPath = null; private ImmutableDictionary _transformOriginalPathToMappedPath = null; - public void OnActivate(BuildContext context) + internal void OnActivate(BuildContext context, AnimationDatabase animationDatabase) { + _animationDatabase = animationDatabase; _objectToOriginalPaths.Clear(); _transformLookthroughObjects.Clear(); ClearCache(); @@ -195,74 +195,6 @@ namespace nadena.dev.modular_avatar.animation } } - public RuntimeAnimatorController ApplyMappingsToAnimator( - BuildContext context, - RuntimeAnimatorController controller, - Dictionary clipCache = null) - { - if (clipCache == null) - { - clipCache = new Dictionary(); - } - - if (controller == null) return null; - - switch (controller) - { - case AnimatorController ac: - if (!context.IsTemporaryAsset(ac)) - { - ac = AnimationUtil.DeepCloneAnimator(context, ac); - } - - foreach (var asset in ac.ReferencedAssets()) - { - if (asset is AnimatorState state) - { - if (state.motion is AnimationClip clip) - { - state.motion = ApplyMappingsToClip(clip, clipCache); - } - } - else if (asset is BlendTree tree) - { - var children = tree.children; - for (int i = 0; i < children.Length; i++) - { - var child = children[i]; - if (child.motion is AnimationClip clip) - { - child.motion = ApplyMappingsToClip(clip, clipCache); - } - } - - tree.children = children; - } - } - - return ac; - case AnimatorOverrideController aoc: - { - AnimatorOverrideController newController = new AnimatorOverrideController(); - newController.runtimeAnimatorController = - ApplyMappingsToAnimator(context, aoc.runtimeAnimatorController); - List> overrides = - new List>(); - - overrides = overrides.Select(kvp => - new KeyValuePair(kvp.Key, - ApplyMappingsToClip(kvp.Value, clipCache))) - .ToList(); - - newController.ApplyOverrides(overrides); - - return newController; - } - default: - throw new Exception("Unknown animator controller type: " + controller.GetType().Name); - } - } - private string MapPath(EditorCurveBinding binding) { if (binding.type == typeof(Animator) && binding.path == "") @@ -276,13 +208,29 @@ namespace nadena.dev.modular_avatar.animation } private AnimationClip ApplyMappingsToClip(AnimationClip originalClip, - Dictionary clipCache = null) + Dictionary clipCache) { if (originalClip == null) return null; if (clipCache != null && clipCache.TryGetValue(originalClip, out var cachedClip)) return cachedClip; if (originalClip.IsProxyAnimation()) return originalClip; + var curveBindings = AnimationUtility.GetCurveBindings(originalClip); + var objectBindings = AnimationUtility.GetObjectReferenceCurveBindings(originalClip); + + bool hasMapping = false; + foreach (var binding in curveBindings.Concat(objectBindings)) + { + if (MapPath(binding) != binding.path) + { + hasMapping = true; + break; + } + } + + if (!hasMapping) return originalClip; + + var newClip = new AnimationClip(); newClip.name = originalClip.name; @@ -296,7 +244,7 @@ namespace nadena.dev.modular_avatar.animation after.ApplyModifiedPropertiesWithoutUndo(); // TODO - should we use direct SerializedObject manipulation to avoid missing script issues? - foreach (var binding in AnimationUtility.GetCurveBindings(originalClip)) + foreach (var binding in curveBindings) { var newBinding = binding; newBinding.path = MapPath(binding); @@ -304,7 +252,7 @@ namespace nadena.dev.modular_avatar.animation AnimationUtility.GetEditorCurve(originalClip, binding)); } - foreach (var objBinding in AnimationUtility.GetObjectReferenceCurveBindings(originalClip)) + foreach (var objBinding in objectBindings) { var newBinding = objBinding; newBinding.path = MapPath(objBinding); @@ -326,36 +274,22 @@ namespace nadena.dev.modular_avatar.animation return newClip; } - public void OnDeactivate(BuildContext context) + internal void OnDeactivate(BuildContext context) { - context.AvatarDescriptor.baseAnimationLayers = - MapLayers(context, context.AvatarDescriptor.baseAnimationLayers); - context.AvatarDescriptor.specialAnimationLayers = - MapLayers(context, context.AvatarDescriptor.specialAnimationLayers); + Dictionary clipCache = new Dictionary(); + + _animationDatabase.ForeachClip(holder => + { + if (holder.CurrentClip is AnimationClip clip) + { + holder.CurrentClip = ApplyMappingsToClip(clip, clipCache); + } + }); foreach (var listener in context.AvatarRootObject.GetComponentsInChildren()) { listener.OnCommitObjectRenames(context, this); } } - - // TODO: port test AnimatesAddedBones from MA - - private VRCAvatarDescriptor.CustomAnimLayer[] MapLayers( - BuildContext buildContext, - VRCAvatarDescriptor.CustomAnimLayer[] layers - ) - { - if (layers == null) return null; - - for (int i = 0; i < layers.Length; i++) - { - var layer = layers[i]; - layer.animatorController = ApplyMappingsToAnimator(buildContext, layer.animatorController); - layers[i] = layer; - } - - return layers; - } } } \ No newline at end of file diff --git a/Packages/nadena.dev.modular-avatar/Editor/Animation/TrackObjectRenamesContext.cs.meta b/Packages/nadena.dev.modular-avatar/Editor/Animation/PathMappings.cs.meta similarity index 100% rename from Packages/nadena.dev.modular-avatar/Editor/Animation/TrackObjectRenamesContext.cs.meta rename to Packages/nadena.dev.modular-avatar/Editor/Animation/PathMappings.cs.meta diff --git a/Packages/nadena.dev.modular-avatar/Editor/BuildContext.cs b/Packages/nadena.dev.modular-avatar/Editor/BuildContext.cs index 57908f9d..5eb60dd5 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/BuildContext.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/BuildContext.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using nadena.dev.modular_avatar.animation; using UnityEditor; using UnityEditor.Animations; using UnityEngine; @@ -14,17 +15,23 @@ namespace nadena.dev.modular_avatar.core.editor internal readonly nadena.dev.ndmf.BuildContext PluginBuildContext; internal VRCAvatarDescriptor AvatarDescriptor => PluginBuildContext.AvatarDescriptor; - internal readonly AnimationDatabase AnimationDatabase = new AnimationDatabase(); + + internal AnimationDatabase AnimationDatabase => + PluginBuildContext.Extension().AnimationDatabase; + + internal PathMappings PathMappings => + PluginBuildContext.Extension().PathMappings; + internal UnityEngine.Object AssetContainer => PluginBuildContext.AssetContainer; private bool SaveImmediate = false; internal readonly Dictionary ClonedMenus = new Dictionary(); - + public static implicit operator BuildContext(ndmf.BuildContext ctx) => ctx.Extension().BuildContext; - + /// /// This dictionary overrides the _original contents_ of ModularAvatarMenuInstallers. Notably, this does not /// replace the source menu for the purposes of identifying any other MAMIs that might install to the same diff --git a/Packages/nadena.dev.modular-avatar/Editor/FixupPasses/FixupExpressionsMenuPass.cs b/Packages/nadena.dev.modular-avatar/Editor/FixupPasses/FixupExpressionsMenuPass.cs index d18ebc13..16c049fd 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/FixupPasses/FixupExpressionsMenuPass.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/FixupPasses/FixupExpressionsMenuPass.cs @@ -14,18 +14,18 @@ namespace nadena.dev.modular_avatar.core.editor { private const string DEFAULT_EXP_MENU_GUID = "024fb8ef5b3988c46b446863c92f4522"; private const string DEFAULT_EXP_PARAM_GUID = "03a6d797deb62f0429471c4e17ea99a7"; - + internal static void FixupExpressionsMenu(BuildContext context) { context.AvatarDescriptor.customExpressions = true; - + var expressionsMenu = context.AvatarDescriptor.expressionsMenu; if (expressionsMenu == null) { var defaultExpMenu = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath(DEFAULT_EXP_MENU_GUID) ); - + expressionsMenu = Object.Instantiate(defaultExpMenu); context.AvatarDescriptor.expressionsMenu = expressionsMenu; } @@ -35,20 +35,20 @@ namespace nadena.dev.modular_avatar.core.editor var defaultExpParam = AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath(DEFAULT_EXP_PARAM_GUID) ); - + context.AvatarDescriptor.expressionParameters = Object.Instantiate(defaultExpParam); } - + var parameters = context.AvatarDescriptor.expressionParameters.parameters ?? new VRCExpressionParameters.Parameter[0]; - var parameterNames = parameters.Select(p=> p.name).ToImmutableHashSet(); + var parameterNames = parameters.Select(p => p.name).ToImmutableHashSet(); - if (!Util.IsTemporaryAsset(expressionsMenu)) + if (!context.PluginBuildContext.IsTemporaryAsset(expressionsMenu)) { expressionsMenu = context.CloneMenu(expressionsMenu); context.AvatarDescriptor.expressionsMenu = expressionsMenu; } - + // Walk menu recursively var visitedMenus = new HashSet(); var iconMapping = new Dictionary(); @@ -68,7 +68,8 @@ namespace nadena.dev.modular_avatar.core.editor control.parameter.name = ""; } - foreach (var subParam in control.subParameters ?? Array.Empty()) + foreach (var subParam in control.subParameters ?? + Array.Empty()) { if (subParam != null && !string.IsNullOrEmpty(subParam.name) && @@ -93,7 +94,7 @@ namespace nadena.dev.modular_avatar.core.editor for (int i = 0; i < control.labels.Length; i++) { var label = control.labels[i]; - + if (label.icon != null) { if (!iconMapping.TryGetValue(label.icon, out var newIcon)) @@ -110,29 +111,29 @@ namespace nadena.dev.modular_avatar.core.editor } } - #if UNITY_ANDROID +#if UNITY_ANDROID private const TextureFormat TargetFormat = TextureFormat.ASTC_4x4; - #else +#else private const TextureFormat TargetFormat = TextureFormat.DXT5; - #endif - +#endif + private static Texture2D MaybeScaleIcon(BuildContext context, Texture2D original) { if (original.width <= 256 && original.height <= 256 && IsCompressedFormat(original.format)) { return original; } - + var newRatio = Math.Min(256f / original.width, 256f / original.height); var newWidth = Math.Min(256, Mathf.RoundToInt(original.width * newRatio)); var newHeight = Math.Min(256, Mathf.RoundToInt(original.height * newRatio)); var newTex = new Texture2D(newWidth, newHeight, TextureFormat.RGBA32, true); context.SaveAsset(newTex); - + var tmpRenderTex = RenderTexture.GetTemporary(newWidth, newHeight, 0, RenderTextureFormat.ARGB32); var originalActiveRenderTex = RenderTexture.active; - + try { Graphics.Blit(original, tmpRenderTex); diff --git a/Packages/nadena.dev.modular-avatar/Editor/MergeArmatureHook.cs b/Packages/nadena.dev.modular-avatar/Editor/MergeArmatureHook.cs index 6352f77a..3ee53f67 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/MergeArmatureHook.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/MergeArmatureHook.cs @@ -42,7 +42,8 @@ namespace nadena.dev.modular_avatar.core.editor private BuildContext context; private BoneDatabase BoneDatabase = new BoneDatabase(); - private TrackObjectRenamesContext PathMappings => frameworkContext.Extension(); + private PathMappings PathMappings => frameworkContext.Extension() + .PathMappings; private HashSet mergedObjects = new HashSet(); private HashSet thisPassAdded = new HashSet(); diff --git a/Packages/nadena.dev.modular-avatar/Editor/MeshRetargeter.cs b/Packages/nadena.dev.modular-avatar/Editor/MeshRetargeter.cs index 2eb54555..154e9ee9 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/MeshRetargeter.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/MeshRetargeter.cs @@ -84,10 +84,10 @@ namespace nadena.dev.modular_avatar.core.editor internal class RetargetMeshes { private BoneDatabase _boneDatabase; - private TrackObjectRenamesContext _pathTracker; + private PathMappings _pathTracker; internal void OnPreprocessAvatar(GameObject avatarGameObject, BoneDatabase boneDatabase, - TrackObjectRenamesContext pathMappings) + PathMappings pathMappings) { this._boneDatabase = boneDatabase; this._pathTracker = pathMappings; diff --git a/Packages/nadena.dev.modular-avatar/Editor/PluginDefinition/PluginDefinition.cs b/Packages/nadena.dev.modular-avatar/Editor/PluginDefinition/PluginDefinition.cs index 7d93cccc..bf9a6e3d 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/PluginDefinition/PluginDefinition.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/PluginDefinition/PluginDefinition.cs @@ -36,7 +36,7 @@ namespace nadena.dev.modular_avatar.core.editor.plugin seq.Run(RenameParametersPluginPass.Instance); seq.Run(MergeAnimatorPluginPass.Instance); seq.Run(MenuInstallPluginPass.Instance); - seq.WithRequiredExtension(typeof(TrackObjectRenamesContext), _s2 => + seq.WithRequiredExtension(typeof(AnimationServicesContext), _s2 => { seq.Run(MergeArmaturePluginPass.Instance); seq.Run(BoneProxyPluginPass.Instance); @@ -45,8 +45,8 @@ namespace nadena.dev.modular_avatar.core.editor.plugin ctx => new WorldFixedObjectProcessor(ctx.AvatarDescriptor).Process(ctx) ); seq.Run(ReplaceObjectPluginPass.Instance); + seq.Run(BlendshapeSyncAnimationPluginPass.Instance); }); - seq.Run(BlendshapeSyncAnimationPluginPass.Instance); seq.Run(PhysbonesBlockerPluginPass.Instance); seq.Run("Fixup Expressions Menu", ctx => { @@ -170,11 +170,7 @@ namespace nadena.dev.modular_avatar.core.editor.plugin { protected override void Execute(ndmf.BuildContext context) { - // The animation database is currently only used by the merge armature hook; it should probably become - // an extension context instead. - MAContext(context).AnimationDatabase.Bootstrap(context.AvatarDescriptor); new MergeArmatureHook().OnPreprocessAvatar(context, context.AvatarRootObject); - MAContext(context).AnimationDatabase.Commit(); } } diff --git a/Packages/nadena.dev.modular-avatar/Editor/RenameParametersHook.cs b/Packages/nadena.dev.modular-avatar/Editor/RenameParametersHook.cs index 0b4882b5..11a0336a 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/RenameParametersHook.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/RenameParametersHook.cs @@ -232,7 +232,7 @@ namespace nadena.dev.modular_avatar.core.editor var queue = new Queue(); // Deep clone the animator - if (!Util.IsTemporaryAsset(controller)) + if (!_context.PluginBuildContext.IsTemporaryAsset(controller)) { controller = _context.DeepCloneAnimator(controller); } diff --git a/Packages/nadena.dev.modular-avatar/Editor/ReplaceObjectPass.cs b/Packages/nadena.dev.modular-avatar/Editor/ReplaceObjectPass.cs index a14c7fa7..7d13e772 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/ReplaceObjectPass.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/ReplaceObjectPass.cs @@ -123,7 +123,7 @@ namespace nadena.dev.modular_avatar.core.editor } } - _buildContext.Extension() + _buildContext.Extension().PathMappings .ReplaceObject(original, replacement); // Destroy original diff --git a/Packages/nadena.dev.modular-avatar/Editor/Util.cs b/Packages/nadena.dev.modular-avatar/Editor/Util.cs index 76316e78..d205ddda 100644 --- a/Packages/nadena.dev.modular-avatar/Editor/Util.cs +++ b/Packages/nadena.dev.modular-avatar/Editor/Util.cs @@ -190,15 +190,6 @@ namespace nadena.dev.modular_avatar.core.editor }; } - public static bool IsTemporaryAsset(Object obj) - { - var path = AssetDatabase.GetAssetPath(obj); - var generatedAssetsFolder = OverridePath ?? generatedAssetsPath; - - return !EditorUtility.IsPersistent(obj) || string.IsNullOrEmpty(path) || - path.StartsWith(generatedAssetsFolder + "/"); - } - public static Type FindType(string typeName) { Type avatarValidation = null;