Skip to content

Commit

Permalink
Merge pull request #6 from ir-engine/move-back-out-webxr-emulator
Browse files Browse the repository at this point in the history
move back out webxr emulator
  • Loading branch information
HexaField authored Nov 21, 2024
2 parents 694fc17 + 06cc8d0 commit 8d273b1
Show file tree
Hide file tree
Showing 64 changed files with 3,789 additions and 0 deletions.
154 changes: 154 additions & 0 deletions devtool/EmulatorDevtools.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*
CPAL-1.0 License
The contents of this file are subject to the Common Public Attribution License
Version 1.0. (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
https://github.com/ir-engine/ir-engine/blob/dev/LICENSE.
The License is based on the Mozilla Public License Version 1.1, but Sections 14
and 15 have been added to cover use of software over a computer network and
provide for limited attribution for the Original Developer. In addition,
Exhibit A has been modified to be consistent with Exhibit B.
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
specific language governing rights and limitations under the License.
The Original Code is Infinite Reality Engine.
The Original Developer is the Initial Developer. The Initial Developer of the
Original Code is the Infinite Reality Engine team.
All portions of the code written by the Infinite Reality Engine team are Copyright © 2021-2023
Infinite Reality Engine. All Rights Reserved.
*/

import { useHookstate, useImmediateEffect, useMutableState } from '@ir-engine/hyperflux'
import { endXRSession, requestXRSession } from '@ir-engine/spatial/src/xr/XRSessionFunctions'
import Button from '@ir-engine/ui/src/primitives/tailwind/Button'
import React from 'react'

import EmulatedDevice from './js/emulatedDevice'
import { EmulatorSettings, emulatorStates } from './js/emulatorStates'
import { syncDevicePose } from './js/messenger'
import Devtool from './jsx/app'
import devtoolCSS from './styles/index.css?inline'

import { XRState } from '@ir-engine/spatial/src/xr/XRState'
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'
import { WebXREventDispatcher } from '@ir-engine/spatial/tests/webxr/emulator/WebXREventDispatcher'
import { POLYFILL_ACTIONS } from '@ir-engine/spatial/tests/webxr/emulator/actions'

export async function overrideXR(args: { mode: 'immersive-vr' | 'immersive-ar' }) {
// inject the webxr polyfill from the webxr emulator source - this is a script added by the bot
// globalThis.WebXRPolyfillInjection()

const { CustomWebXRPolyfill } = await import('@ir-engine/spatial/tests/webxr/emulator/CustomWebXRPolyfill')
new CustomWebXRPolyfill()
// override session supported request, it hangs indefinitely for some reason
;(navigator as any).xr.isSessionSupported = () => {
return true
}

const deviceDefinition = {
id: 'Oculus Quest',
name: 'Oculus Quest',
modes: ['inline', 'immersive-vr', 'immersive-ar'],
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
}
],
environmentBlendMode: args.mode === 'immersive-vr' ? 'opaque' : 'additive'
}

// send our device info to the polyfill API so it knows our capabilities
WebXREventDispatcher.instance.dispatchEvent({
type: POLYFILL_ACTIONS.DEVICE_INIT,
detail: { stereoEffect: false, deviceDefinition }
})
}

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 (
<>
<style type="text/css">{devtoolCSS.toString()}</style>
<div
id="devtools"
className="flex-no-wrap m-0 flex h-full h-full select-none flex-col overflow-hidden overflow-hidden bg-gray-900 text-xs text-gray-900"
>
<div className="flex-no-wrap flex h-10 select-none flex-row bg-gray-800 text-xs text-gray-900">
<Button className="my-1 ml-auto mr-6 px-10" onClick={toggleXR} disabled={xrState.requestingSession.value}>
{(xrActive ? 'Exit ' : 'Enter ') + (props.mode === 'immersive-ar' ? 'AR' : 'VR')}
</Button>
{props.mode === 'immersive-ar' && (
<Button className="my-1 ml-auto mr-6 px-10" onClick={togglePlacement} disabled={!xrActive}>
Place Scene
</Button>
)}
</div>
{deviceState.value && <Devtool device={deviceState.value} />}
</div>
</>
)
}
Binary file added devtool/assets/headset.glb
Binary file not shown.
Binary file added devtool/assets/images/auto-return.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/button1-left.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/button1-right.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/button2-left.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/button2-right.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/delete.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/exit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/gamepad.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/grip-left.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/grip-right.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/hand-pose.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/hand-tracking.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/headset-type.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/headset.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/horizontal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/info.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/joystick.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/keyboard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/left-controller.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/left-hand.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/lock.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/move.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/play.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/polyfill-on.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/pose.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devtool/assets/images/press.png
Binary file added devtool/assets/images/reset.png
Binary file added devtool/assets/images/revert.png
Binary file added devtool/assets/images/right-controller.png
Binary file added devtool/assets/images/right-hand.png
Binary file added devtool/assets/images/roomscale.png
Binary file added devtool/assets/images/rotation.png
Binary file added devtool/assets/images/save-copy.png
Binary file added devtool/assets/images/save.png
Binary file added devtool/assets/images/send.png
Binary file added devtool/assets/images/settings.png
Binary file added devtool/assets/images/stereo.png
Binary file added devtool/assets/images/sticky.png
Binary file added devtool/assets/images/trash.png
Binary file added devtool/assets/images/trigger-left.png
Binary file added devtool/assets/images/trigger-right.png
Binary file added devtool/assets/images/undo.png
Binary file added devtool/assets/images/vertical.png
Binary file added devtool/assets/left-controller.glb
Binary file not shown.
Binary file added devtool/assets/left-hand.glb
Binary file not shown.
Binary file added devtool/assets/right-controller.glb
Binary file not shown.
Binary file added devtool/assets/right-hand.glb
Binary file not shown.
60 changes: 60 additions & 0 deletions devtool/js/actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* 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',
};
141 changes: 141 additions & 0 deletions devtool/js/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/**
* 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,
},
};
Loading

0 comments on commit 8d273b1

Please sign in to comment.