WebXRController doesn't check for button pressed changes

I would like to use some of the controller buttons to control some things. However there is no event to detect button pressed states. Am I required to modify the controller to check input sources in the update method and send an event. Considering the update method isn’t doing it. Its not great having to do that externally and then check with controller it came from.

This seems to work patching the player. The less code in a frame loop the better so have it optional checking for button states. The controller grip model also has button state checks but its not sent as an event.

The only problem now is the pressed state continues for 8 frames.

class XRController extends THREE.WebXRController {
				constructor(xrManager) {
					super();

					this.previousButtonState = [];
				}

				static patchXRManager(xr) {
					xr._getController = ( index ) => {

						let controller = xr._controllers[ index ];

						if ( controller === undefined ) {

							controller = new XRController();
							xr._controllers[ index ] = controller;

						}

						return controller;

					}

				}

				update( inputSource, frame, referenceSpace ) {
					super.update(inputSource, frame, referenceSpace);

			
					const buttons = inputSource.gamepad.buttons,
					activeButton = buttons.filter(button => button.pressed)[0],
					activeIndex = buttons.indexOf(activeButton);

					if (this.previousButtonState[activeIndex]) {
						console.log("previous active indesx ", activeIndex);
						this.previousButtonState[activeIndex] = false;
					} else if (activeButton && !this.previousButtonState[activeIndex]) {
						console.log(activeButton, activeIndex);

						this.previousButtonState[activeIndex] = true;
					}
					

				}
			}
XRController.patchXRManager(renderer.xr);

Better example. The button pressed state doesnt clear for 300ms ? Very clunky to handle. There must be a better way ?

class XRController extends THREE.WebXRController {
				constructor(xrManager) {
					super();

					this.previousButtonState = [];
				}

				static patchXRManager(xr) {
					xr._getController = ( index ) => {

						let controller = xr._controllers[ index ];

						if ( controller === undefined ) {

							controller = new XRController();
							xr._controllers[ index ] = controller;

						}

						return controller;

					}

				}

				update( inputSource, frame, referenceSpace ) {
					super.update(inputSource, frame, referenceSpace);

			
					const buttons = inputSource.gamepad.buttons,
					activeButton = buttons.filter(button => button.pressed && button.value == 1)[0],
					activeIndex = buttons.indexOf(activeButton);

					 if (activeButton && !this.previousButtonState[activeIndex]) {
						//console.log("active ", activeButton, activeIndex);

						this.previousButtonState[activeIndex] = true;

						this.dispatchEvent( { type: 'pressed', button: activeButton, index: activeIndex } );

						setTimeout(() => {
							this.previousButtonState[activeIndex] = false;
							this.dispatchEvent( { type: 'pressedend', button: activeButton, index: activeIndex } );
						}, 300);
					}
					

				}
			}

controller1.addEventListener( 'pressed', (event) => {
					console.log(`Button Pressed: ${event.button} index : ${event.index}`);
				} );

				controller1.addEventListener( 'pressedend', (event) => {
					console.log(`Button Pressed End: ${event.button} index : ${event.index}`);
				} );

I’ve made it a module. Seems to work. GitHub - danrossi/three-xr-controller

1 Like