chore: use ndmf Avatar Root api where applicable (#482)

* expose ndmf AvatarRoot APIs through ma.RuntimeUtil

* refactor: prefer RuntimeUtil helpers for checking avatar root

* refactor: ndmf.BuildContext represents Avatar (log)

* refactor: ndmf.BuildContext represents Avatar (WorldFixed)

* refactor: ndmf.BuildContext represents Avatar (FirstPersonVisible)

* refactor: ndmf.BuildContext represents Avatar (BlendShapeSync)

* refactor: prefer FindAvatarTransformInParents() (ErrorReportUI)

* refactor: prefer FindAvatarTransformInParents() (Runtime)

* refactor: prefer FindAvatarTransformInParents() (Editor)

* delegate more ndmf AvatarRoot APIs through ma.RuntimeUtil
This commit is contained in:
kaikoga 2023-10-15 18:44:53 +09:00 committed by GitHub
parent 939e63c297
commit ae7103cf82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 104 additions and 113 deletions

View File

@ -57,7 +57,7 @@ namespace nadena.dev.modular_avatar.core.editor
_boneDatabase = boneDatabase;
_pathMappings = context.PluginBuildContext.Extension<AnimationServicesContext>().PathMappings;
while (root != null && root.GetComponent<VRCAvatarDescriptor>() == null)
while (root != null && !RuntimeUtil.IsAvatarRoot(root))
{
var originalPath = RuntimeUtil.AvatarRootPath(root.gameObject);
System.Diagnostics.Debug.Assert(originalPath != null);

View File

@ -42,16 +42,17 @@ namespace nadena.dev.modular_avatar.core.editor
}
}
public void OnPreprocessAvatar(GameObject avatar, BuildContext context)
public void OnPreprocessAvatar(BuildContext context)
{
_context = context;
var avatarGameObject = context.AvatarRootObject;
var animDb = _context.AnimationDatabase;
var avatarDescriptor = avatar.GetComponent<VRCAvatarDescriptor>();
var avatarDescriptor = context.AvatarDescriptor;
_bindingMappings = new Dictionary<SummaryBinding, List<SummaryBinding>>();
_motionCache = new Dictionary<Motion, Motion>();
var components = avatarDescriptor.GetComponentsInChildren<ModularAvatarBlendshapeSync>(true);
var components = avatarGameObject.GetComponentsInChildren<ModularAvatarBlendshapeSync>(true);
if (components.Length == 0) return;
var layers = avatarDescriptor.baseAnimationLayers;
@ -77,7 +78,7 @@ namespace nadena.dev.modular_avatar.core.editor
foreach (var component in components)
{
BuildReport.ReportingObject(component, () => ProcessComponent(avatarDescriptor, component));
BuildReport.ReportingObject(component, () => ProcessComponent(avatarGameObject, component));
}
// Walk and transform all clips
@ -91,9 +92,9 @@ namespace nadena.dev.modular_avatar.core.editor
});
}
private void ProcessComponent(VRCAvatarDescriptor avatarDescriptor, ModularAvatarBlendshapeSync component)
private void ProcessComponent(GameObject avatarGameObject, ModularAvatarBlendshapeSync component)
{
var targetObj = RuntimeUtil.RelativePath(avatarDescriptor.gameObject, component.gameObject);
var targetObj = RuntimeUtil.RelativePath(avatarGameObject, component.gameObject);
foreach (var binding in component.Bindings)
{
@ -102,7 +103,7 @@ namespace nadena.dev.modular_avatar.core.editor
var refSmr = refObj.GetComponent<SkinnedMeshRenderer>();
if (refSmr == null) continue;
var refPath = RuntimeUtil.RelativePath(avatarDescriptor.gameObject, refObj);
var refPath = RuntimeUtil.RelativePath(avatarGameObject, refObj);
var srcBinding = new SummaryBinding(refPath, binding.Blendshape);

View File

@ -15,6 +15,8 @@ namespace nadena.dev.modular_avatar.core.editor
internal readonly nadena.dev.ndmf.BuildContext PluginBuildContext;
internal VRCAvatarDescriptor AvatarDescriptor => PluginBuildContext.AvatarDescriptor;
internal GameObject AvatarRootObject => PluginBuildContext.AvatarRootObject;
internal Transform AvatarRootTransform => PluginBuildContext.AvatarRootTransform;
internal AnimationDatabase AnimationDatabase =>
PluginBuildContext.Extension<AnimationServicesContext>().AnimationDatabase;
@ -50,6 +52,11 @@ namespace nadena.dev.modular_avatar.core.editor
{
}
public BuildContext(GameObject avatarGameObject)
: this(new ndmf.BuildContext(avatarGameObject, null))
{
}
public void SaveAsset(Object obj)
{
if (!SaveImmediate || AssetDatabase.IsMainAsset(obj) || AssetDatabase.IsSubAsset(obj)) return;

View File

@ -280,16 +280,16 @@ namespace nadena.dev.modular_avatar.core.editor
// descriptors when transplanting outfits. Block this (and require that there be only one avdesc) by
// refusing to run if we detect multiple avatar descriptors above the current object (or if we're run on
// the avdesc object itself)
var nearestAvatar = RuntimeUtil.FindAvatarInParents(xform);
if (nearestAvatar == null || nearestAvatar.transform == xform)
var nearestAvatarTransform = RuntimeUtil.FindAvatarTransformInParents(xform);
if (nearestAvatarTransform == null || nearestAvatarTransform == xform)
{
errorMessageGroups = new string[]
{S_f("setup_outfit.err.multiple_avatar_descriptors", xform.gameObject.name)};
return false;
}
var parent = nearestAvatar.transform.parent;
if (parent != null && RuntimeUtil.FindAvatarInParents(parent) != null)
var parent = nearestAvatarTransform.parent;
if (parent != null && RuntimeUtil.FindAvatarTransformInParents(parent) != null)
{
errorMessageGroups = new string[]
{
@ -308,7 +308,7 @@ namespace nadena.dev.modular_avatar.core.editor
avatarHips = outfitHips = null;
var outfitRoot = obj as GameObject;
avatarRoot = outfitRoot != null
? RuntimeUtil.FindAvatarInParents(outfitRoot.transform)?.gameObject
? RuntimeUtil.FindAvatarTransformInParents(outfitRoot.transform)?.gameObject
: null;
if (avatarRoot == null)

View File

@ -5,7 +5,6 @@ using System.Linq;
using nadena.dev.modular_avatar.core;
using Newtonsoft.Json;
using UnityEngine;
using VRC.SDK3.Avatars.Components;
using UnityEditor;
using UnityEngine.SceneManagement;
using Object = UnityEngine.Object;
@ -273,17 +272,17 @@ namespace nadena.dev.modular_avatar.editor.ErrorReporting
}
}
internal IDisposable ReportingOnAvatar(VRCAvatarDescriptor descriptor)
internal IDisposable ReportingOnAvatar(GameObject avatarGameObject)
{
if (descriptor != null)
if (avatarGameObject != null)
{
AvatarReport report = new AvatarReport();
report.objectRef = new ObjectRef(descriptor.gameObject);
report.objectRef = new ObjectRef(avatarGameObject);
Avatars.Add(report);
_currentAvatar = report;
_currentAvatar.successful = true;
_currentAvatar.logs.AddRange(ComponentValidation.ValidateAll(descriptor.gameObject));
_currentAvatar.logs.AddRange(ComponentValidation.ValidateAll(avatarGameObject));
}
return new AvatarReportScope();

View File

@ -110,7 +110,7 @@ namespace nadena.dev.modular_avatar.editor.ErrorReporting
GameObject activeAvatarObject = null;
if (Selection.gameObjects.Length == 1)
{
activeAvatarObject = RuntimeUtil.FindAvatarInParents(Selection.activeGameObject.transform)?.gameObject;
activeAvatarObject = RuntimeUtil.FindAvatarTransformInParents(Selection.activeGameObject.transform)?.gameObject;
activeAvatar = BuildReport.CurrentReport.Avatars.FirstOrDefault(av =>
av.objectRef.path == RuntimeUtil.RelativePath(null, activeAvatarObject)
|| av.objectRef.path == RuntimeUtil.RelativePath(null, activeAvatarObject) + "(Clone)");

View File

@ -356,7 +356,7 @@ namespace nadena.dev.modular_avatar.core.editor
internal static void RenameBonesByHeuristic(ModularAvatarMergeArmature config)
{
var target = config.mergeTarget.Get(RuntimeUtil.FindAvatarInParents(config.transform));
var target = config.mergeTarget.Get(RuntimeUtil.FindAvatarTransformInParents(config.transform));
if (target == null) return;
Traverse(config.transform, target.transform);

View File

@ -1,6 +1,5 @@
using UnityEditor;
using UnityEngine;
using VRC.SDK3.Avatars.Components;
namespace nadena.dev.modular_avatar.core.editor
{
@ -34,15 +33,15 @@ namespace nadena.dev.modular_avatar.core.editor
try
{
var avatar = findContainingAvatar(property);
if (avatar == null) return false;
var avatarTransform = findContainingAvatarTransform(property);
if (avatarTransform == null) return false;
bool isRoot = property.stringValue == AvatarObjectReference.AVATAR_ROOT;
bool isNull = string.IsNullOrEmpty(property.stringValue);
Transform target;
if (isNull) target = null;
else if (isRoot) target = avatar.transform;
else target = avatar.transform.Find(property.stringValue);
else if (isRoot) target = avatarTransform;
else target = avatarTransform.Find(property.stringValue);
var labelRect = position;
position = EditorGUI.PrefixLabel(position, label);
@ -62,14 +61,14 @@ namespace nadena.dev.modular_avatar.core.editor
{
property.stringValue = "";
}
else if (newTarget == avatar.transform)
else if (newTarget == avatarTransform)
{
property.stringValue = AvatarObjectReference.AVATAR_ROOT;
}
else
{
var relPath =
RuntimeUtil.RelativePath(avatar.gameObject, ((Transform) newTarget).gameObject);
RuntimeUtil.RelativePath(avatarTransform.gameObject, ((Transform) newTarget).gameObject);
if (relPath == null) return true;
property.stringValue = relPath;
@ -93,14 +92,14 @@ namespace nadena.dev.modular_avatar.core.editor
{
property.stringValue = "";
}
else if (newTarget == avatar.transform)
else if (newTarget == avatarTransform)
{
property.stringValue = AvatarObjectReference.AVATAR_ROOT;
}
else
{
var relPath =
RuntimeUtil.RelativePath(avatar.gameObject, ((Transform) newTarget).gameObject);
RuntimeUtil.RelativePath(avatarTransform.gameObject, ((Transform) newTarget).gameObject);
if (relPath == null) return true;
property.stringValue = relPath;
@ -122,12 +121,12 @@ namespace nadena.dev.modular_avatar.core.editor
}
}
private static VRCAvatarDescriptor findContainingAvatar(SerializedProperty property)
private static Transform findContainingAvatarTransform(SerializedProperty property)
{
// Find containing object, and from that the avatar
if (property.serializedObject == null) return null;
VRCAvatarDescriptor commonAvatar = null;
Transform commonAvatar = null;
var targets = property.serializedObject.targetObjects;
for (int i = 0; i < targets.Length; i++)
{
@ -135,7 +134,7 @@ namespace nadena.dev.modular_avatar.core.editor
if (obj == null) return null;
var transform = obj.transform;
var avatar = RuntimeUtil.FindAvatarInParents(transform);
var avatar = RuntimeUtil.FindAvatarTransformInParents(transform);
if (i == 0)
{

View File

@ -263,7 +263,7 @@ namespace nadena.dev.modular_avatar.core.editor
{
if (_window != null) DestroyImmediate(_window);
_window = ScriptableObject.CreateInstance<BlendshapeSelectWindow>();
_window.AvatarRoot = RuntimeUtil.FindAvatarInParents(((ModularAvatarBlendshapeSync) target).transform)
_window.AvatarRoot = RuntimeUtil.FindAvatarTransformInParents(((ModularAvatarBlendshapeSync) target).transform)
.gameObject;
_window.OfferBinding += OfferBinding;
_window.Show();

View File

@ -50,10 +50,10 @@ namespace nadena.dev.modular_avatar.core.editor
for (int i = 0; i < targets.Length; i++)
{
var t = (ModularAvatarBoneProxy) targets[i];
var av = RuntimeUtil.FindAvatarInParents(t.transform);
var avTr = RuntimeUtil.FindAvatarTransformInParents(t.transform);
if (av != null && parentAvatar == null) parentAvatar = av.gameObject;
if (av == null || parentAvatar != av.gameObject)
if (avTr != null && parentAvatar == null) parentAvatar = avTr.gameObject;
if (avTr == null || parentAvatar != avTr.gameObject)
{
suppressTarget = true;
break;
@ -91,7 +91,7 @@ namespace nadena.dev.modular_avatar.core.editor
var t = (ModularAvatarBoneProxy) targets[i];
Undo.RecordObjects(targets, "Set targets");
var xform = ((TempObjRef) objRefs[i]).target;
if (RuntimeUtil.FindAvatarInParents(xform)?.gameObject != parentAvatar) continue;
if (RuntimeUtil.FindAvatarTransformInParents(xform)?.gameObject != parentAvatar) continue;
t.target = xform;
}
}

View File

@ -10,9 +10,9 @@ namespace nadena.dev.modular_avatar.core.editor
private void OnEnable()
{
var target = (ModularAvatarVisibleHeadAccessory) this.target;
var avatar = RuntimeUtil.FindAvatarInParents(target.transform);
var avatar = RuntimeUtil.FindAvatarTransformInParents(target.transform);
if (avatar != null) _processor = new VisibleHeadAccessoryProcessor(avatar);
if (avatar != null) _processor = new VisibleHeadAccessoryProcessor(new BuildContext(avatar.gameObject));
}
protected override void OnInnerInspectorGUI()

View File

@ -20,7 +20,7 @@ namespace nadena.dev.modular_avatar.core.editor
var target = targets[0] as Component;
if (target == null) return;
if (RuntimeUtil.FindAvatarInParents(target.transform) == null)
if (RuntimeUtil.FindAvatarTransformInParents(target.transform) == null)
{
EditorGUILayout.HelpBox(Localization.S("hint.not_in_avatar"), MessageType.Warning);
}

View File

@ -41,11 +41,11 @@ namespace nadena.dev.modular_avatar.core.editor
if (targets.Length == 1)
{
settings = (ModularAvatarMeshSettings) target;
var avatar = RuntimeUtil.FindAvatarInParents(settings.transform);
if (avatar != null)
var avatarTransform = RuntimeUtil.FindAvatarTransformInParents(settings.transform);
if (avatarTransform != null)
{
Component mesh = (Component) target;
merged = MeshSettingsPass.MergeSettings(avatar.transform, mesh.transform);
merged = MeshSettingsPass.MergeSettings(avatarTransform, mesh.transform);
haveMerged = true;
}
}

View File

@ -180,9 +180,8 @@ namespace nadena.dev.modular_avatar.core.editor
[CanBeNull]
public Mesh Retarget()
{
var avatar = RuntimeUtil.FindAvatarInParents(renderer.transform);
if (avatar == null) throw new System.Exception("Could not find avatar in parents of " + renderer.name);
var avatarTransform = avatar.transform;
var avatarTransform = RuntimeUtil.FindAvatarTransformInParents(renderer.transform);
if (avatarTransform == null) throw new System.Exception("Could not find avatar in parents of " + renderer.name);
var avPos = avatarTransform.position;
var avRot = avatarTransform.rotation;

View File

@ -16,7 +16,7 @@ namespace nadena.dev.modular_avatar.core.editor
BuildContext = new BuildContext(context);
}
toDispose = BuildReport.CurrentReport.ReportingOnAvatar(context.AvatarDescriptor);
toDispose = BuildReport.CurrentReport.ReportingOnAvatar(context.AvatarRootObject);
}
public void OnDeactivate(ndmf.BuildContext context)

View File

@ -42,7 +42,7 @@ namespace nadena.dev.modular_avatar.core.editor.plugin
seq.Run(BoneProxyPluginPass.Instance);
seq.Run(VisibleHeadAccessoryPluginPass.Instance);
seq.Run("World Fixed Object",
ctx => new WorldFixedObjectProcessor(ctx.AvatarDescriptor).Process(ctx)
ctx => new WorldFixedObjectProcessor().Process(ctx)
);
seq.Run(ReplaceObjectPluginPass.Instance);
seq.Run(BlendshapeSyncAnimationPluginPass.Instance);
@ -186,7 +186,7 @@ namespace nadena.dev.modular_avatar.core.editor.plugin
{
protected override void Execute(ndmf.BuildContext context)
{
new VisibleHeadAccessoryProcessor(context.AvatarDescriptor).Process(MAContext(context));
new VisibleHeadAccessoryProcessor(MAContext(context)).Process();
}
}
@ -202,7 +202,7 @@ namespace nadena.dev.modular_avatar.core.editor.plugin
{
protected override void Execute(ndmf.BuildContext context)
{
new BlendshapeSyncAnimationProcessor().OnPreprocessAvatar(context.AvatarRootObject, MAContext(context));
new BlendshapeSyncAnimationProcessor().OnPreprocessAvatar(MAContext(context));
}
}

View File

@ -29,7 +29,6 @@ using JetBrains.Annotations;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
using VRC.SDK3.Avatars.Components;
using VRC.SDKBase.Editor.BuildPipeline;
using Object = UnityEngine.Object;
@ -238,7 +237,7 @@ namespace nadena.dev.modular_avatar.core.editor
{
var component = ptr.GetComponent<T>();
if (component != null) yield return component;
if (ptr.GetComponent<VRCAvatarDescriptor>() != null) break;
if (RuntimeUtil.IsAvatarRoot(ptr)) break;
ptr = ptr.parent;
}
}

View File

@ -2,7 +2,6 @@
using nadena.dev.modular_avatar.editor.ErrorReporting;
using UnityEngine;
using UnityEngine.Animations;
using VRC.SDK3.Avatars.Components;
using VRC.SDK3.Dynamics.PhysBone.Components;
namespace nadena.dev.modular_avatar.core.editor
@ -19,21 +18,23 @@ namespace nadena.dev.modular_avatar.core.editor
InPhysBoneChain
}
private VRCAvatarDescriptor _avatar;
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(VRCAvatarDescriptor avatar)
public VisibleHeadAccessoryProcessor(BuildContext context)
{
_avatar = avatar;
_context = context;
_avatarTransform = context.AvatarRootTransform;
var animator = avatar.GetComponent<Animator>();
var animator = _avatarTransform.GetComponent<Animator>();
_headBone = animator != null ? animator.GetBoneTransform(HumanBodyBones.Head) : null;
foreach (var physBone in avatar.GetComponentsInChildren<VRCPhysBone>(true))
foreach (var physBone in _avatarTransform.GetComponentsInChildren<VRCPhysBone>(true))
{
var boneRoot = physBone.rootTransform != null ? physBone.rootTransform : physBone.transform;
var ignored = new HashSet<Transform>(physBone.ignoreTransforms);
@ -56,11 +57,11 @@ namespace nadena.dev.modular_avatar.core.editor
}
}
public void Process(BuildContext context)
public void Process()
{
bool didWork = false;
foreach (var target in _avatar.GetComponentsInChildren<ModularAvatarVisibleHeadAccessory>(true))
foreach (var target in _avatarTransform.GetComponentsInChildren<ModularAvatarVisibleHeadAccessory>(true))
{
var w = BuildReport.ReportingObject(target, () => Process(target));
didWork = didWork || w;
@ -69,10 +70,10 @@ namespace nadena.dev.modular_avatar.core.editor
if (didWork)
{
// Process meshes
foreach (var smr in _avatar.GetComponentsInChildren<SkinnedMeshRenderer>(true))
foreach (var smr in _avatarTransform.GetComponentsInChildren<SkinnedMeshRenderer>(true))
{
BuildReport.ReportingObject(smr,
() => new VisibleHeadAccessoryMeshProcessor(smr, _visibleBones, _proxyHead).Retarget(context));
() => new VisibleHeadAccessoryMeshProcessor(smr, _visibleBones, _proxyHead).Retarget(_context));
}
}
}

View File

@ -3,25 +3,20 @@ using nadena.dev.modular_avatar.editor.ErrorReporting;
using UnityEditor;
using UnityEngine;
using UnityEngine.Animations;
using VRC.SDK3.Avatars.Components;
namespace nadena.dev.modular_avatar.core.editor
{
internal class WorldFixedObjectProcessor
{
private BuildContext _context;
private VRCAvatarDescriptor _avatar;
private Transform _avatarTransform;
private Transform _proxy;
public WorldFixedObjectProcessor(VRCAvatarDescriptor avatar)
{
_avatar = avatar;
}
public void Process(BuildContext context)
{
_avatarTransform = context.AvatarRootTransform;
_context = context;
foreach (var target in _avatar.GetComponentsInChildren<ModularAvatarWorldFixedObject>(true)
foreach (var target in _avatarTransform.GetComponentsInChildren<ModularAvatarWorldFixedObject>(true)
.OrderByDescending(x => NestCount(x.transform)))
BuildReport.ReportingObject(target, () => Process(target));
}
@ -66,7 +61,7 @@ namespace nadena.dev.modular_avatar.core.editor
var fixedGameObject = AssetDatabase.LoadAssetAtPath<GameObject>(
AssetDatabase.GUIDToAssetPath("78828bfbcb4cb4ce3b00de044eb2d927"));
var avatarRoot = _avatar.transform;
var avatarRoot = _avatarTransform;
GameObject obj = new GameObject("(MA WorldFixedRoot)");
obj.transform.SetParent(avatarRoot, false);

View File

@ -1,6 +1,5 @@
using System;
using UnityEngine;
using VRC.SDK3.Avatars.Components;
namespace nadena.dev.modular_avatar.core
{
@ -34,16 +33,16 @@ namespace nadena.dev.modular_avatar.core
RuntimeUtil.OnHierarchyChanged -= InvalidateCache;
RuntimeUtil.OnHierarchyChanged += InvalidateCache;
var avatar = RuntimeUtil.FindAvatarInParents(container.transform);
if (avatar == null) return (_cachedReference = null);
var avatarTransform = RuntimeUtil.FindAvatarTransformInParents(container.transform);
if (avatarTransform == null) return (_cachedReference = null);
if (referencePath == AVATAR_ROOT)
{
_cachedReference = avatar.gameObject;
_cachedReference = avatarTransform.gameObject;
return _cachedReference;
}
_cachedReference = avatar.transform.Find(referencePath)?.gameObject;
_cachedReference = avatarTransform.Find(referencePath)?.gameObject;
if (_cachedReference == null) return null;
// https://github.com/bdunderscore/modular-avatar/issues/308
@ -72,7 +71,7 @@ namespace nadena.dev.modular_avatar.core
{
referencePath = "";
}
else if (target.GetComponent<VRCAvatarDescriptor>() != null)
else if (RuntimeUtil.IsAvatarRoot(target.transform))
{
referencePath = AVATAR_ROOT;
}

View File

@ -161,20 +161,20 @@ namespace nadena.dev.modular_avatar.core
return null;
}
var avatar = RuntimeUtil.FindAvatarInParents(transform);
if (avatar == null) return null;
var avatarTransform = RuntimeUtil.FindAvatarTransformInParents(transform);
if (avatarTransform == null) return null;
if (subPath == "$$AVATAR")
{
return avatar.transform;
return avatarTransform;
}
if (boneReference == HumanBodyBones.LastBone)
{
return avatar.transform.Find(subPath);
return avatarTransform.Find(subPath);
}
var animator = avatar.GetComponent<Animator>();
var animator = avatarTransform.GetComponent<Animator>();
if (animator == null) return null;
var bone = animator.GetBoneTransform(boneReference);
if (bone == null) return null;
@ -184,9 +184,9 @@ namespace nadena.dev.modular_avatar.core
private void UpdateStaticMapping(Transform newTarget)
{
var avatar = RuntimeUtil.FindAvatarInParents(transform);
var avatarTransform = RuntimeUtil.FindAvatarTransformInParents(transform);
var humanBones = new Dictionary<Transform, HumanBodyBones>();
var animator = avatar.GetComponent<Animator>();
var animator = avatarTransform.GetComponent<Animator>();
if (animator == null)
{
return;
@ -201,7 +201,6 @@ namespace nadena.dev.modular_avatar.core
}
Transform iter = newTarget;
Transform avatarTransform = avatar.transform;
if (newTarget == avatarTransform)
{

View File

@ -163,7 +163,7 @@ namespace nadena.dev.modular_avatar.core
public void InferPrefixSuffix()
{
// We only infer if targeting the armature (below the Hips bone)
var rootAnimator = RuntimeUtil.FindAvatarInParents(transform)?.GetComponent<Animator>();
var rootAnimator = RuntimeUtil.FindAvatarTransformInParents(transform)?.GetComponent<Animator>();
if (rootAnimator == null) return;
var hips = rootAnimator.GetBoneTransform(HumanBodyBones.Hips);

View File

@ -63,28 +63,18 @@ namespace nadena.dev.modular_avatar.core
[CanBeNull]
public static string RelativePath(GameObject root, GameObject child)
{
if (root == child) return "";
List<string> pathSegments = new List<string>();
while (child != root && child != null)
{
pathSegments.Add(child.name);
child = child.transform.parent?.gameObject;
}
if (child == null && root != null) return null;
pathSegments.Reverse();
return String.Join("/", pathSegments);
return ndmf.runtime.RuntimeUtil.RelativePath(root, child);
}
[CanBeNull]
public static string AvatarRootPath(GameObject child)
{
if (child == null) return null;
var avatar = FindAvatarInParents(child.transform);
if (avatar == null) return null;
return RelativePath(avatar.gameObject, child);
return ndmf.runtime.RuntimeUtil.AvatarRootPath(child);
}
public static bool IsAvatarRoot(Transform target)
{
return ndmf.runtime.RuntimeUtil.IsAvatarRoot(target);
}
public static VRCAvatarDescriptor FindAvatarInParents(Transform target)
@ -99,6 +89,11 @@ namespace nadena.dev.modular_avatar.core
return null;
}
public static Transform FindAvatarTransformInParents(Transform target)
{
return ndmf.runtime.RuntimeUtil.FindAvatarInParents(target);
}
public static void MarkDirty(UnityEngine.Object obj)
{
#if UNITY_EDITOR
@ -154,11 +149,8 @@ namespace nadena.dev.modular_avatar.core
#endif
}
#if UNITY_EDITOR
public static bool isPlaying => UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode;
#else
public static bool isPlaying => true;
#endif
public static bool isPlaying => ndmf.runtime.RuntimeUtil.IsPlaying;
public static void InvokeHierarchyChanged()
{
OnHierarchyChanged?.Invoke();

View File

@ -1,7 +1,8 @@
{
"name": "nadena.dev.modular-avatar.core",
"references": [
"GUID:2665a8d13d1b3f18800f46e256720795"
"GUID:2665a8d13d1b3f18800f46e256720795",
"GUID:fe747755f7b44e048820525b07f9b956"
],
"includePlatforms": [],
"excludePlatforms": [],

View File

@ -105,7 +105,7 @@ namespace modular_avatar_tests.ReplaceObject
BuildReport.Clear();
Assert.Throws<Exception>(() =>
{
using (BuildReport.CurrentReport.ReportingOnAvatar(root.GetComponent<VRCAvatarDescriptor>()))
using (BuildReport.CurrentReport.ReportingOnAvatar(root))
{
Process(root);
}
@ -125,7 +125,7 @@ namespace modular_avatar_tests.ReplaceObject
BuildReport.Clear();
Assert.Throws<Exception>(() =>
{
using (BuildReport.CurrentReport.ReportingOnAvatar(root.GetComponent<VRCAvatarDescriptor>()))
using (BuildReport.CurrentReport.ReportingOnAvatar(root))
{
Process(root);
}

View File

@ -19,7 +19,7 @@ public class WorldFixedObjectTest : TestBase
var buildContext = new BuildContext(descriptor);
buildContext.PluginBuildContext.ActivateExtensionContext<AnimationServicesContext>();
new WorldFixedObjectProcessor(descriptor).Process(buildContext);
new WorldFixedObjectProcessor().Process(buildContext);
var fixedRoot = avatar.transform.Find("(MA WorldFixedRoot)");
var movedFixedObject = avatar.transform.Find("(MA WorldFixedRoot)/FixedObject");
@ -46,7 +46,7 @@ public class WorldFixedObjectTest : TestBase
var buildContext = new BuildContext(descriptor);
buildContext.PluginBuildContext.ActivateExtensionContext<AnimationServicesContext>();
new WorldFixedObjectProcessor(descriptor).Process(buildContext);
new WorldFixedObjectProcessor().Process(buildContext);
var fixedRoot = avatar.transform.Find("(MA WorldFixedRoot)");
var movedFixedObject = avatar.transform.Find("(MA WorldFixedRoot)/FixedObject");