Restore compatibility with legacy unitypackage VRCSDKs

If this breaks again I probably won't fix it.
This commit is contained in:
bd_ 2022-11-26 12:56:32 -08:00
parent 25729dc81b
commit 0dd571e371
8 changed files with 78 additions and 44 deletions

View File

@ -23,13 +23,13 @@
*/ */
using System; using System;
using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;
using System.Reflection;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
using VRC.SDK3.Avatars.Components; using VRC.SDK3.Avatars.Components;
using VRC.SDK3.Editor;
using VRC.SDKBase.Editor.BuildPipeline; using VRC.SDKBase.Editor.BuildPipeline;
using VRC.SDKBase.Validation.Performance.Stats;
using Object = UnityEngine.Object; using Object = UnityEngine.Object;
namespace nadena.dev.modular_avatar.core.editor namespace nadena.dev.modular_avatar.core.editor
@ -139,14 +139,57 @@ namespace nadena.dev.modular_avatar.core.editor
} }
} }
// The VRCSDK captures some debug information about animators as part of the build process, prior to invoking FixupAnimatorDebugData(avatarGameObject);
// hooks. For some reason this happens in the ValidateFeatures call on the SDK builder. Reinvoke it to }
// refresh this debug info.
var avatar = avatarGameObject.GetComponent<VRCAvatarDescriptor>(); [SuppressMessage("ReSharper", "PossibleNullReferenceException")]
var animator = avatarGameObject.GetComponent<Animator>(); private static void FixupAnimatorDebugData(GameObject avatarGameObject)
var builder = new VRCSdkControlPanelAvatarBuilder3A(); {
builder.RegisterBuilder(ScriptableObject.CreateInstance<VRCSdkControlPanel>()); Object tempControlPanel = null;
builder.ValidateFeatures(avatar, animator, new AvatarPerformanceStats(false)); try
{
// The VRCSDK captures some debug information about animators as part of the build process, prior to invoking
// hooks. For some reason this happens in the ValidateFeatures call on the SDK builder. Reinvoke it to
// refresh this debug info.
//
// All of these methods are public, but for compatibility with unitypackage-based SDKs, we need to use
// reflection to invoke everything here, as the asmdef structure is different between the two SDK variants.
// Bleh.
//
// Canny filed requesting that this processing move after build hooks:
// https://feedback.vrchat.com/sdk-bug-reports/p/animator-debug-information-needs-to-be-captured-after-invoking-preprocess-avatar
var ty_VRCSdkControlPanelAvatarBuilder3A = Util.FindType(
"VRC.SDK3.Editor.VRCSdkControlPanelAvatarBuilder3A"
);
var ty_AvatarPerformanceStats = Util.FindType(
"VRC.SDKBase.Validation.Performance.Stats.AvatarPerformanceStats"
);
var ty_VRCSdkControlPanel = Util.FindType("VRCSdkControlPanel");
tempControlPanel = ScriptableObject.CreateInstance(ty_VRCSdkControlPanel) as Object;
var avatar = avatarGameObject.GetComponent<VRCAvatarDescriptor>();
var animator = avatarGameObject.GetComponent<Animator>();
var builder = ty_VRCSdkControlPanelAvatarBuilder3A.GetConstructor(Type.EmptyTypes)
.Invoke(Array.Empty<object>());
var perfStats = ty_AvatarPerformanceStats.GetConstructor(new[] {typeof(bool)})
.Invoke(new object[] {false});
ty_VRCSdkControlPanelAvatarBuilder3A
.GetMethod("RegisterBuilder", BindingFlags.Public | BindingFlags.Instance)
.Invoke(builder, new object[] {tempControlPanel});
ty_VRCSdkControlPanelAvatarBuilder3A.GetMethod("ValidateFeatures").Invoke(
builder, new object[] {avatar, animator, perfStats}
);
}
catch (Exception e)
{
Debug.LogWarning(
"[ModularAvatar] Incompatible VRCSDK version; failed to regenerate animator debug data");
Debug.LogException(e);
}
finally
{
if (tempControlPanel != null) Object.DestroyImmediate(tempControlPanel);
}
} }
} }
} }

View File

