feat/escaperoom: work in progress [might break]

This commit is contained in:
Leon van Kammen 2024-07-09 17:27:21 +00:00
parent 485c3d4cfd
commit 6fc94b66c4
19 changed files with 10172 additions and 1666897 deletions

File diff suppressed because one or more lines are too long

View file

@ -1,8 +1,9 @@
/* /*
* v0.5.1 generated at Wed Jun 26 11:16:30 AM UTC 2024 * v0.5.1 generated at Tue Jul 9 04:28:50 PM UTC 2024
* https://xrfragment.org * https://xrfragment.org
* SPDX-License-Identifier: MPL-2.0 * SPDX-License-Identifier: MPL-2.0
*/ */
// Generated by Haxe 4.3.3
var $hx_exports = typeof exports != "undefined" ? exports : typeof window != "undefined" ? window : typeof self != "undefined" ? self : this; var $hx_exports = typeof exports != "undefined" ? exports : typeof window != "undefined" ? window : typeof self != "undefined" ? self : this;
(function ($global) { "use strict"; (function ($global) { "use strict";
$hx_exports["xrfragment"] = $hx_exports["xrfragment"] || {}; $hx_exports["xrfragment"] = $hx_exports["xrfragment"] || {};
@ -158,24 +159,11 @@ Std.string = function(s) {
return js_Boot.__string_rec(s,""); return js_Boot.__string_rec(s,"");
}; };
Std.parseInt = function(x) { Std.parseInt = function(x) {
if(x != null) { var v = parseInt(x);
var _g = 0; if(isNaN(v)) {
var _g1 = x.length; return null;
while(_g < _g1) {
var i = _g++;
var c = x.charCodeAt(i);
if(c <= 8 || c >= 14 && c != 32 && c != 45) {
var nc = x.charCodeAt(i + 1);
var v = parseInt(x,nc == 120 || nc == 88 ? 16 : 10);
if(isNaN(v)) {
return null;
} else {
return v;
}
}
}
} }
return null; return v;
}; };
var StringBuf = function() { var StringBuf = function() {
this.b = ""; this.b = "";
@ -471,10 +459,10 @@ haxe_Template.prototype = {
var _g_offset = 0; var _g_offset = 0;
var _g_s = data; var _g_s = data;
while(_g_offset < _g_s.length) { while(_g_offset < _g_s.length) {
var _g1_key = _g_offset; var _g_key = _g_offset;
var _g1_value = _g_s.charCodeAt(_g_offset++); var _g_value = _g_s.charCodeAt(_g_offset++);
var i = _g1_key; var i = _g_key;
var c = _g1_value; var c = _g_value;
if(c != 32) { if(c != 32) {
l.add({ p : HxOverrides.substr(data,i,null), s : true}); l.add({ p : HxOverrides.substr(data,i,null), s : true});
break; break;
@ -1384,6 +1372,8 @@ xrfragment_URI.toAbsolute = function(url,newUrl) {
} }
if(newURI.directory != null) { if(newURI.directory != null) {
if(newUrl.charAt(0) != "/" && newUrl.indexOf("://") == -1) { if(newUrl.charAt(0) != "/" && newUrl.indexOf("://") == -1) {
var stripRelative_r = new RegExp("\\./.*","".split("u").join(""));
directory = directory.replace(stripRelative_r,"");
directory += newURI.directory; directory += newURI.directory;
} else { } else {
directory = newURI.directory; directory = newURI.directory;
@ -1668,6 +1658,7 @@ xrf.emit = function(eventName, data){
console.groupCollapsed(label) console.groupCollapsed(label)
console.info(data) console.info(data)
console.groupEnd(label) console.groupEnd(label)
if( eventName == 'reset' ) debugger
if( xrf.debug > 2 ) debugger if( xrf.debug > 2 ) debugger
} }
return xrf.emit.promise(eventName,data) return xrf.emit.promise(eventName,data)
@ -1845,12 +1836,13 @@ pub.fragment = (k, opts ) => { // evaluate one fragment
if( !opts.skipXRWG && isPVorMediaFrag ) pub.XRWG(k,opts) if( !opts.skipXRWG && isPVorMediaFrag ) pub.XRWG(k,opts)
// call native function (xrf/env.js e.g.), or pass it to user decorator // call native function (xrf/env.js e.g.), or pass it to user decorator
xrf.emit(k,opts) if( xrf.frag[k] ){
.then( () => { xrf.emit(k,opts)
let func = xrf.frag[k] || function(){} .then( () => {
if( typeof xrf[k] == 'function' ) xrf[k]( func, frag, opts) let func = xrf.frag[k] || function(){}
else func( frag, opts) func( frag, opts)
}) })
}
} }
pub.XRWG = (word,opts) => { pub.XRWG = (word,opts) => {
@ -2024,14 +2016,15 @@ xrf.hasNoMaterial = (mesh) => {
const hasMaterialName = mesh.material && mesh.material.name.length > 0 const hasMaterialName = mesh.material && mesh.material.name.length > 0
return mesh.geometry && !hasMaterialName && !hasTexture return mesh.geometry && !hasMaterialName && !hasTexture
} }
xrf.navigator = { xrf.navigator = {
URI:{ URI: xrf.URI.parse(document.location.href)
scheme: document.location.protocol.replace(/:$/,''), // scheme: document.location.protocol.replace(/:$/,''),
directory: document.location.pathname, // directory: document.location.pathname,
host: document.location.hostname, // host: document.location.hostname,
port: document.location.port, // port: document.location.port,
file: 'index.glb' // file: 'index.glb'
} // }
} }
xrf.navigator.to = (url,flags,loader,data) => { xrf.navigator.to = (url,flags,loader,data) => {
@ -2041,6 +2034,8 @@ xrf.navigator.to = (url,flags,loader,data) => {
URI.hash = xrf.navigator.reactifyHash(URI.hash) // automatically reflect hash-changes to navigator.to(...) URI.hash = xrf.navigator.reactifyHash(URI.hash) // automatically reflect hash-changes to navigator.to(...)
// decorate with extra state // decorate with extra state
URI.fileChange = URI.file && URI.URN + URI.file != xrf.navigator.URI.URN + xrf.navigator.URI.file URI.fileChange = URI.file && URI.URN + URI.file != xrf.navigator.URI.URN + xrf.navigator.URI.file
console.log( URI.URN + URI.file )
console.log( xrf.navigator.URI.URN + xrf.navigator.URI.file )
URI.external = URI.file && URI.URN != document.location.origin + document.location.pathname URI.external = URI.file && URI.URN != document.location.origin + document.location.pathname
URI.hasPos = URI.hash.pos ? true : false URI.hasPos = URI.hash.pos ? true : false
URI.duplicatePos = URI.source == xrf.navigator.URI.source && URI.hasPos URI.duplicatePos = URI.source == xrf.navigator.URI.source && URI.hasPos
@ -2068,8 +2063,7 @@ xrf.navigator.to = (url,flags,loader,data) => {
loader = loader || new Loader().setPath( URI.URN ) loader = loader || new Loader().setPath( URI.URN )
} }
if( URI.duplicatePos || (!Object.values(URI.XRF).length && !URI.file && !URI.fileExt) ){
if( URI.duplicatePos || (!URI.fragment && !URI.file && !URI.fileExt) ){
return resolve(xrf.model) // nothing we can do here return resolve(xrf.model) // nothing we can do here
} }
if( xrf.model && !URI.fileChange && URI.hashChange && !URI.hasPos ){ if( xrf.model && !URI.fileChange && URI.hashChange && !URI.hasPos ){
@ -2173,14 +2167,14 @@ xrf.navigator.setupNavigateFallbacks = () => {
xrf.navigator.updateHash = (hash,opts) => { xrf.navigator.updateHash = (hash,opts) => {
if( hash.replace(/^#/,'') == document.location.hash.substr(1) || hash.match(/\|/) ) return // skip unnecesary pushState triggers if( hash.replace(/^#/,'') == document.location.hash.substr(1) || hash.match(/\|/) ) return // skip unnecesary pushState triggers
console.log(`URI: ${document.location.search.substr(1)}#${hash}`) console.log(`URI: ${document.location.search.substr(1)}#${hash}`)
xrf.navigator.updateHash.active = true // important to prevent recursion xrf.navigator.updateHash.active = false // important to prevent recursion
document.location.hash = hash document.location.hash = hash
xrf.navigator.updateHash.active = false xrf.navigator.updateHash.active = true
} }
xrf.navigator.pushState = (file,hash) => { xrf.navigator.pushState = (file,hash) => {
if( file == document.location.search.substr(1) ) return // page is in its default state if( file == document.location.search.substr(1) ) return // page is in its default state
window.history.pushState({},`${file}#${hash}`, document.location.pathname + `?${file}#${hash}` ) window.history.pushState({}, '', document.location.pathname + `?${xrf.navigator.URI.source.replace(/#.*/,'')}#${hash}` )
xrf.emit('pushState', {file, hash} ) xrf.emit('pushState', {file, hash} )
} }
@ -2243,7 +2237,8 @@ xrf.frag.href = function(v, opts){
if( !mesh.material || !mesh.material.visible ) return // ignore invisible nodes if( !mesh.material || !mesh.material.visible ) return // ignore invisible nodes
// update our values to the latest value (might be edited) // update our values to the latest value (might be edited)
xrf.Parser.parse( "href", mesh.userData.href, frag ) let URI = xrf.URI.template( mesh.userData.href, xrf.URI.vars.__object )
xrf.Parser.parse( "href", URI, frag )
const v = frag.href const v = frag.href
// bubble up! // bubble up!
@ -2361,8 +2356,9 @@ xrf.addEventListener('audioInited', function(opts){
*/ */
// this is called by navigator.js rather than by a URL e.g. // this is called by navigator.js rather than by a URL e.g.
xrf.frag.defaultPredefinedViews = (opts) => { xrf.frag['#'] = xrf.frag.defaultPredefinedViews = (opts) => {
let {scene,model} = opts; let {scene,model} = opts;
if( !scene ) return
let defaultFragment; let defaultFragment;
scene.traverse( (n) => { scene.traverse( (n) => {
if( n.userData && n.userData['#'] ){ if( n.userData && n.userData['#'] ){
@ -2715,10 +2711,17 @@ xrf.frag.t.default = {
xrf.addEventListener('parseModel', (opts) => { xrf.addEventListener('parseModel', (opts) => {
let {model} = opts let {model} = opts
let mixer = model.mixer = new xrf.THREE.AnimationMixer(model.scene) let mixer = model.mixer = new xrf.THREE.AnimationMixer(model.scene)
mixer.model = model mixer.model = model
mixer.loop = {timeStart:0,timeStop:0,speed:1.0} mixer.loop = {timeStart:0,timeStop:0,speed:1.0}
mixer.i = xrf.mixers.length mixer.i = xrf.mixers.length
mixer.actions = [] mixer.actions = []
// calculate total duration/frame based on longest animation
mixer.duration = 0
if( model.animations.length ){
model.animations.map( (a) => mixer.duration = ( a.duration > mixer.duration ) ? a.duration : mixer.duration )
}
model.animations.map( (anim) => { model.animations.map( (anim) => {
anim.optimize() anim.optimize()
@ -2739,7 +2742,7 @@ xrf.addEventListener('parseModel', (opts) => {
mixer.updateLoop = (t) => { mixer.updateLoop = (t) => {
if( t ){ if( t ){
mixer.loop.timeStart = t.x != undefined ? t.x : mixer.loop.timeStart mixer.loop.timeStart = t.x != undefined ? t.x : mixer.loop.timeStart
mixer.loop.timeStop = t.y != undefined ? t.y : mixer.duration mixer.loop.timeStop = t.y != undefined ? t.y : mixer.loop.timeStop
} }
mixer.actions.map( (action) => { mixer.actions.map( (action) => {
if( mixer.loop.timeStart != undefined ){ if( mixer.loop.timeStart != undefined ){
@ -2762,7 +2765,6 @@ xrf.addEventListener('parseModel', (opts) => {
mixer.update = function(time){ mixer.update = function(time){
mixer.time = Math.abs(mixer.time) mixer.time = Math.abs(mixer.time)
if( time == 0 ) return update.call(this,time) if( time == 0 ) return update.call(this,time)
// loop jump // loop jump
if( mixer.loop.timeStop > 0 && mixer.time > mixer.loop.timeStop ){ if( mixer.loop.timeStop > 0 && mixer.time > mixer.loop.timeStop ){
if( mixer.loop.enabled ){ if( mixer.loop.enabled ){
@ -2774,12 +2776,6 @@ xrf.addEventListener('parseModel', (opts) => {
mixer.update.patched = true mixer.update.patched = true
} }
// calculate total duration/frame based on longest animation
mixer.duration = 0
if( model.animations.length ){
model.animations.map( (a) => mixer.duration = ( a.duration > mixer.duration ) ? a.duration : mixer.duration )
}
xrf.mixers.push(mixer) xrf.mixers.push(mixer)
}) })
@ -3401,8 +3397,8 @@ xrf.addEventListener('parseModel', (opts) => {
if( n.userData ){ if( n.userData ){
for( let i in n.userData ){ for( let i in n.userData ){
if( i[0] == '#' || i.match(/^(href|tag)$/) ) continue // ignore XR Fragment aliases //if( i[0] == '#' || i.match(/^(href|tag)$/) ) continue // ignore XR Fragment aliases
if( i == 'src' ){ if( i.match(/^(src|href|tag)/) ){
// lets declare empty variables found in src-values ('https://foo.com/video.mp4#{somevar}') e.g. // lets declare empty variables found in src-values ('https://foo.com/video.mp4#{somevar}') e.g.
if( n.userData[i].match(variables) ){ if( n.userData[i].match(variables) ){
let vars = [].concat( n.userData[i].match(variables) ) let vars = [].concat( n.userData[i].match(variables) )
@ -3431,10 +3427,11 @@ xrf.addEventListener('dynamicKeyValue', (opts) => {
if( !xrf.URI.vars[ v.string ] ) return console.error(`'${v.string}' metadata-key not found in scene`) if( !xrf.URI.vars[ v.string ] ) return console.error(`'${v.string}' metadata-key not found in scene`)
//if( xrf.URI.vars[ id ] && !match.length ) return console.error(`'${id}' object/tag/metadata-key not found in scene`) //if( xrf.URI.vars[ id ] && !match.length ) return console.error(`'${id}' object/tag/metadata-key not found in scene`)
if( xrf.debug ) console.log(`URI.vars[${id}]='${v.string}'`) if( xrf.debug ) console.log(`URI.vars[${id}] => '${v.string}'`)
if( xrf.URI.vars[id] ){ if( xrf.URI.vars[id] ){
xrf.URI.vars[ id ] = xrf.URI.vars[ v.string ] // update var xrf.URI.vars[ id ] = xrf.URI.vars[ v.string ] // update var
if( xrf.debug ) console.log(`URI.vars[${id}] => '${xrf.URI.vars[ v.string ]()}'`)
xrf.scene.traverse( (n) => { xrf.scene.traverse( (n) => {
// re-expand src-values which use the updated URI Template var // re-expand src-values which use the updated URI Template var
if( n.userData && n.userData.src && n.userData.srcTemplate && n.userData.srcTemplate.match(`{${id}}`) ){ if( n.userData && n.userData.src && n.userData.srcTemplate && n.userData.srcTemplate.match(`{${id}}`) ){
@ -4178,6 +4175,14 @@ window.AFRAME.registerComponent('xrf', {
if( VRbutton ) VRbutton.addEventListener('click', () => AFRAME.XRF.hashbus.pub( '#VR' ) ) if( VRbutton ) VRbutton.addEventListener('click', () => AFRAME.XRF.hashbus.pub( '#VR' ) )
}) })
// not part of the spec, but convenient to only show AR button when negative VR-tag was defined in default fragment ('#' in rootscene file)
xrf.addEventListener('#', function(e){
if( e.frag['#'].string.match(/-VR/) ){
aScene.removeAttribute('xr-mode-ui')
aScene.setAttribute('xr-mode-ui',"XRMode: ar")
}
})
let repositionUser = (scale) => () => { let repositionUser = (scale) => () => {
// sometimes AFRAME resets the user position to 0,0,0 when entering VR (not sure why) // sometimes AFRAME resets the user position to 0,0,0 when entering VR (not sure why)
setTimeout( () => { setTimeout( () => {
@ -4190,6 +4195,7 @@ window.AFRAME.registerComponent('xrf', {
aScene.addEventListener('enter-ar', repositionUser(2) ) aScene.addEventListener('enter-ar', repositionUser(2) )
xrf.addEventListener('navigateLoaded', (opts) => { xrf.addEventListener('navigateLoaded', (opts) => {
setTimeout( () => AFRAME.fade.out(),500) setTimeout( () => AFRAME.fade.out(),500)
let isLocal = opts.url.match(/^#/) let isLocal = opts.url.match(/^#/)
if( isLocal ) return if( isLocal ) return

32
dist/xrfragment.js vendored
View file

@ -1,3 +1,4 @@
// Generated by Haxe 4.3.3
var $hx_exports = typeof exports != "undefined" ? exports : typeof window != "undefined" ? window : typeof self != "undefined" ? self : this; var $hx_exports = typeof exports != "undefined" ? exports : typeof window != "undefined" ? window : typeof self != "undefined" ? self : this;
(function ($global) { "use strict"; (function ($global) { "use strict";
$hx_exports["xrfragment"] = $hx_exports["xrfragment"] || {}; $hx_exports["xrfragment"] = $hx_exports["xrfragment"] || {};
@ -153,24 +154,11 @@ Std.string = function(s) {
return js_Boot.__string_rec(s,""); return js_Boot.__string_rec(s,"");
}; };
Std.parseInt = function(x) { Std.parseInt = function(x) {
if(x != null) { var v = parseInt(x);
var _g = 0; if(isNaN(v)) {
var _g1 = x.length; return null;
while(_g < _g1) {
var i = _g++;
var c = x.charCodeAt(i);
if(c <= 8 || c >= 14 && c != 32 && c != 45) {
var nc = x.charCodeAt(i + 1);
var v = parseInt(x,nc == 120 || nc == 88 ? 16 : 10);
if(isNaN(v)) {
return null;
} else {
return v;
}
}
}
} }
return null; return v;
}; };
var StringBuf = function() { var StringBuf = function() {
this.b = ""; this.b = "";
@ -466,10 +454,10 @@ haxe_Template.prototype = {
var _g_offset = 0; var _g_offset = 0;
var _g_s = data; var _g_s = data;
while(_g_offset < _g_s.length) { while(_g_offset < _g_s.length) {
var _g1_key = _g_offset; var _g_key = _g_offset;
var _g1_value = _g_s.charCodeAt(_g_offset++); var _g_value = _g_s.charCodeAt(_g_offset++);
var i = _g1_key; var i = _g_key;
var c = _g1_value; var c = _g_value;
if(c != 32) { if(c != 32) {
l.add({ p : HxOverrides.substr(data,i,null), s : true}); l.add({ p : HxOverrides.substr(data,i,null), s : true});
break; break;
@ -1379,6 +1367,8 @@ xrfragment_URI.toAbsolute = function(url,newUrl) {
} }
if(newURI.directory != null) { if(newURI.directory != null) {
if(newUrl.charAt(0) != "/" && newUrl.indexOf("://") == -1) { if(newUrl.charAt(0) != "/" && newUrl.indexOf("://") == -1) {
var stripRelative_r = new RegExp("\\./.*","".split("u").join(""));
directory = directory.replace(stripRelative_r,"");
directory += newURI.directory; directory += newURI.directory;
} else { } else {
directory = newURI.directory; directory = newURI.directory;

1317
dist/xrfragment.lua vendored

File diff suppressed because it is too large Load diff

1675034
dist/xrfragment.module.js vendored

File diff suppressed because it is too large Load diff

205
dist/xrfragment.py vendored
View file

@ -1,3 +1,5 @@
# Generated by Haxe 4.3.3
# coding: utf-8
import sys import sys
import math as python_lib_Math import math as python_lib_Math
@ -305,67 +307,48 @@ class Std:
def parseInt(x): def parseInt(x):
if (x is None): if (x is None):
return None return None
try: _hx_len = len(x)
return int(x) index = 0
except BaseException as _g: while (index < _hx_len):
None if (not (x[index] in " \n\r\t\x0B\x0C")):
base = 10 break
_hx_len = len(x) index = (index + 1)
foundCount = 0 isNegative = None
sign = 0 if (index < _hx_len):
firstDigitIndex = 0 sign = x[index]
lastDigitIndex = -1 if ((sign == "-") or ((sign == "+"))):
previous = 0 index = (index + 1)
_g = 0 isNegative = (sign == "-")
_g1 = _hx_len else:
while (_g < _g1): isNegative = False
i = _g isHexadecimal = None
_g = (_g + 1) if ((index + 1) < _hx_len):
c = (-1 if ((i >= len(x))) else ord(x[i])) cur = x[index]
if (((c > 8) and ((c < 14))) or ((c == 32))): next = x[(index + 1)]
if (foundCount > 0): isHexadecimal = ((cur == "0") and (((next == "x") or ((next == "X")))))
return None else:
continue isHexadecimal = False
else: if isHexadecimal:
c1 = c index = (index + 2)
if (c1 == 43): cur = index
if (foundCount == 0): if isHexadecimal:
sign = 1 while (cur < _hx_len):
elif (not (((48 <= c) and ((c <= 57))))): if (not (x[cur] in "0123456789abcdefABCDEF")):
if (not (((base == 16) and ((((97 <= c) and ((c <= 122))) or (((65 <= c) and ((c <= 90))))))))): break
break cur = (cur + 1)
elif (c1 == 45): else:
if (foundCount == 0): while (cur < _hx_len):
sign = -1 if (not (x[cur] in "0123456789")):
elif (not (((48 <= c) and ((c <= 57))))): break
if (not (((base == 16) and ((((97 <= c) and ((c <= 122))) or (((65 <= c) and ((c <= 90))))))))): cur = (cur + 1)
break firstInvalidIndex = cur
elif (c1 == 48): if (index == firstInvalidIndex):
if (not (((foundCount == 0) or (((foundCount == 1) and ((sign != 0))))))):
if (not (((48 <= c) and ((c <= 57))))):
if (not (((base == 16) and ((((97 <= c) and ((c <= 122))) or (((65 <= c) and ((c <= 90))))))))):
break
elif ((c1 == 120) or ((c1 == 88))):
if ((previous == 48) and ((((foundCount == 1) and ((sign == 0))) or (((foundCount == 2) and ((sign != 0))))))):
base = 16
elif (not (((48 <= c) and ((c <= 57))))):
if (not (((base == 16) and ((((97 <= c) and ((c <= 122))) or (((65 <= c) and ((c <= 90))))))))):
break
elif (not (((48 <= c) and ((c <= 57))))):
if (not (((base == 16) and ((((97 <= c) and ((c <= 122))) or (((65 <= c) and ((c <= 90))))))))):
break
if (((foundCount == 0) and ((sign == 0))) or (((foundCount == 1) and ((sign != 0))))):
firstDigitIndex = i
foundCount = (foundCount + 1)
lastDigitIndex = i
previous = c
if (firstDigitIndex <= lastDigitIndex):
digits = HxString.substring(x,firstDigitIndex,(lastDigitIndex + 1))
try:
return (((-1 if ((sign == -1)) else 1)) * int(digits,base))
except BaseException as _g:
return None
return None return None
result = int(HxString.substring(x,index,firstInvalidIndex),(16 if isHexadecimal else 10))
if isNegative:
return -result
else:
return result
@staticmethod @staticmethod
def shortenPossibleNumber(x): def shortenPossibleNumber(x):
@ -860,13 +843,13 @@ class haxe_Template:
_g_offset = 0 _g_offset = 0
_g_s = data _g_s = data
while (_g_offset < len(_g_s)): while (_g_offset < len(_g_s)):
_g1_key = _g_offset _g_key = _g_offset
s = _g_s s = _g_s
index = _g_offset index = _g_offset
_g_offset = (_g_offset + 1) _g_offset = (_g_offset + 1)
_g1_value = (-1 if ((index >= len(s))) else ord(s[index])) _g_value = (-1 if ((index >= len(s))) else ord(s[index]))
i = _g1_key i = _g_key
c = _g1_value c = _g_value
if (c != 32): if (c != 32):
l.add(_hx_AnonObject({'p': HxString.substr(data,i,None), 's': True})) l.add(_hx_AnonObject({'p': HxString.substr(data,i,None), 's': True}))
break break
@ -1169,7 +1152,7 @@ class haxe_ValueException(haxe_Exception):
def __init__(self,value,previous = None,native = None): def __init__(self,value,previous = None,native = None):
self.value = None self.value = None
super().__init__(Std.string(value),previous,native) super().__init__(("null" if ((value is None)) else Std.string(value)),previous,native)
self.value = value self.value = value
def unwrap(self): def unwrap(self):
@ -1494,10 +1477,7 @@ class python_Boot:
return python_internal_MethodClosure(o,HxString.charCodeAt) return python_internal_MethodClosure(o,HxString.charCodeAt)
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
elif (_hx_local_0 == 11): elif (_hx_local_0 == 11):
if (field1 == "lastIndexOf"): if (field1 == "lastIndexOf"):
return python_internal_MethodClosure(o,HxString.lastIndexOf) return python_internal_MethodClosure(o,HxString.lastIndexOf)
@ -1507,46 +1487,31 @@ class python_Boot:
return python_internal_MethodClosure(o,HxString.toUpperCase) return python_internal_MethodClosure(o,HxString.toUpperCase)
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
elif (_hx_local_0 == 9): elif (_hx_local_0 == 9):
if (field1 == "substring"): if (field1 == "substring"):
return python_internal_MethodClosure(o,HxString.substring) return python_internal_MethodClosure(o,HxString.substring)
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
elif (_hx_local_0 == 5): elif (_hx_local_0 == 5):
if (field1 == "split"): if (field1 == "split"):
return python_internal_MethodClosure(o,HxString.split) return python_internal_MethodClosure(o,HxString.split)
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
elif (_hx_local_0 == 7): elif (_hx_local_0 == 7):
if (field1 == "indexOf"): if (field1 == "indexOf"):
return python_internal_MethodClosure(o,HxString.indexOf) return python_internal_MethodClosure(o,HxString.indexOf)
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
elif (_hx_local_0 == 8): elif (_hx_local_0 == 8):
if (field1 == "toString"): if (field1 == "toString"):
return python_internal_MethodClosure(o,HxString.toString) return python_internal_MethodClosure(o,HxString.toString)
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
elif (_hx_local_0 == 6): elif (_hx_local_0 == 6):
if (field1 == "charAt"): if (field1 == "charAt"):
return python_internal_MethodClosure(o,HxString.charAt) return python_internal_MethodClosure(o,HxString.charAt)
@ -1556,16 +1521,10 @@ class python_Boot:
return python_internal_MethodClosure(o,HxString.substr) return python_internal_MethodClosure(o,HxString.substr)
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
elif isinstance(o,list): elif isinstance(o,list):
field1 = field field1 = field
_hx_local_1 = len(field1) _hx_local_1 = len(field1)
@ -1574,10 +1533,7 @@ class python_Boot:
return python_internal_MethodClosure(o,python_internal_ArrayImpl.lastIndexOf) return python_internal_MethodClosure(o,python_internal_ArrayImpl.lastIndexOf)
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
elif (_hx_local_1 == 4): elif (_hx_local_1 == 4):
if (field1 == "copy"): if (field1 == "copy"):
return python_internal_MethodClosure(o,python_internal_ArrayImpl.copy) return python_internal_MethodClosure(o,python_internal_ArrayImpl.copy)
@ -1589,10 +1545,7 @@ class python_Boot:
return python_internal_MethodClosure(o,python_internal_ArrayImpl.sort) return python_internal_MethodClosure(o,python_internal_ArrayImpl.sort)
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
elif (_hx_local_1 == 5): elif (_hx_local_1 == 5):
if (field1 == "shift"): if (field1 == "shift"):
return python_internal_MethodClosure(o,python_internal_ArrayImpl.shift) return python_internal_MethodClosure(o,python_internal_ArrayImpl.shift)
@ -1600,10 +1553,7 @@ class python_Boot:
return python_internal_MethodClosure(o,python_internal_ArrayImpl.slice) return python_internal_MethodClosure(o,python_internal_ArrayImpl.slice)
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
elif (_hx_local_1 == 7): elif (_hx_local_1 == 7):
if (field1 == "indexOf"): if (field1 == "indexOf"):
return python_internal_MethodClosure(o,python_internal_ArrayImpl.indexOf) return python_internal_MethodClosure(o,python_internal_ArrayImpl.indexOf)
@ -1613,10 +1563,7 @@ class python_Boot:
return python_internal_MethodClosure(o,python_internal_ArrayImpl.unshift) return python_internal_MethodClosure(o,python_internal_ArrayImpl.unshift)
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
elif (_hx_local_1 == 3): elif (_hx_local_1 == 3):
if (field1 == "map"): if (field1 == "map"):
return python_internal_MethodClosure(o,python_internal_ArrayImpl.map) return python_internal_MethodClosure(o,python_internal_ArrayImpl.map)
@ -1624,10 +1571,7 @@ class python_Boot:
return python_internal_MethodClosure(o,python_internal_ArrayImpl.pop) return python_internal_MethodClosure(o,python_internal_ArrayImpl.pop)
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
elif (_hx_local_1 == 8): elif (_hx_local_1 == 8):
if (field1 == "contains"): if (field1 == "contains"):
return python_internal_MethodClosure(o,python_internal_ArrayImpl.contains) return python_internal_MethodClosure(o,python_internal_ArrayImpl.contains)
@ -1637,19 +1581,13 @@ class python_Boot:
return python_internal_MethodClosure(o,python_internal_ArrayImpl.toString) return python_internal_MethodClosure(o,python_internal_ArrayImpl.toString)
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
elif (_hx_local_1 == 16): elif (_hx_local_1 == 16):
if (field1 == "keyValueIterator"): if (field1 == "keyValueIterator"):
return python_internal_MethodClosure(o,python_internal_ArrayImpl.keyValueIterator) return python_internal_MethodClosure(o,python_internal_ArrayImpl.keyValueIterator)
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
elif (_hx_local_1 == 6): elif (_hx_local_1 == 6):
if (field1 == "concat"): if (field1 == "concat"):
return python_internal_MethodClosure(o,python_internal_ArrayImpl.concat) return python_internal_MethodClosure(o,python_internal_ArrayImpl.concat)
@ -1665,22 +1603,13 @@ class python_Boot:
return python_internal_MethodClosure(o,python_internal_ArrayImpl.splice) return python_internal_MethodClosure(o,python_internal_ArrayImpl.splice)
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
else: else:
field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field)) field1 = (("_hx_" + field) if ((field in python_Boot.keywords)) else (("_hx_" + field) if (((((len(field) > 2) and ((ord(field[0]) == 95))) and ((ord(field[1]) == 95))) and ((ord(field[(len(field) - 1)]) != 95)))) else field))
if hasattr(o,field1): return (getattr(o,field1) if (hasattr(o,field1)) else None)
return getattr(o,field1)
else:
return None
@staticmethod @staticmethod
def getInstanceFields(c): def getInstanceFields(c):
@ -2574,6 +2503,8 @@ class xrfragment_URI:
else: else:
tmp = False tmp = False
if tmp: if tmp:
stripRelative = EReg("\\./.*","")
directory = stripRelative.replace(directory,"")
directory = (("null" if directory is None else directory) + HxOverrides.stringOrNull(newURI.directory)) directory = (("null" if directory is None else directory) + HxOverrides.stringOrNull(newURI.directory))
else: else:
directory = newURI.directory directory = newURI.directory

View file

@ -1,8 +1,9 @@
/* /*
* v0.5.1 generated at Wed Jun 26 11:16:30 AM UTC 2024 * v0.5.1 generated at Tue Jul 9 04:28:50 PM UTC 2024
* https://xrfragment.org * https://xrfragment.org
* SPDX-License-Identifier: MPL-2.0 * SPDX-License-Identifier: MPL-2.0
*/ */
// Generated by Haxe 4.3.3
var $hx_exports = typeof exports != "undefined" ? exports : typeof window != "undefined" ? window : typeof self != "undefined" ? self : this; var $hx_exports = typeof exports != "undefined" ? exports : typeof window != "undefined" ? window : typeof self != "undefined" ? self : this;
(function ($global) { "use strict"; (function ($global) { "use strict";
$hx_exports["xrfragment"] = $hx_exports["xrfragment"] || {}; $hx_exports["xrfragment"] = $hx_exports["xrfragment"] || {};
@ -158,24 +159,11 @@ Std.string = function(s) {
return js_Boot.__string_rec(s,""); return js_Boot.__string_rec(s,"");
}; };
Std.parseInt = function(x) { Std.parseInt = function(x) {
if(x != null) { var v = parseInt(x);
var _g = 0; if(isNaN(v)) {
var _g1 = x.length; return null;
while(_g < _g1) {
var i = _g++;
var c = x.charCodeAt(i);
if(c <= 8 || c >= 14 && c != 32 && c != 45) {
var nc = x.charCodeAt(i + 1);
var v = parseInt(x,nc == 120 || nc == 88 ? 16 : 10);
if(isNaN(v)) {
return null;
} else {
return v;
}
}
}
} }
return null; return v;
}; };
var StringBuf = function() { var StringBuf = function() {
this.b = ""; this.b = "";
@ -471,10 +459,10 @@ haxe_Template.prototype = {
var _g_offset = 0; var _g_offset = 0;
var _g_s = data; var _g_s = data;
while(_g_offset < _g_s.length) { while(_g_offset < _g_s.length) {
var _g1_key = _g_offset; var _g_key = _g_offset;
var _g1_value = _g_s.charCodeAt(_g_offset++); var _g_value = _g_s.charCodeAt(_g_offset++);
var i = _g1_key; var i = _g_key;
var c = _g1_value; var c = _g_value;
if(c != 32) { if(c != 32) {
l.add({ p : HxOverrides.substr(data,i,null), s : true}); l.add({ p : HxOverrides.substr(data,i,null), s : true});
break; break;
@ -1384,6 +1372,8 @@ xrfragment_URI.toAbsolute = function(url,newUrl) {
} }
if(newURI.directory != null) { if(newURI.directory != null) {
if(newUrl.charAt(0) != "/" && newUrl.indexOf("://") == -1) { if(newUrl.charAt(0) != "/" && newUrl.indexOf("://") == -1) {
var stripRelative_r = new RegExp("\\./.*","".split("u").join(""));
directory = directory.replace(stripRelative_r,"");
directory += newURI.directory; directory += newURI.directory;
} else { } else {
directory = newURI.directory; directory = newURI.directory;
@ -1668,6 +1658,7 @@ xrf.emit = function(eventName, data){
console.groupCollapsed(label) console.groupCollapsed(label)
console.info(data) console.info(data)
console.groupEnd(label) console.groupEnd(label)
if( eventName == 'reset' ) debugger
if( xrf.debug > 2 ) debugger if( xrf.debug > 2 ) debugger
} }
return xrf.emit.promise(eventName,data) return xrf.emit.promise(eventName,data)
@ -1845,12 +1836,13 @@ pub.fragment = (k, opts ) => { // evaluate one fragment
if( !opts.skipXRWG && isPVorMediaFrag ) pub.XRWG(k,opts) if( !opts.skipXRWG && isPVorMediaFrag ) pub.XRWG(k,opts)
// call native function (xrf/env.js e.g.), or pass it to user decorator // call native function (xrf/env.js e.g.), or pass it to user decorator
xrf.emit(k,opts) if( xrf.frag[k] ){
.then( () => { xrf.emit(k,opts)
let func = xrf.frag[k] || function(){} .then( () => {
if( typeof xrf[k] == 'function' ) xrf[k]( func, frag, opts) let func = xrf.frag[k] || function(){}
else func( frag, opts) func( frag, opts)
}) })
}
} }
pub.XRWG = (word,opts) => { pub.XRWG = (word,opts) => {
@ -2024,14 +2016,15 @@ xrf.hasNoMaterial = (mesh) => {
const hasMaterialName = mesh.material && mesh.material.name.length > 0 const hasMaterialName = mesh.material && mesh.material.name.length > 0
return mesh.geometry && !hasMaterialName && !hasTexture return mesh.geometry && !hasMaterialName && !hasTexture
} }
xrf.navigator = { xrf.navigator = {
URI:{ URI: xrf.URI.parse(document.location.href)
scheme: document.location.protocol.replace(/:$/,''), // scheme: document.location.protocol.replace(/:$/,''),
directory: document.location.pathname, // directory: document.location.pathname,
host: document.location.hostname, // host: document.location.hostname,
port: document.location.port, // port: document.location.port,
file: 'index.glb' // file: 'index.glb'
} // }
} }
xrf.navigator.to = (url,flags,loader,data) => { xrf.navigator.to = (url,flags,loader,data) => {
@ -2041,6 +2034,8 @@ xrf.navigator.to = (url,flags,loader,data) => {
URI.hash = xrf.navigator.reactifyHash(URI.hash) // automatically reflect hash-changes to navigator.to(...) URI.hash = xrf.navigator.reactifyHash(URI.hash) // automatically reflect hash-changes to navigator.to(...)
// decorate with extra state // decorate with extra state
URI.fileChange = URI.file && URI.URN + URI.file != xrf.navigator.URI.URN + xrf.navigator.URI.file URI.fileChange = URI.file && URI.URN + URI.file != xrf.navigator.URI.URN + xrf.navigator.URI.file
console.log( URI.URN + URI.file )
console.log( xrf.navigator.URI.URN + xrf.navigator.URI.file )
URI.external = URI.file && URI.URN != document.location.origin + document.location.pathname URI.external = URI.file && URI.URN != document.location.origin + document.location.pathname
URI.hasPos = URI.hash.pos ? true : false URI.hasPos = URI.hash.pos ? true : false
URI.duplicatePos = URI.source == xrf.navigator.URI.source && URI.hasPos URI.duplicatePos = URI.source == xrf.navigator.URI.source && URI.hasPos
@ -2068,8 +2063,7 @@ xrf.navigator.to = (url,flags,loader,data) => {
loader = loader || new Loader().setPath( URI.URN ) loader = loader || new Loader().setPath( URI.URN )
} }
if( URI.duplicatePos || (!Object.values(URI.XRF).length && !URI.file && !URI.fileExt) ){
if( URI.duplicatePos || (!URI.fragment && !URI.file && !URI.fileExt) ){
return resolve(xrf.model) // nothing we can do here return resolve(xrf.model) // nothing we can do here
} }
if( xrf.model && !URI.fileChange && URI.hashChange && !URI.hasPos ){ if( xrf.model && !URI.fileChange && URI.hashChange && !URI.hasPos ){
@ -2173,14 +2167,14 @@ xrf.navigator.setupNavigateFallbacks = () => {
xrf.navigator.updateHash = (hash,opts) => { xrf.navigator.updateHash = (hash,opts) => {
if( hash.replace(/^#/,'') == document.location.hash.substr(1) || hash.match(/\|/) ) return // skip unnecesary pushState triggers if( hash.replace(/^#/,'') == document.location.hash.substr(1) || hash.match(/\|/) ) return // skip unnecesary pushState triggers
console.log(`URI: ${document.location.search.substr(1)}#${hash}`) console.log(`URI: ${document.location.search.substr(1)}#${hash}`)
xrf.navigator.updateHash.active = true // important to prevent recursion xrf.navigator.updateHash.active = false // important to prevent recursion
document.location.hash = hash document.location.hash = hash
xrf.navigator.updateHash.active = false xrf.navigator.updateHash.active = true
} }
xrf.navigator.pushState = (file,hash) => { xrf.navigator.pushState = (file,hash) => {
if( file == document.location.search.substr(1) ) return // page is in its default state if( file == document.location.search.substr(1) ) return // page is in its default state
window.history.pushState({},`${file}#${hash}`, document.location.pathname + `?${file}#${hash}` ) window.history.pushState({}, '', document.location.pathname + `?${xrf.navigator.URI.source.replace(/#.*/,'')}#${hash}` )
xrf.emit('pushState', {file, hash} ) xrf.emit('pushState', {file, hash} )
} }
@ -2243,7 +2237,8 @@ xrf.frag.href = function(v, opts){
if( !mesh.material || !mesh.material.visible ) return // ignore invisible nodes if( !mesh.material || !mesh.material.visible ) return // ignore invisible nodes
// update our values to the latest value (might be edited) // update our values to the latest value (might be edited)
xrf.Parser.parse( "href", mesh.userData.href, frag ) let URI = xrf.URI.template( mesh.userData.href, xrf.URI.vars.__object )
xrf.Parser.parse( "href", URI, frag )
const v = frag.href const v = frag.href
// bubble up! // bubble up!
@ -2361,8 +2356,9 @@ xrf.addEventListener('audioInited', function(opts){
*/ */
// this is called by navigator.js rather than by a URL e.g. // this is called by navigator.js rather than by a URL e.g.
xrf.frag.defaultPredefinedViews = (opts) => { xrf.frag['#'] = xrf.frag.defaultPredefinedViews = (opts) => {
let {scene,model} = opts; let {scene,model} = opts;
if( !scene ) return
let defaultFragment; let defaultFragment;
scene.traverse( (n) => { scene.traverse( (n) => {
if( n.userData && n.userData['#'] ){ if( n.userData && n.userData['#'] ){
@ -2715,10 +2711,17 @@ xrf.frag.t.default = {
xrf.addEventListener('parseModel', (opts) => { xrf.addEventListener('parseModel', (opts) => {
let {model} = opts let {model} = opts
let mixer = model.mixer = new xrf.THREE.AnimationMixer(model.scene) let mixer = model.mixer = new xrf.THREE.AnimationMixer(model.scene)
mixer.model = model mixer.model = model
mixer.loop = {timeStart:0,timeStop:0,speed:1.0} mixer.loop = {timeStart:0,timeStop:0,speed:1.0}
mixer.i = xrf.mixers.length mixer.i = xrf.mixers.length
mixer.actions = [] mixer.actions = []
// calculate total duration/frame based on longest animation
mixer.duration = 0
if( model.animations.length ){
model.animations.map( (a) => mixer.duration = ( a.duration > mixer.duration ) ? a.duration : mixer.duration )
}
model.animations.map( (anim) => { model.animations.map( (anim) => {
anim.optimize() anim.optimize()
@ -2739,7 +2742,7 @@ xrf.addEventListener('parseModel', (opts) => {
mixer.updateLoop = (t) => { mixer.updateLoop = (t) => {
if( t ){ if( t ){
mixer.loop.timeStart = t.x != undefined ? t.x : mixer.loop.timeStart mixer.loop.timeStart = t.x != undefined ? t.x : mixer.loop.timeStart
mixer.loop.timeStop = t.y != undefined ? t.y : mixer.duration mixer.loop.timeStop = t.y != undefined ? t.y : mixer.loop.timeStop
} }
mixer.actions.map( (action) => { mixer.actions.map( (action) => {
if( mixer.loop.timeStart != undefined ){ if( mixer.loop.timeStart != undefined ){
@ -2762,7 +2765,6 @@ xrf.addEventListener('parseModel', (opts) => {
mixer.update = function(time){ mixer.update = function(time){
mixer.time = Math.abs(mixer.time) mixer.time = Math.abs(mixer.time)
if( time == 0 ) return update.call(this,time) if( time == 0 ) return update.call(this,time)
// loop jump // loop jump
if( mixer.loop.timeStop > 0 && mixer.time > mixer.loop.timeStop ){ if( mixer.loop.timeStop > 0 && mixer.time > mixer.loop.timeStop ){
if( mixer.loop.enabled ){ if( mixer.loop.enabled ){
@ -2774,12 +2776,6 @@ xrf.addEventListener('parseModel', (opts) => {
mixer.update.patched = true mixer.update.patched = true
} }
// calculate total duration/frame based on longest animation
mixer.duration = 0
if( model.animations.length ){
model.animations.map( (a) => mixer.duration = ( a.duration > mixer.duration ) ? a.duration : mixer.duration )
}
xrf.mixers.push(mixer) xrf.mixers.push(mixer)
}) })
@ -3401,8 +3397,8 @@ xrf.addEventListener('parseModel', (opts) => {
if( n.userData ){ if( n.userData ){
for( let i in n.userData ){ for( let i in n.userData ){
if( i[0] == '#' || i.match(/^(href|tag)$/) ) continue // ignore XR Fragment aliases //if( i[0] == '#' || i.match(/^(href|tag)$/) ) continue // ignore XR Fragment aliases
if( i == 'src' ){ if( i.match(/^(src|href|tag)/) ){
// lets declare empty variables found in src-values ('https://foo.com/video.mp4#{somevar}') e.g. // lets declare empty variables found in src-values ('https://foo.com/video.mp4#{somevar}') e.g.
if( n.userData[i].match(variables) ){ if( n.userData[i].match(variables) ){
let vars = [].concat( n.userData[i].match(variables) ) let vars = [].concat( n.userData[i].match(variables) )
@ -3431,10 +3427,11 @@ xrf.addEventListener('dynamicKeyValue', (opts) => {
if( !xrf.URI.vars[ v.string ] ) return console.error(`'${v.string}' metadata-key not found in scene`) if( !xrf.URI.vars[ v.string ] ) return console.error(`'${v.string}' metadata-key not found in scene`)
//if( xrf.URI.vars[ id ] && !match.length ) return console.error(`'${id}' object/tag/metadata-key not found in scene`) //if( xrf.URI.vars[ id ] && !match.length ) return console.error(`'${id}' object/tag/metadata-key not found in scene`)
if( xrf.debug ) console.log(`URI.vars[${id}]='${v.string}'`) if( xrf.debug ) console.log(`URI.vars[${id}] => '${v.string}'`)
if( xrf.URI.vars[id] ){ if( xrf.URI.vars[id] ){
xrf.URI.vars[ id ] = xrf.URI.vars[ v.string ] // update var xrf.URI.vars[ id ] = xrf.URI.vars[ v.string ] // update var
if( xrf.debug ) console.log(`URI.vars[${id}] => '${xrf.URI.vars[ v.string ]()}'`)
xrf.scene.traverse( (n) => { xrf.scene.traverse( (n) => {
// re-expand src-values which use the updated URI Template var // re-expand src-values which use the updated URI Template var
if( n.userData && n.userData.src && n.userData.srcTemplate && n.userData.srcTemplate.match(`{${id}}`) ){ if( n.userData && n.userData.src && n.userData.srcTemplate && n.userData.srcTemplate.match(`{${id}}`) ){

View file

@ -1,8 +1,9 @@
/* /*
* v0.5.1 generated at Wed Jun 26 11:16:30 AM UTC 2024 * v0.5.1 generated at Tue Jul 9 04:28:50 PM UTC 2024
* https://xrfragment.org * https://xrfragment.org
* SPDX-License-Identifier: MPL-2.0 * SPDX-License-Identifier: MPL-2.0
*/ */
// Generated by Haxe 4.3.3
var $hx_exports = typeof exports != "undefined" ? exports : typeof window != "undefined" ? window : typeof self != "undefined" ? self : this; var $hx_exports = typeof exports != "undefined" ? exports : typeof window != "undefined" ? window : typeof self != "undefined" ? self : this;
(function ($global) { "use strict"; (function ($global) { "use strict";
$hx_exports["xrfragment"] = $hx_exports["xrfragment"] || {}; $hx_exports["xrfragment"] = $hx_exports["xrfragment"] || {};
@ -158,24 +159,11 @@ Std.string = function(s) {
return js_Boot.__string_rec(s,""); return js_Boot.__string_rec(s,"");
}; };
Std.parseInt = function(x) { Std.parseInt = function(x) {
if(x != null) { var v = parseInt(x);
var _g = 0; if(isNaN(v)) {
var _g1 = x.length; return null;
while(_g < _g1) {
var i = _g++;
var c = x.charCodeAt(i);
if(c <= 8 || c >= 14 && c != 32 && c != 45) {
var nc = x.charCodeAt(i + 1);
var v = parseInt(x,nc == 120 || nc == 88 ? 16 : 10);
if(isNaN(v)) {
return null;
} else {
return v;
}
}
}
} }
return null; return v;
}; };
var StringBuf = function() { var StringBuf = function() {
this.b = ""; this.b = "";
@ -471,10 +459,10 @@ haxe_Template.prototype = {
var _g_offset = 0; var _g_offset = 0;
var _g_s = data; var _g_s = data;
while(_g_offset < _g_s.length) { while(_g_offset < _g_s.length) {
var _g1_key = _g_offset; var _g_key = _g_offset;
var _g1_value = _g_s.charCodeAt(_g_offset++); var _g_value = _g_s.charCodeAt(_g_offset++);
var i = _g1_key; var i = _g_key;
var c = _g1_value; var c = _g_value;
if(c != 32) { if(c != 32) {
l.add({ p : HxOverrides.substr(data,i,null), s : true}); l.add({ p : HxOverrides.substr(data,i,null), s : true});
break; break;
@ -1384,6 +1372,8 @@ xrfragment_URI.toAbsolute = function(url,newUrl) {
} }
if(newURI.directory != null) { if(newURI.directory != null) {
if(newUrl.charAt(0) != "/" && newUrl.indexOf("://") == -1) { if(newUrl.charAt(0) != "/" && newUrl.indexOf("://") == -1) {
var stripRelative_r = new RegExp("\\./.*","".split("u").join(""));
directory = directory.replace(stripRelative_r,"");
directory += newURI.directory; directory += newURI.directory;
} else { } else {
directory = newURI.directory; directory = newURI.directory;
@ -1668,6 +1658,7 @@ xrf.emit = function(eventName, data){
console.groupCollapsed(label) console.groupCollapsed(label)
console.info(data) console.info(data)
console.groupEnd(label) console.groupEnd(label)
if( eventName == 'reset' ) debugger
if( xrf.debug > 2 ) debugger if( xrf.debug > 2 ) debugger
} }
return xrf.emit.promise(eventName,data) return xrf.emit.promise(eventName,data)
@ -1845,12 +1836,13 @@ pub.fragment = (k, opts ) => { // evaluate one fragment
if( !opts.skipXRWG && isPVorMediaFrag ) pub.XRWG(k,opts) if( !opts.skipXRWG && isPVorMediaFrag ) pub.XRWG(k,opts)
// call native function (xrf/env.js e.g.), or pass it to user decorator // call native function (xrf/env.js e.g.), or pass it to user decorator
xrf.emit(k,opts) if( xrf.frag[k] ){
.then( () => { xrf.emit(k,opts)
let func = xrf.frag[k] || function(){} .then( () => {
if( typeof xrf[k] == 'function' ) xrf[k]( func, frag, opts) let func = xrf.frag[k] || function(){}
else func( frag, opts) func( frag, opts)
}) })
}
} }
pub.XRWG = (word,opts) => { pub.XRWG = (word,opts) => {
@ -2024,14 +2016,15 @@ xrf.hasNoMaterial = (mesh) => {
const hasMaterialName = mesh.material && mesh.material.name.length > 0 const hasMaterialName = mesh.material && mesh.material.name.length > 0
return mesh.geometry && !hasMaterialName && !hasTexture return mesh.geometry && !hasMaterialName && !hasTexture
} }
xrf.navigator = { xrf.navigator = {
URI:{ URI: xrf.URI.parse(document.location.href)
scheme: document.location.protocol.replace(/:$/,''), // scheme: document.location.protocol.replace(/:$/,''),
directory: document.location.pathname, // directory: document.location.pathname,
host: document.location.hostname, // host: document.location.hostname,
port: document.location.port, // port: document.location.port,
file: 'index.glb' // file: 'index.glb'
} // }
} }
xrf.navigator.to = (url,flags,loader,data) => { xrf.navigator.to = (url,flags,loader,data) => {
@ -2041,6 +2034,8 @@ xrf.navigator.to = (url,flags,loader,data) => {
URI.hash = xrf.navigator.reactifyHash(URI.hash) // automatically reflect hash-changes to navigator.to(...) URI.hash = xrf.navigator.reactifyHash(URI.hash) // automatically reflect hash-changes to navigator.to(...)
// decorate with extra state // decorate with extra state
URI.fileChange = URI.file && URI.URN + URI.file != xrf.navigator.URI.URN + xrf.navigator.URI.file URI.fileChange = URI.file && URI.URN + URI.file != xrf.navigator.URI.URN + xrf.navigator.URI.file
console.log( URI.URN + URI.file )
console.log( xrf.navigator.URI.URN + xrf.navigator.URI.file )
URI.external = URI.file && URI.URN != document.location.origin + document.location.pathname URI.external = URI.file && URI.URN != document.location.origin + document.location.pathname
URI.hasPos = URI.hash.pos ? true : false URI.hasPos = URI.hash.pos ? true : false
URI.duplicatePos = URI.source == xrf.navigator.URI.source && URI.hasPos URI.duplicatePos = URI.source == xrf.navigator.URI.source && URI.hasPos
@ -2068,8 +2063,7 @@ xrf.navigator.to = (url,flags,loader,data) => {
loader = loader || new Loader().setPath( URI.URN ) loader = loader || new Loader().setPath( URI.URN )
} }
if( URI.duplicatePos || (!Object.values(URI.XRF).length && !URI.file && !URI.fileExt) ){
if( URI.duplicatePos || (!URI.fragment && !URI.file && !URI.fileExt) ){
return resolve(xrf.model) // nothing we can do here return resolve(xrf.model) // nothing we can do here
} }
if( xrf.model && !URI.fileChange && URI.hashChange && !URI.hasPos ){ if( xrf.model && !URI.fileChange && URI.hashChange && !URI.hasPos ){
@ -2173,14 +2167,14 @@ xrf.navigator.setupNavigateFallbacks = () => {
xrf.navigator.updateHash = (hash,opts) => { xrf.navigator.updateHash = (hash,opts) => {
if( hash.replace(/^#/,'') == document.location.hash.substr(1) || hash.match(/\|/) ) return // skip unnecesary pushState triggers if( hash.replace(/^#/,'') == document.location.hash.substr(1) || hash.match(/\|/) ) return // skip unnecesary pushState triggers
console.log(`URI: ${document.location.search.substr(1)}#${hash}`) console.log(`URI: ${document.location.search.substr(1)}#${hash}`)
xrf.navigator.updateHash.active = true // important to prevent recursion xrf.navigator.updateHash.active = false // important to prevent recursion
document.location.hash = hash document.location.hash = hash
xrf.navigator.updateHash.active = false xrf.navigator.updateHash.active = true
} }
xrf.navigator.pushState = (file,hash) => { xrf.navigator.pushState = (file,hash) => {
if( file == document.location.search.substr(1) ) return // page is in its default state if( file == document.location.search.substr(1) ) return // page is in its default state
window.history.pushState({},`${file}#${hash}`, document.location.pathname + `?${file}#${hash}` ) window.history.pushState({}, '', document.location.pathname + `?${xrf.navigator.URI.source.replace(/#.*/,'')}#${hash}` )
xrf.emit('pushState', {file, hash} ) xrf.emit('pushState', {file, hash} )
} }
@ -2243,7 +2237,8 @@ xrf.frag.href = function(v, opts){
if( !mesh.material || !mesh.material.visible ) return // ignore invisible nodes if( !mesh.material || !mesh.material.visible ) return // ignore invisible nodes
// update our values to the latest value (might be edited) // update our values to the latest value (might be edited)
xrf.Parser.parse( "href", mesh.userData.href, frag ) let URI = xrf.URI.template( mesh.userData.href, xrf.URI.vars.__object )
xrf.Parser.parse( "href", URI, frag )
const v = frag.href const v = frag.href
// bubble up! // bubble up!
@ -2361,8 +2356,9 @@ xrf.addEventListener('audioInited', function(opts){
*/ */
// this is called by navigator.js rather than by a URL e.g. // this is called by navigator.js rather than by a URL e.g.
xrf.frag.defaultPredefinedViews = (opts) => { xrf.frag['#'] = xrf.frag.defaultPredefinedViews = (opts) => {
let {scene,model} = opts; let {scene,model} = opts;
if( !scene ) return
let defaultFragment; let defaultFragment;
scene.traverse( (n) => { scene.traverse( (n) => {
if( n.userData && n.userData['#'] ){ if( n.userData && n.userData['#'] ){
@ -2715,10 +2711,17 @@ xrf.frag.t.default = {
xrf.addEventListener('parseModel', (opts) => { xrf.addEventListener('parseModel', (opts) => {
let {model} = opts let {model} = opts
let mixer = model.mixer = new xrf.THREE.AnimationMixer(model.scene) let mixer = model.mixer = new xrf.THREE.AnimationMixer(model.scene)
mixer.model = model mixer.model = model
mixer.loop = {timeStart:0,timeStop:0,speed:1.0} mixer.loop = {timeStart:0,timeStop:0,speed:1.0}
mixer.i = xrf.mixers.length mixer.i = xrf.mixers.length
mixer.actions = [] mixer.actions = []
// calculate total duration/frame based on longest animation
mixer.duration = 0
if( model.animations.length ){
model.animations.map( (a) => mixer.duration = ( a.duration > mixer.duration ) ? a.duration : mixer.duration )
}
model.animations.map( (anim) => { model.animations.map( (anim) => {
anim.optimize() anim.optimize()
@ -2739,7 +2742,7 @@ xrf.addEventListener('parseModel', (opts) => {
mixer.updateLoop = (t) => { mixer.updateLoop = (t) => {
if( t ){ if( t ){
mixer.loop.timeStart = t.x != undefined ? t.x : mixer.loop.timeStart mixer.loop.timeStart = t.x != undefined ? t.x : mixer.loop.timeStart
mixer.loop.timeStop = t.y != undefined ? t.y : mixer.duration mixer.loop.timeStop = t.y != undefined ? t.y : mixer.loop.timeStop
} }
mixer.actions.map( (action) => { mixer.actions.map( (action) => {
if( mixer.loop.timeStart != undefined ){ if( mixer.loop.timeStart != undefined ){
@ -2762,7 +2765,6 @@ xrf.addEventListener('parseModel', (opts) => {
mixer.update = function(time){ mixer.update = function(time){
mixer.time = Math.abs(mixer.time) mixer.time = Math.abs(mixer.time)
if( time == 0 ) return update.call(this,time) if( time == 0 ) return update.call(this,time)
// loop jump // loop jump
if( mixer.loop.timeStop > 0 && mixer.time > mixer.loop.timeStop ){ if( mixer.loop.timeStop > 0 && mixer.time > mixer.loop.timeStop ){
if( mixer.loop.enabled ){ if( mixer.loop.enabled ){
@ -2774,12 +2776,6 @@ xrf.addEventListener('parseModel', (opts) => {
mixer.update.patched = true mixer.update.patched = true
} }
// calculate total duration/frame based on longest animation
mixer.duration = 0
if( model.animations.length ){
model.animations.map( (a) => mixer.duration = ( a.duration > mixer.duration ) ? a.duration : mixer.duration )
}
xrf.mixers.push(mixer) xrf.mixers.push(mixer)
}) })
@ -3401,8 +3397,8 @@ xrf.addEventListener('parseModel', (opts) => {
if( n.userData ){ if( n.userData ){
for( let i in n.userData ){ for( let i in n.userData ){
if( i[0] == '#' || i.match(/^(href|tag)$/) ) continue // ignore XR Fragment aliases //if( i[0] == '#' || i.match(/^(href|tag)$/) ) continue // ignore XR Fragment aliases
if( i == 'src' ){ if( i.match(/^(src|href|tag)/) ){
// lets declare empty variables found in src-values ('https://foo.com/video.mp4#{somevar}') e.g. // lets declare empty variables found in src-values ('https://foo.com/video.mp4#{somevar}') e.g.
if( n.userData[i].match(variables) ){ if( n.userData[i].match(variables) ){
let vars = [].concat( n.userData[i].match(variables) ) let vars = [].concat( n.userData[i].match(variables) )
@ -3431,10 +3427,11 @@ xrf.addEventListener('dynamicKeyValue', (opts) => {
if( !xrf.URI.vars[ v.string ] ) return console.error(`'${v.string}' metadata-key not found in scene`) if( !xrf.URI.vars[ v.string ] ) return console.error(`'${v.string}' metadata-key not found in scene`)
//if( xrf.URI.vars[ id ] && !match.length ) return console.error(`'${id}' object/tag/metadata-key not found in scene`) //if( xrf.URI.vars[ id ] && !match.length ) return console.error(`'${id}' object/tag/metadata-key not found in scene`)
if( xrf.debug ) console.log(`URI.vars[${id}]='${v.string}'`) if( xrf.debug ) console.log(`URI.vars[${id}] => '${v.string}'`)
if( xrf.URI.vars[id] ){ if( xrf.URI.vars[id] ){
xrf.URI.vars[ id ] = xrf.URI.vars[ v.string ] // update var xrf.URI.vars[ id ] = xrf.URI.vars[ v.string ] // update var
if( xrf.debug ) console.log(`URI.vars[${id}] => '${xrf.URI.vars[ v.string ]()}'`)
xrf.scene.traverse( (n) => { xrf.scene.traverse( (n) => {
// re-expand src-values which use the updated URI Template var // re-expand src-values which use the updated URI Template var
if( n.userData && n.userData.src && n.userData.srcTemplate && n.userData.srcTemplate.match(`{${id}}`) ){ if( n.userData && n.userData.src && n.userData.srcTemplate && n.userData.srcTemplate.match(`{${id}}`) ){

View file

@ -10,7 +10,9 @@
<script src="./../../../dist/xrfragment.aframe.js"></script> <script src="./../../../dist/xrfragment.aframe.js"></script>
<!-- important: allow touchevents in AR --> <!-- important: allow touchevents in AR -->
<style type="text/css"> canvas.a-dom-overlay:not(.a-no-style) { padding: 0; pointer-events: auto; }</style> <style type="text/css">
canvas.a-dom-overlay:not(.a-no-style) { padding: 0; pointer-events: auto; }
</style>
</head> </head>
<body> <body>

BIN
example/assets/ARwindow.glb Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -55,6 +55,14 @@ window.AFRAME.registerComponent('xrf', {
if( VRbutton ) VRbutton.addEventListener('click', () => AFRAME.XRF.hashbus.pub( '#VR' ) ) if( VRbutton ) VRbutton.addEventListener('click', () => AFRAME.XRF.hashbus.pub( '#VR' ) )
}) })
// not part of the spec, but convenient to only show AR button when negative VR-tag was defined in default fragment ('#' in rootscene file)
xrf.addEventListener('#', function(e){
if( e.frag['#'].string.match(/-VR/) ){
aScene.removeAttribute('xr-mode-ui')
aScene.setAttribute('xr-mode-ui',"XRMode: ar")
}
})
let repositionUser = (scale) => () => { let repositionUser = (scale) => () => {
// sometimes AFRAME resets the user position to 0,0,0 when entering VR (not sure why) // sometimes AFRAME resets the user position to 0,0,0 when entering VR (not sure why)
setTimeout( () => { setTimeout( () => {
@ -67,6 +75,7 @@ window.AFRAME.registerComponent('xrf', {
aScene.addEventListener('enter-ar', repositionUser(2) ) aScene.addEventListener('enter-ar', repositionUser(2) )
xrf.addEventListener('navigateLoaded', (opts) => { xrf.addEventListener('navigateLoaded', (opts) => {
setTimeout( () => AFRAME.fade.out(),500) setTimeout( () => AFRAME.fade.out(),500)
let isLocal = opts.url.match(/^#/) let isLocal = opts.url.match(/^#/)
if( isLocal ) return if( isLocal ) return

View file

@ -114,7 +114,7 @@ window.accessibility = (opts) => new Proxy({
this.helper.selected = n.uuid this.helper.selected = n.uuid
xrf.scene.add(this.helper) xrf.scene.add(this.helper)
notify(`${n.userData['aria-description']||''}` + (n.userData.href ? `<br><b>name:</b> ${n.name}<br><b>link:</b> ${n.userData['href']}` :'') ) notify(`${n.userData['aria-description']||''}` + (n.userData.href ? `<br><b>name:</b> ${n.name}<br><b>href:</b> ${n.userData['href']}` :'') )
} }
if( e.key == 'Enter' && objects[cache.current].userData.href ){ if( e.key == 'Enter' && objects[cache.current].userData.href ){

View file

@ -1,11 +1,12 @@
xrf.navigator = { xrf.navigator = {
URI:{ URI: xrf.URI.parse(document.location.href)
scheme: document.location.protocol.replace(/:$/,''), // scheme: document.location.protocol.replace(/:$/,''),
directory: document.location.pathname, // directory: document.location.pathname,
host: document.location.hostname, // host: document.location.hostname,
port: document.location.port, // port: document.location.port,
file: 'index.glb' // file: 'index.glb'
} // }
} }
xrf.navigator.to = (url,flags,loader,data) => { xrf.navigator.to = (url,flags,loader,data) => {
@ -15,6 +16,8 @@ xrf.navigator.to = (url,flags,loader,data) => {
URI.hash = xrf.navigator.reactifyHash(URI.hash) // automatically reflect hash-changes to navigator.to(...) URI.hash = xrf.navigator.reactifyHash(URI.hash) // automatically reflect hash-changes to navigator.to(...)
// decorate with extra state // decorate with extra state
URI.fileChange = URI.file && URI.URN + URI.file != xrf.navigator.URI.URN + xrf.navigator.URI.file URI.fileChange = URI.file && URI.URN + URI.file != xrf.navigator.URI.URN + xrf.navigator.URI.file
console.log( URI.URN + URI.file )
console.log( xrf.navigator.URI.URN + xrf.navigator.URI.file )
URI.external = URI.file && URI.URN != document.location.origin + document.location.pathname URI.external = URI.file && URI.URN != document.location.origin + document.location.pathname
URI.hasPos = URI.hash.pos ? true : false URI.hasPos = URI.hash.pos ? true : false
URI.duplicatePos = URI.source == xrf.navigator.URI.source && URI.hasPos URI.duplicatePos = URI.source == xrf.navigator.URI.source && URI.hasPos
@ -146,14 +149,14 @@ xrf.navigator.setupNavigateFallbacks = () => {
xrf.navigator.updateHash = (hash,opts) => { xrf.navigator.updateHash = (hash,opts) => {
if( hash.replace(/^#/,'') == document.location.hash.substr(1) || hash.match(/\|/) ) return // skip unnecesary pushState triggers if( hash.replace(/^#/,'') == document.location.hash.substr(1) || hash.match(/\|/) ) return // skip unnecesary pushState triggers
console.log(`URI: ${document.location.search.substr(1)}#${hash}`) console.log(`URI: ${document.location.search.substr(1)}#${hash}`)
xrf.navigator.updateHash.active = true // important to prevent recursion xrf.navigator.updateHash.active = false // important to prevent recursion
document.location.hash = hash document.location.hash = hash
xrf.navigator.updateHash.active = false xrf.navigator.updateHash.active = true
} }
xrf.navigator.pushState = (file,hash) => { xrf.navigator.pushState = (file,hash) => {
if( file == document.location.search.substr(1) ) return // page is in its default state if( file == document.location.search.substr(1) ) return // page is in its default state
window.history.pushState({},`${file}#${hash}`, document.location.pathname + `?${xrf.navigator.URI.source}#${hash}` ) window.history.pushState({}, '', document.location.pathname + `?${xrf.navigator.URI.source.replace(/#.*/,'')}#${hash}` )
xrf.emit('pushState', {file, hash} ) xrf.emit('pushState', {file, hash} )
} }

View file

@ -1,7 +1,8 @@
// this is called by navigator.js rather than by a URL e.g. // this is called by navigator.js rather than by a URL e.g.
xrf.frag.defaultPredefinedViews = (opts) => { xrf.frag['#'] = xrf.frag.defaultPredefinedViews = (opts) => {
let {scene,model} = opts; let {scene,model} = opts;
if( !scene ) return
let defaultFragment; let defaultFragment;
scene.traverse( (n) => { scene.traverse( (n) => {
if( n.userData && n.userData['#'] ){ if( n.userData && n.userData['#'] ){

View file

@ -17,5 +17,7 @@
{"fn":"url","data":"/bar/flop#mycustom=foo", "expect":{ "fn":"testURLBrowse", "input":"host","out":"foo.com"},"label":"test URLBrowser (maintain host)"}, {"fn":"url","data":"/bar/flop#mycustom=foo", "expect":{ "fn":"testURLBrowse", "input":"host","out":"foo.com"},"label":"test URLBrowser (maintain host)"},
{"fn":"url","data":"c/d?foo=1#mycustom=foo", "expect":{ "fn":"testURLBrowse", "input":"path","out":"/bar/flop/c/d"},"label":"test URLBrowser (append path+query)"}, {"fn":"url","data":"c/d?foo=1#mycustom=foo", "expect":{ "fn":"testURLBrowse", "input":"path","out":"/bar/flop/c/d"},"label":"test URLBrowser (append path+query)"},
{"fn":"url","data":"a/b#foo=bar", "expect":{ "fn":"testURL", "input":"hash.foo","out":"bar"},"label":"test URL hash #mycustom == foo"}, {"fn":"url","data":"a/b#foo=bar", "expect":{ "fn":"testURL", "input":"hash.foo","out":"bar"},"label":"test URL hash #mycustom == foo"},
{"fn":"url","data":"a/b?index.glb#foo=bar://foo/flop.gltf", "expect":{ "fn":"testURL", "input":"directory","out":"a/b"},"label":"test URLhash with protocol"} {"fn":"url","data":"./../../xyz", "expect":{ "fn":"testURLBrowse", "input":"path","out":"/bar/flop/c/d/./../../xyz"},"label":"test URL relative path"},
{"fn":"url","data":"./../../xyz", "expect":{ "fn":"testURLBrowse", "input":"path","out":"/bar/flop/c/d/./../../xyz"},"label":"test URL relative path"},
{"fn":"url","data":"a/b?index.glb#foo=bar://foo/flop.gltf", "expect":{ "fn":"testURL", "input":"directory","out":"/a/b"},"label":"test URLhash with protocol"}
] ]

View file

@ -434,6 +434,8 @@ class URI {
if (newURI.directory != null) if (newURI.directory != null)
{ {
if( newUrl.charAt(0) != '/' && newUrl.indexOf("://") == -1 ){ if( newUrl.charAt(0) != '/' && newUrl.indexOf("://") == -1 ){
var stripRelative : EReg = ~/\.\/.*/;
directory = stripRelative.replace( directory, '');
directory += newURI.directory; directory += newURI.directory;
}else{ }else{
directory = newURI.directory; directory = newURI.directory;
@ -448,7 +450,7 @@ class URI {
}else{ }else{
resultURI.file = url.file; resultURI.file = url.file;
} }
resultURI.path = resultURI.directory + resultURI.file; resultURI.path = resultURI.directory + resultURI.file;
if (newURI.query != null) if (newURI.query != null)