playcanvas
Version:
PlayCanvas WebGL game engine
137 lines (134 loc) • 4.84 kB
JavaScript
import { platform } from '../../core/platform.js';
import { EventHandler } from '../../core/event-handler.js';
import { XRSPACE_VIEWER } from './constants.js';
import { XrHitTestSource } from './xr-hit-test-source.js';
class XrHitTest extends EventHandler {
_onSessionStart() {
if (this.manager.session.enabledFeatures) {
var available = this.manager.session.enabledFeatures.indexOf('hit-test') !== -1;
if (!available) return;
this._available = available;
this.fire('available');
} else if (!this._checkingAvailability) {
this._checkingAvailability = true;
this.manager.session.requestReferenceSpace(XRSPACE_VIEWER).then((referenceSpace)=>{
this.manager.session.requestHitTestSource({
space: referenceSpace
}).then((hitTestSource)=>{
hitTestSource.cancel();
if (this.manager.active) {
this._available = true;
this.fire('available');
}
}).catch(()=>{});
}).catch(()=>{});
}
}
_onSessionEnd() {
if (!this._available) return;
this._available = false;
for(var i = 0; i < this.sources.length; i++){
this.sources[i].onStop();
}
this.sources = [];
this.fire('unavailable');
}
start(options) {
if (options === undefined) options = {};
if (!this._supported) {
options.callback == null ? undefined : options.callback.call(options, new Error('XR HitTest is not supported'), null);
return;
}
if (!this._available) {
options.callback == null ? undefined : options.callback.call(options, new Error('XR HitTest is not available'), null);
return;
}
if (!options.profile && !options.spaceType) {
options.spaceType = XRSPACE_VIEWER;
}
var xrRay;
var offsetRay = options.offsetRay;
if (offsetRay) {
var origin = new DOMPoint(offsetRay.origin.x, offsetRay.origin.y, offsetRay.origin.z, 1.0);
var direction = new DOMPoint(offsetRay.direction.x, offsetRay.direction.y, offsetRay.direction.z, 0.0);
xrRay = new XRRay(origin, direction);
}
var callback = options.callback;
if (options.spaceType) {
this.manager.session.requestReferenceSpace(options.spaceType).then((referenceSpace)=>{
if (!this.manager.session) {
var err = new Error('XR Session is not started (2)');
if (callback) callback(err);
this.fire('error', err);
return;
}
this.manager.session.requestHitTestSource({
space: referenceSpace,
entityTypes: options.entityTypes || undefined,
offsetRay: xrRay
}).then((xrHitTestSource)=>{
this._onHitTestSource(xrHitTestSource, false, options.inputSource, callback);
}).catch((ex)=>{
if (callback) callback(ex);
this.fire('error', ex);
});
}).catch((ex)=>{
if (callback) callback(ex);
this.fire('error', ex);
});
} else {
this.manager.session.requestHitTestSourceForTransientInput({
profile: options.profile,
entityTypes: options.entityTypes || undefined,
offsetRay: xrRay
}).then((xrHitTestSource)=>{
this._onHitTestSource(xrHitTestSource, true, options.inputSource, callback);
}).catch((ex)=>{
if (callback) callback(ex);
this.fire('error', ex);
});
}
}
_onHitTestSource(xrHitTestSource, transient, inputSource, callback) {
if (!this.manager.session) {
xrHitTestSource.cancel();
var err = new Error('XR Session is not started (3)');
if (callback) callback(err);
this.fire('error', err);
return;
}
var hitTestSource = new XrHitTestSource(this.manager, xrHitTestSource, transient, inputSource != null ? inputSource : null);
this.sources.push(hitTestSource);
if (callback) callback(null, hitTestSource);
this.fire('add', hitTestSource);
}
update(frame) {
if (!this._available) {
return;
}
for(var i = 0; i < this.sources.length; i++){
this.sources[i].update(frame);
}
}
get supported() {
return this._supported;
}
get available() {
return this._available;
}
constructor(manager){
super(), this._supported = platform.browser && !!(window.XRSession && window.XRSession.prototype.requestHitTestSource), this._available = false, this._checkingAvailability = false, this.sources = [];
this.manager = manager;
if (this._supported) {
this.manager.on('start', this._onSessionStart, this);
this.manager.on('end', this._onSessionEnd, this);
}
}
}
XrHitTest.EVENT_AVAILABLE = 'available';
XrHitTest.EVENT_UNAVAILABLE = 'unavailable';
XrHitTest.EVENT_ADD = 'add';
XrHitTest.EVENT_REMOVE = 'remove';
XrHitTest.EVENT_RESULT = 'result';
XrHitTest.EVENT_ERROR = 'error';
export { XrHitTest };