fix: Move Independently breaks armature lock (#457)

This commit is contained in:
bd_ 2023-09-27 20:24:42 +09:00 committed by GitHub
parent 587084ffb7
commit bef17bbaf8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 78 additions and 14 deletions

View File

@ -10,6 +10,9 @@ namespace nadena.dev.modular_avatar.core.armature_lock
{
internal class ArmatureLockController : IDisposable
{
private static long lastMovedFrame = 0;
public static bool MovedThisFrame => Time.frameCount == lastMovedFrame;
// Undo operations can reinitialize the MAMA component, which destroys critical lock controller state.
// Avoid this issue by keeping a static reference to the controller for each MAMA component.
private static Dictionary<ModularAvatarMergeArmature, ArmatureLockController>
@ -32,11 +35,11 @@ namespace nadena.dev.modular_avatar.core.armature_lock
#if UNITY_EDITOR
if (value)
{
EditorApplication.update += VoidUpdate;
UpdateLoopController.OnArmatureLockUpdate += VoidUpdate;
}
else
{
EditorApplication.update -= VoidUpdate;
UpdateLoopController.OnArmatureLockUpdate -= VoidUpdate;
}
_updateActive = value;
@ -121,6 +124,11 @@ namespace nadena.dev.modular_avatar.core.armature_lock
if (_curMode == _mode)
{
result = _lock?.Execute() ?? LockResult.Failed;
if (result == LockResult.Success)
{
lastMovedFrame = Time.frameCount;
}
if (result != LockResult.Failed) return true;
}

View File

@ -50,7 +50,7 @@ namespace nadena.dev.modular_avatar.core.armature_lock
}
}
[BurstCompile]
//[BurstCompile]
struct ComputePosition : IJobParallelFor
{
[ReadOnly] public NativeArray<BoneStaticData> _boneStatic;
@ -75,6 +75,7 @@ namespace nadena.dev.modular_avatar.core.armature_lock
if (TransformState.Differs(mergeSaved, mergeState))
{
TransformState.Differs(mergeSaved, mergeState);
_fault.Increment();
}

View File

@ -0,0 +1,24 @@
using System;
namespace nadena.dev.modular_avatar.core.armature_lock
{
internal static class UpdateLoopController
{
internal static event Action OnArmatureLockUpdate;
internal static event Action OnMoveIndependentlyUpdate;
#if UNITY_EDITOR
[UnityEditor.InitializeOnLoadMethod]
private static void Init()
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.update += () =>
{
OnArmatureLockUpdate?.Invoke();
OnMoveIndependentlyUpdate?.Invoke();
};
#endif
}
#endif
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5f22557c7545402e89ebceae70132d85
timeCreated: 1695811856

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using nadena.dev.modular_avatar.core.armature_lock;
using UnityEngine;
using VRC.SDKBase;
@ -111,7 +112,7 @@ namespace nadena.dev.modular_avatar.core.ArmatureAwase
var localRotation = child.localRotation;
var localScale = child.localScale;
if (_children.TryGetValue(child, out var state))
if (!ArmatureLockController.MovedThisFrame && _children.TryGetValue(child, out var state))
{
var deltaPos = localPosition - state.childLocalPos;
var deltaRot = Quaternion.Angle(localRotation, state.childLocalRot);
@ -120,16 +121,27 @@ namespace nadena.dev.modular_avatar.core.ArmatureAwase
if (deltaPos.sqrMagnitude < EPSILON && deltaRot < EPSILON && deltaScale < EPSILON)
{
Matrix4x4 childNewLocal = parent.worldToLocalMatrix * state.childWorld;
#if UNITY_EDITOR
UnityEditor.Undo.RecordObject(child, UnityEditor.Undo.GetCurrentGroupName());
#endif
child.localPosition = childNewLocal.MultiplyPoint(Vector3.zero);
child.localRotation = childNewLocal.rotation;
child.localScale = childNewLocal.lossyScale;
state.childLocalPos = child.localPosition;
state.childLocalRot = child.localRotation;
state.childLocalScale = child.localScale;
var newPosition = childNewLocal.MultiplyPoint(Vector3.zero);
var newRotation = childNewLocal.rotation;
var newScale = childNewLocal.lossyScale;
if ((newPosition - localPosition).sqrMagnitude > EPSILON
|| Quaternion.Angle(newRotation, localRotation) > EPSILON
|| (newScale - localScale).sqrMagnitude > EPSILON)
{
#if UNITY_EDITOR
UnityEditor.Undo.RecordObject(child, UnityEditor.Undo.GetCurrentGroupName());
#endif
child.localPosition = newPosition;
child.localRotation = newRotation;
child.localScale = newScale;
state.childLocalPos = child.localPosition;
state.childLocalRot = child.localRotation;
state.childLocalScale = child.localScale;
}
_children[child] = state;
@ -151,8 +163,24 @@ namespace nadena.dev.modular_avatar.core.ArmatureAwase
}
}
void Update()
private void OnEnable()
{
UpdateLoopController.OnMoveIndependentlyUpdate += OnUpdate;
}
private void OnDisable()
{
UpdateLoopController.OnMoveIndependentlyUpdate -= OnUpdate;
}
void OnUpdate()
{
if (this == null)
{
UpdateLoopController.OnMoveIndependentlyUpdate -= OnUpdate;
return;
}
var deltaPos = transform.position - _priorFrameState.MultiplyPoint(Vector3.zero);
var deltaRot = Quaternion.Angle(_priorFrameState.rotation, transform.rotation);
var deltaScale = (transform.lossyScale - _priorFrameState.lossyScale).sqrMagnitude;