This PR makes the communication menu ( bot commands ) available in VR by adding the menu itself to the world UI, and adding a new action, OpenAndSelectComms that both opens the menu and navigates to the next item. Navigation can also be accomplished with the weapon prev/next buttons ( base game behavior, no logic added ). Interact is used to select an item, and the existing dismiss button ( Reload ) is used to dismiss the menu.
( Originally OpenAndSelectComms was used to both open the menu and select items, and weaponPrev/Next was used for navigation. This was changed to accommodate people who instead use the radial menu for weapon selection. )
In the process of adding the menu to the WorldSpaceUI, UI element text not rendering through geometry has also been fixed, both for the HUD and nav markers.
VRWorldSpaceUI.cs was heavily refactored to have all the elements share the same code, instead of duplicating basically the same logic for each individual element.
The Communication Menu works the exact same as the other UI elements, but there are no references to it, so we grab a reference by hooking PUI_CommunicationMenu.Setup()
The input is bound to both ToggleCommunicationMenu and indirectly the MenuScroll (-1f) actions, and we only return true for the relevant action depending on whether the eFocusState is FPS or FPS_CommunicationDialog.
This is complicated by the fact that, as far as I can tell, the game never queries the SelectCommunicationMenu action.
Even in the base game I could not get SelectCommunicationMenu to work with an xbox controller, so I'm going to go ahead and say it is broken.
To overcome this we Prefix patch PUI_CommunicationMenu.Update() and check the input ourselves, calling PUI_CommunicationMenu.MoveNext() with PUI_CommunicationMenu.m_highlightedButtonIndex to make it "select" the currently highlighted item. The Prefix skips the function if an item is selected, so it shouldn't break is the devs decide to fix their input at some point.
Since the menu toggle button obviously cannot be held down when the same button is used to navigate, we force eCellSettingID.Gameplay_HoldToShowComsList to false every time the eFocusState changes to FPS.
Finally, PUI_CommunicationMenu.UpdateCmdTripMine, PUI_CommunicationMenu.UpdateCmdSentryGun, and PUI_CommunicationMenu.UpdateButtonsForNode were added to InjectSemanticInteractionTweaks.cs alongside the patches for normal mine and sentry placement, so placement is based on where your hand is rather than where the camera is pointing.
PUI_CommunicationMenu.UpdateButtonsForNode is what is used for the final placement, while the two update functions just display the markers.
WorldSpaceUI geometry clipping
It turns out messing with the MeshRenderer of a TextMeshPro has no affect ( now? It must have worked at some point in time ), and you must instead set either TextMeshPro.FontMaterial or TextMeshPro.fontSharedMaterial.
As luck would have it, most of the WorldSpaceUI elements share same font material, so in VRWorldSpaceUI.setSharedMaterialShader() we just set the fontSharedMaterial and RenderQueue of an existing CommunicationMenu text object and everything magically renders ontop of everything.
The Compass has its own text material, but conveniently exposes it at PUI_Compass.m_fontMaterial, so we repeat the process there, using VRAssets.TextSphereClip instead of VRAssets.GetTextNoCull(), and all is good.
Nav markers text geometry clippingWorldSpaceUI.PrepareNavMarker() was actually already setting the fontSharedMaterial of all TextMeshPro children, but if you inspect the NavMarkers in-game, it turns out they end up with a completely different material. Not sure if they are completely separate objects or if something changes the material later. Ditto for the sprites?
However, we also set the Sprite shader at InjectNavMarkerWorldSpace.InjectNavMarkerWorldSpriteHack patching NavMarkerComponent.Start(). This patch is what actually does all the work.
NavMarkerComponent has an m_text field, and if we modify the fontSharedMaterial of that all our problems are solved.
This patch was also changed to modify the sharedMaterial of the Sprite, instead of the Material.
This is now the only place the NavMarker materials are modified.
What
This PR makes the communication menu ( bot commands ) available in VR by adding the menu itself to the world UI, and adding a new action,
OpenAndSelectComms
that both opens the menu and navigates to the next item. Navigation can also be accomplished with the weapon prev/next buttons ( base game behavior, no logic added ).Interact
is used to select an item, and the existing dismiss button ( Reload ) is used to dismiss the menu.( Originally
OpenAndSelectComms
was used to both open the menu and select items, andweaponPrev/Next
was used for navigation. This was changed to accommodate people who instead use the radial menu for weapon selection. )In the process of adding the menu to the
WorldSpaceUI
, UI element text not rendering through geometry has also been fixed, both for the HUD and nav markers.VRWorldSpaceUI.cs
was heavily refactored to have all the elements share the same code, instead of duplicating basically the same logic for each individual element.Video of bossing bots around: https://www.youtube.com/watch?v=NCvH0gW9EZg
This PR is accompanied by this pull request to the SteamVR_Standalone_IL2CPP library's GTFO branch
How
Communication menu UI
The
Communication Menu
works the exact same as the other UI elements, but there are no references to it, so we grab a reference by hookingPUI_CommunicationMenu.Setup()
OpenAndSelectComms action
Aside from adding the new action alongside the existing ones in
SteamVR_InputHandler.cs
, the action also was also added to the SteamVR_Standalone_IL2CPP library's GTFO branch in this pull requestThe input is bound to both
ToggleCommunicationMenu
and indirectly theMenuScroll (-1f)
actions, and we only return true for the relevant action depending on whether theeFocusState
isFPS
orFPS_CommunicationDialog
.This is complicated by the fact that, as far as I can tell, the game never queries the
SelectCommunicationMenu
action. Even in the base game I could not getSelectCommunicationMenu
to work with an xbox controller, so I'm going to go ahead and say it is broken.To overcome this we
Prefix
patchPUI_CommunicationMenu.Update()
and check the input ourselves, callingPUI_CommunicationMenu.MoveNext()
withPUI_CommunicationMenu.m_highlightedButtonIndex
to make it "select" the currently highlighted item. The Prefix skips the function if an item is selected, so it shouldn't break is the devs decide to fix their input at some point.Since the menu toggle button obviously cannot be held down when the same button is used to navigate, we force
eCellSettingID.Gameplay_HoldToShowComsList
tofalse
every time theeFocusState
changes toFPS
.Finally,
PUI_CommunicationMenu.UpdateCmdTripMine
,PUI_CommunicationMenu.UpdateCmdSentryGun
, andPUI_CommunicationMenu.UpdateButtonsForNode
were added toInjectSemanticInteractionTweaks.cs
alongside the patches for normal mine and sentry placement, so placement is based on where your hand is rather than where the camera is pointing.PUI_CommunicationMenu.UpdateButtonsForNode
is what is used for the final placement, while the twoupdate
functions just display the markers.WorldSpaceUI geometry clipping
It turns out messing with the
MeshRenderer
of aTextMeshPro
has no affect ( now? It must have worked at some point in time ), and you must instead set eitherTextMeshPro.FontMaterial
orTextMeshPro.fontSharedMaterial
. As luck would have it, most of theWorldSpaceUI
elements share same font material, so inVRWorldSpaceUI.setSharedMaterialShader()
we just set thefontSharedMaterial
andRenderQueue
of an existingCommunicationMenu
text object and everything magically renders ontop of everything.The
Compass
has its own text material, but conveniently exposes it atPUI_Compass.m_fontMaterial
, so we repeat the process there, usingVRAssets.TextSphereClip
instead ofVRAssets.GetTextNoCull()
, and all is good.Nav markers text geometry clipping WorldSpaceUI.PrepareNavMarker() was actually already setting the
fontSharedMaterial
of allTextMeshPro
children, but if you inspect theNavMarker
s in-game, it turns out they end up with a completely different material. Not sure if they are completely separate objects or if something changes the material later. Ditto for the sprites?However, we also set the Sprite shader at InjectNavMarkerWorldSpace.InjectNavMarkerWorldSpriteHack patching
NavMarkerComponent.Start()
. This patch is what actually does all the work.NavMarkerComponent
has anm_text
field, and if we modify thefontSharedMaterial
of that all our problems are solved. This patch was also changed to modify thesharedMaterial
of the Sprite, instead of theMaterial
. This is now the only place theNavMarker
materials are modified.