mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2025-03-09 23:34:56 +08:00
Improve stability of locked merge armature system
This commit is contained in:
parent
ab51e9dd82
commit
12fe3f2c87
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 bd_
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace net.fushizen.modular_avatar.core
|
||||
{
|
||||
[ExecuteInEditMode]
|
||||
public class MAInternalOffsetMarker : AvatarTagComponent
|
||||
{
|
||||
void OnValidate()
|
||||
{
|
||||
#if MODULAR_AVATAR_DEBUG
|
||||
hideFlags = HideFlags.None;
|
||||
#else
|
||||
hideFlags = HideFlags.HideInInspector;
|
||||
#endif
|
||||
}
|
||||
|
||||
private const float POS_EPSILON = 0.01f;
|
||||
private const float ROT_EPSILON = 0.01f;
|
||||
|
||||
private Vector3 lastLocalPos;
|
||||
private Vector3 lastLocalScale;
|
||||
private Quaternion lastLocalRot;
|
||||
|
||||
public Transform correspondingObject;
|
||||
|
||||
public bool lockBasePosition;
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (correspondingObject == null) return;
|
||||
|
||||
// ReSharper disable once LocalVariableHidesMember
|
||||
var transform = this.transform;
|
||||
if ((transform.localPosition - lastLocalPos).sqrMagnitude > POS_EPSILON
|
||||
|| (transform.localScale - lastLocalScale).sqrMagnitude > POS_EPSILON
|
||||
|| Quaternion.Angle(lastLocalRot, transform.localRotation) > ROT_EPSILON)
|
||||
{
|
||||
if (lockBasePosition) transform.position = correspondingObject.position;
|
||||
else correspondingObject.localPosition = transform.localPosition;
|
||||
|
||||
correspondingObject.localScale = transform.localScale;
|
||||
correspondingObject.localRotation = transform.localRotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lockBasePosition) transform.position = correspondingObject.position;
|
||||
else transform.localPosition = correspondingObject.localPosition;
|
||||
transform.localScale = correspondingObject.localScale;
|
||||
transform.localRotation = correspondingObject.localRotation;
|
||||
}
|
||||
|
||||
lastLocalPos = transform.localPosition;
|
||||
lastLocalScale = transform.localScale;
|
||||
lastLocalRot = transform.localRotation;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7b59aa936ba8466e85aede8aa3631b84
|
||||
timeCreated: 1661807782
|
@ -23,6 +23,8 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace net.fushizen.modular_avatar.core
|
||||
@ -30,13 +32,26 @@ namespace net.fushizen.modular_avatar.core
|
||||
[ExecuteInEditMode]
|
||||
public class ModularAvatarMergeArmature : AvatarTagComponent
|
||||
{
|
||||
private const float POS_EPSILON = 0.01f;
|
||||
private const float ROT_EPSILON = 0.01f;
|
||||
|
||||
public GameObject mergeTarget;
|
||||
public string mergeTargetPath;
|
||||
public string prefix;
|
||||
public string suffix;
|
||||
public bool locked;
|
||||
|
||||
private bool wasLocked;
|
||||
private class BoneBinding
|
||||
{
|
||||
public Transform baseBone;
|
||||
public Transform mergeBone;
|
||||
|
||||
public Vector3 lastLocalPos;
|
||||
public Vector3 lastLocalScale;
|
||||
public Quaternion lastLocalRot;
|
||||
}
|
||||
|
||||
private List<BoneBinding> lockedBones;
|
||||
void OnValidate()
|
||||
{
|
||||
RuntimeUtil.delayCall(() =>
|
||||
@ -70,50 +85,115 @@ namespace net.fushizen.modular_avatar.core
|
||||
});
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
RuntimeUtil.delayCall(CheckLock);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
RuntimeUtil.delayCall(CheckLock);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
EditorApplication.update -= EditorUpdate;
|
||||
#endif
|
||||
}
|
||||
|
||||
void EditorUpdate()
|
||||
{
|
||||
if (this == null || lockedBones == null)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
EditorApplication.update -= EditorUpdate;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (lockedBones != null)
|
||||
{
|
||||
foreach (var bone in lockedBones)
|
||||
{
|
||||
if (bone.baseBone == null || bone.mergeBone == null)
|
||||
{
|
||||
lockedBones = null;
|
||||
break;
|
||||
}
|
||||
|
||||
var mergeBone = bone.mergeBone;
|
||||
var correspondingObject = bone.baseBone;
|
||||
bool lockBasePosition = bone.baseBone == mergeTarget.transform;
|
||||
|
||||
if ((mergeBone.localPosition - bone.lastLocalPos).sqrMagnitude > POS_EPSILON
|
||||
|| (mergeBone.localScale - bone.lastLocalScale).sqrMagnitude > POS_EPSILON
|
||||
|| Quaternion.Angle(bone.lastLocalRot, mergeBone.localRotation) > ROT_EPSILON)
|
||||
{
|
||||
if (lockBasePosition) mergeBone.position = correspondingObject.position;
|
||||
else correspondingObject.localPosition = mergeBone.localPosition;
|
||||
|
||||
correspondingObject.localScale = mergeBone.localScale;
|
||||
correspondingObject.localRotation = mergeBone.localRotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lockBasePosition) mergeBone.position = correspondingObject.position;
|
||||
else mergeBone.localPosition = correspondingObject.localPosition;
|
||||
mergeBone.localScale = correspondingObject.localScale;
|
||||
mergeBone.localRotation = correspondingObject.localRotation;
|
||||
}
|
||||
|
||||
bone.lastLocalPos = mergeBone.localPosition;
|
||||
bone.lastLocalScale = mergeBone.localScale;
|
||||
bone.lastLocalRot = mergeBone.localRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckLock()
|
||||
{
|
||||
if (RuntimeUtil.isPlaying) return;
|
||||
|
||||
if (locked != wasLocked)
|
||||
{
|
||||
if (!locked)
|
||||
{
|
||||
foreach (var comp in GetComponentsInChildren<MAInternalOffsetMarker>())
|
||||
{
|
||||
DestroyImmediate(comp);
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
EditorApplication.update -= EditorUpdate;
|
||||
#endif
|
||||
|
||||
wasLocked = false;
|
||||
bool shouldLock = locked && isActiveAndEnabled;
|
||||
bool wasLocked = lockedBones != null;
|
||||
if (shouldLock != wasLocked)
|
||||
{
|
||||
if (!shouldLock)
|
||||
{
|
||||
lockedBones = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mergeTarget == null) return;
|
||||
lockedBones = new List<BoneBinding>();
|
||||
|
||||
foreach (var xform in GetComponentsInChildren<Transform>(true))
|
||||
{
|
||||
Transform baseObject = FindCorresponding(xform);
|
||||
var marker = xform.gameObject.GetComponent<MAInternalOffsetMarker>();
|
||||
|
||||
if (baseObject == null)
|
||||
lockedBones.Add(new BoneBinding()
|
||||
{
|
||||
if (marker != null)
|
||||
{
|
||||
DestroyImmediate(marker);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (marker == null)
|
||||
{
|
||||
marker = xform.gameObject.AddComponent<MAInternalOffsetMarker>();
|
||||
}
|
||||
marker.correspondingObject = baseObject;
|
||||
marker.lockBasePosition = baseObject.gameObject == mergeTarget;
|
||||
}
|
||||
baseBone = baseObject,
|
||||
mergeBone = xform,
|
||||
lastLocalPos = xform.localPosition,
|
||||
lastLocalScale = xform.localScale,
|
||||
lastLocalRot = xform.localRotation
|
||||
});
|
||||
}
|
||||
|
||||
wasLocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
if (locked)
|
||||
{
|
||||
EditorApplication.update += EditorUpdate;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
private Transform FindCorresponding(Transform xform)
|
||||
|
Loading…
Reference in New Issue
Block a user