mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2024-12-29 18:55:06 +08:00
fix: visible head accessory editor breaks on prefabs (#543)
Closes: #534
This commit is contained in:
parent
1dacdc4b37
commit
409501cb39
@ -5,14 +5,14 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
[CustomEditor(typeof(ModularAvatarVisibleHeadAccessory))]
|
||||
internal class FirstPersonVisibleEditor : MAEditorBase
|
||||
{
|
||||
private VisibleHeadAccessoryProcessor _processor;
|
||||
private VisibleHeadAccessoryValidation _validation;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
var target = (ModularAvatarVisibleHeadAccessory) this.target;
|
||||
var avatar = RuntimeUtil.FindAvatarTransformInParents(target.transform);
|
||||
|
||||
if (avatar != null) _processor = new VisibleHeadAccessoryProcessor(new BuildContext(avatar.gameObject));
|
||||
if (avatar != null) _validation = new VisibleHeadAccessoryValidation(avatar.gameObject);
|
||||
}
|
||||
|
||||
protected override void OnInnerInspectorGUI()
|
||||
@ -25,14 +25,14 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
|
||||
#else
|
||||
|
||||
if (_processor != null)
|
||||
if (_validation != null)
|
||||
{
|
||||
var status = _processor.Validate(target);
|
||||
var status = _validation.Validate(target);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case VisibleHeadAccessoryProcessor.ReadyStatus.Ready:
|
||||
case VisibleHeadAccessoryProcessor.ReadyStatus.ParentMarked:
|
||||
case VisibleHeadAccessoryValidation.ReadyStatus.Ready:
|
||||
case VisibleHeadAccessoryValidation.ReadyStatus.ParentMarked:
|
||||
EditorGUILayout.HelpBox(Localization.S("fpvisible.normal"), MessageType.Info);
|
||||
break;
|
||||
default:
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using nadena.dev.modular_avatar.editor.ErrorReporting;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Animations;
|
||||
@ -9,9 +10,10 @@ using VRC.SDK3.Dynamics.PhysBone.Components;
|
||||
|
||||
namespace nadena.dev.modular_avatar.core.editor
|
||||
{
|
||||
internal class VisibleHeadAccessoryProcessor
|
||||
internal class VisibleHeadAccessoryValidation
|
||||
{
|
||||
private const double EPSILON = 0.01;
|
||||
internal ImmutableHashSet<Transform> ActiveBones { get; }
|
||||
internal Transform HeadBone { get; }
|
||||
|
||||
internal enum ReadyStatus
|
||||
{
|
||||
@ -21,24 +23,14 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
InPhysBoneChain
|
||||
}
|
||||
|
||||
private BuildContext _context;
|
||||
private Transform _avatarTransform;
|
||||
private HashSet<Transform> _activeBones = new HashSet<Transform>();
|
||||
private Transform _headBone;
|
||||
|
||||
private HashSet<Transform> _visibleBones = new HashSet<Transform>();
|
||||
private Transform _proxyHead;
|
||||
|
||||
public VisibleHeadAccessoryProcessor(BuildContext context)
|
||||
public VisibleHeadAccessoryValidation(GameObject avatarRoot)
|
||||
{
|
||||
_context = context;
|
||||
_avatarTransform = context.AvatarRootTransform;
|
||||
|
||||
var animator = _avatarTransform.GetComponent<Animator>();
|
||||
_headBone = animator != null ? animator.GetBoneTransform(HumanBodyBones.Head) : null;
|
||||
|
||||
var animator = avatarRoot.GetComponent<Animator>();
|
||||
HeadBone = animator != null ? animator.GetBoneTransform(HumanBodyBones.Head) : null;
|
||||
|
||||
var activeBones = ImmutableHashSet.CreateBuilder<Transform>();
|
||||
#if MA_VRCSDK3_AVATARS
|
||||
foreach (var physBone in _avatarTransform.GetComponentsInChildren<VRCPhysBone>(true))
|
||||
foreach (var physBone in avatarRoot.GetComponentsInChildren<VRCPhysBone>(true))
|
||||
{
|
||||
var boneRoot = physBone.rootTransform != null ? physBone.rootTransform : physBone.transform;
|
||||
var ignored = new HashSet<Transform>(physBone.ignoreTransforms);
|
||||
@ -49,10 +41,12 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
}
|
||||
}
|
||||
|
||||
ActiveBones = activeBones.ToImmutable();
|
||||
|
||||
void Traverse(Transform bone, HashSet<Transform> ignored)
|
||||
{
|
||||
if (ignored.Contains(bone)) return;
|
||||
_activeBones.Add(bone);
|
||||
activeBones.Add(bone);
|
||||
|
||||
foreach (Transform child in bone)
|
||||
{
|
||||
@ -62,6 +56,53 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
#endif
|
||||
}
|
||||
|
||||
internal ReadyStatus Validate(ModularAvatarVisibleHeadAccessory target)
|
||||
{
|
||||
ReadyStatus status = ReadyStatus.NotUnderHead;
|
||||
Transform node = target.transform.parent;
|
||||
|
||||
if (ActiveBones.Contains(target.transform)) return ReadyStatus.InPhysBoneChain;
|
||||
|
||||
while (node != null)
|
||||
{
|
||||
if (node.GetComponent<ModularAvatarVisibleHeadAccessory>()) return ReadyStatus.ParentMarked;
|
||||
if (ActiveBones.Contains(node)) return ReadyStatus.InPhysBoneChain;
|
||||
|
||||
if (node == HeadBone)
|
||||
{
|
||||
status = ReadyStatus.Ready;
|
||||
break;
|
||||
}
|
||||
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
internal class VisibleHeadAccessoryProcessor
|
||||
{
|
||||
private const double EPSILON = 0.01;
|
||||
|
||||
private BuildContext _context;
|
||||
private VisibleHeadAccessoryValidation _validator;
|
||||
|
||||
private Transform _avatarTransform;
|
||||
private ImmutableHashSet<Transform> _activeBones => _validator.ActiveBones;
|
||||
private Transform _headBone => _validator.HeadBone;
|
||||
|
||||
private HashSet<Transform> _visibleBones = new HashSet<Transform>();
|
||||
private Transform _proxyHead;
|
||||
|
||||
public VisibleHeadAccessoryProcessor(BuildContext context)
|
||||
{
|
||||
_context = context;
|
||||
_avatarTransform = context.AvatarRootTransform;
|
||||
|
||||
_validator = new VisibleHeadAccessoryValidation(context.AvatarRootObject);
|
||||
}
|
||||
|
||||
public void Process()
|
||||
{
|
||||
bool didWork = false;
|
||||
@ -91,8 +132,8 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
#endif
|
||||
|
||||
bool didWork = false;
|
||||
|
||||
if (Validate(target) == ReadyStatus.Ready)
|
||||
|
||||
if (_validator.Validate(target) == VisibleHeadAccessoryValidation.ReadyStatus.Ready)
|
||||
{
|
||||
var proxy = CreateProxy();
|
||||
|
||||
@ -146,29 +187,5 @@ namespace nadena.dev.modular_avatar.core.editor
|
||||
|
||||
return obj.transform;
|
||||
}
|
||||
|
||||
internal ReadyStatus Validate(ModularAvatarVisibleHeadAccessory target)
|
||||
{
|
||||
ReadyStatus status = ReadyStatus.NotUnderHead;
|
||||
Transform node = target.transform.parent;
|
||||
|
||||
if (_activeBones.Contains(target.transform)) return ReadyStatus.InPhysBoneChain;
|
||||
|
||||
while (node != null)
|
||||
{
|
||||
if (node.GetComponent<ModularAvatarVisibleHeadAccessory>()) return ReadyStatus.ParentMarked;
|
||||
if (_activeBones.Contains(node)) return ReadyStatus.InPhysBoneChain;
|
||||
|
||||
if (node == _headBone)
|
||||
{
|
||||
status = ReadyStatus.Ready;
|
||||
break;
|
||||
}
|
||||
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user