VR Design Notes – Radial Menu and Control Overrides

      Comments Off on VR Design Notes – Radial Menu and Control Overrides

Goal:

I want a radial menu with a variable # of buttons that comes up on a transposed position from the parent object. It will use the touchpad to detect the direction of the button the user wants to select, and a press of the button will press that button. The center area will be a back button to close the menu without making a selection. Optionally I’ll require a selection and that center area won’t be available.


Implementation:

I need a custom shaped button that will have a triangular shape from the origin with a neutral point in the center that has no selection to close the menu. An implementation of BaseInputModule will be needed to translate the touchpad Axis0 positions to screen coordinates for selection as well as the touch button push to fire pressed events. The menu itself will deal with positioning a variable # of buttons and handle events for each button pressed that will funnel into a single event that the parent object will consume and handle. Multiple components on the source of the menu object might need to know the result of a menu selection so I’ll want to give the event subscribing component a reference to each object or have a common interface and use GetComponents<T>() to get everything that needs notification. SendMessage or BroadcastMessage would be a way as well but I’m not a fan of that loosely connected style and it also has some requirements about the object structure that I don’t want to enforce. Since the touchpad will be used to interface with the menu I’ll need a way to lock down any other usage of the touchpad while the menu is open. I’m thinking perhaps I need a shared component for each controller that checks to see if a component is allowed to use a button. A higher priority component could lock down access to a particular button and a lower priority component bypasses parts of its update cycle if a button it requires is unavailable. In my current setup a component is either on a vive controller, or it’s picked up by a controller and has a reference to the controller holding it, so since I can guarantee a reference to a button access manager component through that route I won’t be adding any undue reference wiring or hierarchy searching.


New Components:

ViveTouchpadInputModule: Implementation of BaseInputModule to map touchpad controls to ScreenSpace UI interactions.

MenuController: This component is on the menu panel/canvas game object. Will receive method calls with string arguments from button presses wired up in the editor and fire an event back up to notify that a press happened.

MenuEventDispatcher: This component is on the object that needs to spawn the menu. It will show / hide the menu as well as subscribe to events from the MenuController. The MenuController is referenced in the inspector window. This component will also notify IMenuEventReceiver implementations when an event comes back from the MenuController.

IMenuEventReceiver: Implements a method to receive the string argument which identifies the button press on the menu. Components that need to react in some way to the press of a menu button will implement this interface. The method will give a string key representing which menu the event came from as well as a string value to inform about the selection made.

ButtonAvailabilityManager: maintains a dictionary if ViveButton enum and boolean access flags. Certain components that take priority will set this while lower priority components need to check if they’re allowed to function. Scenarios where more than one high priority component uses the same button shouldn’t come up and if they do it might be an indicator that the control scheme has gotten too complicated with too much functionality tied to the same buttons at the same time.