diff --git a/devtool/EmulatorDevtools.tsx b/devtool/EmulatorDevtools.tsx
deleted file mode 100644
index b381c4c..0000000
--- a/devtool/EmulatorDevtools.tsx
+++ /dev/null
@@ -1,77 +0,0 @@
-import React from 'react'
-import { useHookstate, useImmediateEffect, useMutableState } from '@ir-engine/hyperflux'
-import Button from '@ir-engine/ui/src/primitives/tailwind/Button'
-import { endXRSession, requestXRSession } from '@ir-engine/spatial/src/xr/XRSessionFunctions'
-
-import { EmulatorSettings, emulatorStates } from './js/emulatorStates.js'
-import EmulatedDevice from './js/emulatedDevice.js'
-import { syncDevicePose } from './js/messenger.js'
-import Devtool from './jsx/app'
-import devtoolCSS from './styles/index.css?inline'
-import { overrideXR } from '../src/functions/xrBotHookFunctions.js'
-
-import 'bootstrap/dist/css/bootstrap.min.css'
-import 'bootstrap'
-import { XRState } from '@ir-engine/spatial/src/xr/XRState.js'
-
-const setup = async (mode: 'immersive-vr' | 'immersive-ar') => {
- await overrideXR({ mode })
- await EmulatorSettings.instance.load()
- const device = new EmulatedDevice()
- device.on('pose', syncDevicePose)
- ;(emulatorStates as any).emulatedDevice = device
-
- return device
-}
-
-export const EmulatorDevtools = (props: { mode: 'immersive-vr' | 'immersive-ar' }) => {
- const xrState = useMutableState(XRState)
- const xrActive = xrState.sessionActive.value && !xrState.requestingSession.value
-
- const deviceState = useHookstate(null as null | EmulatedDevice)
- useImmediateEffect(() => {
- setup(props.mode).then((device) => {
- deviceState.set(device)
- })
- }, [])
-
- const toggleXR = async () => {
- if (xrActive) {
- endXRSession()
- } else {
- requestXRSession({ mode: props.mode })
- }
- }
-
- const togglePlacement = () => {
- if (xrState.scenePlacementMode.value !== 'placing') {
- xrState.scenePlacementMode.set('placing')
- xrState.sceneScaleAutoMode.set(false)
- xrState.sceneScaleTarget.set(0.1)
- } else {
- xrState.scenePlacementMode.set('placed')
- }
- }
-
- return (
- <>
-
-
- >
- )
-}
diff --git a/devtool/assets/headset.glb b/devtool/assets/headset.glb
deleted file mode 100644
index 485e243..0000000
Binary files a/devtool/assets/headset.glb and /dev/null differ
diff --git a/devtool/assets/images/auto-return.png b/devtool/assets/images/auto-return.png
deleted file mode 100644
index ac294f8..0000000
Binary files a/devtool/assets/images/auto-return.png and /dev/null differ
diff --git a/devtool/assets/images/button1-left.png b/devtool/assets/images/button1-left.png
deleted file mode 100644
index ac16bca..0000000
Binary files a/devtool/assets/images/button1-left.png and /dev/null differ
diff --git a/devtool/assets/images/button1-right.png b/devtool/assets/images/button1-right.png
deleted file mode 100644
index 4343c70..0000000
Binary files a/devtool/assets/images/button1-right.png and /dev/null differ
diff --git a/devtool/assets/images/button2-left.png b/devtool/assets/images/button2-left.png
deleted file mode 100644
index c2222d7..0000000
Binary files a/devtool/assets/images/button2-left.png and /dev/null differ
diff --git a/devtool/assets/images/button2-right.png b/devtool/assets/images/button2-right.png
deleted file mode 100644
index 88d7136..0000000
Binary files a/devtool/assets/images/button2-right.png and /dev/null differ
diff --git a/devtool/assets/images/delete.png b/devtool/assets/images/delete.png
deleted file mode 100644
index efe5c73..0000000
Binary files a/devtool/assets/images/delete.png and /dev/null differ
diff --git a/devtool/assets/images/exit.png b/devtool/assets/images/exit.png
deleted file mode 100644
index f7a1a72..0000000
Binary files a/devtool/assets/images/exit.png and /dev/null differ
diff --git a/devtool/assets/images/gamepad.png b/devtool/assets/images/gamepad.png
deleted file mode 100644
index 97cb605..0000000
Binary files a/devtool/assets/images/gamepad.png and /dev/null differ
diff --git a/devtool/assets/images/grip-left.png b/devtool/assets/images/grip-left.png
deleted file mode 100644
index 926f292..0000000
Binary files a/devtool/assets/images/grip-left.png and /dev/null differ
diff --git a/devtool/assets/images/grip-right.png b/devtool/assets/images/grip-right.png
deleted file mode 100644
index 7f3ad8f..0000000
Binary files a/devtool/assets/images/grip-right.png and /dev/null differ
diff --git a/devtool/assets/images/hand-pose.png b/devtool/assets/images/hand-pose.png
deleted file mode 100644
index 28d7f3b..0000000
Binary files a/devtool/assets/images/hand-pose.png and /dev/null differ
diff --git a/devtool/assets/images/hand-tracking.png b/devtool/assets/images/hand-tracking.png
deleted file mode 100644
index 10fadea..0000000
Binary files a/devtool/assets/images/hand-tracking.png and /dev/null differ
diff --git a/devtool/assets/images/headset-type.png b/devtool/assets/images/headset-type.png
deleted file mode 100644
index 83358d2..0000000
Binary files a/devtool/assets/images/headset-type.png and /dev/null differ
diff --git a/devtool/assets/images/headset.png b/devtool/assets/images/headset.png
deleted file mode 100644
index cc47029..0000000
Binary files a/devtool/assets/images/headset.png and /dev/null differ
diff --git a/devtool/assets/images/horizontal.png b/devtool/assets/images/horizontal.png
deleted file mode 100644
index 07e1db7..0000000
Binary files a/devtool/assets/images/horizontal.png and /dev/null differ
diff --git a/devtool/assets/images/info.png b/devtool/assets/images/info.png
deleted file mode 100644
index bf27215..0000000
Binary files a/devtool/assets/images/info.png and /dev/null differ
diff --git a/devtool/assets/images/joystick.png b/devtool/assets/images/joystick.png
deleted file mode 100644
index b248180..0000000
Binary files a/devtool/assets/images/joystick.png and /dev/null differ
diff --git a/devtool/assets/images/keyboard.png b/devtool/assets/images/keyboard.png
deleted file mode 100644
index ac58759..0000000
Binary files a/devtool/assets/images/keyboard.png and /dev/null differ
diff --git a/devtool/assets/images/left-controller.png b/devtool/assets/images/left-controller.png
deleted file mode 100644
index eac798c..0000000
Binary files a/devtool/assets/images/left-controller.png and /dev/null differ
diff --git a/devtool/assets/images/left-hand.png b/devtool/assets/images/left-hand.png
deleted file mode 100644
index cee6edd..0000000
Binary files a/devtool/assets/images/left-hand.png and /dev/null differ
diff --git a/devtool/assets/images/lock.png b/devtool/assets/images/lock.png
deleted file mode 100644
index 5f79253..0000000
Binary files a/devtool/assets/images/lock.png and /dev/null differ
diff --git a/devtool/assets/images/move.png b/devtool/assets/images/move.png
deleted file mode 100644
index d12b091..0000000
Binary files a/devtool/assets/images/move.png and /dev/null differ
diff --git a/devtool/assets/images/play.png b/devtool/assets/images/play.png
deleted file mode 100644
index e512702..0000000
Binary files a/devtool/assets/images/play.png and /dev/null differ
diff --git a/devtool/assets/images/polyfill-on.png b/devtool/assets/images/polyfill-on.png
deleted file mode 100644
index c4fe0b0..0000000
Binary files a/devtool/assets/images/polyfill-on.png and /dev/null differ
diff --git a/devtool/assets/images/pose.png b/devtool/assets/images/pose.png
deleted file mode 100644
index 6551a82..0000000
Binary files a/devtool/assets/images/pose.png and /dev/null differ
diff --git a/devtool/assets/images/press.png b/devtool/assets/images/press.png
deleted file mode 100644
index 443404b..0000000
Binary files a/devtool/assets/images/press.png and /dev/null differ
diff --git a/devtool/assets/images/reset.png b/devtool/assets/images/reset.png
deleted file mode 100644
index 476b652..0000000
Binary files a/devtool/assets/images/reset.png and /dev/null differ
diff --git a/devtool/assets/images/revert.png b/devtool/assets/images/revert.png
deleted file mode 100644
index 0974e7d..0000000
Binary files a/devtool/assets/images/revert.png and /dev/null differ
diff --git a/devtool/assets/images/right-controller.png b/devtool/assets/images/right-controller.png
deleted file mode 100644
index 27888ab..0000000
Binary files a/devtool/assets/images/right-controller.png and /dev/null differ
diff --git a/devtool/assets/images/right-hand.png b/devtool/assets/images/right-hand.png
deleted file mode 100644
index 0047730..0000000
Binary files a/devtool/assets/images/right-hand.png and /dev/null differ
diff --git a/devtool/assets/images/roomscale.png b/devtool/assets/images/roomscale.png
deleted file mode 100644
index 24fbf51..0000000
Binary files a/devtool/assets/images/roomscale.png and /dev/null differ
diff --git a/devtool/assets/images/rotation.png b/devtool/assets/images/rotation.png
deleted file mode 100644
index 4aea38e..0000000
Binary files a/devtool/assets/images/rotation.png and /dev/null differ
diff --git a/devtool/assets/images/save-copy.png b/devtool/assets/images/save-copy.png
deleted file mode 100644
index 5509eab..0000000
Binary files a/devtool/assets/images/save-copy.png and /dev/null differ
diff --git a/devtool/assets/images/save.png b/devtool/assets/images/save.png
deleted file mode 100644
index 3629043..0000000
Binary files a/devtool/assets/images/save.png and /dev/null differ
diff --git a/devtool/assets/images/send.png b/devtool/assets/images/send.png
deleted file mode 100644
index 7908702..0000000
Binary files a/devtool/assets/images/send.png and /dev/null differ
diff --git a/devtool/assets/images/settings.png b/devtool/assets/images/settings.png
deleted file mode 100644
index 1e83b62..0000000
Binary files a/devtool/assets/images/settings.png and /dev/null differ
diff --git a/devtool/assets/images/stereo.png b/devtool/assets/images/stereo.png
deleted file mode 100644
index 0bd7d89..0000000
Binary files a/devtool/assets/images/stereo.png and /dev/null differ
diff --git a/devtool/assets/images/sticky.png b/devtool/assets/images/sticky.png
deleted file mode 100644
index ae1a79c..0000000
Binary files a/devtool/assets/images/sticky.png and /dev/null differ
diff --git a/devtool/assets/images/trash.png b/devtool/assets/images/trash.png
deleted file mode 100644
index 5ce87e0..0000000
Binary files a/devtool/assets/images/trash.png and /dev/null differ
diff --git a/devtool/assets/images/trigger-left.png b/devtool/assets/images/trigger-left.png
deleted file mode 100644
index 02929f9..0000000
Binary files a/devtool/assets/images/trigger-left.png and /dev/null differ
diff --git a/devtool/assets/images/trigger-right.png b/devtool/assets/images/trigger-right.png
deleted file mode 100644
index 52b9113..0000000
Binary files a/devtool/assets/images/trigger-right.png and /dev/null differ
diff --git a/devtool/assets/images/undo.png b/devtool/assets/images/undo.png
deleted file mode 100644
index ce84255..0000000
Binary files a/devtool/assets/images/undo.png and /dev/null differ
diff --git a/devtool/assets/images/vertical.png b/devtool/assets/images/vertical.png
deleted file mode 100644
index d6ef3fb..0000000
Binary files a/devtool/assets/images/vertical.png and /dev/null differ
diff --git a/devtool/assets/left-controller.glb b/devtool/assets/left-controller.glb
deleted file mode 100644
index 56d914d..0000000
Binary files a/devtool/assets/left-controller.glb and /dev/null differ
diff --git a/devtool/assets/left-hand.glb b/devtool/assets/left-hand.glb
deleted file mode 100644
index 9feae89..0000000
Binary files a/devtool/assets/left-hand.glb and /dev/null differ
diff --git a/devtool/assets/right-controller.glb b/devtool/assets/right-controller.glb
deleted file mode 100644
index bb3d9df..0000000
Binary files a/devtool/assets/right-controller.glb and /dev/null differ
diff --git a/devtool/assets/right-hand.glb b/devtool/assets/right-hand.glb
deleted file mode 100644
index 2c29a7d..0000000
Binary files a/devtool/assets/right-hand.glb and /dev/null differ
diff --git a/devtool/js/actions.js b/devtool/js/actions.js
deleted file mode 100644
index b7a9911..0000000
--- a/devtool/js/actions.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-/**
- * Events triggered by the emulator UI and sent to the content script
- */
-export const EMULATOR_ACTIONS = {
- HEADSET_POSE_CHANGE: 'ea-headset-pose-change',
- CONTROLLER_POSE_CHANGE: 'ea-controller-pose-change',
- CONTROLLER_VISIBILITY_CHANGE: 'ea-controller-visibility-change',
- BUTTON_STATE_CHANGE: 'ea-button-state-change',
- ANALOG_VALUE_CHANGE: 'ea-analog-value-change',
- DEVICE_TYPE_CHANGE: 'ea-device-type-change',
- STEREO_TOGGLE: 'ea-stereo-toggle',
- KEYBOARD_EVENT: 'ea-keyboard-event',
- EXIT_IMMERSIVE: 'ea-exit-immersive',
- ROOM_DIMENSION_CHANGE: 'ea-room-dimension-change',
- EXCLUDE_POLYFILL: 'ea-exclude-polyfill',
- INPUT_MODE_CHANGE: 'ea-input-mode-change',
- HAND_POSE_CHANGE: 'ea-hand-pose-change',
- HAND_VISIBILITY_CHANGE: 'ea-hand-visibility-change',
- PINCH_VALUE_CHANGE: 'ea-pinch-value-change',
- USER_OBJECTS_CHANGE: 'ea-user-objects-change',
-};
-
-/**
- * Events triggered by the content script and caught and processed by the custom WebXR Polyfill
- */
-export const POLYFILL_ACTIONS = EMULATOR_ACTIONS
-// {
-// HEADSET_POSE_CHANGE: 'pa-headset-pose-change',
-// CONTROLLER_POSE_CHANGE: 'pa-controller-pose-change',
-// CONTROLLER_VISIBILITY_CHANGE: 'pa-controller-visibility-change',
-// BUTTON_STATE_CHANGE: 'pa-button-state-change',
-// ANALOG_VALUE_CHANGE: 'pa-analog-value-change',
-// DEVICE_TYPE_CHANGE: 'pa-device-type-change',
-// STEREO_TOGGLE: 'pa-stereo-toggle',
-// KEYBOARD_EVENT: 'pa-keyboard-event',
-// EXIT_IMMERSIVE: 'pa-exit-immersive',
-// DEVICE_INIT: 'pa-device-init',
-// ROOM_DIMENSION_CHANGE: 'pa-room-dimension-change',
-// INPUT_MODE_CHANGE: 'pa-input-mode-change',
-// HAND_POSE_CHANGE: 'pa-hand-pose-change',
-// HAND_VISIBILITY_CHANGE: 'pa-hand-visibility-change',
-// PINCH_VALUE_CHANGE: 'pa-pinch-value-change',
-// USER_OBJECTS_CHANGE: 'pa-user-objects-change',
-// };
-
-/**
- * Events triggered from the client side that are caught by the content script and then relayed back to the emulator side
- */
-export const CLIENT_ACTIONS = {
- ENTER_IMMERSIVE: 'ca-enter-immersive',
- EXIT_IMMERSIVE: 'ca-exit-immersive',
- PING: 'ca-ping',
-};
diff --git a/devtool/js/constants.js b/devtool/js/constants.js
deleted file mode 100644
index 3eeee5c..0000000
--- a/devtool/js/constants.js
+++ /dev/null
@@ -1,141 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-export const PRESS_AND_RELEASE_DURATION = 250;
-
-export const BUTTON_POLYFILL_INDEX_MAPPING = {
- joystick: 0,
- trigger: 1,
- grip: 2,
- button1: 3,
- button2: 4,
-};
-
-export const DEVICE = {
- HEADSET: '0',
- INPUT_RIGHT: '2',
- INPUT_LEFT: '3',
-};
-
-export const OBJECT_NAME = {};
-OBJECT_NAME[DEVICE.HEADSET] = 'headset';
-OBJECT_NAME[DEVICE.INPUT_LEFT] = 'left-controller';
-OBJECT_NAME[DEVICE.INPUT_RIGHT] = 'right-controller';
-
-export const DEFAULT_TRANSFORMS = {};
-DEFAULT_TRANSFORMS[DEVICE.HEADSET] = {
- position: [0, 1.7, 0],
- rotation: [0, 0, 0, 'XYZ'],
-};
-DEFAULT_TRANSFORMS[DEVICE.INPUT_RIGHT] = {
- position: [0.25, 1.5, -0.4],
- rotation: [0, 0, 0, 'XYZ'],
-};
-DEFAULT_TRANSFORMS[DEVICE.INPUT_LEFT] = {
- position: [-0.25, 1.5, -0.4],
- rotation: [0, 0, 0, 'XYZ'],
-};
-
-export const CONTROLLER_STRINGS = {};
-CONTROLLER_STRINGS[DEVICE.INPUT_LEFT] = {
- name: 'left-controller',
- displayName: 'Left Controller',
- handedness: 'left',
- button1: 'ButtonX',
- button2: 'ButtonY',
-};
-CONTROLLER_STRINGS[DEVICE.INPUT_RIGHT] = {
- name: 'right-controller',
- displayName: 'Right Controller',
- handedness: 'right',
- button1: 'ButtonA',
- button2: 'ButtonB',
-};
-
-export const HAND_STRINGS = {};
-HAND_STRINGS[DEVICE.INPUT_LEFT] = {
- name: 'left-hand',
- displayName: 'Left Hand',
- handedness: 'left',
-};
-HAND_STRINGS[DEVICE.INPUT_RIGHT] = {
- name: 'right-hand',
- displayName: 'Right Hand',
- handedness: 'right',
-};
-
-export const KEYBOARD_CONTROL_MAPPING = {
- left: {
- joystickLeft: 'a',
- joystickRight: 'd',
- joystickForward: 'w',
- joystickBackward: 's',
- trigger: 'e',
- grip: 'q',
- button1: 'x',
- button2: 'z',
- joystick: 'c',
- },
- right: {
- joystickLeft: 'ArrowLeft',
- joystickRight: 'ArrowRight',
- joystickForward: 'ArrowUp',
- joystickBackward: 'ArrowDown',
- trigger: 'Enter',
- grip: 'Shift',
- button1: "'",
- button2: '/',
- joystick: '.',
- },
-};
-
-export const GAMEPAD_ID_TO_INPUT_ID_MAPPING = {
- 3: 'joystick',
- 5: 'button2',
- 4: 'button1',
- 0: 'trigger',
- 1: 'grip',
-};
-
-export const SEMANTIC_LABELS = {
- Desk: 'desk',
- Couch: 'couch',
- Floor: 'floor',
- Ceiling: 'ceiling',
- Wall: 'wall',
- Door: 'door',
- Window: 'window',
- Table: 'table',
- Shelf: 'shelf',
- Bed: 'bed',
- Screen: 'screen',
- Lamp: 'lamp',
- Plant: 'plant',
- WallArt: 'wall art',
- Other: 'other',
-};
-
-export const TRIGGER_MODES = ['slow', 'normal', 'fast', 'turbo'];
-
-export const TRIGGER_CONFIG = {
- slow: {
- interval: 20,
- holdTime: 100,
- },
- normal: {
- interval: 10,
- holdTime: 50,
- },
- fast: {
- interval: 5,
- holdTime: 10,
- },
- turbo: {
- interval: 1,
- holdTime: 1,
- },
-};
diff --git a/devtool/js/devices.js b/devtool/js/devices.js
deleted file mode 100644
index 468698a..0000000
--- a/devtool/js/devices.js
+++ /dev/null
@@ -1,235 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-export const DEVICE_DEFINITIONS = {
- 'Oculus Rift CV1': {
- id: 'Oculus Rift CV1',
- name: 'Oculus Rift CV1',
- shortName: 'Rift CV1',
- profile: 'oculus-touch',
- modes: ['inline', 'immersive-vr'],
- headset: {
- hasPosition: true,
- hasRotation: true,
- },
- controllers: [
- {
- id: 'Oculus Touch (Left)',
- buttonNum: 7,
- /**
- * this is not the index in gamepad.buttons, but the index used for input remapping in WebXR Polyfill
- * @see https://github.com/immersive-web/webxr-polyfill/blob/main/src/devices/GamepadMappings.js
- */
- primaryButtonIndex: 1,
- primarySqueezeButtonIndex: 2,
- hasPosition: true,
- hasRotation: true,
- hasSqueezeButton: true,
- handedness: 'left',
- },
- {
- id: 'Oculus Touch (Right)',
- buttonNum: 7,
- primaryButtonIndex: 1,
- primarySqueezeButtonIndex: 2,
- hasPosition: true,
- hasRotation: true,
- hasSqueezeButton: true,
- handedness: 'right',
- },
- ],
- polyfillInputMapping: {
- axes: [2, 3, 0, 1],
- buttons: [1, 2, null, 0, 3, 4, null],
- },
- },
- 'Oculus Rift S': {
- id: 'Oculus Rift S',
- name: 'Oculus Rift S',
- shortName: 'Rift S',
- profile: 'oculus-touch-v2',
- modes: ['inline', 'immersive-vr'],
- headset: {
- hasPosition: true,
- hasRotation: true,
- },
- controllers: [
- {
- id: 'Oculus Touch V2 (Left)',
- buttonNum: 7,
- primaryButtonIndex: 1,
- primarySqueezeButtonIndex: 2,
- hasPosition: true,
- hasRotation: true,
- hasSqueezeButton: true,
- handedness: 'left',
- },
- {
- id: 'Oculus Touch V2 (Right)',
- buttonNum: 7,
- primaryButtonIndex: 1,
- primarySqueezeButtonIndex: 2,
- hasPosition: true,
- hasRotation: true,
- hasSqueezeButton: true,
- handedness: 'right',
- },
- ],
- polyfillInputMapping: {
- axes: [2, 3, 0, 1],
- buttons: [1, 2, null, 0, 3, 4, null],
- },
- },
- 'Oculus Quest': {
- id: 'Oculus Quest',
- name: 'Oculus Quest',
- shortName: 'Quest 1',
- profile: 'oculus-touch-v2',
- modes: ['inline', 'immersive-vr'],
- headset: {
- hasPosition: true,
- hasRotation: true,
- },
- controllers: [
- {
- id: 'Oculus Touch V2 (Left)',
- buttonNum: 7,
- primaryButtonIndex: 1,
- primarySqueezeButtonIndex: 2,
- hasPosition: true,
- hasRotation: true,
- hasSqueezeButton: true,
- handedness: 'left',
- },
- {
- id: 'Oculus Touch V2 (Right)',
- buttonNum: 7,
- primaryButtonIndex: 1,
- primarySqueezeButtonIndex: 2,
- hasPosition: true,
- hasRotation: true,
- hasSqueezeButton: true,
- handedness: 'right',
- },
- ],
- polyfillInputMapping: {
- axes: [2, 3, 0, 1],
- buttons: [1, 2, null, 0, 3, 4, null],
- },
- },
- 'Oculus Quest 2': {
- id: 'Oculus Quest 2',
- name: 'Oculus Quest 2',
- shortName: 'Quest 2',
- profile: 'oculus-touch-v3',
- modes: ['inline', 'immersive-vr', 'immersive-ar'],
- headset: {
- hasPosition: true,
- hasRotation: true,
- },
- controllers: [
- {
- id: 'Oculus Touch V3 (Left)',
- buttonNum: 7,
- primaryButtonIndex: 1,
- primarySqueezeButtonIndex: 2,
- hasPosition: true,
- hasRotation: true,
- hasSqueezeButton: true,
- handedness: 'left',
- },
- {
- id: 'Oculus Touch V3 (Right)',
- buttonNum: 7,
- primaryButtonIndex: 1,
- primarySqueezeButtonIndex: 2,
- hasPosition: true,
- hasRotation: true,
- hasSqueezeButton: true,
- handedness: 'right',
- },
- ],
- polyfillInputMapping: {
- axes: [2, 3, 0, 1],
- buttons: [1, 2, null, 0, 3, 4, null],
- },
- },
- 'Meta Quest Pro': {
- id: 'Meta Quest Pro',
- name: 'Meta Quest Pro',
- shortName: 'Quest Pro',
- profile: 'meta-quest-touch-pro',
- modes: ['inline', 'immersive-vr', 'immersive-ar'],
- headset: {
- hasPosition: true,
- hasRotation: true,
- },
- controllers: [
- {
- id: 'Meta Quest Touch Pro (Left)',
- buttonNum: 7,
- primaryButtonIndex: 1,
- primarySqueezeButtonIndex: 2,
- hasPosition: true,
- hasRotation: true,
- hasSqueezeButton: true,
- handedness: 'left',
- },
- {
- id: 'Meta Quest Touch Pro (Right)',
- buttonNum: 7,
- primaryButtonIndex: 1,
- primarySqueezeButtonIndex: 2,
- hasPosition: true,
- hasRotation: true,
- hasSqueezeButton: true,
- handedness: 'right',
- },
- ],
- polyfillInputMapping: {
- axes: [2, 3, 0, 1],
- buttons: [1, 2, null, 0, 3, 4, null],
- },
- },
- 'Meta Quest 3': {
- id: 'Meta Quest 3',
- name: 'Meta Quest 3',
- shortName: 'Quest 3',
- profile: 'meta-quest-touch-plus',
- modes: ['inline', 'immersive-vr', 'immersive-ar'],
- headset: {
- hasPosition: true,
- hasRotation: true,
- },
- controllers: [
- {
- id: 'Meta Quest Touch Plus (Left)',
- buttonNum: 7,
- primaryButtonIndex: 1,
- primarySqueezeButtonIndex: 2,
- hasPosition: true,
- hasRotation: true,
- hasSqueezeButton: true,
- handedness: 'left',
- },
- {
- id: 'Meta Quest Touch Plus (Right)',
- buttonNum: 7,
- primaryButtonIndex: 1,
- primarySqueezeButtonIndex: 2,
- hasPosition: true,
- hasRotation: true,
- hasSqueezeButton: true,
- handedness: 'right',
- },
- ],
- polyfillInputMapping: {
- axes: [2, 3, 0, 1],
- buttons: [1, 2, null, 0, 3, 4, null],
- },
- },
-};
diff --git a/devtool/js/emulatedDevice.js b/devtool/js/emulatedDevice.js
deleted file mode 100644
index 8f7cde2..0000000
--- a/devtool/js/emulatedDevice.js
+++ /dev/null
@@ -1,537 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-import * as THREE from 'three';
-
-import {
- CONTROLLER_STRINGS,
- DEVICE,
- HAND_STRINGS,
- OBJECT_NAME,
-} from './constants';
-import { EmulatorSettings, emulatorStates } from './emulatorStates';
-
-import { BoxLineGeometry } from 'three/examples/jsm/geometries/BoxLineGeometry.js';
-import { EventEmitter } from 'events';
-import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
-import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
-import { TransformControls } from 'three/examples/jsm/controls/TransformControls.js';
-import { generateUUID } from 'three/src/math/MathUtils.js';
-import { updateUserObjects } from './messenger';
-
-import config from '@ir-engine/common/src/config';
-const assetURL = config.client.fileServer + '/projects/ir-engine/ir-bot/devtool'
-
-const SELECTION_MOUSE_DOWN_THRESHOLD = 300;
-
-const isNumber = function isNumber(value) {
- return typeof value === 'number' && isFinite(value);
-};
-
-export default class EmulatedDevice extends EventEmitter {
- constructor() {
- super();
- this._renderer = new THREE.WebGLRenderer({ antialias: true });
- this._renderer.setPixelRatio(window.devicePixelRatio);
- this._renderer.setSize(1, 1);
- this._renderer.domElement.style.position = 'absolute';
-
- this._scene = new THREE.Scene();
- this._scene.background = new THREE.Color(0x505050);
- this._scene.add(new THREE.DirectionalLight(0xffffff, 1));
- this._scene.add(new THREE.AmbientLight(0x404040, 2));
-
- this._camera = new THREE.PerspectiveCamera(45, 1 / 1, 0.1, 100);
- this._camera.position.set(-1.5, 1.7, 2);
- this._camera.lookAt(new THREE.Vector3(0, 1.6, 0));
-
- this._controllerMeshes = {};
- this._controllerMeshesHidden = {};
- this._handMeshes = {};
- this._handMeshesHidden = {};
-
- this._labelContainer = document.createElement('div');
-
- const oc = new OrbitControls(this._camera, this.canvas);
- oc.addEventListener('change', this.render.bind(this));
- oc.target.set(0, 1.6, 0);
- oc.update();
- this._orbitControls = oc;
-
- const loader = new GLTFLoader();
- this._transformControls = {};
- Object.values(DEVICE).forEach((deviceKey) => {
- const node = new THREE.Group();
- node.position.fromArray(
- EmulatorSettings.instance.defaultPose[deviceKey].position,
- );
- node.rotation.fromArray(
- EmulatorSettings.instance.defaultPose[deviceKey].rotation,
- );
- emulatorStates.assetNodes[deviceKey] = node;
- this._scene.add(node);
-
- // add device node mesh to parent
- loader.load(`${assetURL}/assets/${OBJECT_NAME[deviceKey]}.glb`, (gltf) => {
- const mesh = gltf.scene;
- mesh.scale.setScalar(2);
- mesh.rotateY(Math.PI);
- mesh.traverse((child) => {
- child.userData['deviceKey'] = deviceKey;
- });
- node.add(mesh);
- if (CONTROLLER_STRINGS[deviceKey]) {
- this._controllerMeshes[deviceKey] = mesh;
- mesh.visible = EmulatorSettings.instance.inputMode === 'controllers';
- this._controllerMeshesHidden[deviceKey] = false;
- }
- this.render();
- });
-
- if (HAND_STRINGS[deviceKey]) {
- loader.load(`${assetURL}/assets/${HAND_STRINGS[deviceKey].name}.glb`, (gltf) => {
- const mesh = gltf.scene;
- mesh.scale.setScalar(2);
- mesh.rotateY(Math.PI);
- mesh.traverse((child) => {
- child.userData['deviceKey'] = deviceKey;
- });
- node.add(mesh);
- this._handMeshes[deviceKey] = mesh;
- mesh.visible = EmulatorSettings.instance.inputMode === 'hands';
- this._handMeshesHidden[deviceKey] = false;
- this.render();
- });
- }
-
- // setup transform control
- const controls = new TransformControls(this._camera, this.canvas);
- controls.attach(node);
- controls.enabled = false;
- controls.visible = false;
- controls.addEventListener('mouseDown', () => (oc.enabled = false));
- controls.addEventListener('mouseUp', () => (oc.enabled = true));
- controls.addEventListener('change', () => {
- this._emitPoseEvent(deviceKey);
- this.render();
- });
- this._transformControls[deviceKey] = controls;
- this._scene.add(controls);
- });
-
- this._userObjects = {};
- this._recoverObjects();
-
- // check device node selection by raycast
- this._raycaster = new THREE.Raycaster();
- this._mouseVec2 = new THREE.Vector2();
- this._mouseDownTime = null;
- this._selectedDeviceKey = null;
- this.canvas.addEventListener('mousedown', (event) => {
- this._selectedDeviceKey = this._findSelectedDeviceNode(event);
- this._mouseDownTime = performance.now();
- });
- this.canvas.addEventListener('mouseup', () => {
- if (this._selectedDeviceKey != null) {
- const currentTime = performance.now();
- if (
- currentTime - this._mouseDownTime <
- SELECTION_MOUSE_DOWN_THRESHOLD
- ) {
- this.toggleControlMode(this._selectedDeviceKey);
- oc.enabled = true;
- }
- }
- });
-
- this.updateRoom();
- }
-
- _emitPoseEvent(deviceKey) {
- const node = this.getDeviceNode(deviceKey);
- this.emit('pose', {
- deviceKey,
- position: node.position.toArray(),
- rotation: node.rotation.toArray(),
- quaternion: node.quaternion.toArray(),
- });
- }
-
- _findSelectedDeviceNode(mouseEvent) {
- const rect = this.canvas.getBoundingClientRect();
- const point = {
- x: (mouseEvent.clientX - rect.left) / rect.width,
- y: (mouseEvent.clientY - rect.top) / rect.height,
- };
- this._mouseVec2.set(point.x * 2 - 1, -(point.y * 2) + 1);
- this._raycaster.setFromCamera(this._mouseVec2, this._camera);
- const intersect = this._raycaster.intersectObjects(
- [
- ...Object.values(emulatorStates.assetNodes),
- ...Object.values(this._userObjects),
- ],
- true,
- )[0];
-
- return (
- intersect?.object.userData['deviceKey'] ??
- intersect?.object.userData['userObjectId']
- );
- }
-
- updateRoom() {
- const dimension = EmulatorSettings.instance.roomDimension;
- if (this._roomObject) {
- this._scene.remove(this._roomObject);
- }
- this._roomObject = new THREE.LineSegments(
- new BoxLineGeometry(
- dimension.x,
- dimension.y,
- dimension.z,
- Math.ceil(dimension.x * 2),
- Math.ceil(dimension.y * 2),
- Math.ceil(dimension.z * 2),
- ),
- new THREE.LineBasicMaterial({ color: 0x808080 }),
- );
- this._roomObject.geometry.translate(0, dimension.y / 2, 0);
- this._scene.add(this._roomObject);
- this.render();
- }
-
- addObject(object, semanticLabel, idOverride = null) {
- this._scene.add(object);
- const controls = new TransformControls(this._camera, this.canvas);
- controls.attach(object);
- controls.enabled = false;
- controls.visible = false;
- controls.addEventListener(
- 'mouseDown',
- () => (this._orbitControls.enabled = false),
- );
- controls.addEventListener('mouseUp', () => {
- this._orbitControls.enabled = true;
- this._updateObjects();
- });
- controls.addEventListener('change', () => {
- this.render();
- });
- this._scene.add(controls);
- const userObjectId = idOverride ?? generateUUID();
- this._transformControls[userObjectId] = controls;
- this._userObjects[userObjectId] = object;
- const label = document.createElement('div');
- label.classList.add('semantic-label');
- label.innerHTML = semanticLabel;
- this._labelContainer.appendChild(label);
- object.userData = { userObjectId, controls, semanticLabel, label };
- if (idOverride == null) {
- this.render();
- }
- return userObjectId;
- }
-
- addMesh(
- width,
- height,
- depth,
- semanticLabel,
- idOverride = null,
- active = true,
- ) {
- if (
- !isNumber(width) ||
- !isNumber(height) ||
- !isNumber(depth) ||
- width * height * depth == 0
- ) {
- return;
- }
- const object = new THREE.Mesh(
- new THREE.BoxGeometry(width, height, depth),
- new THREE.MeshPhongMaterial({
- color: 0xffffff * Math.random(),
- transparent: true,
- }),
- );
- const userObjectId = this.addObject(object, semanticLabel, idOverride);
- EmulatorSettings.instance.userObjects[userObjectId] = {
- type: 'mesh',
- active: true,
- width,
- height,
- depth,
- semanticLabel,
- position: object.position.toArray(),
- quaternion: object.quaternion.toArray(),
- };
- this._toggleObjectVisibility(userObjectId, active);
- EmulatorSettings.instance.write().then(updateUserObjects);
- return object;
- }
-
- addPlane(
- width,
- height,
- isVertical,
- semanticLabel,
- idOverride = null,
- active = true,
- ) {
- if (!isNumber(width) || !isNumber(height) || width * height == 0) {
- return;
- }
- const planeGeometry = new THREE.PlaneGeometry(width, height);
- planeGeometry.rotateX(Math.PI / 2);
- const object = new THREE.Mesh(
- planeGeometry,
- new THREE.MeshPhongMaterial({
- color: 0xffffff * Math.random(),
- side: THREE.DoubleSide,
- transparent: true,
- }),
- );
- if (isVertical) {
- object.rotateX(Math.PI / 2);
- }
- const userObjectId = this.addObject(object, semanticLabel, idOverride);
- EmulatorSettings.instance.userObjects[userObjectId] = {
- type: 'plane',
- active: true,
- width,
- height,
- isVertical,
- semanticLabel,
- position: object.position.toArray(),
- quaternion: object.quaternion.toArray(),
- };
- this._toggleObjectVisibility(userObjectId, active);
- EmulatorSettings.instance.write().then(updateUserObjects);
- return object;
- }
-
- deleteSelectedObject() {
- Object.entries(this._transformControls).forEach(([key, controls]) => {
- if (controls.enabled) {
- const object = this._userObjects[key];
- if (object) {
- const { label } = object.userData;
- this._labelContainer.removeChild(label);
- controls.detach();
- this._scene.remove(object);
- delete this._userObjects[key];
- controls.dispose();
- delete this._transformControls[key];
- this.render();
- delete EmulatorSettings.instance.userObjects[key];
- EmulatorSettings.instance.write().then(updateUserObjects);
- }
- }
- });
- }
-
- _toggleObjectVisibility(objectId, active = undefined) {
- const object = this._userObjects[objectId];
- if (object) {
- const isActive =
- active ?? !EmulatorSettings.instance.userObjects[objectId].active;
- EmulatorSettings.instance.userObjects[objectId].active = isActive;
- const { label, semanticLabel } = object.userData;
- if (isActive) {
- object.material.opacity = 1;
- label.innerHTML = semanticLabel;
- } else {
- object.material.opacity = 0.4;
- label.innerHTML = '[hidden] ' + semanticLabel;
- }
- }
- }
-
- toggleSelectedObjectVisibility() {
- Object.entries(this._transformControls).forEach(([objectId, controls]) => {
- if (controls.enabled) {
- this._toggleObjectVisibility(objectId);
- this.render();
- EmulatorSettings.instance.write().then(updateUserObjects);
- }
- });
- }
-
- _updateObjects() {
- Object.entries(this._transformControls).forEach(
- ([userObjectId, controls]) => {
- if (controls.enabled) {
- const object = this._userObjects[userObjectId];
- if (object) {
- EmulatorSettings.instance.userObjects[userObjectId].position =
- object.position.toArray();
- EmulatorSettings.instance.userObjects[userObjectId].quaternion =
- object.quaternion.toArray();
- }
- }
- },
- );
- EmulatorSettings.instance.write().then(updateUserObjects);
- }
-
- _recoverObjects() {
- Object.entries(EmulatorSettings.instance.userObjects).forEach(
- ([userObjectId, objectData]) => {
- const {
- type,
- active,
- width,
- height,
- depth,
- isVertical,
- semanticLabel,
- position,
- quaternion,
- } = objectData;
- let object;
- if (type === 'mesh') {
- object = this.addMesh(
- width,
- height,
- depth,
- semanticLabel,
- userObjectId,
- active,
- );
- } else if (type === 'plane') {
- object = this.addPlane(
- width,
- height,
- isVertical,
- semanticLabel,
- userObjectId,
- active,
- );
- }
- if (object) {
- object.position.fromArray(position);
- object.quaternion.fromArray(quaternion);
- }
- },
- );
- }
-
- get canvas() {
- return this._renderer.domElement;
- }
-
- get labels() {
- return this._labelContainer;
- }
-
- getDeviceNode(deviceKey) {
- return emulatorStates.assetNodes[deviceKey];
- }
-
- forceEmitPose() {
- Object.values(DEVICE).forEach((deviceKey) => {
- this._emitPoseEvent(deviceKey);
- });
- }
-
- toggleControlMode(deviceKey, clearOthers = true) {
- if (clearOthers) {
- Object.entries(this._transformControls).forEach(([key, controls]) => {
- if (key != deviceKey) {
- controls.enabled = false;
- controls.visible = false;
- }
- });
- }
- const controls = this._transformControls[deviceKey];
- if (!controls.enabled) {
- controls.enabled = true;
- controls.visible = true;
- controls.setMode('translate');
- } else if (controls.getMode() === 'translate') {
- controls.setMode('rotate');
- } else {
- controls.enabled = false;
- controls.visible = false;
- }
- this.render();
- }
-
- toggleControllerVisibility(deviceKey, visible) {
- this._controllerMeshesHidden[deviceKey] = !visible;
- this.render();
- }
-
- toggleHandVisibility(deviceKey, visible) {
- this._handMeshesHidden[deviceKey] = !visible;
- this.render();
- }
-
- setDeviceTransform(deviceKey, position, rotation) {
- const deviceNode = this.getDeviceNode(deviceKey);
- if (deviceNode) {
- deviceNode.position.fromArray(position);
- deviceNode.rotation.fromArray(rotation);
- this._emitPoseEvent(deviceKey);
- this.render();
- }
- }
-
- resetPose() {
- Object.values(DEVICE).forEach((deviceKey) => {
- const deviceNode = this.getDeviceNode(deviceKey);
- deviceNode.position.fromArray(
- EmulatorSettings.instance.defaultPose[deviceKey].position,
- );
- deviceNode.rotation.fromArray(
- EmulatorSettings.instance.defaultPose[deviceKey].rotation,
- );
- this._emitPoseEvent(deviceKey);
- });
- this.render();
- }
-
- render() {
- Object.entries(this._handMeshes).forEach(([deviceKey, mesh]) => {
- mesh.visible =
- EmulatorSettings.instance.inputMode === 'hands' &&
- !this._handMeshesHidden[deviceKey];
- });
- Object.entries(this._controllerMeshes).forEach(([deviceKey, mesh]) => {
- mesh.visible =
- EmulatorSettings.instance.inputMode === 'controllers' &&
- !this._controllerMeshesHidden[deviceKey];
- });
- const parent = this.canvas.parentElement;
- if (!parent) return;
- const width = parent.offsetWidth;
- const height = parent.offsetHeight;
- if (width != this._lastWidth || height != this._lastHeight) {
- this._camera.aspect = width / height;
- this._camera.updateProjectionMatrix();
- this._renderer.setSize(width, height);
- this._lastWidth = width;
- this._lastHeight = height;
- }
- this._renderer.render(this._scene, this._camera);
-
- const sceneContainer = this._renderer.domElement.parentElement;
- if (!sceneContainer) return;
-
- Object.values(this._userObjects).forEach((object) => {
- const { label } = object.userData;
- if (label) {
- const screenVec = object.position.clone().project(this._camera);
- screenVec.x = ((screenVec.x + 1) * sceneContainer.offsetWidth) / 2;
- screenVec.y = (-(screenVec.y - 1) * sceneContainer.offsetHeight) / 2;
- label.style.top = `${screenVec.y}px`;
- label.style.left = `${screenVec.x}px`;
- }
- });
- }
-}
diff --git a/devtool/js/emulatorStates.js b/devtool/js/emulatorStates.js
deleted file mode 100644
index 837e81c..0000000
--- a/devtool/js/emulatorStates.js
+++ /dev/null
@@ -1,172 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-import { DEFAULT_TRANSFORMS } from './constants';
-
-// eslint-disable-next-line no-undef
-// const localStorage = chrome.storage.local;
-const originalLocalStorage = window.localStorage;
-const localStorage = {
- get: (key, callback) => {
- callback(originalLocalStorage.getItem(key))
- },
- set: (data, callback) => {
- Object.entries(data).forEach(([key, value]) => {
- originalLocalStorage.setItem(key, value)
- })
- callback()
- }
-}
-
-
-const STORAGE_KEY = 'immersive-web-emulator-settings';
-localStorage.set({ [STORAGE_KEY]: null }, () => {});
-
-export const emulatorStates = {
- inImmersive: false,
- actionMappingOn: true,
- assetNodes: {},
- controllers: {
- 'left-controller': {
- joystick: {
- touched: false,
- pressed: false,
- valueX: 0,
- valueY: 0,
- },
- trigger: {
- touched: false,
- value: 0,
- },
- grip: {
- touched: false,
- value: 0,
- },
- button1: {
- touched: false,
- pressed: false,
- },
- button2: {
- touched: false,
- pressed: false,
- },
- },
- 'right-controller': {
- joystick: {
- touched: false,
- pressed: false,
- valueX: 0,
- valueY: 0,
- },
- trigger: {
- touched: false,
- value: 0,
- },
- grip: {
- touched: false,
- value: 0,
- },
- button1: {
- touched: false,
- pressed: false,
- },
- button2: {
- touched: false,
- pressed: false,
- },
- },
- },
- playbackInProgress: false,
- pinchValues: {
- 'left-hand': 0,
- 'right-hand': 0,
- },
- joysticks: {},
- buttons: {},
- sliders: {},
- emulatedDevice: null,
-};
-
-export class EmulatorSettings {
- static get instance() {
- if (!EmulatorSettings._instance) {
- EmulatorSettings._instance = new EmulatorSettings();
- }
- return EmulatorSettings._instance;
- }
-
- constructor() {
- this.stereoOn = false;
- this.actionMappingOn = true;
- this.defaultPose = DEFAULT_TRANSFORMS;
- this.deviceKey = 'Meta Quest 3';
- this.keyboardMappingOn = true;
- this.roomDimension = { x: 6, y: 3, z: 6 };
- this.polyfillExcludes = new Set();
- this.inputMode = 'controllers';
- this.handPoses = {
- 'left-hand': 'relaxed',
- 'right-hand': 'relaxed',
- };
- this.userObjects = {};
- this.triggerMode = 'normal';
- }
-
- load() {
- return new Promise((resolve) => {
- localStorage.get(STORAGE_KEY, (result) => {
- const settings = result[STORAGE_KEY]
- ? JSON.parse(result[STORAGE_KEY])
- : null;
- this.stereoOn = settings?.stereoOn ?? false;
- this.actionMappingOn = settings?.actionMappingOn ?? true;
- this.defaultPose = settings?.defaultPose ?? DEFAULT_TRANSFORMS;
- this.deviceKey = settings?.deviceKey ?? 'Meta Quest 3';
- this.keyboardMappingOn = settings?.keyboardMappingOn ?? true;
- this.roomDimension = settings?.roomDimension ?? { x: 6, y: 3, z: 6 };
- this.polyfillExcludes = new Set(settings?.polyfillExcludes ?? []);
- this.inputMode = settings?.inputMode ?? 'controllers';
- this.handPoses = settings?.handPoses ?? this.handPoses;
- this.userObjects = settings?.userObjects ?? {};
- this.triggerMode = settings?.triggerMode ?? 'normal';
- resolve(result);
- });
- });
- }
-
- write() {
- const settings = {};
- settings[STORAGE_KEY] = JSON.stringify({
- stereoOn: this.stereoOn,
- actionMappingOn: this.actionMappingOn,
- defaultPose: this.defaultPose,
- deviceKey: this.deviceKey,
- keyboardMappingOn: this.keyboardMappingOn,
- roomDimension: this.roomDimension,
- polyfillExcludes: Array.from(this.polyfillExcludes),
- inputMode: this.inputMode,
- handPoses: this.handPoses,
- userObjects: this.userObjects,
- triggerMode: this.triggerMode,
- });
- return new Promise((resolve) => {
- localStorage.set(settings, () => {
- resolve(settings);
- });
- });
- }
-
- clear() {
- const settings = {};
- settings[STORAGE_KEY] = null;
- return new Promise((resolve) => {
- localStorage.set(settings, () => {
- resolve(settings);
- });
- });
- }
-}
diff --git a/devtool/js/joystick.js b/devtool/js/joystick.js
deleted file mode 100644
index 0c1dac8..0000000
--- a/devtool/js/joystick.js
+++ /dev/null
@@ -1,172 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-import { EventEmitter } from 'events';
-
-const CIRCUMFERENCE = 2 * Math.PI;
-const LINEWIDTH = 4;
-const OUTER_STROKE_COLOR = '#e4e6eb';
-const INNER_FILL_COLOR = '#317BEF';
-
-export class Joystick extends EventEmitter {
- constructor(size, autoReturn, renderScale = 2) {
- super();
- this._renderScale = renderScale;
- this._autoReturn = autoReturn;
-
- const canvas = document.createElement('canvas');
- canvas.id = 'Joystick';
- canvas.width = size * renderScale;
- canvas.height = size * renderScale;
- this._radius = (size / 2) * renderScale;
- canvas.style.width = 75;
- canvas.style.height = 75;
- this._canvas = canvas;
-
- this._pressed = false;
- this._innerRadius = this._radius / 2;
- this._outerRadius = this._innerRadius * 1.5;
- this._maxStickDelta = this._outerRadius - this._innerRadius / 2;
-
- this._centerX = this._radius;
- this._centerY = this._radius;
- this._refX = 0;
- this._refY = 0;
- this._deltaX = 0;
- this._deltaY = 0;
-
- canvas.addEventListener('mousedown', this._onMouseDown.bind(this), false);
- document.addEventListener('mousemove', this._onMouseMove.bind(this), false);
- document.addEventListener('mouseup', this._onMouseUp.bind(this), false);
-
- this._drawOuterCircle();
- this._drawInnerCircle();
- }
-
- _drawOuterCircle() {
- const context = this._canvas.getContext('2d');
- context.imageSmoothingQuality = 'high';
- context.beginPath();
- context.arc(
- this._centerX,
- this._centerY,
- this._outerRadius,
- 0,
- CIRCUMFERENCE,
- false,
- );
-
- context.lineWidth = LINEWIDTH * this._renderScale;
- context.strokeStyle = OUTER_STROKE_COLOR;
- context.stroke();
- }
-
- _drawInnerCircle() {
- const context = this._canvas.getContext('2d');
- context.beginPath();
- const deltaDistance = Math.sqrt(
- this._deltaX * this._deltaX + this._deltaY * this._deltaY,
- );
- const scaleFactor = deltaDistance / this._maxStickDelta;
- if (scaleFactor > 1) {
- this._deltaX /= scaleFactor;
- this._deltaY /= scaleFactor;
- }
- context.arc(
- this._deltaX + this._centerX,
- this._deltaY + this._centerY,
- this._innerRadius,
- 0,
- CIRCUMFERENCE,
- false,
- );
-
- context.fillStyle = INNER_FILL_COLOR;
- context.fill();
- context.lineWidth = 0;
- }
-
- _onMouseDown(event) {
- this._refX = event.pageX;
- this._refY = event.pageY;
- this._pressed = true;
- this._dispatchEvent();
- }
-
- _onMouseUp(_event) {
- const context = this._canvas.getContext('2d');
- this._pressed = false;
-
- if (this._autoReturn) {
- this._deltaX = 0;
- this._deltaY = 0;
- }
-
- context.clearRect(0, 0, this._canvas.width, this._canvas.height);
-
- this._drawOuterCircle();
- this._drawInnerCircle();
- this._dispatchEvent();
- }
-
- _onMouseMove(event) {
- if (this._pressed) {
- const context = this._canvas.getContext('2d');
- this._deltaX = (event.pageX - this._refX) * this._renderScale;
- this._deltaY = (event.pageY - this._refY) * this._renderScale;
-
- context.clearRect(0, 0, this._canvas.width, this._canvas.height);
-
- this._drawOuterCircle();
- this._drawInnerCircle();
- this._dispatchEvent();
- }
- }
-
- _dispatchEvent() {
- this.emit('joystickmove');
- }
-
- overrideMove(x, y) {
- const context = this._canvas.getContext('2d');
- this._deltaX = x * this._maxStickDelta;
- this._deltaY = y * this._maxStickDelta;
-
- context.clearRect(0, 0, this._canvas.width, this._canvas.height);
-
- this._drawOuterCircle();
- this._drawInnerCircle();
- this._dispatchEvent();
- }
-
- addToParent(parent) {
- parent.appendChild(this._canvas);
- }
-
- getX() {
- return (100 * (this._deltaX / this._maxStickDelta)).toFixed() / 100;
- }
-
- getY() {
- return (100 * (this._deltaY / this._maxStickDelta)).toFixed() / 100;
- }
-
- reset() {
- this._deltaX = 0;
- this._deltaY = 0;
- this._onMouseUp();
- }
-
- get sticky() {
- return !this._autoReturn;
- }
-
- setSticky(sticky) {
- this._autoReturn = !sticky;
- this._onMouseUp();
- }
-}
diff --git a/devtool/js/keyboard.js b/devtool/js/keyboard.js
deleted file mode 100644
index 6ac9fe8..0000000
--- a/devtool/js/keyboard.js
+++ /dev/null
@@ -1,185 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-import { DEVICE, KEYBOARD_CONTROL_MAPPING, OBJECT_NAME } from './constants';
-import { EmulatorSettings, emulatorStates } from './emulatorStates';
-
-import { relayKeyboardEvent } from './messenger';
-
-const emulatedJoysticks = {};
-const JOYSTICKS = emulatorStates.joysticks;
-
-const resetEmulatedJoysticks = () => {
- emulatedJoysticks.left = {
- left: false,
- right: false,
- forward: false,
- backward: false,
- };
- emulatedJoysticks.right = {
- left: false,
- right: false,
- forward: false,
- backward: false,
- };
-};
-
-const getReservedKeyAction = (key) => {
- let result = null;
- Object.entries(KEYBOARD_CONTROL_MAPPING).forEach(([handKey, mapping]) => {
- Object.entries(mapping).forEach(([action, mappedKey]) => {
- if (mappedKey == key) {
- result = [handKey, action];
- }
- });
- });
- return result;
-};
-
-const onReservedKeyDown = (handKey, action) => {
- switch (action) {
- case 'joystickLeft':
- emulatedJoysticks[handKey].left = true;
- break;
- case 'joystickRight':
- emulatedJoysticks[handKey].right = true;
- break;
- case 'joystickForward':
- emulatedJoysticks[handKey].forward = true;
- break;
- case 'joystickBackward':
- emulatedJoysticks[handKey].backward = true;
- break;
- case 'trigger':
- case 'grip':
- emulatorStates.sliders[handKey][action].value = 100;
- emulatorStates.buttons[handKey][action].disabled = true;
- emulatorStates.sliders[handKey][action].onInputFunc();
- break;
- default:
- emulatorStates.buttons[handKey][action].click();
- }
-};
-
-const onReservedKeyUp = (handKey, action) => {
- switch (action) {
- case 'joystickLeft':
- emulatedJoysticks[handKey].left = false;
- break;
- case 'joystickRight':
- emulatedJoysticks[handKey].right = false;
- break;
- case 'joystickForward':
- emulatedJoysticks[handKey].forward = false;
- break;
- case 'joystickBackward':
- emulatedJoysticks[handKey].backward = false;
- break;
- case 'trigger':
- case 'grip':
- emulatorStates.sliders[handKey][action].value = 0;
- emulatorStates.buttons[handKey][action].disabled = false;
- emulatorStates.sliders[handKey][action].onInputFunc();
- break;
- default:
- emulatorStates.buttons[handKey][action].click();
- }
-};
-
-/**
- *
- * @param {KeyboardEvent} event
- */
-const passThroughKeyboardEvent = (event) => {
- const options = {
- key: event.key,
- code: event.code,
- location: event.location,
- repeat: event.repeat,
- isComposing: event.isComposing,
- ctrlKey: event.ctrlKey,
- shiftKey: event.shiftKey,
- altKey: event.altKey,
- metaKey: event.metaKey,
- };
-
- relayKeyboardEvent(event.type, options);
-};
-
-const moveJoysticks = () => {
- Object.entries(emulatedJoysticks).forEach(([handKey, directions]) => {
- const deviceId = handKey == 'left' ? DEVICE.INPUT_LEFT : DEVICE.INPUT_RIGHT;
- const deviceName = OBJECT_NAME[deviceId];
- if (
- directions.left ||
- directions.right ||
- directions.forward ||
- directions.backward
- ) {
- const axisX = directions.left ? -1 : 0 + directions.right ? 1 : 0;
- const axisY = directions.forward ? -1 : 0 + directions.backward ? 1 : 0;
- const normalizeScale = Math.sqrt(axisX * axisX + axisY * axisY);
-
- if (JOYSTICKS[deviceName]) {
- JOYSTICKS[deviceName].overrideMove(
- axisX / normalizeScale,
- axisY / normalizeScale,
- );
- }
- } else {
- if (JOYSTICKS[deviceName]) {
- JOYSTICKS[deviceName].overrideMove(0, 0);
- }
- }
- });
-};
-
-export default function initKeyboardControl() {
- resetEmulatedJoysticks();
- window.addEventListener('blur', resetEmulatedJoysticks);
-
- document.addEventListener(
- 'keydown',
- (event) => {
- const result = getReservedKeyAction(event.key);
- if (EmulatorSettings.instance.actionMappingOn && result) {
- const [handKey, action] = result;
- onReservedKeyDown(handKey, action);
- moveJoysticks();
- } else {
- passThroughKeyboardEvent(event);
- }
- },
- false,
- );
-
- document.addEventListener(
- 'keyup',
- (event) => {
- const result = getReservedKeyAction(event.key);
- if (result) {
- const [handKey, action] = result;
- onReservedKeyUp(handKey, action);
- moveJoysticks();
- } else if (EmulatorSettings.instance.actionMappingOn) {
- passThroughKeyboardEvent(event);
- }
- },
- false,
- );
-
- document.addEventListener(
- 'keypress',
- (event) => {
- const result = getReservedKeyAction(event.key);
- if (!result && EmulatorSettings.instance.actionMappingOn) {
- passThroughKeyboardEvent(event);
- }
- },
- false,
- );
-}
diff --git a/devtool/js/messenger.js b/devtool/js/messenger.js
deleted file mode 100644
index 397b0f0..0000000
--- a/devtool/js/messenger.js
+++ /dev/null
@@ -1,178 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-import { WebXREventDispatcher } from '../../webxr-emulator/WebXREventDispatcher';
-import { CLIENT_ACTIONS, EMULATOR_ACTIONS } from './actions';
-import { DEVICE, HAND_STRINGS, OBJECT_NAME } from './constants';
-import { EmulatorSettings, emulatorStates } from './emulatorStates';
-
-const tabId = 0// chrome.devtools.inspectedWindow.tabId;
-
-const connection = {
- port: null,
- connect: () => {
- connection.port = chrome.runtime.connect(null, { name: 'iwe_devtool' });
- connection.port.onMessage.addListener((payload) => {
- switch (payload.action) {
- case CLIENT_ACTIONS.ENTER_IMMERSIVE:
- emulatorStates.inImmersive = true;
- emulatorStates.emulatedDevice?.forceEmitPose();
- break;
- case CLIENT_ACTIONS.EXIT_IMMERSIVE:
- emulatorStates.inImmersive = false;
- break;
- }
- });
- connection.port.onDisconnect.addListener(connection.connect);
- },
-};
-
-const executeAction = (action, detail = {}) => {
- const payload = { detail };
- payload.tabId = tabId;
- payload.action = action;
- payload.type = action
- WebXREventDispatcher.instance.dispatchEvent(payload);
- // try {
- // connection.port.postMessage(payload);
- // } catch (_e) {
- // connection.connect();
- // connection.port.postMessage(payload);
- // }
-};
-
-export const syncDevicePose = (event) => {
- const { deviceKey, position, quaternion } = event;
- if (deviceKey === DEVICE.HEADSET) {
- executeAction(EMULATOR_ACTIONS.HEADSET_POSE_CHANGE, {
- position,
- quaternion,
- });
- } else {
- executeAction(EMULATOR_ACTIONS.CONTROLLER_POSE_CHANGE, {
- objectName: OBJECT_NAME[deviceKey],
- position,
- quaternion,
- });
- }
-};
-
-export const applyControllerButtonPressed = (key, buttonIndex, pressed) => {
- executeAction(EMULATOR_ACTIONS.BUTTON_STATE_CHANGE, {
- objectName: OBJECT_NAME[key],
- buttonIndex,
- pressed,
- });
-};
-
-export const applyControllerButtonChanged = (
- key,
- buttonIndex,
- pressed,
- touched,
- value,
-) => {
- executeAction(EMULATOR_ACTIONS.BUTTON_STATE_CHANGE, {
- objectName: OBJECT_NAME[key],
- buttonIndex,
- pressed,
- touched,
- value,
- });
-};
-
-export const applyControllerAnalogValue = (key, axisIndex, value) => {
- executeAction(EMULATOR_ACTIONS.ANALOG_VALUE_CHANGE, {
- objectName: OBJECT_NAME[key],
- axisIndex,
- value,
- });
-};
-
-export const changeEmulatedDeviceType = (deviceDefinition) => {
- executeAction(EMULATOR_ACTIONS.DEVICE_TYPE_CHANGE, { deviceDefinition });
-};
-
-export const toggleStereoMode = (enabled) => {
- executeAction(EMULATOR_ACTIONS.STEREO_TOGGLE, { enabled });
-};
-
-export const relayKeyboardEvent = (eventType, eventOptions) => {
- executeAction(EMULATOR_ACTIONS.KEYBOARD_EVENT, {
- eventType,
- eventOptions,
- });
-};
-
-export const notifyExitImmersive = () => {
- executeAction(EMULATOR_ACTIONS.EXIT_IMMERSIVE);
-};
-
-export const changeRoomDimension = () => {
- executeAction(EMULATOR_ACTIONS.ROOM_DIMENSION_CHANGE, {
- dimension: EmulatorSettings.instance.roomDimension,
- });
-};
-
-export const changeInputMode = () => {
- executeAction(EMULATOR_ACTIONS.INPUT_MODE_CHANGE, {
- inputMode: EmulatorSettings.instance.inputMode,
- });
-};
-
-export const changeHandPose = (deviceId) => {
- const handName = HAND_STRINGS[deviceId].name;
- executeAction(EMULATOR_ACTIONS.HAND_POSE_CHANGE, {
- handedness: deviceId === DEVICE.INPUT_LEFT ? 'left' : 'right',
- pose: EmulatorSettings.instance.handPoses[handName],
- });
-};
-
-export const updatePinchValue = (deviceId) => {
- const handName = HAND_STRINGS[deviceId].name;
- executeAction(EMULATOR_ACTIONS.PINCH_VALUE_CHANGE, {
- handedness: deviceId === DEVICE.INPUT_LEFT ? 'left' : 'right',
- value: emulatorStates.pinchValues[handName],
- });
-};
-
-export const togglePolyfill = () => {
- chrome.tabs.get(tabId, (tab) => {
- const url = new URL(tab.url);
- const urlMatchPattern = url.origin + '/*';
- if (EmulatorSettings.instance.polyfillExcludes.has(urlMatchPattern)) {
- EmulatorSettings.instance.polyfillExcludes.delete(urlMatchPattern);
- } else {
- EmulatorSettings.instance.polyfillExcludes.add(urlMatchPattern);
- }
- EmulatorSettings.instance.write().then(() => {
- executeAction(EMULATOR_ACTIONS.EXCLUDE_POLYFILL);
- });
- });
-};
-
-export const toggleControllerVisibility = (deviceKey, visible) => {
- executeAction(EMULATOR_ACTIONS.CONTROLLER_VISIBILITY_CHANGE, {
- objectName: OBJECT_NAME[deviceKey],
- visible,
- });
-};
-
-export const toggleHandVisibility = (deviceId, visible) => {
- executeAction(EMULATOR_ACTIONS.HAND_VISIBILITY_CHANGE, {
- handedness: HAND_STRINGS[deviceId].handedness,
- visible,
- });
-};
-
-export const reloadInspectedTab = () => {
- executeAction(EMULATOR_ACTIONS.EXCLUDE_POLYFILL);
-};
-
-export const updateUserObjects = () => {
- executeAction(EMULATOR_ACTIONS.USER_OBJECTS_CHANGE);
-};
diff --git a/devtool/jsx/app.jsx b/devtool/jsx/app.jsx
deleted file mode 100644
index 454e3fc..0000000
--- a/devtool/jsx/app.jsx
+++ /dev/null
@@ -1,123 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-import ControllerPanel from './controllers.jsx';
-import { DEVICE } from '../js/constants';
-import { EmulatorSettings } from '../js/emulatorStates.js';
-import HandPanel from './hands.jsx';
-import HeadsetBar from './headset.jsx';
-import Inspector from './inspector.jsx';
-import PoseBar from './pose.jsx';
-import React from 'react';
-
-const MIN_PANEL_WIDTH = 327;
-const MIN_PANEL_HEIGHT = 256;
-const MIN_INPUT_PANEL_WIDTH = 420;
-const MIN_INPUT_PANEL_HEIGHTS = {
- controllers: 452,
- hands: 327,
-};
-
-export default function App({ device }) {
- const [inputMode, setInputMode] = React.useState(
- EmulatorSettings.instance.inputMode,
- );
- const [showInspector, setShowInspector] = React.useState(true);
- const [showControls, setShowControls] = React.useState(true);
- const sizeWarningRef = React.useRef();
- React.useEffect(onResize, [inputMode]);
-
- React.useEffect(() => {
- window.addEventListener('resize', function () {
- onResize();
- });
- });
-
- function onResize() {
- const body = document.getElementById('devtools')
- if (body.offsetHeight < MIN_PANEL_HEIGHT) {
- if (showInspector) setShowInspector(false);
- if (showControls) setShowControls(false);
- sizeWarningRef.current.innerHTML = 'Not Enough Vertical Space';
- } else if (body.offsetWidth < MIN_PANEL_WIDTH) {
- if (showInspector) setShowInspector(false);
- if (showControls) setShowControls(false);
- sizeWarningRef.current.innerHTML = 'Not Enough Horizontal Space';
- } else {
- if (!showInspector) setShowInspector(true);
- const inputMode = EmulatorSettings.instance.inputMode;
- if (body.offsetWidth < MIN_INPUT_PANEL_WIDTH) {
- if (showControls) setShowControls(false);
- sizeWarningRef.current.innerHTML = 'Not Enough Horizontal Space';
- } else if (
- body.offsetHeight < MIN_INPUT_PANEL_HEIGHTS[inputMode]
- ) {
- if (showControls) setShowControls(false);
- sizeWarningRef.current.innerHTML = 'Not Enough Vertical Space';
- } else {
- if (!showControls) setShowControls(true);
- }
- }
- device.render();
- }
-
- return (
- <>
-
-
-
- {[DEVICE.INPUT_LEFT, DEVICE.INPUT_RIGHT].map((deviceKey) => (
-
- ))}
-
-
- {[DEVICE.INPUT_LEFT, DEVICE.INPUT_RIGHT].map((deviceKey) => (
-
- ))}
-
-
-
-
- >
- );
-}
diff --git a/devtool/jsx/controllers.jsx b/devtool/jsx/controllers.jsx
deleted file mode 100644
index 3e1a60d..0000000
--- a/devtool/jsx/controllers.jsx
+++ /dev/null
@@ -1,339 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-import {
- BUTTON_POLYFILL_INDEX_MAPPING,
- CONTROLLER_STRINGS,
- PRESS_AND_RELEASE_DURATION,
- TRIGGER_CONFIG,
-} from '../js/constants';
-import { EmulatorSettings, emulatorStates } from '../js/emulatorStates';
-import {
- applyControllerAnalogValue,
- applyControllerButtonChanged,
- applyControllerButtonPressed,
- toggleControllerVisibility,
-} from '../js/messenger';
-import config from '@ir-engine/common/src/config';
-
-const assetURL = config.client.fileServer + '/projects/ir-engine/ir-bot/devtool'
-
-import { Joystick } from '../js/joystick';
-import React from 'react';
-
-function ControlButtonGroup({ isAnalog, deviceKey, buttonKey }) {
- const touchRef = React.useRef();
- const pressRef = React.useRef();
- const holdRef = React.useRef();
- const rangeRef = React.useRef();
- const deviceName = CONTROLLER_STRINGS[deviceKey].name;
- const buttonState = emulatorStates.controllers[deviceName][buttonKey];
-
- function onTouchToggle() {
- buttonState.touched = !buttonState.touched;
- buttonState.touched ||= buttonState.pressed;
- touchRef.current.classList.toggle('button-pressed', buttonState.touched);
- applyControllerButtonChanged(
- deviceKey,
- BUTTON_POLYFILL_INDEX_MAPPING[buttonKey],
- buttonState.pressed,
- buttonState.touched,
- buttonState.value,
- );
- }
-
- function onHoldToggle() {
- buttonState.pressed = !buttonState.pressed;
- buttonState.touched ||= buttonState.pressed;
- pressRef.current.disabled = buttonState.pressed;
- holdRef.current.classList.toggle('button-pressed', buttonState.pressed);
- applyControllerButtonPressed(
- deviceKey,
- BUTTON_POLYFILL_INDEX_MAPPING[buttonKey],
- buttonState.pressed,
- );
- }
-
- function onPressBinary() {
- if (buttonState.pressed) return;
- onHoldToggle();
- pressRef.current.disabled = true;
- holdRef.current.disabled = true;
- setTimeout(() => {
- onHoldToggle();
- pressRef.current.disabled = false;
- holdRef.current.disabled = false;
- }, PRESS_AND_RELEASE_DURATION);
- }
-
- function onRangeInput() {
- const inputValue = rangeRef.current.value / 100;
- applyControllerButtonChanged(
- deviceKey,
- BUTTON_POLYFILL_INDEX_MAPPING[buttonKey],
- inputValue != 0,
- buttonState.touched,
- inputValue,
- );
- }
-
- const onPressAnalog = createAnalogPressFunction(
- pressRef,
- rangeRef,
- onRangeInput,
- );
-
- React.useEffect(() => {
- const handedness = CONTROLLER_STRINGS[deviceKey].handedness;
- if (isAnalog) {
- rangeRef.current.value = 0;
- onRangeInput();
- if (!emulatorStates.sliders[handedness]) {
- emulatorStates.sliders[handedness] = {};
- }
- rangeRef.current.onInputFunc = onRangeInput;
- emulatorStates.sliders[handedness][buttonKey] = rangeRef.current;
- }
- if (!emulatorStates.buttons[handedness]) {
- emulatorStates.buttons[handedness] = {};
- }
- emulatorStates.buttons[handedness][buttonKey] = pressRef.current;
- });
-
- return (
-
-
-
- {isAnalog ? (
-
- ) : (
-
- )}
-
- );
-}
-
-export default function ControllerPanel({ deviceKey, device }) {
- const strings = CONTROLLER_STRINGS[deviceKey];
- const joystickContainerRef = React.useRef();
- const joystickResetRef = React.useRef();
- const joystickStickyRef = React.useRef();
-
- const [showController, setShowController] = React.useState(true);
-
- const joystick = new Joystick(100, true, 1);
- emulatorStates.joysticks[strings.name] = joystick;
- joystick.on('joystickmove', () => {
- // update joystick
- applyControllerAnalogValue(deviceKey, 0, joystick.getX());
- applyControllerAnalogValue(deviceKey, 1, joystick.getY());
-
- joystickResetRef.current.disabled = !(
- joystick.sticky &&
- joystick.getX() != 0 &&
- joystick.getY() != 0
- );
- });
-
- function onStickyToggle() {
- joystick.setSticky(!joystick.sticky);
- joystickStickyRef.current.classList.toggle(
- 'button-pressed',
- joystick.sticky,
- );
- }
-
- function toggleDeviceVisibility(event) {
- setShowController(!showController); // React state only applies to the next rendering frame
- device.toggleControllerVisibility(deviceKey, !showController);
- toggleControllerVisibility(deviceKey, !showController);
- event.target.classList.toggle('button-pressed', showController);
- }
-
- React.useEffect(() => {
- joystick.addToParent(joystickContainerRef.current);
- }, []);
-
- return (
-
-
-
-
-
-
-
{strings.displayName}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {['trigger', 'grip'].map((controlName) => (
-
-
-
-
{controlName}
-
-
-
-
-
- ))}
- {['button2', 'button1'].map((controlName) => (
-
-
-
-
{strings[controlName]}
-
-
-
-
-
- ))}
-
-
-
-
- );
-}
-
-export function createAnalogPressFunction(pressRef, rangeRef, onRangeInput) {
- return function () {
- const step = 10;
- const { interval, holdTime } =
- TRIGGER_CONFIG[EmulatorSettings.instance.triggerMode];
- pressRef.current.disabled = true;
- let rangeValue = 0;
- const pressIntervalId = setInterval(() => {
- if (rangeRef.current.value >= 100) {
- rangeRef.current.value = 100;
- clearInterval(pressIntervalId);
- setTimeout(() => {
- const depressIntervalId = setInterval(() => {
- if (rangeRef.current.value <= 0) {
- rangeRef.current.value = 0;
- clearInterval(depressIntervalId);
- pressRef.current.disabled = false;
- } else {
- rangeRef.current.value -= step;
- }
- onRangeInput();
- }, interval);
- }, holdTime);
- } else {
- rangeValue += step;
- rangeRef.current.value = rangeValue;
- }
- onRangeInput();
- }, interval);
- };
-}
diff --git a/devtool/jsx/hands.jsx b/devtool/jsx/hands.jsx
deleted file mode 100644
index af4e8dc..0000000
--- a/devtool/jsx/hands.jsx
+++ /dev/null
@@ -1,138 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-import { EmulatorSettings, emulatorStates } from '../js/emulatorStates';
-import {
- changeHandPose,
- updatePinchValue,
- toggleHandVisibility,
-} from '../js/messenger';
-
-import { HAND_STRINGS } from '../js/constants';
-import React from 'react';
-import { createAnalogPressFunction } from './controllers.jsx';
-
-import config from '@ir-engine/common/src/config';
-const assetURL = config.client.fileServer + '/projects/ir-engine/ir-bot/devtool'
-
-
-export default function HandPanel({ deviceKey, device }) {
- const strings = HAND_STRINGS[deviceKey];
- const pressRef = React.createRef();
- const rangeRef = React.createRef();
- const poseSelectRef = React.createRef();
-
- const [showHand, setShowHand] = React.useState(true);
-
- function onHandPoseChange() {
- EmulatorSettings.instance.handPoses[strings.name] =
- poseSelectRef.current.value;
- EmulatorSettings.instance.write();
- changeHandPose(deviceKey);
- }
-
- function onRangeInput() {
- emulatorStates.pinchValues[strings.name] = rangeRef.current.value / 100;
- updatePinchValue(deviceKey);
- }
-
- function toggleDeviceVisibility(event) {
- setShowHand(!showHand); // React state only applies to the next rendering frame
- device.toggleHandVisibility(deviceKey, !showHand);
- toggleHandVisibility(deviceKey, !showHand);
- event.target.classList.toggle('button-pressed', showHand);
- }
-
- const onPressAnalog = createAnalogPressFunction(
- pressRef,
- rangeRef,
- onRangeInput,
- );
-
- React.useEffect(onRangeInput, []);
-
- return (
-
-
-
-
-
-
-
{strings.displayName}
-
-
-
-
-
-
-
- Pose
-
-
-
-
-
-
-
-
-
- Pinch
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/devtool/jsx/headset.jsx b/devtool/jsx/headset.jsx
deleted file mode 100644
index 9636d83..0000000
--- a/devtool/jsx/headset.jsx
+++ /dev/null
@@ -1,217 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-import { DEFAULT_TRANSFORMS, TRIGGER_MODES } from '../js/constants';
-import {
- changeEmulatedDeviceType,
- notifyExitImmersive,
- reloadInspectedTab,
- togglePolyfill,
- toggleStereoMode,
-} from '../js/messenger';
-import config from '@ir-engine/common/src/config';
-
-const assetURL = config.client.fileServer + '/projects/ir-engine/ir-bot/devtool'
-
-import { DEVICE_DEFINITIONS } from '../js/devices';
-import { EmulatorSettings } from '../js/emulatorStates';
-import React from 'react';
-
-export default function HeadsetBar({ device }) {
- const headsetSelectRef = React.useRef();
- const polyfillToggleRef = React.useRef();
- const stereoToggleRef = React.useRef();
- const [polyfillOn, setPolyfillOn] = React.useState(true);
- const [showDropDown, setShowDropDown] = React.useState(false);
- const [triggerMode, setTriggerMode] = React.useState(
- EmulatorSettings.instance.triggerMode,
- );
-
- function onChangeDevice() {
- const deviceId = headsetSelectRef.current.value;
- if (DEVICE_DEFINITIONS[deviceId]) {
- EmulatorSettings.instance.deviceKey = deviceId;
- changeEmulatedDeviceType(DEVICE_DEFINITIONS[deviceId]);
- EmulatorSettings.instance.write();
- }
- }
-
- function onToggleStereo() {
- EmulatorSettings.instance.stereoOn = !EmulatorSettings.instance.stereoOn;
- toggleStereoMode(EmulatorSettings.instance.stereoOn);
- stereoToggleRef.current.classList.toggle(
- 'button-pressed',
- EmulatorSettings.instance.stereoOn,
- );
- EmulatorSettings.instance.write();
- }
-
- const updatePolyfillState = (tab) => {
- const url = new URL(tab.url);
- const urlMatchPattern = url.origin + '/*';
- setPolyfillOn(
- !EmulatorSettings.instance.polyfillExcludes.has(urlMatchPattern),
- );
- };
-
- React.useEffect(() => {
- // check every time navigation happens on the tab
- // chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
- // if (
- // tabId === chrome.devtools.inspectedWindow.tabId &&
- // changeInfo.status === 'complete'
- // ) {
- // updatePolyfillState(tab);
- // }
- // });
-
- // // check on start up
- // chrome.tabs.get(chrome.devtools.inspectedWindow.tabId, (tab) => {
- // updatePolyfillState(tab);
- // });
- });
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {showDropDown && (
-
-
-
-
-
-
- )}
-
-
-
-
- );
-}
diff --git a/devtool/jsx/inspector.jsx b/devtool/jsx/inspector.jsx
deleted file mode 100644
index 3932266..0000000
--- a/devtool/jsx/inspector.jsx
+++ /dev/null
@@ -1,381 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-import {
- CONTROLLER_STRINGS,
- DEVICE,
- HAND_STRINGS,
- OBJECT_NAME,
- SEMANTIC_LABELS,
-} from '../js/constants';
-
-import { EmulatorSettings } from '../js/emulatorStates';
-import React from 'react';
-import { changeRoomDimension } from '../js/messenger';
-
-import config from '@ir-engine/common/src/config';
-const assetURL = config.client.fileServer + '/projects/ir-engine/ir-bot/devtool'
-
-export default function Inspector({ device, inputMode }) {
- const sceneContainerRef = React.useRef();
- // plane setting refs
- const planeWidthRef = React.useRef();
- const planeHeightRef = React.useRef();
- const [planeVertical, setPlaneVertical] = React.useState(true);
- const planeSemanticLabelRef = React.useRef();
- // mesh setting refs
- const meshWidthRef = React.useRef();
- const meshHeightRef = React.useRef();
- const meshDepthRef = React.useRef();
- const meshSemanticLabelRef = React.useRef();
-
- const [showTransforms, setShowTransforms] = React.useState(true);
- const [showRoomSettings, setShowRoomSettings] = React.useState(false);
- const [showPlaneSettings, setShowPlaneSettings] = React.useState(false);
- const [showMeshSettings, setShowMeshSettings] = React.useState(false);
- const transformData = {};
- Object.values(DEVICE).forEach((deviceKey) => {
- const deviceName = OBJECT_NAME[deviceKey];
- transformData[deviceName] = React.useState({
- position: [0, 0, 0],
- rotation: [0, 0, 0],
- });
- });
-
- const [inputValues, setInputValues] = React.useState(
- Object.values(DEVICE).reduce((acc, deviceKey) => {
- const deviceName = OBJECT_NAME[deviceKey];
- for (let i = 0; i < 3; i++) {
- acc[`${deviceName}-position-${i}`] =
- transformData[deviceName][0].position[i];
- acc[`${deviceName}-rotation-${i}`] =
- transformData[deviceName][0].rotation[i];
- }
- return acc;
- }, {}),
- );
-
- function handleInputChange(key, event) {
- const value = parseFloat(event.target.value);
- if (!isNaN(value)) {
- const clampedValue = roundAndClamp(value);
- setInputValues((prevValues) => ({
- ...prevValues,
- [key]: clampedValue,
- }));
- // Split the key into its components
- const [deviceName, type, index] = key.split('-');
- const deviceKey = Object.keys(OBJECT_NAME).find(
- (key) => OBJECT_NAME[key] === deviceName,
- );
- // Update the device transform
- if (deviceKey) {
- const position = [...transformData[deviceName][0].position];
- const rotation = [...transformData[deviceName][0].rotation];
- if (type === 'position') {
- position[index] = clampedValue;
- } else if (type === 'rotation') {
- rotation[index] = clampedValue;
- }
- device.setDeviceTransform(deviceKey, position, rotation);
- }
- }
- }
-
- function roundAndClamp(number) {
- const rounded = Math.round(number * 100) / 100;
- return Math.min(Math.max(rounded, -99.99), 99.99);
- }
-
- React.useEffect(() => {
- sceneContainerRef.current.appendChild(device.canvas);
- sceneContainerRef.current.appendChild(device.labels);
- device.on('pose', (event) => {
- const { deviceKey, position, rotation } = event;
- const deviceName = OBJECT_NAME[deviceKey];
- const transform = transformData[deviceName];
- const setTransform = transform[1];
- setTransform({ position, rotation });
- setInputValues((prevValues) => ({
- ...prevValues,
- [`${deviceName}-position-0`]: roundAndClamp(position[0]),
- [`${deviceName}-position-1`]: roundAndClamp(position[1]),
- [`${deviceName}-position-2`]: roundAndClamp(position[2]),
- [`${deviceName}-rotation-0`]: roundAndClamp(rotation[0]),
- [`${deviceName}-rotation-1`]: roundAndClamp(rotation[1]),
- [`${deviceName}-rotation-2`]: roundAndClamp(rotation[2]),
- }));
- });
- device.forceEmitPose();
- }, []);
- return (
- <>
-
-
- >
- );
-}
diff --git a/devtool/jsx/pose.jsx b/devtool/jsx/pose.jsx
deleted file mode 100644
index 87bd12d..0000000
--- a/devtool/jsx/pose.jsx
+++ /dev/null
@@ -1,157 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-import { EmulatorSettings, emulatorStates } from '../js/emulatorStates';
-
-import { DEVICE } from '../js/constants';
-import React from 'react';
-import { changeInputMode } from '../js/messenger';
-import initKeyboardControl from '../js/keyboard';
-
-
-import config from '@ir-engine/common/src/config';
-const assetURL = config.client.fileServer + '/projects/ir-engine/ir-bot/devtool'
-
-export default function PoseBar({ device, setInputMode }) {
- const saveDefaultPoseRef = React.useRef();
- const resetPoseRef = React.useRef();
- const actionMappingToggleRef = React.useRef();
- const handModeToggleRef = React.useRef();
- const controllerModeToggleRef = React.useRef();
-
- function onSaveDefaultPose() {
- const deviceTransform = {};
- Object.values(DEVICE).forEach((device) => {
- deviceTransform[device] = {};
- deviceTransform[device].position =
- emulatorStates.assetNodes[device].position.toArray();
- deviceTransform[device].rotation =
- emulatorStates.assetNodes[device].rotation.toArray();
- });
- EmulatorSettings.instance.defaultPose = deviceTransform;
- EmulatorSettings.instance.write();
- }
-
- function onActionMappingToggle() {
- EmulatorSettings.instance.actionMappingOn =
- !EmulatorSettings.instance.actionMappingOn;
- actionMappingToggleRef.current.classList.toggle(
- 'button-pressed',
- EmulatorSettings.instance.actionMappingOn,
- );
- EmulatorSettings.instance.write();
- }
-
- function onInputModeChange(inputMode) {
- EmulatorSettings.instance.inputMode = inputMode;
- EmulatorSettings.instance.write();
- changeInputMode();
- controllerModeToggleRef.current.classList.toggle(
- 'button-pressed',
- inputMode === 'controllers',
- );
- handModeToggleRef.current.classList.toggle(
- 'button-pressed',
- inputMode === 'hands',
- );
- setInputMode(inputMode);
- }
-
- React.useEffect(() => {
- changeInputMode();
- initKeyboardControl();
- }, []);
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/devtool/styles/index.css b/devtool/styles/index.css
deleted file mode 100644
index 7536ec7..0000000
--- a/devtool/styles/index.css
+++ /dev/null
@@ -1,600 +0,0 @@
-/*
- Copyright (c) Meta Platforms, Inc. and affiliates.
-
- This source code is licensed under the MIT license found in the
- LICENSE file in the root directory of this source tree.
-*/
-
-.row {
- margin: 0px;
-}
-
-.row > * {
- padding-left: 5px;
- padding-right: 5px;
-}
-
-.component {
- display: flex;
- flex-direction: column;
-}
-
-.card {
- border: 0px;
-}
-
-.component-container {
- width: 100%;
- padding: 0;
-}
-
-.root-panel {
- border-radius: 10px;
- color: #a7a7a7;
-}
-
-.inspector-panel {
- flex: 1 1 auto;
- display: flex;
- flex-direction: column;
-}
-
-.controls-panel {
- flex: 0 1 auto;
-}
-
-.inspector-panel .row {
- flex: 1 1 auto;
-}
-
-.inspector-panel .row:first-child,
-.inspector-panel .row:last-child {
- flex: 0 1 auto;
-}
-
-#scene-container {
- padding: 0;
- width: 100%;
- height: 100%;
- position: relative;
- overflow: hidden;
-}
-
-.headset-action-button {
- height: 24px;
- border-radius: 6px;
- border-style: none;
- padding: 4px 6px 4px 6px;
- margin: 0px 0px 0px 10px;
- font-size: small;
- background-color: #3b3b3c;
- color: #e4e6eb;
- text-align: center;
-}
-
-.headset-select {
- height: 2.1em;
- width: 70px;
- appearance: none;
- border-radius: 6px;
- border-style: none;
- padding: 4px;
- margin: 0px 0px 0px 10px;
- font-size: small;
- background-color: #252526;
- color: #e4e6eb;
- text-align: center;
-}
-
-.headset-select:hover {
- background-color: #3b3b3c;
-}
-
-.headset-select:before {
- content: 'Device: ';
- color: #e4e6eb;
-}
-
-.special-button {
- height: 2.1em;
- border-radius: 6px;
- padding: 4px;
- margin: 0px 0px 0px 10px;
- font-size: small;
- background-color: #3b3b3c;
- color: #e4e6eb;
-}
-
-.special-button img {
- width: 1.2em;
-}
-
-.pose-action-button {
- height: 2em;
- display: inline-block;
- border-radius: 6px;
- border-style: none;
- padding: 2px 6px;
- margin: 0px;
- font-size: small;
- background-color: #3b3b3c;
- color: #e4e6eb;
- text-align: center;
- vertical-align: middle;
-}
-
-.pose-action-button:hover,
-.headset-action-button:hover,
-.special-button:hover {
- background-color: #676767;
- color: #e4e6eb;
-}
-
-.pose-action-button:disabled,
-.special-button:disabled {
- background-color: #2a2a2b;
- /* color: #656568; */
- color: #b0b0b0;
-}
-
-.button-pressed {
- background-color: #317bef;
-}
-
-.button-pressed:hover {
- background-color: #679bec;
-}
-
-.button-rightmost {
- border-radius: 2px 6px 6px 2px !important;
- margin-left: 0px;
-}
-
-.button-leftmost {
- border-radius: 6px 2px 2px 6px !important;
-}
-
-.button-middle {
- border-radius: 2px !important;
- margin-left: 0px;
-}
-
-.joystick-button {
- top: 0px;
- right: 12px;
- position: absolute;
- width: 70px;
- margin: 2px;
-}
-
-.action-icon {
- width: 1.25em;
- height: 1.25em;
-}
-
-.control-icon {
- width: 2em;
- height: 2em;
-}
-
-.control-label {
- text-transform: capitalize;
- padding-left: 5px;
-}
-
-.control-button-group {
- margin-left: 5px;
-}
-
-.control-button-group * {
- border-radius: 2px !important;
- margin: 0px 2px 0px 0px;
-}
-
-.control-button-group *:first-child {
- border-radius: 6px 2px 2px 6px !important;
-}
-
-.control-button-group *:last-child {
- border-radius: 2px 6px 6px 2px !important;
- margin: 0px;
-}
-
-.controller-card {
- border-radius: 10px;
- background-color: #252526;
- color: #a7a7a7;
-}
-
-.headset-card {
- border-radius: 10px 10px 0 0;
- background-color: #252526;
- color: #a7a7a7;
- margin: 5px 5px 0px 5px;
-}
-
-.headset-card .card-body,
-.pose-card .card-body {
- padding: 5px 0px 5px 0px;
-}
-
-.headset-card .row > *,
-.pose-card .row > * {
- padding-right: 0px;
-}
-
-.controller-panel {
- width: 100%;
- padding: 5px;
-}
-
-.controller-panel .row {
- margin: 4px 0px !important;
-}
-
-.controller-panel .col {
- padding: 0;
-}
-
-.controller-panel .col:first-child {
- margin-right: 2.5px;
-}
-
-.controller-panel .col:last-child {
- margin-left: 2.5px;
-}
-
-.controller-card .card-header {
- border-bottom-width: 2px;
- padding: 2px 5px;
-}
-
-.controller-card .card-body {
- padding: 0 0 1px 0;
-}
-
-.joystick-panel {
- width: 80px;
- position: relative;
- top: 30px;
- left: 0px;
-}
-
-#render-component {
- padding-left: 5px;
- padding-right: 5px;
- width: 100%;
-}
-
-#transform-component {
- position: absolute;
- padding: 0;
- pointer-events: none;
-}
-
-#transform-component button {
- border: none;
- pointer-events: all;
-}
-
-#transform-component > button {
- background-color: #252526;
- color: white;
- opacity: 50%;
- height: 18px;
- padding: 0px;
- width: 50px;
- border-radius: 4px;
- margin: 2px 0px 1px 2px;
-}
-
-#transform-component button:hover {
- opacity: 1;
-}
-
-#transform-component button.active {
- font-weight: bold;
- opacity: 1;
-}
-
-#transform-component input {
- pointer-events: all;
-}
-
-.transform-card {
- color: white;
- margin: 2px !important;
- width: 155px;
- font-size: 10px;
- line-height: 1.2em;
-}
-
-.transform-icon {
- background-color: #252526;
- opacity: 50%;
- border-radius: 6px 2px 2px 6px;
-}
-
-.transform-body {
- background-color: #252526;
- width: 127px;
- opacity: 50%;
- color: white;
- border-radius: 2px 6px 6px 2px;
- padding: 0px;
- margin-left: 2px;
-}
-
-.transform-body .row {
- margin: 1%;
-}
-
-.value {
- font-family: 'Roboto Mono', monospace;
- padding: 0;
-}
-
-.value > input[type='number'] {
- border: none;
- background-color: black;
- border-radius: 5px;
- width: 40px;
- -webkit-appearance: none;
- -moz-appearance: textfield;
- appearance: textfield;
- margin-left: 2px;
- color: white;
- text-align: center;
-}
-
-.value > input[type='number']:first-child {
- margin-left: 0;
-}
-
-.value > input[type='number']:focus {
- outline: none;
-}
-
-.value-changed {
- color: #679bec;
-}
-
-.form-range {
- max-width: 50px;
- vertical-align: middle;
-}
-
-.form-range:hover {
- background-color: #3b3b3c;
-}
-
-.form-range::-webkit-slider-runnable-track {
- height: 1.4em;
- border-radius: 5px;
-}
-
-.form-range::-webkit-slider-thumb {
- -webkit-appearance: none; /* Override default look */
- appearance: none;
- margin-top: -0.35em; /* Centers thumb on the track */
- border-radius: 2px;
- height: 2.1em;
- width: 8px;
-}
-
-.pose-left-full {
- width: 110px;
-}
-
-.pose-right-full {
- width: 85px;
- margin-left: 3px;
-}
-
-.pose-left-long {
- width: 78px;
- border-radius: 6px 2px 2px 6px;
-}
-
-.pose-left-short {
- width: 30px;
- margin-left: 2px;
- border-radius: 2px 6px 6px 2px;
-}
-
-.pose-card {
- border-radius: 0 0 10px 10px;
- background-color: #252526;
- color: #a7a7a7;
- margin: 0px 5px 0px 5px;
-}
-
-#mask {
- background-color: #3b3b3c;
- color: #e4e6eb;
- position: absolute;
- width: 100%;
- height: 100%;
- z-index: 1000;
-}
-
-.prompt {
- width: calc(100% - 10px);
- height: calc(100% - 10px);
- display: flex;
- justify-content: center;
- align-items: center;
- margin: 5px;
- border-radius: 3px;
- border-width: 3px;
- border-style: dashed;
-}
-
-.alternative-control-card {
- border-radius: 10px;
- background-color: #252526;
- color: #a7a7a7;
-}
-
-.alternative-control-card .card-body {
- padding: 5px 0px 5px 0px;
-}
-
-.resize-warning-card {
- background-color: #252526;
- color: #a7a7a7;
- align-items: center;
- margin: 5px 5px 0px 5px;
- border: 3px dashed;
- border-bottom: none;
- border-radius: 10px 10px 0px 0px;
- height: 100%;
- justify-content: center;
-}
-
-.session-progress-bar {
- display: inline-block;
- width: calc(100% - 32px - 6em);
- margin: 10px 5px 0px 5px;
-}
-
-#session-file {
- margin: 8px 0px 0px 16px;
-}
-
-#save-default-pose {
- margin-left: 10px;
-}
-
-.playback-action-button {
- height: 2.1em;
- width: 2.1em;
- border-radius: 6px;
- border-style: none;
- padding: 4px 6px 4px 6px;
- font-size: small;
- background-color: #3b3b3c;
- color: #e4e6eb;
- text-align: center;
-}
-
-#playback-control {
- margin: 5px 0px 0px 16px;
-}
-
-#room-dimension-settings span {
- height: 20px;
- padding-left: 5px;
-}
-
-#room-dimension-settings input {
- width: 35px;
- height: 15px;
- padding: 1px 5px;
- position: absolute;
- border-radius: 8px;
- border: 0px;
- left: 100px;
- background-color: #a7a7a7;
-}
-
-#room-dimension-settings .row {
- height: 15px;
-}
-
-.controller-card .form-select {
- width: 105px;
-}
-
-.controller-card .form-select:focus {
- color: #fff;
- background-color: #3b3b3c;
-}
-
-.controller-card .card-header .title {
- padding-bottom: auto;
-}
-
-.controller-card .card-body .row {
- margin: 2%;
-}
-
-.hand-card .form-range {
- max-width: 78px;
-}
-
-.component-container.row {
- width: calc(100% - 10px);
-}
-
-.drop-down-container {
- background-color: #3b3b3c;
- position: absolute;
- width: 126px;
- height: auto;
- top: 41px;
- right: 5px;
- border-radius: 10px 2px 10px 10px;
- z-index: 1;
- padding: 5px;
-}
-
-.drop-down-container button {
- width: 100%;
- margin: 0;
- text-align: start;
-}
-
-.mesh-menu {
- margin: 5px;
- width: 141px;
-}
-
-.mesh-menu > div {
- margin-bottom: 2px;
-}
-
-input::-webkit-outer-spin-button,
-input::-webkit-inner-spin-button {
- -webkit-appearance: none;
- margin: 0;
-}
-
-.mesh-menu input[type='number'],
-.mesh-menu select,
-.mesh-menu button {
- height: 18px;
- border: none;
- border-radius: 2px;
- margin-right: 2px;
- pointer-events: all;
- text-align: center;
- background-color: #252526;
- color: white;
- opacity: 50%;
- vertical-align: middle;
-}
-
-.mesh-menu input[type='number'],
-.mesh-menu button {
- appearance: none;
- -webkit-appearance: none;
- width: 40px;
- padding: 0;
-}
-
-.mesh-menu select {
- width: 82px;
-}
-
-.semantic-label {
- position: absolute;
- color: white;
- pointer-events: none;
- z-index: 20;
- width: 50px;
- height: 20px;
- text-align: center;
- margin-left: -25px;
- margin-top: -10px;
-}
diff --git a/package.json b/package.json
index 3392534..2301aad 100755
--- a/package.json
+++ b/package.json
@@ -32,9 +32,7 @@
"koa": "^2.14.2",
"koa-bodyparser": "^4.4.0",
"koa-router": "^12.0.0",
- "localforage": "^1.10.0",
- "puppeteer": "^19.6.3",
- "webxr-polyfill": "github:felixtrz/webxr-polyfill#81d2db4f01b518f2c42b74a90973dac095515e9f"
+ "puppeteer": "^19.6.3"
},
"license": "ISC",
"devDependencies": {
diff --git a/tests/xr.test.ts b/tests/xr.test.ts
deleted file mode 100644
index 2f1956e..0000000
--- a/tests/xr.test.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-import { mockEngineRenderer } from '@ir-engine/spatial/tests/util/MockEngineRenderer'
-import { createEngine, destroyEngine } from '@ir-engine/ecs/src/Engine'
-import {
- destroySpatialEngine,
- destroySpatialViewer,
- initializeSpatialEngine,
- initializeSpatialViewer
-} from '@ir-engine/spatial/src/initializeEngine'
-import { requestXRSession } from '@ir-engine/spatial/src/xr/XRSessionFunctions'
-import { describe, it, beforeEach, afterEach, assert, beforeAll } from 'vitest'
-import { WebXREventDispatcher } from '../webxr-emulator/WebXREventDispatcher'
-import { POLYFILL_ACTIONS } from '../webxr-emulator/actions'
-import { getMutableState, getState } from '@ir-engine/hyperflux'
-import { XRState } from '@ir-engine/spatial/src/xr/XRState'
-import { EngineState } from '@ir-engine/spatial/src/EngineState'
-import { RendererComponent } from '@ir-engine/spatial/src/renderer/WebGLRendererSystem'
-import { ECSState, Timer, setComponent } from '@ir-engine/ecs'
-
-const deviceDefinition = {
- id: 'Oculus Quest',
- name: 'Oculus Quest',
- modes: ['inline', 'immersive-vr'],
- headset: {
- hasPosition: true,
- hasRotation: true
- },
- controllers: [
- {
- id: 'Oculus Touch (Right)',
- buttonNum: 7,
- primaryButtonIndex: 0,
- primarySqueezeButtonIndex: 1,
- hasPosition: true,
- hasRotation: true,
- hasSqueezeButton: true,
- isComplex: true
- },
- {
- id: 'Oculus Touch (Left)',
- buttonNum: 7,
- primaryButtonIndex: 0,
- primarySqueezeButtonIndex: 1,
- hasPosition: true,
- hasRotation: true,
- hasSqueezeButton: true,
- isComplex: true
- }
- ]
-}
-
-describe.skip('WebXR', () => {
- beforeAll(async () => {
- const { CustomWebXRPolyfill } = await import('../webxr-emulator/CustomWebXRPolyfill')
- new CustomWebXRPolyfill()
- })
-
- beforeEach(async () => {
- createEngine()
- initializeSpatialEngine()
- initializeSpatialViewer()
-
- const timer = Timer((_time, xrFrame) => {
- getMutableState(XRState).xrFrame.set(xrFrame)
- // executeSystems(time)
- getMutableState(XRState).xrFrame.set(null)
- })
- getMutableState(ECSState).timer.set(timer)
-
- const { originEntity, localFloorEntity, viewerEntity } = getState(EngineState)
- mockEngineRenderer(viewerEntity)
- setComponent(viewerEntity, RendererComponent, { scenes: [originEntity, localFloorEntity, viewerEntity] })
- })
-
- afterEach(async () => {
- destroySpatialViewer()
- destroySpatialEngine()
- return await destroyEngine()
- })
-
- it('can define and initialize a device', async () => {
- WebXREventDispatcher.instance.dispatchEvent({
- type: POLYFILL_ACTIONS.DEVICE_INIT,
- detail: { stereoEffect: false, deviceDefinition }
- })
-
- await requestXRSession()
-
- assert(getState(XRState).session)
- })
-})
diff --git a/webxr-emulator/CustomWebXRPolyfill.js b/webxr-emulator/CustomWebXRPolyfill.js
deleted file mode 100644
index f1ffbbc..0000000
--- a/webxr-emulator/CustomWebXRPolyfill.js
+++ /dev/null
@@ -1,621 +0,0 @@
-import {
- XRAnchor,
- XRAnchorSet,
- deletePersistentAnchor,
- restorePersistentAnchors,
-} from './api/XRAnchor';
-import XRFrame, {
- PRIVATE as XRFRAME_PRIVATE,
-} from 'webxr-polyfill/src/api/XRFrame';
-import XRSession, {
- PRIVATE as XRSESSION_PRIVATE,
-} from 'webxr-polyfill/src/api/XRSession';
-import { mat4, quat, vec3 } from 'gl-matrix';
-
-import API from 'webxr-polyfill/src/api/index';
-import EX_API from './api/index';
-import EmulatedXRDevice from './EmulatedXRDevice';
-import { HAND_POSES } from './api/handPose';
-import { POLYFILL_ACTIONS } from './actions';
-import WebXRPolyfill from 'webxr-polyfill/src/WebXRPolyfill';
-import { PRIVATE as XRHAND_PRIVATE } from './api/XRHand';
-import XRHitTestResult from './api/XRHitTestResult';
-import XRHitTestSource from './api/XRHitTestSource';
-import { PRIVATE as XRJOINTSPACE_PRIVATE } from './api/XRJointSpace';
-import { XRJointPose } from './api/XRJointPose';
-import { XRMeshSet } from './api/XRMesh';
-import { XRPlaneSet } from './api/XRPlane';
-import XRReferenceSpace from 'webxr-polyfill/src/api/XRReferenceSpace';
-import XRRigidTransform from 'webxr-polyfill/src/api/XRRigidTransform';
-import XRSpace from 'webxr-polyfill/src/api/XRSpace';
-import XRSystem from 'webxr-polyfill/src/api/XRSystem';
-import XRTransientInputHitTestResult from './api/XRTransientInputHitTestResult';
-import XRTransientInputHitTestSource from './api/XRTransientInputHitTestSource';
-import { XR_COMPATIBLE } from 'webxr-polyfill/src/constants';
-import { WebXREventDispatcher } from './WebXREventDispatcher';
-
-const handMatrixInvert = [1, -1, -1, 0, -1, 1, 1, 0, -1, 1, 1, 0, -1, 1, 1, 1];
-const getJointMatrix = (handPose, jointName, handedness) => {
- const rawTransform = [...handPose[jointName].transform];
- if (handedness == 'right') {
- for (let i = 0; i < 16; i++) {
- rawTransform[i] = rawTransform[i] * handMatrixInvert[i];
- }
- }
- return mat4.fromValues(...rawTransform);
-};
-const interpolateMatrix = (fromMatrix, toMatrix, alpha) => {
- const fromPosition = vec3.create();
- mat4.getTranslation(fromPosition, fromMatrix);
- const fromQuaternion = quat.create();
- mat4.getRotation(fromQuaternion, fromMatrix);
- const fromScale = vec3.create();
- mat4.getScaling(fromScale, fromMatrix);
- const toPosition = vec3.create();
- mat4.getTranslation(toPosition, toMatrix);
- const toQuaternion = quat.create();
- mat4.getRotation(toQuaternion, toMatrix);
- const toScale = vec3.create();
- mat4.getScaling(toScale, toMatrix);
- const interpolatedPosition = vec3.create();
- vec3.lerp(interpolatedPosition, fromPosition, toPosition, alpha);
- const interpolatedQuaternion = quat.create();
- quat.slerp(interpolatedQuaternion, fromQuaternion, toQuaternion, alpha);
- const interpolatedScale = vec3.create();
- vec3.lerp(interpolatedScale, fromScale, toScale, alpha);
- const out = mat4.create();
- mat4.fromRotationTranslationScale(
- out,
- interpolatedQuaternion,
- interpolatedPosition,
- interpolatedScale,
- );
- return out;
-};
-
-export class CustomWebXRPolyfill extends WebXRPolyfill {
- constructor() {
- super();
-
- // Note: Experimental.
- // Override some XR APIs to track active immersive session to
- // enable to exit immersive by the extension.
- // Exiting without user gesture in the page might violate security policy
- // so there might be a chance that we remove this feature at some point.
-
- let activeImmersiveSession = null;
- const originalRequestSession = XRSystem.prototype.requestSession;
- XRSystem.prototype.requestSession = function (mode, enabledFeatures = {}) {
- return originalRequestSession
- .call(this, mode, enabledFeatures)
- .then((session) => {
- if (mode === 'immersive-vr' || mode === 'immersive-ar') {
- activeImmersiveSession = session;
-
- session.interactionMode = 'world-space'
-
- // DOM-Overlay API
- const optionalFeatures = enabledFeatures.optionalFeatures;
- const domOverlay = enabledFeatures.domOverlay;
- if (
- optionalFeatures &&
- optionalFeatures.includes('dom-overlay') &&
- domOverlay &&
- domOverlay.root
- ) {
- const device = session[XRSESSION_PRIVATE].device;
- device.setDomOverlayRoot(domOverlay.root);
- session.domOverlayState = { type: 'screen' };
- }
-
- restorePersistentAnchors(session);
- }
- return session;
- });
- };
-
- const originalEnd = XRSession.prototype.end;
- XRSession.prototype.end = function () {
- return originalEnd.call(this).then(() => {
- if (activeImmersiveSession === this) {
- activeImmersiveSession = null;
- }
- });
- };
-
- // add event listener for onreset event, but do nothing since we cannot re-center in emulator
- XRReferenceSpace.prototype.addEventListener = () => {
- // do nothing
- };
-
- WebXREventDispatcher.instance.addEventListener(POLYFILL_ACTIONS.EXIT_IMMERSIVE, () => {
- if (activeImmersiveSession && !activeImmersiveSession.ended) {
- activeImmersiveSession.end().then(() => {
- activeImmersiveSession = null;
- });
- }
- });
-
- XRSession.prototype.addTrackedAnchor = function (anchor) {
- if (this.trackedAnchors == null) this.trackedAnchors = new Set();
- this.trackedAnchors.add(anchor);
- };
-
- XRSession.prototype.getTrackedAnchors = function () {
- return this.trackedAnchors;
- };
-
- XRSession.prototype.hasTrackedAnchor = function (anchor) {
- return this.trackedAnchors.has(anchor);
- };
-
- XRSession.prototype.deleteTrackedAnchor = function (anchor) {
- if (this.trackedAnchors != null) {
- this.trackedAnchors.delete(anchor);
- }
- };
-
- XRSession.prototype.addPersistentAnchor = function (uuid, anchor) {
- if (this.persistentAnchorsMap == null) {
- this.persistentAnchorsMap = new Map();
- }
- this.persistentAnchorsMap.set(uuid, anchor);
- };
-
- XRSession.prototype.getPersistentAnchorUUID = function (anchor) {
- if (this.persistentAnchorsMap != null) {
- let uuid;
- this.persistentAnchorsMap.forEach((value, key) => {
- if (value === anchor) {
- uuid = key;
- }
- });
- return uuid;
- }
- };
-
- Object.defineProperty(XRSession.prototype, 'persistentAnchors', {
- get: function () {
- const device = this[XRSESSION_PRIVATE].device;
- const session = device.sessions.get(this[XRSESSION_PRIVATE].id);
- if (!session.enabledFeatures.has('anchors')) {
- return [];
- } else if (this.persistentAnchorsMap != null) {
- return Object.freeze(Array.from(this.persistentAnchorsMap.keys()));
- } else {
- return [];
- }
- },
- });
-
- XRSession.prototype.restorePersistentAnchor = async function (uuid) {
- const device = this[XRSESSION_PRIVATE].device;
- const session = device.sessions.get(this[XRSESSION_PRIVATE].id);
- if (!session.enabledFeatures.has('anchors')) {
- return Promise.reject(
- new DOMException(
- "Failed to execute 'restorePersistentAnchor' on 'XRFrame': Anchors feature is not supported by the session.",
- 'NotSupportedError',
- ),
- );
- }
- if (!this.persistentAnchors.includes(uuid)) {
- throw new DOMException(
- 'specified persistent anchor cannot be found',
- 'InvalidStateError',
- );
- }
- if (this[XRSESSION_PRIVATE].ended) {
- throw new DOMException('session ended', 'InvalidStateError');
- }
-
- const anchor = this.persistentAnchorsMap.get(uuid);
- this.addTrackedAnchor(anchor);
- this.addPersistentAnchor(uuid, anchor);
- return anchor;
- };
-
- XRSession.prototype.deletePersistentAnchor = async function (uuid) {
- const device = this[XRSESSION_PRIVATE].device;
- const session = device.sessions.get(this[XRSESSION_PRIVATE].id);
- if (!session.enabledFeatures.has('anchors')) {
- return Promise.reject(
- new DOMException(
- "Failed to execute 'deletePersistentAnchor' on 'XRFrame': Anchors feature is not supported by the session.",
- 'NotSupportedError',
- ),
- );
- }
- if (!this.persistentAnchors.includes(uuid)) {
- throw new DOMException(
- 'specified persistent anchor cannot be found',
- 'InvalidStateError',
- );
- }
-
- const anchor = this.persistentAnchorsMap.get(uuid);
- this.deleteTrackedAnchor(anchor);
- this.persistentAnchorsMap.delete(uuid);
- await deletePersistentAnchor(uuid);
- };
-
- XRSession.prototype.updateTargetFrameRate = function (frameRate) {
- console.log('now targeting', frameRate, 'fps');
- };
-
- /**
- * @param {import('webxr-polyfill/src/api/XRRigidTransform').default} pose
- * @param {import('webxr-polyfill/src/api/XRSpace').default} space
- * @see https://immersive-web.github.io/anchors/#dom-xrframe-createanchor
- */
- XRFrame.prototype.createAnchor = async function (pose, space) {
- const session = this[XRFRAME_PRIVATE].session;
- const device = this[XRFRAME_PRIVATE].device;
- const xrSession = device.sessions.get(session[XRSESSION_PRIVATE].id);
- if (!xrSession.enabledFeatures.has('anchors')) {
- return Promise.reject(
- new DOMException(
- "Failed to execute 'createAnchor' on 'XRFrame': Anchors feature is not supported by the session.",
- 'NotSupportedError',
- ),
- );
- }
- const localRefSpace = await session.requestReferenceSpace('local');
-
- let currentSpaceTransform = null;
- if (
- space._specialType === 'target-ray' ||
- space._specialType === 'grip'
- ) {
- currentSpaceTransform = device.getInputPose(
- space._inputSource,
- localRefSpace,
- space._specialType,
- ).transform;
- } else {
- space._ensurePoseUpdated(device, this[XRFRAME_PRIVATE].id);
- localRefSpace._ensurePoseUpdated(device, this[XRFRAME_PRIVATE].id);
- currentSpaceTransform = localRefSpace._getSpaceRelativeTransform(space);
- }
- if (!currentSpaceTransform) throw 'error creating anchor';
-
- const currentSpaceBaseSpaceMatrix = new Float32Array(16);
- mat4.multiply(
- currentSpaceBaseSpaceMatrix,
- localRefSpace._baseMatrix,
- currentSpaceTransform.matrix,
- );
- const anchorSpaceBaseSpaceMatrix = new Float32Array(16);
- mat4.multiply(
- anchorSpaceBaseSpaceMatrix,
- currentSpaceBaseSpaceMatrix,
- pose.matrix,
- );
- const anchorSpace = new XRSpace();
- anchorSpace._baseMatrix = anchorSpaceBaseSpaceMatrix;
- const anchor = new XRAnchor(session, anchorSpace);
- session.addTrackedAnchor(anchor);
- return anchor;
- };
-
- Object.defineProperty(XRFrame.prototype, 'trackedAnchors', {
- get: function () {
- const xrSession = this[XRFRAME_PRIVATE].session;
- const device = this[XRFRAME_PRIVATE].device;
- const session = device.sessions.get(xrSession[XRSESSION_PRIVATE].id);
- if (!session.enabledFeatures.has('anchors')) {
- return new XRAnchorSet();
- } else {
- return new XRAnchorSet(xrSession.getTrackedAnchors());
- }
- },
- });
-
- Object.defineProperty(XRFrame.prototype, 'detectedPlanes', {
- get: function () {
- const device = this[XRFRAME_PRIVATE].device;
- return new XRPlaneSet(device.xrScene.xrPlanes);
- },
- });
-
- Object.defineProperty(XRFrame.prototype, 'detectedMeshes', {
- get: function () {
- const device = this[XRFRAME_PRIVATE].device;
- return new XRMeshSet(device.xrScene.xrMeshes);
- },
- });
-
- XRFrame.prototype.getJointPose = function (joint, baseSpace) {
- const xrhand = joint[XRJOINTSPACE_PRIVATE].xrhand;
- const xrInputSource = xrhand[XRHAND_PRIVATE].inputSource;
- const handedness = xrInputSource.handedness;
- const device = this[XRFRAME_PRIVATE].device;
- const poseId = device.handPoseData[handedness].poseId;
- const pinchValue = device.handPoseData[handedness].pinchValue;
- const handPose = HAND_POSES[poseId];
- const pinchPose = HAND_POSES.pinch;
-
- // the joints transforms are sampled with gripSpace as the reference space
- const gripMatrix = new Float32Array(16);
- if (baseSpace == xrInputSource.gripSpace) {
- mat4.fromRotationTranslation(gripMatrix, quat.create(), vec3.create());
- } else {
- const gripPose = this.getPose(xrInputSource.gripSpace, baseSpace);
- mat4.copy(gripMatrix, gripPose.transform.matrix);
- }
-
- const jointMatrix = getJointMatrix(handPose, joint.jointName, handedness);
- const pinchMatrix = getJointMatrix(
- pinchPose,
- joint.jointName,
- handedness,
- );
- const isPinchJoint =
- joint.jointName.startsWith('thumb') ||
- joint.jointName.startsWith('index');
- const interpolatedMatrix = interpolateMatrix(
- jointMatrix,
- pinchMatrix,
- isPinchJoint ? pinchValue : 0,
- );
-
- const out = new Float32Array(16);
- mat4.multiply(out, gripMatrix, interpolatedMatrix);
- return new XRJointPose(
- new XRRigidTransform(out),
- handPose[joint.jointName].radius,
- );
- };
-
- /**
- * @param {IterableIterator} jointSpaces
- * @param {Float32Array} radii
- */
- XRFrame.prototype.fillJointRadii = function (jointSpaces, radii) {
- const spaces = Array.from(jointSpaces);
- if (spaces.length > radii.length) {
- throw new TypeError('radii array size insufficient');
- }
- spaces.forEach((jointSpace, i) => {
- const xrhand = jointSpace[XRJOINTSPACE_PRIVATE].xrhand;
- const xrInputSource = xrhand[XRHAND_PRIVATE].inputSource;
- const handedness = xrInputSource.handedness;
- const device = this[XRFRAME_PRIVATE].device;
- const poseId = device.handPoseData[handedness].poseId;
- const handPose = HAND_POSES[poseId];
- const jointName = jointSpace.jointName;
- radii[i] = handPose[jointName].radius;
- });
- return true;
- };
-
- /**
- * @param {IterableIterator} spaces
- * @param {XRSpace} baseSpace
- * @param {Float32Array} transforms
- */
- XRFrame.prototype.fillPoses = function (spaces, baseSpace, transforms) {
- const spacesArray = Array.from(spaces);
- if (transforms.length < spaces.length * 16) {
- throw new TypeError('transforms array size insufficient');
- }
- spacesArray.forEach((space, i) => {
- let pose;
- if (space.jointName) {
- pose = this.getJointPose(space, baseSpace);
- } else {
- pose = this.getPose(space, baseSpace);
- }
- for (let j = 0; j < 16; j++) {
- transforms[i * 16 + j] = pose.transform.matrix[j];
- }
- });
- return true;
- };
-
- // Extending XRSession and XRFrame for AR hitting test API.
-
- XRSession.prototype.requestHitTestSource = function (options) {
- const device = this[XRSESSION_PRIVATE].device;
- const session = device.sessions.get(this[XRSESSION_PRIVATE].id);
- if (!session.enabledFeatures.has('hit-test')) {
- return Promise.reject(
- new DOMException(
- 'hit-test feature not requested or not supported',
- 'NotSupportedError',
- ),
- );
- }
- const source = new XRHitTestSource(this, options);
- device.addHitTestSource(source);
- return Promise.resolve(source);
- };
-
- XRSession.prototype.requestHitTestSourceForTransientInput = function (
- options,
- ) {
- const device = this[XRSESSION_PRIVATE].device;
- const session = device.sessions.get(this[XRSESSION_PRIVATE].id);
- if (!session.enabledFeatures.has('hit-test')) {
- return Promise.reject(
- new DOMException(
- 'hit-test feature not requested or not supported',
- 'NotSupportedError',
- ),
- );
- }
- const source = new XRTransientInputHitTestSource(this, options);
- device.addHitTestSourceForTransientInput(source);
- return Promise.resolve(source);
- };
-
- Object.defineProperty(XRSession.prototype, 'enabledFeatures', {
- get: function () {
- const device = this[XRSESSION_PRIVATE].device;
- const session = device.sessions.get(this[XRSESSION_PRIVATE].id);
- return Object.freeze(Array.from(session.enabledFeatures));
- },
- });
-
- Object.defineProperty(XRSession.prototype, 'inputSources', {
- get: function () {
- const device = this[XRSESSION_PRIVATE].device;
- const inputSources = device.getInputSources();
- const session = device.sessions.get(this[XRSESSION_PRIVATE].id);
- if (!session.enabledFeatures.has('hand-tracking')) {
- return inputSources.filter((inputSource) => inputSource.hand == null);
- }
- return inputSources;
- },
- });
-
- XRFrame.prototype.getHitTestResults = function (hitTestSource) {
- const device = this.session[XRSESSION_PRIVATE].device;
- const hitTestResults = device.getHitTestResults(hitTestSource);
- const results = [];
- for (const matrix of hitTestResults) {
- results.push(new XRHitTestResult(this, new XRRigidTransform(matrix)));
- }
- return results;
- };
-
- XRFrame.prototype.getHitTestResultsForTransientInput = function (
- hitTestSource,
- ) {
- const device = this.session[XRSESSION_PRIVATE].device;
- const hitTestResults =
- device.getHitTestResultsForTransientInput(hitTestSource);
- if (hitTestResults.length === 0) {
- return [];
- }
- const results = [];
- for (const matrix of hitTestResults) {
- results.push(new XRHitTestResult(this, new XRRigidTransform(matrix)));
- }
- const inputSource = device.getInputSources()[0];
- return [new XRTransientInputHitTestResult(this, results, inputSource)];
- };
-
- //
-
- if (this.nativeWebXR) {
- // Note: Even if native WebXR API is available the extension overrides
- // it with WebXR polyfill because the extension doesn't work with
- // the native one (yet).
- overrideAPI(this.global);
- this.injected = true;
- this._patchNavigatorXR();
- } else {
- installEX_API(this.global);
- // Note: WebXR API polyfill can be overridden by native WebXR API on the latest Chrome 78
- // after the extension is loaded but before loading page is completed
- // if the native WebXR API is disabled via chrome://flags and the page includes
- // WebXR origin trial.
- // Here is a workaround. Check if XR class is native code when node is appended or
- // the page is loaded. If it detects, override WebXR API with the polyfill.
- // @TODO: Remove this workaround if the major browser officially support native WebXR API
- let overridden = false;
- const overrideIfNeeded = () => {
- if (overridden) {
- return false;
- }
- if (isNativeFunction(this.global.XRSystem)) {
- overrideAPI(this.global);
- overridden = true;
- return true;
- }
- return false;
- };
- const observer = new MutationObserver((list) => {
- for (const record of list) {
- for (const node of record.addedNodes) {
- if (node.localName === 'script' && overrideIfNeeded()) {
- observer.disconnect();
- break;
- }
- }
- if (overridden) {
- break;
- }
- }
- });
- observer.observe(document, { subtree: true, childList: true });
- const onLoad = (_event) => {
- if (!overridden) {
- observer.disconnect();
- overrideIfNeeded();
- }
- document.removeEventListener('DOMContentLoaded', onLoad);
- };
- document.addEventListener('DOMContentLoaded', onLoad);
- }
- }
-
- _patchNavigatorXR() {
- const devicePromise = requestXRDevice(this.global);
- this.xr = new XRSystem(devicePromise);
- Object.defineProperty(this.global.navigator, 'xr', {
- value: this.xr,
- configurable: true,
- });
- }
-}
-
-const requestXRDevice = async (global, _config) => {
- // resolve when receiving configuration parameters from content-script as an event
- return new Promise((resolve, _reject) => {
- const callback = (event) => {
- WebXREventDispatcher.instance.removeEventListener(POLYFILL_ACTIONS.DEVICE_INIT, callback);
- resolve(
- new EmulatedXRDevice(
- global,
- Object.assign({}, event.detail.deviceDefinition, {
- stereoEffect: event.detail.stereoEffect,
- }),
- ),
- );
- };
- WebXREventDispatcher.instance.addEventListener(POLYFILL_ACTIONS.DEVICE_INIT, callback, false);
- });
-};
-
-// Easy native function detection.
-const isNativeFunction = (func) => {
- return /\[native code\]/i.test(func.toString());
-};
-
-const overrideAPI = (global) => {
- console.log(
- '[Immersive Web Emulator] native WebXR API successfully overridden',
- );
- for (const className in API) {
- global[className] = API[className];
- }
- installEX_API(global);
-
- // Since (desktop) Chrome 88 WebGL(2)RenderingContext.makeXRCompatible() seems
- // to start to reject if no immersive XR device is plugged in.
- // So we need to override them, too. Otherwise JS engines/apps including
- // "await context.makeXRCompatible();" won't work with the extension.
- // See https://github.com/MozillaReality/WebXR-emulator-extension/issues/266
- if (typeof WebGLRenderingContext !== 'undefined') {
- overrideMakeXRCompatible(WebGLRenderingContext);
- }
- if (typeof WebGL2RenderingContext !== 'undefined') {
- overrideMakeXRCompatible(WebGL2RenderingContext);
- }
-};
-
-const installEX_API = (global) => {
- for (const className in EX_API) {
- global[className] = EX_API[className];
- }
-};
-
-const overrideMakeXRCompatible = (Context) => {
- Context.prototype.makeXRCompatible = function () {
- this[XR_COMPATIBLE] = true;
- // This is all fake, so just resolve immediately.
- return Promise.resolve();
- };
-};
diff --git a/webxr-emulator/EmulatedXRDevice.js b/webxr-emulator/EmulatedXRDevice.js
deleted file mode 100644
index f1ed7d3..0000000
--- a/webxr-emulator/EmulatedXRDevice.js
+++ /dev/null
@@ -1,1155 +0,0 @@
-import { CLIENT_ACTIONS, POLYFILL_ACTIONS } from './actions';
-import { mat4, quat, vec3 } from 'gl-matrix';
-
-import GamepadMappings from 'webxr-polyfill/src/devices/GamepadMappings';
-import GamepadXRInputSource from './api/XRGamepadInput';
-import HandXRInputSource from './api/XRHandInput';
-import XRDevice from 'webxr-polyfill/src/devices/XRDevice';
-import { PRIVATE as XRINPUTSOURCE_PRIVATE } from './api/XRInputSource';
-import { PRIVATE as XRSESSION_PRIVATE } from 'webxr-polyfill/src/api/XRSession';
-import XRScene from './XRScene';
-import XRTransientInputHitTestSource from './api/XRTransientInputHitTestSource';
-import { WebXREventDispatcher } from './WebXREventDispatcher';
-import { isClient } from '@ir-engine/common/src/utils/getEnvironment';
-
-const DEFAULT_MODES = ['inline'];
-
-// @TODO: This value should shared with panel.js?
-const DEFAULT_HEADSET_POSITION = [0, 1.6, 0];
-
-// 10000 is for AR Scene
-const APP_CANVAS_Z_INDEX = '9999';
-const AR_CANVAS_Z_INDEX = '9998';
-const DOM_OVERLAY_Z_INDEX = '10001';
-
-// For AR
-const DEFAULT_RESOLUTION = { width: 1024, height: 2048 };
-const DEFAULT_DEVICE_SIZE = { width: 0.05, height: 0.1, depth: 0.005 };
-
-// @TODO: Duplicated with content-scripts.js. Move to somewhere common place?
-const dispatchCustomEvent = (type, detail) => {
- WebXREventDispatcher.instance.dispatchEvent(
- new CustomEvent(type, {
- detail:
- // eslint-disable-next-line no-undef
- typeof cloneInto !== 'undefined' ? cloneInto(detail, window) : detail,
- }),
- );
-};
-
-export default class EmulatedXRDevice extends XRDevice {
- // @TODO: write config parameter comment
-
- constructor(global, config = {}) {
- super(global);
-
- this.sessions = new Map();
-
- this.modes = config.modes || DEFAULT_MODES;
- this.features = config.features || [];
- this.environmentBlendMode = config.environmentBlendMode || 'opaque';
- this.xrScene = new XRScene();
-
- // headset
- this.position = vec3.copy(vec3.create(), DEFAULT_HEADSET_POSITION);
- this.quaternion = quat.create();
- this.scale = vec3.fromValues(1, 1, 1);
- this.matrix = mat4.create();
- this.projectionMatrix = mat4.create();
- this.leftProjectionMatrix = mat4.create();
- this.rightProjectionMatrix = mat4.create();
- this.viewMatrix = mat4.create();
- this.leftViewMatrix = mat4.create();
- this.rightViewMatrix = mat4.create();
-
- this.handMode = true;
- this.handPoseData = {
- left: { poseId: 'relaxed', pinchValue: 0, prevPinchValue: 0 },
- right: { poseId: 'relaxed', pinchValue: 0, prevPinchValue: 0 },
- };
-
- // controllers
- this.gamepads = [];
- this.gamepadInputSources = [];
-
- // hands
- this.handGamepads = [];
- this.handInputSources = [];
-
- // other configurations
- this.stereoEffectEnabled =
- config.stereoEffect !== undefined ? config.stereoEffect : true;
-
- // @TODO: Edit this comment
- // For case where baseLayer's canvas isn't in document.body
-
- const createCanvasContainer = (zIndex) => {
- const canvasContainer = document.createElement('div');
- canvasContainer.style.position = 'fixed';
- canvasContainer.style.width = '100%';
- canvasContainer.style.height = '100%';
- canvasContainer.style.top = '0';
- canvasContainer.style.left = '0';
- canvasContainer.style.zIndex = zIndex;
- return canvasContainer;
- };
-
- if (isClient) {
- this.appCanvasContainer = createCanvasContainer(APP_CANVAS_Z_INDEX);
- // console.log(this.appCanvasContainer);
- this.arCanvasContainer = createCanvasContainer(AR_CANVAS_Z_INDEX);
- }
-
- this.originalCanvasParams = {
- parentElement: null,
- width: 0,
- height: 0,
- };
-
- // For DOM overlay API
-
- this.domOverlayRoot = null;
-
- // For AR
-
- // Assuming a device supports at most either one VR or AR
- this.resolution =
- config.resolution !== undefined ? config.resolution : DEFAULT_RESOLUTION;
- this.deviceSize =
- config.size !== undefined ? config.size : DEFAULT_DEVICE_SIZE;
- this.touched = false;
- this.isPointerAndTabledCloseEnough = false; // UGH... @TODO: Rename
-
- this.hitTestSources = [];
- this.hitTestResults = new Map();
-
- this.hitTestSourcesForTransientInput = [];
- this.hitTestResultsForTransientInput = new Map();
-
- //
- this._initializeControllers(config);
- this._initializeHands();
- this._setupEventListeners();
- }
-
- onBaseLayerSet(sessionId, layer) {
- const session = this.sessions.get(sessionId);
-
- // Remove old canvas first
- // if (session.immersive && session.baseLayer) {
- // this._removeBaseLayerCanvasFromDiv(sessionId);
- // }
-
- session.baseLayer = layer;
- // if (session.immersive && session.baseLayer) {
- // this._appendBaseLayerCanvasToDiv(sessionId);
- // }
- }
-
- isSessionSupported(mode) {
- return this.modes.includes(mode);
- }
-
- isFeatureSupported(featureDescriptor) {
- if (this.features.includes(featureDescriptor)) {
- return true;
- }
- switch (featureDescriptor) {
- case 'viewer':
- return true;
- case 'local':
- return true;
- case 'local-floor':
- return true;
- case 'bounded-floor':
- return false;
- case 'unbounded':
- return false;
- case 'dom-overlay':
- return true;
- case 'anchors':
- return true;
- case 'plane-detection':
- return true;
- case 'hit-test':
- return true;
- case 'high-fixed-foveation-level':
- console.warn(
- 'The high-fixed-foveation-level feature is non-standard and deprecated. Refer to the documentation at https://immersive-web.github.io/layers/#dom-xrprojectionlayer-fixedfoveation for the standard way to adjust fixed foveation level.',
- );
- return true;
- case 'hand-tracking':
- return true;
- case 'mesh-detection':
- return true;
- default:
- return false; // @TODO: Throw an error?
- }
- }
-
- async requestSession(mode, enabledFeatures) {
- if (!this.isSessionSupported(mode)) {
- return Promise.reject();
- }
- const session = new Session(mode, enabledFeatures);
- this.sessions.set(session.id, session);
- if (mode === 'immersive-ar') {
- // document.body.appendChild(this.arCanvasContainer);
- // this.xrScene.inject(this.arCanvasContainer);
- }
- if (session.immersive) {
- this.dispatchEvent('@@webxr-polyfill/vr-present-start', session.id);
- this._notifyEnterImmersive();
- }
- return Promise.resolve(session.id);
- }
-
- requestAnimationFrame(callback) {
- return this.global.requestAnimationFrame(callback);
- }
-
- cancelAnimationFrame(handle) {
- this.global.cancelAnimationFrame(handle);
- }
-
- onFrameStart(sessionId, renderState) {
- const session = this.sessions.get(sessionId);
- // guaranteed by the caller that session.baseLayer is not null
- const context = session.baseLayer.context;
- const canvas = context.canvas;
- const near = renderState.depthNear;
- const far = renderState.depthFar;
- const width = canvas.width;
- const height = canvas.height;
-
- // If session is not an inline session, XRWebGLLayer's composition disabled boolean
- // should be false and then framebuffer should be marked as opaque.
- // The buffers attached to an opaque framebuffer must be cleared prior to the
- // processing of each XR animation frame.
- if (session.immersive) {
- const currentClearColor = context.getParameter(context.COLOR_CLEAR_VALUE);
- const currentClearDepth = context.getParameter(context.DEPTH_CLEAR_VALUE);
- const currentClearStencil = context.getParameter(
- context.STENCIL_CLEAR_VALUE,
- );
- context.clearColor(0.0, 0.0, 0.0, 0.0);
- context.clearDepth(1, 0);
- context.clearStencil(0.0);
- context.clear(
- context.DEPTH_BUFFER_BIT |
- context.COLOR_BUFFER_BIT |
- context.STENCIL_BUFFER_BIT,
- );
- context.clearColor(
- currentClearColor[0],
- currentClearColor[1],
- currentClearColor[2],
- currentClearColor[3],
- );
- context.clearDepth(currentClearDepth);
- context.clearStencil(currentClearStencil);
- }
-
- this.gamepads.forEach((gamepad) => {
- gamepad.connected = session.immersive;
- });
-
- if (session.vr || (session.ar && session.immersive)) {
- // @TODO: proper FOV
- const aspect = (width * (this.stereoEffectEnabled ? 0.5 : 1.0)) / height;
- mat4.perspective(
- this.leftProjectionMatrix,
- Math.PI / 2,
- aspect,
- near,
- far,
- );
- mat4.perspective(
- this.rightProjectionMatrix,
- Math.PI / 2,
- aspect,
- near,
- far,
- );
- } else if (session.ar) {
- // @TODO: support mobile AR
- // @TODO: proper FOV
- const aspect = this.deviceSize.width / this.deviceSize.height;
- mat4.perspective(this.projectionMatrix, Math.PI / 2, aspect, near, far);
- } else {
- const aspect = width / height;
- mat4.perspective(
- this.projectionMatrix,
- renderState.inlineVerticalFieldOfView,
- aspect,
- near,
- far,
- );
- }
- if (session.ar && !session.immersive) {
- mat4.fromRotationTranslationScale(
- this.matrix,
- this.gamepads[1].pose.orientation,
- this.gamepads[1].pose.position,
- this.scale,
- );
- } else {
- mat4.fromRotationTranslationScale(
- this.matrix,
- this.quaternion,
- this.position,
- this.scale,
- );
- }
- mat4.invert(this.viewMatrix, this.matrix);
-
- // Move matrices left/right a bit and then calculate left/rightViewMatrix
- // @TODO: proper left/right distance
- mat4.invert(
- this.leftViewMatrix,
- translateOnX(mat4.copy(this.leftViewMatrix, this.matrix), -0.02),
- );
- mat4.invert(
- this.rightViewMatrix,
- translateOnX(mat4.copy(this.rightViewMatrix, this.matrix), 0.02),
- );
-
- // @TODO: Confirm if input events are only for immersive session
- // @TODO: If there are multiple immersive sessions, input events are fired only for the first session.
- // Fix this issue (if multiple immersive sessions can be created).
- if (session.immersive) {
- for (let i = 0; i < this.gamepads.length; ++i) {
- const gamepad = this.gamepads[i];
- const inputSourceImpl = this.gamepadInputSources[i];
- const handInputImpl = this.handInputSources[i];
- inputSourceImpl.updateFromGamepad(gamepad);
- const handedness = handInputImpl.handedness;
- const pinchValue = this.handPoseData[handedness]
- ? this.handPoseData[handedness].pinchValue
- : 0;
- handInputImpl.updateFromGamepad(gamepad, pinchValue);
- if (inputSourceImpl.primaryButtonIndex !== -1 && inputSourceImpl.active) {
- const primaryActionPressed =
- gamepad.buttons[inputSourceImpl.primaryButtonIndex].pressed;
- if (primaryActionPressed && !inputSourceImpl.primaryActionPressed) {
- this.dispatchEvent('@@webxr-polyfill/input-select-start', {
- sessionId: session.id,
- inputSource: inputSourceImpl.inputSource,
- });
- } else if (
- !primaryActionPressed &&
- inputSourceImpl.primaryActionPressed
- ) {
- this.dispatchEvent('@@webxr-polyfill/input-select-end', {
- sessionId: session.id,
- inputSource: inputSourceImpl.inputSource,
- });
- }
- // imputSourceImpl.primaryActionPressed is updated in onFrameEnd().
- }
- if (inputSourceImpl.primarySqueezeButtonIndex !== -1 && inputSourceImpl.active) {
- const primarySqueezeActionPressed =
- gamepad.buttons[inputSourceImpl.primarySqueezeButtonIndex].pressed;
- if (
- primarySqueezeActionPressed &&
- !inputSourceImpl.primarySqueezeActionPressed
- ) {
- this.dispatchEvent('@@webxr-polyfill/input-squeeze-start', {
- sessionId: session.id,
- inputSource: inputSourceImpl.inputSource,
- });
- } else if (
- !primarySqueezeActionPressed &&
- inputSourceImpl.primarySqueezeActionPressed
- ) {
- this.dispatchEvent('@@webxr-polyfill/input-squeeze-end', {
- sessionId: session.id,
- inputSource: inputSourceImpl.inputSource,
- });
- }
- inputSourceImpl.primarySqueezeActionPressed =
- primarySqueezeActionPressed;
- }
- if (
- this.handPoseData[gamepad.hand].pinchValue == 1 &&
- this.handPoseData[gamepad.hand].prevPinchValue != 1
- ) {
- this.dispatchEvent('@@webxr-polyfill/input-select-start', {
- sessionId: session.id,
- inputSource: handInputImpl.inputSource,
- });
- }
- if (
- this.handPoseData[gamepad.hand].pinchValue != 1 &&
- this.handPoseData[gamepad.hand].prevPinchValue == 1
- ) {
- this.dispatchEvent('@@webxr-polyfill/input-select-end', {
- sessionId: session.id,
- inputSource: handInputImpl.inputSource,
- });
- }
- this.handPoseData[gamepad.hand].prevPinchValue =
- this.handPoseData[gamepad.hand].pinchValue;
- }
-
- this._hitTest(sessionId, this.hitTestSources, this.hitTestResults);
- this._hitTest(
- sessionId,
- this.hitTestSourcesForTransientInput,
- this.hitTestResultsForTransientInput,
- );
- }
- }
-
- onFrameEnd(sessionId) {
- // We handle touch event on AR device as transient input for now.
- // If primary action happens on transient input
- // 1. First fire intputsourceschange event
- // 2. And then fire select start event
- // But in webxr-polyfill.js, inputsourceschange event is fired
- // after onFrameStart() by making an input source active.
- // So I need to postpone input select event until onFrameEnd() here.
- // Regarding select and select end events, they should be fired
- // before inputsourceschange event, so ok to be in onFrameStart().
- const session = this.sessions.get(sessionId);
- if (session.immersive) {
- for (let i = 0; i < this.gamepads.length; ++i) {
- const gamepad = this.gamepads[i];
- const inputSourceImpl = this.gamepadInputSources[i];
- if (inputSourceImpl.primaryButtonIndex !== -1) {
- const primaryActionPressed =
- gamepad.buttons[inputSourceImpl.primaryButtonIndex].pressed;
- inputSourceImpl.primaryActionPressed = primaryActionPressed;
- }
- }
- }
- }
-
- async requestFrameOfReferenceTransform(type, _options) {
- // @TODO: Add note
- const matrix = mat4.create();
- switch (type) {
- case 'viewer':
- case 'local':
- matrix[13] = -DEFAULT_HEADSET_POSITION[1];
- return matrix;
-
- case 'local-floor':
- return matrix;
-
- case 'bounded-floor':
- case 'unbound':
- default:
- // @TODO: Throw an error?
- return matrix;
- }
- }
-
- endSession(sessionId) {
- const session = this.sessions.get(sessionId);
- if (session.immersive && session.baseLayer) {
- this._removeBaseLayerCanvasFromDiv(sessionId);
- this.domOverlayRoot = null;
- this.dispatchEvent('@@webxr-polyfill/vr-present-end', sessionId);
- this._notifyLeaveImmersive(sessionId);
- }
- session.ended = true;
- }
-
- doesSessionSupportReferenceSpace(sessionId, type) {
- const session = this.sessions.get(sessionId);
- if (session.ended) {
- return false;
- }
- return session.enabledFeatures.has(type);
- }
-
- getViewport(sessionId, eye, _layer, target) {
- const session = this.sessions.get(sessionId);
- const canvas = session.baseLayer.context.canvas;
- const width = canvas.width;
- const height = canvas.height;
- if (session.ar && !session.immersive) {
- // Currently the polyfill let any immersive mode has two ViewSpaces left and right.
- // Return the same viewport for any eye type so far.
- // @TODO: Send feedback to webxr-polyfill.js about one 'none' view option
- // for AR monoscopic device
- target.x = 0;
- target.y = 0;
- target.width = width;
- target.height = height;
- } else {
- if (eye === 'none') {
- target.x = 0;
- target.width = width;
- } else if (this.stereoEffectEnabled) {
- target.x = eye === 'left' ? 0 : width / 2;
- target.width = width / 2;
- } else {
- target.x = 0;
- target.width = eye === 'left' ? width : 0;
- }
- target.y = 0;
- target.height = height;
- }
- return true;
- }
-
- getProjectionMatrix(eye) {
- return eye === 'none'
- ? this.projectionMatrix
- : eye === 'left'
- ? this.leftProjectionMatrix
- : this.rightProjectionMatrix;
- }
-
- getBasePoseMatrix() {
- return this.matrix;
- }
-
- getBaseViewMatrix(eye) {
- if (eye === 'none' || !this.stereoEffectEnabled) {
- return this.viewMatrix;
- }
- return eye === 'left' ? this.leftViewMatrix : this.rightViewMatrix;
- }
-
- getInputSources() {
- const inputSources = [];
- for (const inputSourceImpl of this.handMode
- ? this.handInputSources
- : this.gamepadInputSources) {
- if (inputSourceImpl.active) {
- inputSources.push(inputSourceImpl.inputSource);
- }
- }
-
- return inputSources;
- }
-
- getInputPose(inputSource, coordinateSystem, poseType) {
- for (const inputSourceImpl of [].concat(
- this.gamepadInputSources,
- this.handInputSources,
- )) {
- if (inputSourceImpl.inputSource === inputSource) {
- const pose = inputSourceImpl.getXRPose(coordinateSystem, poseType);
-
- return pose;
- }
- }
- return null;
- }
-
- onWindowResize() {
- // @TODO: implement
- }
-
- // DOM Overlay API
-
- setDomOverlayRoot(root) {
- this.domOverlayRoot = root;
- }
-
- // AR Hitting test
-
- addHitTestSource(source) {
- this.hitTestSources.push(source);
- }
-
- getHitTestResults(source) {
- return this.hitTestResults.get(source) || [];
- }
-
- addHitTestSourceForTransientInput(source) {
- this.hitTestSourcesForTransientInput.push(source);
- }
-
- getHitTestResultsForTransientInput(source) {
- return this.hitTestResultsForTransientInput.get(source) || [];
- }
-
- _hitTest(sessionId, hitTestSources, hitTestResults) {
- // Remove inactive sources first
- let activeHitTestSourceNum = 0;
- for (let i = 0; i < hitTestSources.length; i++) {
- const source = hitTestSources[i];
- if (source._active) {
- hitTestSources[activeHitTestSourceNum++] = source;
- }
- }
- hitTestSources.length = activeHitTestSourceNum;
-
- // Do hit test next
- hitTestResults.clear();
- for (const source of hitTestSources) {
- if (sessionId !== source._session[XRSESSION_PRIVATE].id) {
- continue;
- }
-
- // Gets base matrix depending on hit test source type
- let baseMatrix;
- if (source instanceof XRTransientInputHitTestSource) {
- if (!this.gamepadInputSources[0].active) {
- continue;
- }
- if (!source._profile.includes('touch')) {
- continue;
- }
- const gamepad = this.gamepads[0];
- const matrix = mat4.identity(mat4.create());
- matrix[12] = gamepad.axes[0];
- matrix[13] = -gamepad.axes[1];
- baseMatrix = mat4.multiply(matrix, this.matrix, matrix);
- } else {
- baseMatrix = source._space._baseMatrix;
- if (!baseMatrix) {
- continue;
- }
- }
-
- // Calculates origin and direction used for hit test in AR scene
- const offsetRay = source._offsetRay;
- const origin = vec3.set(
- vec3.create(),
- offsetRay.origin.x,
- offsetRay.origin.y,
- offsetRay.origin.z,
- );
- const direction = vec3.set(
- vec3.create(),
- offsetRay.direction.x,
- offsetRay.direction.y,
- offsetRay.direction.z,
- );
- vec3.transformMat4(origin, origin, baseMatrix);
- vec3.transformQuat(
- direction,
- direction,
- mat4.getRotation(quat.create(), baseMatrix),
- );
-
- // Do hit test in AR scene and stores the result matrices
- const arHitTestResults = this.xrScene.getHitTestResults(
- origin,
- direction,
- );
- hitTestResults.set(source, arHitTestResults);
- }
- }
-
- // Private methods
-
- // If session is immersive mode, resize the canvas size to full window size.
- // To do that, changing canvas size and moving the canvas to
- // the special div. They are restored when exiting immersive mode.
- // @TODO: Simplify the method names
-
- _appendBaseLayerCanvasToDiv(sessionId) {
- const session = this.sessions.get(sessionId);
- const canvas = session.baseLayer.context.canvas;
-
- this.originalCanvasParams.width = canvas.width;
- this.originalCanvasParams.height = canvas.height;
-
- document.body.appendChild(this.appCanvasContainer);
-
- // If canvas is OffscreenCanvas we don't further touch so far.
- if (!(canvas instanceof HTMLCanvasElement)) {
- return;
- }
-
- this.originalCanvasParams.parentElement = canvas.parentElement;
- canvas.width = window.innerWidth;
- canvas.height = window.innerHeight;
- this.appCanvasContainer.appendChild(canvas);
-
- // DOM overlay API
- // @TODO: Is this the best place to handle?
- // @TODO: What if dom element is appened/removed while in immersive mode?
- // Should we observe?
- if (this.domOverlayRoot) {
- const el = this.domOverlayRoot;
- el.style._zIndex = el.style.zIndex; // Polluting is bad...
- el.style.zIndex = DOM_OVERLAY_Z_INDEX;
- }
- }
-
- _removeBaseLayerCanvasFromDiv(sessionId) {
- const session = this.sessions.get(sessionId);
- const canvas = session.baseLayer.context.canvas;
-
- canvas.width = this.originalCanvasParams.width;
- canvas.height = this.originalCanvasParams.height;
-
- // There may be a case where an application operates DOM elements
- // in immersive mode. In such case, we don't restore DOM elements
- // hierarchies so far.
- if (this.appCanvasContainer.parentElement === document.body) {
- document.body.removeChild(this.appCanvasContainer);
- }
- if (canvas.parentElement === this.appCanvasContainer) {
- this.appCanvasContainer.removeChild(canvas);
- }
-
- // If canvas is OffscreenCanvas we don't touch so far.
- if (!(canvas instanceof HTMLCanvasElement)) {
- return;
- }
-
- if (this.originalCanvasParams.parentElement) {
- this.originalCanvasParams.parentElement.appendChild(canvas);
- }
- this.originalCanvasParams.parentElement = null;
-
- // DOM overlay API
- // @TODO: Is this the best place to handle?
- if (this.domOverlayRoot) {
- const el = this.domOverlayRoot;
- el.style.zIndex = el.style._zIndex;
- delete el.style._zIndex;
- this.appCanvasContainer.style.zIndex = APP_CANVAS_Z_INDEX;
- }
- }
-
- // For AR. Check if right controller(pointer) is touched with left controller(tablet)
-
- // UGH... @TODO: Rename
- _isPointerCloseEnoughToTablet() {
- // @TODO: Optimize if possible
- const pose = this.gamepads[0].pose;
- const matrix = mat4.fromRotationTranslation(
- mat4.create(),
- pose.orientation,
- pose.position,
- );
- mat4.multiply(matrix, this.viewMatrix, matrix);
- const dx = matrix[12] / (this.deviceSize.width * 0.5);
- const dy = matrix[13] / (this.deviceSize.height * 0.5);
- const dz = matrix[14];
- return (
- dx <= 1.0 &&
- dx >= -1.0 &&
- dy <= 1.0 &&
- dy >= -1.0 &&
- dz <= 0.01 &&
- dz >= 0.0
- );
- }
-
- _getTouchCoordinates() {
- // @TODO: Optimize if possible
- const pose = this.gamepads[0].pose;
- const matrix = mat4.fromRotationTranslation(
- mat4.create(),
- pose.orientation,
- pose.position,
- );
- mat4.multiply(matrix, this.viewMatrix, matrix);
- const dx = matrix[12] / (this.deviceSize.width * 0.5);
- const dy = matrix[13] / (this.deviceSize.height * 0.5);
- return [dx, dy];
- }
-
- // Notify the update to panel
-
- _notifyPoseUpdate() {
- dispatchCustomEvent('device-pose', {
- position: this.position,
- quaternion: this.quaternion,
- });
- }
-
- // controllerIndex: 0 => Right, 1 => Left
- _notifyInputPoseUpdate(controllerIndex) {
- const pose = this.gamepads[controllerIndex].pose;
- const objectName =
- controllerIndex === 0 ? 'right-controller' : 'left-controller';
- dispatchCustomEvent('device-input-pose', {
- position: pose.position,
- quaternion: pose.orientation,
- objectName: objectName,
- });
- }
-
- _notifyEnterImmersive() {
- dispatchCustomEvent(CLIENT_ACTIONS.ENTER_IMMERSIVE, {});
- }
-
- _notifyLeaveImmersive(sessionId) {
- // const session = this.sessions.get(sessionId);
- // if (session.mode === 'immersive-ar') {
- // this.arCanvasContainer.remove();
- // }
- dispatchCustomEvent(CLIENT_ACTIONS.EXIT_IMMERSIVE, {});
- }
-
- // Device status update methods invoked from event listeners.
-
- _updateStereoEffect(enabled) {
- this.stereoEffectEnabled = enabled;
- }
-
- _updatePose(positionArray, quaternionArray) {
- for (let i = 0; i < 3; i++) {
- this.position[i] = positionArray[i];
- }
- for (let i = 0; i < 4; i++) {
- this.quaternion[i] = quaternionArray[i];
- }
- }
-
- _updateInputPose(positionArray, quaternionArray, index) {
- if (index >= this.gamepads.length) {
- return;
- }
- const gamepad = this.gamepads[index];
- const pose = gamepad.pose;
- for (let i = 0; i < 3; i++) {
- pose.position[i] = positionArray[i];
- }
- for (let i = 0; i < 4; i++) {
- pose.orientation[i] = quaternionArray[i];
- }
- this.gamepadInputSources[index].inputSource[
- XRINPUTSOURCE_PRIVATE
- ].targetRaySpace._baseMatrix =
- this.gamepadInputSources[index].basePoseMatrix;
- }
-
- _updateInputButtonPressed(pressed, controllerIndex, buttonIndex) {
- if (controllerIndex >= this.gamepads.length) {
- return;
- }
- const gamepad = this.gamepads[controllerIndex];
- if (buttonIndex >= gamepad.buttons.length) {
- return;
- }
- gamepad.buttons[buttonIndex].pressed = pressed;
- gamepad.buttons[buttonIndex].value = pressed ? 1.0 : 0.0;
- }
-
- _updateInputButton(
- controllerIndex,
- buttonIndex,
- pressed,
- touched = false,
- value = null,
- ) {
- if (controllerIndex >= this.gamepads.length) {
- return;
- }
- const gamepad = this.gamepads[controllerIndex];
- if (buttonIndex >= gamepad.buttons.length) {
- return;
- }
- gamepad.buttons[buttonIndex].pressed = pressed;
- gamepad.buttons[buttonIndex].touched = touched;
- if (value != null) {
- gamepad.buttons[buttonIndex].value = value;
- } else {
- gamepad.buttons[buttonIndex].value = pressed ? 1.0 : 0.0;
- }
- }
-
- _updateInputAxisValue(value, controllerIndex, axisIndex) {
- if (controllerIndex >= this.gamepads.length) {
- return;
- }
- const gamepad = this.gamepads[controllerIndex];
- if (axisIndex >= gamepad.axes.length) {
- return;
- }
- gamepad.axes[axisIndex] = value;
- }
-
- _updateControllerInputVisibility(controllerIndex, visible) {
- if (controllerIndex >= this.gamepadInputSources.length) {
- throw new Error('ControllerIndex ' + controllerIndex + ' is greater than the gamepadInputSources.length ' + this.gamepadInputSources.length);
- }
- const inputSourceImpl = this.gamepadInputSources[controllerIndex];
- inputSourceImpl.active = visible;
- }
-
- _updateHandInputVisibility(handIndex, visible) {
- if (handIndex >= this.handInputSources.length) {
- throw new Error('HandIndex ' + handIndex + ' is greater than the handInputSources.length ' + this.handInputSources.length);
- }
- const inputSourceImpl = this.handInputSources[handIndex];
- inputSourceImpl.active = visible;
- }
-
- _initializeControllers(config) {
- const hasController = config.controllers !== undefined;
- const controllerNum = hasController ? config.controllers.length : 0;
- this.gamepads.length = 0;
- this.gamepadInputSources.length = 0;
- for (let i = 0; i < controllerNum; i++) {
- const controller = config.controllers[i];
- const id = controller.id || '';
- const hasPosition = controller.hasPosition || false;
- const buttonNum = controller.buttonNum || 0;
- const primaryButtonIndex =
- controller.primaryButtonIndex !== undefined
- ? controller.primaryButtonIndex
- : 0;
- const primarySqueezeButtonIndex =
- controller.primarySqueezeButtonIndex !== undefined
- ? controller.primarySqueezeButtonIndex
- : -1;
- this.gamepads.push(
- createGamepad(id, i === 0 ? 'right' : 'left', buttonNum, hasPosition),
- );
- // @TODO: targetRayMode should be screen for right controller(pointer) in AR
- const imputSourceImpl = new GamepadXRInputSource(
- this,
- {},
- primaryButtonIndex,
- primarySqueezeButtonIndex,
- );
- imputSourceImpl.active = true; // Override property for transient imput
- imputSourceImpl.profilesOverride =
- GamepadMappings[controller.id].profiles;
- this.gamepadInputSources.push(imputSourceImpl);
- }
- }
-
- _initializeHands() {
- this.handInputSources.length = 0;
- for (let i = 0; i < 2; i++) {
- const handInputImpl = new HandXRInputSource(this);
- handInputImpl.active = true;
- this.handInputSources.push(handInputImpl);
- }
- }
-
- // Set up event listeners. Events are sent from panel via background.
-
- _setupEventListeners() {
- WebXREventDispatcher.instance.addEventListener(POLYFILL_ACTIONS.DEVICE_TYPE_CHANGE, (event) => {
- const config = event.detail.deviceDefinition;
-
- this.modes = config.modes || DEFAULT_MODES;
- this.features = config.features || [];
- this.resolution =
- config.resolution !== undefined
- ? config.resolution
- : DEFAULT_RESOLUTION;
- this.deviceSize =
- config.size !== undefined ? config.size : DEFAULT_DEVICE_SIZE;
-
- // Note: Just in case release primary buttons and wait for two frames to fire selectend event
- // before initialize controllers.
- // @TODO: Very hacky. We should go with more proper way.
- for (let i = 0; i < this.gamepads.length; ++i) {
- const gamepad = this.gamepads[i];
- const inputSourceImpl = this.gamepadInputSources[i];
- inputSourceImpl.active = true;
- if (inputSourceImpl.primaryButtonIndex !== -1) {
- gamepad.buttons[inputSourceImpl.primaryButtonIndex].pressed = false;
- }
- if (inputSourceImpl.primarySqueezeButtonIndex !== -1) {
- gamepad.buttons[
- inputSourceImpl.primarySqueezeButtonIndex
- ].pressed = false;
- }
- }
-
- this.requestAnimationFrame(() => {
- this.requestAnimationFrame(() => {
- this._initializeControllers(config);
- });
- });
- });
-
- WebXREventDispatcher.instance.addEventListener(
- POLYFILL_ACTIONS.HEADSET_POSE_CHANGE,
- (event) => {
- const positionArray = event.detail.position;
- const quaternionArray = event.detail.quaternion;
- this._updatePose(positionArray, quaternionArray);
- if (this.xrScene) {
- this.xrScene.updateCameraTransform(positionArray, quaternionArray);
- }
- },
- false,
- );
-
- WebXREventDispatcher.instance.addEventListener(
- POLYFILL_ACTIONS.CONTROLLER_POSE_CHANGE,
- (event) => {
- const positionArray = event.detail.position;
- const quaternionArray = event.detail.quaternion;
- const objectName = event.detail.objectName;
-
- switch (objectName) {
- case 'right-controller':
- case 'left-controller':
- this._updateInputPose(
- positionArray,
- quaternionArray,
- objectName === 'right-controller' ? 0 : 1,
- ); // @TODO: remove magic number
- break;
- }
- },
- );
-
- WebXREventDispatcher.instance.addEventListener(
- POLYFILL_ACTIONS.CONTROLLER_VISIBILITY_CHANGE,
- (event) => {
- const objectName = event.detail.objectName;
- const visible = event.detail.visible;
-
- switch (objectName) {
- case 'right-controller':
- case 'left-controller':
- this._updateControllerInputVisibility(
- objectName === 'right-controller' ? 0 : 1, // @TODO: remove magic number
- visible,
- );
- break;
- }
- },
- );
-
- WebXREventDispatcher.instance.addEventListener(
- POLYFILL_ACTIONS.BUTTON_STATE_CHANGE,
- (event) => {
- const objectName = event.detail.objectName;
- const buttonIndex = event.detail.buttonIndex;
- const pressed = event.detail.pressed;
- const touched = event.detail.touched;
- const value = event.detail.value;
-
- switch (objectName) {
- case 'right-controller':
- case 'left-controller':
- this._updateInputButton(
- objectName === 'right-controller' ? 0 : 1, // @TODO: remove magic number
- buttonIndex,
- pressed,
- touched,
- value,
- );
- break;
- }
- },
- false,
- );
-
- WebXREventDispatcher.instance.addEventListener(
- POLYFILL_ACTIONS.ANALOG_VALUE_CHANGE,
- (event) => {
- const value = event.detail.value;
- const objectName = event.detail.objectName;
- const axisIndex = event.detail.axisIndex;
-
- switch (objectName) {
- case 'right-controller':
- case 'left-controller':
- this._updateInputAxisValue(
- value,
- objectName === 'right-controller' ? 0 : 1, // @TODO: remove magic number
- axisIndex,
- );
- break;
- }
- },
- false,
- );
-
- WebXREventDispatcher.instance.addEventListener(POLYFILL_ACTIONS.ROOM_DIMENSION_CHANGE, (event) => {
- const dimension = event.detail.dimension;
- this.xrScene.createRoom(dimension);
- });
-
- WebXREventDispatcher.instance.addEventListener(POLYFILL_ACTIONS.STEREO_TOGGLE, (event) => {
- this._updateStereoEffect(event.detail.enabled);
- });
-
- WebXREventDispatcher.instance.addEventListener(POLYFILL_ACTIONS.INPUT_MODE_CHANGE, (event) => {
- this.handMode = event.detail.inputMode === 'hands';
- });
-
- WebXREventDispatcher.instance.addEventListener(POLYFILL_ACTIONS.HAND_POSE_CHANGE, (event) => {
- const handedness = event.detail.handedness;
- const poseId = event.detail.pose;
- this.handPoseData[handedness].poseId = poseId;
- });
-
- WebXREventDispatcher.instance.addEventListener(
- POLYFILL_ACTIONS.HAND_VISIBILITY_CHANGE,
- (event) => {
- const handedness = event.detail.handedness;
- const visible = event.detail.visible;
-
- switch (handedness) {
- case 'right':
- case 'left':
- this._updateHandInputVisibility(
- handedness === 'right' ? 0 : 1, // @TODO: remove magic number
- visible,
- );
- break;
- }
- },
- );
-
- WebXREventDispatcher.instance.addEventListener(POLYFILL_ACTIONS.PINCH_VALUE_CHANGE, (event) => {
- const handedness = event.detail.handedness;
- const pinchValue = event.detail.value;
- this.handPoseData[handedness].pinchValue = pinchValue;
- });
-
- WebXREventDispatcher.instance.addEventListener(POLYFILL_ACTIONS.USER_OBJECTS_CHANGE, (event) => {
- const objects = event.detail.objects;
- this.xrScene.updateUserObjects(objects);
- });
- }
-}
-
-let SESSION_ID = 0;
-class Session {
- constructor(mode, enabledFeatures) {
- this.mode = mode;
- // @TODO support mobile non-immersive
- this.immersive = mode == 'immersive-vr' || mode == 'immersive-ar';
- this.vr = mode === 'immersive-vr';
- this.ar = mode == 'immersive-ar';
- this.id = ++SESSION_ID;
- this.baseLayer = null;
- this.inlineVerticalFieldOfView = Math.PI * 0.5;
- this.ended = false;
- this.enabledFeatures = enabledFeatures;
- }
-}
-
-const createGamepad = (id, hand, buttonNum, hasPosition) => {
- const buttons = [];
- for (let i = 0; i < buttonNum; i++) {
- buttons.push({
- pressed: false,
- touched: false,
- value: 0.0,
- });
- }
- return {
- id: id || '',
- pose: {
- hasPosition: hasPosition,
- position: [0, 0, 0],
- orientation: [0, 0, 0, 1],
- },
- buttons: buttons,
- hand: hand,
- mapping: 'xr-standard',
- axes: [0, 0],
- };
-};
-
-const tmpVec3 = vec3.create();
-const translateOnX = (matrix, distance) => {
- vec3.set(tmpVec3, distance, 0, 0);
- return mat4.translate(matrix, matrix, tmpVec3);
-};
diff --git a/webxr-emulator/LICENSE.md b/webxr-emulator/LICENSE.md
deleted file mode 100644
index b93be90..0000000
--- a/webxr-emulator/LICENSE.md
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) Meta Platforms, Inc. and affiliates.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/webxr-emulator/OldCustomWebXRPolyfill.ts b/webxr-emulator/OldCustomWebXRPolyfill.ts
deleted file mode 100644
index 975bd92..0000000
--- a/webxr-emulator/OldCustomWebXRPolyfill.ts
+++ /dev/null
@@ -1,220 +0,0 @@
-// @ts-nocheck
-import EX_API from './api/index'
-import XRHitTestResult from './api/XRHitTestResult'
-import XRHitTestSource from './api/XRHitTestSource'
-import XRTransientInputHitTestResult from './api/XRTransientInputHitTestResult'
-import XRTransientInputHitTestSource from './api/XRTransientInputHitTestSource'
-import EmulatedXRDevice from './EmulatedXRDevice'
-import API from './webxr-polyfill/api/index'
-import XRFrame from './webxr-polyfill/api/XRFrame'
-import XRRigidTransform from './webxr-polyfill/api/XRRigidTransform'
-import XRSession, { PRIVATE as XRSESSION_PRIVATE } from './webxr-polyfill/api/XRSession'
-import XRSystem from './webxr-polyfill/api/XRSystem'
-import { XR_COMPATIBLE } from './webxr-polyfill/constants'
-import WebXRPolyfill from './webxr-polyfill/WebXRPolyfill'
-import { WebXREventDispatcher } from './WebXREventDispatcher'
-
-/**
- * Adapted from the mozilla webxr emulator
- * https://github.com/MozillaReality/WebXR-emulator-extension
- */
-
-export class IREngineWebXRPolyfill extends WebXRPolyfill {
- constructor() {
- super({ global: globalThis })
- // Note: Experimental.
- // Override some XR APIs to track active immersive session to
- // enable to exit immersive by the extension.
- // Exiting without user gesture in the page might violate security policy
- // so there might be a chance that we remove this feature at some point.
-
- let activeImmersiveSession = null
- const originalRequestSession = XRSystem.prototype.requestSession
- XRSystem.prototype.requestSession = function (mode, enabledFeatures: any = {}) {
- return originalRequestSession.call(this, mode, enabledFeatures).then((session) => {
- if (mode === 'immersive-vr' || mode === 'immersive-ar') {
- activeImmersiveSession = session
-
- // DOM-Overlay API
- const optionalFeatures = enabledFeatures.optionalFeatures
- const domOverlay = enabledFeatures.domOverlay
- if (optionalFeatures && optionalFeatures.includes('dom-overlay') && domOverlay && domOverlay.root) {
- const device = session[XRSESSION_PRIVATE].device
- device.setDomOverlayRoot(domOverlay.root)
- session.domOverlayState = { type: 'screen' }
- }
- }
- return session
- })
- }
-
- const originalEnd = XRSession.prototype.end
- XRSession.prototype.end = function () {
- return originalEnd.call(this).then(() => {
- if (activeImmersiveSession === this) {
- activeImmersiveSession = null
- }
- })
- }
-
- WebXREventDispatcher.instance.addEventListener('webxr-exit-immersive', (event) => {
- if (activeImmersiveSession && !activeImmersiveSession.ended) {
- activeImmersiveSession.end().then(() => {
- activeImmersiveSession = null
- })
- }
- })
-
- // Extending XRSession and XRFrame for AR hitting test API.
- ;(XRSession.prototype as any).requestHitTestSource = function (options) {
- const source = new XRHitTestSource(this, options)
- const device = this[XRSESSION_PRIVATE].device
- device.addHitTestSource(source)
- return Promise.resolve(source)
- }
- ;(XRSession.prototype as any).requestHitTestSourceForTransientInput = function (options) {
- const source = new XRTransientInputHitTestSource(this, options)
- const device = this[XRSESSION_PRIVATE].device
- device.addHitTestSourceForTransientInput(source)
- return Promise.resolve(source)
- }
- ;(XRFrame.prototype as any).getHitTestResults = function (hitTestSource) {
- const device = this.session[XRSESSION_PRIVATE].device
- const hitTestResults = device.getHitTestResults(hitTestSource)
- const results = []
- for (const matrix of hitTestResults) {
- results.push(new XRHitTestResult(this, new XRRigidTransform(matrix)))
- }
- return results
- }
- ;(XRFrame.prototype as any).getHitTestResultsForTransientInput = function (hitTestSource) {
- const device = this.session[XRSESSION_PRIVATE].device
- const hitTestResults = device.getHitTestResultsForTransientInput(hitTestSource)
- if (hitTestResults.length === 0) {
- return []
- }
- const results = []
- for (const matrix of hitTestResults) {
- results.push(new XRHitTestResult(this, new XRRigidTransform(matrix)))
- }
- const inputSource = device.getInputSources()[0]
- return [new XRTransientInputHitTestResult(this, results, inputSource)]
- }
-
- if (this.nativeWebXR) {
- // Note: Even if native WebXR API is available the extension overrides
- // it with WebXR polyfill because the extension doesn't work with
- // the native one (yet).
- overrideAPI()
- this.injected = true
- this._patchNavigatorXR()
- } else {
- installEX_API()
- // Note: WebXR API polyfill can be overridden by native WebXR API on the latest Chrome 78
- // after the extension is loaded but before loading page is completed
- // if the native WebXR API is disabled via chrome://flags and the page includes
- // WebXR origin trial.
- // Here is a workaround. Check if XR class is native code when node is appended or
- // the page is loaded. If it detects, override WebXR API with the polyfill.
- // @TODO: Remove this workaround if the major browser officially support native WebXR API
- let overridden = false
- const overrideIfNeeded = () => {
- if (overridden) {
- return false
- }
- if (isNativeFunction(this.global.XRSystem)) {
- overrideAPI()
- overridden = true
- return true
- }
- return false
- }
- const observer = new MutationObserver((list) => {
- for (const record of list) {
- for (const node of record.addedNodes) {
- if ((node as any).localName === 'script' && overrideIfNeeded()) {
- observer.disconnect()
- break
- }
- }
- if (overridden) {
- break
- }
- }
- })
- observer.observe(document, { subtree: true, childList: true })
- const onLoad = (event) => {
- if (!overridden) {
- observer.disconnect()
- overrideIfNeeded()
- }
- document.removeEventListener('DOMContentLoaded', onLoad)
- }
- document.addEventListener('DOMContentLoaded', onLoad)
- }
- }
-
- _patchNavigatorXR() {
- const devicePromise = requestXRDevice()
- this.xr = new XRSystem(devicePromise)
- Object.defineProperty(this.global.navigator, 'xr', {
- value: this.xr,
- configurable: true
- })
- }
-}
-
-const requestXRDevice = async () => {
- // resolve when receiving configuration parameters from content-script as an event
- return new Promise((resolve, reject) => {
- const callback = (event) => {
- WebXREventDispatcher.instance.removeEventListener('webxr-device-init', callback)
- resolve(
- new EmulatedXRDevice(
- globalThis,
- Object.assign({}, event.detail.deviceDefinition, { stereoEffect: event.detail.stereoEffect })
- )
- )
- }
- WebXREventDispatcher.instance.addEventListener('webxr-device-init', callback, false)
- })
-}
-
-// Easy native function detection.
-const isNativeFunction = (func) => {
- return /\[native code\]/i.test(func.toString())
-}
-
-const overrideAPI = () => {
- console.log('WebXR emulator extension overrides native WebXR API with polyfill.')
- for (const className in API) {
- globalThis[className] = API[className]
- }
- installEX_API()
-
- // Since (desktop) Chrome 88 WebGL(2)RenderingContext.makeXRCompatible() seems
- // to start to reject if no immersive XR device is plugged in.
- // So we need to override them, too. Otherwise JS engines/apps including
- // "await context.makeXRCompatible();" won't work with the extension.
- // See https://github.com/MozillaReality/WebXR-emulator-extension/issues/266
- if (typeof WebGLRenderingContext !== 'undefined') {
- overrideMakeXRCompatible(WebGLRenderingContext)
- }
- if (typeof WebGL2RenderingContext !== 'undefined') {
- overrideMakeXRCompatible(WebGL2RenderingContext)
- }
-}
-
-const installEX_API = () => {
- for (const className in EX_API) {
- globalThis[className] = EX_API[className]
- }
-}
-
-const overrideMakeXRCompatible = (Context) => {
- Context.prototype.makeXRCompatible = function () {
- this[XR_COMPATIBLE] = true
- // This is all fake, so just resolve immediately.
- return Promise.resolve()
- }
-}
diff --git a/webxr-emulator/WebXREventDispatcher.ts b/webxr-emulator/WebXREventDispatcher.ts
deleted file mode 100644
index b11a2bc..0000000
--- a/webxr-emulator/WebXREventDispatcher.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-export class WebXREventDispatcher {
- public static instance: WebXREventDispatcher = new WebXREventDispatcher()
- _listeners = {}
- public reset(): void {
- Object.keys(WebXREventDispatcher.instance._listeners).forEach((key) => {
- delete WebXREventDispatcher.instance._listeners[key]
- })
- }
- once(eventName: string | number, listener: Function, ...args: any): void {
- const onEvent = (ev) => {
- WebXREventDispatcher.instance.removeEventListener(eventName, onEvent)
- listener(ev)
- }
- WebXREventDispatcher.instance.addEventListener(eventName, onEvent)
- }
- addEventListener(eventName: string | number, listener: Function, ...args: any): void {
- const listeners = WebXREventDispatcher.instance._listeners
- if (listeners[eventName] === undefined) {
- listeners[eventName] = []
- }
-
- if (listeners[eventName].indexOf(listener) === -1) {
- listeners[eventName].push(listener)
- }
- }
- hasEventListener(eventName: string | number, listener: Function, ...args: any): boolean {
- return (
- WebXREventDispatcher.instance._listeners[eventName] !== undefined &&
- WebXREventDispatcher.instance._listeners[eventName].indexOf(listener) !== -1
- )
- }
- removeEventListener(eventName: string | number, listener: Function, ...args: any): void {
- const listenerArray = WebXREventDispatcher.instance._listeners[eventName]
- if (listenerArray !== undefined) {
- const index = listenerArray.indexOf(listener)
- if (index !== -1) {
- listenerArray.splice(index, 1)
- }
- }
- }
- removeAllListenersForEvent(eventName: string, deleteEvent?: boolean, ...args: any) {
- if (deleteEvent) {
- delete WebXREventDispatcher.instance._listeners[eventName]
- } else {
- WebXREventDispatcher.instance._listeners[eventName] = []
- }
- }
- dispatchEvent(event: { type: string; [attachment: string]: any }, ...args: any): void {
- const listenerArray = WebXREventDispatcher.instance._listeners[event.type]
- if (listenerArray !== undefined) {
- const array = listenerArray.slice(0)
- for (let i = 0; i < array.length; i++) {
- array[i].call(WebXREventDispatcher.instance, event, ...args)
- }
- }
- }
-}
diff --git a/webxr-emulator/XRScene.js b/webxr-emulator/XRScene.js
deleted file mode 100644
index fcb4dd4..0000000
--- a/webxr-emulator/XRScene.js
+++ /dev/null
@@ -1,382 +0,0 @@
-import {
- BoxGeometry,
- Color,
- DirectionalLight,
- DoubleSide,
- LineBasicMaterial,
- LineSegments,
- Mesh,
- MeshBasicMaterial,
- Object3D,
- PerspectiveCamera,
- PlaneGeometry,
- Raycaster,
- Scene,
- Vector3,
- WebGLRenderer,
-} from 'three';
-import { XRPlane, XRPlaneOrientation } from './api/XRPlane';
-
-import { BoxLineGeometry } from 'three/examples/jsm/geometries/BoxLineGeometry.js';
-import { XRMesh } from './api/XRMesh';
-import XRSpace from 'webxr-polyfill/src/api/XRSpace';
-import { mat4 } from 'gl-matrix';
-import { isClient } from '@ir-engine/common/src/utils/getEnvironment';
-
-const DEFAULT_CAMERA_POSITION = [0, 1.6, 0];
-const PLANE_CONFIG = {
- FLOOR: {
- orientation: XRPlaneOrientation.Horizontal,
- quaternion: [0, 0, 0, 1],
- semanticLabel: 'floor',
- },
- CEILING: {
- orientation: XRPlaneOrientation.Horizontal,
- quaternion: [0, 0, 1, 0],
- semanticLabel: 'ceiling',
- },
- RIGHT: {
- orientation: XRPlaneOrientation.Vertical,
- quaternion: [0, 0, 0.7071068, 0.7071068],
- semanticLabel: 'wall',
- },
- LEFT: {
- orientation: XRPlaneOrientation.Vertical,
- quaternion: [0, 0, -0.7071068, 0.7071068],
- semanticLabel: 'wall',
- },
- FRONT: {
- orientation: XRPlaneOrientation.Vertical,
- quaternion: [0.7071068, 0, 0, 0.7071068],
- semanticLabel: 'wall',
- },
- BACK: {
- orientation: XRPlaneOrientation.Vertical,
- quaternion: [-0.7071068, 0, 0, 0.7071068],
- semanticLabel: 'wall',
- },
-};
-const DEFAULT_ROOM_DIMENSION = {
- x: 6,
- y: 3,
- z: 6,
-};
-
-const buildXRPlane = (width, length, position, planeConfig) => {
- const planeMatrix = new Float32Array(16);
- mat4.fromRotationTranslation(planeMatrix, planeConfig.quaternion, position);
- const planeSpace = new XRSpace();
- planeSpace._baseMatrix = planeMatrix;
- const points = [
- new DOMPointReadOnly(width, 0, length),
- new DOMPointReadOnly(width, 0, -length),
- new DOMPointReadOnly(-width, 0, -length),
- new DOMPointReadOnly(-width, 0, length),
- new DOMPointReadOnly(width, 0, length),
- ];
- return new XRPlane(
- planeSpace,
- points,
- planeConfig.orientation,
- planeConfig.semanticLabel,
- );
-};
-
-/**
- * @param {THREE.Mesh} mesh
- */
-const buildXRMesh = (mesh) => {
- const meshMatrix = new Float32Array(16);
- mat4.fromRotationTranslation(
- meshMatrix,
- mesh.quaternion.toArray(),
- mesh.position.toArray(),
- );
- const meshSpace = new XRSpace();
- meshSpace._baseMatrix = meshMatrix;
- const indices = mesh.geometry.index.array;
- const vertices = mesh.geometry.getAttribute('position').array;
- const semanticLabel = mesh.userData.semanticLabel;
- return new XRMesh(meshSpace, vertices, indices, semanticLabel);
-};
-
-class XRRoomFactory {
- constructor(scene) {
- this.scene = scene;
- this.roomObject = null;
- this.roomCollider = null;
- this.xrPlanes = [];
- }
-
- createRoom(x, y, z) {
- if (this.roomObject) this.scene.remove(this.roomObject);
- if (this.roomCollider) this.scene.remove(this.roomCollider);
- this.roomObject = new LineSegments(
- new BoxLineGeometry(
- x,
- y,
- z,
- Math.ceil(x * 2),
- Math.ceil(y * 2),
- Math.ceil(z * 2),
- ),
- new LineBasicMaterial({ color: 0x808080 }),
- );
- this.roomObject.geometry.translate(0, y / 2, 0);
- this.scene.add(this.roomObject);
- this.xrPlanes = [
- buildXRPlane(x / 2, z / 2, [0, 0, 0], PLANE_CONFIG.FLOOR),
- buildXRPlane(x / 2, z / 2, [0, y, 0], PLANE_CONFIG.CEILING),
- buildXRPlane(y / 2, z / 2, [x / 2, y / 2, 0], PLANE_CONFIG.RIGHT),
- buildXRPlane(y / 2, z / 2, [-x / 2, y / 2, 0], PLANE_CONFIG.LEFT),
- buildXRPlane(x / 2, y / 2, [0, y / 2, z / 2], PLANE_CONFIG.BACK),
- buildXRPlane(x / 2, y / 2, [0, y / 2, -z / 2], PLANE_CONFIG.FRONT),
- ];
- this.roomCollider = new Mesh(
- new BoxGeometry(x, y, z),
- new MeshBasicMaterial({
- side: DoubleSide,
- }),
- );
- this.roomCollider.visible = false;
- this.roomCollider.position.y = y / 2;
- this.scene.add(this.roomCollider);
- }
-}
-
-export default class XRScene {
- constructor() {
- this.renderer = null;
- this.camera = null;
-
- this.onCameraPoseUpdate = null;
- this.hitTestTarget = null;
-
- this._init();
- }
-
- _init() {
- const width = window.innerWidth;
- const height = window.innerHeight;
-
- if (isClient) {
- const canvas = document.createElement('canvas');
- const context = canvas.getContext('webgl2', { antialias: true });
- context.globalCompositeOperation = 'destination-over';
-
- const renderer = new WebGLRenderer({ canvas: canvas, context: context });
- renderer.setSize(width, height);
- canvas.width = width;
- canvas.height = height;
- renderer.domElement.oncontextmenu = () => {
- return false;
- };
- this.renderer = renderer;
- }
-
- const scene = new Scene();
- scene.background = new Color(0x444444);
-
- this.roomFactory = new XRRoomFactory(scene);
- this.roomFactory.createRoom(
- DEFAULT_ROOM_DIMENSION.x,
- DEFAULT_ROOM_DIMENSION.y,
- DEFAULT_ROOM_DIMENSION.z,
- );
-
- const camera = new PerspectiveCamera(90, width / height, 0.001, 1000.0);
- camera.position.fromArray(DEFAULT_CAMERA_POSITION);
-
- const light = new DirectionalLight(0xffffff, 4.0);
- light.position.set(-1, 1, -1);
- scene.add(light);
-
- // @TODO: only animate when headset pose change
- const animate = () => {
- requestAnimationFrame(animate);
- const renderer = this.renderer;
- if (!renderer) return;
-
- renderer.render(scene, camera);
- const canvas = renderer.domElement;
- var destCtx = canvas.getContext('2d');
-
- if (this.canvas) {
- destCtx.drawImage(this.appCanvas, 0, 0);
- }
- };
-
- animate();
-
- window.addEventListener(
- 'resize',
- (_event) => {
- const width = window.innerWidth;
- const height = window.innerHeight;
- if (this.renderer) this.renderer.setSize(width, height);
- camera.aspect = width / height;
- camera.updateProjectionMatrix();
- },
- false,
- );
-
- this.scene = scene;
- this.camera = camera;
- this.raycaster = new Raycaster();
- this.hitTestTarget = new Object3D();
- this.hitTestMarker = new Object3D();
- this.hitTestMarker.rotateX(-Math.PI / 2);
- this.hitTestTarget.add(this.hitTestMarker);
- this.userObjects = {};
- }
-
- inject(canvasContainer) {
- const appendCanvas = () => {
- if (this.renderer) canvasContainer.appendChild(this.renderer.domElement);
- };
-
- if (document.body) {
- appendCanvas();
- } else {
- document.addEventListener('DOMContentLoaded', appendCanvas);
- }
- }
-
- eject() {
- if (this.renderer) {
- const element = this.renderer.domElement;
- element.parentElement.remove();
- }
- }
-
- setCanvas(canvas) {
- this.appCanvas = canvas;
- }
-
- updateCameraTransform(positionArray, quaternionArray) {
- this.camera.position.fromArray(positionArray);
- this.camera.quaternion.fromArray(quaternionArray);
- }
-
- createRoom(dimension) {
- this.roomFactory.createRoom(dimension.x, dimension.y, dimension.z);
- }
-
- getHitTestResults(origin, direction) {
- this.raycaster.set(
- new Vector3().fromArray(origin),
- new Vector3().fromArray(direction),
- );
- const targets = [];
- if (this.roomFactory.roomCollider) {
- targets.push(this.roomFactory.roomCollider);
- }
- const intersects = this.raycaster.intersectObjects(targets, true);
-
- const results = [];
- intersects.forEach((intersect) => {
- this.hitTestTarget.position.copy(intersect.point);
- this.hitTestTarget.lookAt(
- new Vector3().addVectors(intersect.point, intersect.face.normal),
- );
- this.hitTestTarget.updateWorldMatrix(false, true);
-
- results.push(
- mat4.fromValues(...this.hitTestMarker.matrixWorld.toArray()),
- );
- });
- return results;
- }
-
- get xrPlanes() {
- return [
- ...this.roomFactory.xrPlanes,
- ...Object.values(this.userObjects)
- .filter((object) => object.userData.type === 'plane')
- .map((object) => object.userData.xrObjectRef),
- ];
- }
-
- get xrMeshes() {
- return new Set(
- Object.values(this.userObjects)
- .filter((object) => object.userData.type === 'mesh')
- .map((object) => object.userData.xrObjectRef),
- );
- }
-
- updateUserObjects(objects) {
- // filter out hidden objects
- [...Object.keys(objects)].forEach((userObjectId) => {
- if (!objects[userObjectId].active) {
- delete objects[userObjectId];
- }
- });
- Object.entries(objects).forEach(([userObjectId, objectData]) => {
- const {
- type,
- width,
- height,
- depth,
- isVertical,
- semanticLabel,
- position,
- quaternion,
- } = objectData;
- let object;
- if (type === 'mesh') {
- if (!this.userObjects[userObjectId]) {
- const mesh = new Mesh(
- new BoxGeometry(width, height, depth),
- new MeshBasicMaterial({ color: 0xffffff * Math.random() }),
- );
- mesh.userData = { type, semanticLabel };
- this.userObjects[userObjectId] = mesh;
- this.scene.add(mesh);
- mesh.userData.xrObjectRef = buildXRMesh(mesh);
- }
- object = this.userObjects[userObjectId];
- } else if (type === 'plane') {
- if (!this.userObjects[userObjectId]) {
- const planeGeometry = new PlaneGeometry(width, height);
- planeGeometry.rotateX(Math.PI / 2);
- const mesh = new Mesh(
- planeGeometry,
- new MeshBasicMaterial({
- color: 0xffffff * Math.random(),
- side: DoubleSide,
- }),
- );
- mesh.userData = { type, semanticLabel };
- this.userObjects[userObjectId] = mesh;
- this.scene.add(mesh);
- mesh.userData.xrObjectRef = buildXRPlane(
- width / 2,
- height / 2,
- position,
- {
- orientation: isVertical
- ? XRPlaneOrientation.Vertical
- : XRPlaneOrientation.Horizontal,
- quaternion,
- semanticLabel,
- },
- );
- }
- object = this.userObjects[userObjectId];
- }
- if (object) {
- object.position.fromArray(position);
- object.quaternion.fromArray(quaternion);
- object.userData.xrObjectRef._updateMatrix(position, quaternion);
- }
- });
-
- Object.keys(this.userObjects)
- .filter((key) => !Object.keys(objects).includes(key))
- .forEach((key) => {
- this.userObjects[key].parent.remove(this.userObjects[key]);
- delete this.userObjects[key];
- });
- }
-}
diff --git a/webxr-emulator/actions.js b/webxr-emulator/actions.js
deleted file mode 100644
index b7a9911..0000000
--- a/webxr-emulator/actions.js
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-/**
- * Events triggered by the emulator UI and sent to the content script
- */
-export const EMULATOR_ACTIONS = {
- HEADSET_POSE_CHANGE: 'ea-headset-pose-change',
- CONTROLLER_POSE_CHANGE: 'ea-controller-pose-change',
- CONTROLLER_VISIBILITY_CHANGE: 'ea-controller-visibility-change',
- BUTTON_STATE_CHANGE: 'ea-button-state-change',
- ANALOG_VALUE_CHANGE: 'ea-analog-value-change',
- DEVICE_TYPE_CHANGE: 'ea-device-type-change',
- STEREO_TOGGLE: 'ea-stereo-toggle',
- KEYBOARD_EVENT: 'ea-keyboard-event',
- EXIT_IMMERSIVE: 'ea-exit-immersive',
- ROOM_DIMENSION_CHANGE: 'ea-room-dimension-change',
- EXCLUDE_POLYFILL: 'ea-exclude-polyfill',
- INPUT_MODE_CHANGE: 'ea-input-mode-change',
- HAND_POSE_CHANGE: 'ea-hand-pose-change',
- HAND_VISIBILITY_CHANGE: 'ea-hand-visibility-change',
- PINCH_VALUE_CHANGE: 'ea-pinch-value-change',
- USER_OBJECTS_CHANGE: 'ea-user-objects-change',
-};
-
-/**
- * Events triggered by the content script and caught and processed by the custom WebXR Polyfill
- */
-export const POLYFILL_ACTIONS = EMULATOR_ACTIONS
-// {
-// HEADSET_POSE_CHANGE: 'pa-headset-pose-change',
-// CONTROLLER_POSE_CHANGE: 'pa-controller-pose-change',
-// CONTROLLER_VISIBILITY_CHANGE: 'pa-controller-visibility-change',
-// BUTTON_STATE_CHANGE: 'pa-button-state-change',
-// ANALOG_VALUE_CHANGE: 'pa-analog-value-change',
-// DEVICE_TYPE_CHANGE: 'pa-device-type-change',
-// STEREO_TOGGLE: 'pa-stereo-toggle',
-// KEYBOARD_EVENT: 'pa-keyboard-event',
-// EXIT_IMMERSIVE: 'pa-exit-immersive',
-// DEVICE_INIT: 'pa-device-init',
-// ROOM_DIMENSION_CHANGE: 'pa-room-dimension-change',
-// INPUT_MODE_CHANGE: 'pa-input-mode-change',
-// HAND_POSE_CHANGE: 'pa-hand-pose-change',
-// HAND_VISIBILITY_CHANGE: 'pa-hand-visibility-change',
-// PINCH_VALUE_CHANGE: 'pa-pinch-value-change',
-// USER_OBJECTS_CHANGE: 'pa-user-objects-change',
-// };
-
-/**
- * Events triggered from the client side that are caught by the content script and then relayed back to the emulator side
- */
-export const CLIENT_ACTIONS = {
- ENTER_IMMERSIVE: 'ca-enter-immersive',
- EXIT_IMMERSIVE: 'ca-exit-immersive',
- PING: 'ca-ping',
-};
diff --git a/webxr-emulator/api/XRAnchor.js b/webxr-emulator/api/XRAnchor.js
deleted file mode 100644
index f269b3c..0000000
--- a/webxr-emulator/api/XRAnchor.js
+++ /dev/null
@@ -1,80 +0,0 @@
-import XRSpace from 'webxr-polyfill/src/api/XRSpace';
-import { generateUUID } from 'three/src/math/MathUtils';
-import localforage from 'localforage';
-
-export const PRIVATE = Symbol('@@webxr-polyfill/XRAnchor');
-
-const ANCHOR_DELETED_ERROR =
- 'Unable to access anchor properties, the anchor was already deleted.';
-
-export class XRAnchor {
- /**
- * @param {import('webxr-polyfill/src/api/XRSession').default} session
- * @param {import('webxr-polyfill/src/api/XRSpace').default} anchorSpace
- */
- constructor(session, anchorSpace) {
- this[PRIVATE] = {
- session,
- anchorSpace,
- };
- }
-
- /**
- * @type {import('webxr-polyfill/src/api/XRSpace').default}
- */
- get anchorSpace() {
- if (this[PRIVATE].session.hasTrackedAnchor(this)) {
- return this[PRIVATE].anchorSpace;
- } else {
- throw new DOMException(ANCHOR_DELETED_ERROR, 'InvalidStateError');
- }
- }
-
- async requestPersistentHandle() {
- const handle = await savePersistentAnchor(this);
- await restorePersistentAnchors(this[PRIVATE].session);
- return handle;
- }
-
- delete() {
- this[PRIVATE].session.deleteTrackedAnchor(this);
- }
-}
-
-export class XRAnchorSet extends Set {}
-
-export const savePersistentAnchor = async (anchor) => {
- const existingUUID = anchor[PRIVATE].session.getPersistentAnchorUUID(anchor);
- if (existingUUID) {
- return existingUUID;
- }
- const prefix = window.location.hostname + PRIVATE.toString();
- const anchorHandle = generateUUID();
- const matrix = Array.from(anchor[PRIVATE].anchorSpace._baseMatrix);
- await localforage.setItem(
- prefix + anchorHandle,
- JSON.stringify({ uuid: anchorHandle, matrixValue: matrix }),
- );
- return anchorHandle;
-};
-
-export const deletePersistentAnchor = async (uuid) => {
- const prefix = window.location.hostname + PRIVATE.toString();
- await localforage.removeItem(prefix + uuid);
-};
-
-export const restorePersistentAnchors = async (session) => {
- session.persistentAnchorsMap = new Map();
- const prefix = window.location.hostname + PRIVATE.toString();
- const keys = (await localforage.keys()).filter((key) =>
- key.startsWith(prefix),
- );
- keys.forEach(async (key) => {
- const { uuid, matrixValue } = JSON.parse(await localforage.getItem(key));
- const matrix = new Float32Array(matrixValue);
- const anchorSpace = new XRSpace();
- anchorSpace._baseMatrix = matrix;
- const anchor = new XRAnchor(session, anchorSpace);
- session.persistentAnchorsMap.set(uuid, anchor);
- });
-};
diff --git a/webxr-emulator/api/XRGamepadInput.js b/webxr-emulator/api/XRGamepadInput.js
deleted file mode 100644
index ba7370f..0000000
--- a/webxr-emulator/api/XRGamepadInput.js
+++ /dev/null
@@ -1,318 +0,0 @@
-import { mat4, quat, vec3 } from 'gl-matrix';
-
-import GamepadMappings from 'webxr-polyfill/src/devices/GamepadMappings';
-import OrientationArmModel from 'webxr-polyfill/src/lib/OrientationArmModel';
-import XRInputSource from './XRInputSource';
-import XRPose from 'webxr-polyfill/src/api/XRPose';
-import XRRigidTransform from 'webxr-polyfill/src/api/XRRigidTransform';
-
-export const PRIVATE = Symbol('@@webxr-polyfill/XRRemappedGamepad');
-
-const PLACEHOLDER_BUTTON = { pressed: false, touched: false, value: 0.0 };
-Object.freeze(PLACEHOLDER_BUTTON);
-
-export class XRRemappedGamepad {
- constructor(gamepad, display, map) {
- if (!map) {
- map = {};
- }
-
- // Apply user-agent-specific overrides to the mapping when applicable.
- if (map.userAgentOverrides) {
- for (const agent in map.userAgentOverrides) {
- if (navigator.userAgent.includes(agent)) {
- const override = map.userAgentOverrides[agent];
-
- for (const key in override) {
- if (key in map) {
- // If the key already exists, merge the override values into the
- // existing dictionary.
- Object.assign(map[key], override[key]);
- } else {
- // If the base mapping doesn't have this key, insert the override
- // values wholesale.
- map[key] = override[key];
- }
- }
- break;
- }
- }
- }
-
- const axes = new Array(
- map.axes && map.axes.length ? map.axes.length : gamepad.axes.length,
- );
- const buttons = new Array(
- map.buttons && map.buttons.length
- ? map.buttons.length
- : gamepad.buttons.length,
- );
-
- let gripTransform = null;
- if (map.gripTransform) {
- const orientation = map.gripTransform.orientation || [0, 0, 0, 1];
- gripTransform = mat4.create();
- mat4.fromRotationTranslation(
- gripTransform,
- quat.normalize(orientation, orientation),
- map.gripTransform.position || [0, 0, 0],
- );
- }
-
- let targetRayTransform = null;
- if (map.targetRayTransform) {
- const orientation = map.targetRayTransform.orientation || [0, 0, 0, 1];
- targetRayTransform = mat4.create();
- mat4.fromRotationTranslation(
- targetRayTransform,
- quat.normalize(orientation, orientation),
- map.targetRayTransform.position || [0, 0, 0],
- );
- }
-
- let profiles = map.profiles;
- if (map.displayProfiles) {
- if (display.displayName in map.displayProfiles) {
- profiles = map.displayProfiles[display.displayName];
- }
- }
-
- this[PRIVATE] = {
- gamepad,
- map,
- profiles: profiles || [gamepad.id],
- mapping: map.mapping || gamepad.mapping,
- axes,
- buttons,
- gripTransform,
- targetRayTransform,
- };
-
- this._update();
- }
-
- _update() {
- const gamepad = this[PRIVATE].gamepad;
- const map = this[PRIVATE].map;
-
- const axes = this[PRIVATE].axes;
- for (let i = 0; i < axes.length; ++i) {
- if (map.axes && i in map.axes) {
- if (map.axes[i] === null) {
- axes[i] = 0;
- } else {
- axes[i] = gamepad.axes[map.axes[i]];
- }
- } else {
- axes[i] = gamepad.axes[i];
- }
- }
-
- if (map.axes && map.axes.invert) {
- for (const axis of map.axes.invert) {
- if (axis < axes.length) {
- axes[axis] *= -1;
- }
- }
- }
-
- const buttons = this[PRIVATE].buttons;
- for (let i = 0; i < buttons.length; ++i) {
- if (map.buttons && i in map.buttons) {
- if (map.buttons[i] === null) {
- buttons[i] = PLACEHOLDER_BUTTON;
- } else {
- buttons[i] = gamepad.buttons[map.buttons[i]];
- }
- } else {
- buttons[i] = gamepad.buttons[i];
- }
- }
- }
-
- get id() {
- return '';
- }
-
- get _profiles() {
- return this[PRIVATE].profiles;
- }
-
- get index() {
- return -1;
- }
-
- get connected() {
- return this[PRIVATE].gamepad.connected;
- }
-
- get timestamp() {
- return this[PRIVATE].gamepad.timestamp;
- }
-
- get mapping() {
- return this[PRIVATE].mapping;
- }
-
- get axes() {
- return this[PRIVATE].axes;
- }
-
- get buttons() {
- return this[PRIVATE].buttons;
- }
-
- // Non-standard extension
- get hapticActuators() {
- return this[PRIVATE].gamepad.hapticActuators;
- }
-}
-
-export default class GamepadXRInputSource {
- constructor(
- polyfill,
- display,
- primaryButtonIndex = 0,
- primarySqueezeButtonIndex = -1,
- ) {
- this.polyfill = polyfill;
- this.display = display;
- this.nativeGamepad = null;
- this.gamepad = null;
- this.inputSource = new XRInputSource(this);
- this.lastPosition = vec3.create();
- this.emulatedPosition = false;
- this.basePoseMatrix = mat4.create();
- this.outputMatrix = mat4.create();
- this.primaryButtonIndex = primaryButtonIndex;
- this.primaryActionPressed = false;
- this.primarySqueezeButtonIndex = primarySqueezeButtonIndex;
- this.primarySqueezeActionPressed = false;
- this.handedness = '';
- this.targetRayMode = 'gaze';
- this.armModel = null;
- this.profilesOverride = null;
- }
-
- get profiles() {
- if (this.profilesOverride) {
- return this.profilesOverride;
- } else {
- return this.gamepad ? this.gamepad._profiles : [];
- }
- }
-
- updateFromGamepad(gamepad) {
- if (this.nativeGamepad !== gamepad) {
- this.nativeGamepad = gamepad;
- if (gamepad) {
- this.gamepad = new XRRemappedGamepad(
- gamepad,
- this.display,
- GamepadMappings[gamepad.id],
- );
- } else {
- this.gamepad = null;
- }
- }
- this.handedness = gamepad.hand === '' ? 'none' : gamepad.hand;
-
- if (this.gamepad) {
- this.gamepad._update();
- }
-
- if (gamepad.pose) {
- this.targetRayMode = 'tracked-pointer';
- this.emulatedPosition = !gamepad.pose.hasPosition;
- } else if (gamepad.hand === '') {
- this.targetRayMode = 'gaze';
- this.emulatedPosition = false;
- }
- }
-
- updateBasePoseMatrix() {
- if (this.nativeGamepad && this.nativeGamepad.pose) {
- const pose = this.nativeGamepad.pose;
- let position = pose.position;
- const orientation = pose.orientation;
- // On initialization, we might not have any values
- if (!position && !orientation) {
- return;
- }
- if (!position) {
- if (!pose.hasPosition) {
- if (!this.armModel) {
- this.armModel = new OrientationArmModel();
- }
-
- this.armModel.setHandedness(this.nativeGamepad.hand);
- this.armModel.update(orientation, this.polyfill.getBasePoseMatrix());
- position = this.armModel.getPosition();
- } else {
- position = this.lastPosition;
- }
- } else {
- // This is if we temporarily lose tracking, so the controller doesn't
- // snap back to the origin.
- this.lastPosition[0] = position[0];
- this.lastPosition[1] = position[1];
- this.lastPosition[2] = position[2];
- }
- mat4.fromRotationTranslation(this.basePoseMatrix, orientation, position);
- } else {
- mat4.copy(this.basePoseMatrix, this.polyfill.getBasePoseMatrix());
- }
- return this.basePoseMatrix;
- }
-
- /**
- * @param {XRReferenceSpace} coordinateSystem
- * @param {string} poseType
- * @return {XRPose?}
- */
- getXRPose(coordinateSystem, poseType) {
- this.updateBasePoseMatrix();
-
- switch (poseType) {
- case 'target-ray':
- coordinateSystem._transformBasePoseMatrix(
- this.outputMatrix,
- this.basePoseMatrix,
- );
- if (this.gamepad && this.gamepad[PRIVATE].targetRayTransform) {
- mat4.multiply(
- this.outputMatrix,
- this.outputMatrix,
- this.gamepad[PRIVATE].targetRayTransform,
- );
- }
- break;
- case 'grip':
- if (!this.nativeGamepad || !this.nativeGamepad.pose) {
- return null;
- }
- // TODO: Does the grip matrix need to be tweaked?
- coordinateSystem._transformBasePoseMatrix(
- this.outputMatrix,
- this.basePoseMatrix,
- );
- if (this.gamepad && this.gamepad[PRIVATE].gripTransform) {
- mat4.multiply(
- this.outputMatrix,
- this.outputMatrix,
- this.gamepad[PRIVATE].gripTransform,
- );
- }
- break;
- default:
- return null;
- }
-
- coordinateSystem._adjustForOriginOffset(this.outputMatrix);
-
- return new XRPose(
- new XRRigidTransform(this.outputMatrix),
- this.emulatedPosition,
- );
- }
-}
diff --git a/webxr-emulator/api/XRHand.js b/webxr-emulator/api/XRHand.js
deleted file mode 100644
index 5c2564e..0000000
--- a/webxr-emulator/api/XRHand.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import { XRJointSpace } from './XRJointSpace';
-
-export const XRHandJoint = {
- Wrist: 'wrist',
-
- ThumbMetacarpal: 'thumb-metacarpal',
- ThumbPhalanxProximal: 'thumb-phalanx-proximal',
- ThumbPhalanxDistal: 'thumb-phalanx-distal',
- ThumbTip: 'thumb-tip',
-
- IndexFingerMetacarpal: 'index-finger-metacarpal',
- IndexFingerPhalanxProximal: 'index-finger-phalanx-proximal',
- IndexFingerPhalanxIntermediate: 'index-finger-phalanx-intermediate',
- IndexFingerPhalanxDistal: 'index-finger-phalanx-distal',
- IndexFingerTip: 'index-finger-tip',
-
- MiddleFingerMetacarpal: 'middle-finger-metacarpal',
- MiddleFingerPhalanxProximal: 'middle-finger-phalanx-proximal',
- MiddleFingerPhalanxIntermediate: 'middle-finger-phalanx-intermediate',
- MiddleFingerPhalanxDistal: 'middle-finger-phalanx-distal',
- MiddleFingerTip: 'middle-finger-tip',
-
- RingFingerMetacarpal: 'ring-finger-metacarpal',
- RingFingerPhalanxProximal: 'ring-finger-phalanx-proximal',
- RingFingerPhalanxIntermediate: 'ring-finger-phalanx-intermediate',
- RingFingerPhalanxDistal: 'ring-finger-phalanx-distal',
- RingFingerTip: 'ring-finger-tip',
-
- PinkyFingerMetacarpal: 'pinky-finger-metacarpal',
- PinkyFingerPhalanxProximal: 'pinky-finger-phalanx-proximal',
- PinkyFingerPhalanxIntermediate: 'pinky-finger-phalanx-intermediate',
- PinkyFingerPhalanxDistal: 'pinky-finger-phalanx-distal',
- PinkyFingerTip: 'pinky-finger-tip',
-};
-
-export const PRIVATE = Symbol('@@webxr-polyfill/XRHand');
-
-export class XRHand extends Map {
- constructor(inputSource) {
- super();
- this[PRIVATE] = {
- inputSource,
- };
- Object.values(XRHandJoint).forEach((jointName) => {
- this.set(jointName, new XRJointSpace(jointName, this));
- });
- }
-}
diff --git a/webxr-emulator/api/XRHandInput.js b/webxr-emulator/api/XRHandInput.js
deleted file mode 100644
index 0d25424..0000000
--- a/webxr-emulator/api/XRHandInput.js
+++ /dev/null
@@ -1,139 +0,0 @@
-import { PRIVATE, XRRemappedGamepad } from './XRGamepadInput';
-import { mat4, vec3 } from 'gl-matrix';
-
-import GamepadMappings from 'webxr-polyfill/src/devices/GamepadMappings';
-import { XRHand } from './XRHand';
-import XRInputSource from './XRInputSource';
-import XRPose from 'webxr-polyfill/src/api/XRPose';
-import XRRigidTransform from 'webxr-polyfill/src/api/XRRigidTransform';
-
-export default class HandXRInputSource {
- constructor(polyfill) {
- this.polyfill = polyfill;
- this.nativeGamepad = null;
- this.gamepad = null;
- this.inputSource = new XRInputSource(this);
- this.lastPosition = vec3.create();
- this.emulatedPosition = false;
- this.basePoseMatrix = mat4.create();
- this.outputMatrix = mat4.create();
- this.primaryActionPressed = false;
- this.handedness = '';
- this.targetRayMode = 'gaze';
- this.armModel = null;
-
- this.hand = new XRHand(this.inputSource);
- }
-
- get profiles() {
- return [
- 'oculus-hand',
- 'generic-hand',
- 'generic-hand-select',
- 'generic-trigger',
- ];
- }
-
- updateFromGamepad(gamepad, pinchValue) {
- if (this.nativeGamepad !== gamepad) {
- this.nativeGamepad = gamepad;
- if (gamepad) {
- this.gamepad = new XRRemappedGamepad(
- gamepad,
- {},
- GamepadMappings[gamepad.id],
- );
- } else {
- this.gamepad = null;
- }
- }
- this.handedness = gamepad.hand === '' ? 'none' : gamepad.hand;
-
- if (this.gamepad) {
- this.gamepad._update();
- this.gamepad[PRIVATE].buttons = [
- {
- pressed: pinchValue == 1,
- touched: pinchValue > 0,
- value: pinchValue,
- },
- ];
- this.gamepad[PRIVATE].axes = [];
- }
-
- if (gamepad.pose) {
- this.targetRayMode = 'tracked-pointer';
- this.emulatedPosition = !gamepad.pose.hasPosition;
- } else if (gamepad.hand === '') {
- this.targetRayMode = 'gaze';
- this.emulatedPosition = false;
- }
- }
-
- updateBasePoseMatrix() {
- if (this.nativeGamepad && this.nativeGamepad.pose) {
- const pose = this.nativeGamepad.pose;
- const position = pose.position;
- const orientation = pose.orientation;
- // On initialization, we might not have any values
- if (!position && !orientation) {
- return;
- }
- mat4.fromRotationTranslation(this.basePoseMatrix, orientation, position);
- } else {
- mat4.copy(this.basePoseMatrix, this.polyfill.getBasePoseMatrix());
- }
- return this.basePoseMatrix;
- }
-
- /**
- * @param {XRReferenceSpace} coordinateSystem
- * @param {string} poseType
- * @return {XRPose?}
- */
- getXRPose(coordinateSystem, poseType) {
- this.updateBasePoseMatrix();
-
- switch (poseType) {
- case 'target-ray':
- coordinateSystem._transformBasePoseMatrix(
- this.outputMatrix,
- this.basePoseMatrix,
- );
- if (this.gamepad && this.gamepad[PRIVATE].targetRayTransform) {
- mat4.multiply(
- this.outputMatrix,
- this.outputMatrix,
- this.gamepad[PRIVATE].targetRayTransform,
- );
- }
- break;
- case 'grip':
- if (!this.nativeGamepad || !this.nativeGamepad.pose) {
- return null;
- }
- // TODO: Does the grip matrix need to be tweaked?
- coordinateSystem._transformBasePoseMatrix(
- this.outputMatrix,
- this.basePoseMatrix,
- );
- if (this.gamepad && this.gamepad[PRIVATE].gripTransform) {
- mat4.multiply(
- this.outputMatrix,
- this.outputMatrix,
- this.gamepad[PRIVATE].gripTransform,
- );
- }
- break;
- default:
- return null;
- }
-
- coordinateSystem._adjustForOriginOffset(this.outputMatrix);
-
- return new XRPose(
- new XRRigidTransform(this.outputMatrix),
- this.emulatedPosition,
- );
- }
-}
diff --git a/webxr-emulator/api/XRHitTestResult.js b/webxr-emulator/api/XRHitTestResult.js
deleted file mode 100644
index bc61bf6..0000000
--- a/webxr-emulator/api/XRHitTestResult.js
+++ /dev/null
@@ -1,36 +0,0 @@
-export const PRIVATE = Symbol('@@webxr-polyfill/XRHitTestResult');
-
-import { XRAnchor } from './XRAnchor';
-import { PRIVATE as XRFRAME_PRIVATE } from 'webxr-polyfill/src/api/XRFrame';
-import XRSpace from 'webxr-polyfill/src/api/XRSpace';
-import { mat4 } from 'gl-matrix';
-
-export default class XRHitTestResult {
- constructor(frame, transform) {
- this[PRIVATE] = {
- frame,
- transform,
- };
- }
-
- getPose(baseSpace) {
- const space = new XRSpace();
- space._baseMatrix = mat4.copy(
- mat4.create(),
- this[PRIVATE].transform.matrix,
- );
- return this[PRIVATE].frame.getPose(space, baseSpace);
- }
-
- async createAnchor() {
- const anchorSpace = new XRSpace();
- anchorSpace._baseMatrix = mat4.copy(
- mat4.create(),
- this[PRIVATE].transform.matrix,
- );
- const session = this[PRIVATE].frame[XRFRAME_PRIVATE].session;
- const anchor = new XRAnchor(session, anchorSpace);
- session.addTrackedAnchor(anchor);
- return anchor;
- }
-}
diff --git a/webxr-emulator/api/XRHitTestSource.js b/webxr-emulator/api/XRHitTestSource.js
deleted file mode 100644
index ed5026f..0000000
--- a/webxr-emulator/api/XRHitTestSource.js
+++ /dev/null
@@ -1,39 +0,0 @@
-export const PRIVATE = Symbol('@@webxr-polyfill/XRHitTestSource');
-
-import XRRay from './XRRay';
-
-export default class XRHitTestSource {
- constructor(session, options) {
- // @TODO: Support options.entityTypes and options.offsetRay
- // if (options.entityTypes && options.entityTypes.length > 0) {
- // throw new Error('XRHitTestSource does not support entityTypes option yet.');
- // }
- this[PRIVATE] = {
- session,
- space: options.space,
- offsetRay: options.offsetRay || new XRRay(),
- active: true
- };
- }
-
- cancel() {
- // @TODO: Throw InvalidStateError if active is already false
- this[PRIVATE].active = false;
- }
-
- get _space() {
- return this[PRIVATE].space;
- }
-
- get _session() {
- return this[PRIVATE].session;
- }
-
- get _offsetRay() {
- return this[PRIVATE].offsetRay;
- }
-
- get _active() {
- return this[PRIVATE].active;
- }
-}
diff --git a/webxr-emulator/api/XRInputSource.js b/webxr-emulator/api/XRInputSource.js
deleted file mode 100644
index cf93268..0000000
--- a/webxr-emulator/api/XRInputSource.js
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2018 Google Inc. All Rights Reserved.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import XRSpace from 'webxr-polyfill/src/api/XRSpace';
-
-export const PRIVATE = Symbol('@@webxr-polyfill/XRInputSource');
-
-export default class XRInputSource {
- /**
- * @param {GamepadXRInputSource} impl
- */
- constructor(impl) {
- this[PRIVATE] = {
- impl,
- gripSpace: new XRSpace('grip', this),
- targetRaySpace: new XRSpace('target-ray', this),
- };
- }
-
- /**
- * @return {XRHandedness}
- */
- get handedness() {
- return this[PRIVATE].impl.handedness;
- }
-
- /**
- * @return {XRTargetRayMode}
- */
- get targetRayMode() {
- return this[PRIVATE].impl.targetRayMode;
- }
-
- /**
- * @return {XRSpace}
- */
- get gripSpace() {
- const mode = this[PRIVATE].impl.targetRayMode;
- if (mode === 'gaze' || mode === 'screen') {
- // grip space must be null for non-trackable input sources
- return null;
- }
- return this[PRIVATE].gripSpace;
- }
-
- /**
- * @return {XRSpace}
- */
- get targetRaySpace() {
- return this[PRIVATE].targetRaySpace;
- }
-
- /**
- * @return {Array}
- */
- get profiles() {
- return this[PRIVATE].impl.profiles;
- }
-
- /**
- * @return {Gamepad}
- */
- get gamepad() {
- return this[PRIVATE].impl.gamepad;
- }
-
- /**
- * @return {XRHand}
- */
- get hand() {
- return this[PRIVATE].impl.hand;
- }
-}
diff --git a/webxr-emulator/api/XRJointPose.js b/webxr-emulator/api/XRJointPose.js
deleted file mode 100644
index 83a54c5..0000000
--- a/webxr-emulator/api/XRJointPose.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import XRPose from 'webxr-polyfill/src/api/XRPose';
-
-export const PRIVATE = Symbol('@@webxr-polyfill/XRJointPose');
-
-export class XRJointPose extends XRPose {
- constructor(transform, radius) {
- super(transform);
- this[PRIVATE] = {
- radius,
- };
- }
-
- get radius() {
- return this[PRIVATE].radius;
- }
-}
diff --git a/webxr-emulator/api/XRJointSpace.js b/webxr-emulator/api/XRJointSpace.js
deleted file mode 100644
index c0c31a9..0000000
--- a/webxr-emulator/api/XRJointSpace.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import XRSpace from 'webxr-polyfill/src/api/XRSpace';
-
-export const PRIVATE = Symbol('@@webxr-polyfill/XRJointSpace');
-
-export class XRJointSpace extends XRSpace {
- constructor(jointName, xrhand) {
- super();
- this[PRIVATE] = {
- jointName,
- xrhand,
- };
- }
-
- get jointName() {
- return this[PRIVATE].jointName;
- }
-}
diff --git a/webxr-emulator/api/XRMesh.js b/webxr-emulator/api/XRMesh.js
deleted file mode 100644
index 90026d1..0000000
--- a/webxr-emulator/api/XRMesh.js
+++ /dev/null
@@ -1,73 +0,0 @@
-import { mat4 } from 'gl-matrix';
-
-/**
- * @see https://immersive-web.github.io/real-world-meshing/
- */
-export class XRMesh {
- /**
- * @param {import('webxr-polyfill/src/api/XRSpace').default} planeSpace
- * @param {Float32Array} pointArray
- * @param {Float32Array} indexArray
- * @param {string} semanticLabel
- */
- constructor(meshSpace, vertices, indices, semanticLabel) {
- this._meshSpace = meshSpace;
- this._vertices = vertices;
- this._indices = indices;
- this._lastChangedTime = performance.now();
- this._semanticLabel = semanticLabel;
- }
-
- /**
- * @type {import('webxr-polyfill/src/api/XRSpace').default}
- * @readonly
- */
- get meshSpace() {
- return this._meshSpace;
- }
-
- /**
- * @type {Float32Array}
- * @readonly
- */
- get vertices() {
- return this._vertices;
- }
-
- /**
- * @type {Float32Array}
- * @readonly
- */
- get indices() {
- return this._indices;
- }
-
- /**
- * @type {DOMHighResTimeStamp}
- * @readonly
- */
- get lastChangedTime() {
- return this._lastChangedTime;
- }
-
- /**
- * @type {string}
- * @readonly
- */
- get semanticLabel() {
- return this._semanticLabel;
- }
-
- /**
- * non-standard
- * @param {number[]} position
- * @param {number[]} quaternion
- */
- _updateMatrix(position, quaternion) {
- const meshMatrix = new Float32Array(16);
- mat4.fromRotationTranslation(meshMatrix, quaternion, position);
- this._meshSpace._baseMatrix = meshMatrix;
- }
-}
-
-export class XRMeshSet extends Set {}
diff --git a/webxr-emulator/api/XRPlane.js b/webxr-emulator/api/XRPlane.js
deleted file mode 100644
index c932e2b..0000000
--- a/webxr-emulator/api/XRPlane.js
+++ /dev/null
@@ -1,83 +0,0 @@
-import { mat4 } from 'gl-matrix';
-
-/**
- * @see https://immersive-web.github.io/real-world-geometry/plane-detection.html#plane-orientation
- * @enum {string}
- */
-export const XRPlaneOrientation = {
- Horizontal: 'horizontal',
- Vertical: 'vertical',
-};
-
-/**
- * @see https://immersive-web.github.io/real-world-geometry/plane-detection.html#plane
- */
-export class XRPlane {
- /**
- * @param {import('webxr-polyfill/src/api/XRSpace').default} planeSpace
- * @param {DOMPointReadOnly[]} pointArray
- * @param {XRPlaneOrientation} orientation
- * @param {string} semanticLabel
- */
- constructor(planeSpace, pointArray, orientation, semanticLabel) {
- this._planeSpace = planeSpace;
- this._polygon = pointArray;
- Object.freeze(this._polygon);
- this._orientation = orientation;
- this._lastChangedTime = performance.now();
- this._semanticLabel = semanticLabel;
- }
-
- /**
- * @type {import('webxr-polyfill/src/api/XRSpace').default}
- * @readonly
- */
- get planeSpace() {
- return this._planeSpace;
- }
-
- /**
- * @type {DOMPointReadOnly[]}
- * @readonly
- */
- get polygon() {
- return this._polygon;
- }
-
- /**
- * @type {XRPlaneOrientation}
- * @readonly
- */
- get orientation() {
- return this._orientation;
- }
-
- /**
- * @type {DOMHighResTimeStamp}
- * @readonly
- */
- get lastChangedTime() {
- return this._lastChangedTime;
- }
-
- /**
- * @type {string}
- * @readonly
- */
- get semanticLabel() {
- return this._semanticLabel;
- }
-
- /**
- * non-standard
- * @param {number[]} position
- * @param {number[]} quaternion
- */
- _updateMatrix(position, quaternion) {
- const meshMatrix = new Float32Array(16);
- mat4.fromRotationTranslation(meshMatrix, quaternion, position);
- this._planeSpace._baseMatrix = meshMatrix;
- }
-}
-
-export class XRPlaneSet extends Set {}
diff --git a/webxr-emulator/api/XRRay.js b/webxr-emulator/api/XRRay.js
deleted file mode 100644
index 10b1992..0000000
--- a/webxr-emulator/api/XRRay.js
+++ /dev/null
@@ -1,120 +0,0 @@
-export const PRIVATE = Symbol('@@webxr-polyfill/XRRay');
-
-import { mat4, vec3, vec4 } from 'gl-matrix';
-
-import XRRigidTransform from 'webxr-polyfill/src/api/XRRigidTransform';
-
-export default class XRRay {
- constructor(origin, direction) {
- const _origin = { x: 0, y: 0, z: 0, w: 1 };
- const _direction = { x: 0, y: 0, z: -1, w: 0 };
-
- if (origin && origin instanceof XRRigidTransform) {
- const transform = origin;
- const matrix = transform.matrix;
- const originVec4 = vec4.set(
- vec4.create(),
- _origin.x,
- _origin.y,
- _origin.z,
- _origin.w,
- );
- const directionVec4 = vec4.set(
- vec4.create(),
- _direction.x,
- _direction.y,
- _direction.z,
- _direction.w,
- );
- vec4.transformMat4(originVec4, originVec4, matrix);
- vec4.transformMat4(directionVec4, directionVec4, matrix);
- _origin.x = originVec4[0];
- _origin.y = originVec4[1];
- _origin.z = originVec4[2];
- _origin.w = originVec4[3];
- _direction.x = directionVec4[0];
- _direction.y = directionVec4[1];
- _direction.z = directionVec4[2];
- _direction.w = directionVec4[3];
- } else {
- if (origin) {
- _origin.x = origin.x;
- _origin.y = origin.y;
- _origin.z = origin.z;
- _origin.w = origin.w;
- }
- if (direction) {
- _direction.x = direction.x;
- _direction.y = direction.y;
- _direction.z = direction.z;
- _direction.w = direction.w;
- }
- }
-
- // Normalize direction
- const length =
- Math.sqrt(
- _direction.x * _direction.x +
- _direction.y * _direction.y +
- _direction.z * _direction.z,
- ) || 1;
- _direction.x = _direction.x / length;
- _direction.y = _direction.y / length;
- _direction.z = _direction.z / length;
-
- this[PRIVATE] = {
- origin: new DOMPointReadOnly(_origin.x, _origin.y, _origin.z, _origin.w),
- direction: new DOMPointReadOnly(
- _direction.x,
- _direction.y,
- _direction.z,
- _direction.w,
- ),
- matrix: null,
- };
- }
-
- get origin() {
- return this[PRIVATE].origin;
- }
-
- get direction() {
- return this[PRIVATE].direction;
- }
-
- get matrix() {
- if (this[PRIVATE].matrix) {
- return this[PRIVATE].matrix;
- }
- // @TODO: Check if the calculation is correct
- const z = vec3.set(vec3.create(), 0, 0, -1);
- const origin = vec3.set(
- vec3.create(),
- this[PRIVATE].origin.x,
- this[PRIVATE].origin.y,
- this[PRIVATE].origin.z,
- );
- const direction = vec3.set(
- vec3.create(),
- this[PRIVATE].direction.x,
- this[PRIVATE].direction.y,
- this[PRIVATE].direction.z,
- );
- const axis = vec3.cross(vec3.create(), direction, z);
- const cosAngle = vec3.dot(direction, z);
- const rotation = mat4.create();
- if (cosAngle > -1 && cosAngle < 1) {
- mat4.fromRotation(rotation, Math.acos(cosAngle), axis);
- } else if (cosAngle === -1) {
- mat4.fromRotation(
- rotation,
- Math.acos(cosAngle),
- vec3.set(vec3.create(), 1, 0, 0),
- );
- }
- const translation = mat4.fromTranslation(mat4.create(), origin);
- const matrix = mat4.multiply(mat4.create(), translation, rotation);
- this[PRIVATE].matrix = matrix;
- return matrix;
- }
-}
diff --git a/webxr-emulator/api/XRTransientInputHitTestResult.js b/webxr-emulator/api/XRTransientInputHitTestResult.js
deleted file mode 100644
index f66ea7d..0000000
--- a/webxr-emulator/api/XRTransientInputHitTestResult.js
+++ /dev/null
@@ -1,19 +0,0 @@
-export const PRIVATE = Symbol('@@webxr-polyfill/XRTransientInputHitTestResult');
-
-export default class XRTransientInputHitTestResult {
- constructor(frame, results, inputSource) {
- this[PRIVATE] = {
- frame,
- inputSource,
- results,
- };
- }
-
- get inputSource() {
- return this[PRIVATE].inputSource;
- }
-
- get results() {
- return this[PRIVATE].results;
- }
-}
diff --git a/webxr-emulator/api/XRTransientInputHitTestSource.js b/webxr-emulator/api/XRTransientInputHitTestSource.js
deleted file mode 100644
index f7a2eca..0000000
--- a/webxr-emulator/api/XRTransientInputHitTestSource.js
+++ /dev/null
@@ -1,41 +0,0 @@
-export const PRIVATE = Symbol('@@webxr-polyfill/XRTransientInputHitTestSource');
-
-import XRRay from './XRRay';
-
-export default class XRTransientInputHitTestSource {
- constructor(session, options) {
- // @TODO: Support options.entityTypes and options.offsetRay
- if (options.entityTypes && options.entityTypes.length > 0) {
- throw new Error(
- 'XRHitTestSource does not support entityTypes option yet.',
- );
- }
- this[PRIVATE] = {
- session,
- profile: options.profile,
- offsetRay: options.offsetRay || new XRRay(),
- active: true,
- };
- }
-
- cancel() {
- // @TODO: Throw InvalidStateError if active is already false
- this[PRIVATE].active = false;
- }
-
- get _profile() {
- return this[PRIVATE].profile;
- }
-
- get _session() {
- return this[PRIVATE].session;
- }
-
- get _offsetRay() {
- return this[PRIVATE].offsetRay;
- }
-
- get _active() {
- return this[PRIVATE].active;
- }
-}
diff --git a/webxr-emulator/api/handPose.js b/webxr-emulator/api/handPose.js
deleted file mode 100644
index caf34df..0000000
--- a/webxr-emulator/api/handPose.js
+++ /dev/null
@@ -1,669 +0,0 @@
-export const handPose = {
- wrist: {
- radius: 0.021460847929120064,
- transform: [0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -0.037, 0.065, 0.002, 1],
- },
- 'thumb-metacarpal': {
- radius: 0.019382517784833908,
- transform: [
- 0.262, -0.498, 0.827, 0, 0.912, 0.408, -0.043, 0, -0.315, 0.765, 0.561, 0,
- -0.018, 0.03, -0.026, 1,
- ],
- },
- 'thumb-phalanx-proximal': {
- radius: 0.01228295173496008,
- transform: [
- 0.306, -0.143, 0.941, 0, 0.9, 0.367, -0.237, 0, -0.311, 0.919, 0.241, 0,
- -0.008, 0.005, -0.045, 1,
- ],
- },
- 'thumb-phalanx-distal': {
- radius: 0.009768804535269737,
- transform: [
- 0.083, -0.018, 0.996, 0, 0.892, 0.448, -0.066, 0, -0.445, 0.894, 0.054, 0,
- 0.002, -0.026, -0.053, 1,
- ],
- },
- 'thumb-tip': {
- radius: 0.008768804371356964,
- transform: [
- 0.083, -0.018, 0.996, 0, 0.892, 0.448, -0.066, 0, -0.445, 0.894, 0.054, 0,
- 0.013, -0.049, -0.055, 1,
- ],
- },
- 'index-finger-metacarpal': {
- radius: 0.021228281781077385,
- transform: [0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -0.026, 0.028, -0.017, 1],
- },
- 'index-finger-phalanx-proximal': {
- radius: 0.010295259766280651,
- transform: [
- 0.066, -0.039, -0.997, 0, -0.981, -0.184, -0.058, 0, -0.181, 0.982, -0.05,
- 0, -0.029, -0.031, -0.021, 1,
- ],
- },
- 'index-finger-phalanx-intermediate': {
- radius: 0.00853810179978609,
- transform: [
- 0.018, -0.062, -0.998, 0, -0.914, -0.406, 0.008, 0, -0.406, 0.912, -0.064,
- 0, -0.022, -0.068, -0.019, 1,
- ],
- },
- 'index-finger-phalanx-distal': {
- radius: 0.007636196445673704,
- transform: [
- 0.01, -0.122, -0.992, 0, -0.896, -0.442, 0.045, 0, -0.444, 0.888, -0.114,
- 0, -0.013, -0.09, -0.018, 1,
- ],
- },
- 'index-finger-tip': {
- radius: 0.006636196281760931,
- transform: [
- 0.01, -0.122, -0.992, 0, -0.896, -0.442, 0.045, 0, -0.444, 0.888, -0.114,
- 0, -0.004, -0.11, -0.015, 1,
- ],
- },
- 'middle-finger-metacarpal': {
- radius: 0.021231964230537415,
- transform: [0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -0.028, 0.03, -0.001, 1],
- },
- 'middle-finger-phalanx-proximal': {
- radius: 0.01117393933236599,
- transform: [
- -0.009, -0.166, -0.986, 0, -0.945, -0.322, 0.063, 0, -0.328, 0.932,
- -0.154, 0, -0.034, -0.03, 0.001, 1,
- ],
- },
- 'middle-finger-phalanx-intermediate': {
- radius: 0.008030958473682404,
- transform: [
- -0.027, -0.182, -0.983, 0, -0.87, -0.48, 0.113, 0, -0.493, 0.858, -0.145,
- 0, -0.02, -0.07, 0.007, 1,
- ],
- },
- 'middle-finger-phalanx-distal': {
- radius: 0.007629410829395056,
- transform: [
- -0.099, -0.222, -0.97, 0, -0.885, -0.426, 0.188, 0, -0.455, 0.877, -0.154,
- 0, -0.006, -0.094, 0.011, 1,
- ],
- },
- 'middle-finger-tip': {
- radius: 0.006629410665482283,
- transform: [
- -0.099, -0.222, -0.97, 0, -0.885, -0.426, 0.188, 0, -0.455, 0.877, -0.154,
- 0, 0.004, -0.116, 0.016, 1,
- ],
- },
- 'ring-finger-metacarpal': {
- radius: 0.019088275730609894,
- transform: [0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -0.031, 0.03, 0.017, 1],
- },
- 'ring-finger-phalanx-proximal': {
- radius: 0.00992213748395443,
- transform: [
- -0.088, -0.279, -0.956, 0, -0.919, -0.347, 0.186, 0, -0.384, 0.895,
- -0.226, 0, -0.03, -0.023, 0.02, 1,
- ],
- },
- 'ring-finger-phalanx-intermediate': {
- radius: 0.007611672393977642,
- transform: [
- -0.15, -0.308, -0.939, 0, -0.844, -0.454, 0.284, 0, -0.514, 0.836, -0.192,
- 0, -0.015, -0.058, 0.029, 1,
- ],
- },
- 'ring-finger-phalanx-distal': {
- radius: 0.007231088820844889,
- transform: [
- -0.194, -0.266, -0.944, 0, -0.79, -0.528, 0.311, 0, -0.582, 0.806, -0.108,
- 0, -0.001, -0.081, 0.034, 1,
- ],
- },
- 'ring-finger-tip': {
- radius: 0.0062310886569321156,
- transform: [
- -0.194, -0.266, -0.944, 0, -0.79, -0.528, 0.311, 0, -0.582, 0.806, -0.108,
- 0, 0.012, -0.101, 0.037, 1,
- ],
- },
- 'pinky-finger-metacarpal': {
- radius: 0.01808827556669712,
- transform: [
- -0.396, -0.279, -0.875, 0, -0.914, 0.023, 0.406, 0, -0.094, 0.96, -0.264,
- 0, -0.027, 0.031, 0.025, 1,
- ],
- },
- 'pinky-finger-phalanx-proximal': {
- radius: 0.008483353070914745,
- transform: [
- -0.225, -0.362, -0.905, 0, -0.881, -0.321, 0.348, 0, -0.417, 0.875,
- -0.246, 0, -0.023, -0.013, 0.037, 1,
- ],
- },
- 'pinky-finger-phalanx-intermediate': {
- radius: 0.0067641944624483585,
- transform: [
- -0.263, -0.461, -0.847, 0, -0.772, -0.426, 0.472, 0, -0.579, 0.778,
- -0.244, 0, -0.01, -0.04, 0.045, 1,
- ],
- },
- 'pinky-finger-phalanx-distal': {
- radius: 0.0064259846694767475,
- transform: [
- -0.318, -0.383, -0.867, 0, -0.762, -0.441, 0.474, 0, -0.564, 0.812,
- -0.151, 0, 0.002, -0.055, 0.05, 1,
- ],
- },
- 'pinky-finger-tip': {
- radius: 0.005425984505563974,
- transform: [
- -0.318, -0.383, -0.867, 0, -0.762, -0.441, 0.474, 0, -0.564, 0.812,
- -0.151, 0, 0.013, -0.074, 0.054, 1,
- ],
- },
-};
-
-export const pinchHandPose = {
- wrist: {
- radius: 0.021460847929120064,
- transform: [0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -0.037, 0.066, 0, 1],
- },
- 'thumb-metacarpal': {
- radius: 0.019382517784833908,
- transform: [
- -0.095, -0.306, 0.947, 0, 0.764, 0.587, 0.266, 0, -0.638, 0.749, 0.178, 0,
- -0.013, 0.028, -0.021, 1,
- ],
- },
- 'thumb-phalanx-proximal': {
- radius: 0.01228295173496008,
- transform: [
- -0.141, 0.041, 0.989, 0, 0.85, 0.517, 0.1, 0, -0.508, 0.855, -0.108, 0,
- 0.008, 0.003, -0.026, 1,
- ],
- },
- 'thumb-phalanx-distal': {
- radius: 0.009768804535269737,
- transform: [
- -0.338, 0.052, 0.94, 0, 0.751, 0.616, 0.237, 0, -0.567, 0.786, -0.247, 0,
- 0.025, -0.026, -0.023, 1,
- ],
- },
- 'thumb-tip': {
- radius: 0.008768804371356964,
- transform: [
- -0.338, 0.052, 0.94, 0, 0.751, 0.616, 0.237, 0, -0.567, 0.786, -0.247, 0,
- 0.039, -0.045, -0.018, 1,
- ],
- },
- 'index-finger-metacarpal': {
- radius: 0.021228281781077385,
- transform: [0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -0.024, 0.028, -0.015, 1],
- },
- 'index-finger-phalanx-proximal': {
- radius: 0.010295259766280651,
- transform: [
- 0.074, 0.097, -0.993, 0, -0.737, -0.665, -0.12, 0, -0.672, 0.74, 0.022, 0,
- -0.03, -0.03, -0.023, 1,
- ],
- },
- 'index-finger-phalanx-intermediate': {
- radius: 0.00853810179978609,
- transform: [
- 0.046, 0.054, -0.997, 0, 0.161, -0.986, -0.046, 0, -0.986, -0.158, -0.054,
- 0, -0.005, -0.058, -0.024, 1,
- ],
- },
- 'index-finger-phalanx-distal': {
- radius: 0.007636196445673704,
- transform: [
- 0.1, 0.037, -0.994, 0, 0.497, -0.867, 0.018, 0, -0.862, -0.496, -0.105, 0,
- 0.019, -0.054, -0.023, 1,
- ],
- },
- 'index-finger-tip': {
- radius: 0.006636196281760931,
- transform: [
- 0.1, 0.037, -0.994, 0, 0.497, -0.867, 0.018, 0, -0.862, -0.496, -0.105, 0,
- 0.039, -0.044, -0.02, 1,
- ],
- },
- 'middle-finger-metacarpal': {
- radius: 0.021231964230537415,
- transform: [0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -0.028, 0.03, 0.001, 1],
- },
- 'middle-finger-phalanx-proximal': {
- radius: 0.01117393933236599,
- transform: [
- -0.014, -0.044, -0.999, 0, -0.96, -0.279, 0.026, 0, -0.28, 0.959, -0.038,
- 0, -0.035, -0.03, -0.001, 1,
- ],
- },
- 'middle-finger-phalanx-intermediate': {
- radius: 0.008030958473682404,
- transform: [
- -0.034, -0.059, -0.998, 0, -0.773, -0.631, 0.064, 0, -0.634, 0.773,
- -0.024, 0, -0.023, -0.071, 0, 1,
- ],
- },
- 'middle-finger-phalanx-distal': {
- radius: 0.007629410829395056,
- transform: [
- -0.1, -0.114, -0.988, 0, -0.775, -0.614, 0.149, 0, -0.624, 0.781, -0.027,
- 0, -0.005, -0.092, 0.001, 1,
- ],
- },
- 'middle-finger-tip': {
- radius: 0.006629410665482283,
- transform: [
- -0.1, -0.114, -0.988, 0, -0.775, -0.614, 0.149, 0, -0.624, 0.781, -0.027,
- 0, 0.009, -0.112, 0.002, 1,
- ],
- },
- 'ring-finger-metacarpal': {
- radius: 0.019088275730609894,
- transform: [0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -0.031, 0.031, 0.015, 1],
- },
- 'ring-finger-phalanx-proximal': {
- radius: 0.00992213748395443,
- transform: [
- -0.095, -0.202, -0.975, 0, -0.972, -0.193, 0.135, 0, -0.215, 0.96, -0.178,
- 0, -0.031, -0.023, 0.018, 1,
- ],
- },
- 'ring-finger-phalanx-intermediate': {
- radius: 0.007611672393977642,
- transform: [
- -0.166, -0.223, -0.961, 0, -0.825, -0.503, 0.259, 0, -0.541, 0.835, -0.1,
- 0, -0.022, -0.06, 0.025, 1,
- ],
- },
- 'ring-finger-phalanx-distal': {
- radius: 0.007231088820844889,
- transform: [
- -0.213, -0.183, -0.96, 0, -0.748, -0.601, 0.28, 0, -0.628, 0.778, -0.009,
- 0, -0.008, -0.082, 0.027, 1,
- ],
- },
- 'ring-finger-tip': {
- radius: 0.0062310886569321156,
- transform: [
- -0.213, -0.183, -0.96, 0, -0.748, -0.601, 0.28, 0, -0.628, 0.778, -0.009,
- 0, 0.006, -0.102, 0.028, 1,
- ],
- },
- 'pinky-finger-metacarpal': {
- radius: 0.01808827556669712,
- transform: [
- -0.396, -0.279, -0.875, 0, -0.914, 0.023, 0.406, 0, -0.094, 0.96, -0.264,
- 0, -0.028, 0.032, 0.023, 1,
- ],
- },
- 'pinky-finger-phalanx-proximal': {
- radius: 0.008483353070914745,
- transform: [
- -0.219, -0.358, -0.908, 0, -0.933, -0.194, 0.302, 0, -0.284, 0.913,
- -0.291, 0, -0.024, -0.012, 0.035, 1,
- ],
- },
- 'pinky-finger-phalanx-intermediate': {
- radius: 0.0067641944624483585,
- transform: [
- -0.277, -0.452, -0.848, 0, -0.784, -0.404, 0.472, 0, -0.556, 0.795,
- -0.242, 0, -0.015, -0.04, 0.044, 1,
- ],
- },
- 'pinky-finger-phalanx-distal': {
- radius: 0.0064259846694767475,
- transform: [
- -0.333, -0.373, -0.866, 0, -0.722, -0.49, 0.489, 0, -0.607, 0.788, -0.106,
- 0, -0.004, -0.056, 0.049, 1,
- ],
- },
- 'pinky-finger-tip': {
- radius: 0.005425984505563974,
- transform: [
- -0.333, -0.373, -0.866, 0, -0.722, -0.49, 0.489, 0, -0.607, 0.788, -0.106,
- 0, 0.009, -0.074, 0.052, 1,
- ],
- },
-};
-
-export const pointHandPose = {
- wrist: {
- radius: 0.021460847929120064,
- transform: [0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -0.037, 0.066, 0.002, 1],
- },
- 'thumb-metacarpal': {
- radius: 0.019382517784833908,
- transform: [
- 0.105, -0.416, 0.903, 0, 0.84, 0.524, 0.144, 0, -0.533, 0.743, 0.405, 0,
- -0.016, 0.029, -0.024, 1,
- ],
- },
- 'thumb-phalanx-proximal': {
- radius: 0.01228295173496008,
- transform: [
- -0.115, 0.252, 0.961, 0, 0.88, 0.475, -0.019, 0, -0.461, 0.843, -0.276, 0,
- 0.002, 0.004, -0.037, 1,
- ],
- },
- 'thumb-phalanx-distal': {
- radius: 0.009768804535269737,
- transform: [
- -0.531, 0.705, 0.47, 0, 0.815, 0.577, 0.056, 0, -0.232, 0.413, -0.881, 0,
- 0.017, -0.024, -0.028, 1,
- ],
- },
- 'thumb-tip': {
- radius: 0.008768804371356964,
- transform: [
- -0.531, 0.705, 0.47, 0, 0.815, 0.577, 0.056, 0, -0.232, 0.413, -0.881, 0,
- 0.023, -0.035, -0.007, 1,
- ],
- },
- 'index-finger-metacarpal': {
- radius: 0.021228281781077385,
- transform: [0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -0.025, 0.028, -0.016, 1],
- },
- 'index-finger-phalanx-proximal': {
- radius: 0.010295259766280651,
- transform: [
- 0.066, -0.02, -0.998, 0, -0.976, -0.211, -0.06, 0, -0.21, 0.977, -0.033,
- 0, -0.03, -0.03, -0.022, 1,
- ],
- },
- 'index-finger-phalanx-intermediate': {
- radius: 0.00853810179978609,
- transform: [
- 0.019, -0.045, -0.999, 0, -0.928, -0.374, -0.001, 0, -0.373, 0.926,
- -0.049, 0, -0.022, -0.067, -0.021, 1,
- ],
- },
- 'index-finger-phalanx-distal': {
- radius: 0.007636196445673704,
- transform: [
- 0.006, -0.106, -0.994, 0, -0.956, -0.294, 0.025, 0, -0.295, 0.95, -0.103,
- 0, -0.013, -0.09, -0.02, 1,
- ],
- },
- 'index-finger-tip': {
- radius: 0.006636196281760931,
- transform: [
- 0.006, -0.106, -0.994, 0, -0.956, -0.294, 0.025, 0, -0.295, 0.95, -0.103,
- 0, -0.007, -0.111, -0.017, 1,
- ],
- },
- 'middle-finger-metacarpal': {
- radius: 0.021231964230537415,
- transform: [0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -0.028, 0.03, 0, 1],
- },
- 'middle-finger-phalanx-proximal': {
- radius: 0.01117393933236599,
- transform: [
- -0.006, -0.157, -0.988, 0, -0.314, -0.937, 0.151, 0, -0.949, 0.311,
- -0.044, 0, -0.034, -0.03, 0, 1,
- ],
- },
- 'middle-finger-phalanx-intermediate': {
- radius: 0.008030958473682404,
- transform: [
- -0.003, -0.183, -0.983, 0, 0.99, -0.142, 0.024, 0, -0.144, -0.973, 0.182,
- 0, 0.006, -0.043, 0.002, 1,
- ],
- },
- 'middle-finger-phalanx-distal': {
- radius: 0.007629410829395056,
- transform: [
- 0.174, -0.155, -0.972, 0, 0.593, 0.805, -0.022, 0, 0.786, -0.573, 0.232,
- 0, 0.01, -0.017, -0.003, 1,
- ],
- },
- 'middle-finger-tip': {
- radius: 0.006629410665482283,
- transform: [
- 0.174, -0.155, -0.972, 0, 0.593, 0.805, -0.022, 0, 0.786, -0.573, 0.232,
- 0, -0.009, -0.001, -0.009, 1,
- ],
- },
- 'ring-finger-metacarpal': {
- radius: 0.019088275730609894,
- transform: [0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -0.031, 0.031, 0.017, 1],
- },
- 'ring-finger-phalanx-proximal': {
- radius: 0.00992213748395443,
- transform: [
- -0.087, -0.215, -0.973, 0, -0.186, -0.956, 0.228, 0, -0.979, 0.201, 0.043,
- 0, -0.03, -0.023, 0.019, 1,
- ],
- },
- 'ring-finger-phalanx-intermediate': {
- radius: 0.007611672393977642,
- transform: [
- -0.074, -0.305, -0.949, 0, 0.991, -0.126, -0.037, 0, -0.108, -0.944,
- 0.312, 0, 0.008, -0.031, 0.017, 1,
- ],
- },
- 'ring-finger-phalanx-distal': {
- radius: 0.007231088820844889,
- transform: [
- -0.001, -0.333, -0.943, 0, 0.583, 0.766, -0.271, 0, 0.812, -0.55, 0.193,
- 0, 0.011, -0.006, 0.009, 1,
- ],
- },
- 'ring-finger-tip': {
- radius: 0.0062310886569321156,
- transform: [
- -0.001, -0.333, -0.943, 0, 0.583, 0.766, -0.271, 0, 0.812, -0.55, 0.193,
- 0, -0.008, 0.009, 0.004, 1,
- ],
- },
- 'pinky-finger-metacarpal': {
- radius: 0.01808827556669712,
- transform: [
- -0.396, -0.279, -0.875, 0, -0.914, 0.023, 0.406, 0, -0.094, 0.96, -0.264,
- 0, -0.028, 0.032, 0.025, 1,
- ],
- },
- 'pinky-finger-phalanx-proximal': {
- radius: 0.008483353070914745,
- transform: [
- -0.266, -0.273, -0.925, 0, -0.203, -0.922, 0.33, 0, -0.942, 0.276, 0.19,
- 0, -0.023, -0.012, 0.037, 1,
- ],
- },
- 'pinky-finger-phalanx-intermediate': {
- radius: 0.0067641944624483585,
- transform: [
- -0.167, -0.416, -0.894, 0, 0.961, -0.272, -0.053, 0, -0.221, -0.868,
- 0.445, 0, 0.006, -0.021, 0.031, 1,
- ],
- },
- 'pinky-finger-phalanx-distal': {
- radius: 0.0064259846694767475,
- transform: [
- -0.147, -0.491, -0.859, 0, 0.681, 0.579, -0.448, 0, 0.717, -0.651, 0.249,
- 0, 0.01, -0.003, 0.022, 1,
- ],
- },
- 'pinky-finger-tip': {
- radius: 0.005425984505563974,
- transform: [
- -0.147, -0.491, -0.859, 0, 0.681, 0.579, -0.448, 0, 0.717, -0.651, 0.249,
- 0, -0.005, 0.012, 0.016, 1,
- ],
- },
-};
-
-export const relaxedHandPose = {
- wrist: {
- radius: 0.021460847929120064,
- transform: [0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -0.037, 0.066, 0.001, 1],
- },
- 'thumb-metacarpal': {
- radius: 0.019382517784833908,
- transform: [
- 0.067, -0.398, 0.915, 0, 0.805, 0.563, 0.186, 0, -0.589, 0.724, 0.358, 0,
- -0.015, 0.028, -0.024, 1,
- ],
- },
- 'thumb-phalanx-proximal': {
- radius: 0.01228295173496008,
- transform: [
- 0.087, -0.137, 0.987, 0, 0.86, 0.511, -0.005, 0, -0.504, 0.849, 0.162, 0,
- 0.004, 0.005, -0.035, 1,
- ],
- },
- 'thumb-phalanx-distal': {
- radius: 0.009768804535269737,
- transform: [
- -0.054, -0.22, 0.974, 0, 0.796, 0.58, 0.175, 0, -0.604, 0.784, 0.144, 0,
- 0.021, -0.024, -0.041, 1,
- ],
- },
- 'thumb-tip': {
- radius: 0.008768804371356964,
- transform: [
- -0.054, -0.22, 0.974, 0, 0.796, 0.58, 0.175, 0, -0.604, 0.784, 0.144, 0,
- 0.036, -0.043, -0.045, 1,
- ],
- },
- 'index-finger-metacarpal': {
- radius: 0.021228281781077385,
- transform: [0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -0.025, 0.028, -0.016, 1],
- },
- 'index-finger-phalanx-proximal': {
- radius: 0.010295259766280651,
- transform: [
- 0.064, 0.038, -0.997, 0, -0.965, -0.253, -0.072, 0, -0.255, 0.967, 0.02,
- 0, -0.03, -0.03, -0.022, 1,
- ],
- },
- 'index-finger-phalanx-intermediate': {
- radius: 0.00853810179978609,
- transform: [
- 0.019, 0.012, -1, 0, -0.679, -0.734, -0.021, 0, -0.734, 0.68, -0.006, 0,
- -0.02, -0.067, -0.023, 1,
- ],
- },
- 'index-finger-phalanx-distal': {
- radius: 0.007636196445673704,
- transform: [
- 0.037, -0.045, -0.998, 0, -0.546, -0.838, 0.018, 0, -0.837, 0.544, -0.055,
- 0, -0.002, -0.084, -0.023, 1,
- ],
- },
- 'index-finger-tip': {
- radius: 0.006636196281760931,
- transform: [
- 0.037, -0.045, -0.998, 0, -0.546, -0.838, 0.018, 0, -0.837, 0.544, -0.055,
- 0, 0.016, -0.097, -0.021, 1,
- ],
- },
- 'middle-finger-metacarpal': {
- radius: 0.021231964230537415,
- transform: [0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -0.028, 0.03, 0, 1],
- },
- 'middle-finger-phalanx-proximal': {
- radius: 0.01117393933236599,
- transform: [
- -0.012, -0.101, -0.995, 0, -0.982, -0.188, 0.031, 0, -0.19, 0.977, -0.097,
- 0, -0.035, -0.03, 0, 1,
- ],
- },
- 'middle-finger-phalanx-intermediate': {
- radius: 0.008030958473682404,
- transform: [
- -0.034, -0.114, -0.993, 0, -0.791, -0.604, 0.096, 0, -0.611, 0.788, -0.07,
- 0, -0.026, -0.072, 0.004, 1,
- ],
- },
- 'middle-finger-phalanx-distal': {
- radius: 0.007629410829395056,
- transform: [
- -0.106, -0.17, -0.98, 0, -0.753, -0.63, 0.191, 0, -0.65, 0.758, -0.062, 0,
- -0.01, -0.094, 0.006, 1,
- ],
- },
- 'middle-finger-tip': {
- radius: 0.006629410665482283,
- transform: [
- -0.106, -0.17, -0.98, 0, -0.753, -0.63, 0.191, 0, -0.65, 0.758, -0.062, 0,
- 0.006, -0.113, 0.008, 1,
- ],
- },
- 'ring-finger-metacarpal': {
- radius: 0.019088275730609894,
- transform: [0, 0, -1, 0, -1, 0, 0, 0, 0, 1, 0, 0, -0.031, 0.031, 0.016, 1],
- },
- 'ring-finger-phalanx-proximal': {
- radius: 0.00992213748395443,
- transform: [
- -0.093, -0.232, -0.968, 0, -0.978, -0.163, 0.133, 0, -0.189, 0.959,
- -0.211, 0, -0.031, -0.023, 0.019, 1,
- ],
- },
- 'ring-finger-phalanx-intermediate': {
- radius: 0.007611672393977642,
- transform: [
- -0.165, -0.251, -0.954, 0, -0.82, -0.502, 0.274, 0, -0.548, 0.828, -0.123,
- 0, -0.023, -0.06, 0.027, 1,
- ],
- },
- 'ring-finger-phalanx-distal': {
- radius: 0.007231088820844889,
- transform: [
- -0.215, -0.214, -0.953, 0, -0.708, -0.637, 0.303, 0, -0.672, 0.74, -0.015,
- 0, -0.009, -0.082, 0.03, 1,
- ],
- },
- 'ring-finger-tip': {
- radius: 0.0062310886569321156,
- transform: [
- -0.215, -0.214, -0.953, 0, -0.708, -0.637, 0.303, 0, -0.672, 0.74, -0.015,
- 0, 0.007, -0.101, 0.031, 1,
- ],
- },
- 'pinky-finger-metacarpal': {
- radius: 0.01808827556669712,
- transform: [
- -0.396, -0.279, -0.875, 0, -0.914, 0.023, 0.406, 0, -0.094, 0.96, -0.264,
- 0, -0.028, 0.032, 0.024, 1,
- ],
- },
- 'pinky-finger-phalanx-proximal': {
- radius: 0.008483353070914745,
- transform: [
- -0.205, -0.431, -0.879, 0, -0.949, -0.131, 0.286, 0, -0.238, 0.893,
- -0.383, 0, -0.023, -0.012, 0.036, 1,
- ],
- },
- 'pinky-finger-phalanx-intermediate': {
- radius: 0.0067641944624483585,
- transform: [
- -0.269, -0.517, -0.813, 0, -0.812, -0.332, 0.48, 0, -0.518, 0.789, -0.331,
- 0, -0.016, -0.04, 0.048, 1,
- ],
- },
- 'pinky-finger-phalanx-distal': {
- radius: 0.0064259846694767475,
- transform: [
- -0.321, -0.438, -0.84, 0, -0.759, -0.411, 0.505, 0, -0.566, 0.799, -0.201,
- 0, -0.006, -0.056, 0.055, 1,
- ],
- },
- 'pinky-finger-tip': {
- radius: 0.005425984505563974,
- transform: [
- -0.321, -0.438, -0.84, 0, -0.759, -0.411, 0.505, 0, -0.566, 0.799, -0.201,
- 0, 0.006, -0.074, 0.06, 1,
- ],
- },
-};
-
-export const HAND_POSES = {
- pinch: pinchHandPose,
- relaxed: relaxedHandPose,
- point: pointHandPose,
-};
diff --git a/webxr-emulator/api/index.js b/webxr-emulator/api/index.js
deleted file mode 100644
index a4981b8..0000000
--- a/webxr-emulator/api/index.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import { XRAnchor, XRAnchorSet } from './XRAnchor';
-import { XRMesh, XRMeshSet } from './XRMesh';
-import { XRPlane, XRPlaneOrientation, XRPlaneSet } from './XRPlane';
-
-import { XRHand } from './XRHand';
-import XRHitTestResult from './XRHitTestResult';
-import XRHitTestSource from './XRHitTestSource';
-import { XRJointPose } from './XRJointPose';
-import { XRJointSpace } from './XRJointSpace';
-import XRRay from './XRRay';
-import XRTransientInputHitTestResult from './XRTransientInputHitTestResult';
-import XRTransientInputHitTestSource from './XRTransientInputHitTestSource';
-
-export default {
- XRHitTestResult,
- XRHitTestSource,
- XRTransientInputHitTestResult,
- XRTransientInputHitTestSource,
- XRRay,
- XRPlane,
- XRPlaneSet,
- XRAnchor,
- XRAnchorSet,
- XRPlaneOrientation,
- XRHand,
- XRJointPose,
- XRJointSpace,
- XRMesh,
- XRMeshSet,
-};