separated code into extensions
This commit is contained in:
parent
33e2b4c335
commit
520b8cd2c5
7 changed files with 177 additions and 50 deletions
46
lib/AsyncEmitter.js
Normal file
46
lib/AsyncEmitter.js
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* async Event Emitter
|
||||
*
|
||||
* // Example usage
|
||||
* const emitter = new AsyncEmitter();
|
||||
*
|
||||
* // Register some async listeners
|
||||
* emitter.on("data", async (msg) => {
|
||||
* console.log("Listener 1 starting...");
|
||||
* await new Promise((r) => setTimeout(r, 1000));
|
||||
* console.log("Listener 1 done:", msg);
|
||||
* });
|
||||
*
|
||||
* emitter.on("data", async (msg) => {
|
||||
* console.log("Listener 2 starting...");
|
||||
* await new Promise((r) => setTimeout(r, 500));
|
||||
* console.log("Listener 2 done:", msg);
|
||||
* });
|
||||
*
|
||||
* (async () => {
|
||||
* console.log("Emitting...");
|
||||
* await emitter.emit("data", "Hello async world!");
|
||||
* console.log("All listeners finished.");
|
||||
* })();
|
||||
*/
|
||||
|
||||
class AsyncEmitter {
|
||||
constructor() {
|
||||
this.listeners = new Map();
|
||||
}
|
||||
|
||||
on(event, listener) {
|
||||
if (!this.listeners.has(event)) this.listeners.set(event, []);
|
||||
this.listeners.get(event).push( listener );
|
||||
}
|
||||
|
||||
async emit(event, ...args) {
|
||||
const listeners = this.listeners.get(event) || [];
|
||||
if( document.location.hostname == 'localhost' ) console.info(`emit(${event})`)
|
||||
for (const fn of listeners) {
|
||||
await fn(...args); // <-- Waits for each listener to finish
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export {AsyncEmitter}
|
||||
|
|
@ -1,42 +1,21 @@
|
|||
import {AsyncEmitter} from "./AsyncEmitter.js"
|
||||
|
||||
function widget(){
|
||||
|
||||
return new Proxy({
|
||||
const me = new AsyncEmitter()
|
||||
me.player = document.querySelector("#player"),
|
||||
me.src = document.location.search.substr(1),
|
||||
me.ext = {}
|
||||
|
||||
backend: null,
|
||||
player: document.querySelector("#player"),
|
||||
src: document.location.search.substr(1),
|
||||
ext: {},
|
||||
return new Proxy( me, {
|
||||
get(me,k){ return me[k] },
|
||||
|
||||
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)
|
||||
set(me,k,v){
|
||||
me[k] = v
|
||||
return true
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
get(me,k){ return me[k] },
|
||||
|
||||
set(me,k,v){
|
||||
me[k] = v
|
||||
return true
|
||||
}
|
||||
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export {widget}
|
||||
|
|
|
|||
34
lib/widget/play.js
Normal file
34
lib/widget/play.js
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
export default function extension(widget){
|
||||
|
||||
const ext = {
|
||||
|
||||
async init(){
|
||||
|
||||
// let other extensions set this.src if needed
|
||||
await widget.emit("init.play", this)
|
||||
|
||||
if( widget.src ){
|
||||
document.querySelector('#scene').setAttribute("gltf-model",`url(${widget.src})`)
|
||||
}
|
||||
|
||||
this.initButton()
|
||||
},
|
||||
|
||||
initButton(){
|
||||
const btn_play = document.querySelector("#btn_play")
|
||||
btn_play.addEventListener("click", async () => {
|
||||
btn_play.style.display = 'none' // hide button
|
||||
widget.emit("play")
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
widget.ext.play = ext
|
||||
|
||||
// register async listeners
|
||||
widget.on("init", ext.init.bind(ext) )
|
||||
|
||||
}
|
||||
|
||||
26
lib/widget/thumb.js
Normal file
26
lib/widget/thumb.js
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
export default function extension(widget){
|
||||
|
||||
const ext = {
|
||||
|
||||
src: "",
|
||||
|
||||
init: async () => {
|
||||
|
||||
// let other extensions set this.src if needed
|
||||
await widget.emit("init.thumb", widget.ext.thumb )
|
||||
|
||||
if( widget.ext.thumb.src ){
|
||||
document.body.style.background = `url(${widget.ext.thumb.src}) no-repeat center / cover`
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
widget.ext.thumb = ext
|
||||
|
||||
// register async listeners
|
||||
widget.on("init", ext.init.bind(ext) )
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,24 +1,61 @@
|
|||
import {widget} from './../widget.js'
|
||||
import {widget as Widget} from './../widget.js'
|
||||
import {inferSource} from './util.js'
|
||||
|
||||
const btn_play = document.querySelector("#btn_play")
|
||||
btn_play.addEventListener("click", () => {
|
||||
btn_play.style.display = 'none' // hide button
|
||||
import('aframe')
|
||||
})
|
||||
// extensions
|
||||
import {default as thumb} from './../widget/thumb.js'
|
||||
import {default as play} from './../widget/play.js'
|
||||
|
||||
let src = document.location.search.substr(1)
|
||||
let cover = src
|
||||
const img = /\.(png|jpg|webp)/
|
||||
const widget = Widget()
|
||||
|
||||
// init extensions
|
||||
thumb(widget)
|
||||
play(widget)
|
||||
|
||||
// init xrforge extension
|
||||
widget.ext.xrforge = {
|
||||
|
||||
// manyfold URLs need to be de-obfuscated
|
||||
if( src.match(img) ){
|
||||
cover = await inferSource(src)
|
||||
src = cover.replace(img,".glb")
|
||||
}
|
||||
|
||||
console.dir({cover,src})
|
||||
// in case of Manyfold backend, a thumbnail is passed (not gltf src e.g.)
|
||||
// so we will infer the source-url based on the thumbnail
|
||||
widget.on('init.thumb', async (thumb) => {
|
||||
let src = widget.src
|
||||
const img = /\.(png|jpg|webp)/
|
||||
|
||||
document.querySelector('#scene').setAttribute("gltf-model",`url(${src})`)
|
||||
document.body.style.background = `url(${cover}) no-repeat center / cover`
|
||||
if( src.match(img) ){
|
||||
thumb.src = src
|
||||
let inferredSrc = await inferSource(src)
|
||||
widget.src = inferredSrc.replace(img,".glb")
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
widget.on("play", async () => {
|
||||
// initialize a specialized build of THREE/AFRAME
|
||||
const AFRAME = await import('aframe')
|
||||
window.THREE.DRACOLoader = await import('three/examples/jsm/loaders/DRACOLoader.js')
|
||||
window.THREE.FBXLoader = await import('three/examples/jsm/loaders/FBXLoader.js')
|
||||
window.THREE.USDZLoader = await import('three/examples/jsm/loaders/USDZLoader.js')
|
||||
window.THREE.ColladaLoader = await import('three/examples/jsm/loaders/ColladaLoader.js')
|
||||
window.THREE.MTLLoader = await import('three/examples/jsm/loaders/MTLLoader.js')
|
||||
window.THREE.GLTFExporter = await import('three/examples/jsm/exporters/GLTFExporter.js')
|
||||
// optional utils
|
||||
window.zipjs = await import("@zip.js/zip.js")
|
||||
window.webdav = await import("webdav")
|
||||
window.rs = await import("remotestoragejs")
|
||||
window.trystero = await import("trystero")
|
||||
|
||||
// include xrsh (remote for now, until the final integration is more clear)
|
||||
const script = document.createElement("script")
|
||||
script.src = "https://xrsh.isvery.ninja/xrsh.js"
|
||||
script.addEventListener("load", function(){
|
||||
const ent = document.createElement("a-entity")
|
||||
ent.setAttribute("isoterminal","minimized:true")
|
||||
ent.setAttribute("position","0 1.6 -0.3")
|
||||
document.querySelector("a-scene").appendChild(ent)
|
||||
})
|
||||
document.body.appendChild(script)
|
||||
})
|
||||
|
||||
await widget.emit("init")
|
||||
console.dir(widget)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,13 @@
|
|||
"license": "",
|
||||
"description": "",
|
||||
"dependencies": {
|
||||
"@needle-tools/three-animation-pointer": "^1.0.7",
|
||||
"@zip.js/zip.js": "^2.8.8",
|
||||
"aframe": "^1.7.1",
|
||||
"xrf": "^0.0.1"
|
||||
"remotestoragejs": "^2.0.0-beta.8",
|
||||
"trystero": "^0.22.0",
|
||||
"webdav": "^5.8.0",
|
||||
"xrf": "^0.0.1",
|
||||
"xrsh": "^0.0.5"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
# nativeBuildInputs is usually what you want -- tools you need to run
|
||||
nativeBuildInputs = with pkgs.buildPackages; [
|
||||
|
||||
nodejs_20
|
||||
monolith
|
||||
bun
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue