fix: workaround issues with double-Armature hack (#436)

fixes: #308
This commit is contained in:
bd_ 2023-09-15 21:00:08 +09:00 committed by GitHub
parent ee8b6d3119
commit 685e690d3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 87 additions and 2 deletions

View File

@ -0,0 +1,21 @@
using modular_avatar_tests;
using nadena.dev.modular_avatar.core;
using NUnit.Framework;
public class AvatarObjectReferenceTest : TestBase
{
[Test]
public void whenFakeArmaturePresent_bindsToRealArmature()
{
var root = CreateRoot("root");
var fake_armature = CreateChild(root, "Armature");
var real_armature = CreateChild(root, "Armature");
var hips = CreateChild(real_armature, "Hips");
var reference = new AvatarObjectReference();
reference.referencePath = "Armature";
Assert.AreEqual(real_armature, reference.Get(root.transform));
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bb23d6c06929440e999c855d3b9f70fc
timeCreated: 1694775902

View File

@ -1,4 +1,5 @@
using modular_avatar_tests; using System.Linq;
using modular_avatar_tests;
using nadena.dev.modular_avatar.core.editor; using nadena.dev.modular_avatar.core.editor;
using NUnit.Framework; using NUnit.Framework;
using UnityEngine; using UnityEngine;
@ -38,4 +39,22 @@ public class GameObjectGC : TestBase
Assert.True(bone2 != null); Assert.True(bone2 != null);
Assert.True(bone3 == null); Assert.True(bone3 == null);
} }
[Test]
public void RetainArmatureHack()
{
var fake_humanoid = CreatePrefab("FakeHumanoid.prefab");
var avdesc = fake_humanoid.GetComponent<VRCAvatarDescriptor>();
var armature = new GameObject();
armature.name = "Armature";
armature.transform.parent = fake_humanoid.transform;
armature.transform.SetSiblingIndex(0);
new GCGameObjectsPass(new BuildContext(avdesc), fake_humanoid).OnPreprocessAvatar();
AvatarProcessor.ProcessAvatar(fake_humanoid);
Assert.AreEqual(2,
avdesc.GetComponentsInChildren<Transform>().Count(t => t.gameObject.name == "Armature"));
}
} }

View File

@ -99,6 +99,28 @@ namespace nadena.dev.modular_avatar.core.editor
MarkObject(t.gameObject); MarkObject(t.gameObject);
} }
} }
// https://github.com/bdunderscore/modular-avatar/issues/308
// If we have duplicate Armature bones, retain them all in order to deal with some horrible hacks that are
// in use in the wild.
try
{
var trueArmature = animator?.GetBoneTransform(HumanBodyBones.Hips)?.parent;
if (trueArmature != null)
{
foreach (Transform t in _root.transform)
{
if (t.name == trueArmature.name)
{
MarkObject(t.gameObject);
}
}
}
}
catch (MissingComponentException e)
{
// No animator? weird. Move on.
}
} }
private void MarkPhysBone(VRCPhysBone pb) private void MarkPhysBone(VRCPhysBone pb)

View File

@ -39,7 +39,27 @@ namespace nadena.dev.modular_avatar.core
return _cachedReference; return _cachedReference;
} }
return (_cachedReference = avatar.transform.Find(referencePath)?.gameObject); _cachedReference = avatar.transform.Find(referencePath)?.gameObject;
if (_cachedReference == null) return null;
// https://github.com/bdunderscore/modular-avatar/issues/308
// Some avatars have multiple "Armature" objects in order to confuse VRChat into changing the avatar eye
// position. We need to be smarter than VRChat and find the "true" armature in this case.
var targetName = _cachedReference.name;
var parent = _cachedReference.transform.parent;
if (targetName == "Armature" && parent != null && _cachedReference.transform.childCount == 0)
{
foreach (Transform possibleTarget in parent)
{
if (possibleTarget.gameObject.name == targetName && possibleTarget.childCount > 0)
{
_cachedReference = possibleTarget.gameObject;
break;
}
}
}
return _cachedReference;
} }
public void Set(GameObject target) public void Set(GameObject target)