From 746a72f60b9b87e95f035faf0f2192ab604a4a1d Mon Sep 17 00:00:00 2001 From: bd_ Date: Sat, 6 Jul 2024 21:34:15 -0700 Subject: [PATCH] fix: unused/hidden subparameters are retained and break builds (#914) --- Runtime/ModularAvatarMenuItem.cs | 29 + .../UnusedSubParametersAreStripped.prefab | 1006 +++++++++++++++++ ...UnusedSubParametersAreStripped.prefab.meta | 7 + .../VRCExpressionParameters.asset | 15 + .../VRCExpressionParameters.asset.meta | 8 + .../VirtualMenuTests/VRCExpressionsMenu.asset | 15 + .../VRCExpressionsMenu.asset.meta | 8 + .../VirtualMenuTests/VirtualMenuTests.cs | 68 +- 8 files changed, 1148 insertions(+), 8 deletions(-) create mode 100644 UnitTests~/VirtualMenuTests/UnusedSubParametersAreStripped.prefab create mode 100644 UnitTests~/VirtualMenuTests/UnusedSubParametersAreStripped.prefab.meta create mode 100644 UnitTests~/VirtualMenuTests/VRCExpressionParameters.asset create mode 100644 UnitTests~/VirtualMenuTests/VRCExpressionParameters.asset.meta create mode 100644 UnitTests~/VirtualMenuTests/VRCExpressionsMenu.asset create mode 100644 UnitTests~/VirtualMenuTests/VRCExpressionsMenu.asset.meta diff --git a/Runtime/ModularAvatarMenuItem.cs b/Runtime/ModularAvatarMenuItem.cs index 6dc56e8b..750b4383 100644 --- a/Runtime/ModularAvatarMenuItem.cs +++ b/Runtime/ModularAvatarMenuItem.cs @@ -1,5 +1,6 @@ #if MA_VRCSDK3_AVATARS +using System.Linq; using nadena.dev.modular_avatar.core.menu; using UnityEngine; using VRC.SDK3.Avatars.ScriptableObjects; @@ -56,6 +57,8 @@ namespace nadena.dev.modular_avatar.core cloned.subMenu = null; cloned.name = gameObject.name; + FilterSubParameters(cloned); + if (cloned.type == VRCExpressionsMenu.Control.ControlType.SubMenu) { switch (this.MenuSource) @@ -77,6 +80,32 @@ namespace nadena.dev.modular_avatar.core context.PushControl(cloned); } + + private void FilterSubParameters(VirtualControl control) + { + var maxSubParams = 0; + switch (control.type) + { + case VRCExpressionsMenu.Control.ControlType.Toggle: + case VRCExpressionsMenu.Control.ControlType.Button: + case VRCExpressionsMenu.Control.ControlType.SubMenu: + default: + maxSubParams = 0; + break; + case VRCExpressionsMenu.Control.ControlType.RadialPuppet: + maxSubParams = 1; + break; + case VRCExpressionsMenu.Control.ControlType.TwoAxisPuppet: + maxSubParams = 2; + break; + case VRCExpressionsMenu.Control.ControlType.FourAxisPuppet: + maxSubParams = 4; + break; + } + + if (control.subParameters.Length > maxSubParams) + control.subParameters = control.subParameters.Take(maxSubParams).ToArray(); + } } } diff --git a/UnitTests~/VirtualMenuTests/UnusedSubParametersAreStripped.prefab b/UnitTests~/VirtualMenuTests/UnusedSubParametersAreStripped.prefab new file mode 100644 index 00000000..15266243 --- /dev/null +++ b/UnitTests~/VirtualMenuTests/UnusedSubParametersAreStripped.prefab @@ -0,0 +1,1006 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &1699353083974983395 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3931337273987494731} + - component: {fileID: 5903003272265408235} + m_Layer: 0 + m_Name: fouraxis + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &3931337273987494731 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1699353083974983395} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1927086902845393368} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &5903003272265408235 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1699353083974983395} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3b29d45007c5493d926d2cd45a489529, type: 3} + m_Name: + m_EditorClassIdentifier: + Control: + name: + icon: {fileID: 0} + type: 202 + parameter: + name: 4a + value: 1 + style: 0 + subMenu: {fileID: 0} + subParameters: + - name: a + - name: b + - name: c + - name: d + labels: + - name: a + icon: {fileID: 0} + - name: b + icon: {fileID: 0} + - name: c + icon: {fileID: 0} + - name: d + icon: {fileID: 0} + MenuSource: 0 + menuSource_otherObjectChildren: {fileID: 0} + isSynced: 1 + isSaved: 1 +--- !u!1 &3260712429637400366 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8490865045078535015} + - component: {fileID: 3586190453628051878} + m_Layer: 0 + m_Name: test + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8490865045078535015 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3260712429637400366} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 11145265991079979} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &3586190453628051878 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3260712429637400366} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3b29d45007c5493d926d2cd45a489529, type: 3} + m_Name: + m_EditorClassIdentifier: + Control: + name: + icon: {fileID: 0} + type: 101 + parameter: + name: + value: 1 + style: 0 + subMenu: {fileID: 0} + subParameters: [] + labels: [] + MenuSource: 0 + menuSource_otherObjectChildren: {fileID: 0} + isSynced: 1 + isSaved: 1 +--- !u!1 &3948405061937128567 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1634219981480252278} + - component: {fileID: 4770195219626346794} + - component: {fileID: 3359411654354469855} + - component: {fileID: 1434722488766259918} + m_Layer: 0 + m_Name: UnusedSubParametersAreStripped + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1634219981480252278 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3948405061937128567} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -2.0320978, y: 0.4740051, z: -1.2750527} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 9146705940674796404} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!95 &4770195219626346794 +Animator: + serializedVersion: 5 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3948405061937128567} + m_Enabled: 1 + m_Avatar: {fileID: 0} + m_Controller: {fileID: 0} + m_CullingMode: 0 + m_UpdateMode: 0 + m_ApplyRootMotion: 0 + m_LinearVelocityBlending: 0 + m_StabilizeFeet: 0 + m_WarningMessage: + m_HasTransformHierarchy: 1 + m_AllowConstantClipSamplingOptimization: 1 + m_KeepAnimatorStateOnDisable: 0 + m_WriteDefaultValuesOnDisable: 0 +--- !u!114 &3359411654354469855 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3948405061937128567} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 542108242, guid: 67cc4cb7839cd3741b63733d5adf0442, type: 3} + m_Name: + m_EditorClassIdentifier: + Name: + ViewPosition: {x: 0, y: 1.6, z: 0.2} + Animations: 0 + ScaleIPD: 1 + lipSync: 0 + lipSyncJawBone: {fileID: 0} + lipSyncJawClosed: {x: 0, y: 0, z: 0, w: 1} + lipSyncJawOpen: {x: 0, y: 0, z: 0, w: 1} + VisemeSkinnedMesh: {fileID: 0} + MouthOpenBlendShapeName: Facial_Blends.Jaw_Down + VisemeBlendShapes: [] + unityVersion: + portraitCameraPositionOffset: {x: 0, y: 0, z: 0} + portraitCameraRotationOffset: {x: 0, y: 1, z: 0, w: -0.00000004371139} + networkIDs: [] + customExpressions: 0 + expressionsMenu: {fileID: 0} + expressionParameters: {fileID: 0} + enableEyeLook: 0 + customEyeLookSettings: + eyeMovement: + confidence: 0.5 + excitement: 0.5 + leftEye: {fileID: 0} + rightEye: {fileID: 0} + eyesLookingStraight: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyesLookingUp: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyesLookingDown: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyesLookingLeft: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyesLookingRight: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyelidType: 0 + upperLeftEyelid: {fileID: 0} + upperRightEyelid: {fileID: 0} + lowerLeftEyelid: {fileID: 0} + lowerRightEyelid: {fileID: 0} + eyelidsDefault: + upper: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + lower: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyelidsClosed: + upper: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + lower: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyelidsLookingUp: + upper: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + lower: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyelidsLookingDown: + upper: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + lower: + linked: 1 + left: {x: 0, y: 0, z: 0, w: 0} + right: {x: 0, y: 0, z: 0, w: 0} + eyelidsSkinnedMesh: {fileID: 0} + eyelidsBlendshapes: + customizeAnimationLayers: 0 + baseAnimationLayers: + - isEnabled: 0 + type: 0 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + - isEnabled: 0 + type: 4 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + - isEnabled: 0 + type: 5 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + specialAnimationLayers: + - isEnabled: 0 + type: 6 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + - isEnabled: 0 + type: 7 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + - isEnabled: 0 + type: 8 + animatorController: {fileID: 0} + mask: {fileID: 0} + isDefault: 1 + AnimationPreset: {fileID: 0} + animationHashSet: [] + autoFootsteps: 1 + autoLocomotion: 1 + collider_head: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_torso: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_footR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_footL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_handR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_handL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerIndexL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerMiddleL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerRingL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerLittleL: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerIndexR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerMiddleR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerRingR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} + collider_fingerLittleR: + isMirrored: 1 + state: 0 + transform: {fileID: 0} + radius: 0 + height: 0 + position: {x: 0, y: 0, z: 0} + rotation: {x: 0, y: 0, z: 0, w: 1} +--- !u!114 &1434722488766259918 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3948405061937128567} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1427037861, guid: 4ecd63eff847044b68db9453ce219299, type: 3} + m_Name: + m_EditorClassIdentifier: + launchedFromSDKPipeline: 0 + completedSDKPipeline: 0 + blueprintId: + contentType: 0 + assetBundleUnityVersion: + fallbackStatus: 0 +--- !u!1 &4700308226395788044 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8164399792362988524} + - component: {fileID: 2555781461834395747} + m_Layer: 0 + m_Name: Button + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8164399792362988524 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4700308226395788044} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1927086902845393368} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2555781461834395747 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4700308226395788044} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3b29d45007c5493d926d2cd45a489529, type: 3} + m_Name: + m_EditorClassIdentifier: + Control: + name: + icon: {fileID: 0} + type: 101 + parameter: + name: bp + value: 1 + style: 0 + subMenu: {fileID: 0} + subParameters: + - name: a + - name: b + - name: c + - name: d + labels: + - name: a + icon: {fileID: 0} + - name: b + icon: {fileID: 0} + - name: c + icon: {fileID: 0} + - name: d + icon: {fileID: 0} + MenuSource: 0 + menuSource_otherObjectChildren: {fileID: 0} + isSynced: 1 + isSaved: 1 +--- !u!1 &4844193151243694628 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 11145265991079979} + - component: {fileID: 7438306800557842929} + m_Layer: 0 + m_Name: Submenu + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &11145265991079979 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4844193151243694628} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 8490865045078535015} + m_Father: {fileID: 1927086902845393368} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &7438306800557842929 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4844193151243694628} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3b29d45007c5493d926d2cd45a489529, type: 3} + m_Name: + m_EditorClassIdentifier: + Control: + name: + icon: {fileID: 0} + type: 103 + parameter: + name: sm + value: 1 + style: 0 + subMenu: {fileID: 0} + subParameters: + - name: a + - name: b + - name: c + - name: d + labels: + - name: a + icon: {fileID: 0} + - name: b + icon: {fileID: 0} + - name: c + icon: {fileID: 0} + - name: d + icon: {fileID: 0} + MenuSource: 1 + menuSource_otherObjectChildren: {fileID: 0} + isSynced: 1 + isSaved: 1 +--- !u!1 &5516685774333614686 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4062932922648400332} + - component: {fileID: 3867256507243885644} + m_Layer: 0 + m_Name: twoaxis + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4062932922648400332 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5516685774333614686} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1927086902845393368} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &3867256507243885644 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5516685774333614686} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3b29d45007c5493d926d2cd45a489529, type: 3} + m_Name: + m_EditorClassIdentifier: + Control: + name: + icon: {fileID: 0} + type: 201 + parameter: + name: 2a + value: 1 + style: 0 + subMenu: {fileID: 0} + subParameters: + - name: a + - name: b + labels: + - name: a + icon: {fileID: 0} + - name: b + icon: {fileID: 0} + - name: c + icon: {fileID: 0} + - name: d + icon: {fileID: 0} + MenuSource: 0 + menuSource_otherObjectChildren: {fileID: 0} + isSynced: 1 + isSaved: 1 +--- !u!1 &5790532758460296946 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1927086902845393368} + - component: {fileID: 5139221914713286524} + - component: {fileID: 2390903256310975148} + - component: {fileID: 4774200290491144813} + m_Layer: 0 + m_Name: menu + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1927086902845393368 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5790532758460296946} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 8164399792362988524} + - {fileID: 8519673002643274296} + - {fileID: 11145265991079979} + - {fileID: 4062932922648400332} + - {fileID: 1280818356743881570} + - {fileID: 3931337273987494731} + m_Father: {fileID: 9146705940674796404} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &5139221914713286524 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5790532758460296946} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 71a96d4ea0c344f39e277d82035bf9bd, type: 3} + m_Name: + m_EditorClassIdentifier: + parameters: [] +--- !u!114 &2390903256310975148 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5790532758460296946} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7ef83cb0c23d4d7c9d41021e544a1978, type: 3} + m_Name: + m_EditorClassIdentifier: + menuToAppend: {fileID: 0} + installTargetMenu: {fileID: 0} +--- !u!114 &4774200290491144813 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5790532758460296946} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3b29d45007c5493d926d2cd45a489529, type: 3} + m_Name: + m_EditorClassIdentifier: + Control: + name: + icon: {fileID: 0} + type: 103 + parameter: + name: + value: 1 + style: 0 + subMenu: {fileID: 0} + subParameters: [] + labels: [] + MenuSource: 1 + menuSource_otherObjectChildren: {fileID: 0} + isSynced: 1 + isSaved: 1 +--- !u!1 &6001750924991485932 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8519673002643274296} + - component: {fileID: 7692492187912880224} + m_Layer: 0 + m_Name: Toggle + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8519673002643274296 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6001750924991485932} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1927086902845393368} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &7692492187912880224 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6001750924991485932} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3b29d45007c5493d926d2cd45a489529, type: 3} + m_Name: + m_EditorClassIdentifier: + Control: + name: + icon: {fileID: 0} + type: 102 + parameter: + name: tp + value: 1 + style: 0 + subMenu: {fileID: 0} + subParameters: + - name: a + - name: b + - name: c + - name: d + labels: + - name: a + icon: {fileID: 0} + - name: b + icon: {fileID: 0} + - name: c + icon: {fileID: 0} + - name: d + icon: {fileID: 0} + MenuSource: 0 + menuSource_otherObjectChildren: {fileID: 0} + isSynced: 1 + isSaved: 1 +--- !u!1 &7683183153733236279 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1280818356743881570} + - component: {fileID: 936057242245787132} + m_Layer: 0 + m_Name: radial + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1280818356743881570 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7683183153733236279} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1927086902845393368} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &936057242245787132 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7683183153733236279} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3b29d45007c5493d926d2cd45a489529, type: 3} + m_Name: + m_EditorClassIdentifier: + Control: + name: + icon: {fileID: 0} + type: 203 + parameter: + name: r + value: 1 + style: 0 + subMenu: {fileID: 0} + subParameters: + - name: a + labels: + - name: a + icon: {fileID: 0} + - name: b + icon: {fileID: 0} + - name: c + icon: {fileID: 0} + - name: d + icon: {fileID: 0} + MenuSource: 0 + menuSource_otherObjectChildren: {fileID: 0} + isSynced: 1 + isSaved: 1 +--- !u!1 &9134507521258309165 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 9146705940674796404} + - component: {fileID: 8566754171799563491} + m_Layer: 0 + m_Name: params + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &9146705940674796404 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9134507521258309165} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1927086902845393368} + m_Father: {fileID: 1634219981480252278} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &8566754171799563491 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9134507521258309165} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 71a96d4ea0c344f39e277d82035bf9bd, type: 3} + m_Name: + m_EditorClassIdentifier: + parameters: + - nameOrPrefix: 2a + remapTo: + internalParameter: 0 + isPrefix: 0 + syncType: 2 + localOnly: 0 + defaultValue: 0 + saved: 0 + hasExplicitDefaultValue: 0 + m_overrideAnimatorDefaults: 0 + - nameOrPrefix: 4a + remapTo: + internalParameter: 0 + isPrefix: 0 + syncType: 2 + localOnly: 0 + defaultValue: 0 + saved: 0 + hasExplicitDefaultValue: 0 + m_overrideAnimatorDefaults: 0 + - nameOrPrefix: bp + remapTo: + internalParameter: 0 + isPrefix: 0 + syncType: 2 + localOnly: 0 + defaultValue: 0 + saved: 0 + hasExplicitDefaultValue: 0 + m_overrideAnimatorDefaults: 0 + - nameOrPrefix: r + remapTo: + internalParameter: 0 + isPrefix: 0 + syncType: 2 + localOnly: 0 + defaultValue: 0 + saved: 0 + hasExplicitDefaultValue: 0 + m_overrideAnimatorDefaults: 0 + - nameOrPrefix: sm + remapTo: + internalParameter: 0 + isPrefix: 0 + syncType: 2 + localOnly: 0 + defaultValue: 0 + saved: 0 + hasExplicitDefaultValue: 0 + m_overrideAnimatorDefaults: 0 + - nameOrPrefix: tp + remapTo: + internalParameter: 0 + isPrefix: 0 + syncType: 2 + localOnly: 0 + defaultValue: 0 + saved: 0 + hasExplicitDefaultValue: 0 + m_overrideAnimatorDefaults: 0 diff --git a/UnitTests~/VirtualMenuTests/UnusedSubParametersAreStripped.prefab.meta b/UnitTests~/VirtualMenuTests/UnusedSubParametersAreStripped.prefab.meta new file mode 100644 index 00000000..928fd0a5 --- /dev/null +++ b/UnitTests~/VirtualMenuTests/UnusedSubParametersAreStripped.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1d9e70d7b7b965045ba1055b2a5b4df0 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnitTests~/VirtualMenuTests/VRCExpressionParameters.asset b/UnitTests~/VirtualMenuTests/VRCExpressionParameters.asset new file mode 100644 index 00000000..7adf5857 --- /dev/null +++ b/UnitTests~/VirtualMenuTests/VRCExpressionParameters.asset @@ -0,0 +1,15 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -1506855854, guid: 67cc4cb7839cd3741b63733d5adf0442, type: 3} + m_Name: VRCExpressionParameters + m_EditorClassIdentifier: + parameters: [] diff --git a/UnitTests~/VirtualMenuTests/VRCExpressionParameters.asset.meta b/UnitTests~/VirtualMenuTests/VRCExpressionParameters.asset.meta new file mode 100644 index 00000000..ff642fa6 --- /dev/null +++ b/UnitTests~/VirtualMenuTests/VRCExpressionParameters.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ed707d3612602d44db77511dae4096d6 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnitTests~/VirtualMenuTests/VRCExpressionsMenu.asset b/UnitTests~/VirtualMenuTests/VRCExpressionsMenu.asset new file mode 100644 index 00000000..1a352185 --- /dev/null +++ b/UnitTests~/VirtualMenuTests/VRCExpressionsMenu.asset @@ -0,0 +1,15 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: -340790334, guid: 67cc4cb7839cd3741b63733d5adf0442, type: 3} + m_Name: VRCExpressionsMenu + m_EditorClassIdentifier: + controls: [] diff --git a/UnitTests~/VirtualMenuTests/VRCExpressionsMenu.asset.meta b/UnitTests~/VirtualMenuTests/VRCExpressionsMenu.asset.meta new file mode 100644 index 00000000..dc0aa090 --- /dev/null +++ b/UnitTests~/VirtualMenuTests/VRCExpressionsMenu.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 233f883cffa916b4aa2bf329f41e65ac +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/UnitTests~/VirtualMenuTests/VirtualMenuTests.cs b/UnitTests~/VirtualMenuTests/VirtualMenuTests.cs index 04669ef5..81a9ffa3 100644 --- a/UnitTests~/VirtualMenuTests/VirtualMenuTests.cs +++ b/UnitTests~/VirtualMenuTests/VirtualMenuTests.cs @@ -670,6 +670,34 @@ namespace modular_avatar_tests.VirtualMenuTests .SubmenuNode.Controls[0].parameter.name); } + [Test] + public void UnusedSubParametersAreStripped() + { + var root = CreatePrefab("UnusedSubParametersAreStripped.prefab"); + + BuildContext buildContext = new BuildContext(root.GetComponent()); + new RenameParametersHook().OnPreprocessAvatar(root, buildContext); + var virtualMenu = VirtualMenu.ForAvatar(root.GetComponent(), buildContext); + + // Button + Assert.AreEqual(0, virtualMenu.RootMenuNode.Controls[0].SubmenuNode.Controls[0].subParameters.Length); + + // Toggle + Assert.AreEqual(0, virtualMenu.RootMenuNode.Controls[0].SubmenuNode.Controls[1].subParameters.Length); + + // SubMenu + Assert.AreEqual(0, virtualMenu.RootMenuNode.Controls[0].SubmenuNode.Controls[2].subParameters.Length); + + // Two Axis + Assert.AreEqual(2, virtualMenu.RootMenuNode.Controls[0].SubmenuNode.Controls[3].subParameters.Length); + + // Radial + Assert.AreEqual(1, virtualMenu.RootMenuNode.Controls[0].SubmenuNode.Controls[4].subParameters.Length); + + // Four Axis + Assert.AreEqual(4, virtualMenu.RootMenuNode.Controls[0].SubmenuNode.Controls[5].subParameters.Length); + } + ModularAvatarMenuInstaller CreateInstaller(string name) { GameObject obj = new GameObject(); @@ -688,6 +716,7 @@ namespace modular_avatar_tests.VirtualMenuTests var control = GenerateTestControl(); control.type = VRCExpressionsMenu.Control.ControlType.SubMenu; control.subMenu = menu; + control.subParameters = Array.Empty(); return control; } @@ -719,13 +748,23 @@ namespace modular_avatar_tests.VirtualMenuTests icon = testTex } }; - control.subParameters = new[] + if (control.type == VRCExpressionsMenu.Control.ControlType.RadialPuppet + || control.type == VRCExpressionsMenu.Control.ControlType.FourAxisPuppet + || control.type == VRCExpressionsMenu.Control.ControlType.TwoAxisPuppet) { - new VRCExpressionsMenu.Control.Parameter() + control.subParameters = new[] { - name = "Test Sub Parameter " + GUID.Generate() - } - }; + new VRCExpressionsMenu.Control.Parameter() + { + name = "Test Sub Parameter " + GUID.Generate() + } + }; + } else + { + control.subParameters = Array.Empty(); + } + + control.value = 0.42f; control.style = VRCExpressionsMenu.Control.Style.Style3; @@ -742,9 +781,22 @@ namespace modular_avatar_tests.VirtualMenuTests Assert.AreEqual(expected.labels.Length, actual.labels.Length); Assert.AreEqual(expected.labels[0].name, actual.labels[0].name); Assert.AreEqual(expected.labels[0].icon, actual.labels[0].icon); - Assert.AreEqual(expected.subParameters.Length, actual.subParameters.Length); - Assert.AreEqual(expected.subParameters[0].name, actual.subParameters[0].name); - Assert.AreNotSame(expected.subParameters[0], actual.subParameters[0]); + switch (expected.type) + { + case VRCExpressionsMenu.Control.ControlType.Button: + case VRCExpressionsMenu.Control.ControlType.Toggle: + case VRCExpressionsMenu.Control.ControlType.SubMenu: + Assert.AreEqual(0, actual.subParameters.Length); + break; + default: + { + Assert.AreEqual(expected.subParameters.Length, actual.subParameters.Length); + Assert.AreEqual(expected.subParameters[0].name, actual.subParameters[0].name); + Assert.AreNotSame(expected.subParameters[0], actual.subParameters[0]); + break; + } + } + Assert.AreEqual(expected.value, actual.value); Assert.AreEqual(expected.style, actual.style); }