Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync XRExtras code with R17.1 release #184

Merged
merged 1 commit into from
Sep 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 78 additions & 71 deletions xrextras/src/aframe/aframe.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,83 @@
/* globals AFRAME, XRExtras, XR8 */

const {xrComponents} = require('./xr-components.js')
const {xrPrimitives} = require('./xr-primitives.js')
const {ensureXrAndExtras} = require('./ensure')

let xrextrasAframe = null

const AFrameFactory = () => {
if (!xrextrasAframe) {
xrextrasAframe = create()
const onxrloaded = () => { XR8.addCameraPipelineModule(XRExtras.Loading.pipelineModule()) }

// We want to start showing the loading screen eagerly (before AFRAME has loaded and parsed the
// scene and set up everything). We also need to work around a bug in the AFRAME loading in iOS
// Webviews for almost there.
const eagerload = () => {
// Manually traverse the dom for an aframe scene and check its attributes.
const scene = document.getElementsByTagName('a-scene')[0]
if (!scene) {
return
}
const attrs = scene.attributes

return xrextrasAframe
}
let foundAlmostThere = false
let foundLoading = false
let redirectUrl = null
let runConfig = null

const onxrloaded = () => { XR8.addCameraPipelineModule(XRExtras.Loading.pipelineModule()) }
// Eagerly inspect the dom, and trigger loading or almost there modules early if appropriate.
Object.keys(attrs).forEach((a) => {
const attr = attrs.item(a).name
if (attr === 'xrextras-almost-there') {
foundAlmostThere = true
const redirectMatch = new RegExp('url:([^;]*)').exec(attrs.item(a).value)
if (redirectMatch) {
redirectUrl = redirectMatch[1]
}
}

if (attr === 'xrextras-loading') {
foundLoading = true
}

if (attr === 'xrweb' || attr === 'xrface') {
const allowedDevicesMatch = new RegExp('allowedDevices:([^;]*)').exec(attrs.item(a).value)
if (allowedDevicesMatch) {
runConfig = {allowedDevices: allowedDevicesMatch[1].trim()}
}
}
})

if (foundAlmostThere) {
if (redirectUrl) {
window.XRExtras.AlmostThere.configure({url: redirectUrl})
}

// eslint-disable-next-line no-unused-expressions
window.XR8
? window.XRExtras.AlmostThere.checkCompatibility(runConfig)
: window.addEventListener(
'xrloaded', () => window.XRExtras.AlmostThere.checkCompatibility(runConfig)
)
}

if (foundLoading) {
const waitForRealityTexture = !!(scene.attributes.xrweb || scene.attributes.xrface)
window.XRExtras.Loading.showLoading({onxrloaded, waitForRealityTexture})
}
}

function create() {
let registered = false

// NOTE: new versions of 8frame should be added in descending order, so that the latest version
// is always in position 1.
const allowed8FrameVersions = ['latest', '0.9.0', '0.8.2']
const LATEST_8FRAME = allowed8FrameVersions[1] // The 'latest' version of 8frame.
const LATEST_8FRAME = allowed8FrameVersions[1] // The 'latest' version of 8frame.

// Check that the requested version of AFrame has a corresponding 8Frame implementation.
const checkAllowed8FrameVersions = version => new Promise((resolve, reject) => (allowed8FrameVersions.includes(version)
? resolve(version === 'latest' ? LATEST_8FRAME : version)
: reject(`${version} is an unsupported AFrame version: (${JSON.stringify(allowedVersions)})`)))
: reject(`'${version}' is an unsupported AFrame version. Alowed versions: (${allowed8FrameVersions})`)))

// Load an external javascript resource in a promise that resolves when the javascript has loaded.
const loadJsPromise = url => new Promise((resolve, reject) => document.head.appendChild(Object.assign(
Expand All @@ -43,9 +95,11 @@ function create() {
// 'component-1': component1,
// 'component-2': component2,
// }
const registerComponents = components => Object.keys(components).map(k => AFRAME.registerComponent(k, components[k]))
const registerComponents =
components => Object.keys(components).map(k => AFRAME.registerComponent(k, components[k]))

const registerPrimitives = primitives => Object.keys(primitives).map(k => AFRAME.registerPrimitive(k, primitives[k]))
const registerPrimitives =
primitives => Object.keys(primitives).map(k => AFRAME.registerPrimitive(k, primitives[k]))

// Load the 8th Wall preferred version of AFrame at runtime ensuring that xr components are added.
const loadAFrameForXr = (args) => {
Expand All @@ -67,6 +121,16 @@ function create() {
// Only register the components once.
registered = true

// Show the loading screen as early as we can - add a System because it will get `init` called
// before assets finish loading, versus a Component which gets `init` after load.
AFRAME.registerSystem('eager-load-system', {
init() {
/* eslint-disable-next-line no-unused-expressions */
window.XRExtras
? eagerload()
: window.addEventListener('xrextrasloaded', eagerload, {once: true})
},
})
registerComponents(xrComponents())
registerPrimitives(xrPrimitives())
}
Expand All @@ -82,70 +146,13 @@ function create() {
}
}

// We want to start showing the loading screen eagerly (before AFRAME has loaded and parsed the
// scene and set up everything). We also need to work around a bug in the AFRAME loading in iOS
// Webviews for almost there.
const eagerload = () => {
// Manually traverse the dom for an aframe scene and check its attributes.
const scene = document.getElementsByTagName('a-scene')[0]
if (!scene) {
return
}
const attrs = scene.attributes

let foundAlmostThere = false
let foundLoading = false
let redirectUrl = null
let runConfig = null

// Eagerly inspect the dom, and trigger loading or almost there modules early if appropriate.
Object.keys(attrs).forEach((a) => {
const attr = attrs.item(a).name
if (attr == 'xrextras-almost-there') {
foundAlmostThere = true
const redirectMatch = new RegExp('url:([^;]*)').exec(attrs.item(a).value)
if (redirectMatch) {
redirectUrl = redirectMatch[1]
}
}

if (attr == 'xrextras-loading') {
foundLoading = true
}

if (attr === 'xrweb' || attr === 'xrface') {
const allowedDevicesMatch = new RegExp('allowedDevices:([^;]*)').exec(attrs.item(a).value)
if (allowedDevicesMatch) {
runConfig = {allowedDevices: allowedDevicesMatch[1].trim()}
}
}
})

if (foundAlmostThere) {
if (redirectUrl) {
window.XRExtras.AlmostThere.configure({url: redirectUrl})
}

window.XR8
? window.XRExtras.AlmostThere.checkCompatibility(runConfig)
: window.addEventListener(
'xrloaded', () => window.XRExtras.AlmostThere.checkCompatibility(runConfig)
)
}

if (foundLoading) {
window.XRExtras.Loading.showLoading({onxrloaded})
const AFrameFactory = () => {
if (!xrextrasAframe) {
xrextrasAframe = create()
}
}

const oldonload = window.onload
const aframeonload = () => {
if (oldonload) {
oldonload()
}
window.XRExtras ? eagerload() : window.addEventListener('xrextrasloaded', eagerload, {once: true})
return xrextrasAframe
}
window.onload = aframeonload

module.exports = {
AFrameFactory,
Expand Down
12 changes: 10 additions & 2 deletions xrextras/src/aframe/xr-components.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* globals XRExtras, XR8 */
/* globals XRExtras, XR8, THREE */

const {ensureXrAndExtras} = require('./ensure')

Expand Down Expand Up @@ -38,7 +38,9 @@ const xrComponents = () => {
const aframeDidLoad = () => aframeLoaded
const load = () => {
XRExtras.Loading.setAppLoadedProvider(aframeDidLoad)
XRExtras.Loading.showLoading({onxrloaded})
const waitForRealityTexture =
!!(this.el.sceneEl.attributes.xrweb || this.el.sceneEl.attributes.xrface)
XRExtras.Loading.showLoading({onxrloaded, waitForRealityTexture})
}
window.XRExtras ? load() : window.addEventListener('xrextrasloaded', load, {once: true})

Expand Down Expand Up @@ -451,8 +453,14 @@ const xrComponents = () => {
},
init() {
this.camera = document.getElementById(this.data.cameraId)
if (!this.camera) {
throw new Error(`[xrextras-hold-drag] Couldn't find camera with id '${this.data.cameraId}'`)
}
this.threeCamera = this.camera.getObject3D('camera')
this.ground = document.getElementById(this.data.groundId)
if (!this.ground) {
throw new Error(`[xrextras-hold-drag] Couldn't find ground with id '${this.data.groundId}'`)
}

this.internalState = {
fingerDown: false,
Expand Down
27 changes: 19 additions & 8 deletions xrextras/src/almosttheremodule/almost-there-module.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ function create() {
if (device.os === 'iOS') {
if (details.inAppBrowserType == 'Safari') {
showId('error_msg_open_in_safari')
showId('apple_open_safari_hint')
} else {
switch (details.inAppBrowser) {
case 'Instagram':
Expand Down Expand Up @@ -136,13 +135,22 @@ function create() {

// Desktop: help our user with a qr code
showId('error_msg_device')
const scriptElem = document.createElement('script')
scriptElem.type = 'text/javascript'
scriptElem.src = 'https://cdn.8thwall.com/web/share/qrcode8-1.1.0.js'
scriptElem.onload = () => {
document.getElementById('qrcode').innerHTML = qrcode8.generateQR8Svg(redirectUrl, 250, 80)
}
document.getElementById('almostthereContainer').appendChild(scriptElem)

// NOTE(christoph): Using an SVG here to preserve backwards compatibility with
// CSS rules for ".qrcode svg"
document.getElementById('qrcode').innerHTML = `\
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 250 250"
width="250" height="250"
>
<image
width="250"
height="250"
xlink:href="https://8th.io/qr?v=2&margin=2&url=${encodeURIComponent(redirectUrl)}"
/>
</svg>`
}

const checkCompatibility = (runConfig) => {
Expand Down Expand Up @@ -174,6 +182,9 @@ function create() {
throw Error('Device or browser incompatible with XR.')
}
},
onRemove: () => {
hideAlmostThere()
},
onException: () => {
checkCompatibility(runConfig_)
},
Expand Down
Loading