Skip to content

Commit 5a0c1bf

Browse files
author
Avaer Kazmer
authored
Merge pull request #104 from exokitxr/xr-engine
<xr-engine> tag
2 parents 21ebac7 + 6bdbf1d commit 5a0c1bf

File tree

10 files changed

+389
-297
lines changed

10 files changed

+389
-297
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
```js
2828
import 'https://web.exokit.org/ew.js';
2929

30-
xrScene = document.createElement('xr-scene');
31-
xrScene.src = 'app.html';
30+
xrEngine = document.createElement('xr-engine');
31+
xrEngine.src = 'app.html';
3232
```
3333

3434
### app.html

boilerplate/index.html

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,21 @@
44
<body>
55
<a class=button id="enter-xr-button">Enter XR</a>
66
<script>
7+
let xrEngine;
78
const enterXrButton = document.getElementById('enter-xr-button');
89
enterXrButton.addEventListener('click', () => {
910
// Enter XR mode when button is clicked
10-
xrScene.enterXr();
11+
xrEngine.enterXr();
1112
});
1213

1314
// Import exokit-web
1415
// replace API_KEY if accessing web origins, otherwise remove
1516
import('https://web.exokit.org/ew.js?key=API_KEY')
1617
.then(async () => {
17-
// Create top-level xr-scene, define src attribute, and append/place it wherever you want as if it were a normal canvas
18-
xrScene = document.createElement('xr-scene');
19-
xrScene.src = 'app.html';
20-
document.body.appendChild(xrScene);
18+
// Create top-level xr-engine, define src attribute, and append/place it wherever you want as if it were a normal canvas
19+
xrEngine = document.createElement('xr-engine');
20+
xrEngine.src = 'app.html';
21+
document.body.appendChild(xrEngine);
2122
});
2223
</script>
2324
</body>

ew.js

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,15 @@ import './src/HelioWebXRPolyfill.js';
55
import './src/event-target-shim.mjs';
66

77
import core from './src/core.js';
8-
// import minimist from '../modules/minimist.js';
98

109
import symbols from './src/symbols.js';
1110
import THREE from './lib/three-min.js';
1211

13-
// import {lookupHMDTypeIndex, FakeMesher, FakePlaneTracker} from './VR.js';
14-
1512
import GlobalContext from './src/GlobalContext.js';
1613

17-
import XRScene from './src/xr-scene.js';
18-
window.XRScene = XRScene;
14+
import {XREngine, XREngineTemplate} from './src/xr-engine.js';
15+
window.XREngine = XREngine;
16+
window.XREngineTemplate = XREngineTemplate;
1917

2018
import utils from './src/utils.js';
2119
const {_makeNullPromise} = utils;
@@ -31,34 +29,6 @@ const windows = [];
3129
GlobalContext.windows = windows;
3230
GlobalContext.loadPromise = _makeNullPromise();
3331

34-
const localVector = new THREE.Vector3();
35-
const localVector2 = new THREE.Vector3();
36-
const localQuaternion = new THREE.Quaternion();
37-
const localMatrix = new THREE.Matrix4();
38-
39-
(async () => {
40-
41-
function parseQuery(queryString) {
42-
var query = {};
43-
var pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
44-
for (var i = 0; i < pairs.length; i++) {
45-
var pair = pairs[i].split('=');
46-
query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '');
47-
}
48-
return query;
49-
}
50-
51-
const {key} = parseQuery(new URL(import.meta.url).search);
52-
if (!key) {
53-
console.warn('exokit-web API key not set! Web origins will not work. See https://github.com/exokitxr/exokit-web/');
54-
}
55-
await navigator.serviceWorker.register('/sw.js' + (key ? `?key=${encodeURIComponent(key)}` : ''));
56-
if (navigator.serviceWorker.controller) {
57-
GlobalContext.loadPromise.resolve();
58-
} else {
59-
window.location.reload();
60-
}
61-
6232
const xrState = (() => {
6333
const _makeSab = size => {
6434
const sab = new ArrayBuffer(size);
@@ -164,6 +134,39 @@ const xrState = (() => {
164134
})();
165135
GlobalContext.xrState = xrState;
166136

137+
const localVector = new THREE.Vector3();
138+
const localVector2 = new THREE.Vector3();
139+
const localQuaternion = new THREE.Quaternion();
140+
const localMatrix = new THREE.Matrix4();
141+
142+
customElements.define('xr-engine', XREngine);
143+
customElements.define('xr-engine-template', XREngineTemplate, {
144+
extends: 'template',
145+
});
146+
147+
(async () => {
148+
149+
function parseQuery(queryString) {
150+
var query = {};
151+
var pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
152+
for (var i = 0; i < pairs.length; i++) {
153+
var pair = pairs[i].split('=');
154+
query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '');
155+
}
156+
return query;
157+
}
158+
159+
const {key} = parseQuery(new URL(import.meta.url).search);
160+
if (!key) {
161+
console.warn('exokit-web API key not set! Web origins will not work. See https://github.com/exokitxr/exokit-web/');
162+
}
163+
await navigator.serviceWorker.register('/sw.js' + (key ? `?key=${encodeURIComponent(key)}` : ''));
164+
if (navigator.serviceWorker.controller) {
165+
GlobalContext.loadPromise.resolve();
166+
} else {
167+
window.location.reload();
168+
}
169+
167170
['keydown', 'keyup', 'keypress', 'paste'].forEach(type => {
168171
window.addEventListener(type, e => {
169172
const event = {

examples/subscene.html

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
<!doctype html>
22
<html>
33
<body>
4-
<xr-site camera-position="0 2 3" camera-orientation="-0.2297529205473612 0 0 0.9732489894677301">
5-
<xr-iframe src="example1xr.html" position="0 0 -1" name="Red Cube"></xr-iframe>
6-
<xr-iframe src="example2xr.html" position="0 0 1" name="Green Cube"></xr-iframe>
7-
</xr-site>
4+
<script type=module>import(`../ew.js${window.location.search}`);</script>
5+
<xr-engine>
6+
<xr-site camera-position="0 2 3" camera-orientation="-0.2297529205473612 0 0 0.9732489894677301">
7+
<xr-iframe src="/examples/example1xr.html" position="0 0 -1" name="Red Cube"></xr-iframe>
8+
<xr-iframe src="/examples/example2xr.html" position="0 0 0" name="Green Cube"></xr-iframe>
9+
</xr-site>
10+
</xr-engine>
811
</body>
912
</html>

index.html

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -264,27 +264,17 @@ <h3>Examples</h3>
264264
return query;
265265
}
266266

267-
let xrScene = null;
268-
267+
let xrEngine;
269268
import(`./ew.js${window.location.search}`)
270269
.then(async () => {
271-
xrScene = document.createElement('xr-scene');
272-
xrScene.src = 'app.html';
273-
// document.getElementById('iframe-wrapper').appendChild(xrScene);
274-
xrScene.addEventListener('canvas', e => {
270+
xrEngine = new XREngine();
271+
// xrEngine = document.createElement('template', {is: 'xr-engine'});
272+
xrEngine.src = 'app.html';
273+
xrEngine.addEventListener('canvas', e => {
275274
const canvas = e.data;
276275
document.getElementById('iframe-wrapper').appendChild(canvas);
277-
278-
const {u} = parseQuery(window.location.search);
279-
if (u) {
280-
setTimeout(() => {
281-
_unloadLink(0);
282-
_unloadLink(0);
283-
_loadLink({href: u, innerText: 'URL'});
284-
});
285-
}
286276
});
287-
xrScene.addEventListener('message', e => {
277+
xrEngine.addEventListener('message', e => {
288278
const {data} = e;
289279
const {method} = data;
290280
switch (method) {
@@ -303,6 +293,14 @@ <h3>Examples</h3>
303293
}
304294
});
305295

296+
const {u} = parseQuery(window.location.search);
297+
if (u) {
298+
while (tabs.childNodes.length > 0) {
299+
_unloadLink(0);
300+
}
301+
_loadLink({href: u, innerText: 'URL'});
302+
}
303+
306304
let result;
307305
if (navigator.xr) {
308306
try {
@@ -340,15 +338,15 @@ <h3>Examples</h3>
340338
const _loadLink = (aCube, origin = false) => {
341339
const name = aCube.innerText;
342340
const url = aCube.href;
343-
xrScene.postMessage({
341+
xrEngine.postMessage({
344342
method: 'load',
345343
name,
346344
url,
347345
origin,
348346
});
349347
};
350348
const _unloadLink = index => {
351-
xrScene.postMessage({
349+
xrEngine.postMessage({
352350
method: 'unload',
353351
index,
354352
});
@@ -376,13 +374,13 @@ <h3>Examples</h3>
376374
if (codeButton.classList.contains('open')) {
377375
code.value = '';
378376

379-
xrScene.postMessage({
377+
xrEngine.postMessage({
380378
method: 'getCode',
381379
});
382380
} else {
383381
const currentCode = code.value;
384382
if (currentCode !== lastCode) {
385-
xrScene.postMessage({
383+
xrEngine.postMessage({
386384
method: 'setCode',
387385
code: currentCode,
388386
});
@@ -395,7 +393,7 @@ <h3>Examples</h3>
395393
const enterXrButton = document.getElementById('enter-xr-button');
396394
const noXrButton = document.getElementById('no-xr-button');
397395
enterXrButton.addEventListener('click', () => {
398-
xrScene.enterXr();
396+
xrEngine.enterXr();
399397
});
400398
</script>
401399
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-147624282-1"></script>

src/Window.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,36 @@ const vrPresentState = {
6767
};
6868
GlobalContext.vrPresentState = vrPresentState;
6969

70+
// unpack xr-engine-template in recursive load scenario
71+
class XREngineTemplate extends HTMLTemplateElement {
72+
constructor() {
73+
super();
74+
75+
(async () => {
76+
if (document.readyState !== 'complete') {
77+
await new Promise((accept, reject) => {
78+
document.addEventListener('readystatechange', () => {
79+
if (document.readyState === 'complete') {
80+
accept();
81+
}
82+
});
83+
});
84+
}
85+
const childNodes = Array.from(this.content.childNodes);
86+
for (let i = 0; i < childNodes.length; i++) {
87+
const childNode = childNodes[i];
88+
if (childNode.nodeType === Node.ELEMENT_NODE) {
89+
const xrIframe = document.importNode(childNode, true);
90+
this.insertAdjacentElement('afterend', xrIframe);
91+
}
92+
}
93+
})();
94+
}
95+
}
96+
customElements.define('xr-engine-template', XREngineTemplate, {
97+
extends: 'template',
98+
});
99+
70100
class PaymentRequest {
71101
constructor(methodData, details, options) {
72102
this.methodData = methodData;

src/WindowVm.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,11 @@ class WorkerVm extends EventTarget {
3939
};
4040
_getFollowUrl(options.args.options.url)
4141
.then(followUrl => new Promise((accept, reject) => {
42-
const src = window.location.origin + options.args.options.url.replace(/^[a-z]+:\/\/[a-zA-Z0-9\-\.]+(?::[0-9]+)?/, '');
42+
const src = window.location.origin +
43+
(options.args.options.url.startsWith('data:') ?
44+
`${window.location.origin}/xr-engine-${Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5)}.html`
45+
:
46+
options.args.options.url.replace(/^[a-z]+:\/\/[a-zA-Z0-9\-\.]+(?::[0-9]+)?/, ''));
4347
const dst = `\
4448
<!doctype html>
4549
<html>

0 commit comments

Comments
 (0)