Skip to content

Commit aff58c8

Browse files
fix(device): Make call to vrDisplay.requestPresent syncrhonously
This should fix things in browsers (like Chrome) that require requestPresent to be called in the same execution context as a user event
1 parent 0f20041 commit aff58c8

File tree

1 file changed

+41
-49
lines changed

1 file changed

+41
-49
lines changed

src/device.ts

Lines changed: 41 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,16 @@ export class DeviceFrameState extends DeviceState {
8080
}];
8181
};
8282

83+
let vrDisplays:VRDisplay[]|undefined;
84+
let vrDisplay:VRDisplay|undefined;
85+
86+
if (typeof navigator !== 'undefined' && navigator.getVRDisplays) {
87+
navigator.getVRDisplays().then(displays => {
88+
vrDisplays = displays;
89+
vrDisplay = displays[0];
90+
});
91+
}
92+
8393
@autoinject()
8494
export class DeviceService {
8595

@@ -230,6 +240,8 @@ export class DeviceService {
230240
private _updateFrameState = () => {
231241
if (!this._updating) return;
232242

243+
this.requestAnimationFrame(this._updateFrameState);
244+
233245
const state = this.frameState = this.frameState || {};
234246
const time = state.time = JulianDate.now(state.time);
235247
state.screenOrientationDegrees = this.getScreenOrientationDegrees();
@@ -245,7 +257,9 @@ export class DeviceService {
245257

246258
this.frameStateEvent.raiseEvent(state);
247259

248-
this.requestAnimationFrame(this._updateFrameState);
260+
if (this.autoSubmitFrame && vrDisplay && vrDisplay.isPresenting) {
261+
vrDisplay.submitFrame();
262+
}
249263
};
250264

251265
public getScreenOrientationDegrees() {
@@ -256,18 +270,18 @@ export class DeviceService {
256270
* Request an animation frame callback for the current view.
257271
*/
258272
public requestAnimationFrame:(callback:(timestamp:number)=>void)=>number = callback => {
259-
if (currentVRDisplay) {
260-
return (currentVRDisplay as VRDisplay).requestAnimationFrame(callback);
273+
if (vrDisplay && this.isPresentingHMD) {
274+
return vrDisplay.requestAnimationFrame(callback);
261275
} else {
262276
return requestAnimationFrame(callback);
263277
}
264278
}
265279

266280
public cancelAnimationFrame:(id:number)=>void = id => {
267-
if (currentVRDisplay) {
268-
return (currentVRDisplay as VRDisplay).cancelAnimationFrame(id);
281+
if (vrDisplay && this.isPresentingHMD) {
282+
vrDisplay.cancelAnimationFrame(id);
269283
} else {
270-
return cancelAnimationFrame(id);
284+
cancelAnimationFrame(id);
271285
}
272286
}
273287

@@ -297,7 +311,7 @@ export class DeviceService {
297311
}
298312

299313
protected onUpdateFrameState() {
300-
if (currentVRDisplay) {
314+
if (vrDisplay && this.isPresentingHMD) {
301315
this._updateForWebVR();
302316
} else {
303317
this._updateDefault();
@@ -380,12 +394,12 @@ export class DeviceService {
380394
private _defaultRightBounds = [ 0.5, 0.0, 0.5, 1.0 ];
381395

382396
private _updateForWebVR() {
397+
398+
if (!vrDisplay) return;
383399

384400
const frameState = this.frameState;
385401
frameState.strict = true;
386402

387-
const vrDisplay:VRDisplay = currentVRDisplay;
388-
389403
// const element = this.viewService.element;
390404

391405
var leftEye = vrDisplay.getEyeParameters("left");
@@ -755,36 +769,30 @@ export class DeviceService {
755769
let currentCanvas:HTMLElement|undefined;
756770
let previousPresentationMode:ViewportMode;
757771

758-
this.contextService.postRenderEvent.addEventListener(()=>{
759-
if (this.autoSubmitFrame && currentVRDisplay && currentVRDisplay.isPresenting) {
760-
currentVRDisplay.submitFrame();
761-
}
762-
});
763-
764772
const handleVRDisplayPresentChange = (e) => {
765773
const viewService = this.viewService;
766-
const vrDisplay:VRDisplay|undefined = e.display || e.detail.vrdisplay || e.detail.display;
767-
if (vrDisplay) {
768-
const layers = vrDisplay.getLayers();
769-
let isThisView = currentVRDisplay === vrDisplay;
774+
const display:VRDisplay|undefined = e.display || e.detail.vrdisplay || e.detail.display;
775+
if (display) {
776+
const layers = display.getLayers();
777+
let isThisView = vrDisplay === display;
770778
for (const layer of layers) {
771779
if (layer.source && viewService.element.contains(layer.source)) {
772780
isThisView = true;
773781
break;
774782
}
775783
}
776784
if (isThisView) {
777-
if (vrDisplay.isPresenting) {
778-
currentVRDisplay = vrDisplay;
779-
if (vrDisplay.displayName.match(/Cardboard/g)) {
780-
currentCanvas = vrDisplay.getLayers()[0].source;
785+
if (display.isPresenting) {
786+
vrDisplay = display;
787+
if (display.displayName.match(/Cardboard/g)) {
788+
currentCanvas = display.getLayers()[0].source;
781789
if (currentCanvas) currentCanvas.classList.add('argon-interactive');
782790
previousPresentationMode = viewService.viewportMode;
783791
viewService.desiredViewportMode = ViewportMode.IMMERSIVE;
784792
}
785793
} else {
786-
currentVRDisplay = undefined;
787-
if (currentCanvas && vrDisplay.displayName.match(/Cardboard/g)) {
794+
vrDisplay = undefined;
795+
if (currentCanvas && display.displayName.match(/Cardboard/g)) {
788796
currentCanvas.classList.remove('argon-interactive');
789797
currentCanvas = undefined;
790798
viewService.desiredViewportMode = previousPresentationMode;
@@ -804,8 +812,6 @@ export class DeviceService {
804812

805813
}
806814

807-
let currentVRDisplay:any;
808-
809815
@autoinject()
810816
export class DeviceServiceProvider {
811817

@@ -877,33 +883,19 @@ export class DeviceServiceProvider {
877883
}
878884

879885
protected handleRequestPresentHMD(session:SessionPort) : Promise<void> {
880-
if (typeof navigator !== 'undefined' &&
881-
navigator.getVRDisplays) {
882-
const requestPresent = (vrDisplay:VRDisplay) => {
883-
currentVRDisplay = vrDisplay;
884-
const element = this.viewService.element;
885-
const layers:VRLayer&{}[] = [];
886-
layers[0] = {source:element.querySelector('canvas') || <HTMLCanvasElement>element.lastElementChild};
887-
return vrDisplay.requestPresent(layers).catch((e)=>{
888-
currentVRDisplay = undefined;
889-
throw e;
890-
});
891-
}
892-
if (navigator.activeVRDisplays && navigator.activeVRDisplays.length) {
893-
return requestPresent(navigator.activeVRDisplays[0]);
894-
} else {
895-
return navigator.getVRDisplays()
896-
.then(displays => displays[0])
897-
.then(requestPresent)
898-
}
886+
if (vrDisplay) {
887+
const element = this.viewService.element;
888+
const layers:VRLayer&{}[] = [];
889+
layers[0] = {source:element.querySelector('canvas') || <HTMLCanvasElement>element.lastElementChild};
890+
return vrDisplay.requestPresent(layers).catch((e)=>{
891+
throw e;
892+
});
899893
}
900894
throw new Error('No HMD available');
901895
}
902896

903897
protected handleExitPresentHMD(session:SessionPort) : Promise<void> {
904-
if (currentVRDisplay) {
905-
const vrDisplay:VRDisplay = currentVRDisplay;
906-
currentVRDisplay = undefined;
898+
if (vrDisplay) {
907899
return vrDisplay.exitPresent();
908900
}
909901
return Promise.resolve();

0 commit comments

Comments
 (0)