From 76eca08c221831f06115705afeeb76d7c22e9c29 Mon Sep 17 00:00:00 2001 From: bd_ Date: Sun, 1 Dec 2024 12:30:49 -0800 Subject: [PATCH] feat: Sync Parameter Sequence --- .../Inspector/SyncParameterSequenceEditor.cs | 101 +++++++ .../SyncParameterSequenceEditor.cs.meta | 3 + Editor/Localization/en-US.json | 10 +- Editor/Localization/ja-JP.json | 10 +- Editor/PluginDefinition/PluginDefinition.cs | 3 +- Editor/SyncParameterSequencePass.cs | 118 ++++++++ Editor/SyncParameterSequencePass.cs.meta | 3 + Runtime/ModularAvatarSyncParameterSequence.cs | 31 +++ ...ModularAvatarSyncParameterSequence.cs.meta | 11 + UnitTests~/SyncParameterSequence.meta | 3 + .../SyncParameterSequenceTest.cs | 251 ++++++++++++++++++ .../SyncParameterSequenceTest.cs.meta | 3 + .../docs/reference/sync-parameter-sequence.md | 38 +++ .../reference/sync-parameter-sequence.png | Bin 0 -> 30572 bytes .../reference/sync-parameter-sequence.md | 32 +++ .../reference/sync-parameter-sequence.png | Bin 0 -> 30910 bytes 16 files changed, 614 insertions(+), 3 deletions(-) create mode 100644 Editor/Inspector/SyncParameterSequenceEditor.cs create mode 100644 Editor/Inspector/SyncParameterSequenceEditor.cs.meta create mode 100644 Editor/SyncParameterSequencePass.cs create mode 100644 Editor/SyncParameterSequencePass.cs.meta create mode 100644 Runtime/ModularAvatarSyncParameterSequence.cs create mode 100644 Runtime/ModularAvatarSyncParameterSequence.cs.meta create mode 100644 UnitTests~/SyncParameterSequence.meta create mode 100644 UnitTests~/SyncParameterSequence/SyncParameterSequenceTest.cs create mode 100644 UnitTests~/SyncParameterSequence/SyncParameterSequenceTest.cs.meta create mode 100644 docs~/docs/reference/sync-parameter-sequence.md create mode 100644 docs~/docs/reference/sync-parameter-sequence.png create mode 100644 docs~/i18n/ja/docusaurus-plugin-content-docs/current/reference/sync-parameter-sequence.md create mode 100644 docs~/i18n/ja/docusaurus-plugin-content-docs/current/reference/sync-parameter-sequence.png diff --git a/Editor/Inspector/SyncParameterSequenceEditor.cs b/Editor/Inspector/SyncParameterSequenceEditor.cs new file mode 100644 index 00000000..284e5fa1 --- /dev/null +++ b/Editor/Inspector/SyncParameterSequenceEditor.cs @@ -0,0 +1,101 @@ +using System; +using UnityEditor; +using UnityEngine; +using VRC.SDK3.Avatars.ScriptableObjects; +using static nadena.dev.modular_avatar.core.editor.Localization; + +namespace nadena.dev.modular_avatar.core.editor +{ + [CustomEditor(typeof(ModularAvatarSyncParameterSequence))] + [CanEditMultipleObjects] + public class SyncParameterSequenceEditor : MAEditorBase + { + private SerializedProperty _p_platform; + private SerializedProperty _p_parameters; + + private void OnEnable() + { + _p_platform = serializedObject.FindProperty(nameof(ModularAvatarSyncParameterSequence.PrimaryPlatform)); + _p_parameters = serializedObject.FindProperty(nameof(ModularAvatarSyncParameterSequence.Parameters)); + } + + protected override void OnInnerInspectorGUI() + { + serializedObject.Update(); + + EditorGUI.BeginChangeCheck(); + +#if MA_VRCSDK3_AVATARS + var disable = false; +#else + bool disable = true; +#endif + + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + if (disable) + // ReSharper disable HeuristicUnreachableCode + { + EditorGUILayout.HelpBox(S("general.vrcsdk-required"), MessageType.Warning); + } + // ReSharper restore HeuristicUnreachableCode + + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + using (new EditorGUI.DisabledGroupScope(disable)) + { + EditorGUILayout.PropertyField(_p_platform, G("sync-param-sequence.platform")); + GUILayout.BeginHorizontal(); + + var label = G("sync-param-sequence.parameters"); + var sizeCalc = EditorStyles.objectField.CalcSize(label); + EditorGUILayout.PropertyField(_p_parameters, label); + + if (GUILayout.Button(G("sync-param-sequence.create-asset"), + GUILayout.ExpandWidth(false), + GUILayout.Height(sizeCalc.y) + )) + { + CreateParameterAsset(); + } + + GUILayout.EndHorizontal(); + } + + if (EditorGUI.EndChangeCheck()) + { + serializedObject.ApplyModifiedProperties(); + } + + ShowLanguageUI(); + } + + private void CreateParameterAsset() + { +#if MA_VRCSDK3_AVATARS + Transform avatarRoot = null; + if (targets.Length == 1) + { + avatarRoot = + RuntimeUtil.FindAvatarTransformInParents(((ModularAvatarSyncParameterSequence)target).transform); + } + + var assetName = "Avatar"; + if (avatarRoot != null) assetName = avatarRoot.gameObject.name; + + assetName += " SyncedParams"; + + var file = EditorUtility.SaveFilePanelInProject("Create new parameter asset", assetName, "asset", + "Create a new parameter asset"); + + var obj = CreateInstance(); + obj.parameters = Array.Empty(); + obj.isEmpty = true; + + AssetDatabase.CreateAsset(obj, file); + Undo.RegisterCreatedObjectUndo(obj, "Create parameter asset"); + + _p_parameters.objectReferenceValue = obj; + serializedObject.ApplyModifiedProperties(); +#endif + } + } +} \ No newline at end of file diff --git a/Editor/Inspector/SyncParameterSequenceEditor.cs.meta b/Editor/Inspector/SyncParameterSequenceEditor.cs.meta new file mode 100644 index 00000000..e0d762ac --- /dev/null +++ b/Editor/Inspector/SyncParameterSequenceEditor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bf6030b7fa704997885767897d1acba0 +timeCreated: 1733090792 \ No newline at end of file diff --git a/Editor/Localization/en-US.json b/Editor/Localization/en-US.json index cc468249..7609d0d0 100644 --- a/Editor/Localization/en-US.json +++ b/Editor/Localization/en-US.json @@ -153,6 +153,7 @@ "error.replace_object.null_target:hint": "Replace object needs a target object to replace. Try setting one.", "error.replace_object.replacing_replacement": "[MA-0009] The same target object cannot be specified in multiple Replace Object components", "error.replace_object.parent_of_target": "[MA-0010] The target object cannot be a parent of this object", + "error.singleton": "[MA-0011] Only one instance of {0} is allowed in an avatar", "validation.blendshape_sync.no_local_renderer": "[MA-1000] No renderer found on this object", "validation.blendshape_sync.no_local_renderer:hint": "Blendshape Sync acts on a Skinned Mesh Renderer on the same GameObject. Did you attach it to the right object?", "validation.blendshape_sync.no_local_mesh": "[MA-1001] No mesh found on the renderer on this object", @@ -287,5 +288,12 @@ "ro_sim.effect_group.conditions": "Conditions", "remove-vertex-color.mode": "Mode", "remove-vertex-color.mode.Remove": "Remove Vertex Colors", - "remove-vertex-color.mode.DontRemove": "Keep Vertex Colors" + "remove-vertex-color.mode.DontRemove": "Keep Vertex Colors", + "general.vrcsdk-required": "This component requires the VRCSDK to function.", + "sync-param-sequence.platform": "Primary Platform", + "sync-param-sequence.platform.tooltip": "When building for this platform, Modular Avatar will record all expression parameters for use on other platform builds", + "sync-param-sequence.parameters": "Common parameters asset", + "sync-param-sequence.parameters.tooltip": "The asset to store common parameters in. Do not use the same Expression Parameters that you have set in your avatar descriptor.", + "sync-param-sequence.create-asset": "New", + "sync-param-sequence.create-asset.tooltip": "Creates a new expression parameters asset" } diff --git a/Editor/Localization/ja-JP.json b/Editor/Localization/ja-JP.json index 14640e70..269545ff 100644 --- a/Editor/Localization/ja-JP.json +++ b/Editor/Localization/ja-JP.json @@ -149,6 +149,7 @@ "error.replace_object.null_target:hint": "Replace Objectは置き換え先のオブジェクトを指定する必要があります。", "error.replace_object.replacing_replacement": "[MA-0009] 複数のReplace Objectコンポーネントで、同じ置き換え先を指定できません", "error.replace_object.parent_of_target": "[MA-0010] このオブジェクトの親を置き換え先に指定できません", + "error.singleton": "[MA-0011] {0} はアバターに一個しか存在できません", "validation.blendshape_sync.no_local_renderer": "[MA-1000] このオブジェクトにはSkinned Mesh Rendererがありません。", "validation.blendshape_sync.no_local_renderer:hint": "Blendshape Syncは同じGameObject上のSkinned Mesh Rendererに作用します。コンポーネントが正しいオブジェクトに追加されているか確認してください。", "validation.blendshape_sync.no_local_mesh": "[MA-1001] このオブジェクトにはSkinned Mesh Rendererがありますが、メッシュがありません。", @@ -279,5 +280,12 @@ "ro_sim.effect_group.conditions": "条件", "remove-vertex-color.mode": "モード", "remove-vertex-color.mode.Remove": "頂点カラーを削除する", - "remove-vertex-color.mode.DontRemove": "頂点カラーを削除しない" + "remove-vertex-color.mode.DontRemove": "頂点カラーを削除しない", + "general.vrcsdk-required": "このコンポーネントにはVRCSDKが必要です。", + "sync-param-sequence.platform": "主要プラットホーム", + "sync-param-sequence.platform.tooltip": "このプラットホームでビルドすると、他のプラットホームを合わせるためにパラメーターを記録します。", + "sync-param-sequence.parameters": "共用パラメーターアセット", + "sync-param-sequence.parameters.tooltip": "共用パラメーターがこのアセットに保持されます。アバターデスクリプターに使われるアセットを流用しないでください。", + "sync-param-sequence.create-asset": "新規作成", + "sync-param-sequence.create-asset.tooltip": "新しい共用パラメーターアセットを作成します" } diff --git a/Editor/PluginDefinition/PluginDefinition.cs b/Editor/PluginDefinition/PluginDefinition.cs index 9be466c9..ffc77033 100644 --- a/Editor/PluginDefinition/PluginDefinition.cs +++ b/Editor/PluginDefinition/PluginDefinition.cs @@ -88,8 +88,9 @@ namespace nadena.dev.modular_avatar.core.editor.plugin var maContext = ctx.Extension().BuildContext; FixupExpressionsMenuPass.FixupExpressionsMenu(maContext); }); - seq.Run(RemoveVertexColorPass.Instance).PreviewingWith(new RemoveVertexColorPreview()); + seq.Run(SyncParameterSequencePass.Instance); #endif + seq.Run(RemoveVertexColorPass.Instance).PreviewingWith(new RemoveVertexColorPreview()); seq.Run(RebindHumanoidAvatarPass.Instance); seq.Run("Purge ModularAvatar components", ctx => { diff --git a/Editor/SyncParameterSequencePass.cs b/Editor/SyncParameterSequencePass.cs new file mode 100644 index 00000000..e6e83d37 --- /dev/null +++ b/Editor/SyncParameterSequencePass.cs @@ -0,0 +1,118 @@ +#nullable enable + +using System; +using System.Collections.Specialized; +using System.Linq; +using nadena.dev.modular_avatar.editor.ErrorReporting; +using nadena.dev.ndmf; +using UnityEditor; +using VRC.SDK3.Avatars.ScriptableObjects; +using static nadena.dev.modular_avatar.core.ModularAvatarSyncParameterSequence; +using Object = UnityEngine.Object; + +namespace nadena.dev.modular_avatar.core.editor +{ + public class SyncParameterSequencePass : Pass + { + private static Platform? CurrentPlatform + { + get + { + switch (EditorUserBuildSettings.activeBuildTarget) + { + case BuildTarget.Android: return Platform.Android; + case BuildTarget.iOS: return Platform.iOS; + case BuildTarget.StandaloneWindows64: return Platform.PC; + case BuildTarget.StandaloneLinux64: return Platform.PC; // for CI + default: return null; + } + } + } + + protected override void Execute(ndmf.BuildContext context) + { + ExecuteStatic(context); + } + + internal static void ExecuteStatic(ndmf.BuildContext context) + { + var avDesc = context.AvatarDescriptor; + + var components = context.AvatarRootObject.GetComponentsInChildren(true); + if (components.Length == 0) return; + if (components.Length > 1) + { + BuildReport.LogFatal("error.singleton", "Sync Parameter Sequence", components.Cast().ToArray()); + return; + } + + var syncComponent = components[0]; + if (syncComponent.Parameters == null) return; + + if (avDesc.expressionParameters == null) return; + var avatarParams = avDesc.expressionParameters; + + if (!context.IsTemporaryAsset(avatarParams)) + { + avatarParams = Object.Instantiate(avatarParams); + avDesc.expressionParameters = avatarParams; + } + + if (syncComponent.Parameters.parameters == null) + { + syncComponent.Parameters.parameters = Array.Empty(); + EditorUtility.SetDirty(syncComponent.Parameters); + } + + // If we're on the primary platform, add in any unknown parameters, and prune if we exceed the limit. + if (CurrentPlatform != null && CurrentPlatform == syncComponent.PrimaryPlatform) + { + var registered = new OrderedDictionary(); + + foreach (var param in syncComponent.Parameters.parameters) + { + if (param == null) continue; + if (!param.networkSynced) continue; + registered[param.name] = param; + } + + foreach (var param in avatarParams.parameters) + { + if (param == null) continue; + if (!param.networkSynced) continue; + registered[param.name] = param; + } + + syncComponent.Parameters.parameters = registered.Values.Cast().ToArray(); + if (!syncComponent.Parameters.IsWithinBudget()) + { + var knownParams = avatarParams.parameters.Where(p => p != null).Select(p => p.name).ToHashSet(); + syncComponent.Parameters.parameters = syncComponent.Parameters.parameters.Where( + p => p != null && knownParams.Contains(p.name) + ).ToArray(); + } + + EditorUtility.SetDirty(syncComponent.Parameters); + } + + // Now copy back... + OrderedDictionary finalParams = new(); + foreach (var param in syncComponent.Parameters.parameters) + { + if (param == null) continue; + if (!param.networkSynced) continue; + finalParams[param.name] = param; + } + + foreach (var param in avatarParams.parameters) + { + if (param == null) continue; + finalParams[param.name] = param; + } + + avatarParams.parameters = finalParams.Values.Cast().ToArray(); + + EditorUtility.SetDirty(avatarParams); + } + } +} \ No newline at end of file diff --git a/Editor/SyncParameterSequencePass.cs.meta b/Editor/SyncParameterSequencePass.cs.meta new file mode 100644 index 00000000..cd61ea01 --- /dev/null +++ b/Editor/SyncParameterSequencePass.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 756425df8aeb4926afceda71bedffa40 +timeCreated: 1733011801 \ No newline at end of file diff --git a/Runtime/ModularAvatarSyncParameterSequence.cs b/Runtime/ModularAvatarSyncParameterSequence.cs new file mode 100644 index 00000000..e721a9ef --- /dev/null +++ b/Runtime/ModularAvatarSyncParameterSequence.cs @@ -0,0 +1,31 @@ +using System; +using JetBrains.Annotations; +using UnityEngine; +using VRC.SDK3.Avatars.ScriptableObjects; + +namespace nadena.dev.modular_avatar.core +{ + [AddComponentMenu("Modular Avatar/MA Sync Parameter Sequence")] + [DisallowMultipleComponent] + [HelpURL("https://modular-avatar.nadena.dev/docs/reference/sync-parameter-sequence?lang=auto")] + [PublicAPI] + public class ModularAvatarSyncParameterSequence : AvatarTagComponent + { + [Serializable] + [PublicAPI] + public enum Platform + { + PC, + Android, + iOS + } + + public Platform PrimaryPlatform = Platform.Android; + #if MA_VRCSDK3_AVATARS + public VRCExpressionParameters Parameters; + #else + // preserve settings on non-VRC platforms at least + public UnityEngine.Object Parameters; + #endif + } +} \ No newline at end of file diff --git a/Runtime/ModularAvatarSyncParameterSequence.cs.meta b/Runtime/ModularAvatarSyncParameterSequence.cs.meta new file mode 100644 index 00000000..051758ba --- /dev/null +++ b/Runtime/ModularAvatarSyncParameterSequence.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 934543afe4744213b5621aa13a67e3b4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: a8edd5bd1a0a64a40aa99cc09fb5f198, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnitTests~/SyncParameterSequence.meta b/UnitTests~/SyncParameterSequence.meta new file mode 100644 index 00000000..ef65c7de --- /dev/null +++ b/UnitTests~/SyncParameterSequence.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 7b09a147690448ac94d495e90c761c0d +timeCreated: 1733093978 \ No newline at end of file diff --git a/UnitTests~/SyncParameterSequence/SyncParameterSequenceTest.cs b/UnitTests~/SyncParameterSequence/SyncParameterSequenceTest.cs new file mode 100644 index 00000000..73c5eb33 --- /dev/null +++ b/UnitTests~/SyncParameterSequence/SyncParameterSequenceTest.cs @@ -0,0 +1,251 @@ +#if MA_VRCSDK3_AVATARS + +using modular_avatar_tests; +using nadena.dev.modular_avatar.core; +using nadena.dev.modular_avatar.core.editor; +using NUnit.Framework; +using UnityEditor; +using UnityEngine; +using VRC.SDK3.Avatars.Components; +using VRC.SDK3.Avatars.ScriptableObjects; + +namespace UnitTests.SyncParameterSequence +{ + public class SyncParameterSequenceTest : TestBase + { + [Test] + public void NonPrimaryPlatform() + { + ModularAvatarSyncParameterSequence.Platform platform; + switch (EditorUserBuildSettings.activeBuildTarget) + { + case BuildTarget.Android: + platform = ModularAvatarSyncParameterSequence.Platform.PC; + break; + default: + platform = ModularAvatarSyncParameterSequence.Platform.Android; + break; + } + + var root = CreateRoot("root"); + var avdesc = root.GetComponent(); + + var expParams = ScriptableObject.CreateInstance(); + + expParams.parameters = new[] + { + new VRCExpressionParameters.Parameter() + { + name = "p1", + valueType = VRCExpressionParameters.ValueType.Bool, + networkSynced = true, + defaultValue = 0.5f, + }, + new VRCExpressionParameters.Parameter() + { + name = "p2", + valueType = VRCExpressionParameters.ValueType.Int, + networkSynced = true, + defaultValue = 0.5f, + } + }; + + var refParams = ScriptableObject.CreateInstance(); + refParams.parameters = new[] + { + new VRCExpressionParameters.Parameter() + { + name = "p0", + valueType = VRCExpressionParameters.ValueType.Bool, + networkSynced = true + }, + new VRCExpressionParameters.Parameter() + { + name = "p2", + valueType = VRCExpressionParameters.ValueType.Int, + networkSynced = true + } + }; + + var c = avdesc.gameObject.AddComponent(); + c.PrimaryPlatform = platform; + c.Parameters = refParams; + + avdesc.expressionParameters = expParams; + + var context = CreateContext(root); + SyncParameterSequencePass.ExecuteStatic(context); + + expParams = avdesc.expressionParameters; + + Assert.AreEqual("p0", expParams.parameters[0].name); + Assert.AreEqual("p2", expParams.parameters[1].name); + Assert.AreEqual("p1", expParams.parameters[2].name); + + Assert.IsTrue(Mathf.Approximately(0f, expParams.parameters[0].defaultValue)); + Assert.IsTrue(Mathf.Approximately(0.5f, expParams.parameters[1].defaultValue)); + Assert.IsTrue(Mathf.Approximately(0.5f, expParams.parameters[2].defaultValue)); + + Assert.AreEqual(2, refParams.parameters.Length); + } + + [Test] + public void PrimaryPlatform() + { + ModularAvatarSyncParameterSequence.Platform platform; + switch (EditorUserBuildSettings.activeBuildTarget) + { + case BuildTarget.Android: + platform = ModularAvatarSyncParameterSequence.Platform.Android; + break; + default: + platform = ModularAvatarSyncParameterSequence.Platform.PC; + break; + } + + var root = CreateRoot("root"); + var avdesc = root.GetComponent(); + + var expParams = ScriptableObject.CreateInstance(); + + expParams.parameters = new[] + { + new VRCExpressionParameters.Parameter() + { + name = "p1", + valueType = VRCExpressionParameters.ValueType.Bool, + networkSynced = true, + defaultValue = 0.5f, + }, + new VRCExpressionParameters.Parameter() + { + name = "p2", + valueType = VRCExpressionParameters.ValueType.Int, + networkSynced = true, + defaultValue = 0.5f, + }, + new VRCExpressionParameters.Parameter() { + name = "notsynced", + valueType = VRCExpressionParameters.ValueType.Int, + networkSynced = false, + } + }; + + var refParams = ScriptableObject.CreateInstance(); + refParams.parameters = new[] + { + new VRCExpressionParameters.Parameter() + { + name = "p0", + valueType = VRCExpressionParameters.ValueType.Bool, + networkSynced = true + }, + new VRCExpressionParameters.Parameter() + { + name = "p2", + valueType = VRCExpressionParameters.ValueType.Int, + networkSynced = true + } + }; + + var c = avdesc.gameObject.AddComponent(); + c.PrimaryPlatform = platform; + c.Parameters = refParams; + + avdesc.expressionParameters = expParams; + + var context = CreateContext(root); + SyncParameterSequencePass.ExecuteStatic(context); + + expParams = avdesc.expressionParameters; + + Assert.AreEqual("p0", expParams.parameters[0].name); + Assert.AreEqual("p2", expParams.parameters[1].name); + Assert.AreEqual("p1", expParams.parameters[2].name); + Assert.AreEqual("notsynced", expParams.parameters[3].name); + + Assert.IsTrue(Mathf.Approximately(0f, expParams.parameters[0].defaultValue)); + Assert.IsTrue(Mathf.Approximately(0.5f, expParams.parameters[1].defaultValue)); + Assert.IsTrue(Mathf.Approximately(0.5f, expParams.parameters[2].defaultValue)); + + Assert.AreEqual(3, refParams.parameters.Length); + Assert.AreEqual("p0", refParams.parameters[0].name); + Assert.AreEqual("p2", refParams.parameters[1].name); + Assert.AreEqual("p1", refParams.parameters[2].name); + } + + + [Test] + public void PrimaryPlatformOverflow() + { + ModularAvatarSyncParameterSequence.Platform platform; + switch (EditorUserBuildSettings.activeBuildTarget) + { + case BuildTarget.Android: + platform = ModularAvatarSyncParameterSequence.Platform.Android; + break; + default: + platform = ModularAvatarSyncParameterSequence.Platform.PC; + break; + } + + var root = CreateRoot("root"); + var avdesc = root.GetComponent(); + + var expParams = ScriptableObject.CreateInstance(); + + expParams.parameters = new[] + { + new VRCExpressionParameters.Parameter() + { + name = "p1", + valueType = VRCExpressionParameters.ValueType.Bool, + networkSynced = true, + defaultValue = 0.5f, + }, + new VRCExpressionParameters.Parameter() + { + name = "p2", + valueType = VRCExpressionParameters.ValueType.Int, + networkSynced = true, + defaultValue = 0.5f, + } + }; + + var refParams = ScriptableObject.CreateInstance(); + var paramList = new System.Collections.Generic.List(); + for (int i = 0; i < VRCExpressionParameters.MAX_PARAMETER_COST; i++) + { + paramList.Add(new() + { + name = "b" + i, + valueType = VRCExpressionParameters.ValueType.Bool, + networkSynced = true + }); + } + + refParams.parameters = paramList.ToArray(); + + var c = avdesc.gameObject.AddComponent(); + c.PrimaryPlatform = platform; + c.Parameters = refParams; + + avdesc.expressionParameters = expParams; + + var context = CreateContext(root); + SyncParameterSequencePass.ExecuteStatic(context); + + expParams = avdesc.expressionParameters; + + Assert.AreEqual(2, expParams.parameters.Length); + Assert.AreEqual("p1", expParams.parameters[0].name); + Assert.AreEqual("p2", expParams.parameters[1].name); + + Assert.AreEqual(2, refParams.parameters.Length); + Assert.AreEqual("p1", refParams.parameters[0].name); + Assert.AreEqual("p2", refParams.parameters[1].name); + } + } +} + +#endif \ No newline at end of file diff --git a/UnitTests~/SyncParameterSequence/SyncParameterSequenceTest.cs.meta b/UnitTests~/SyncParameterSequence/SyncParameterSequenceTest.cs.meta new file mode 100644 index 00000000..9611d253 --- /dev/null +++ b/UnitTests~/SyncParameterSequence/SyncParameterSequenceTest.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 37fcaa6b7094408eac945c2887a1101e +timeCreated: 1733093994 \ No newline at end of file diff --git a/docs~/docs/reference/sync-parameter-sequence.md b/docs~/docs/reference/sync-parameter-sequence.md new file mode 100644 index 00000000..1505195f --- /dev/null +++ b/docs~/docs/reference/sync-parameter-sequence.md @@ -0,0 +1,38 @@ +# Sync Parameter Sequence + +![Sync Parameter Sequence](sync-parameter-sequence.png) + +On VRChat, it's necessary for parameters that are shared between different-platforms of an avatar (e.g. PC and Android) +to appear at the start of the expressions parameters list, and in the same order. This component adjusts the order of +your expressions parameters, and adds additional parameters where necessary, to ensure that your avatar syncs properly +between PC and Android. + +## When should I use it? + +You should use this component if you are uploading different versions of the same avatar to PC and Android, and both +versions make use of synced expressions parameters. + +## When shouldn't I use it? + +This component may have compatibility issues with certain VRCFury components, such as Parameter Compressor. + +## How should I use it? + +First, attach the Sync Parameter Sequence component to any object on your avatar. Then, click the New button to create +an asset to save the parameter sequence. On other platform variants of your avatar, attach the component, and select the +asset you just created. Upload on Android (or whichever platform you want to be the primary platform), then upload for +other platforms as well. + +Whenever you upload your avatar on the platform listed as "Primary Platform", Modular Avatar will record its expression +parameters in this asset. Then, later, when you upload on some other platform, Modular Avatar will adjust the order of +the parameters to match the primary platform. + +## Parameter limits + +The Sync Parameter Sequence component will add additional parameters to your avatar if necessary to ensure that the +order of parameters matches between platforms. This may cause your avatar to exceed the maximum number of parameters, +in which case the build will fail. + +To address this, you can clear the contents of the parameters asset to clear out obsolete parameters; otherwise, make +sure you don't have a lot of both android-only and PC-only parameters, because you'll end up using the combination of +both. \ No newline at end of file diff --git a/docs~/docs/reference/sync-parameter-sequence.png b/docs~/docs/reference/sync-parameter-sequence.png new file mode 100644 index 0000000000000000000000000000000000000000..0bc7c83f2b46acafd2fdb4cdaf4083e8fced4c83 GIT binary patch literal 30572 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 Yku>G81x@n+n2?L6rmUq@reFsDFO)-w&;S4c literal 0 HcmV?d00001 diff --git a/docs~/i18n/ja/docusaurus-plugin-content-docs/current/reference/sync-parameter-sequence.md b/docs~/i18n/ja/docusaurus-plugin-content-docs/current/reference/sync-parameter-sequence.md new file mode 100644 index 00000000..11e7ffee --- /dev/null +++ b/docs~/i18n/ja/docusaurus-plugin-content-docs/current/reference/sync-parameter-sequence.md @@ -0,0 +1,32 @@ +# Sync Parameter Sequence + +![Sync Parameter Sequence](sync-parameter-sequence.png) + +VRChatでは、異なるプラットフォーム間で共有されるパラメータ(例:PCとAndroid)が、パラメータリストの先頭に、同じ順序で登録してある必要が +あります。このコンポーネントは、アバターがPCとAndroid間で正しく同期するために、表情パラメータの順序を調整し、必要に応じてパラメータを追加します。 + +## いつ使うべきか? + +同じアバターの異なるバージョンをPCとAndroidにアップロードし、両方のバージョンが同期パラメータを使用する場合、このコンポーネントを使用すると +便利です。 + +## 使わない方がいい場合 + +このコンポーネントは、Parameter Compressorなど一部のVRCFuryコンポーネントと互換性問題がある可能性があります。 + +## 使い方 + +まず、Sync Parameter Sequenceコンポーネントをアバターの任意のオブジェクトに追加します。次に、「新規作成」ボタンをクリックして、パラメータ +順序を保存するアセットを作成します。アバターの他のプラットフォーム用のバージョンに同じくコンポーネントを追加し、作成したアセットをセットします。 +Android(あるいは主要プラットホームで選択したプラットフォーム)でアップロードし、そのあとに他のプラットフォームにもアップロードします。 + +「主要プラットフォーム」として設定されたプラットフォームでアバターをアップロードするたびに、Modular Avatarはパラメータリストをアセットに +記録します。その後、他のプラットフォームにアップロードする際に、Modular Avatarはパラメータの順序を主要プラットフォームに合わせて調整します。 + +## パラメータ制限について + +Sync Parameter Sequenceコンポーネントは、パラメータの順序が一致するように必要に応じてアバターにパラメータを追加します。これにより、 +アバターがパラメータの最大数を超える可能性があり、ビルドが失敗することがあります。 + +解決するために、パラメータアセットの内容をクリアして、不要なパラメータを削除するか、Android専用のパラメータとPC専用のパラメータの +両方を多く持っていないことを確認してください。そうしないと、両方の組み合わせを登録して限界を超えることになります。 \ No newline at end of file diff --git a/docs~/i18n/ja/docusaurus-plugin-content-docs/current/reference/sync-parameter-sequence.png b/docs~/i18n/ja/docusaurus-plugin-content-docs/current/reference/sync-parameter-sequence.png new file mode 100644 index 0000000000000000000000000000000000000000..5b7700591e07ece702648a7bafa26aae940b8319 GIT binary patch literal 30910 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