Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MA Merge VRM1 SpringBones #601

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
2 changes: 2 additions & 0 deletions Editor/Animation/AnimationDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ internal void OnActivate(ndmf.BuildContext context)
#if MA_VRCSDK3_AVATARS
var avatarDescriptor = context.AvatarDescriptor;

if (!avatarDescriptor) return;

foreach (var layer in avatarDescriptor.baseAnimationLayers)
{
BootstrapLayer(layer);
Expand Down
7 changes: 5 additions & 2 deletions Editor/Animation/AnimationUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,12 @@ internal static void CloneAllControllers(BuildContext context)
// This helps reduce the risk that we'll accidentally modify the original assets.

#if MA_VRCSDK3_AVATARS
context.AvatarDescriptor.baseAnimationLayers =
var avatarDescriptor = context.AvatarDescriptor;
if (!avatarDescriptor) return;

avatarDescriptor.baseAnimationLayers =
CloneLayers(context, context.AvatarDescriptor.baseAnimationLayers);
context.AvatarDescriptor.specialAnimationLayers =
avatarDescriptor.specialAnimationLayers =
CloneLayers(context, context.AvatarDescriptor.specialAnimationLayers);
#endif
}
Expand Down
2 changes: 2 additions & 0 deletions Editor/FixupPasses/FixupExpressionsMenuPass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ internal class FixupExpressionsMenuPass

internal static void FixupExpressionsMenu(BuildContext context)
{
if (!context.AvatarDescriptor) return;

context.AvatarDescriptor.customExpressions = true;

var expressionsMenu = context.AvatarDescriptor.expressionsMenu;
Expand Down
3 changes: 3 additions & 0 deletions Editor/Inspector/VRM.meta

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

31 changes: 31 additions & 0 deletions Editor/Inspector/VRM/MergeVRM1SpringBonesEditor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#if MA_VRM1

using nadena.dev.modular_avatar.core.vrm;
using UnityEditor;
using static nadena.dev.modular_avatar.core.editor.Localization;

namespace nadena.dev.modular_avatar.core.editor.vrm
{
[CustomEditor(typeof(ModularAvatarMergeVRM1SpringBones))]
internal class MergeVRM1SpringBonesEditor : MAEditorBase
{
private SerializedProperty _prop_collider_groups;
private SerializedProperty _prop_springs;

private void OnEnable()
{
_prop_collider_groups = serializedObject.FindProperty(nameof(ModularAvatarMergeVRM1SpringBones.colliderGroups));
_prop_springs = serializedObject.FindProperty(nameof(ModularAvatarMergeVRM1SpringBones.springs));
}

protected override void OnInnerInspectorGUI()
{
EditorGUILayout.PropertyField(_prop_collider_groups, G("merge_vrm1_spring_bones.collider_groups"));
EditorGUILayout.PropertyField(_prop_springs, G("merge_vrm1_spring_bones.springs"));
serializedObject.ApplyModifiedProperties();
ShowLanguageUI();
}
}
}

#endif
3 changes: 3 additions & 0 deletions Editor/Inspector/VRM/MergeVRM1SpringBonesEditor.cs.meta

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

2 changes: 2 additions & 0 deletions Editor/Localization/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@
"merge_blend_tree.path_mode.tooltip": "How to interpret paths in animations. Using relative mode lets you record animations from an animator on this object.",
"merge_blend_tree.relative_path_root": "Relative Path Root",
"merge_blend_tree.relative_path_root.tooltip": "The root object to use when interpreting relative paths. If not specified, the object this component is attached to will be used.",
"merge_vrm1_spring_bones.collider_groups": "Collider Groups",
"merge_vrm1_spring_bones.springs": "Springs",
"worldfixed.quest": "This component is not compatible with Android builds and will have no effect.",
"worldfixed.normal": "This object will be fixed to world unless you fixed to avatar with constraint.",
"fpvisible.normal": "This object will be visible in your first person view.",
Expand Down
1 change: 1 addition & 0 deletions Editor/MergeAnimatorProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ internal void OnPreprocessAvatar(GameObject avatarGameObject, BuildContext conte
mergeSessions.Clear();

var descriptor = avatarGameObject.GetComponent<VRCAvatarDescriptor>();
if (!descriptor) return;

if (descriptor.baseAnimationLayers != null) InitSessions(descriptor.baseAnimationLayers);
if (descriptor.specialAnimationLayers != null) InitSessions(descriptor.specialAnimationLayers);
Expand Down
40 changes: 40 additions & 0 deletions Editor/MergeArmatureHook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@
using UnityEditor;
using UnityEngine;
using UnityEngine.Animations;

#if MA_VRM0
using VRM;
#endif

#if MA_VRM1
using UniVRM10;
#endif

using Object = UnityEngine.Object;

#endregion
Expand Down Expand Up @@ -109,6 +118,35 @@ internal void OnPreprocessAvatar(ndmf.BuildContext context, GameObject avatarGam
}
#endif

#if MA_VRM0
foreach (var c in avatarGameObject.transform.GetComponentsInChildren<VRMSpringBone>(true))
{
RetainBoneReferences(c);
}

foreach (var c in avatarGameObject.transform.GetComponentsInChildren<VRMSpringBoneColliderGroup>(true))
{
RetainBoneReferences(c);
}
#endif

#if MA_VRM1
foreach (var c in avatarGameObject.transform.GetComponentsInChildren<VRM10SpringBoneJoint>(true))
{
RetainBoneReferences(c);
}

foreach (var c in avatarGameObject.transform.GetComponentsInChildren<VRM10SpringBoneCollider>(true))
{
RetainBoneReferences(c);
}

foreach (var c in avatarGameObject.transform.GetComponentsInChildren<VRM10SpringBoneColliderGroup>(true))
{
RetainBoneReferences(c);
}
#endif

foreach (var c in avatarGameObject.transform.GetComponentsInChildren<IConstraint>(true))
{
RetainBoneReferences(c as Component);
Expand Down Expand Up @@ -477,5 +515,7 @@ private void PruneDuplicatePhysBones()
}
}
#endif

// TODO - deduplicate VRM0/1 SpringBone components... doesn't break avatars either
}
}
27 changes: 27 additions & 0 deletions Editor/OptimizationPasses/GCGameObjectsPass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
using VRC.SDK3.Dynamics.PhysBone.Components;
#endif

