From ef5368a5a87f55b503b2655bb5d3034cc9f55bcc Mon Sep 17 00:00:00 2001 From: Leon van Kammen Date: Fri, 3 Oct 2025 13:41:51 +0200 Subject: [PATCH] wip: webxr client --- clients/webxr/{viewer => aframe}/index.html | 0 clients/webxr/aframe/index.js | 49 +++++++++++++++ clients/webxr/{viewer => aframe}/play.svg | 0 .../{viewer => aframe}/plugin.xrforge.js | 0 clients/webxr/dist/xrforge.html | 44 ++++++++++++++ clients/webxr/dist/xrforge/play-c89r1cs1.svg | 43 ++++++++++++++ .../webxr/dist/xrforge/xrforge-gent5bnt.js | 59 +++++++++++++++++++ clients/webxr/dist/xrforge/xrforge.html | 44 ++++++++++++++ clients/webxr/package-lock.json | 28 +++++++++ clients/webxr/package.json | 5 +- clients/webxr/{viewer => }/shell.nix | 8 +-- clients/webxr/xrforge.html | 44 ++++++++++++++ 12 files changed, 317 insertions(+), 7 deletions(-) rename clients/webxr/{viewer => aframe}/index.html (100%) create mode 100644 clients/webxr/aframe/index.js rename clients/webxr/{viewer => aframe}/play.svg (100%) rename clients/webxr/{viewer => aframe}/plugin.xrforge.js (100%) create mode 100644 clients/webxr/dist/xrforge.html create mode 100644 clients/webxr/dist/xrforge/play-c89r1cs1.svg create mode 100644 clients/webxr/dist/xrforge/xrforge-gent5bnt.js create mode 100644 clients/webxr/dist/xrforge/xrforge.html create mode 100644 clients/webxr/package-lock.json rename clients/webxr/{viewer => }/shell.nix (71%) create mode 100644 clients/webxr/xrforge.html diff --git a/clients/webxr/viewer/index.html b/clients/webxr/aframe/index.html similarity index 100% rename from clients/webxr/viewer/index.html rename to clients/webxr/aframe/index.html diff --git a/clients/webxr/aframe/index.js b/clients/webxr/aframe/index.js new file mode 100644 index 0000000..0d7c136 --- /dev/null +++ b/clients/webxr/aframe/index.js @@ -0,0 +1,49 @@ + +import * as xrforge from './plugin.xrforge.js'; +import * as level0 from 'xrf/level0'; + +const widget = new Proxy({ + + backend: null, + player: document.querySelector("#player"), + src: document.location.search.substr(1), + ext: {}, + + init(opts){ + for( var i in opts) this[i] = opts[i] + }, + + play(){ + // set URL + player.setAttribute("gltf-model", `url(${widget.src})` ) + + document.querySelector("#btn_play").style.display = 'none' + + let script = document.createElement("script") + script.src = "https://aframe.io/releases/1.7.0/aframe.min.js" + document.head.appendChild(script) + + script = document.createElement("script") + script.src = "backend.xrforge.js" + document.head.appendChild(script) + } + +}, + { + get(me,k){ return me[k] }, + + set(me,k,v){ + me[k] = v + return true + } + + }) + +xrforge.init(widget) +//level0.init(widget) + +document.querySelector("#btn_play").addEventListener("click", () => widget.play() ) + +//document.body.style.background = `url(${src.replace( /\.(glb|usdz|gltf|obj|col)$/ , ".png")})` + + diff --git a/clients/webxr/viewer/play.svg b/clients/webxr/aframe/play.svg similarity index 100% rename from clients/webxr/viewer/play.svg rename to clients/webxr/aframe/play.svg diff --git a/clients/webxr/viewer/plugin.xrforge.js b/clients/webxr/aframe/plugin.xrforge.js similarity index 100% rename from clients/webxr/viewer/plugin.xrforge.js rename to clients/webxr/aframe/plugin.xrforge.js diff --git a/clients/webxr/dist/xrforge.html b/clients/webxr/dist/xrforge.html new file mode 100644 index 0000000..8671a56 --- /dev/null +++ b/clients/webxr/dist/xrforge.html @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + diff --git a/clients/webxr/dist/xrforge/play-c89r1cs1.svg b/clients/webxr/dist/xrforge/play-c89r1cs1.svg new file mode 100644 index 0000000..72c813a --- /dev/null +++ b/clients/webxr/dist/xrforge/play-c89r1cs1.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/clients/webxr/dist/xrforge/xrforge-gent5bnt.js b/clients/webxr/dist/xrforge/xrforge-gent5bnt.js new file mode 100644 index 0000000..a97a336 --- /dev/null +++ b/clients/webxr/dist/xrforge/xrforge-gent5bnt.js @@ -0,0 +1,59 @@ +// viewer/plugin.xrforge.js +function init(widget2) { + inferSource(widget2.src); +} +async function inferSource(src) { + response = await fetch(src, { + method: "HEAD" + }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + contentDisposition = response.headers.get("Content-Disposition"); + console.log(widget.src); + widget.src = extractFilename(contentDisposition); + console.log("detected: " + widget.src); +} +function extractFilename(contentDispositionHeader) { + const utf8Match = contentDispositionHeader.match(/filename\*=(?:utf-8|UTF-8)''(.+?)(?:;|$)/i); + if (utf8Match && utf8Match[1]) { + return decodeURIComponent(utf8Match[1].trim()); + } + const basicMatch = contentDispositionHeader.match(/filename="(.+?)"/i); + if (basicMatch && basicMatch[1]) { + return basicMatch[1].trim(); + } + return null; +} + +// viewer/index.js +var widget2 = new Proxy({ + backend: null, + player: document.querySelector("#player"), + src: document.location.search.substr(1), + ext: {}, + init(opts) { + for (var i in opts) + this[i] = opts[i]; + }, + play() { + player.setAttribute("gltf-model", `url(${widget2.src})`); + document.querySelector("#btn_play").style.display = "none"; + let script = document.createElement("script"); + script.src = "https://aframe.io/releases/1.7.0/aframe.min.js"; + document.head.appendChild(script); + script = document.createElement("script"); + script.src = "backend.xrforge.js"; + document.head.appendChild(script); + } +}, { + get(me, k) { + return me[k]; + }, + set(me, k, v) { + me[k] = v; + return true; + } +}); +init(widget2); +document.querySelector("#btn_play").addEventListener("click", () => widget2.play()); diff --git a/clients/webxr/dist/xrforge/xrforge.html b/clients/webxr/dist/xrforge/xrforge.html new file mode 100644 index 0000000..e0da36e --- /dev/null +++ b/clients/webxr/dist/xrforge/xrforge.html @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + diff --git a/clients/webxr/package-lock.json b/clients/webxr/package-lock.json new file mode 100644 index 0000000..ce72d98 --- /dev/null +++ b/clients/webxr/package-lock.json @@ -0,0 +1,28 @@ +{ + "name": "webxr", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "webxr", + "version": "1.0.0", + "license": "AGPL3", + "dependencies": { + "xrf": "^0.0.1" + } + }, + "../../../xrfragment/xrf.js": { + "name": "xrf", + "version": "0.0.1", + "extraneous": true, + "license": "MIT" + }, + "node_modules/xrf": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/xrf/-/xrf-0.0.1.tgz", + "integrity": "sha512-uYa8M73z45DRTymga+48gTDEeur+iM3jPktVBnaOHopb17VvZxJ6yZy6TAhMURMrliHB48mYUUSC5J5NRF8wZA==", + "license": "MIT" + } + } +} diff --git a/clients/webxr/package.json b/clients/webxr/package.json index fe3dbcb..6295598 100644 --- a/clients/webxr/package.json +++ b/clients/webxr/package.json @@ -3,10 +3,11 @@ "version": "1.0.0", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "build": "npm run build-xrforge", + "build-xrforge": "mkdir -p dist/xrforge && bun build --outdir=dist/xrforge xrforge.html && monolith dist/xrforge/xrforge.html --output dist/xrforge.html" }, "author": "Leon van Kammen", - "license": "AGPL3", + "license": "", "description": "", "dependencies": { "xrf": "^0.0.1" diff --git a/clients/webxr/viewer/shell.nix b/clients/webxr/shell.nix similarity index 71% rename from clients/webxr/viewer/shell.nix rename to clients/webxr/shell.nix index bdb1a75..94a7d7a 100644 --- a/clients/webxr/viewer/shell.nix +++ b/clients/webxr/shell.nix @@ -12,15 +12,13 @@ nativeBuildInputs = with pkgs.buildPackages; [ nodejs_20 + monolith + bun ]; shellHook = '' - # install bun - alias bun="steam-run ~/.bun/bin/bun" - test -f ~/.bun/bin/bun || curl -fsSL https://bun.com/install | bash -s "bun-v1.2.22" - - export NIX_SHELL_DEV=1 + export NIX_XRFORGE_WEBXR=1 ''; } diff --git a/clients/webxr/xrforge.html b/clients/webxr/xrforge.html new file mode 100644 index 0000000..aa195ec --- /dev/null +++ b/clients/webxr/xrforge.html @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + +