Skip to content

Mechanical buttons

richardTingle edited this page Feb 9, 2024 · 4 revisions

Mechanical buttons are a specialised form of touch control (or technically a series of nodes that use a touch control. The idea is to create pressable buttons. They will also respond to pick line based interaction.

Simple mechanical toggles

Mechanical buttons

Mechanical buttons are pressed then immediately release. They issue a click event when they are fully depressed. They support both finger tip interaction and pick line interaction (and also Non-VR mouse interaction for non VR modes)

Geometry button = (Geometry)getApplication().getAssetManager().loadModel("Models/buttons/redCircle.j3o");
MechanicalButton mechanicalButton = new MechanicalButton(button, ButtonMovementAxis.NEGATIVE_Z, 0.02f, 0.5f);
mechanicalButton.setHapticOnFullDepress(new Haptic(ActionHandles.HAPTIC, 0.1f, 100f, 0.5f));
mechanicalButton.addPressListener(() -> System.out.println("pressed"));
node.attachChild(mechanicalButton);

Mechanical toggles

Mechanical toggles have two stable states; on and off. Each time they are fully depressed they change states, when the button is [on] its stop point is closer in; like a toggle button (see diagram)

Toggle explanation

 Geometry button = (Geometry)getApplication().getAssetManager().loadModel("Models/buttons/redHexagon.j3o");
 MechanicalToggle mechanicalToggle = new MechanicalToggle(button, ButtonMovementAxis.NEGATIVE_Z, 0.04f, 0.03f, 0.2f);
 mechanicalToggle.addPressListener((toggleState) -> System.out.println("State is " + toggleState)));
 node.attachChild(mechanicalToggle);

Observing state changes

The mechanical button/toggle exposes two interfaces to query it for change, neither of these are inherently better than the other but both are provided to fit into your application flow as required

Callbacks

The mechanical buttons can have listeners attached to them

mechanicalButton.addPressListener(() -> System.out.println("pressed"));

mechanicalToggle.addPressListener((toggleState) -> System.out.println("State is " + toggleState)));

These instantly call the callbacks when the buttons are interacted with

Observable Value subscriptions

These allow a subscription to changes to be obtained that can be periodically polled for new events (probably within an update loop

ObservableEventSubscription mechanicalButtonChanges = mechanicalButton.subscribeToPressEvents();

ObservableValueSubscription<ToggleState> toggleState = mechanicalToggle.subscribeToPressEvents();

//later within an update loop
void update(tpf){
   if (mechanicalButtonChanges.checkHasChanged()){
       //make some action
   }

   if (toggleState.checkHasChanged()){
       ToggleState newValue = toggleState.get();
       //make some action
   }

}

Note that the mechanicalToggle has 4 states; FULLY_OFF, TOGGLED_ON, TRANSITIONING_OFF, TRANSITIONING_ON. It is possible to only listen to major state changes (ON and OFF):

ObservableValueSubscription<Boolean> majorEventsSubscription = mechanicalToggle.subscribeToOnOffEvents()

The Observable style can give more predicable update times (you choose where in your update cycle that button events are processed) but do require more set up.

#Desktop Mouse Interaction

While Tamarin is a VR library it aims to not get in the way of dual form factor applications. If you are using Lemur both the MechanicalButton and MechanicalToggle will respond to mouse button clicks.

Clone this wiki locally