Browse Source

Core: Convert Object3D and EventDispatcher to ES6 classes. (#21646)

* Core: Convert Object3D and EventDispatcher.

* WebXRManager: Convert to ES6 class.
Michael Herzog 4 years ago
parent
commit
669e43a51e
3 changed files with 455 additions and 454 deletions
  1. 9 11
      src/core/EventDispatcher.js
  2. 155 156
      src/core/Object3D.js
  3. 291 287
      src/renderers/webxr/WebXRManager.js

+ 9 - 11
src/core/EventDispatcher.js

@@ -2,11 +2,9 @@
  * https://github.com/mrdoob/eventdispatcher.js/
  */
 
-function EventDispatcher() {}
+class EventDispatcher {
 
-Object.assign( EventDispatcher.prototype, {
-
-	addEventListener: function ( type, listener ) {
+	addEventListener( type, listener ) {
 
 		if ( this._listeners === undefined ) this._listeners = {};
 
@@ -24,9 +22,9 @@ Object.assign( EventDispatcher.prototype, {
 
 		}
 
-	},
+	}
 
-	hasEventListener: function ( type, listener ) {
+	hasEventListener( type, listener ) {
 
 		if ( this._listeners === undefined ) return false;
 
@@ -34,9 +32,9 @@ Object.assign( EventDispatcher.prototype, {
 
 		return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;
 
-	},
+	}
 
-	removeEventListener: function ( type, listener ) {
+	removeEventListener( type, listener ) {
 
 		if ( this._listeners === undefined ) return;
 
@@ -55,9 +53,9 @@ Object.assign( EventDispatcher.prototype, {
 
 		}
 
-	},
+	}
 
-	dispatchEvent: function ( event ) {
+	dispatchEvent( event ) {
 
 		if ( this._listeners === undefined ) return;
 
@@ -83,7 +81,7 @@ Object.assign( EventDispatcher.prototype, {
 
 	}
 
-} );
+}
 
 
 export { EventDispatcher };

+ 155 - 156
src/core/Object3D.js

@@ -9,119 +9,114 @@ import { MathUtils } from '../math/MathUtils.js';
 
 let _object3DId = 0;
 
-const _v1 = new Vector3();
-const _q1 = new Quaternion();
-const _m1 = new Matrix4();
-const _target = new Vector3();
+const _v1 = new /*@__PURE__*/ Vector3();
+const _q1 = new /*@__PURE__*/ Quaternion();
+const _m1 = new /*@__PURE__*/ Matrix4();
+const _target = new /*@__PURE__*/ Vector3();
 
-const _position = new Vector3();
-const _scale = new Vector3();
-const _quaternion = new Quaternion();
+const _position = new /*@__PURE__*/ Vector3();
+const _scale = new /*@__PURE__*/ Vector3();
+const _quaternion = new /*@__PURE__*/ Quaternion();
 
-const _xAxis = new Vector3( 1, 0, 0 );
-const _yAxis = new Vector3( 0, 1, 0 );
-const _zAxis = new Vector3( 0, 0, 1 );
+const _xAxis = new /*@__PURE__*/ Vector3( 1, 0, 0 );
+const _yAxis = new /*@__PURE__*/ Vector3( 0, 1, 0 );
+const _zAxis = new /*@__PURE__*/ Vector3( 0, 0, 1 );
 
 const _addedEvent = { type: 'added' };
 const _removedEvent = { type: 'removed' };
 
-function Object3D() {
+class Object3D extends EventDispatcher {
 
-	Object.defineProperty( this, 'id', { value: _object3DId ++ } );
+	constructor() {
 
-	this.uuid = MathUtils.generateUUID();
+		super();
 
-	this.name = '';
-	this.type = 'Object3D';
+		Object.defineProperty( this, 'id', { value: _object3DId ++ } );
 
-	this.parent = null;
-	this.children = [];
+		this.uuid = MathUtils.generateUUID();
 
-	this.up = Object3D.DefaultUp.clone();
+		this.name = '';
+		this.type = 'Object3D';
 
-	const position = new Vector3();
-	const rotation = new Euler();
-	const quaternion = new Quaternion();
-	const scale = new Vector3( 1, 1, 1 );
+		this.parent = null;
+		this.children = [];
 
-	function onRotationChange() {
+		this.up = Object3D.DefaultUp.clone();
 
-		quaternion.setFromEuler( rotation, false );
+		const position = new Vector3();
+		const rotation = new Euler();
+		const quaternion = new Quaternion();
+		const scale = new Vector3( 1, 1, 1 );
 
-	}
+		function onRotationChange() {
 
-	function onQuaternionChange() {
+			quaternion.setFromEuler( rotation, false );
 
-		rotation.setFromQuaternion( quaternion, undefined, false );
+		}
 
-	}
+		function onQuaternionChange() {
 
-	rotation._onChange( onRotationChange );
-	quaternion._onChange( onQuaternionChange );
+			rotation.setFromQuaternion( quaternion, undefined, false );
 
-	Object.defineProperties( this, {
-		position: {
-			configurable: true,
-			enumerable: true,
-			value: position
-		},
-		rotation: {
-			configurable: true,
-			enumerable: true,
-			value: rotation
-		},
-		quaternion: {
-			configurable: true,
-			enumerable: true,
-			value: quaternion
-		},
-		scale: {
-			configurable: true,
-			enumerable: true,
-			value: scale
-		},
-		modelViewMatrix: {
-			value: new Matrix4()
-		},
-		normalMatrix: {
-			value: new Matrix3()
 		}
-	} );
 
-	this.matrix = new Matrix4();
-	this.matrixWorld = new Matrix4();
+		rotation._onChange( onRotationChange );
+		quaternion._onChange( onQuaternionChange );
 
-	this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
-	this.matrixWorldNeedsUpdate = false;
+		Object.defineProperties( this, {
+			position: {
+				configurable: true,
+				enumerable: true,
+				value: position
+			},
+			rotation: {
+				configurable: true,
+				enumerable: true,
+				value: rotation
+			},
+			quaternion: {
+				configurable: true,
+				enumerable: true,
+				value: quaternion
+			},
+			scale: {
+				configurable: true,
+				enumerable: true,
+				value: scale
+			},
+			modelViewMatrix: {
+				value: new Matrix4()
+			},
+			normalMatrix: {
+				value: new Matrix3()
+			}
+		} );
 
-	this.layers = new Layers();
-	this.visible = true;
+		this.matrix = new Matrix4();
+		this.matrixWorld = new Matrix4();
 
-	this.castShadow = false;
-	this.receiveShadow = false;
+		this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;
+		this.matrixWorldNeedsUpdate = false;
 
-	this.frustumCulled = true;
-	this.renderOrder = 0;
+		this.layers = new Layers();
+		this.visible = true;
 
-	this.animations = [];
+		this.castShadow = false;
+		this.receiveShadow = false;
 
-	this.userData = {};
+		this.frustumCulled = true;
+		this.renderOrder = 0;
 
-}
+		this.animations = [];
 
-Object3D.DefaultUp = new Vector3( 0, 1, 0 );
-Object3D.DefaultMatrixAutoUpdate = true;
+		this.userData = {};
 
-Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {
-
-	constructor: Object3D,
-
-	isObject3D: true,
+	}
 
-	onBeforeRender: function () {},
-	onAfterRender: function () {},
+	onBeforeRender() {}
+	onAfterRender() {}
 
-	applyMatrix4: function ( matrix ) {
+	applyMatrix4( matrix ) {
 
 		if ( this.matrixAutoUpdate ) this.updateMatrix();
 
@@ -129,47 +124,47 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		this.matrix.decompose( this.position, this.quaternion, this.scale );
 
-	},
+	}
 
-	applyQuaternion: function ( q ) {
+	applyQuaternion( q ) {
 
 		this.quaternion.premultiply( q );
 
 		return this;
 
-	},
+	}
 
-	setRotationFromAxisAngle: function ( axis, angle ) {
+	setRotationFromAxisAngle( axis, angle ) {
 
 		// assumes axis is normalized
 
 		this.quaternion.setFromAxisAngle( axis, angle );
 
-	},
+	}
 
-	setRotationFromEuler: function ( euler ) {
+	setRotationFromEuler( euler ) {
 
 		this.quaternion.setFromEuler( euler, true );
 
-	},
+	}
 
-	setRotationFromMatrix: function ( m ) {
+	setRotationFromMatrix( m ) {
 
 		// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
 
 		this.quaternion.setFromRotationMatrix( m );
 
-	},
+	}
 
-	setRotationFromQuaternion: function ( q ) {
+	setRotationFromQuaternion( q ) {
 
 		// assumes q is normalized
 
 		this.quaternion.copy( q );
 
-	},
+	}
 
-	rotateOnAxis: function ( axis, angle ) {
+	rotateOnAxis( axis, angle ) {
 
 		// rotate object on axis in object space
 		// axis is assumed to be normalized
@@ -180,9 +175,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		return this;
 
-	},
+	}
 
-	rotateOnWorldAxis: function ( axis, angle ) {
+	rotateOnWorldAxis( axis, angle ) {
 
 		// rotate object on axis in world space
 		// axis is assumed to be normalized
@@ -194,27 +189,27 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		return this;
 
-	},
+	}
 
-	rotateX: function ( angle ) {
+	rotateX( angle ) {
 
 		return this.rotateOnAxis( _xAxis, angle );
 
-	},
+	}
 
-	rotateY: function ( angle ) {
+	rotateY( angle ) {
 
 		return this.rotateOnAxis( _yAxis, angle );
 
-	},
+	}
 
-	rotateZ: function ( angle ) {
+	rotateZ( angle ) {
 
 		return this.rotateOnAxis( _zAxis, angle );
 
-	},
+	}
 
-	translateOnAxis: function ( axis, distance ) {
+	translateOnAxis( axis, distance ) {
 
 		// translate object by distance along axis in object space
 		// axis is assumed to be normalized
@@ -225,39 +220,39 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		return this;
 
-	},
+	}
 
-	translateX: function ( distance ) {
+	translateX( distance ) {
 
 		return this.translateOnAxis( _xAxis, distance );
 
-	},
+	}
 
-	translateY: function ( distance ) {
+	translateY( distance ) {
 
 		return this.translateOnAxis( _yAxis, distance );
 
-	},
+	}
 
-	translateZ: function ( distance ) {
+	translateZ( distance ) {
 
 		return this.translateOnAxis( _zAxis, distance );
 
-	},
+	}
 
-	localToWorld: function ( vector ) {
+	localToWorld( vector ) {
 
 		return vector.applyMatrix4( this.matrixWorld );
 
-	},
+	}
 
-	worldToLocal: function ( vector ) {
+	worldToLocal( vector ) {
 
 		return vector.applyMatrix4( _m1.copy( this.matrixWorld ).invert() );
 
-	},
+	}
 
-	lookAt: function ( x, y, z ) {
+	lookAt( x, y, z ) {
 
 		// This method does not support objects having non-uniformly-scaled parent(s)
 
@@ -297,9 +292,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		}
 
-	},
+	}
 
-	add: function ( object ) {
+	add( object ) {
 
 		if ( arguments.length > 1 ) {
 
@@ -341,9 +336,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		return this;
 
-	},
+	}
 
-	remove: function ( object ) {
+	remove( object ) {
 
 		if ( arguments.length > 1 ) {
 
@@ -370,9 +365,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		return this;
 
-	},
+	}
 
-	clear: function () {
+	clear() {
 
 		for ( let i = 0; i < this.children.length; i ++ ) {
 
@@ -389,9 +384,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 		return this;
 
 
-	},
+	}
 
-	attach: function ( object ) {
+	attach( object ) {
 
 		// adds object as a child of this, while maintaining the object's world transform
 
@@ -415,21 +410,21 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		return this;
 
-	},
+	}
 
-	getObjectById: function ( id ) {
+	getObjectById( id ) {
 
 		return this.getObjectByProperty( 'id', id );
 
-	},
+	}
 
-	getObjectByName: function ( name ) {
+	getObjectByName( name ) {
 
 		return this.getObjectByProperty( 'name', name );
 
-	},
+	}
 
-	getObjectByProperty: function ( name, value ) {
+	getObjectByProperty( name, value ) {
 
 		if ( this[ name ] === value ) return this;
 
@@ -448,9 +443,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		return undefined;
 
-	},
+	}
 
-	getWorldPosition: function ( target ) {
+	getWorldPosition( target ) {
 
 		if ( target === undefined ) {
 
@@ -463,9 +458,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		return target.setFromMatrixPosition( this.matrixWorld );
 
-	},
+	}
 
-	getWorldQuaternion: function ( target ) {
+	getWorldQuaternion( target ) {
 
 		if ( target === undefined ) {
 
@@ -480,9 +475,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		return target;
 
-	},
+	}
 
-	getWorldScale: function ( target ) {
+	getWorldScale( target ) {
 
 		if ( target === undefined ) {
 
@@ -497,9 +492,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		return target;
 
-	},
+	}
 
-	getWorldDirection: function ( target ) {
+	getWorldDirection( target ) {
 
 		if ( target === undefined ) {
 
@@ -514,11 +509,11 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();
 
-	},
+	}
 
-	raycast: function () {},
+	raycast() {}
 
-	traverse: function ( callback ) {
+	traverse( callback ) {
 
 		callback( this );
 
@@ -530,9 +525,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		}
 
-	},
+	}
 
-	traverseVisible: function ( callback ) {
+	traverseVisible( callback ) {
 
 		if ( this.visible === false ) return;
 
@@ -546,9 +541,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		}
 
-	},
+	}
 
-	traverseAncestors: function ( callback ) {
+	traverseAncestors( callback ) {
 
 		const parent = this.parent;
 
@@ -560,17 +555,17 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		}
 
-	},
+	}
 
-	updateMatrix: function () {
+	updateMatrix() {
 
 		this.matrix.compose( this.position, this.quaternion, this.scale );
 
 		this.matrixWorldNeedsUpdate = true;
 
-	},
+	}
 
-	updateMatrixWorld: function ( force ) {
+	updateMatrixWorld( force ) {
 
 		if ( this.matrixAutoUpdate ) this.updateMatrix();
 
@@ -602,9 +597,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		}
 
-	},
+	}
 
-	updateWorldMatrix: function ( updateParents, updateChildren ) {
+	updateWorldMatrix( updateParents, updateChildren ) {
 
 		const parent = this.parent;
 
@@ -640,9 +635,9 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		}
 
-	},
+	}
 
-	toJSON: function ( meta ) {
+	toJSON( meta ) {
 
 		// meta is a string when called from JSON.stringify
 		const isRootObject = ( meta === undefined || typeof meta === 'string' );
@@ -857,15 +852,15 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 		}
 
-	},
+	}
 
-	clone: function ( recursive ) {
+	clone( recursive ) {
 
 		return new this.constructor().copy( this, recursive );
 
-	},
+	}
 
-	copy: function ( source, recursive = true ) {
+	copy( source, recursive = true ) {
 
 		this.name = source.name;
 
@@ -908,7 +903,11 @@ Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 
 	}
 
-} );
+}
+
+Object3D.DefaultUp = new Vector3( 0, 1, 0 );
+Object3D.DefaultMatrixAutoUpdate = true;
 
+Object3D.prototype.isObject3D = true;
 
 export { Object3D };

+ 291 - 287
src/renderers/webxr/WebXRManager.js

@@ -6,485 +6,489 @@ import { Vector4 } from '../../math/Vector4.js';
 import { WebGLAnimation } from '../webgl/WebGLAnimation.js';
 import { WebXRController } from './WebXRController.js';
 
-function WebXRManager( renderer, gl ) {
+class WebXRManager extends EventDispatcher {
 
-	const scope = this;
-	const state = renderer.state;
+	constructor( renderer, gl ) {
 
-	let session = null;
+		super();
 
-	let framebufferScaleFactor = 1.0;
+		const scope = this;
+		const state = renderer.state;
 
-	let referenceSpace = null;
-	let referenceSpaceType = 'local-floor';
+		let session = null;
 
-	let pose = null;
+		let framebufferScaleFactor = 1.0;
 
-	const controllers = [];
-	const inputSourcesMap = new Map();
+		let referenceSpace = null;
+		let referenceSpaceType = 'local-floor';
 
-	//
+		let pose = null;
 
-	const cameraL = new PerspectiveCamera();
-	cameraL.layers.enable( 1 );
-	cameraL.viewport = new Vector4();
+		const controllers = [];
+		const inputSourcesMap = new Map();
 
-	const cameraR = new PerspectiveCamera();
-	cameraR.layers.enable( 2 );
-	cameraR.viewport = new Vector4();
+		//
+
+		const cameraL = new PerspectiveCamera();
+		cameraL.layers.enable( 1 );
+		cameraL.viewport = new Vector4();
 
-	const cameras = [ cameraL, cameraR ];
+		const cameraR = new PerspectiveCamera();
+		cameraR.layers.enable( 2 );
+		cameraR.viewport = new Vector4();
 
-	const cameraVR = new ArrayCamera();
-	cameraVR.layers.enable( 1 );
-	cameraVR.layers.enable( 2 );
+		const cameras = [ cameraL, cameraR ];
 
-	let _currentDepthNear = null;
-	let _currentDepthFar = null;
+		const cameraVR = new ArrayCamera();
+		cameraVR.layers.enable( 1 );
+		cameraVR.layers.enable( 2 );
 
-	//
+		let _currentDepthNear = null;
+		let _currentDepthFar = null;
 
-	this.enabled = false;
+		//
 
-	this.isPresenting = false;
+		this.enabled = false;
 
-	this.getController = function ( index ) {
+		this.isPresenting = false;
 
-		let controller = controllers[ index ];
+		this.getController = function ( index ) {
 
-		if ( controller === undefined ) {
+			let controller = controllers[ index ];
 
-			controller = new WebXRController();
-			controllers[ index ] = controller;
+			if ( controller === undefined ) {
 
-		}
+				controller = new WebXRController();
+				controllers[ index ] = controller;
 
-		return controller.getTargetRaySpace();
+			}
 
-	};
+			return controller.getTargetRaySpace();
 
-	this.getControllerGrip = function ( index ) {
+		};
 
-		let controller = controllers[ index ];
+		this.getControllerGrip = function ( index ) {
 
-		if ( controller === undefined ) {
+			let controller = controllers[ index ];
 
-			controller = new WebXRController();
-			controllers[ index ] = controller;
+			if ( controller === undefined ) {
 
-		}
+				controller = new WebXRController();
+				controllers[ index ] = controller;
 
-		return controller.getGripSpace();
+			}
 
-	};
+			return controller.getGripSpace();
 
-	this.getHand = function ( index ) {
+		};
 
-		let controller = controllers[ index ];
+		this.getHand = function ( index ) {
 
-		if ( controller === undefined ) {
+			let controller = controllers[ index ];
 
-			controller = new WebXRController();
-			controllers[ index ] = controller;
+			if ( controller === undefined ) {
 
-		}
+				controller = new WebXRController();
+				controllers[ index ] = controller;
 
-		return controller.getHandSpace();
+			}
+
+			return controller.getHandSpace();
 
-	};
+		};
+
+		//
 
-	//
+		function onSessionEvent( event ) {
 
-	function onSessionEvent( event ) {
+			const controller = inputSourcesMap.get( event.inputSource );
 
-		const controller = inputSourcesMap.get( event.inputSource );
+			if ( controller ) {
 
-		if ( controller ) {
+				controller.dispatchEvent( { type: event.type, data: event.inputSource } );
 
-			controller.dispatchEvent( { type: event.type, data: event.inputSource } );
+			}
 
 		}
 
-	}
+		function onSessionEnd() {
 
-	function onSessionEnd() {
+			inputSourcesMap.forEach( function ( controller, inputSource ) {
 
-		inputSourcesMap.forEach( function ( controller, inputSource ) {
+				controller.disconnect( inputSource );
 
-			controller.disconnect( inputSource );
+			} );
 
-		} );
+			inputSourcesMap.clear();
 
-		inputSourcesMap.clear();
+			_currentDepthNear = null;
+			_currentDepthFar = null;
 
-		_currentDepthNear = null;
-		_currentDepthFar = null;
+			// restore framebuffer/rendering state
 
-		// restore framebuffer/rendering state
+			state.bindXRFramebuffer( null );
+			renderer.setRenderTarget( renderer.getRenderTarget() );
 
-		state.bindXRFramebuffer( null );
-		renderer.setRenderTarget( renderer.getRenderTarget() );
+			//
 
-		//
+			animation.stop();
 
-		animation.stop();
+			scope.isPresenting = false;
 
-		scope.isPresenting = false;
+			scope.dispatchEvent( { type: 'sessionend' } );
 
-		scope.dispatchEvent( { type: 'sessionend' } );
+		}
 
-	}
+		this.setFramebufferScaleFactor = function ( value ) {
 
-	this.setFramebufferScaleFactor = function ( value ) {
+			framebufferScaleFactor = value;
 
-		framebufferScaleFactor = value;
+			if ( scope.isPresenting === true ) {
 
-		if ( scope.isPresenting === true ) {
+				console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' );
 
-			console.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' );
+			}
 
-		}
+		};
 
-	};
+		this.setReferenceSpaceType = function ( value ) {
 
-	this.setReferenceSpaceType = function ( value ) {
+			referenceSpaceType = value;
 
-		referenceSpaceType = value;
+			if ( scope.isPresenting === true ) {
 
-		if ( scope.isPresenting === true ) {
+				console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' );
 
-			console.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' );
+			}
 
-		}
+		};
 
-	};
+		this.getReferenceSpace = function () {
 
-	this.getReferenceSpace = function () {
+			return referenceSpace;
 
-		return referenceSpace;
+		};
 
-	};
+		this.getSession = function () {
 
-	this.getSession = function () {
+			return session;
 
-		return session;
+		};
 
-	};
+		this.setSession = async function ( value ) {
 
-	this.setSession = async function ( value ) {
+			session = value;
 
-		session = value;
+			if ( session !== null ) {
 
-		if ( session !== null ) {
+				session.addEventListener( 'select', onSessionEvent );
+				session.addEventListener( 'selectstart', onSessionEvent );
+				session.addEventListener( 'selectend', onSessionEvent );
+				session.addEventListener( 'squeeze', onSessionEvent );
+				session.addEventListener( 'squeezestart', onSessionEvent );
+				session.addEventListener( 'squeezeend', onSessionEvent );
+				session.addEventListener( 'end', onSessionEnd );
+				session.addEventListener( 'inputsourceschange', onInputSourcesChange );
 
-			session.addEventListener( 'select', onSessionEvent );
-			session.addEventListener( 'selectstart', onSessionEvent );
-			session.addEventListener( 'selectend', onSessionEvent );
-			session.addEventListener( 'squeeze', onSessionEvent );
-			session.addEventListener( 'squeezestart', onSessionEvent );
-			session.addEventListener( 'squeezeend', onSessionEvent );
-			session.addEventListener( 'end', onSessionEnd );
-			session.addEventListener( 'inputsourceschange', onInputSourcesChange );
+				const attributes = gl.getContextAttributes();
 
-			const attributes = gl.getContextAttributes();
+				if ( attributes.xrCompatible !== true ) {
 
-			if ( attributes.xrCompatible !== true ) {
+					await gl.makeXRCompatible();
 
-				await gl.makeXRCompatible();
+				}
 
-			}
+				const layerInit = {
+					antialias: attributes.antialias,
+					alpha: attributes.alpha,
+					depth: attributes.depth,
+					stencil: attributes.stencil,
+					framebufferScaleFactor: framebufferScaleFactor
+				};
 
-			const layerInit = {
-				antialias: attributes.antialias,
-				alpha: attributes.alpha,
-				depth: attributes.depth,
-				stencil: attributes.stencil,
-				framebufferScaleFactor: framebufferScaleFactor
-			};
+				// eslint-disable-next-line no-undef
+				const baseLayer = new XRWebGLLayer( session, gl, layerInit );
 
-			// eslint-disable-next-line no-undef
-			const baseLayer = new XRWebGLLayer( session, gl, layerInit );
+				session.updateRenderState( { baseLayer: baseLayer } );
 
-			session.updateRenderState( { baseLayer: baseLayer } );
+				referenceSpace = await session.requestReferenceSpace( referenceSpaceType );
 
-			referenceSpace = await session.requestReferenceSpace( referenceSpaceType );
+				animation.setContext( session );
+				animation.start();
 
-			animation.setContext( session );
-			animation.start();
+				scope.isPresenting = true;
 
-			scope.isPresenting = true;
+				scope.dispatchEvent( { type: 'sessionstart' } );
 
-			scope.dispatchEvent( { type: 'sessionstart' } );
+			}
 
-		}
+		};
 
-	};
+		function onInputSourcesChange( event ) {
 
-	function onInputSourcesChange( event ) {
+			const inputSources = session.inputSources;
 
-		const inputSources = session.inputSources;
+			// Assign inputSources to available controllers
 
-		// Assign inputSources to available controllers
+			for ( let i = 0; i < controllers.length; i ++ ) {
 
-		for ( let i = 0; i < controllers.length; i ++ ) {
+				inputSourcesMap.set( inputSources[ i ], controllers[ i ] );
 
-			inputSourcesMap.set( inputSources[ i ], controllers[ i ] );
+			}
 
-		}
+			// Notify disconnected
 
-		// Notify disconnected
+			for ( let i = 0; i < event.removed.length; i ++ ) {
 
-		for ( let i = 0; i < event.removed.length; i ++ ) {
+				const inputSource = event.removed[ i ];
+				const controller = inputSourcesMap.get( inputSource );
 
-			const inputSource = event.removed[ i ];
-			const controller = inputSourcesMap.get( inputSource );
+				if ( controller ) {
 
-			if ( controller ) {
+					controller.dispatchEvent( { type: 'disconnected', data: inputSource } );
+					inputSourcesMap.delete( inputSource );
 
-				controller.dispatchEvent( { type: 'disconnected', data: inputSource } );
-				inputSourcesMap.delete( inputSource );
+				}
 
 			}
 
-		}
+			// Notify connected
 
-		// Notify connected
+			for ( let i = 0; i < event.added.length; i ++ ) {
 
-		for ( let i = 0; i < event.added.length; i ++ ) {
+				const inputSource = event.added[ i ];
+				const controller = inputSourcesMap.get( inputSource );
 
-			const inputSource = event.added[ i ];
-			const controller = inputSourcesMap.get( inputSource );
+				if ( controller ) {
 
-			if ( controller ) {
+					controller.dispatchEvent( { type: 'connected', data: inputSource } );
 
-				controller.dispatchEvent( { type: 'connected', data: inputSource } );
+				}
 
 			}
 
 		}
 
-	}
+		//
 
-	//
-
-	const cameraLPos = new Vector3();
-	const cameraRPos = new Vector3();
-
-	/**
-	 * Assumes 2 cameras that are parallel and share an X-axis, and that
-	 * the cameras' projection and world matrices have already been set.
-	 * And that near and far planes are identical for both cameras.
-	 * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
-	 */
-	function setProjectionFromUnion( camera, cameraL, cameraR ) {
-
-		cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
-		cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
-
-		const ipd = cameraLPos.distanceTo( cameraRPos );
-
-		const projL = cameraL.projectionMatrix.elements;
-		const projR = cameraR.projectionMatrix.elements;
-
-		// VR systems will have identical far and near planes, and
-		// most likely identical top and bottom frustum extents.
-		// Use the left camera for these values.
-		const near = projL[ 14 ] / ( projL[ 10 ] - 1 );
-		const far = projL[ 14 ] / ( projL[ 10 ] + 1 );
-		const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
-		const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
-
-		const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
-		const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
-		const left = near * leftFov;
-		const right = near * rightFov;
-
-		// Calculate the new camera's position offset from the
-		// left camera. xOffset should be roughly half `ipd`.
-		const zOffset = ipd / ( - leftFov + rightFov );
-		const xOffset = zOffset * - leftFov;
-
-		// TODO: Better way to apply this offset?
-		cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
-		camera.translateX( xOffset );
-		camera.translateZ( zOffset );
-		camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
-		camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
-
-		// Find the union of the frustum values of the cameras and scale
-		// the values so that the near plane's position does not change in world space,
-		// although must now be relative to the new union camera.
-		const near2 = near + zOffset;
-		const far2 = far + zOffset;
-		const left2 = left - xOffset;
-		const right2 = right + ( ipd - xOffset );
-		const top2 = topFov * far / far2 * near2;
-		const bottom2 = bottomFov * far / far2 * near2;
-
-		camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
+		const cameraLPos = new Vector3();
+		const cameraRPos = new Vector3();
+
+		/**
+		 * Assumes 2 cameras that are parallel and share an X-axis, and that
+		 * the cameras' projection and world matrices have already been set.
+		 * And that near and far planes are identical for both cameras.
+		 * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765
+		 */
+		function setProjectionFromUnion( camera, cameraL, cameraR ) {
+
+			cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
+			cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
+
+			const ipd = cameraLPos.distanceTo( cameraRPos );
+
+			const projL = cameraL.projectionMatrix.elements;
+			const projR = cameraR.projectionMatrix.elements;
+
+			// VR systems will have identical far and near planes, and
+			// most likely identical top and bottom frustum extents.
+			// Use the left camera for these values.
+			const near = projL[ 14 ] / ( projL[ 10 ] - 1 );
+			const far = projL[ 14 ] / ( projL[ 10 ] + 1 );
+			const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
+			const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
+
+			const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
+			const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
+			const left = near * leftFov;
+			const right = near * rightFov;
+
+			// Calculate the new camera's position offset from the
+			// left camera. xOffset should be roughly half `ipd`.
+			const zOffset = ipd / ( - leftFov + rightFov );
+			const xOffset = zOffset * - leftFov;
+
+			// TODO: Better way to apply this offset?
+			cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
+			camera.translateX( xOffset );
+			camera.translateZ( zOffset );
+			camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
+			camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
+
+			// Find the union of the frustum values of the cameras and scale
+			// the values so that the near plane's position does not change in world space,
+			// although must now be relative to the new union camera.
+			const near2 = near + zOffset;
+			const far2 = far + zOffset;
+			const left2 = left - xOffset;
+			const right2 = right + ( ipd - xOffset );
+			const top2 = topFov * far / far2 * near2;
+			const bottom2 = bottomFov * far / far2 * near2;
+
+			camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
 
-	}
+		}
 
-	function updateCamera( camera, parent ) {
+		function updateCamera( camera, parent ) {
 
-		if ( parent === null ) {
+			if ( parent === null ) {
 
-			camera.matrixWorld.copy( camera.matrix );
+				camera.matrixWorld.copy( camera.matrix );
 
-		} else {
+			} else {
 
-			camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
+				camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
 
-		}
+			}
 
-		camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
+			camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
 
-	}
+		}
 
-	this.getCamera = function ( camera ) {
+		this.getCamera = function ( camera ) {
 
-		cameraVR.near = cameraR.near = cameraL.near = camera.near;
-		cameraVR.far = cameraR.far = cameraL.far = camera.far;
+			cameraVR.near = cameraR.near = cameraL.near = camera.near;
+			cameraVR.far = cameraR.far = cameraL.far = camera.far;
 
-		if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) {
+			if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) {
 
-			// Note that the new renderState won't apply until the next frame. See #18320
+				// Note that the new renderState won't apply until the next frame. See #18320
 
-			session.updateRenderState( {
-				depthNear: cameraVR.near,
-				depthFar: cameraVR.far
-			} );
+				session.updateRenderState( {
+					depthNear: cameraVR.near,
+					depthFar: cameraVR.far
+				} );
 
-			_currentDepthNear = cameraVR.near;
-			_currentDepthFar = cameraVR.far;
+				_currentDepthNear = cameraVR.near;
+				_currentDepthFar = cameraVR.far;
 
-		}
+			}
 
-		const parent = camera.parent;
-		const cameras = cameraVR.cameras;
+			const parent = camera.parent;
+			const cameras = cameraVR.cameras;
 
-		updateCamera( cameraVR, parent );
+			updateCamera( cameraVR, parent );
 
-		for ( let i = 0; i < cameras.length; i ++ ) {
+			for ( let i = 0; i < cameras.length; i ++ ) {
 
-			updateCamera( cameras[ i ], parent );
+				updateCamera( cameras[ i ], parent );
 
-		}
+			}
 
-		// update camera and its children
+			// update camera and its children
 
-		camera.matrixWorld.copy( cameraVR.matrixWorld );
-		camera.matrix.copy( cameraVR.matrix );
-		camera.matrix.decompose( camera.position, camera.quaternion, camera.scale );
+			camera.matrixWorld.copy( cameraVR.matrixWorld );
+			camera.matrix.copy( cameraVR.matrix );
+			camera.matrix.decompose( camera.position, camera.quaternion, camera.scale );
 
-		const children = camera.children;
+			const children = camera.children;
 
-		for ( let i = 0, l = children.length; i < l; i ++ ) {
+			for ( let i = 0, l = children.length; i < l; i ++ ) {
 
-			children[ i ].updateMatrixWorld( true );
+				children[ i ].updateMatrixWorld( true );
 
-		}
+			}
 
-		// update projection matrix for proper view frustum culling
+			// update projection matrix for proper view frustum culling
 
-		if ( cameras.length === 2 ) {
+			if ( cameras.length === 2 ) {
 
-			setProjectionFromUnion( cameraVR, cameraL, cameraR );
+				setProjectionFromUnion( cameraVR, cameraL, cameraR );
 
-		} else {
+			} else {
 
-			// assume single camera setup (AR)
+				// assume single camera setup (AR)
 
-			cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
+				cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
 
-		}
+			}
 
-		return cameraVR;
+			return cameraVR;
 
-	};
+		};
 
-	// Animation Loop
+		// Animation Loop
 
-	let onAnimationFrameCallback = null;
+		let onAnimationFrameCallback = null;
 
-	function onAnimationFrame( time, frame ) {
+		function onAnimationFrame( time, frame ) {
 
-		pose = frame.getViewerPose( referenceSpace );
+			pose = frame.getViewerPose( referenceSpace );
 
-		if ( pose !== null ) {
+			if ( pose !== null ) {
 
-			const views = pose.views;
-			const baseLayer = session.renderState.baseLayer;
+				const views = pose.views;
+				const baseLayer = session.renderState.baseLayer;
 
-			state.bindXRFramebuffer( baseLayer.framebuffer );
+				state.bindXRFramebuffer( baseLayer.framebuffer );
 
-			let cameraVRNeedsUpdate = false;
+				let cameraVRNeedsUpdate = false;
 
-			// check if it's necessary to rebuild cameraVR's camera list
+				// check if it's necessary to rebuild cameraVR's camera list
 
-			if ( views.length !== cameraVR.cameras.length ) {
+				if ( views.length !== cameraVR.cameras.length ) {
 
-				cameraVR.cameras.length = 0;
-				cameraVRNeedsUpdate = true;
+					cameraVR.cameras.length = 0;
+					cameraVRNeedsUpdate = true;
 
-			}
+				}
 
-			for ( let i = 0; i < views.length; i ++ ) {
+				for ( let i = 0; i < views.length; i ++ ) {
 
-				const view = views[ i ];
-				const viewport = baseLayer.getViewport( view );
+					const view = views[ i ];
+					const viewport = baseLayer.getViewport( view );
 
-				const camera = cameras[ i ];
-				camera.matrix.fromArray( view.transform.matrix );
-				camera.projectionMatrix.fromArray( view.projectionMatrix );
-				camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
+					const camera = cameras[ i ];
+					camera.matrix.fromArray( view.transform.matrix );
+					camera.projectionMatrix.fromArray( view.projectionMatrix );
+					camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
 
-				if ( i === 0 ) {
+					if ( i === 0 ) {
 
-					cameraVR.matrix.copy( camera.matrix );
+						cameraVR.matrix.copy( camera.matrix );
 
-				}
+					}
 
-				if ( cameraVRNeedsUpdate === true ) {
+					if ( cameraVRNeedsUpdate === true ) {
 
-					cameraVR.cameras.push( camera );
+						cameraVR.cameras.push( camera );
+
+					}
 
 				}
 
 			}
 
-		}
+			//
 
-		//
+			const inputSources = session.inputSources;
+
+			for ( let i = 0; i < controllers.length; i ++ ) {
 
-		const inputSources = session.inputSources;
+				const controller = controllers[ i ];
+				const inputSource = inputSources[ i ];
 
-		for ( let i = 0; i < controllers.length; i ++ ) {
+				controller.update( inputSource, frame, referenceSpace );
 
-			const controller = controllers[ i ];
-			const inputSource = inputSources[ i ];
+			}
 
-			controller.update( inputSource, frame, referenceSpace );
+			if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );
 
 		}
 
-		if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );
+		const animation = new WebGLAnimation();
+		animation.setAnimationLoop( onAnimationFrame );
 
-	}
+		this.setAnimationLoop = function ( callback ) {
 
-	const animation = new WebGLAnimation();
-	animation.setAnimationLoop( onAnimationFrame );
+			onAnimationFrameCallback = callback;
 
-	this.setAnimationLoop = function ( callback ) {
+		};
 
-		onAnimationFrameCallback = callback;
+		this.dispose = function () {};
 
-	};
-
-	this.dispose = function () {};
+	}
 
 }
 
-Object.assign( WebXRManager.prototype, EventDispatcher.prototype );
-
 export { WebXRManager };