#if MA_VRM0
using VRM;
#endif

namespace nadena.dev.modular_avatar.core.editor
{
/// <summary>
Expand Down Expand Up @@ -66,6 +70,13 @@ private void MarkAll()
break;
#endif

#if MA_VRM0
case VRMSpringBone sb:
MarkObject(obj);
MarkSpringBone(sb);
break;
#endif

case AvatarTagComponent _:
// Tag components will not be retained at runtime, so pretend they're not there.
break;
Expand Down Expand Up @@ -147,6 +158,22 @@ private void MarkPhysBone(VRCPhysBone pb)
}
#endif

#if MA_VRM0
private void MarkSpringBone(VRMSpringBone sb)
{
foreach (var rootBone in sb.RootBones)
{
foreach (var obj in GameObjects(rootBone.gameObject))
{
MarkObject(obj);
}
}

// Mark etc
MarkAllReferencedObjects(sb);
}
#endif

private void MarkAllReferencedObjects(Component component)
{
var so = new SerializedObject(component);
Expand Down
2 changes: 2 additions & 0 deletions Editor/OptimizationPasses/PruneParametersPass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ internal class PruneParametersPass : Pass<PruneParametersPass>
{
protected override void Execute(ndmf.BuildContext context)
{
if (!context.AvatarDescriptor) return;

var expParams = context.AvatarDescriptor.expressionParameters;
if (expParams != null && context.IsTemporaryAsset(expParams))
{
Expand Down
9 changes: 8 additions & 1 deletion Editor/PluginDefinition/PluginDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@

#endregion

#if MA_VRM0 || MA_VRM1
using nadena.dev.modular_avatar.core.editor.vrm;
#endif

[assembly: ExportsPlugin(
typeof(PluginDefinition)
)]
Expand Down Expand Up @@ -57,6 +61,9 @@ protected override void Configure()
seq.WithRequiredExtension(typeof(AnimationServicesContext), _s2 =>
{
seq.Run(MergeArmaturePluginPass.Instance);
#if MA_VRM1
seq.Run(MergeVRM1SpringBonesPass.Instance);
#endif
seq.Run(BoneProxyPluginPass.Instance);
seq.Run(VisibleHeadAccessoryPluginPass.Instance);
seq.Run("World Fixed Object",
Expand Down Expand Up @@ -125,7 +132,7 @@ protected override void Execute(ndmf.BuildContext context)
}
}

abstract class MAPass<T> : Pass<T> where T : Pass<T>, new()
internal abstract class MAPass<T> : Pass<T> where T : Pass<T>, new()
{
protected BuildContext MAContext(ndmf.BuildContext context)
{
Expand Down
2 changes: 2 additions & 0 deletions Editor/RenameParametersHook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ private void SetExpressionParameters(GameObject avatarRoot, ImmutableDictionary<
.ToImmutableDictionary();

var avatar = avatarRoot.GetComponent<VRCAvatarDescriptor>();
if (!avatar) return;

var expParams = avatar.expressionParameters;

if (expParams == null)
Expand Down
3 changes: 3 additions & 0 deletions Editor/VRM.meta

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

46 changes: 46 additions & 0 deletions Editor/VRM/MergeVRM1SpringBonesPass.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#if MA_VRM1

using System.Linq;
using nadena.dev.ndmf;
using nadena.dev.modular_avatar.core.vrm;

using UniVRM10;

namespace nadena.dev.modular_avatar.core.editor.vrm
{
internal class MergeVRM1SpringBonesPass : Pass<MergeVRM1SpringBonesPass>
{
protected override void Execute(ndmf.BuildContext context)
{
var processor = new MergeVRM1SpringBoneProcessor();
processor.ProcessVRM1(context);
}
}

internal class MergeVRM1SpringBoneProcessor
{
public void ProcessVRM1(ndmf.BuildContext context)
{
var rootTransform = context.AvatarRootObject;
var vrmInstance = rootTransform.GetComponent<Vrm10Instance>();
if (!vrmInstance) return;

var sources = rootTransform.GetComponentsInChildren<ModularAvatarMergeVRM1SpringBones>();

vrmInstance.SpringBone.ColliderGroups = vrmInstance.SpringBone.ColliderGroups
.Concat(sources.SelectMany(bone => bone.colliderGroups))
.ToList();

vrmInstance.SpringBone.Springs = vrmInstance.SpringBone.Springs
.Concat(sources.SelectMany(bone => bone.springs))
.ToList();

foreach (var source in sources)
{
UnityEngine.Object.DestroyImmediate(source);
}
}
}
}

#endif
3 changes: 3 additions & 0 deletions Editor/VRM/MergeVRM1SpringBonesPass.cs.meta

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

14 changes: 13 additions & 1 deletion Editor/nadena.dev.modular-avatar.core.editor.asmdef
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
"VRC.SDK3A",
"VRC.SDKBase",
"nadena.dev.ndmf",
"nadena.dev.ndmf.vrchat"
"nadena.dev.ndmf.vrchat",
"VRM",
"VRM10"
],
"includePlatforms": [
"Editor"
Expand Down Expand Up @@ -41,6 +43,16 @@
"name": "com.vrchat.avatars",
"expression": "",
"define": "MA_VRCSDK3_AVATARS"
},
{
"name": "com.vrmc.univrm",
"expression": "",
"define": "MA_VRM0"
},
{
"name": "com.vrmc.vrm",
"expression": "",
"define": "MA_VRM1"
}
],
"noEngineReferences": false
Expand Down
3 changes: 3 additions & 0 deletions Runtime/VRM.meta

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

18 changes: 18 additions & 0 deletions Runtime/VRM/ModularAvatarMergeVRM1SpringBones.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#if MA_VRM1

using System.Collections.Generic;
using UnityEngine;
using UniVRM10;

namespace nadena.dev.modular_avatar.core.vrm
{
[AddComponentMenu("Modular Avatar/MA Merge VRM1 SpringBones")]
[DisallowMultipleComponent]
public class ModularAvatarMergeVRM1SpringBones : AvatarTagComponent
{
public List<VRM10SpringBoneColliderGroup> colliderGroups = new List<VRM10SpringBoneColliderGroup>();
public List<Vrm10InstanceSpringBone.Spring> springs = new List<Vrm10InstanceSpringBone.Spring>();
}
}

#endif
11 changes: 11 additions & 0 deletions Runtime/VRM/ModularAvatarMergeVRM1SpringBones.cs.meta

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

14 changes: 13 additions & 1 deletion Runtime/nadena.dev.modular-avatar.core.asmdef
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
"rootNamespace": "",
"references": [
"Unity.Burst",
"nadena.dev.ndmf.runtime"
"nadena.dev.ndmf.runtime",
"VRM",
"VRM10"
],
"includePlatforms": [],
"excludePlatforms": [],
Expand All @@ -24,6 +26,16 @@
"name": "com.vrchat.avatars",
"expression": "",
"define": "MA_VRCSDK3_AVATARS"
},
{
"name": "com.vrmc.univrm",
"expression": "",
"define": "MA_VRM0"
},
{
"name": "com.vrmc.vrm",
"expression": "",
"define": "MA_VRM1"
}
],
"noEngineReferences": false
Expand Down