From f7e574654ff7cb4fdb0c9d0352e8057a9c8403eb Mon Sep 17 00:00:00 2001 From: bd_ Date: Fri, 8 Mar 2024 00:59:04 -0800 Subject: [PATCH 01/10] fix: parent scale ignored in Scale Adjuster (#744) Closes: #740 --- .../ModularAvatarScaleAdjuster.cs | 70 ++++++++++++++----- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/Runtime/ScaleAdjuster/ModularAvatarScaleAdjuster.cs b/Runtime/ScaleAdjuster/ModularAvatarScaleAdjuster.cs index 33f90a5b..1b8dbbae 100644 --- a/Runtime/ScaleAdjuster/ModularAvatarScaleAdjuster.cs +++ b/Runtime/ScaleAdjuster/ModularAvatarScaleAdjuster.cs @@ -34,7 +34,7 @@ namespace nadena.dev.modular_avatar.core [SerializeField] [FormerlySerializedAs("scaleProxy")] internal Transform legacyScaleProxy; - internal Transform scaleProxyParent, scaleProxyChild; + internal Transform scaleProxyChild; [NonSerialized] private bool initialized = false; @@ -56,15 +56,14 @@ namespace nadena.dev.modular_avatar.core { if (PrefabUtility.IsPartOfPrefabAsset(this)) return; - if (scaleProxyParent == null || initialized == false) + if (scaleProxyChild == null || initialized == false) { InitializeProxy(); } + UpdateProxyParent(scaleProxyChild, transform); + var xform = transform; - scaleProxyParent.position = transform.position; - scaleProxyParent.rotation = transform.rotation; - scaleProxyParent.localScale = transform.localScale; scaleProxyChild.localScale = m_Scale; ProxyManager.RegisterBone(xform, scaleProxyChild); @@ -76,27 +75,60 @@ namespace nadena.dev.modular_avatar.core } } + private void UpdateProxyParent(Transform proxyChild, Transform trueParent) + { + while (trueParent != null) + { + Transform parent = proxyChild.parent; + if (parent == null) + { + GameObject obj = new GameObject(); + proxyChild.transform.SetParent(obj.transform, false); + #if MODULAR_AVATAR_DEBUG_HIDDEN + obj.hideFlags = HideFlags.DontSave; + #else + obj.hideFlags = HideFlags.HideAndDontSave; + #endif + parent = obj.transform; + + if (obj.scene != gameObject.scene && gameObject.scene.IsValid()) + { + SceneManager.MoveGameObjectToScene(obj, gameObject.scene); + } + } + + parent.gameObject.name = "Proxy object for " + trueParent.gameObject.name; + parent.localPosition = trueParent.localPosition; + parent.localRotation = trueParent.localRotation; + parent.localScale = trueParent.localScale; + + proxyChild = parent; + trueParent = trueParent.parent; + } + + if (proxyChild.parent != null) + { + // Reparent to root + proxyChild.SetParent(null, false); + + // Destroy old hierarchy + Transform parent = proxyChild.parent; + while (parent.parent != null) parent = parent.parent; + DestroyImmediate(parent.gameObject); + } + } + private void InitializeProxy() { - if (scaleProxyParent == null) + if (scaleProxyChild == null) { - scaleProxyParent = new GameObject(gameObject.name + " (Scale Proxy)").transform; scaleProxyChild = new GameObject("Child").transform; - scaleProxyChild.transform.SetParent(scaleProxyParent, false); - #if MODULAR_AVATAR_DEBUG_HIDDEN - scaleProxyParent.gameObject.hideFlags = HideFlags.DontSave; scaleProxyChild.gameObject.hideFlags = HideFlags.DontSave; #else - scaleProxyParent.gameObject.hideFlags = HideFlags.HideAndDontSave; scaleProxyChild.gameObject.hideFlags = HideFlags.HideAndDontSave; #endif - - if (scaleProxyParent.gameObject.scene != gameObject.scene && gameObject.scene.IsValid()) - { - SceneManager.MoveGameObjectToScene(scaleProxyParent.gameObject, gameObject.scene); - } } initialized = true; @@ -106,9 +138,11 @@ namespace nadena.dev.modular_avatar.core { ProxyManager.UnregisterAdjuster(this); - if (scaleProxyParent != null) + if (scaleProxyChild != null) { - DestroyImmediate(scaleProxyParent.gameObject); + Transform parent = scaleProxyChild.parent; + while (parent.parent != null) parent = parent.parent; + DestroyImmediate(parent.gameObject); } if (transform != null) From fcc3752bcc378df72951a0067170af480f954ae3 Mon Sep 17 00:00:00 2001 From: bd_ Date: Fri, 8 Mar 2024 00:59:13 -0800 Subject: [PATCH 02/10] fix: double free message from armature lock (#745) Closes: #741 --- Runtime/ArmatureAwase/ArmatureLockOperator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Runtime/ArmatureAwase/ArmatureLockOperator.cs b/Runtime/ArmatureAwase/ArmatureLockOperator.cs index b4e113d1..510d0cf3 100644 --- a/Runtime/ArmatureAwase/ArmatureLockOperator.cs +++ b/Runtime/ArmatureAwase/ArmatureLockOperator.cs @@ -212,7 +212,7 @@ namespace nadena.dev.modular_avatar.core.armature_lock { // Initial setup failed; roll things back job.IsValid = false; - RemoveJob(job); + job.Dispose(); } } From d85bbb257c45ccf5bf34bb680f09d5e71de648fe Mon Sep 17 00:00:00 2001 From: bd_ Date: Fri, 8 Mar 2024 00:59:21 -0800 Subject: [PATCH 03/10] fix: nullref from Setup Outfit on non-humanoid rigs (#746) Closes: #742 --- Editor/EasySetupOutfit.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Editor/EasySetupOutfit.cs b/Editor/EasySetupOutfit.cs index 1afbbcc3..59ed6bef 100644 --- a/Editor/EasySetupOutfit.cs +++ b/Editor/EasySetupOutfit.cs @@ -386,8 +386,8 @@ namespace nadena.dev.modular_avatar.core.editor outfitHips = outfitAnimator.isHuman ? outfitAnimator.GetBoneTransform(HumanBodyBones.Hips)?.gameObject : null; - - if (outfitHips.transform.parent == outfitRoot.transform) + + if (outfitHips != null && outfitHips.transform.parent == outfitRoot.transform) { // Sometimes broken rigs can have the hips as a direct child of the root, instead of having // an intermediate Armature object. We do not currently support this kind of rig, and so we'll From 95a686609d8eb173cbc7ac8b7c4aaa00f7c9fca5 Mon Sep 17 00:00:00 2001 From: bd_ Date: Fri, 8 Mar 2024 00:59:30 -0800 Subject: [PATCH 04/10] fix: Visible Head Accessory breaks transform animations (#747) Closes: #743 --- Editor/VisibleHeadAccessoryProcessor.cs | 72 +- UnitTests~/VisibleHeadAccessoryTest.meta | 3 + .../VisibleHeadAccessoryTest/VHA_anim.anim | 461 +++++++++++ .../VHA_anim.anim.meta | 8 + .../VHA_controller.controller | 72 ++ .../VHA_controller.controller.meta | 8 + .../VHA_shapell.prefab | 718 ++++++++++++++++++ .../VHA_shapell.prefab.meta | 7 + .../VisibleHeadAccessoryTest.cs | 58 ++ .../VisibleHeadAccessoryTest.cs.meta | 3 + 10 files changed, 1407 insertions(+), 3 deletions(-) create mode 100644 UnitTests~/VisibleHeadAccessoryTest.meta create mode 100644 UnitTests~/VisibleHeadAccessoryTest/VHA_anim.anim create mode 100644 UnitTests~/VisibleHeadAccessoryTest/VHA_anim.anim.meta create mode 100644 UnitTests~/VisibleHeadAccessoryTest/VHA_controller.controller create mode 100644 UnitTests~/VisibleHeadAccessoryTest/VHA_controller.controller.meta create mode 100644 UnitTests~/VisibleHeadAccessoryTest/VHA_shapell.prefab create mode 100644 UnitTests~/VisibleHeadAccessoryTest/VHA_shapell.prefab.meta create mode 100644 UnitTests~/VisibleHeadAccessoryTest/VisibleHeadAccessoryTest.cs create mode 100644 UnitTests~/VisibleHeadAccessoryTest/VisibleHeadAccessoryTest.cs.meta diff --git a/Editor/VisibleHeadAccessoryProcessor.cs b/Editor/VisibleHeadAccessoryProcessor.cs index a2b78d34..dad2a4c0 100644 --- a/Editor/VisibleHeadAccessoryProcessor.cs +++ b/Editor/VisibleHeadAccessoryProcessor.cs @@ -1,13 +1,20 @@ -using System.Collections.Generic; +#region + +using System; +using System.Collections.Generic; using System.Collections.Immutable; using nadena.dev.modular_avatar.editor.ErrorReporting; +using UnityEditor; using UnityEngine; using UnityEngine.Animations; +using Object = UnityEngine.Object; #if MA_VRCSDK3_AVATARS using VRC.SDK3.Dynamics.PhysBone.Components; #endif +#endregion + namespace nadena.dev.modular_avatar.core.editor { internal class VisibleHeadAccessoryValidation @@ -95,6 +102,8 @@ namespace nadena.dev.modular_avatar.core.editor private HashSet _visibleBones = new HashSet(); private Transform _proxyHead; + private Dictionary _boneShims = new Dictionary(); + public VisibleHeadAccessoryProcessor(BuildContext context) { _context = context; @@ -135,9 +144,9 @@ namespace nadena.dev.modular_avatar.core.editor if (_validator.Validate(target) == VisibleHeadAccessoryValidation.ReadyStatus.Ready) { - var proxy = CreateProxy(); + var shim = CreateShim(target.transform.parent); - target.transform.SetParent(proxy, true); + target.transform.SetParent(shim, true); didWork = true; } @@ -148,6 +157,8 @@ namespace nadena.dev.modular_avatar.core.editor { _visibleBones.Add(xform); } + + ProcessAnimations(); } Object.DestroyImmediate(target); @@ -155,6 +166,61 @@ namespace nadena.dev.modular_avatar.core.editor return didWork; } + private void ProcessAnimations() + { + var animdb = _context.AnimationDatabase; + var paths = _context.PathMappings; + Dictionary pathMappings = new Dictionary(); + + foreach (var kvp in _boneShims) + { + var orig = paths.GetObjectIdentifier(kvp.Key.gameObject); + var shim = paths.GetObjectIdentifier(kvp.Value.gameObject); + + pathMappings[orig] = shim; + } + + animdb.ForeachClip(motion => + { + if (!(motion.CurrentClip is AnimationClip clip)) return; + + var bindings = AnimationUtility.GetCurveBindings(clip); + foreach (var binding in bindings) + { + if (binding.type != typeof(Transform)) continue; + if (!pathMappings.TryGetValue(binding.path, out var newPath)) continue; + + var newBinding = binding; + newBinding.path = newPath; + AnimationUtility.SetEditorCurve(clip, newBinding, AnimationUtility.GetEditorCurve(clip, binding)); + } + }); + } + + private Transform CreateShim(Transform target) + { + if (_boneShims.TryGetValue(target.transform, out var shim)) return shim; + + if (target == _headBone) return CreateProxy(); + if (target.parent == null) + { + // parent is not the head bone...? + throw new ArgumentException("Failed to find head bone"); + } + + var parentShim = CreateShim(target.parent); + + GameObject obj = new GameObject(target.gameObject.name); + obj.transform.SetParent(parentShim, false); + obj.transform.localPosition = target.localPosition; + obj.transform.localRotation = target.localRotation; + obj.transform.localScale = target.localScale; + + _boneShims[target] = obj.transform; + + return obj.transform; + } + private Transform CreateProxy() { if (_proxyHead != null) return _proxyHead; diff --git a/UnitTests~/VisibleHeadAccessoryTest.meta b/UnitTests~/VisibleHeadAccessoryTest.meta new file mode 100644 index 00000000..5acf5d82 --- /dev/null +++ b/UnitTests~/VisibleHeadAccessoryTest.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 685a22a434b643cc9425bad359b53896 +timeCreated: 1709886464 \ No newline at end of file diff --git a/UnitTests~/VisibleHeadAccessoryTest/VHA_anim.anim b/UnitTests~/VisibleHeadAccessoryTest/VHA_anim.anim new file mode 100644 index 00000000..e531a691 --- /dev/null +++ b/UnitTests~/VisibleHeadAccessoryTest/VHA_anim.anim @@ -0,0 +1,461 @@ +%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: VHA_anim + serializedVersion: 7 + m_Legacy: 0 + m_Compressed: 0 + m_UseHighQualityCurve: 1 + m_RotationCurves: [] + m_CompressedRotationCurves: [] + m_EulerCurves: + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: {x: 0, y: 0, z: 0} + inSlope: {x: 0, y: 0, z: Infinity} + outSlope: {x: 0, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 1 + value: {x: 0, y: 360, z: 0} + inSlope: {x: 0, y: 0, z: 0} + outSlope: {x: 0, y: Infinity, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + path: O1/O2 + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: {x: 0, y: 0, z: 0} + inSlope: {x: 0, y: 0, z: 0} + outSlope: {x: 0, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0, y: 0.33333334, z: 0.33333334} + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + path: O1/O2/Cube + m_PositionCurves: + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: {x: 0.2, y: 0, z: 0.257} + inSlope: {x: 0, y: 0, z: 0} + outSlope: {x: 0, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + - serializedVersion: 3 + time: 1 + value: {x: -0.2, y: 0, z: 0.257} + inSlope: {x: 0, y: 0, z: 0} + outSlope: {x: 0, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334} + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + path: O1 + m_ScaleCurves: [] + m_FloatCurves: [] + 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: 1743143183 + attribute: 1 + script: {fileID: 0} + typeID: 4 + customType: 0 + isPPtrCurve: 0 + isIntCurve: 0 + isSerializeReferenceCurve: 0 + - serializedVersion: 2 + path: 3627132118 + attribute: 4 + script: {fileID: 0} + typeID: 4 + customType: 4 + isPPtrCurve: 0 + isIntCurve: 0 + isSerializeReferenceCurve: 0 + - serializedVersion: 2 + path: 2630830665 + attribute: 4 + script: {fileID: 0} + typeID: 4 + customType: 4 + isPPtrCurve: 0 + isIntCurve: 0 + isSerializeReferenceCurve: 0 + pptrCurveMapping: [] + m_AnimationClipSettings: + serializedVersion: 2 + m_AdditiveReferencePoseClip: {fileID: 0} + m_AdditiveReferencePoseTime: 0 + m_StartTime: 0 + m_StopTime: 1 + 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: + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.2 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: -0.2 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.x + path: O1 + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.y + path: O1 + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0.257 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0.257 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.z + path: O1 + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: localEulerAnglesRaw.x + path: O1/O2 + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 360 + inSlope: 0 + outSlope: Infinity + tangentMode: 97 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: localEulerAnglesRaw.y + path: O1/O2 + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: Infinity + outSlope: 0 + tangentMode: 7 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: localEulerAnglesRaw.z + path: O1/O2 + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: localEulerAnglesRaw.x + path: O1/O2/Cube + classID: 4 + script: {fileID: 0} + flags: 16 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: localEulerAnglesRaw.y + path: O1/O2/Cube + classID: 4 + script: {fileID: 0} + flags: 16 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: localEulerAnglesRaw.z + path: O1/O2/Cube + classID: 4 + script: {fileID: 0} + flags: 16 + m_EulerEditorCurves: + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalEulerAngles.x + path: O1/O2 + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalEulerAngles.y + path: O1/O2 + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalEulerAngles.z + path: O1/O2 + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalEulerAngles.x + path: O1/O2/Cube + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalEulerAngles.y + path: O1/O2/Cube + classID: 4 + script: {fileID: 0} + flags: 0 + - serializedVersion: 2 + curve: + serializedVersion: 2 + m_Curve: [] + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalEulerAngles.z + path: O1/O2/Cube + classID: 4 + script: {fileID: 0} + flags: 0 + m_HasGenericRootTransform: 0 + m_HasMotionFloatCurves: 0 + m_Events: [] diff --git a/UnitTests~/VisibleHeadAccessoryTest/VHA_anim.anim.meta b/UnitTests~/VisibleHeadAccessoryTest/VHA_anim.anim.meta new file mode 100644 index 00000000..6bd00fcf --- /dev/null +++ b/UnitTests~/VisibleHeadAccessoryTest/VHA_anim.anim.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 395bf1adee3f366408b42537fb6a0323 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 7400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnitTests~/VisibleHeadAccessoryTest/VHA_controller.controller b/UnitTests~/VisibleHeadAccessoryTest/VHA_controller.controller new file mode 100644 index 00000000..2a5f5c56 --- /dev/null +++ b/UnitTests~/VisibleHeadAccessoryTest/VHA_controller.controller @@ -0,0 +1,72 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1102 &-8909200628966768515 +AnimatorState: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: New Animation + 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: 395bf1adee3f366408b42537fb6a0323, type: 2} + m_Tag: + m_SpeedParameter: + m_MirrorParameter: + m_CycleOffsetParameter: + m_TimeParameter: +--- !u!91 &9100000 +AnimatorController: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: VHA_controller + serializedVersion: 5 + m_AnimatorParameters: [] + m_AnimatorLayers: + - serializedVersion: 5 + m_Name: test + m_StateMachine: {fileID: 4222333013491571632} + 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!1107 &4222333013491571632 +AnimatorStateMachine: + serializedVersion: 6 + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: test + m_ChildStates: + - serializedVersion: 1 + m_State: {fileID: -8909200628966768515} + m_Position: {x: 299, y: 442, 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: -8909200628966768515} diff --git a/UnitTests~/VisibleHeadAccessoryTest/VHA_controller.controller.meta b/UnitTests~/VisibleHeadAccessoryTest/VHA_controller.controller.meta new file mode 100644 index 00000000..d9d83748 --- /dev/null +++ b/UnitTests~/VisibleHeadAccessoryTest/VHA_controller.controller.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8c6b7f6e97e71aa498d41e7fd515d5e4 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 9100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnitTests~/VisibleHeadAccessoryTest/VHA_shapell.prefab b/UnitTests~/VisibleHeadAccessoryTest/VHA_shapell.prefab new file mode 100644 index 00000000..e35db2ce --- /dev/null +++ b/UnitTests~/VisibleHeadAccessoryTest/VHA_shapell.prefab @@ -0,0 +1,718 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &612357985844559561 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6941655322303215058} + m_Layer: 0 + m_Name: O1 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6941655322303215058 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 612357985844559561} + serializedVersion: 2 + m_LocalRotation: {x: 0.0049364693, y: 0.7070896, z: -0.0049364693, w: 0.7070896} + m_LocalPosition: {x: 0, y: 0, z: 0.257} + m_LocalScale: {x: 0.5050202, y: 0.50501996, z: 0.5050202} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 6119058143242962149} + m_Father: {fileID: 998838968424483778} + m_LocalEulerAnglesHint: {x: 0.8, y: 90, z: 0} +--- !u!1 &7512821753243497707 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6119058143242962149} + - component: {fileID: 2220748906585489117} + m_Layer: 0 + m_Name: O2 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6119058143242962149 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7512821753243497707} + serializedVersion: 2 + m_LocalRotation: {x: 0.000000059604645, y: 2.7918645e-10, z: -4.3299586e-11, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 3679325629687017410} + m_Father: {fileID: 6941655322303215058} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2220748906585489117 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7512821753243497707} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1631200402, guid: 2a2c05204084d904aa4945ccff20d8e5, type: 3} + m_Name: + m_EditorClassIdentifier: + rootTransform: {fileID: 0} + shapeType: 0 + insideBounds: 0 + radius: 0.5 + height: 2 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + bonesAsSpheres: 0 +--- !u!1 &8427497452436561553 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3679325629687017410} + - component: {fileID: 5025199119919284425} + - component: {fileID: 6601260729858082086} + - component: {fileID: 379020477460227636} + - component: {fileID: 5368776189515489596} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &3679325629687017410 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8427497452436561553} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.049999997, y: 0.049999997, z: 0.049999997} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 6119058143242962149} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &5025199119919284425 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8427497452436561553} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &6601260729858082086 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8427497452436561553} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!65 &379020477460227636 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8427497452436561553} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!114 &5368776189515489596 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8427497452436561553} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 33dac8cfeaeb4c399ddd90597f849f70, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1001 &998838968424616154 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 100220, guid: 1418fcab2d94f9d4982cd714b598900f, type: 3} + propertyPath: m_Name + value: VHA_shapell + objectReference: {fileID: 0} + - target: {fileID: 400220, guid: 1418fcab2d94f9d4982cd714b598900f, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 400220, guid: 1418fcab2d94f9d4982cd714b598900f, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 400220, guid: 1418fcab2d94f9d4982cd714b598900f, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 400220, guid: 1418fcab2d94f9d4982cd714b598900f, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 400220, guid: 1418fcab2d94f9d4982cd714b598900f, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 400220, guid: 1418fcab2d94f9d4982cd714b598900f, type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 400220, guid: 1418fcab2d94f9d4982cd714b598900f, type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 400220, guid: 1418fcab2d94f9d4982cd714b598900f, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 400220, guid: 1418fcab2d94f9d4982cd714b598900f, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 400220, guid: 1418fcab2d94f9d4982cd714b598900f, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: + - targetCorrespondingSourceObject: {fileID: 400152, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + insertIndex: -1 + addedObject: {fileID: 6941655322303215058} + m_AddedComponents: + - targetCorrespondingSourceObject: {fileID: 100220, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + insertIndex: -1 + addedObject: {fileID: 327153454849042022} + - targetCorrespondingSourceObject: {fileID: 100220, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + insertIndex: -1 + addedObject: {fileID: -8174728745731488521} + - targetCorrespondingSourceObject: {fileID: 100220, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + insertIndex: -1 + addedObject: {fileID: 3115850923318163834} + - targetCorrespondingSourceObject: {fileID: 100152, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + insertIndex: -1 + addedObject: {fileID: 8862200023606039557} + - targetCorrespondingSourceObject: {fileID: 100152, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + insertIndex: -1 + addedObject: {fileID: 5357983429381432312} + m_SourcePrefab: {fileID: 100100000, guid: 1418fcab2d94f9d4982cd714b598900f, type: 3} +--- !u!4 &998838968424483396 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 400030, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + m_PrefabInstance: {fileID: 998838968424616154} + m_PrefabAsset: {fileID: 0} +--- !u!4 &998838968424483640 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 400354, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + m_PrefabInstance: {fileID: 998838968424616154} + m_PrefabAsset: {fileID: 0} +--- !u!4 &998838968424483646 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 400356, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + m_PrefabInstance: {fileID: 998838968424616154} + m_PrefabAsset: {fileID: 0} +--- !u!4 &998838968424483720 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 400210, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + m_PrefabInstance: {fileID: 998838968424616154} + m_PrefabAsset: {fileID: 0} +--- !u!4 &998838968424483722 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 400208, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + m_PrefabInstance: {fileID: 998838968424616154} + m_PrefabAsset: {fileID: 0} +--- !u!4 &998838968424483736 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 400194, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + m_PrefabInstance: {fileID: 998838968424616154} + m_PrefabAsset: {fileID: 0} +--- !u!4 &998838968424483738 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 400192, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + m_PrefabInstance: {fileID: 998838968424616154} + m_PrefabAsset: {fileID: 0} +--- !u!4 &998838968424483778 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 400152, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + m_PrefabInstance: {fileID: 998838968424616154} + m_PrefabAsset: {fileID: 0} +--- !u!4 &998838968424483780 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 400158, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + m_PrefabInstance: {fileID: 998838968424616154} + m_PrefabAsset: {fileID: 0} +--- !u!4 &998838968424483782 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 400156, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + m_PrefabInstance: {fileID: 998838968424616154} + m_PrefabAsset: {fileID: 0} +--- !u!4 &998838968424483788 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 400150, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + m_PrefabInstance: {fileID: 998838968424616154} + m_PrefabAsset: {fileID: 0} +--- !u!4 &998838968424483790 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 400148, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + m_PrefabInstance: {fileID: 998838968424616154} + m_PrefabAsset: {fileID: 0} +--- !u!4 &998838968424483824 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 400170, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + m_PrefabInstance: {fileID: 998838968424616154} + m_PrefabAsset: {fileID: 0} +--- !u!4 &998838968424483830 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 400172, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + m_PrefabInstance: {fileID: 998838968424616154} + m_PrefabAsset: {fileID: 0} +--- !u!1 &998838968424716198 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 100220, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + m_PrefabInstance: {fileID: 998838968424616154} + m_PrefabAsset: {fileID: 0} +--- !u!114 &327153454849042022 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 998838968424716198} + 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: 0 + baseAnimationLayers: + - isEnabled: 0 + type: 0 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + - isEnabled: 0 + type: 2 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + - isEnabled: 0 + type: 3 + 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: 0} + mask: {fileID: 0} + isDefault: 1 + 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: 998838968424483778} + radius: 0.056251545 + height: 0 + position: {x: -0.000000032606955, y: 0.07031424, z: 0.00000009799261} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_torso: + isMirrored: 1 + state: 0 + transform: {fileID: 998838968424483396} + radius: 0.07861339 + height: 0.3628603 + position: {x: 0.000017229731, y: 0.0038627048, z: -0.008662622} + rotation: {x: -0.023554876, y: 0, z: -0.000046907786, w: 0.99972254} + collider_footR: + isMirrored: 1 + state: 0 + transform: {fileID: 998838968424483646} + radius: 0.06282255 + 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: 998838968424483640} + radius: 0.06281703 + 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: 998838968424483788} + radius: 0.017221563 + height: 0.06888625 + position: {x: 0.001446783, y: 0.058534563, z: 0.0003410885} + rotation: {x: 0.0005407688, y: 0, z: -0.715791, w: 0.6983144} + collider_handL: + isMirrored: 1 + state: 0 + transform: {fileID: 998838968424483790} + radius: 0.017564295 + height: 0.07025718 + position: {x: -0.0014467348, y: 0.059689727, z: 0.0011713395} + rotation: {x: -0.0006730006, y: 0, z: 0.715616, w: 0.6984936} + collider_fingerIndexL: + isMirrored: 1 + state: 0 + transform: {fileID: 998838968424483782} + radius: 0.0051649124 + height: 0.025824562 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerMiddleL: + isMirrored: 1 + state: 0 + transform: {fileID: 998838968424483738} + radius: 0.0053481604 + height: 0.0267408 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerRingL: + isMirrored: 1 + state: 0 + transform: {fileID: 998838968424483722} + radius: 0.005303362 + height: 0.02651681 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerLittleL: + isMirrored: 1 + state: 0 + transform: {fileID: 998838968424483824} + radius: 0.004442837 + height: 0.022214185 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerIndexR: + isMirrored: 1 + state: 0 + transform: {fileID: 998838968424483780} + radius: 0.0051649334 + height: 0.025824666 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerMiddleR: + isMirrored: 1 + state: 0 + transform: {fileID: 998838968424483736} + radius: 0.0053481823 + height: 0.02674091 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerRingR: + isMirrored: 1 + state: 0 + transform: {fileID: 998838968424483720} + radius: 0.00530343 + height: 0.026517149 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerLittleR: + isMirrored: 1 + state: 0 + transform: {fileID: 998838968424483830} + radius: 0.0044428115 + height: 0.022214057 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} +--- !u!114 &-8174728745731488521 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 998838968424716198} + 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 &3115850923318163834 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 998838968424716198} + 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!1 &998838968424716258 stripped +GameObject: + m_CorrespondingSourceObject: {fileID: 100152, guid: 1418fcab2d94f9d4982cd714b598900f, + type: 3} + m_PrefabInstance: {fileID: 998838968424616154} + m_PrefabAsset: {fileID: 0} +--- !u!114 &8862200023606039557 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 998838968424716258} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1bb122659f724ebf85fe095ac02dc339, type: 3} + m_Name: + m_EditorClassIdentifier: + animator: {fileID: 9100000, guid: 8c6b7f6e97e71aa498d41e7fd515d5e4, type: 2} + layerType: 5 + deleteAttachedAnimator: 0 + pathMode: 0 + matchAvatarWriteDefaults: 0 + relativePathRoot: + referencePath: + layerPriority: 0 +--- !u!95 &5357983429381432312 +Animator: + serializedVersion: 5 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 998838968424716258} + m_Enabled: 1 + m_Avatar: {fileID: 0} + m_Controller: {fileID: 9100000, guid: 8c6b7f6e97e71aa498d41e7fd515d5e4, type: 2} + m_CullingMode: 0 + m_UpdateMode: 0 + m_ApplyRootMotion: 0 + m_LinearVelocityBlending: 0 + m_StabilizeFeet: 0 + m_WarningMessage: + m_HasTransformHierarchy: 1 + m_AllowConstantClipSamplingOptimization: 1 + m_KeepAnimatorStateOnDisable: 0 + m_WriteDefaultValuesOnDisable: 0 diff --git a/UnitTests~/VisibleHeadAccessoryTest/VHA_shapell.prefab.meta b/UnitTests~/VisibleHeadAccessoryTest/VHA_shapell.prefab.meta new file mode 100644 index 00000000..5704defe --- /dev/null +++ b/UnitTests~/VisibleHeadAccessoryTest/VHA_shapell.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b50cb5d9ccb8382478ee3142483398bf +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnitTests~/VisibleHeadAccessoryTest/VisibleHeadAccessoryTest.cs b/UnitTests~/VisibleHeadAccessoryTest/VisibleHeadAccessoryTest.cs new file mode 100644 index 00000000..147de6c8 --- /dev/null +++ b/UnitTests~/VisibleHeadAccessoryTest/VisibleHeadAccessoryTest.cs @@ -0,0 +1,58 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using modular_avatar_tests; +using nadena.dev.modular_avatar.core.editor; +using NUnit.Framework; +using UnityEditor; +using UnityEngine; +using UnityEngine.Animations; + +namespace UnitTests.VisibleHeadAccessoryTest +{ + internal class VisibleHeadAccessoryTest : TestBase + { + [Test] + [SuppressMessage("ReSharper", "Unity.InefficientPropertyAccess")] // false positive + public void Test() + { + var prefab = CreatePrefab("VHA_shapell.prefab"); + + var cubeObj = prefab.transform.Find( + "Armature/Hips/Spine/Chest/Neck/Head/O1/O2/Cube" + ); + var priorWorldPos = cubeObj.position; + var priorWorldRot = cubeObj.rotation; + + AvatarProcessor.ProcessAvatar(prefab); + + Assert.Less((cubeObj.position - priorWorldPos).magnitude, 0.001f); + Assert.Less(Quaternion.Angle(cubeObj.rotation, priorWorldRot), 0.001f); + + var fx_anim = findFxClip(prefab, "test"); + + var expectedBindings = new HashSet() + { + "Armature/Hips/Spine/Chest/Neck/Head/O1", + "Armature/Hips/Spine/Chest/Neck/Head/O1/O2", + "Armature/Hips/Spine/Chest/Neck/Head (FirstPersonVisible)/O1", + "Armature/Hips/Spine/Chest/Neck/Head (FirstPersonVisible)/O1/O2", + "Armature/Hips/Spine/Chest/Neck/Head (FirstPersonVisible)/O1/O2/Cube", + }.ToImmutableSortedSet(); + + var bindings = AnimationUtility.GetCurveBindings(fx_anim).Select(binding => binding.path) + .ToImmutableSortedSet(); + Assert.AreEqual(expectedBindings, bindings); + + var head = prefab.transform.Find("Armature/Hips/Spine/Chest/Neck/Head"); + var constraint = prefab.transform.Find("Armature/Hips/Spine/Chest/Neck/Head (FirstPersonVisible)") + .GetComponent(); + + Assert.AreEqual(head, constraint.GetSource(0).sourceTransform); + Assert.AreEqual(1, constraint.GetSource(0).weight); + Assert.AreEqual(new Vector3(0, 0, 0), constraint.translationOffsets[0]); + Assert.AreEqual(new Vector3(0, 0, 0), constraint.rotationOffsets[0]); + } + } +} \ No newline at end of file diff --git a/UnitTests~/VisibleHeadAccessoryTest/VisibleHeadAccessoryTest.cs.meta b/UnitTests~/VisibleHeadAccessoryTest/VisibleHeadAccessoryTest.cs.meta new file mode 100644 index 00000000..73c3342d --- /dev/null +++ b/UnitTests~/VisibleHeadAccessoryTest/VisibleHeadAccessoryTest.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c1ce51ca63454f34a9a679cd11f9de96 +timeCreated: 1709886599 \ No newline at end of file From 37e7ebcae1dc9f7ac92e0f3071f254adae90694f Mon Sep 17 00:00:00 2001 From: bd_ Date: Fri, 8 Mar 2024 20:25:43 +0900 Subject: [PATCH 05/10] 1.9.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index be10858c..7280ee56 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nadena.dev.modular-avatar", "displayName": "Modular Avatar", - "version": "1.9.5", + "version": "1.9.6", "unity": "2019.4", "description": "A suite of tools for assembling your avatar out of reusable components", "author": { From 01d24f68091f6a4b60a9c5e688bc2e5447ccaa0d Mon Sep 17 00:00:00 2001 From: Reina_Sakiria <99442371+ReinaS-64892@users.noreply.github.com> Date: Sat, 9 Mar 2024 17:57:15 +0900 Subject: [PATCH 06/10] fix: no purge MoveIndependently (#749) --- Editor/PluginDefinition/PluginDefinition.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Editor/PluginDefinition/PluginDefinition.cs b/Editor/PluginDefinition/PluginDefinition.cs index 8f99db5a..bb5307fd 100644 --- a/Editor/PluginDefinition/PluginDefinition.cs +++ b/Editor/PluginDefinition/PluginDefinition.cs @@ -84,6 +84,10 @@ namespace nadena.dev.modular_avatar.core.editor.plugin { UnityEngine.Object.DestroyImmediate(component); } + foreach (var component in ctx.AvatarRootTransform.GetComponentsInChildren(true)) + { + UnityEngine.Object.DestroyImmediate(component); + } }); #if MA_VRCSDK3_AVATARS seq.Run(PruneParametersPass.Instance); From 17e6c22335f79a3c418d75bf092fd1ec8b007196 Mon Sep 17 00:00:00 2001 From: bd_ Date: Sat, 9 Mar 2024 01:08:38 -0800 Subject: [PATCH 07/10] fix: potential null reference exceptions from ProxyManager (#750) * chore: fix incorrect namespace * fix: potential null reference exceptions from ProxyManager --- Runtime/ScaleAdjuster/ProxyManager.cs | 9 ++++----- Runtime/Util/ObjectIdentityComparer.cs | 8 ++++++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Runtime/ScaleAdjuster/ProxyManager.cs b/Runtime/ScaleAdjuster/ProxyManager.cs index 84749ad8..7956630f 100644 --- a/Runtime/ScaleAdjuster/ProxyManager.cs +++ b/Runtime/ScaleAdjuster/ProxyManager.cs @@ -3,13 +3,12 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using nadena.dev.modular_avatar.JacksonDunstan.NativeCollections; +using UnityEngine; +using UnityEngine.SceneManagement; #if UNITY_EDITOR using UnityEditor; using UnityEditor.SceneManagement; #endif -using UnityEngine; -using UnityEngine.SceneManagement; #endregion @@ -90,7 +89,7 @@ namespace nadena.dev.modular_avatar.core internal static ImmutableDictionary OriginalToProxyRenderer => _originalToReplacementRenderer; - internal static ImmutableHashSet RetainedObjects; + internal static ImmutableHashSet RetainedObjects = ImmutableHashSet.Empty; internal static bool ShouldRetain(GameObject obj) => RetainedObjects.Contains(obj); @@ -220,7 +219,7 @@ namespace nadena.dev.modular_avatar.core for (var i = 0; i < weights.Length; i++) { var bone = bones[weights[i].boneIndex]; - if (_capturedBones.ContainsKey(bone)) return true; + if (bone != null && _capturedBones.ContainsKey(bone)) return true; } return false; diff --git a/Runtime/Util/ObjectIdentityComparer.cs b/Runtime/Util/ObjectIdentityComparer.cs index 002f6395..80d47032 100644 --- a/Runtime/Util/ObjectIdentityComparer.cs +++ b/Runtime/Util/ObjectIdentityComparer.cs @@ -1,7 +1,11 @@ -using System.Collections.Generic; +#region + +using System.Collections.Generic; using System.Runtime.CompilerServices; -namespace nadena.dev.modular_avatar.JacksonDunstan.NativeCollections +#endregion + +namespace nadena.dev.modular_avatar { internal class ObjectIdentityComparer : IEqualityComparer { From e31a33b82c20c14fc5eff0abcb342b1b55d070f1 Mon Sep 17 00:00:00 2001 From: bd_ Date: Sat, 9 Mar 2024 01:51:14 -0800 Subject: [PATCH 08/10] chore: configure crowdin (#756) --- .../Localization/{en-us.json => en-US.json} | 0 .../{en-us.json.meta => en-US.json.meta} | 0 .../Localization/{ja-jp.json => ja-JP.json} | 0 .../{ja-jp.json.meta => ja-JP.json.meta} | 0 .../Localization/{ko-kr.json => ko-KR.json} | 0 .../{ko-kr.json.meta => ko-KR.json.meta} | 0 .../{zh-hans.json => zh-Hans.json} | 0 .../{zh-hans.json.meta => zh-Hans.json.meta} | 0 crowdin.yml | 127 ++++++++++++++++++ 9 files changed, 127 insertions(+) rename Editor/Localization/{en-us.json => en-US.json} (100%) rename Editor/Localization/{en-us.json.meta => en-US.json.meta} (100%) rename Editor/Localization/{ja-jp.json => ja-JP.json} (100%) rename Editor/Localization/{ja-jp.json.meta => ja-JP.json.meta} (100%) rename Editor/Localization/{ko-kr.json => ko-KR.json} (100%) rename Editor/Localization/{ko-kr.json.meta => ko-KR.json.meta} (100%) rename Editor/Localization/{zh-hans.json => zh-Hans.json} (100%) rename Editor/Localization/{zh-hans.json.meta => zh-Hans.json.meta} (100%) create mode 100644 crowdin.yml diff --git a/Editor/Localization/en-us.json b/Editor/Localization/en-US.json similarity index 100% rename from Editor/Localization/en-us.json rename to Editor/Localization/en-US.json diff --git a/Editor/Localization/en-us.json.meta b/Editor/Localization/en-US.json.meta similarity index 100% rename from Editor/Localization/en-us.json.meta rename to Editor/Localization/en-US.json.meta diff --git a/Editor/Localization/ja-jp.json b/Editor/Localization/ja-JP.json similarity index 100% rename from Editor/Localization/ja-jp.json rename to Editor/Localization/ja-JP.json diff --git a/Editor/Localization/ja-jp.json.meta b/Editor/Localization/ja-JP.json.meta similarity index 100% rename from Editor/Localization/ja-jp.json.meta rename to Editor/Localization/ja-JP.json.meta diff --git a/Editor/Localization/ko-kr.json b/Editor/Localization/ko-KR.json similarity index 100% rename from Editor/Localization/ko-kr.json rename to Editor/Localization/ko-KR.json diff --git a/Editor/Localization/ko-kr.json.meta b/Editor/Localization/ko-KR.json.meta similarity index 100% rename from Editor/Localization/ko-kr.json.meta rename to Editor/Localization/ko-KR.json.meta diff --git a/Editor/Localization/zh-hans.json b/Editor/Localization/zh-Hans.json similarity index 100% rename from Editor/Localization/zh-hans.json rename to Editor/Localization/zh-Hans.json diff --git a/Editor/Localization/zh-hans.json.meta b/Editor/Localization/zh-Hans.json.meta similarity index 100% rename from Editor/Localization/zh-hans.json.meta rename to Editor/Localization/zh-Hans.json.meta diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 00000000..05ae2e38 --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,127 @@ +# +# Your Crowdin credentials +# +"project_id": "" +"api_token": "" +"base_path": "." +"base_url": "https://api.crowdin.com" + +# +# Choose file structure in Crowdin +# e.g. true or false +# +"preserve_hierarchy": true + +# +# Files configuration +# +files: [ + { + # + # Source files filter + # e.g. "/resources/en/*.json" + # + "source": "/Editor/Localization/en-US.json", + + # + # Where translations will be placed + # e.g. "/resources/%two_letters_code%/%original_file_name%" + # + "translation": "/Editor/Localization/%locale%.json", + + # + # Files or directories for ignore + # e.g. ["/**/?.txt", "/**/[0-9].txt", "/**/*\?*.txt"] + # + # "ignore": [], + + # + # The dest allows you to specify a file name in Crowdin + # e.g. "/messages.json" + # + # "dest": "", + + # + # File type + # e.g. "json" + # + # "type": "", + + # + # The parameter "update_option" is optional. If it is not set, after the files update the translations for changed strings will be removed. Use to fix typos and for minor changes in the source strings + # e.g. "update_as_unapproved" or "update_without_changes" + # + # "update_option": "", + + # + # Start block (for XML only) + # + + # + # Defines whether to translate tags attributes. + # e.g. 0 or 1 (Default is 1) + # + # "translate_attributes": 1, + + # + # Defines whether to translate texts placed inside the tags. + # e.g. 0 or 1 (Default is 1) + # + # "translate_content": 1, + + # + # This is an array of strings, where each item is the XPaths to DOM element that should be imported + # e.g. ["/content/text", "/content/text[@value]"] + # + # "translatable_elements": [], + + # + # Defines whether to split long texts into smaller text segments + # e.g. 0 or 1 (Default is 1) + # + # "content_segmentation": 1, + + # + # End block (for XML only) + # + + # + # Start .properties block + # + + # + # Defines whether single quote should be escaped by another single quote or backslash in exported translations + # e.g. 0 or 1 or 2 or 3 (Default is 3) + # 0 - do not escape single quote; + # 1 - escape single quote by another single quote; + # 2 - escape single quote by backslash; + # 3 - escape single quote by another single quote only in strings containing variables ( {0} ). + # + # "escape_quotes": 3, + + # + # Defines whether any special characters (=, :, ! and #) should be escaped by backslash in exported translations. + # e.g. 0 or 1 (Default is 0) + # 0 - do not escape special characters + # 1 - escape special characters by a backslash + # + # "escape_special_characters": 0 + # + + # + # End .properties block + # + + # + # Does the first line contain header? + # e.g. true or false + # + # "first_line_contains_header": true, + + # + # for spreadsheets + # e.g. "identifier,source_phrase,context,uk,ru,fr" + # + # "scheme": "", + } +] \ No newline at end of file From 0ff1da073419c6324fe1e15adaaef22e7e38c33d Mon Sep 17 00:00:00 2001 From: bd_ Date: Sat, 9 Mar 2024 01:55:31 -0800 Subject: [PATCH 09/10] fix: type corrections not applied to substatemachine exit transitions (#751) Closes: #748 --- Editor/Animation/AnimatorCombiner.cs | 21 ++++++++++++++++-- .../TypeAdjustment/ConvertTransitionTypes.cs | 17 ++++++++++++++ .../TypeAdjustment/ac1.controller | 22 ++++++++++++++++++- 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/Editor/Animation/AnimatorCombiner.cs b/Editor/Animation/AnimatorCombiner.cs index 419de050..2b83849d 100644 --- a/Editor/Animation/AnimatorCombiner.cs +++ b/Editor/Animation/AnimatorCombiner.cs @@ -22,10 +22,13 @@ * SOFTWARE. */ +#region + using System; using System.Collections.Generic; using System.Linq; using nadena.dev.modular_avatar.editor.ErrorReporting; +using nadena.dev.ndmf; using nadena.dev.ndmf.util; using UnityEditor; using UnityEditor.Animations; @@ -37,11 +40,13 @@ using VRC.SDK3.Avatars.Components; using VRC.SDKBase; #endif +#endregion + namespace nadena.dev.modular_avatar.animation { internal class AnimatorCombiner { - private readonly ndmf.BuildContext _context; + private readonly BuildContext _context; private readonly AnimatorController _combined; private readonly DeepClone _deepClone; @@ -68,7 +73,7 @@ namespace nadena.dev.modular_avatar.animation public VRC_AnimatorLayerControl.BlendableLayer? BlendableLayer; #endif - public AnimatorCombiner(ndmf.BuildContext context, String assetName) + public AnimatorCombiner(BuildContext context, String assetName) { _combined = new AnimatorController(); if (context.AssetContainer != null && EditorUtility.IsPersistent(context.AssetContainer)) @@ -141,6 +146,18 @@ namespace nadena.dev.modular_avatar.animation .SelectMany(FixupTransition).ToArray(); asm.anyStateTransitions = asm.anyStateTransitions .SelectMany(FixupTransition).ToArray(); + + foreach (var stateMachine in asm.stateMachines) + { + var ssm = stateMachine.stateMachine; + + var stateMachineTransitions = asm.GetStateMachineTransitions(ssm); + if (stateMachineTransitions.Length > 0) + { + asm.SetStateMachineTransitions(ssm, + stateMachineTransitions.SelectMany(FixupTransition).ToArray()); + } + } } } } diff --git a/UnitTests~/MergeAnimatorTests/TypeAdjustment/ConvertTransitionTypes.cs b/UnitTests~/MergeAnimatorTests/TypeAdjustment/ConvertTransitionTypes.cs index a8ef66b9..0161235d 100644 --- a/UnitTests~/MergeAnimatorTests/TypeAdjustment/ConvertTransitionTypes.cs +++ b/UnitTests~/MergeAnimatorTests/TypeAdjustment/ConvertTransitionTypes.cs @@ -180,6 +180,23 @@ public class ConvertTransitionTypes : TestBase AssertTransitions(layer, "int", "eq1", 0, ("int", AnimatorConditionMode.Equals, 1f)); } + [Test] + public void SubStateMachineExitTransitions() + { + var prefab = CreatePrefab("ConvertTransitionTypes.prefab"); + + AvatarProcessor.ProcessAvatar(prefab); + + var layer = findFxLayer(prefab, "sub_state_machine"); + + var rootStateMachine = layer.stateMachine; + var ssm1 = layer.stateMachine.stateMachines[0].stateMachine; + var exitTransitions = rootStateMachine.GetStateMachineTransitions(ssm1); + + AssertSingleTransition(exitTransitions[0], ("int", AnimatorConditionMode.Greater, 0.1f)); + AssertSingleTransition(exitTransitions[1], ("int", AnimatorConditionMode.Less, -0.1f)); + } + [Test] public void CrossLayerTypeConsistency() { diff --git a/UnitTests~/MergeAnimatorTests/TypeAdjustment/ac1.controller b/UnitTests~/MergeAnimatorTests/TypeAdjustment/ac1.controller index 42d2465f..ba04b0c9 100644 --- a/UnitTests~/MergeAnimatorTests/TypeAdjustment/ac1.controller +++ b/UnitTests~/MergeAnimatorTests/TypeAdjustment/ac1.controller @@ -506,6 +506,23 @@ AnimatorState: m_MirrorParameter: m_CycleOffsetParameter: m_TimeParameter: +--- !u!1109 &-1214348927005070382 +AnimatorTransition: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: + m_Conditions: + - m_ConditionMode: 7 + m_ConditionEvent: int + m_EventTreshold: 0 + m_DstStateMachine: {fileID: 0} + m_DstState: {fileID: 0} + m_Solo: 0 + m_Mute: 0 + m_IsExit: 1 + serializedVersion: 1 --- !u!91 &9100000 AnimatorController: m_ObjectHideFlags: 0 @@ -1034,7 +1051,10 @@ AnimatorStateMachine: - {fileID: 1712637675519008892} m_EntryTransitions: - {fileID: 6284330602530841453} - m_StateMachineTransitions: {} + m_StateMachineTransitions: + - first: {fileID: -2155158836370751539} + second: + - {fileID: -1214348927005070382} m_StateMachineBehaviours: [] m_AnyStatePosition: {x: 50, y: 20, z: 0} m_EntryPosition: {x: 50, y: 120, z: 0} From 12de13a9475e3a8d52c81039d35dbd901e023ab1 Mon Sep 17 00:00:00 2001 From: bd_ Date: Sat, 9 Mar 2024 01:57:38 -0800 Subject: [PATCH 10/10] chore: fix localization capitalization (#758) --- Editor/Localization/Localization.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Editor/Localization/Localization.cs b/Editor/Localization/Localization.cs index 43e69e6b..b98a9c3a 100644 --- a/Editor/Localization/Localization.cs +++ b/Editor/Localization/Localization.cs @@ -23,13 +23,13 @@ namespace nadena.dev.modular_avatar.core.editor private static ImmutableDictionary SupportedLanguageDisplayNames = ImmutableDictionary.Empty - .Add("en-us", "English") - .Add("ja-jp", "日本語") - .Add("zh-hans", "简体中文") - .Add("ko-kr", "한국어"); + .Add("en-US", "English") + .Add("ja-JP", "日本語") + .Add("zh-Hans", "简体中文") + .Add("ko-KR", "한국어"); private static ImmutableList - SupportedLanguages = new string[] {"en-us", "ja-jp", "zh-hans", "ko-kr"}.ToImmutableList(); + SupportedLanguages = new string[] {"en-US", "ja-JP", "zh-Hans", "ko-KR"}.ToImmutableList(); private static string[] DisplayNames = SupportedLanguages.Select(l => {