Skip to content

Commit

Permalink
offersession support
Browse files Browse the repository at this point in the history
Summary:
- Add support for navigator.xr.offerSession
- Optimize how devui and sem plugs into IWER
- bump version to v2.0.0 because of breaking change to API

Reviewed By: cabanier

Differential Revision:
D68745942

Privacy Context Container: L1233623

fbshipit-source-id: cefdb6738b58b4217200db7e8d6e00f1525e4e27
  • Loading branch information
felixtrz authored and facebook-github-bot committed Jan 28, 2025
1 parent 44dde27 commit 51ce3dc
Show file tree
Hide file tree
Showing 7 changed files with 208 additions and 72 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ node_modules/
docs/.vitepress/dist/
docs/.vitepress/cache/

src/version.ts
**/src/version.ts
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "iwer",
"version": "1.1.1",
"version": "2.0.0",
"description": "Javascript WebXR Runtime for Emulation",
"type": "module",
"main": "lib/index.js",
Expand Down
6 changes: 6 additions & 0 deletions src/device/XRController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface XRControllerConfig {

export class XRController extends XRTrackedInput {
[P_CONTROLLER]: {
profileId: string;
gamepadConfig: GamepadConfig;
};

Expand Down Expand Up @@ -64,6 +65,7 @@ export class XRController extends XRTrackedInput {

super(inputSource);
this[P_CONTROLLER] = {
profileId: controllerConfig.profileId,
gamepadConfig: controllerConfig.layout[handedness]!.gamepad,
};
}
Expand All @@ -72,6 +74,10 @@ export class XRController extends XRTrackedInput {
return this[P_CONTROLLER].gamepadConfig;
}

get profileId() {
return this[P_CONTROLLER].profileId;
}

updateButtonValue(id: string, value: number) {
if (value > 1 || value < 0) {
console.warn(`Out-of-range value ${value} provided for button ${id}.`);
Expand Down
85 changes: 75 additions & 10 deletions src/device/XRDevice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,22 @@ const DEFAULTS = {
stereoEnabled: false,
};

export interface DevUIConstructor {
new (xrDevice: XRDevice): DevUI;
}
export interface DevUI {
version: string;
render(time: number): void;
get devUICanvas(): HTMLCanvasElement;
get devUIContainer(): HTMLDivElement;
}

export interface SEMConstructor {
new (xrDevice: XRDevice): SyntheticEnvironmentModule;
}
export interface SyntheticEnvironmentModule {
render(xrDevice: XRDevice): void;
version: string;
render(time: number): void;
loadEnvironment(json: any): void;
planesVisible: boolean;
boundingBoxesVisible: boolean;
Expand All @@ -115,11 +129,18 @@ export interface SyntheticEnvironmentModule {
computeHitTestResults(rayMatrix: mat4): mat4[];
}

const Z_INDEX_SEM_CANVAS = 1;
const Z_INDEX_APP_CANVAS = 2;
const Z_INDEX_DEVUI_CANVAS = 3;
const Z_INDEX_DEVUI_CONTAINER = 4;

/**
* XRDevice is not a standard API class outlined in the WebXR Device API Specifications
* Instead, it serves as an user-facing interface to control the emulated XR Device
*/
export class XRDevice {
public readonly version = VERSION;

[P_DEVICE]: {
// device config
name: string;
Expand Down Expand Up @@ -158,6 +179,7 @@ export class XRDevice {
parent: HTMLElement | null;
width: number;
height: number;
zIndex: string;
};
canvasContainer: HTMLDivElement;

Expand All @@ -170,8 +192,9 @@ export class XRDevice {
// action playback
actionPlayer?: ActionPlayer;

// synthetic environment
syntheticEnvironmentModule?: SyntheticEnvironmentModule;
// add-on modules:
devui?: DevUI;
sem?: SyntheticEnvironmentModule;
};

constructor(
Expand Down Expand Up @@ -306,16 +329,27 @@ export class XRDevice {
// backup canvas data
const canvas = baseLayer.context.canvas as HTMLCanvasElement;
if (canvas.parentElement !== this[P_DEVICE].canvasContainer) {
const sem = this[P_DEVICE].syntheticEnvironmentModule;
const devui = this[P_DEVICE].devui;
if (devui) {
const { devUICanvas, devUIContainer } = devui;
devUICanvas.style.zIndex = Z_INDEX_DEVUI_CANVAS.toString();
devUIContainer.style.zIndex = Z_INDEX_DEVUI_CONTAINER.toString();
this[P_DEVICE].canvasContainer.appendChild(devui.devUICanvas);
this[P_DEVICE].canvasContainer.appendChild(devui.devUIContainer);
}
const sem = this[P_DEVICE].sem;
if (sem) {
sem.environmentCanvas.style.zIndex = Z_INDEX_SEM_CANVAS.toString();
this[P_DEVICE].canvasContainer.appendChild(sem.environmentCanvas);
}
this[P_DEVICE].canvasData = {
canvas,
parent: canvas.parentElement,
width: canvas.width,
height: canvas.height,
zIndex: canvas.style.zIndex,
};
canvas.style.zIndex = Z_INDEX_APP_CANVAS.toString();
this[P_DEVICE].canvasContainer.appendChild(canvas);
document.body.appendChild(this[P_DEVICE].canvasContainer);
}
Expand All @@ -325,15 +359,22 @@ export class XRDevice {
},
onSessionEnd: () => {
if (this[P_DEVICE].canvasData) {
const { canvas, parent, width, height } = this[P_DEVICE].canvasData;
const { canvas, parent, width, height, zIndex } =
this[P_DEVICE].canvasData;
canvas.width = width;
canvas.height = height;
canvas.style.zIndex = zIndex;
if (parent) {
parent.appendChild(canvas);
} else {
this[P_DEVICE].canvasContainer.removeChild(canvas);
}
const sem = this[P_DEVICE].syntheticEnvironmentModule;
const devui = this[P_DEVICE].devui;
if (devui) {
this[P_DEVICE].canvasContainer.removeChild(devui.devUICanvas);
this[P_DEVICE].canvasContainer.removeChild(devui.devUIContainer);
}
const sem = this[P_DEVICE].sem;
if (sem) {
this[P_DEVICE].canvasContainer.removeChild(sem.environmentCanvas);
}
Expand Down Expand Up @@ -436,8 +477,12 @@ export class XRDevice {
globalObject['XRReferenceSpaceEvent'] = XRReferenceSpaceEvent;
}

installSyntheticEnvironmentModule(sem: SyntheticEnvironmentModule) {
this[P_DEVICE].syntheticEnvironmentModule = sem;
installDevUI(devUIConstructor: DevUIConstructor) {
this[P_DEVICE].devui = new devUIConstructor(this);
}

installSEM(semConstructor: SEMConstructor) {
this[P_DEVICE].sem = new semConstructor(this);
}

get supportedSessionModes() {
Expand Down Expand Up @@ -563,6 +608,22 @@ export class XRDevice {
return this[P_DEVICE].xrSystem?.[P_SYSTEM].activeSession;
}

get sessionOffered(): boolean {
return Boolean(this[P_DEVICE].xrSystem?.[P_SYSTEM].offeredSessionConfig);
}

get name() {
return this[P_DEVICE].name;
}

grantOfferedSession(): void {
const pSystem = this[P_DEVICE].xrSystem?.[P_SYSTEM];
if (pSystem && pSystem.offeredSessionConfig) {
pSystem.grantSession(pSystem.offeredSessionConfig);
pSystem.offeredSessionConfig = undefined;
}
}

recenter() {
const deltaVec = new Vector3(-this.position.x, 0, -this.position.z);
const forward = new Vector3(0, 0, -1).applyQuaternion(this.quaternion);
Expand Down Expand Up @@ -625,7 +686,11 @@ export class XRDevice {
return this[P_DEVICE].actionPlayer;
}

get syntheticEnvironmentModule() {
return this[P_DEVICE].syntheticEnvironmentModule;
get devui() {
return this[P_DEVICE].devui;
}

get sem() {
return this[P_DEVICE].sem;
}
}
Loading

0 comments on commit 51ce3dc

Please sign in to comment.