mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2025-01-01 20:25:07 +08:00
b25359a14a
* fix: Scale Adjusters outside an avatar throw exceptions * fix: improve scale adjuster performance
169 lines
4.9 KiB
C#
169 lines
4.9 KiB
C#
#region
|
|
|
|
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
using UnityEngine.Serialization;
|
|
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
#endif
|
|
|
|
#endregion
|
|
|
|
namespace nadena.dev.modular_avatar.core
|
|
{
|
|
[ExecuteInEditMode]
|
|
[DisallowMultipleComponent]
|
|
[AddComponentMenu("Modular Avatar/MA Scale Adjuster")]
|
|
[HelpURL("https://modular-avatar.nadena.dev/docs/reference/scale-adjuster?lang=auto")]
|
|
public sealed class ModularAvatarScaleAdjuster : AvatarTagComponent
|
|
{
|
|
private const string ADJUSTER_OBJECT = "MA Scale Adjuster Proxy Renderer";
|
|
[SerializeField] private Vector3 m_Scale = Vector3.one;
|
|
|
|
public Vector3 Scale
|
|
{
|
|
get => m_Scale;
|
|
set
|
|
{
|
|
m_Scale = value;
|
|
PreCull();
|
|
}
|
|
}
|
|
|
|
[SerializeField] [FormerlySerializedAs("scaleProxy")]
|
|
internal Transform legacyScaleProxy;
|
|
|
|
internal Transform scaleProxyChild;
|
|
|
|
[NonSerialized]
|
|
private bool initialized = false;
|
|
|
|
#if UNITY_EDITOR
|
|
void Awake()
|
|
{
|
|
ProxyManager.RegisterAdjuster(this);
|
|
initialized = false;
|
|
}
|
|
|
|
void OnValidate()
|
|
{
|
|
ProxyManager.RegisterAdjuster(this);
|
|
initialized = false;
|
|
}
|
|
|
|
internal void PreCull()
|
|
{
|
|
if (this == null)
|
|
{
|
|
EditorApplication.delayCall += () => ProxyManager.UnregisterAdjuster(this);
|
|
return;
|
|
}
|
|
|
|
if (PrefabUtility.IsPartOfPrefabAsset(this)) return;
|
|
|
|
if (scaleProxyChild == null || initialized == false)
|
|
{
|
|
InitializeProxy();
|
|
}
|
|
|
|
UpdateProxyParent(scaleProxyChild, transform);
|
|
|
|
var xform = transform;
|
|
scaleProxyChild.localScale = m_Scale;
|
|
|
|
ProxyManager.RegisterBone(xform, scaleProxyChild);
|
|
|
|
if (legacyScaleProxy != null && !PrefabUtility.IsPartOfPrefabAsset(legacyScaleProxy))
|
|
{
|
|
DestroyImmediate(legacyScaleProxy.gameObject);
|
|
legacyScaleProxy = null;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
// Clean up any additional parentage we might not want
|
|
if (proxyChild.parent != null)
|
|
{
|
|
Transform parent = proxyChild.parent;
|
|
|
|
// Reparent to root
|
|
proxyChild.SetParent(null, false);
|
|
|
|
// Destroy old hierarchy
|
|
while (parent.parent != null) parent = parent.parent;
|
|
DestroyImmediate(parent.gameObject);
|
|
}
|
|
}
|
|
|
|
private void InitializeProxy()
|
|
{
|
|
if (scaleProxyChild == null)
|
|
{
|
|
scaleProxyChild = new GameObject("Child").transform;
|
|
|
|
#if MODULAR_AVATAR_DEBUG_HIDDEN
|
|
scaleProxyChild.gameObject.hideFlags = HideFlags.DontSave;
|
|
#else
|
|
scaleProxyChild.gameObject.hideFlags = HideFlags.HideAndDontSave;
|
|
#endif
|
|
}
|
|
|
|
initialized = true;
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
ProxyManager.UnregisterAdjuster(this);
|
|
|
|
if (scaleProxyChild != null)
|
|
{
|
|
Transform parent = scaleProxyChild.parent;
|
|
while (parent.parent != null) parent = parent.parent;
|
|
DestroyImmediate(parent.gameObject);
|
|
}
|
|
|
|
if (transform != null)
|
|
{
|
|
ProxyManager.UnregisterBone(transform);
|
|
}
|
|
|
|
base.OnDestroy();
|
|
}
|
|
#else
|
|
internal void PreCull() {
|
|
// build time stub
|
|
}
|
|
#endif
|
|
}
|
|
} |