Skip to content

Commit

Permalink
feat: Implement AvatarRootComponent registry
Browse files Browse the repository at this point in the history
  • Loading branch information
kaikoga committed Nov 25, 2024
1 parent 1d07a93 commit b58f3bd
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 44 deletions.
18 changes: 3 additions & 15 deletions Editor/PreviewSystem/ComputeContext/GlobalQueries.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,8 @@
using System.Collections.Immutable;
using System.Linq;
using nadena.dev.ndmf.cs;
using UnityEngine;
#if NDMF_VRCSDK3_AVATARS
using VRC.SDK3.Avatars.Components;

#else
using nadena.dev.ndmf.runtime;
#endif
using UnityEngine;

#endregion

Expand Down Expand Up @@ -56,16 +51,9 @@ public static ImmutableList<Component> GetComponentsByType(this ComputeContext c

public static ImmutableList<GameObject> GetAvatarRoots(this ComputeContext ctx)
{
// TODO: multiple platform support
#if NDMF_VRCSDK3_AVATARS
return ctx.GetComponentsByType<VRCAvatarDescriptor>()
return AvatarDescriptorComponentRegistry.Instance.AvatarRootComponentTypes
.SelectMany(ctx.GetComponentsByType)
.Select(c => c.gameObject).ToImmutableList();
#else
return ctx.GetComponentsByType<Animator>()
.Select(c => c.gameObject)
.Where(g => RuntimeUtil.IsAvatarRoot(g.transform))
.ToImmutableList();
#endif
}
}
}
13 changes: 2 additions & 11 deletions Editor/PreviewSystem/ComputeContext/SingleObjectQueries.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
#region

#if NDMF_VRCSDK3_AVATARS
using VRC.SDK3.Avatars.Components;
#endif
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using JetBrains.Annotations;
using nadena.dev.ndmf.cs;
using nadena.dev.ndmf.runtime;
using UnityEngine;
using Object = UnityEngine.Object;

Expand Down Expand Up @@ -37,18 +35,11 @@ public static GameObject GetAvatarRoot(
GameObject candidate = null;
foreach (var elem in context.ObservePath(obj.transform))
{
#if NDMF_VRCSDK3_AVATARS
if (context.GetComponent<VRCAvatarDescriptor>(elem.gameObject) != null)
if (RuntimeUtil.IsAvatarRoot(elem.gameObject.transform))
{
candidate = elem.gameObject;
break;
}
#else
if (context.GetComponent<Animator>(elem.gameObject) != null)
{
candidate = elem.gameObject;
}
#endif
}

return candidate;
Expand Down
20 changes: 20 additions & 0 deletions Runtime/Attributes/AvatarDescriptorComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#region
using System;
#endregion

namespace nadena.dev.ndmf
{
/// <summary>
/// This attribute declares specific type of component as root object of an avatar.
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public sealed class AvatarDescriptorComponent : Attribute
{
public Type AvatarDescriptorComponentType { get; }

public AvatarDescriptorComponent(Type avatarDescriptorComponentType)
{
AvatarDescriptorComponentType = avatarDescriptorComponentType;
}
}
}
3 changes: 3 additions & 0 deletions Runtime/Attributes/AvatarDescriptorComponent.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 44 additions & 18 deletions Runtime/RuntimeUtil.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using nadena.dev.ndmf;
using UnityEngine;
using UnityEngine.SceneManagement;

#if NDMF_VRCSDK3_AVATARS
using VRC.SDK3.Avatars.Components;
#endif

#if NDMF_VRCSDK3_AVATARS
[assembly: AvatarDescriptorComponent(typeof(VRCAvatarDescriptor))]
#endif

namespace nadena.dev.ndmf.runtime
{
/// <summary>
Expand Down Expand Up @@ -93,14 +99,7 @@ public static string AvatarRootPath(GameObject child)
/// <returns></returns>
public static bool IsAvatarRoot(Transform target)
{
#if NDMF_VRCSDK3_AVATARS
return target.TryGetComponent<VRCAvatarDescriptor>(out _);
#else
if (!target.TryGetComponent<Animator>(out _)) return false;

var parent = target.transform.parent;
return !(parent && parent.GetComponentInParent<Animator>());
#endif
return AvatarDescriptorComponentRegistry.Instance.IsAvatarRoot(target.gameObject);
}

/// <summary>
Expand Down Expand Up @@ -129,11 +128,7 @@ public static IEnumerable<GameObject> FindAvatarRoots(GameObject root = null)
else
{
GameObject priorRoot = null;
#if NDMF_VRCSDK3_AVATARS
var candidates = root.GetComponentsInChildren<VRCAvatarDescriptor>();
#else
var candidates = root.GetComponentsInChildren<Animator>();
#endif
var candidates = AvatarDescriptorComponentRegistry.Instance.GetAvatarDescriptorsInChildren(root);
foreach (var candidate in candidates)
{

Expand Down Expand Up @@ -172,15 +167,46 @@ internal static IEnumerable<Transform> FindAvatarsInScene(Scene scene)
{
foreach (var root in scene.GetRootGameObjects())
{
#if NDMF_VRCSDK3_AVATARS
foreach (var avatar in root.GetComponentsInChildren<VRCAvatarDescriptor>())
#else
foreach (var avatar in root.GetComponentsInChildren<Animator>())
#endif
foreach (var avatar in AvatarDescriptorComponentRegistry.Instance.GetAvatarDescriptorsInChildren(root))
{
if (IsAvatarRoot(avatar.transform)) yield return avatar.transform;
}
}
}
}

public sealed class AvatarDescriptorComponentRegistry
{
public static readonly AvatarDescriptorComponentRegistry Instance = new AvatarDescriptorComponentRegistry();

public Type[] AvatarRootComponentTypes { get; }

internal bool IsAvatarRoot(GameObject gameObject)
{
foreach (var type in AvatarRootComponentTypes)
{
if (gameObject.TryGetComponent(type, out _)) return true;
}
return false;
}

internal IEnumerable<Component> GetAvatarDescriptorsInChildren(GameObject gameObject)
{
return AvatarRootComponentTypes.SelectMany(gameObject.GetComponentsInChildren);
}

AvatarDescriptorComponentRegistry(IEnumerable<Type> componentTypes)
{
AvatarRootComponentTypes = componentTypes.Distinct().ToArray();
}

AvatarDescriptorComponentRegistry() : this(
AppDomain.CurrentDomain.GetAssemblies().SelectMany(
assembly => assembly.GetCustomAttributes(typeof(AvatarDescriptorComponent), false))
.OfType<AvatarDescriptorComponent>()
.Select(attr => attr.AvatarDescriptorComponentType)
)
{
}
}
}

0 comments on commit b58f3bd

Please sign in to comment.