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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace net.fushizen.modular_avatar.core
|
namespace net.fushizen.modular_avatar.core
|
||||||
@ -30,13 +32,26 @@ namespace net.fushizen.modular_avatar.core
|
|||||||
[ExecuteInEditMode]
|
[ExecuteInEditMode]
|
||||||
public class ModularAvatarMergeArmature : AvatarTagComponent
|
public class ModularAvatarMergeArmature : AvatarTagComponent
|
||||||
{
|
{
|
||||||
|
private const float POS_EPSILON = 0.01f;
|
||||||
|
private const float ROT_EPSILON = 0.01f;
|
||||||
|
|
||||||
public GameObject mergeTarget;
|
public GameObject mergeTarget;
|
||||||
public string mergeTargetPath;
|
public string mergeTargetPath;
|
||||||
public string prefix;
|
public string prefix;
|
||||||
public string suffix;
|
public string suffix;
|
||||||
public bool locked;
|
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()
|
void OnValidate()
|
||||||
{
|
{
|
||||||
RuntimeUtil.delayCall(() =>
|
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()
|
void CheckLock()
|
||||||
{
|
{
|
||||||
if (RuntimeUtil.isPlaying) return;
|
if (RuntimeUtil.isPlaying) return;
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
EditorApplication.update -= EditorUpdate;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (locked != wasLocked)
|
bool shouldLock = locked && isActiveAndEnabled;
|
||||||
|
bool wasLocked = lockedBones != null;
|
||||||
|
if (shouldLock != wasLocked)
|
||||||
{
|
{
|
||||||
if (!locked)
|
if (!shouldLock)
|
||||||
{
|
{
|
||||||
foreach (var comp in GetComponentsInChildren<MAInternalOffsetMarker>())
|
lockedBones = null;
|
||||||
{
|
|
||||||
DestroyImmediate(comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
wasLocked = false;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (mergeTarget == null) return;
|
if (mergeTarget == null) return;
|
||||||
|
lockedBones = new List<BoneBinding>();
|
||||||
|
|
||||||
foreach (var xform in GetComponentsInChildren<Transform>(true))
|
foreach (var xform in GetComponentsInChildren<Transform>(true))
|
||||||
{
|
{
|
||||||
Transform baseObject = FindCorresponding(xform);
|
Transform baseObject = FindCorresponding(xform);
|
||||||
var marker = xform.gameObject.GetComponent<MAInternalOffsetMarker>();
|
|
||||||
|
lockedBones.Add(new BoneBinding()
|
||||||
if (baseObject == null)
|
|
||||||
{
|
{
|
||||||
if (marker != null)
|
baseBone = baseObject,
|
||||||
{
|
mergeBone = xform,
|
||||||
DestroyImmediate(marker);
|
lastLocalPos = xform.localPosition,
|
||||||
}
|
lastLocalScale = xform.localScale,
|
||||||
}
|
lastLocalRot = xform.localRotation
|
||||||
else
|
});
|
||||||
{
|
|
||||||
if (marker == null)
|
|
||||||
{
|
|
||||||
marker = xform.gameObject.AddComponent<MAInternalOffsetMarker>();
|
|
||||||
}
|
|
||||||
marker.correspondingObject = baseObject;
|
|
||||||
marker.lockBasePosition = baseObject.gameObject == mergeTarget;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wasLocked = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (locked)
|
||||||
|
{
|
||||||
|
EditorApplication.update += EditorUpdate;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private Transform FindCorresponding(Transform xform)
|
private Transform FindCorresponding(Transform xform)
|
||||||
|
Loading…
Reference in New Issue
Block a user