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
* 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;
(function ($global) { "use strict";
$hx_exports["xrfragment"] = $hx_exports["xrfragment"] || {};
@ -158,24 +159,11 @@ Std.string = function(s) {
return js_Boot.__string_rec(s,"");
};
Std.parseInt = function(x) {
if(x != null) {
var _g = 0;
var _g1 = x.length;
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;
}
}
}
var v = parseInt(x);
if(isNaN(v)) {
return null;
}
return null;
return v;
};
var StringBuf = function() {
this.b = "";
@ -471,10 +459,10 @@ haxe_Template.prototype = {
var _g_offset = 0;
var _g_s = data;
while(_g_offset < _g_s.length) {
var _g1_key = _g_offset;
var _g1_value = _g_s.charCodeAt(_g_offset++);
var i = _g1_key;
var c = _g1_value;
var _g_key = _g_offset;
var _g_value = _g_s.charCodeAt(_g_offset++);
var i = _g_key;
var c = _g_value;
if(c != 32) {
l.add({ p : HxOverrides.substr(data,i,null), s : true});
break;
@ -1384,6 +1372,8 @@ xrfragment_URI.toAbsolute = function(url,newUrl) {
}
if(newURI.directory != null) {
if(newUrl.charAt(0) != "/" && newUrl.indexOf("://") == -1) {
var stripRelative_r = new RegExp("\\./.*","".split("u").join(""));
directory = directory.replace(stripRelative_r,"");
directory += newURI.directory;
} else {
directory = newURI.directory;
@ -1668,6 +1658,7 @@ xrf.emit = function(eventName, data){
console.groupCollapsed(label)
console.info(data)
console.groupEnd(label)
if( eventName == 'reset' ) debugger
if( xrf.debug > 2 ) debugger
}
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)
// call native function (xrf/env.js e.g.), or pass it to user decorator
xrf.emit(k,opts)
.then( () => {
let func = xrf.frag[k] || function(){}
if( typeof xrf[k] == 'function' ) xrf[k]( func, frag, opts)
else func( frag, opts)
})
if( xrf.frag[k] ){
xrf.emit(k,opts)
.then( () => {
let func = xrf.frag[k] || function(){}
func( frag, opts)
})
}
}
pub.XRWG = (word,opts) => {
@ -2024,14 +2016,15 @@ xrf.hasNoMaterial = (mesh) => {
const hasMaterialName = mesh.material && mesh.material.name.length > 0
return mesh.geometry && !hasMaterialName && !hasTexture
}
xrf.navigator = {
URI:{
scheme: document.location.protocol.replace(/:$/,''),
directory: document.location.pathname,
host: document.location.hostname,
port: document.location.port,
file: 'index.glb'
}
URI: xrf.URI.parse(document.location.href)
// scheme: document.location.protocol.replace(/:$/,''),
// directory: document.location.pathname,
// host: document.location.hostname,
// port: document.location.port,
// file: 'index.glb'
// }
}
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(...)
// decorate with extra state
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.hasPos = URI.hash.pos ? true : false
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 )
}
if( URI.duplicatePos || (!URI.fragment && !URI.file && !URI.fileExt) ){
if( URI.duplicatePos || (!Object.values(URI.XRF).length && !URI.file && !URI.fileExt) ){
return resolve(xrf.model) // nothing we can do here
}
if( xrf.model && !URI.fileChange && URI.hashChange && !URI.hasPos ){
@ -2173,14 +2167,14 @@ xrf.navigator.setupNavigateFallbacks = () => {
xrf.navigator.updateHash = (hash,opts) => {
if( hash.replace(/^#/,'') == document.location.hash.substr(1) || hash.match(/\|/) ) return // skip unnecesary pushState triggers
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
xrf.navigator.updateHash.active = false
xrf.navigator.updateHash.active = true
}
xrf.navigator.pushState = (file,hash) => {
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} )
}
@ -2243,7 +2237,8 @@ xrf.frag.href = function(v, opts){
if( !mesh.material || !mesh.material.visible ) return // ignore invisible nodes
// 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
// bubble up!
@ -2361,8 +2356,9 @@ xrf.addEventListener('audioInited', function(opts){
*/
// 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;
if( !scene ) return
let defaultFragment;
scene.traverse( (n) => {
if( n.userData && n.userData['#'] ){
@ -2715,10 +2711,17 @@ xrf.frag.t.default = {
xrf.addEventListener('parseModel', (opts) => {
let {model} = opts
let mixer = model.mixer = new xrf.THREE.AnimationMixer(model.scene)
mixer.model = model
mixer.loop = {timeStart:0,timeStop:0,speed:1.0}
mixer.i = xrf.mixers.length
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) => {
anim.optimize()
@ -2739,7 +2742,7 @@ xrf.addEventListener('parseModel', (opts) => {
mixer.updateLoop = (t) => {
if( t ){
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) => {
if( mixer.loop.timeStart != undefined ){
@ -2762,7 +2765,6 @@ xrf.addEventListener('parseModel', (opts) => {
mixer.update = function(time){
mixer.time = Math.abs(mixer.time)
if( time == 0 ) return update.call(this,time)
// loop jump
if( mixer.loop.timeStop > 0 && mixer.time > mixer.loop.timeStop ){
if( mixer.loop.enabled ){
@ -2774,12 +2776,6 @@ xrf.addEventListener('parseModel', (opts) => {
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)
})
@ -3401,8 +3397,8 @@ xrf.addEventListener('parseModel', (opts) => {
if( n.userData ){
for( let i in n.userData ){
if( i[0] == '#' || i.match(/^(href|tag)$/) ) continue // ignore XR Fragment aliases
if( i == 'src' ){
//if( i[0] == '#' || i.match(/^(href|tag)$/) ) continue // ignore XR Fragment aliases
if( i.match(/^(src|href|tag)/) ){
// lets declare empty variables found in src-values ('https://foo.com/video.mp4#{somevar}') e.g.
if( 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[ 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] ){
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) => {
// 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}}`) ){
@ -4178,6 +4175,14 @@ window.AFRAME.registerComponent('xrf', {
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) => () => {
// sometimes AFRAME resets the user position to 0,0,0 when entering VR (not sure why)
setTimeout( () => {
@ -4190,6 +4195,7 @@ window.AFRAME.registerComponent('xrf', {
aScene.addEventListener('enter-ar', repositionUser(2) )
xrf.addEventListener('navigateLoaded', (opts) => {
setTimeout( () => AFRAME.fade.out(),500)
let isLocal = opts.url.match(/^#/)
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;
(function ($global) { "use strict";
$hx_exports["xrfragment"] = $hx_exports["xrfragment"] || {};
@ -153,24 +154,11 @@ Std.string = function(s) {
return js_Boot.__string_rec(s,"");
};
Std.parseInt = function(x) {
if(x != null) {
var _g = 0;
var _g1 = x.length;
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;
}
}
}
var v = parseInt(x);
if(isNaN(v)) {
return null;
}
return null;
return v;
};
var StringBuf = function() {
this.b = "";
@ -466,10 +454,10 @@ haxe_Template.prototype = {
var _g_offset = 0;
var _g_s = data;
while(_g_offset < _g_s.length) {
var _g1_key = _g_offset;
var _g1_value = _g_s.charCodeAt(_g_offset++);
var i = _g1_key;
var c = _g1_value;
var _g_key = _g_offset;
var _g_value = _g_s.charCodeAt(_g_offset++);
var i = _g_key;
var c = _g_value;
if(c != 32) {
l.add({ p : HxOverrides.substr(data,i,null), s : true});
break;
@ -1379,6 +1367,8 @@ xrfragment_URI.toAbsolute = function(url,newUrl) {
}
if(newURI.directory != null) {
if(newUrl.charAt(0) != "/" && newUrl.indexOf("://") == -1) {
var stripRelative_r = new RegExp("\\./.*","".split("u").join(""));
directory = directory.replace(stripRelative_r,"");
directory += newURI.directory;
} else {
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 math as python_lib_Math
@ -305,67 +307,48 @@ class Std:
def parseInt(x):
if (x is None):
return None
try:
return int(x)
except BaseException as _g:
None
base = 10
_hx_len = len(x)
foundCount = 0
sign = 0
firstDigitIndex = 0
lastDigitIndex = -1
previous = 0
_g = 0
_g1 = _hx_len
while (_g < _g1):
i = _g
_g = (_g + 1)
c = (-1 if ((i >= len(x))) else ord(x[i]))
if (((c > 8) and ((c < 14))) or ((c == 32))):
if (foundCount > 0):
return None
continue
else:
c1 = c
if (c1 == 43):
if (foundCount == 0):
sign = 1
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 (c1 == 45):
if (foundCount == 0):
sign = -1
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 (c1 == 48):
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
_hx_len = len(x)
index = 0
while (index < _hx_len):
if (not (x[index] in " \n\r\t\x0B\x0C")):
break
index = (index + 1)
isNegative = None
if (index < _hx_len):
sign = x[index]
if ((sign == "-") or ((sign == "+"))):
index = (index + 1)
isNegative = (sign == "-")
else:
isNegative = False
isHexadecimal = None
if ((index + 1) < _hx_len):
cur = x[index]
next = x[(index + 1)]
isHexadecimal = ((cur == "0") and (((next == "x") or ((next == "X")))))
else:
isHexadecimal = False
if isHexadecimal:
index = (index + 2)
cur = index
if isHexadecimal:
while (cur < _hx_len):
if (not (x[cur] in "0123456789abcdefABCDEF")):
break
cur = (cur + 1)
else:
while (cur < _hx_len):
if (not (x[cur] in "0123456789")):
break
cur = (cur + 1)
firstInvalidIndex = cur
if (index == firstInvalidIndex):
return None
result = int(HxString.substring(x,index,firstInvalidIndex),(16 if isHexadecimal else 10))
if isNegative:
return -result
else:
return result
@staticmethod
def shortenPossibleNumber(x):
@ -860,13 +843,13 @@ class haxe_Template:
_g_offset = 0
_g_s = data
while (_g_offset < len(_g_s)):
_g1_key = _g_offset
_g_key = _g_offset
s = _g_s
index = _g_offset
_g_offset = (_g_offset + 1)
_g1_value = (-1 if ((index >= len(s))) else ord(s[index]))
i = _g1_key
c = _g1_value
_g_value = (-1 if ((index >= len(s))) else ord(s[index]))
i = _g_key
c = _g_value
if (c != 32):
l.add(_hx_AnonObject({'p': HxString.substr(data,i,None), 's': True}))
break
@ -1169,7 +1152,7 @@ class haxe_ValueException(haxe_Exception):
def __init__(self,value,previous = None,native = 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
def unwrap(self):
@ -1494,10 +1477,7 @@ class python_Boot:
return python_internal_MethodClosure(o,HxString.charCodeAt)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
elif (_hx_local_0 == 11):
if (field1 == "lastIndexOf"):
return python_internal_MethodClosure(o,HxString.lastIndexOf)
@ -1507,46 +1487,31 @@ class python_Boot:
return python_internal_MethodClosure(o,HxString.toUpperCase)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
elif (_hx_local_0 == 9):
if (field1 == "substring"):
return python_internal_MethodClosure(o,HxString.substring)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
elif (_hx_local_0 == 5):
if (field1 == "split"):
return python_internal_MethodClosure(o,HxString.split)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
elif (_hx_local_0 == 7):
if (field1 == "indexOf"):
return python_internal_MethodClosure(o,HxString.indexOf)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
elif (_hx_local_0 == 8):
if (field1 == "toString"):
return python_internal_MethodClosure(o,HxString.toString)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
elif (_hx_local_0 == 6):
if (field1 == "charAt"):
return python_internal_MethodClosure(o,HxString.charAt)
@ -1556,16 +1521,10 @@ class python_Boot:
return python_internal_MethodClosure(o,HxString.substr)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
elif isinstance(o,list):
field1 = field
_hx_local_1 = len(field1)
@ -1574,10 +1533,7 @@ class python_Boot:
return python_internal_MethodClosure(o,python_internal_ArrayImpl.lastIndexOf)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
elif (_hx_local_1 == 4):
if (field1 == "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)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
elif (_hx_local_1 == 5):
if (field1 == "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)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
elif (_hx_local_1 == 7):
if (field1 == "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)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
elif (_hx_local_1 == 3):
if (field1 == "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)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
elif (_hx_local_1 == 8):
if (field1 == "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)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
elif (_hx_local_1 == 16):
if (field1 == "keyValueIterator"):
return python_internal_MethodClosure(o,python_internal_ArrayImpl.keyValueIterator)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
elif (_hx_local_1 == 6):
if (field1 == "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)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
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))
if hasattr(o,field1):
return getattr(o,field1)
else:
return None
return (getattr(o,field1) if (hasattr(o,field1)) else None)
@staticmethod
def getInstanceFields(c):
@ -2574,6 +2503,8 @@ class xrfragment_URI:
else:
tmp = False
if tmp:
stripRelative = EReg("\\./.*","")
directory = stripRelative.replace(directory,"")
directory = (("null" if directory is None else directory) + HxOverrides.stringOrNull(newURI.directory))
else:
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
* 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;
(function ($global) { "use strict";
$hx_exports["xrfragment"] = $hx_exports["xrfragment"] || {};
@ -158,24 +159,11 @@ Std.string = function(s) {
return js_Boot.__string_rec(s,"");
};
Std.parseInt = function(x) {
if(x != null) {
var _g = 0;
var _g1 = x.length;
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;
}
}
}
var v = parseInt(x);
if(isNaN(v)) {
return null;
}
return null;
return v;
};
var StringBuf = function() {
this.b = "";
@ -471,10 +459,10 @@ haxe_Template.prototype = {
var _g_offset = 0;
var _g_s = data;
while(_g_offset < _g_s.length) {
var _g1_key = _g_offset;
var _g1_value = _g_s.charCodeAt(_g_offset++);
var i = _g1_key;
var c = _g1_value;
var _g_key = _g_offset;
var _g_value = _g_s.charCodeAt(_g_offset++);
var i = _g_key;
var c = _g_value;
if(c != 32) {
l.add({ p : HxOverrides.substr(data,i,null), s : true});
break;
@ -1384,6 +1372,8 @@ xrfragment_URI.toAbsolute = function(url,newUrl) {
}
if(newURI.directory != null) {
if(newUrl.charAt(0) != "/" && newUrl.indexOf("://") == -1) {
var stripRelative_r = new RegExp("\\./.*","".split("u").join(""));
directory = directory.replace(stripRelative_r,"");
directory += newURI.directory;
} else {
directory = newURI.directory;
@ -1668,6 +1658,7 @@ xrf.emit = function(eventName, data){
console.groupCollapsed(label)
console.info(data)
console.groupEnd(label)
if( eventName == 'reset' ) debugger
if( xrf.debug > 2 ) debugger
}
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)
// call native function (xrf/env.js e.g.), or pass it to user decorator
xrf.emit(k,opts)
.then( () => {
let func = xrf.frag[k] || function(){}
if( typeof xrf[k] == 'function' ) xrf[k]( func, frag, opts)
else func( frag, opts)
})
if( xrf.frag[k] ){
xrf.emit(k,opts)
.then( () => {
let func = xrf.frag[k] || function(){}
func( frag, opts)
})
}
}
pub.XRWG = (word,opts) => {
@ -2024,14 +2016,15 @@ xrf.hasNoMaterial = (mesh) => {
const hasMaterialName = mesh.material && mesh.material.name.length > 0
return mesh.geometry && !hasMaterialName && !hasTexture
}
xrf.navigator = {
URI:{
scheme: document.location.protocol.replace(/:$/,''),
directory: document.location.pathname,
host: document.location.hostname,
port: document.location.port,
file: 'index.glb'
}
URI: xrf.URI.parse(document.location.href)
// scheme: document.location.protocol.replace(/:$/,''),
// directory: document.location.pathname,
// host: document.location.hostname,
// port: document.location.port,
// file: 'index.glb'
// }
}
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(...)
// decorate with extra state
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.hasPos = URI.hash.pos ? true : false
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 )
}
if( URI.duplicatePos || (!URI.fragment && !URI.file && !URI.fileExt) ){
if( URI.duplicatePos || (!Object.values(URI.XRF).length && !URI.file && !URI.fileExt) ){
return resolve(xrf.model) // nothing we can do here
}
if( xrf.model && !URI.fileChange && URI.hashChange && !URI.hasPos ){
@ -2173,14 +2167,14 @@ xrf.navigator.setupNavigateFallbacks = () => {
xrf.navigator.updateHash = (hash,opts) => {
if( hash.replace(/^#/,'') == document.location.hash.substr(1) || hash.match(/\|/) ) return // skip unnecesary pushState triggers
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
xrf.navigator.updateHash.active = false
xrf.navigator.updateHash.active = true
}
xrf.navigator.pushState = (file,hash) => {
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} )
}
@ -2243,7 +2237,8 @@ xrf.frag.href = function(v, opts){
if( !mesh.material || !mesh.material.visible ) return // ignore invisible nodes
// 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
// bubble up!
@ -2361,8 +2356,9 @@ xrf.addEventListener('audioInited', function(opts){
*/
// 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;
if( !scene ) return
let defaultFragment;
scene.traverse( (n) => {
if( n.userData && n.userData['#'] ){
@ -2715,10 +2711,17 @@ xrf.frag.t.default = {
xrf.addEventListener('parseModel', (opts) => {
let {model} = opts
let mixer = model.mixer = new xrf.THREE.AnimationMixer(model.scene)
mixer.model = model
mixer.loop = {timeStart:0,timeStop:0,speed:1.0}
mixer.i = xrf.mixers.length
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) => {
anim.optimize()
@ -2739,7 +2742,7 @@ xrf.addEventListener('parseModel', (opts) => {
mixer.updateLoop = (t) => {
if( t ){
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) => {
if( mixer.loop.timeStart != undefined ){
@ -2762,7 +2765,6 @@ xrf.addEventListener('parseModel', (opts) => {
mixer.update = function(time){
mixer.time = Math.abs(mixer.time)
if( time == 0 ) return update.call(this,time)
// loop jump
if( mixer.loop.timeStop > 0 && mixer.time > mixer.loop.timeStop ){
if( mixer.loop.enabled ){
@ -2774,12 +2776,6 @@ xrf.addEventListener('parseModel', (opts) => {
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)
})
@ -3401,8 +3397,8 @@ xrf.addEventListener('parseModel', (opts) => {
if( n.userData ){
for( let i in n.userData ){
if( i[0] == '#' || i.match(/^(href|tag)$/) ) continue // ignore XR Fragment aliases
if( i == 'src' ){
//if( i[0] == '#' || i.match(/^(href|tag)$/) ) continue // ignore XR Fragment aliases
if( i.match(/^(src|href|tag)/) ){
// lets declare empty variables found in src-values ('https://foo.com/video.mp4#{somevar}') e.g.
if( 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[ 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] ){
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) => {
// 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}}`) ){

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
* 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;
(function ($global) { "use strict";
$hx_exports["xrfragment"] = $hx_exports["xrfragment"] || {};
@ -158,24 +159,11 @@ Std.string = function(s) {
return js_Boot.__string_rec(s,"");
};
Std.parseInt = function(x) {
if(x != null) {
var _g = 0;
var _g1 = x.length;
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;
}
}
}
var v = parseInt(x);
if(isNaN(v)) {
return null;
}
return null;
return v;
};
var StringBuf = function() {
this.b = "";
@ -471,10 +459,10 @@ haxe_Template.prototype = {
var _g_offset = 0;
var _g_s = data;
while(_g_offset < _g_s.length) {
var _g1_key = _g_offset;
var _g1_value = _g_s.charCodeAt(_g_offset++);
var i = _g1_key;
var c = _g1_value;
var _g_key = _g_offset;
var _g_value = _g_s.charCodeAt(_g_offset++);
var i = _g_key;
var c = _g_value;
if(c != 32) {
l.add({ p : HxOverrides.substr(data,i,null), s : true});
break;
@ -1384,6 +1372,8 @@ xrfragment_URI.toAbsolute = function(url,newUrl) {
}
if(newURI.directory != null) {
if(newUrl.charAt(0) != "/" && newUrl.indexOf("://") == -1) {
var stripRelative_r = new RegExp("\\./.*","".split("u").join(""));
directory = directory.replace(stripRelative_r,"");
directory += newURI.directory;
} else {
directory = newURI.directory;
@ -1668,6 +1658,7 @@ xrf.emit = function(eventName, data){
console.groupCollapsed(label)
console.info(data)
console.groupEnd(label)
if( eventName == 'reset' ) debugger
if( xrf.debug > 2 ) debugger
}
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)
// call native function (xrf/env.js e.g.), or pass it to user decorator
xrf.emit(k,opts)
.then( () => {
let func = xrf.frag[k] || function(){}
if( typeof xrf[k] == 'function' ) xrf[k]( func, frag, opts)
else func( frag, opts)
})
if( xrf.frag[k] ){
xrf.emit(k,opts)
.then( () => {
let func = xrf.frag[k] || function(){}
func( frag, opts)
})
}
}
pub.XRWG = (word,opts) => {
@ -2024,14 +2016,15 @@ xrf.hasNoMaterial = (mesh) => {
const hasMaterialName = mesh.material && mesh.material.name.length > 0
return mesh.geometry && !hasMaterialName && !hasTexture
}
xrf.navigator = {
URI:{
scheme: document.location.protocol.replace(/:$/,''),
directory: document.location.pathname,
host: document.location.hostname,
port: document.location.port,
file: 'index.glb'
}
URI: xrf.URI.parse(document.location.href)
// scheme: document.location.protocol.replace(/:$/,''),
// directory: document.location.pathname,
// host: document.location.hostname,
// port: document.location.port,
// file: 'index.glb'
// }
}
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(...)
// decorate with extra state
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.hasPos = URI.hash.pos ? true : false
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 )
}
if( URI.duplicatePos || (!URI.fragment && !URI.file && !URI.fileExt) ){
if( URI.duplicatePos || (!Object.values(URI.XRF).length && !URI.file && !URI.fileExt) ){
return resolve(xrf.model) // nothing we can do here
}
if( xrf.model && !URI.fileChange && URI.hashChange && !URI.hasPos ){
@ -2173,14 +2167,14 @@ xrf.navigator.setupNavigateFallbacks = () => {
xrf.navigator.updateHash = (hash,opts) => {
if( hash.replace(/^#/,'') == document.location.hash.substr(1) || hash.match(/\|/) ) return // skip unnecesary pushState triggers
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
xrf.navigator.updateHash.active = false
xrf.navigator.updateHash.active = true
}
xrf.navigator.pushState = (file,hash) => {
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} )
}
@ -2243,7 +2237,8 @@ xrf.frag.href = function(v, opts){
if( !mesh.material || !mesh.material.visible ) return // ignore invisible nodes
// 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
// bubble up!
@ -2361,8 +2356,9 @@ xrf.addEventListener('audioInited', function(opts){
*/
// 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;
if( !scene ) return
let defaultFragment;
scene.traverse( (n) => {
if( n.userData && n.userData['#'] ){
@ -2715,10 +2711,17 @@ xrf.frag.t.default = {
xrf.addEventListener('parseModel', (opts) => {
let {model} = opts
let mixer = model.mixer = new xrf.THREE.AnimationMixer(model.scene)
mixer.model = model
mixer.loop = {timeStart:0,timeStop:0,speed:1.0}
mixer.i = xrf.mixers.length
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) => {
anim.optimize()
@ -2739,7 +2742,7 @@ xrf.addEventListener('parseModel', (opts) => {
mixer.updateLoop = (t) => {
if( t ){
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) => {
if( mixer.loop.timeStart != undefined ){
@ -2762,7 +2765,6 @@ xrf.addEventListener('parseModel', (opts) => {
mixer.update = function(time){
mixer.time = Math.abs(mixer.time)
if( time == 0 ) return update.call(this,time)
// loop jump
if( mixer.loop.timeStop > 0 && mixer.time > mixer.loop.timeStop ){
if( mixer.loop.enabled ){
@ -2774,12 +2776,6 @@ xrf.addEventListener('parseModel', (opts) => {
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)
})
@ -3401,8 +3397,8 @@ xrf.addEventListener('parseModel', (opts) => {
if( n.userData ){
for( let i in n.userData ){
if( i[0] == '#' || i.match(/^(href|tag)$/) ) continue // ignore XR Fragment aliases
if( i == 'src' ){
//if( i[0] == '#' || i.match(/^(href|tag)$/) ) continue // ignore XR Fragment aliases
if( i.match(/^(src|href|tag)/) ){
// lets declare empty variables found in src-values ('https://foo.com/video.mp4#{somevar}') e.g.
if( 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[ 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] ){
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) => {
// 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}}`) ){

View File

@ -10,7 +10,9 @@
<script src="./../../../dist/xrfragment.aframe.js"></script>
<!-- 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>
<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' ) )
})
// 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) => () => {
// sometimes AFRAME resets the user position to 0,0,0 when entering VR (not sure why)
setTimeout( () => {
@ -67,6 +75,7 @@ window.AFRAME.registerComponent('xrf', {
aScene.addEventListener('enter-ar', repositionUser(2) )
xrf.addEventListener('navigateLoaded', (opts) => {
setTimeout( () => AFRAME.fade.out(),500)
let isLocal = opts.url.match(/^#/)
if( isLocal ) return

View File

@ -114,7 +114,7 @@ window.accessibility = (opts) => new Proxy({
this.helper.selected = n.uuid
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 ){

View File

@ -1,11 +1,12 @@
xrf.navigator = {
URI:{
scheme: document.location.protocol.replace(/:$/,''),
directory: document.location.pathname,
host: document.location.hostname,
port: document.location.port,
file: 'index.glb'
}
URI: xrf.URI.parse(document.location.href)
// scheme: document.location.protocol.replace(/:$/,''),
// directory: document.location.pathname,
// host: document.location.hostname,
// port: document.location.port,
// file: 'index.glb'
// }
}
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(...)
// decorate with extra state
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.hasPos = URI.hash.pos ? true : false
URI.duplicatePos = URI.source == xrf.navigator.URI.source && URI.hasPos
@ -146,14 +149,14 @@ xrf.navigator.setupNavigateFallbacks = () => {
xrf.navigator.updateHash = (hash,opts) => {
if( hash.replace(/^#/,'') == document.location.hash.substr(1) || hash.match(/\|/) ) return // skip unnecesary pushState triggers
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
xrf.navigator.updateHash.active = false
xrf.navigator.updateHash.active = true
}
xrf.navigator.pushState = (file,hash) => {
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} )
}

View File

@ -1,7 +1,8 @@
// 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;
if( !scene ) return
let defaultFragment;
scene.traverse( (n) => {
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":"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?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( newUrl.charAt(0) != '/' && newUrl.indexOf("://") == -1 ){
var stripRelative : EReg = ~/\.\/.*/;
directory = stripRelative.replace( directory, '');
directory += newURI.directory;
}else{
directory = newURI.directory;
@ -448,7 +450,7 @@ class URI {
}else{
resultURI.file = url.file;
}
resultURI.path = resultURI.directory + resultURI.file;
if (newURI.query != null)