mirror of
https://github.com/bdunderscore/modular-avatar.git
synced 2025-01-01 20:25:07 +08:00
fix: issues with menu generation (#371)
* chore: adding unit tests for #366 and #326 * fix: duplicate submenu controls not generated for multiple installers When multiple installers referenced the same expressions menu asset, only one submenu control would be generated. * fix: submenus incorrectly deduping across different postprocessing contexts Fixes: #366, #326 * fix: postprocess context not being inherited into submenus (#326) This caused issues where parameter mappings were not being applied to submenus.
This commit is contained in:
parent
333d4e8a95
commit
3044969454
@ -0,0 +1,25 @@
|
|||||||
|
%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: InternalParamTestMenu
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
controls:
|
||||||
|
- name: item
|
||||||
|
icon: {fileID: 0}
|
||||||
|
type: 102
|
||||||
|
parameter:
|
||||||
|
name: x
|
||||||
|
value: 1
|
||||||
|
style: 0
|
||||||
|
subMenu: {fileID: 0}
|
||||||
|
subParameters: []
|
||||||
|
labels: []
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 09a6ec3c61c7db840b3cd958099c5798
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,450 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!1 &2860324038786842778
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 2860324038786842773}
|
||||||
|
- component: {fileID: 2860324038786842772}
|
||||||
|
- component: {fileID: 1761937879440307670}
|
||||||
|
- component: {fileID: 3202484316900348122}
|
||||||
|
- component: {fileID: 2669963860607714920}
|
||||||
|
- component: {fileID: 5085570563562387984}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: InternalParameterTest
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &2860324038786842773
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2860324038786842778}
|
||||||
|
m_LocalRotation: {x: 0.07681167, y: 0.62035006, z: 0.20221491, w: 0.7539065}
|
||||||
|
m_LocalPosition: {x: -0.0534066, y: 0.9950551, z: 0.14142857}
|
||||||
|
m_LocalScale: {x: 1.098901, y: 1.0989009, z: 1.098901}
|
||||||
|
m_Children:
|
||||||
|
- {fileID: 8910535925068494434}
|
||||||
|
m_Father: {fileID: 0}
|
||||||
|
m_RootOrder: 0
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &2860324038786842772
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2860324038786842778}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 71a96d4ea0c344f39e277d82035bf9bd, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
parameters:
|
||||||
|
- nameOrPrefix: x
|
||||||
|
remapTo:
|
||||||
|
internalParameter: 1
|
||||||
|
isPrefix: 0
|
||||||
|
syncType: 3
|
||||||
|
localOnly: 0
|
||||||
|
defaultValue: 0
|
||||||
|
saved: 1
|
||||||
|
--- !u!114 &1761937879440307670
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2860324038786842778}
|
||||||
|
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: 11400000, guid: 09a6ec3c61c7db840b3cd958099c5798, type: 2}
|
||||||
|
subParameters: []
|
||||||
|
labels: []
|
||||||
|
MenuSource: 0
|
||||||
|
menuSource_otherObjectChildren: {fileID: 0}
|
||||||
|
isSynced: 1
|
||||||
|
isSaved: 1
|
||||||
|
--- !u!114 &3202484316900348122
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2860324038786842778}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 7ef83cb0c23d4d7c9d41021e544a1978, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
menuToAppend: {fileID: 11400000, guid: 09a6ec3c61c7db840b3cd958099c5798, type: 2}
|
||||||
|
installTargetMenu: {fileID: 0}
|
||||||
|
--- !u!114 &2669963860607714920
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2860324038786842778}
|
||||||
|
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: 2
|
||||||
|
animatorController: {fileID: 0}
|
||||||
|
mask: {fileID: 0}
|
||||||
|
isDefault: 1
|
||||||
|
- isEnabled: 0
|
||||||
|
type: 3
|
||||||
|
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 &5085570563562387984
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 2860324038786842778}
|
||||||
|
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 &7624042284818776979
|
||||||
|
GameObject:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
serializedVersion: 6
|
||||||
|
m_Component:
|
||||||
|
- component: {fileID: 8910535925068494434}
|
||||||
|
- component: {fileID: 2708762870899574912}
|
||||||
|
- component: {fileID: 216941358938488416}
|
||||||
|
m_Layer: 0
|
||||||
|
m_Name: Menu
|
||||||
|
m_TagString: Untagged
|
||||||
|
m_Icon: {fileID: 0}
|
||||||
|
m_NavMeshLayer: 0
|
||||||
|
m_StaticEditorFlags: 0
|
||||||
|
m_IsActive: 1
|
||||||
|
--- !u!4 &8910535925068494434
|
||||||
|
Transform:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 7624042284818776979}
|
||||||
|
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_Children: []
|
||||||
|
m_Father: {fileID: 2860324038786842773}
|
||||||
|
m_RootOrder: 0
|
||||||
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
|
--- !u!114 &2708762870899574912
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 7624042284818776979}
|
||||||
|
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: 0
|
||||||
|
menuSource_otherObjectChildren: {fileID: 0}
|
||||||
|
isSynced: 1
|
||||||
|
isSaved: 1
|
||||||
|
--- !u!114 &216941358938488416
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 7624042284818776979}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 7ef83cb0c23d4d7c9d41021e544a1978, type: 3}
|
||||||
|
m_Name:
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
menuToAppend: {fileID: 0}
|
||||||
|
installTargetMenu: {fileID: 0}
|
@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 15cecd8ca5178eb40953a581734e61f6
|
||||||
|
PrefabImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -1,12 +1,18 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using nadena.dev.modular_avatar.core;
|
using nadena.dev.modular_avatar.core;
|
||||||
|
using nadena.dev.modular_avatar.core.editor;
|
||||||
using nadena.dev.modular_avatar.core.editor.menu;
|
using nadena.dev.modular_avatar.core.editor.menu;
|
||||||
using nadena.dev.modular_avatar.core.menu;
|
using nadena.dev.modular_avatar.core.menu;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEditor.VersionControl;
|
using UnityEditor.VersionControl;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using VRC.SDK3.Avatars.Components;
|
||||||
using VRC.SDK3.Avatars.ScriptableObjects;
|
using VRC.SDK3.Avatars.ScriptableObjects;
|
||||||
|
using Object = UnityEngine.Object;
|
||||||
|
using Random = UnityEngine.Random;
|
||||||
|
|
||||||
namespace modular_avatar_tests.VirtualMenuTests
|
namespace modular_avatar_tests.VirtualMenuTests
|
||||||
{
|
{
|
||||||
@ -73,9 +79,9 @@ namespace modular_avatar_tests.VirtualMenuTests
|
|||||||
virtualMenu.FreezeMenu();
|
virtualMenu.FreezeMenu();
|
||||||
|
|
||||||
Assert.AreEqual(1, virtualMenu.ResolvedMenu.Count);
|
Assert.AreEqual(1, virtualMenu.ResolvedMenu.Count);
|
||||||
var root = virtualMenu.ResolvedMenu[rootMenu];
|
var root = virtualMenu.NodeForMenuAsset(rootMenu);
|
||||||
Assert.AreEqual(2, root.Controls.Count);
|
Assert.AreEqual(2, root.Controls.Count);
|
||||||
Assert.AreSame(rootMenu, root.NodeKey);
|
Assert.AreSame(rootMenu, root.SourceMenu());
|
||||||
AssertControlEquals(rootMenu.controls[0], root.Controls[0]);
|
AssertControlEquals(rootMenu.controls[0], root.Controls[0]);
|
||||||
AssertControlEquals(rootMenu.controls[1], root.Controls[1]);
|
AssertControlEquals(rootMenu.controls[1], root.Controls[1]);
|
||||||
}
|
}
|
||||||
@ -106,22 +112,22 @@ namespace modular_avatar_tests.VirtualMenuTests
|
|||||||
virtualMenu.FreezeMenu();
|
virtualMenu.FreezeMenu();
|
||||||
|
|
||||||
Assert.AreEqual(3, virtualMenu.ResolvedMenu.Count);
|
Assert.AreEqual(3, virtualMenu.ResolvedMenu.Count);
|
||||||
var rootNode = virtualMenu.ResolvedMenu[rootMenu];
|
var rootNode = virtualMenu.ResolvedMenu[virtualMenu.RootMenuKey];
|
||||||
var sub1Node = virtualMenu.ResolvedMenu[sub1];
|
var sub1Node = virtualMenu.NodeForMenuAsset(sub1);
|
||||||
var sub2Node = virtualMenu.ResolvedMenu[sub2];
|
var sub2Node = virtualMenu.NodeForMenuAsset(sub2);
|
||||||
|
|
||||||
Assert.AreEqual(1, rootNode.Controls.Count);
|
Assert.AreEqual(1, rootNode.Controls.Count);
|
||||||
Assert.AreSame(rootMenu, rootNode.NodeKey);
|
Assert.AreSame(virtualMenu.RootMenuKey, rootNode.NodeKey);
|
||||||
Assert.AreSame(sub1Node, rootNode.Controls[0].SubmenuNode);
|
Assert.AreSame(sub1Node, rootNode.Controls[0].SubmenuNode);
|
||||||
Assert.IsNull(rootNode.Controls[0].subMenu);
|
Assert.IsNull(rootNode.Controls[0].subMenu);
|
||||||
|
|
||||||
Assert.AreEqual(1, sub1Node.Controls.Count);
|
Assert.AreEqual(1, sub1Node.Controls.Count);
|
||||||
Assert.AreSame(sub1, sub1Node.NodeKey);
|
Assert.AreSame(sub1, sub1Node.SourceMenu());
|
||||||
Assert.AreSame(sub2Node, sub1Node.Controls[0].SubmenuNode);
|
Assert.AreSame(sub2Node, sub1Node.Controls[0].SubmenuNode);
|
||||||
Assert.IsNull(sub1Node.Controls[0].subMenu);
|
Assert.IsNull(sub1Node.Controls[0].subMenu);
|
||||||
|
|
||||||
Assert.AreEqual(1, sub2Node.Controls.Count);
|
Assert.AreEqual(1, sub2Node.Controls.Count);
|
||||||
Assert.AreSame(sub2, sub2Node.NodeKey);
|
Assert.AreSame(sub2, sub2Node.SourceMenu());
|
||||||
Assert.AreSame(rootNode, sub2Node.Controls[0].SubmenuNode);
|
Assert.AreSame(rootNode, sub2Node.Controls[0].SubmenuNode);
|
||||||
Assert.IsNull(sub2Node.Controls[0].subMenu);
|
Assert.IsNull(sub2Node.Controls[0].subMenu);
|
||||||
}
|
}
|
||||||
@ -243,10 +249,10 @@ namespace modular_avatar_tests.VirtualMenuTests
|
|||||||
|
|
||||||
Assert.AreEqual(2, virtualMenu.ResolvedMenu.Count);
|
Assert.AreEqual(2, virtualMenu.ResolvedMenu.Count);
|
||||||
var rootMenu = virtualMenu.ResolvedMenu[RootMenu.Instance];
|
var rootMenu = virtualMenu.ResolvedMenu[RootMenu.Instance];
|
||||||
var subMenu = virtualMenu.ResolvedMenu[menu_b];
|
var subMenu = virtualMenu.NodeForMenuAsset(menu_b);
|
||||||
Assert.AreSame(subMenu, rootMenu.Controls[0].SubmenuNode);
|
Assert.AreSame(subMenu, rootMenu.Controls[0].SubmenuNode);
|
||||||
Assert.AreSame(RootMenu.Instance, rootMenu.NodeKey);
|
Assert.AreSame(RootMenu.Instance, rootMenu.NodeKey);
|
||||||
Assert.AreSame(menu_b, subMenu.NodeKey);
|
Assert.AreSame(menu_b, ((ValueTuple<object, object>) subMenu.NodeKey).Item1);
|
||||||
Assert.AreEqual(1, subMenu.Controls.Count);
|
Assert.AreEqual(1, subMenu.Controls.Count);
|
||||||
AssertControlEquals(menu_b.controls[0], subMenu.Controls[0]);
|
AssertControlEquals(menu_b.controls[0], subMenu.Controls[0]);
|
||||||
}
|
}
|
||||||
@ -324,8 +330,7 @@ namespace modular_avatar_tests.VirtualMenuTests
|
|||||||
virtualMenu.FreezeMenu();
|
virtualMenu.FreezeMenu();
|
||||||
|
|
||||||
Assert.AreEqual(1, virtualMenu.ResolvedMenu.Count);
|
Assert.AreEqual(1, virtualMenu.ResolvedMenu.Count);
|
||||||
var rootMenu = virtualMenu.ResolvedMenu[menu_a];
|
var rootMenu = virtualMenu.NodeForMenuAsset(menu_a);
|
||||||
var menu_a_node = virtualMenu.ResolvedMenu[menu_a];
|
|
||||||
Assert.AreEqual(3, rootMenu.Controls.Count);
|
Assert.AreEqual(3, rootMenu.Controls.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -557,10 +562,113 @@ namespace modular_avatar_tests.VirtualMenuTests
|
|||||||
|
|
||||||
virtualMenu.FreezeMenu();
|
virtualMenu.FreezeMenu();
|
||||||
|
|
||||||
var root = virtualMenu.ResolvedMenu[menu_a];
|
var root = virtualMenu.NodeForMenuAsset(menu_a);
|
||||||
Assert.AreEqual(1, root.Controls.Count);
|
Assert.AreEqual(1, root.Controls.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void multipleMenuAssets_areInstalledMultipleTimes()
|
||||||
|
{
|
||||||
|
var menu_a = Create<VRCExpressionsMenu>();
|
||||||
|
menu_a.controls.Add(new VRCExpressionsMenu.Control()
|
||||||
|
{
|
||||||
|
name = "control",
|
||||||
|
parameter = new VRCExpressionsMenu.Control.Parameter()
|
||||||
|
{
|
||||||
|
name = "p"
|
||||||
|
},
|
||||||
|
type = VRCExpressionsMenu.Control.ControlType.Toggle
|
||||||
|
});
|
||||||
|
|
||||||
|
var av_root = CreateRoot("avatar");
|
||||||
|
|
||||||
|
var node_a = CreateInstaller("menu_a");
|
||||||
|
node_a.transform.SetParent(av_root.transform);
|
||||||
|
node_a.menuToAppend = menu_a;
|
||||||
|
|
||||||
|
var node_b = CreateInstaller("menu_b");
|
||||||
|
node_b.transform.SetParent(av_root.transform);
|
||||||
|
node_b.menuToAppend = menu_a;
|
||||||
|
|
||||||
|
var virtualMenu = VirtualMenu.ForAvatar(av_root.GetComponent<VRCAvatarDescriptor>());
|
||||||
|
virtualMenu.FreezeMenu();
|
||||||
|
Assert.AreEqual(2, virtualMenu.RootMenuNode.Controls.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void remapParams_isAppliedSeparatelyForEachDedup()
|
||||||
|
{
|
||||||
|
var menu_a = Create<VRCExpressionsMenu>();
|
||||||
|
menu_a.controls.Add(new VRCExpressionsMenu.Control()
|
||||||
|
{
|
||||||
|
name = "control",
|
||||||
|
parameter = new VRCExpressionsMenu.Control.Parameter()
|
||||||
|
{
|
||||||
|
name = "p"
|
||||||
|
},
|
||||||
|
type = VRCExpressionsMenu.Control.ControlType.Toggle
|
||||||
|
});
|
||||||
|
var menu_outer = Create<VRCExpressionsMenu>();
|
||||||
|
menu_outer.controls.Add(new VRCExpressionsMenu.Control()
|
||||||
|
{
|
||||||
|
name = "control",
|
||||||
|
type = VRCExpressionsMenu.Control.ControlType.SubMenu,
|
||||||
|
subMenu = menu_a
|
||||||
|
});
|
||||||
|
|
||||||
|
var av_root = CreateRoot("avatar");
|
||||||
|
|
||||||
|
var node_a = CreateInstaller("menu_a");
|
||||||
|
node_a.transform.SetParent(av_root.transform);
|
||||||
|
node_a.menuToAppend = menu_outer;
|
||||||
|
node_a.gameObject.AddComponent<ModularAvatarParameters>().parameters = new List<ParameterConfig>()
|
||||||
|
{
|
||||||
|
new ParameterConfig()
|
||||||
|
{
|
||||||
|
nameOrPrefix = "p",
|
||||||
|
remapTo = "a",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var node_b = CreateInstaller("menu_b");
|
||||||
|
node_b.transform.SetParent(av_root.transform);
|
||||||
|
node_b.menuToAppend = menu_outer;
|
||||||
|
node_b.gameObject.AddComponent<ModularAvatarParameters>().parameters = new List<ParameterConfig>()
|
||||||
|
{
|
||||||
|
new ParameterConfig()
|
||||||
|
{
|
||||||
|
nameOrPrefix = "p",
|
||||||
|
remapTo = "b",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var buildContext = new BuildContext(av_root.GetComponent<VRCAvatarDescriptor>());
|
||||||
|
new RenameParametersHook().OnPreprocessAvatar(av_root, buildContext);
|
||||||
|
|
||||||
|
var virtualMenu = VirtualMenu.ForAvatar(av_root.GetComponent<VRCAvatarDescriptor>(), buildContext);
|
||||||
|
virtualMenu.FreezeMenu();
|
||||||
|
|
||||||
|
Assert.IsTrue(virtualMenu.RootMenuNode.Controls.Any(c =>
|
||||||
|
c.SubmenuNode.Controls[0].parameter.name == "a"
|
||||||
|
));
|
||||||
|
Assert.IsTrue(virtualMenu.RootMenuNode.Controls.Any(c =>
|
||||||
|
c.SubmenuNode.Controls[0].parameter.name == "b"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void internalParameterTest()
|
||||||
|
{
|
||||||
|
var root = CreatePrefab("InternalParameterTest.prefab");
|
||||||
|
|
||||||
|
BuildContext buildContext = new BuildContext(root.GetComponent<VRCAvatarDescriptor>());
|
||||||
|
new RenameParametersHook().OnPreprocessAvatar(root, buildContext);
|
||||||
|
var virtualMenu = VirtualMenu.ForAvatar(root.GetComponent<VRCAvatarDescriptor>(), buildContext);
|
||||||
|
|
||||||
|
Assert.AreNotEqual("x", virtualMenu.RootMenuNode.Controls[0]
|
||||||
|
.SubmenuNode.Controls[0].parameter.name);
|
||||||
|
}
|
||||||
|
|
||||||
ModularAvatarMenuInstaller CreateInstaller(string name)
|
ModularAvatarMenuInstaller CreateInstaller(string name)
|
||||||
{
|
{
|
||||||
GameObject obj = new GameObject();
|
GameObject obj = new GameObject();
|
||||||
@ -640,4 +748,24 @@ namespace modular_avatar_tests.VirtualMenuTests
|
|||||||
Assert.AreEqual(expected.style, actual.style);
|
Assert.AreEqual(expected.style, actual.style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static class TestHelpers
|
||||||
|
{
|
||||||
|
internal static VirtualMenuNode NodeForMenuAsset(this VirtualMenu menu, VRCExpressionsMenu asset)
|
||||||
|
{
|
||||||
|
return menu.ResolvedMenu.FirstOrDefault(
|
||||||
|
kvp => kvp.Key is ValueTuple<object, object> tuple && ReferenceEquals(tuple.Item1, asset)
|
||||||
|
).Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static VRCExpressionsMenu SourceMenu(this VirtualMenuNode node)
|
||||||
|
{
|
||||||
|
if (node.NodeKey is ValueTuple<object, object> tuple && tuple.Item1 is VRCExpressionsMenu menu)
|
||||||
|
{
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -107,7 +107,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
|
|
||||||
public void DoGUI(VRCExpressionsMenu menu, GameObject parameterReference = null)
|
public void DoGUI(VRCExpressionsMenu menu, GameObject parameterReference = null)
|
||||||
{
|
{
|
||||||
new VisitorContext(this).PushNode(menu);
|
new VisitorContext(this).PushMenuContents(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PushGuiNode(object key, Func<Action> guiBuilder)
|
private void PushGuiNode(object key, Func<Action> guiBuilder)
|
||||||
@ -162,7 +162,7 @@ namespace nadena.dev.modular_avatar.core.editor
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PushNode(VRCExpressionsMenu expMenu)
|
public void PushMenuContents(VRCExpressionsMenu expMenu)
|
||||||
{
|
{
|
||||||
PushMenu(expMenu, null);
|
PushMenu(expMenu, null);
|
||||||
}
|
}
|
||||||
|
@ -87,13 +87,15 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
_currentPostprocessor = postprocessor;
|
_currentPostprocessor = postprocessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PushNode(VRCExpressionsMenu expMenu)
|
public void PushMenuContents(VRCExpressionsMenu expMenu)
|
||||||
{
|
{
|
||||||
if (expMenu == null) return;
|
if (expMenu == null) return;
|
||||||
if (_visited.Contains(expMenu)) return;
|
if (_visited.Contains(expMenu)) return;
|
||||||
_visited.Add(expMenu);
|
_visited.Add(expMenu);
|
||||||
_visitedMenu(expMenu);
|
_visitedMenu(expMenu);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
foreach (var control in expMenu.controls)
|
foreach (var control in expMenu.controls)
|
||||||
{
|
{
|
||||||
PushControl(control);
|
PushControl(control);
|
||||||
@ -110,6 +112,13 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// We can visit the same expMenu multiple times, with different visit contexts (owing to having
|
||||||
|
// different source installers, with different postprocessing configurations).
|
||||||
|
_visited.Remove(expMenu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void PushNode(MenuSource source)
|
public void PushNode(MenuSource source)
|
||||||
{
|
{
|
||||||
@ -118,6 +127,8 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
_visited.Add(source);
|
_visited.Add(source);
|
||||||
|
|
||||||
BuildReport.ReportingObject(source as UnityEngine.Object, () => source.Visit(this));
|
BuildReport.ReportingObject(source as UnityEngine.Object, () => source.Visit(this));
|
||||||
|
|
||||||
|
_visited.Remove(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PushNode(ModularAvatarMenuInstaller installer)
|
public void PushNode(ModularAvatarMenuInstaller installer)
|
||||||
@ -127,6 +138,8 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
_visited.Add(installer);
|
_visited.Add(installer);
|
||||||
|
|
||||||
BuildReport.ReportingObject(installer, () =>
|
BuildReport.ReportingObject(installer, () =>
|
||||||
|
{
|
||||||
|
using (new PostprocessorContext(this, _postProcessControls.GetValueOrDefault(installer)))
|
||||||
{
|
{
|
||||||
var menuSourceComp = installer.GetComponent<MenuSource>();
|
var menuSourceComp = installer.GetComponent<MenuSource>();
|
||||||
if (menuSourceComp != null)
|
if (menuSourceComp != null)
|
||||||
@ -135,19 +148,25 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
}
|
}
|
||||||
else if (installer.menuToAppend != null)
|
else if (installer.menuToAppend != null)
|
||||||
{
|
{
|
||||||
using (new PostprocessorContext(this, _postProcessControls.GetValueOrDefault(installer)))
|
PushMenuContents(installer.menuToAppend);
|
||||||
{
|
|
||||||
PushNode(installer.menuToAppend);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_visited.Remove(installer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PushControl(VRCExpressionsMenu.Control control)
|
public void PushControl(VRCExpressionsMenu.Control control)
|
||||||
{
|
{
|
||||||
|
// XXX: When we invoke NodeFor on the subMenu, we need to ensure we dedup considering the parameter context
|
||||||
|
// of the source control. This is because the same subMenu can be used in multiple places, with different
|
||||||
|
// parameter replacements. (FIXME)
|
||||||
var virtualControl = new VirtualControl(control);
|
var virtualControl = new VirtualControl(control);
|
||||||
|
|
||||||
|
if (control.subMenu != null)
|
||||||
|
{
|
||||||
virtualControl.SubmenuNode = NodeFor(control.subMenu);
|
virtualControl.SubmenuNode = NodeFor(control.subMenu);
|
||||||
|
}
|
||||||
|
|
||||||
_currentPostprocessor(virtualControl);
|
_currentPostprocessor(virtualControl);
|
||||||
|
|
||||||
@ -178,6 +197,8 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
*/
|
*/
|
||||||
internal class VirtualMenu
|
internal class VirtualMenu
|
||||||
{
|
{
|
||||||
|
private static readonly Action<VRCExpressionsMenu.Control> NoopPostprocessor = control => { };
|
||||||
|
|
||||||
internal readonly object RootMenuKey;
|
internal readonly object RootMenuKey;
|
||||||
|
|
||||||
private static long _cacheSeq = 0;
|
private static long _cacheSeq = 0;
|
||||||
@ -236,7 +257,7 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
|
|
||||||
if (rootMenu != null)
|
if (rootMenu != null)
|
||||||
{
|
{
|
||||||
RootMenuKey = rootMenu;
|
RootMenuKey = (ValueTuple<object, object>) (rootMenu, NoopPostprocessor);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -335,22 +356,32 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
var rootContext =
|
var rootContext =
|
||||||
new NodeContextImpl(RootNode, NodeFor, menuToInstallerFiltered, _postprocessControlsHooks,
|
new NodeContextImpl(RootNode, NodeFor, menuToInstallerFiltered, _postprocessControlsHooks,
|
||||||
m => _visitedMenus.Add(m),
|
m => _visitedMenus.Add(m),
|
||||||
_control => { });
|
NoopPostprocessor);
|
||||||
if (RootMenuKey is VRCExpressionsMenu menu)
|
if (RootMenuKey is ValueTuple<object, object> tuple && tuple.Item1 is VRCExpressionsMenu menu)
|
||||||
{
|
{
|
||||||
foreach (var control in menu.controls)
|
foreach (var control in menu.controls)
|
||||||
{
|
{
|
||||||
rootContext.PushControl(control);
|
rootContext.PushControl(control);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (menuToInstallerFiltered.TryGetValue(RootMenuKey, out var installers))
|
// Some menu installers may be bound to the root menu _asset_ directly.
|
||||||
|
if (menuToInstallerFiltered.TryGetValue(menu, out var installers))
|
||||||
{
|
{
|
||||||
foreach (var installer in installers)
|
foreach (var installer in installers)
|
||||||
{
|
{
|
||||||
rootContext.PushNode(installer);
|
rootContext.PushNode(installer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Untargeted installers are bound to the RootMenuKey, rather than the menu asset itself.
|
||||||
|
if (menuToInstallerFiltered.TryGetValue(RootMenuKey, out var installers2))
|
||||||
|
{
|
||||||
|
foreach (var installer in installers2)
|
||||||
|
{
|
||||||
|
rootContext.PushNode(installer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (_pendingGeneration.Count > 0)
|
while (_pendingGeneration.Count > 0)
|
||||||
{
|
{
|
||||||
@ -361,9 +392,15 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
|
|
||||||
VirtualMenuNode NodeFor(object key, Action<VRCExpressionsMenu.Control> postprocessContext)
|
VirtualMenuNode NodeFor(object key, Action<VRCExpressionsMenu.Control> postprocessContext)
|
||||||
{
|
{
|
||||||
if (_resolvedMenu.TryGetValue(key, out var node)) return node;
|
var lookupKey = key;
|
||||||
node = new VirtualMenuNode(key);
|
if (key is VRCExpressionsMenu)
|
||||||
_resolvedMenu[key] = node;
|
{
|
||||||
|
lookupKey = (ValueTuple<object, object>) (key, postprocessContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_resolvedMenu.TryGetValue(lookupKey, out var node)) return node;
|
||||||
|
node = new VirtualMenuNode(lookupKey);
|
||||||
|
_resolvedMenu[lookupKey] = node;
|
||||||
|
|
||||||
_pendingGeneration.Enqueue(() =>
|
_pendingGeneration.Enqueue(() =>
|
||||||
{
|
{
|
||||||
@ -375,7 +412,7 @@ namespace nadena.dev.modular_avatar.core.editor.menu
|
|||||||
postprocessContext);
|
postprocessContext);
|
||||||
if (key is VRCExpressionsMenu expMenu)
|
if (key is VRCExpressionsMenu expMenu)
|
||||||
{
|
{
|
||||||
context.PushNode(expMenu);
|
context.PushMenuContents(expMenu);
|
||||||
}
|
}
|
||||||
else if (key is MenuSource source)
|
else if (key is MenuSource source)
|
||||||
{
|
{
|
||||||
|
@ -106,7 +106,7 @@ namespace nadena.dev.modular_avatar.core.menu
|
|||||||
/// installer invocations.
|
/// installer invocations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="expMenu"></param>
|
/// <param name="expMenu"></param>
|
||||||
void PushNode(VRCExpressionsMenu expMenu);
|
void PushMenuContents(VRCExpressionsMenu expMenu);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pushes the contents of this menu source onto the current menu node.
|
/// Pushes the contents of this menu source onto the current menu node.
|
||||||
|
Loading…
Reference in New Issue
Block a user