@ -57,7 +57,7 @@ namespace nadena.dev.modular_avatar.core.editor
// side-effect) causes the list to be initially cached. This call will throw a NPE because we're passing // side-effect) causes the list to be initially cached. This call will throw a NPE because we're passing
// a null GameObject, but that's okay. // a null GameObject, but that's okay.
var avatarValidation = FindType("VRC.SDK3.Validation.AvatarValidation"); var avatarValidation = Util.FindType("VRC.SDK3.Validation.AvatarValidation");
var findIllegalComponents = var findIllegalComponents =
avatarValidation?.GetMethod("FindIllegalComponents", BindingFlags.Public | BindingFlags.Static); avatarValidation?.GetMethod("FindIllegalComponents", BindingFlags.Public | BindingFlags.Static);
@ -86,7 +86,7 @@ namespace nadena.dev.modular_avatar.core.editor
} }
// Now fetch the cached allowlist and add our components to it. // Now fetch the cached allowlist and add our components to it.
var validationUtils = FindType("VRC.SDKBase.Validation.ValidationUtils"); var validationUtils = Util.FindType("VRC.SDKBase.Validation.ValidationUtils");
var whitelistedTypes = validationUtils?.GetMethod( var whitelistedTypes = validationUtils?.GetMethod(
"WhitelistedTypes", "WhitelistedTypes",
BindingFlags.Public | BindingFlags.Static, BindingFlags.Public | BindingFlags.Static,
@ -124,20 +124,5 @@ namespace nadena.dev.modular_avatar.core.editor
} }
} }
} }
private static Type FindType(string typeName)
{
Type avatarValidation = null;
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
avatarValidation = assembly.GetType(typeName);
if (avatarValidation != null)
{
break;
}
}
return avatarValidation;
}
} }
} }

View File

@ -22,11 +22,13 @@
* SOFTWARE. * SOFTWARE.
*/ */
using System;
using System.Reflection;
using JetBrains.Annotations; using JetBrains.Annotations;
using UnityEditor; using UnityEditor;
using UnityEditor.Animations; using UnityEditor.Animations;
using UnityEngine;
using VRC.SDKBase.Editor.BuildPipeline; using VRC.SDKBase.Editor.BuildPipeline;
using Object = UnityEngine.Object;
namespace nadena.dev.modular_avatar.core.editor namespace nadena.dev.modular_avatar.core.editor
{ {
@ -121,5 +123,20 @@ namespace nadena.dev.modular_avatar.core.editor
return path != null && path.StartsWith(GetGeneratedAssetsFolder() + "/"); return path != null && path.StartsWith(GetGeneratedAssetsFolder() + "/");
} }
public static Type FindType(string typeName)
{
Type avatarValidation = null;
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
avatarValidation = assembly.GetType(typeName);
if (avatarValidation != null)
{
break;
}
}
return avatarValidation;
}
} }
} }

View File

@ -2,9 +2,7 @@
"name": "nadena.dev.modular-avatar.core.editor", "name": "nadena.dev.modular-avatar.core.editor",
"references": [ "references": [
"GUID:fc900867c0f47cd49b6e2ae4ef907300", "GUID:fc900867c0f47cd49b6e2ae4ef907300",
"GUID:5718fb738711cd34ea54e9553040911d", "GUID:5718fb738711cd34ea54e9553040911d"
"GUID:6e9c6119ac4eb334284fb7b4bc6d1f05",
"GUID:b906909fcc54f634db50f2cad0f988d9"
], ],
"includePlatforms": [ "includePlatforms": [
"Editor" "Editor"

View File

@ -12,6 +12,7 @@
"url": "", "url": "",
"repo": "https://vpm.nadena.dev/vpm.json", "repo": "https://vpm.nadena.dev/vpm.json",
"dependencies": { "dependencies": {
"com.unity.nuget.newtonsoft-json": "2.0.0"
}, },
"vpmDependencies": { "vpmDependencies": {
"com.vrchat.base": "3.1.9", "com.vrchat.base": "3.1.9",

View File

@ -145,7 +145,9 @@
"version": "file:nadena.dev.modular-avatar", "version": "file:nadena.dev.modular-avatar",
"depth": 0, "depth": 0,
"source": "embedded", "source": "embedded",
"dependencies": {} "dependencies": {
"com.unity.nuget.newtonsoft-json": "2.0.0"
}
}, },
"com.unity.modules.ai": { "com.unity.modules.ai": {
"version": "1.0.0", "version": "1.0.0",

View File

@ -19,12 +19,6 @@ be made prior to version 1.0. As such, it is not recommended to distribute prefa
::: :::
:::caution
Modular Avatar is currently only compatible with installations of the VRCSDK that use the VRChat Creator Companion.
:::
To install Modular Avatar, download and import the `unitypackage` file from the "Assets" section on [the latest release](https://github.com/bdunderscore/modular-avatar/releases). To install Modular Avatar, download and import the `unitypackage` file from the "Assets" section on [the latest release](https://github.com/bdunderscore/modular-avatar/releases).
Then, check out one of the tutorials below: Then, check out one of the tutorials below:

View File

@ -16,12 +16,6 @@ Modular Avatarは開発途中であり、まだ本格運用が非推奨です。
::: :::
:::caution
現在、Modular AvatarはVRChat Creator Companionを使ったVRCSDKのインストールのみに対応しています。
:::
Modular Avatarをインストールするには、[最新リリース]のAssets項目から`unitypackage`ファイルをダウンロードして、インポートしてください。 Modular Avatarをインストールするには、[最新リリース]のAssets項目から`unitypackage`ファイルをダウンロードして、インポートしてください。
その後の手順に関しては以下のチュートリアルを見てください その後の手順に関しては以下のチュートリアルを見てください