mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2025-01-01 20:25:07 +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))]
|
[CustomEditor(typeof(ModularAvatarVisibleHeadAccessory))]
|
||||||
internal class FirstPersonVisibleEditor : MAEditorBase
|
internal class FirstPersonVisibleEditor : MAEditorBase
|
||||||
{
|
{
|
||||||
private VisibleHeadAccessoryProcessor _processor;
|
private VisibleHeadAccessoryValidation _validation;
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
var target = (ModularAvatarVisibleHeadAccessory) this.target;
|
var target = (ModularAvatarVisibleHeadAccessory) this.target;
|
||||||
var avatar = RuntimeUtil.FindAvatarTransformInParents(target.transform);
|
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()
|
protected override void OnInnerInspectorGUI()
|
||||||
@ -25,14 +25,14 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
if (_processor != null)
|
if (_validation != null)
|
||||||
{
|
{
|
||||||
var status = _processor.Validate(target);
|
var status = _validation.Validate(target);
|
||||||
|
|
||||||
switch (status)
|
switch (status)
|
||||||
{
|
{
|
||||||
case VisibleHeadAccessoryProcessor.ReadyStatus.Ready:
|
case VisibleHeadAccessoryValidation.ReadyStatus.Ready:
|
||||||
case VisibleHeadAccessoryProcessor.ReadyStatus.ParentMarked:
|
case VisibleHeadAccessoryValidation.ReadyStatus.ParentMarked:
|
||||||
EditorGUILayout.HelpBox(Localization.S("fpvisible.normal"), MessageType.Info);
|
EditorGUILayout.HelpBox(Localization.S("fpvisible.normal"), MessageType.Info);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using nadena.dev.modular_avatar.editor.ErrorReporting;
|
using nadena.dev.modular_avatar.editor.ErrorReporting;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Animations;
|
using UnityEngine.Animations;
|
||||||
@ -9,9 +10,10 @@ using VRC.SDK3.Dynamics.PhysBone.Components;
|
|||||||
|
|
||||||
namespace nadena.dev.modular_avatar.core.editor
|
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
|
internal enum ReadyStatus
|
||||||
{
|
{
|
||||||
@ -21,24 +23,14 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
InPhysBoneChain
|
InPhysBoneChain
|
||||||
}
|
}
|
||||||
|
|
||||||
private BuildContext _context;
|
public VisibleHeadAccessoryValidation(GameObject avatarRoot)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
_context = context;
|
var animator = avatarRoot.GetComponent<Animator>();
|
||||||
_avatarTransform = context.AvatarRootTransform;
|
HeadBone = animator != null ? animator.GetBoneTransform(HumanBodyBones.Head) : null;
|
||||||
|
|
||||||
var animator = _avatarTransform.GetComponent<Animator>();
|
var activeBones = ImmutableHashSet.CreateBuilder<Transform>();
|
||||||
_headBone = animator != null ? animator.GetBoneTransform(HumanBodyBones.Head) : null;
|
|
||||||
|
|
||||||
#if MA_VRCSDK3_AVATARS
|
#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 boneRoot = physBone.rootTransform != null ? physBone.rootTransform : physBone.transform;
|
||||||
var ignored = new HashSet<Transform>(physBone.ignoreTransforms);
|
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)
|
void Traverse(Transform bone, HashSet<Transform> ignored)
|
||||||
{
|
{
|
||||||
if (ignored.Contains(bone)) return;
|
if (ignored.Contains(bone)) return;
|
||||||
_activeBones.Add(bone);
|
activeBones.Add(bone);
|
||||||
|
|
||||||
foreach (Transform child in bone)
|
foreach (Transform child in bone)
|
||||||
{
|
{
|
||||||
@ -62,6 +56,53 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
#endif
|
#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()
|
public void Process()
|
||||||
{
|
{
|
||||||
bool didWork = false;
|
bool didWork = false;
|
||||||
@ -91,8 +132,8 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool didWork = false;
|
bool didWork = false;
|
||||||
|
|
||||||
if (Validate(target) == ReadyStatus.Ready)
|
if (_validator.Validate(target) == VisibleHeadAccessoryValidation.ReadyStatus.Ready)
|
||||||
{
|
{
|
||||||
var proxy = CreateProxy();
|
var proxy = CreateProxy();
|
||||||
|
|
||||||
@ -146,29 +187,5 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
return obj.transform;
|
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