upgraded aframe + wip filters
This commit is contained in:
parent
34f71d0238
commit
bb35044df3
Binary file not shown.
|
@ -7,7 +7,7 @@
|
|||
<link rel="stylesheet" href="./../../assets/css/axist.min.css" />
|
||||
<link type="text/css" rel="stylesheet" href="./../../assets/css/style.css"/>
|
||||
<script async src="./../../assets/js/alpine.min.js" defer></script>
|
||||
<script src="https://aframe.io/releases/1.4.2/aframe.min.js"></script>
|
||||
<script src="https://aframe.io/releases/1.5.0/aframe.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/aframe-blink-controls/dist/aframe-blink-controls.min.js"></script>
|
||||
<script src="./../../../dist/xrfragment.aframe.js"></script>
|
||||
<script src="./../../assets/js/qr.js"></script>
|
||||
|
@ -42,7 +42,7 @@
|
|||
<a-entity id="right-hand" laser-controls="hand: right" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: #floor"></a-entity>
|
||||
</a-entity>
|
||||
|
||||
<a-entity id="home" xrf="index.gltf"></a-entity>
|
||||
<a-entity id="home" xrf="index.glb"></a-entity>
|
||||
<a-plane id="floor" position="0 0 0" rotation="-90 0 0" width="100" height="100" material="visible:false"></a-plane>
|
||||
</a-scene>
|
||||
|
||||
|
|
Binary file not shown.
File diff suppressed because one or more lines are too long
3
make
3
make
|
@ -55,8 +55,7 @@ build(){
|
|||
|
||||
parser(){
|
||||
try rm dist/*
|
||||
haxe build.hxml
|
||||
ok=$?
|
||||
haxe build.hxml || exit 1
|
||||
sed -i 's|.*nonlocal .*||g' dist/xrfragment.py
|
||||
ls -lah dist/*
|
||||
echo -e "[OK] parser build\n"
|
||||
|
|
|
@ -1,43 +1,74 @@
|
|||
/*
|
||||
* TODO: refactor/fix this (queries are being refactored to filters)
|
||||
*/
|
||||
// spec: https://xrfragment.org/#queries
|
||||
// spec: https://xrfragment.org/#filters
|
||||
xrf.filter = function(){
|
||||
|
||||
xrf.filter = function(v, opts){
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
console.log(" └ running query ")
|
||||
let qobjs = Object.keys(v.query)
|
||||
|
||||
// convience function for other fragments (which apply to the query)
|
||||
frag.filter.getObjects = () => {
|
||||
let objs = []
|
||||
scene.traverse( (o) => {
|
||||
for ( let name in v.query ) {
|
||||
let qobj = v.query[name];
|
||||
if( qobj.tag && o.userData.tag && xrf.hasTag(name,o.userData.tag) ) objs.push(o)
|
||||
else if( qobj.id && o.name == name ) objs.push(o)
|
||||
}
|
||||
})
|
||||
return objs.filter( (o) => o ) // return and filter out empty
|
||||
.map( (o) => {
|
||||
if( !o.positionOriginal ) o.positionOriginal = o.position.clone()
|
||||
return o
|
||||
})
|
||||
}
|
||||
xrf.filter.scene(scene,frag) // spec : https://xrfragment.org/#queries
|
||||
}
|
||||
|
||||
xrf.filter.scene = function(scene,frag){
|
||||
// spec: https://xrfragment.org/#queries
|
||||
let q = frag.q.query
|
||||
scene.traverse( (mesh) => {
|
||||
for ( let i in q ) {
|
||||
let isMeshId = q[i].id != undefined
|
||||
let isMeshProperty = q[i].filter != undefined && !isMeshId
|
||||
if( q[i].root && mesh.isSRC ) continue; // ignore nested object for root-items (queryseletor '/foo' e.g.)
|
||||
if( isMeshId &&
|
||||
(i == mesh.name || xrf.hasTag(i,mesh.userData.tag))) mesh.visible = q[i].id
|
||||
//if( isMeshProperty && mesh.userData[i] ) mesh.visible = (new xrf.Query(frag.q.string)).testProperty(i,mesh.userData[i])
|
||||
xrf.filter.scene = function(opts){
|
||||
let {scene,frag} = opts
|
||||
|
||||
xrf.filter
|
||||
.sort(frag) // get (sorted) filters from XR Fragments
|
||||
.process(frag,scene) // show/hide things
|
||||
|
||||
return scene
|
||||
}
|
||||
|
||||
xrf.filter.sort = function(frag){
|
||||
// get all filters from XR Fragments
|
||||
frag.filters = Object.values(frag)
|
||||
.filter( (v) => v.filter ? v : null )
|
||||
.sort( (a,b) => a.index > b.index )
|
||||
return xrf.filter
|
||||
}
|
||||
|
||||
xrf.filter.process = function(frag,scene,opts){
|
||||
// include all when query starts with negative objectnames/tags are included
|
||||
let firstFilter = frag.filters[0].filter.get()
|
||||
let showAll = firstFilter.show === false
|
||||
let showers = frag.filters.filter( (v) => v.filter.get().show === true )
|
||||
if( !showAll ) scene.traverse( (n) => n.visible = false )
|
||||
|
||||
// reparent if first selector is positive and has no value
|
||||
if( firstFilter.show === true ){
|
||||
let obj = scene.getObjectByName( firstFilter.key )
|
||||
while( scene.children.length > 0 ) scene.children[0].removeFromParent()
|
||||
if(obj) scene.add(obj)
|
||||
}
|
||||
|
||||
frag.filters.map( (v) => {
|
||||
const filter = v.filter.get()
|
||||
const name_or_tag = v.fragment.replace(/[-\*]/g,'')
|
||||
let seen = {}
|
||||
|
||||
const setVisibleUnseen = (m,visible) => {
|
||||
if( seen[m.uuid] ) return
|
||||
m.visible = visible
|
||||
seen[ m.uuid ] = true
|
||||
}
|
||||
|
||||
scene.traverse( (m) => {
|
||||
const isMatch = m.name == name_or_tag || m.userData[filter.key]
|
||||
|
||||
// filter on value(expression) #foo=>3 e.g.
|
||||
if( filter.value && m.userData[filter.key] ){
|
||||
const visible = v.filter.testProperty(filter.key, m.userData[filter.key], filter.show === false )
|
||||
setVisibleUnseen(m,visible)
|
||||
if( filter.deep ){
|
||||
m.traverse( (n) => setVisibleUnseen(n,visible) )
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// include/exclude object(s) when id/tag matches (#foo or #-foo e.g.)
|
||||
if( isMatch ){
|
||||
m.visible = filter.show
|
||||
if( filter.deep ) m.traverse( (n) => n.visible = m.visible )
|
||||
}
|
||||
})
|
||||
})
|
||||
return xrf.filter
|
||||
}
|
||||
|
||||
|
|
|
@ -20,15 +20,14 @@ xrf.frag.src = function(v, opts){
|
|||
|
||||
const addModel = (model,url,frag) => {
|
||||
let scene = model.scene
|
||||
src = xrf.frag.src.filterScene(scene,{...opts,frag})
|
||||
xrf.frag.src.scale( src, opts, url )
|
||||
xrf.frag.src.eval( src, opts, url )
|
||||
xrf.frag.src.filterScene(scene,{...opts,frag})
|
||||
xrf.frag.src.scale( scene, opts, url )
|
||||
xrf.frag.src.eval( scene, opts, url )
|
||||
// allow 't'-fragment to setup separate animmixer
|
||||
enableSourcePortation(src)
|
||||
model.scene = src
|
||||
//enableSourcePortation(scene)
|
||||
mesh.add(model.scene)
|
||||
mesh.traverse( (n) => n.isSRC = n.isXRF = true ) // mark everything SRC
|
||||
xrf.emit('parseModel', {...opts, scene:src, model})
|
||||
xrf.emit('parseModel', {...opts, scene, model})
|
||||
if( mesh.material ) mesh.material.visible = false
|
||||
}
|
||||
|
||||
|
@ -67,10 +66,12 @@ xrf.frag.src = function(v, opts){
|
|||
}
|
||||
|
||||
if( url[0] == "#" ){
|
||||
let modelClone = {...model, scene: model.scene.clone()}
|
||||
modelClone.scenes = [modelClone.scene]
|
||||
modelClone.animations = modelClone.animations.map( (a) => a.clone() )
|
||||
addModel(modelClone,url,vfrag) // current file
|
||||
let _model = {
|
||||
animations: model.animations,
|
||||
scene: scene.clone()
|
||||
}
|
||||
_model.scenes = [_model.scene]
|
||||
addModel(_model,url,vfrag) // current file
|
||||
}else externalSRC(url,vfrag) // external file
|
||||
}
|
||||
|
||||
|
@ -126,8 +127,11 @@ xrf.frag.src.scale = function(scene, opts, url){
|
|||
|
||||
xrf.frag.src.filterScene = (scene,opts) => {
|
||||
let { mesh, model, camera, renderer, THREE, hashbus, frag} = opts
|
||||
let obj, src
|
||||
// cherrypicking of object(s)
|
||||
|
||||
xrf.filter.scene({scene,frag})
|
||||
if( scene.children.length == 1 ) scene.children[0].position.set(0,0,0)
|
||||
|
||||
/*
|
||||
if( !frag.filter ){
|
||||
src = new THREE.Group()
|
||||
if( Object.keys(frag).length > 0 ){
|
||||
|
@ -142,8 +146,7 @@ xrf.frag.src.filterScene = (scene,opts) => {
|
|||
}
|
||||
|
||||
// filtering of objects using query
|
||||
if( frag.filter ){
|
||||
console.warn("TODO: filter scene");
|
||||
if( Object.keys(frag).length > 1 ){
|
||||
src = scene
|
||||
xrf.filter.scene(src,frag)
|
||||
}
|
||||
|
@ -151,7 +154,8 @@ xrf.frag.src.filterScene = (scene,opts) => {
|
|||
if( m.userData && (m.userData.src || m.userData.href) ) return ; // prevent infinite recursion
|
||||
hashbus.pub.mesh(m,{scene,recursive:true}) // cool idea: recursion-depth based distance between face & src
|
||||
})
|
||||
return src
|
||||
*/
|
||||
return scene
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,18 +1,7 @@
|
|||
xrf.portalNonEuclidian = function(opts){
|
||||
let { frag, mesh, model, camera, scene, renderer} = opts
|
||||
|
||||
// turn plane into stencilplane
|
||||
mesh.material = new xrf.THREE.MeshBasicMaterial({ color: 'white' });
|
||||
mesh.material.depthWrite = true;
|
||||
mesh.material.depthTest = false;
|
||||
mesh.material.colorWrite = false;
|
||||
mesh.material.stencilWrite = true;
|
||||
mesh.material.stencilRef = xrf.portalNonEuclidian.stencilRef;
|
||||
mesh.material.stencilFunc = THREE.AlwaysStencilFunc;
|
||||
mesh.material.stencilZPass = THREE.ReplaceStencilOp;
|
||||
mesh.material.stencilFail = THREE.ReplaceStencilOp;
|
||||
mesh.material.stencilZFail = THREE.ReplaceStencilOp;
|
||||
//mesh.material.side = THREE.DoubleSide // *TODO* this requires flipping normals based on camera orientation
|
||||
|
||||
mesh.portal = {
|
||||
pos: mesh.position.clone(),
|
||||
posWorld: new xrf.THREE.Vector3(),
|
||||
|
@ -20,7 +9,11 @@ xrf.portalNonEuclidian = function(opts){
|
|||
needUpdate: false
|
||||
}
|
||||
|
||||
mesh.getWorldPosition(mesh.portal.posWorld)
|
||||
// turn mesh into stencilplane
|
||||
xrf
|
||||
.portalNonEuclidian
|
||||
.setMaterial(mesh)
|
||||
.getWorldPosition(mesh.portal.posWorld)
|
||||
|
||||
// allow objects to flip between original and stencil position (which puts them behind stencilplane)
|
||||
const addStencilFeature = (n) => {
|
||||
|
@ -101,4 +94,19 @@ xrf.portalNonEuclidian.selectStencil = (n, stencilRef, nested) => {
|
|||
if( n.children && !nested ) n.traverse( (m) => !m.portal && (xrf.portalNonEuclidian.selectStencil(m,stencilRef,true)) )
|
||||
}
|
||||
|
||||
xrf.portalNonEuclidian.setMaterial = function(mesh){
|
||||
mesh.material = new xrf.THREE.MeshBasicMaterial({ color: 'white' });
|
||||
mesh.material.depthWrite = true;
|
||||
mesh.material.depthTest = false;
|
||||
mesh.material.colorWrite = false;
|
||||
mesh.material.stencilWrite = true;
|
||||
mesh.material.stencilRef = xrf.portalNonEuclidian.stencilRef;
|
||||
mesh.material.stencilFunc = THREE.AlwaysStencilFunc;
|
||||
mesh.material.stencilZPass = THREE.ReplaceStencilOp;
|
||||
mesh.material.stencilFail = THREE.ReplaceStencilOp;
|
||||
mesh.material.stencilZFail = THREE.ReplaceStencilOp;
|
||||
return mesh
|
||||
}
|
||||
|
||||
|
||||
xrf.portalNonEuclidian.stencilRef = 1
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
{"fn":"url","data":"http://foo.com?foo=1#price=>2", "expect":{ "fn":"testParsed", "input":"price","out":true},"label":"query test"},
|
||||
{"fn":"query","data":"tag=bar", "expect":{ "fn":"testProperty","input":["tag","bar"],"out":true}},
|
||||
{"fn":"query","data":"-tag=foo", "expect":{ "fn":"testProperty","input":["tag","foo"],"out":false}},
|
||||
{"fn":"query","data":"-tag*=foo", "expect":{ "fn":"testProperty","input":["tag","foo"],"out":false}},
|
||||
{"fn":"query","data":"-tag=>2", "expect":{ "fn":"testProperty","input":["tag","3"],"out":false}},
|
||||
{"fn":"query","data":"price=>2", "expect":{ "fn":"testProperty","input":["price","1"],"out":false}},
|
||||
{"fn":"query","data":"price=<2", "expect":{ "fn":"testProperty","input":["price","5"],"out":false}},
|
||||
{"fn":"query","data":"price=<2", "expect":{ "fn":"testProperty","input":["price","1"],"out":true}}
|
||||
|
|
|
@ -56,7 +56,7 @@ class Filter {
|
|||
private var isExclude:EReg = ~/^-/; // 1. detect excluders like `-foo`,`-foo=1`,`-.foo`,`-/foo` (reference regex= `/^-/` )
|
||||
private var isRoot:EReg = ~/^[-]?\//; // 1. detect root selectors like `/foo` (reference regex= `/^[-]?\//` )
|
||||
private var isNumber:EReg = ~/^[0-9\.]+$/; // 1. detect number values like `foo=1` (reference regex= `/^[0-9\.]+$/` )
|
||||
private var isDeepSelect:EReg = ~/\*$/; // 1. detect nested keys like 'foo*' (reference regex= `/\*$/` )
|
||||
private var isDeepSelect:EReg = ~/(^-|\*$)/; // 1. detect nested keys like 'foo*' (reference regex= `/\*$/` )
|
||||
private var isSelectorExclude:EReg = ~/^-/; // 1. detect exclude keys like `-foo` (reference regex= `/^-/` )
|
||||
|
||||
public function new(str:String){
|
||||
|
@ -64,11 +64,11 @@ class Filter {
|
|||
}
|
||||
|
||||
public function toObject() : Dynamic {
|
||||
return this.q;
|
||||
return Reflect.copy(this.q);
|
||||
}
|
||||
|
||||
public function get() : Dynamic {
|
||||
return this.q;
|
||||
return Reflect.copy(this.q);
|
||||
}
|
||||
|
||||
public function parse(str:String) : Dynamic {
|
||||
|
@ -90,24 +90,21 @@ class Filter {
|
|||
if( str.indexOf(">") != -1 ) oper = ">"; // 1. then scan for `>` operator
|
||||
if( str.indexOf("<") != -1 ) oper = "<"; // 1. then scan for `<` operator
|
||||
if( isExclude.match(k) ){
|
||||
oper = "=!";
|
||||
k = k.substr(1); // 1. then strip key-operator: convert "-foo" into "foo"
|
||||
}else v = v.substr(oper.length); // 1. then strip value operator: change value ">=foo" into "foo"
|
||||
}
|
||||
v = v.substr(oper.length); // 1. then strip value operator: change value ">=foo" into "foo"
|
||||
if( oper.length == 0 ) oper = "=";
|
||||
var rule:haxe.DynamicAccess<Dynamic> = {};
|
||||
if( isNumber.match(v) ) rule[ oper ] = Std.parseFloat(v);
|
||||
else rule[oper] = v;
|
||||
filter['filter'] = rule; // 1. add filter rule
|
||||
q.set( k, filter );
|
||||
return;
|
||||
q.set('expr',rule);
|
||||
}else{ // 1. <b>ELSE </b> we are dealing with an object
|
||||
filter[ "id" ] = isExclude.match(str) ? false: true; // 1. therefore we we set `id` to `true` or `false` (false=excluder `-`)
|
||||
filter[ "root" ] = isRoot.match(str) ? true: false; // 1. and we set `root` to `true` or `false` (true=`/` root selector is present)
|
||||
filter[ "deep" ] = isDeepSelect.match(str) ? true: false; // 1. and we set `deep` to `true` or `false` (for objectnames with * suffix)
|
||||
if( isExclude.match(str) ) str = str.substr(1); // convert '-foo' into 'foo'
|
||||
if( isRoot.match(str) ) str = str.substr(1); // 1. we convert key '/foo' into 'foo'
|
||||
q.set( str ,filter ); // 1. finally we add the key/value to the store (`store.foo = {id:false,root:true}` e.g.)
|
||||
q.set("root", isRoot.match(str) ? true : false ); // 1. and we set `root` to `true` or `false` (true=`/` root selector is present)
|
||||
}
|
||||
q.set("show", isExclude.match(str) ? false : true ); // 1. therefore we we set `show` to `true` or `false` (false=excluder `-`)
|
||||
q.set("deep", isDeepSelect.match(k) ? true : false ); // 1. set `deep` (for objectnames with * suffix or negative selectors)
|
||||
q.set("key", isDeepSelect.replace(k,'') );
|
||||
q.set("value",v);
|
||||
}
|
||||
for( i in 0...token.length ) process( token[i] );
|
||||
return this.q = q;
|
||||
|
@ -151,22 +148,18 @@ class Filter {
|
|||
}
|
||||
|
||||
// conditional rules
|
||||
for ( k in Reflect.fields(q) ){
|
||||
var f:Dynamic = Reflect.field(q,k);
|
||||
if( f.filter == null ) continue;
|
||||
if( Reflect.field(q,'expr') ){
|
||||
var f:Dynamic = Reflect.field(q,'expr');
|
||||
|
||||
//if( Std.isOfType(value, String) ) contiggnue;
|
||||
if( exclude ){
|
||||
if( Reflect.field(f.filter,'!=') != null && testprop( Std.string(value) == Std.string(Reflect.field(f.filter,'!='))) && exclude ) qualify += 1;
|
||||
if( !Reflect.field(q,'show') ){
|
||||
if( Reflect.field(f,'!=') != null && testprop( Std.string(value) == Std.string(Reflect.field(f,'!='))) && exclude ) qualify += 1;
|
||||
}else{
|
||||
if( Reflect.field(f.filter,'*') != null && testprop( Std.parseFloat(value) != null ) ) qualify += 1;
|
||||
if( Reflect.field(f.filter,'>') != null && testprop( Std.parseFloat(value) > Std.parseFloat(Reflect.field(f.filter,'>' )) ) ) qualify += 1;
|
||||
if( Reflect.field(f.filter,'<') != null && testprop( Std.parseFloat(value) < Std.parseFloat(Reflect.field(f.filter,'<' )) ) ) qualify += 1;
|
||||
if( Reflect.field(f.filter,'>=') != null && testprop( Std.parseFloat(value) >= Std.parseFloat(Reflect.field(f.filter,'>=')) ) ) qualify += 1;
|
||||
if( Reflect.field(f.filter,'<=') != null && testprop( Std.parseFloat(value) <= Std.parseFloat(Reflect.field(f.filter,'<=')) ) ) qualify += 1;
|
||||
if( Reflect.field(f.filter,'=') != null && (
|
||||
testprop( value == Reflect.field(f.filter,'=')) ||
|
||||
testprop( Std.parseFloat(value) == Std.parseFloat(Reflect.field(f.filter,'=')))
|
||||
if( Reflect.field(f,'*') != null && testprop( Std.parseFloat(value) != null ) ) qualify += 1;
|
||||
if( Reflect.field(f,'>') != null && testprop( Std.parseFloat(value) > Std.parseFloat(Reflect.field(f,'>' )) ) ) qualify += 1;
|
||||
if( Reflect.field(f,'<') != null && testprop( Std.parseFloat(value) < Std.parseFloat(Reflect.field(f,'<' )) ) ) qualify += 1;
|
||||
if( Reflect.field(f,'=') != null && (
|
||||
testprop( value == Reflect.field(f,'=')) ||
|
||||
testprop( Std.parseFloat(value) == Std.parseFloat(Reflect.field(f,'=')))
|
||||
)) qualify += 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ class Parser {
|
|||
public static var keyClean:EReg = ~/(\*$|^-)/g;
|
||||
|
||||
@:keep
|
||||
public static function parse(key:String,value:String,store:haxe.DynamicAccess<Dynamic>):Bool {
|
||||
public static function parse(key:String,value:String,store:haxe.DynamicAccess<Dynamic>,?index:Int):Bool {
|
||||
// here we define allowed characteristics & datatypes for each fragment (stored as bitmasked int for performance purposes)
|
||||
var Frag:Map<String, Int> = new Map<String, Int>();
|
||||
|
||||
|
@ -52,14 +52,14 @@ class Parser {
|
|||
var isPVDynamic:Bool = key.length > 0 && !Frag.exists(key);
|
||||
var isPVDefault:Bool = value.length == 0 && key.length > 0 && key == "#";
|
||||
if( isPVDynamic ){ //|| isPVDefault ){ // 1. add keys without values to store as [predefined view](predefined_view)
|
||||
var v:XRF = new XRF(key, XRF.PV_EXECUTE | XRF.NAVIGATOR );
|
||||
var v:XRF = new XRF(key, XRF.PV_EXECUTE | XRF.NAVIGATOR, index );
|
||||
v.validate(value); // will fail but will parse multiple args for us (separated by |)
|
||||
store.set( keyClean.replace(key,''), v );
|
||||
return true;
|
||||
}
|
||||
|
||||
// regular fragments:
|
||||
var v:XRF = new XRF(key, Frag.get(key));
|
||||
var v:XRF = new XRF(key, Frag.get(key), index);
|
||||
if( Frag.exists(key) ){ // 1. check if fragment is official XR Fragment
|
||||
if( !v.validate(value) ){ // 1. guess the type of the value (string,int,float,x,y,z,color,args,query)
|
||||
trace("⚠ fragment '"+key+"' has incompatible value ("+value+")");// 1. don't add to store if value-type is incorrect
|
||||
|
|
|
@ -40,7 +40,7 @@ class URI {
|
|||
if (splitByEqual.length > 1) {
|
||||
value = StringTools.urlDecode(regexPlus.split(splitByEqual[1]).join(" "));
|
||||
}
|
||||
var ok:Bool = Parser.parse(key,value,store); // 1. for every recognized fragment key/value-pair call [Parser.parse](#%E2%86%AA%20Parser.parse%28k%2Cv%2Cstore%29)
|
||||
var ok:Bool = Parser.parse(key,value,store,i); // 1. for every recognized fragment key/value-pair call [Parser.parse](#%E2%86%AA%20Parser.parse%28k%2Cv%2Cstore%29)
|
||||
}
|
||||
if( filter != null && filter != 0 ){
|
||||
for (key in store.keys()) {
|
||||
|
|
|
@ -47,6 +47,7 @@ class XRF {
|
|||
// value holder(s) // |------|------|--------|----------------------------------|
|
||||
public var fragment:String;
|
||||
public var flags:Int;
|
||||
public var index:Int;
|
||||
public var x:Float; // |vector| x,y,z| comma-separated | #pos=1,2,3 |
|
||||
public var y:Float;
|
||||
public var z:Float;
|
||||
|
@ -58,9 +59,10 @@ class XRF {
|
|||
public var filter:Filter;
|
||||
public var noXRF:Bool;
|
||||
//
|
||||
public function new(_fragment:String,_flags:Int){
|
||||
public function new(_fragment:String,_flags:Int,?_index:Int){
|
||||
fragment = _fragment;
|
||||
flags = _flags;
|
||||
index = _index;
|
||||
}
|
||||
|
||||
public function is(flag:Int):Bool {
|
||||
|
@ -107,8 +109,8 @@ class XRF {
|
|||
v.int = Std.parseInt(str);
|
||||
v.x = cast(v.int);
|
||||
}
|
||||
filter = (new Filter(v.fragment+"="+v.string)).get();
|
||||
}else filter = (new Filter(v.fragment)).get();
|
||||
v.filter = new Filter(v.fragment+"="+v.string);
|
||||
}else v.filter = new Filter(v.fragment);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
// test the XR Fragments parser-filters with THREEjs scenes
|
||||
THREE = AFRAME.THREE
|
||||
|
||||
createScene = (noadd) => {
|
||||
let obj = {a:{},b:{},c:{}}
|
||||
for ( let i in obj ){
|
||||
obj[i] = new THREE.Object3D()
|
||||
obj[i].name = i
|
||||
}
|
||||
let {a,b,c} = obj
|
||||
let scene = new THREE.Scene()
|
||||
if( !noadd ){
|
||||
a.add(b)
|
||||
b.add(c)
|
||||
scene.add(a)
|
||||
}
|
||||
b.userData.score = 2
|
||||
return {a,b,c,scene}
|
||||
}
|
||||
|
||||
filterScene = (URI) => {
|
||||
frag = xrf.URI.parse(URI)
|
||||
var {a,b,c,scene} = createScene()
|
||||
xrf.filter.scene({scene,frag})
|
||||
return scene
|
||||
}
|
||||
|
||||
scene = filterScene("#b")
|
||||
test = () => !scene.getObjectByName("a") &&
|
||||
scene.getObjectByName("b").visible &&
|
||||
!scene.getObjectByName("c")
|
||||
console.assert( test(), {scene,reason:`objectname: #b => a = removed b = visible c = removed`})
|
||||
|
||||
scene = filterScene("#b*")
|
||||
test = () => !scene.getObjectByName("a") &&
|
||||
scene.getObjectByName("b").visible &&
|
||||
scene.getObjectByName("c").visible
|
||||
console.assert( test(), {scene,reason:`objectname: #b* => a = removed b = visible c = visible`})
|
||||
|
||||
scene = filterScene("#-b")
|
||||
test = () => scene.getObjectByName("a").visible &&
|
||||
!scene.getObjectByName("b").visible &&
|
||||
!scene.getObjectByName("c").visible
|
||||
console.assert( test(), {scene,reason:`objectname: #-b => a = visible b = invisible c = invisible`})
|
||||
|
||||
scene = filterScene("#a&-b")
|
||||
test = () => scene.getObjectByName("a").visible &&
|
||||
!scene.getObjectByName("b").visible &&
|
||||
!scene.getObjectByName("c").visible
|
||||
console.assert( test(), {scene,reason:`objectname: #a&-b => a = visible b = invisible c = invisible`})
|
||||
|
||||
scene = filterScene("#-b&b")
|
||||
test = () => !scene.getObjectByName("a") &&
|
||||
scene.getObjectByName("b").visible &&
|
||||
!scene.getObjectByName("c").visible
|
||||
console.assert( test(), {scene,reason:`objectname: #-b&b => a = removed b = invisible c = invisible (last duplicate wins)`})
|
||||
|
||||
scene = filterScene("#-c")
|
||||
test = () => scene.getObjectByName("a").visible &&
|
||||
scene.getObjectByName("b").visible &&
|
||||
!scene.getObjectByName("c").visible
|
||||
console.assert( test(), {scene,reason:`objectname: #-b&b => a = visible b = visible c = invisible`})
|
||||
|
||||
scene = filterScene("#-b*")
|
||||
test = () => scene.getObjectByName("a").visible &&
|
||||
!scene.getObjectByName("b").visible &&
|
||||
!scene.getObjectByName("c").visible
|
||||
console.assert( test(), {scene,reason:`objectname: #-b&b => a = visible b = visible c = invisible`})
|
||||
|
||||
scene = filterScene("#score")
|
||||
test = () => !scene.getObjectByName("a") &&
|
||||
scene.getObjectByName("b").visible &&
|
||||
!scene.getObjectByName("c").visible
|
||||
console.assert( test(), {scene,reason:`objectname: #score => a = removed b = visible c = invisible`})
|
||||
|
||||
scene = filterScene("#score=>1")
|
||||
test = () => !scene.getObjectByName("a") &&
|
||||
scene.getObjectByName("b").visible &&
|
||||
!scene.getObjectByName("c").visible
|
||||
console.assert( test(), {scene,reason:`objectname: #score=>1 => a = removed b = visible c = invisible`})
|
||||
|
||||
scene = filterScene("#score=>3")
|
||||
test = () => !scene.getObjectByName("a").visible &&
|
||||
!scene.getObjectByName("b").visible &&
|
||||
!scene.getObjectByName("c").visible
|
||||
console.assert( test(), {scene,reason:`objectname: #score=>3 => a = invisible b = visible c = invisible`})
|
||||
|
||||
scene = filterScene("#score*=>1")
|
||||
test = () => !scene.getObjectByName("a").visible &&
|
||||
scene.getObjectByName("b").visible &&
|
||||
scene.getObjectByName("c").visible
|
||||
console.assert( test(), {scene,reason:`objectname: #score*=>1 => a = invisible b = visible c = visible`})
|
||||
|
||||
scene = filterScene("#-score*=>1")
|
||||
test = () => scene.getObjectByName("a").visible &&
|
||||
!scene.getObjectByName("b").visible &&
|
||||
!scene.getObjectByName("c").visible
|
||||
console.assert( test(), {scene,reason:`objectname: #-score*=>1 => a = visible b = invisible c = invisible`})
|
||||
|
||||
scene = filterScene("#-score*=>1&c")
|
||||
test = () => scene.getObjectByName("a").visible &&
|
||||
!scene.getObjectByName("b").visible &&
|
||||
scene.getObjectByName("c").visible
|
||||
console.assert( test(), {scene,reason:`objectname: #-score*=>1 => a = visible b = invisible c = visible`})
|
|
@ -3,10 +3,11 @@
|
|||
<title>AFRAME - xrfragment sandbox</title>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
||||
<script src="https://aframe.io/releases/1.4.2/aframe.min.js"></script>
|
||||
<script src="https://aframe.io/releases/1.5.0/aframe.min.js"></script>
|
||||
<script src="./../../dist/xrfragment.aframe.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
<script src="./pubsub.js"></script>
|
||||
<script src="./filter.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h3>open the browserconsole to see the results</h3>
|
||||
|
|
|
@ -18,6 +18,6 @@ console.assert = ((assert) => (a,b) => {
|
|||
let frags = xrf.URI.parse('://foo.com/1.gltf#pos=1.0,2.0,3.0&q=-.foo&t=1,100',true)
|
||||
console.assert( frags.t, {frags, reason:'URI.parse(): t needs to be set'})
|
||||
|
||||
let q = new xrf.Query();
|
||||
console.assert( new xrf.Query(), {reason: 'new Query() should be available'})
|
||||
let frag = xrf.URI.parse("#foo=1")
|
||||
console.assert( frag, {reason: 'xrf.URI.parse() should be available'})
|
||||
|
||||
|
|
Loading…
Reference in New Issue