Preserve local transform when rebinding humanoid avatar (#1062)

* Preserve local transform when rebinding humanoid avatar

* Check Animator.avatar

* Restore all transforms
This commit is contained in:
KOBAYASHI Yū 2024-09-01 08:54:48 +09:00 committed by GitHub
parent 2148ab0bfc
commit 3bc090dc7d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 83 additions and 13 deletions

View File

@ -81,19 +81,7 @@ namespace nadena.dev.modular_avatar.core.editor.plugin
FixupExpressionsMenuPass.FixupExpressionsMenu(maContext);
});
#endif
seq.Run("Rebind humanoid avatar", ctx =>
{
// workaround problem with avatar matching
// https://github.com/bdunderscore/modular-avatar/issues/430
var animator = ctx.AvatarRootObject.GetComponent<Animator>();
if (animator)
{
var avatar = animator.avatar;
animator.avatar = null;
// ReSharper disable once Unity.InefficientPropertyAccess
animator.avatar = avatar;
}
});
seq.Run(RebindHumanoidAvatarPass.Instance);
seq.Run("Purge ModularAvatar components", ctx =>
{
foreach (var component in ctx.AvatarRootTransform.GetComponentsInChildren<AvatarTagComponent>(true))
@ -253,6 +241,14 @@ namespace nadena.dev.modular_avatar.core.editor.plugin
}
#endif
class RebindHumanoidAvatarPass : MAPass<RebindHumanoidAvatarPass>
{
protected override void Execute(ndmf.BuildContext context)
{
new RebindHumanoidAvatar(context).Process();
}
}
class GCGameObjectsPluginPass : MAPass<GCGameObjectsPluginPass>
{
protected override void Execute(ndmf.BuildContext context)

View File

@ -0,0 +1,63 @@
using System.Linq;
using UnityEngine;
namespace nadena.dev.modular_avatar.core.editor.plugin
{
// workaround problem with avatar matching
// https://github.com/bdunderscore/modular-avatar/issues/430
internal class RebindHumanoidAvatar
{
private readonly ndmf.BuildContext _buildContext;
public RebindHumanoidAvatar(ndmf.BuildContext context)
{
_buildContext = context;
}
public void Process()
{
var avatarAnimator = _buildContext.AvatarRootObject.GetComponent<Animator>();
if (avatarAnimator == null || avatarAnimator.avatar == null) return;
var localTransformValues = _buildContext.AvatarRootObject
.GetComponentsInChildren<Transform>(true)
.ToDictionary((t) => t, LocalTransformValue.FromTransform);
var boundAvatar = avatarAnimator.avatar;
avatarAnimator.avatar = null;
// ReSharper disable once Unity.InefficientPropertyAccess
avatarAnimator.avatar = boundAvatar;
// resetting avatar also resets local transform value from avatar asset
// needs to restore them manually from pre-cache
// https://github.com/bdunderscore/modular-avatar/issues/1036
foreach (var (transform, preserved) in localTransformValues)
{
preserved.RestoreToTransform(transform);
}
}
struct LocalTransformValue
{
Vector3 Position;
Quaternion Rotation;
Vector3 Scale;
internal static LocalTransformValue FromTransform(Transform t)
{
return new LocalTransformValue
{
Position = t.localPosition,
Rotation = t.localRotation,
Scale = t.localScale
};
}
internal readonly void RestoreToTransform(Transform t)
{
t.SetLocalPositionAndRotation(Position, Rotation);
t.localScale = Scale;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1f0b7a3de79e73a4f853218f26ed7077
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: