removed += from spec + added / root-selector to spec

This commit is contained in:
Leon van Kammen 2023-06-20 14:59:25 +02:00
parent b01d0e57d9
commit e3cf693fa7
11 changed files with 154 additions and 111 deletions

View File

@ -265,7 +265,7 @@ xrfragment_Parser.parse = function(key,value,resultMap) {
var xrfragment_Query = $hx_exports["xrfragment"]["Query"] = function(str) { var xrfragment_Query = $hx_exports["xrfragment"]["Query"] = function(str) {
this.isNumber = new EReg("^[0-9\\.]+$",""); this.isNumber = new EReg("^[0-9\\.]+$","");
this.isClass = new EReg("^[-]?class$",""); this.isClass = new EReg("^[-]?class$","");
this.isAddition = new EReg("^\\+",""); this.isRoot = new EReg("^/","");
this.isExclude = new EReg("^-",""); this.isExclude = new EReg("^-","");
this.isProp = new EReg("^.*:[><=!]?",""); this.isProp = new EReg("^.*:[><=!]?","");
this.q = { }; this.q = { };
@ -329,9 +329,6 @@ xrfragment_Query.prototype = {
if(_gthis.isExclude.match(k)) { if(_gthis.isExclude.match(k)) {
oper = "!="; oper = "!=";
k = HxOverrides.substr(k,1,null); k = HxOverrides.substr(k,1,null);
} else if(_gthis.isAddition.match(k)) {
oper = "+=";
k = HxOverrides.substr(k,1,null);
} else { } else {
v = HxOverrides.substr(v,oper.length,null); v = HxOverrides.substr(v,oper.length,null);
} }
@ -353,6 +350,12 @@ xrfragment_Query.prototype = {
} }
return; return;
} else { } else {
if(_gthis.isRoot.match(k)) {
str = HxOverrides.substr(k,1,null);
filter["root"] = true;
} else if(filter["root"] == true) {
Reflect.deleteField(filter,"root");
}
filter["id"] = _gthis.isExclude.match(str) ? false : true; filter["id"] = _gthis.isExclude.match(str) ? false : true;
var key = _gthis.isExclude.match(str) ? HxOverrides.substr(str,1,null) : str; var key = _gthis.isExclude.match(str) ? HxOverrides.substr(str,1,null) : str;
q[key] = filter; q[key] = filter;
@ -1066,7 +1069,7 @@ xrf.frag.href = function(v, opts){
quat: new THREE.Quaternion() quat: new THREE.Quaternion()
} }
// detect equirectangular image // detect equirectangular image
let texture = mesh.material.map let texture = mesh.material && mesh.material.map ? mesh.material.map : null
if( texture && texture.source.data.height == texture.source.data.width/2 ){ if( texture && texture.source.data.height == texture.source.data.width/2 ){
texture.mapping = THREE.ClampToEdgeWrapping texture.mapping = THREE.ClampToEdgeWrapping
texture.needsUpdate = true texture.needsUpdate = true
@ -1113,7 +1116,7 @@ xrf.frag.href = function(v, opts){
`, `,
}); });
mesh.material.needsUpdate = true mesh.material.needsUpdate = true
}else mesh.material = mesh.material.clone() }else if( mesh.material){ mesh.material = mesh.material.clone() }
let click = mesh.userData.XRF.href.exec = (e) => { let click = mesh.userData.XRF.href.exec = (e) => {
xrf xrf
@ -1128,8 +1131,10 @@ xrf.frag.href = function(v, opts){
let selected = (state) => () => { let selected = (state) => () => {
if( mesh.selected == state ) return // nothing changed if( mesh.selected == state ) return // nothing changed
if( mesh.material.uniforms ) mesh.material.uniforms.selected.value = state if( mesh.material ){
else mesh.material.color.r = mesh.material.color.g = mesh.material.color.b = state ? 2.0 : 1.0 if( mesh.material.uniforms ) mesh.material.uniforms.selected.value = state
else mesh.material.color.r = mesh.material.color.g = mesh.material.color.b = state ? 2.0 : 1.0
}
// update mouse cursor // update mouse cursor
if( !renderer.domElement.lastCursor ) if( !renderer.domElement.lastCursor )
renderer.domElement.lastCursor = renderer.domElement.style.cursor renderer.domElement.lastCursor = renderer.domElement.style.cursor
@ -1181,11 +1186,12 @@ const doPredefinedView = (opts) => {
const selectionOfInterest = (frag,scene,mesh) => { const selectionOfInterest = (frag,scene,mesh) => {
let id = frag.string let id = frag.string
// Selection of Interest if predefined_view matches object name if(!id) return id // important: ignore empty strings
if( mesh.selection ){ if( mesh.selection ){
scene.remove(mesh.selection) scene.remove(mesh.selection)
delete mesh.selection delete mesh.selection
} }
// Selection of Interest if predefined_view matches object name
if( id == mesh.name || id.substr(1) == mesh.userData.class ){ if( id == mesh.name || id.substr(1) == mesh.userData.class ){
xrf.emit('selection',{...opts,frag}) xrf.emit('selection',{...opts,frag})
.then( () => { .then( () => {
@ -1202,9 +1208,10 @@ const doPredefinedView = (opts) => {
} }
const predefinedView = (frag,scene,mesh) => { const predefinedView = (frag,scene,mesh) => {
let id = frag.string let id = frag.string
if( mesh.userData[`#${id}`] ){ if( !id ) return // prevent empty matches
let frag = xrf.URI.parse( mesh.userData[id], xrf.XRF.NAVIGATOR | xrf.XRF.PV_OVERRIDE | xrf.XRF.EMBEDDED ) if( mesh.userData[`#${id}`] ){ // get alias
frag = xrf.URI.parse( mesh.userData[`#${id}`], xrf.XRF.NAVIGATOR | xrf.XRF.PV_OVERRIDE | xrf.XRF.EMBEDDED )
for ( let k in frag ){ for ( let k in frag ){
let opts = {frag, model, camera: xrf.camera, scene: xrf.scene, renderer: xrf.renderer, THREE: xrf.THREE } let opts = {frag, model, camera: xrf.camera, scene: xrf.scene, renderer: xrf.renderer, THREE: xrf.THREE }
xrf.emit('predefinedView',{...opts,frag}) xrf.emit('predefinedView',{...opts,frag})
@ -1271,14 +1278,14 @@ xrf.frag.q = function(v, opts){
target.mesh.rotation.set(0,0,0) target.mesh.rotation.set(0,0,0)
} }
} }
// remove negative selectors // hide negative selectors
let remove = [] let negative = []
v.scene.traverse( (mesh) => { v.scene.traverse( (mesh) => {
for ( let i in v.query ) { for ( let i in v.query ) {
if( mesh.name == i && v.query[i].id === false ) remove.push(mesh) if( mesh.name == i && v.query[i].id === false ) negative.push(mesh)
} }
}) })
remove.map( (mesh) => mesh.parent.remove( mesh ) ) negative.map( (mesh) => mesh.visible = false )
} }
const showHide = () => { const showHide = () => {
@ -1326,7 +1333,7 @@ xrf.frag.src = function(v, opts){
xrf.eval.fragment(i, Object.assign(opts,{frag, model,scene})) xrf.eval.fragment(i, Object.assign(opts,{frag, model,scene}))
} }
if( frag.q.query ){ if( frag.q.query ){
let srcScene = frag.q.scene let srcScene = frag.q.scene // three/xrf/q.js initializes .scene
if( !srcScene || !srcScene.visible ) return if( !srcScene || !srcScene.visible ) return
console.log(" └ inserting "+i+" (srcScene)") console.log(" └ inserting "+i+" (srcScene)")
srcScene.position.set(0,0,0) srcScene.position.set(0,0,0)
@ -1334,6 +1341,7 @@ xrf.frag.src = function(v, opts){
srcScene.traverse( (m) => { srcScene.traverse( (m) => {
if( m.userData && (m.userData.src || m.userData.href) ) return ;//delete m.userData.src // prevent infinite recursion if( m.userData && (m.userData.src || m.userData.href) ) return ;//delete m.userData.src // prevent infinite recursion
xrf.eval.mesh(m,{scene,recursive:true}) xrf.eval.mesh(m,{scene,recursive:true})
m.name = mesh.name+"."+m.name // prefix meshname so predefined views don't affect objectnames anymore
}) })
if( srcScene.visible ) src.add( srcScene ) if( srcScene.visible ) src.add( srcScene )
} }

11
dist/xrfragment.js vendored
View File

@ -265,7 +265,7 @@ xrfragment_Parser.parse = function(key,value,resultMap) {
var xrfragment_Query = $hx_exports["xrfragment"]["Query"] = function(str) { var xrfragment_Query = $hx_exports["xrfragment"]["Query"] = function(str) {
this.isNumber = new EReg("^[0-9\\.]+$",""); this.isNumber = new EReg("^[0-9\\.]+$","");
this.isClass = new EReg("^[-]?class$",""); this.isClass = new EReg("^[-]?class$","");
this.isAddition = new EReg("^\\+",""); this.isRoot = new EReg("^/","");
this.isExclude = new EReg("^-",""); this.isExclude = new EReg("^-","");
this.isProp = new EReg("^.*:[><=!]?",""); this.isProp = new EReg("^.*:[><=!]?","");
this.q = { }; this.q = { };
@ -329,9 +329,6 @@ xrfragment_Query.prototype = {
if(_gthis.isExclude.match(k)) { if(_gthis.isExclude.match(k)) {
oper = "!="; oper = "!=";
k = HxOverrides.substr(k,1,null); k = HxOverrides.substr(k,1,null);
} else if(_gthis.isAddition.match(k)) {
oper = "+=";
k = HxOverrides.substr(k,1,null);
} else { } else {
v = HxOverrides.substr(v,oper.length,null); v = HxOverrides.substr(v,oper.length,null);
} }
@ -353,6 +350,12 @@ xrfragment_Query.prototype = {
} }
return; return;
} else { } else {
if(_gthis.isRoot.match(k)) {
str = HxOverrides.substr(k,1,null);
filter["root"] = true;
} else if(filter["root"] == true) {
Reflect.deleteField(filter,"root");
}
filter["id"] = _gthis.isExclude.match(str) ? false : true; filter["id"] = _gthis.isExclude.match(str) ? false : true;
var key = _gthis.isExclude.match(str) ? HxOverrides.substr(str,1,null) : str; var key = _gthis.isExclude.match(str) ? HxOverrides.substr(str,1,null) : str;
q[key] = filter; q[key] = filter;

71
dist/xrfragment.lua vendored
View File

@ -1633,7 +1633,7 @@ end
__xrfragment_Query.super = function(self,str) __xrfragment_Query.super = function(self,str)
self.isNumber = EReg.new("^[0-9\\.]+$", ""); self.isNumber = EReg.new("^[0-9\\.]+$", "");
self.isClass = EReg.new("^[-]?class$", ""); self.isClass = EReg.new("^[-]?class$", "");
self.isAddition = EReg.new("^\\+", ""); self.isRoot = EReg.new("^/", "");
self.isExclude = EReg.new("^-", ""); self.isExclude = EReg.new("^-", "");
self.isProp = EReg.new("^.*:[><=!]?", ""); self.isProp = EReg.new("^.*:[><=!]?", "");
self.q = _hx_e(); self.q = _hx_e();
@ -1852,42 +1852,22 @@ __xrfragment_Query.prototype.parse = function(self,str,recurse)
end; end;
k = __lua_lib_luautf8_Utf8.sub(k, pos + 1, pos + len); k = __lua_lib_luautf8_Utf8.sub(k, pos + 1, pos + len);
else else
if (_gthis.isAddition:match(k)) then local pos = __lua_lib_luautf8_Utf8.len(oper);
oper = "+="; local len = nil;
local pos = 1; if ((len == nil) or (len > (pos + __lua_lib_luautf8_Utf8.len(v)))) then
local len = nil; len = __lua_lib_luautf8_Utf8.len(v);
if ((len == nil) or (len > (pos + __lua_lib_luautf8_Utf8.len(k)))) then
len = __lua_lib_luautf8_Utf8.len(k);
else
if (len < 0) then
len = __lua_lib_luautf8_Utf8.len(k) + len;
end;
end;
if (pos < 0) then
pos = __lua_lib_luautf8_Utf8.len(k) + pos;
end;
if (pos < 0) then
pos = 0;
end;
k = __lua_lib_luautf8_Utf8.sub(k, pos + 1, pos + len);
else else
local pos = __lua_lib_luautf8_Utf8.len(oper); if (len < 0) then
local len = nil; len = __lua_lib_luautf8_Utf8.len(v) + len;
if ((len == nil) or (len > (pos + __lua_lib_luautf8_Utf8.len(v)))) then
len = __lua_lib_luautf8_Utf8.len(v);
else
if (len < 0) then
len = __lua_lib_luautf8_Utf8.len(v) + len;
end;
end; end;
if (pos < 0) then
pos = __lua_lib_luautf8_Utf8.len(v) + pos;
end;
if (pos < 0) then
pos = 0;
end;
v = __lua_lib_luautf8_Utf8.sub(v, pos + 1, pos + len);
end; end;
if (pos < 0) then
pos = __lua_lib_luautf8_Utf8.len(v) + pos;
end;
if (pos < 0) then
pos = 0;
end;
v = __lua_lib_luautf8_Utf8.sub(v, pos + 1, pos + len);
end; end;
if (__lua_lib_luautf8_Utf8.len(oper) == 0) then if (__lua_lib_luautf8_Utf8.len(oper) == 0) then
oper = "="; oper = "=";
@ -1909,6 +1889,29 @@ __xrfragment_Query.prototype.parse = function(self,str,recurse)
end; end;
do return end; do return end;
else else
if (_gthis.isRoot:match(k)) then
local pos = 1;
local len = nil;
if ((len == nil) or (len > (pos + __lua_lib_luautf8_Utf8.len(k)))) then
len = __lua_lib_luautf8_Utf8.len(k);
else
if (len < 0) then
len = __lua_lib_luautf8_Utf8.len(k) + len;
end;
end;
if (pos < 0) then
pos = __lua_lib_luautf8_Utf8.len(k) + pos;
end;
if (pos < 0) then
pos = 0;
end;
str = __lua_lib_luautf8_Utf8.sub(k, pos + 1, pos + len);
filter.root = true;
else
if (Reflect.field(filter, "root") == true) then
Reflect.deleteField(filter, "root");
end;
end;
local value = (function() local value = (function()
local _hx_7 local _hx_7
if (_gthis.isExclude:match(str)) then if (_gthis.isExclude:match(str)) then

View File

@ -265,7 +265,7 @@ xrfragment_Parser.parse = function(key,value,resultMap) {
var xrfragment_Query = $hx_exports["xrfragment"]["Query"] = function(str) { var xrfragment_Query = $hx_exports["xrfragment"]["Query"] = function(str) {
this.isNumber = new EReg("^[0-9\\.]+$",""); this.isNumber = new EReg("^[0-9\\.]+$","");
this.isClass = new EReg("^[-]?class$",""); this.isClass = new EReg("^[-]?class$","");
this.isAddition = new EReg("^\\+",""); this.isRoot = new EReg("^/","");
this.isExclude = new EReg("^-",""); this.isExclude = new EReg("^-","");
this.isProp = new EReg("^.*:[><=!]?",""); this.isProp = new EReg("^.*:[><=!]?","");
this.q = { }; this.q = { };
@ -329,9 +329,6 @@ xrfragment_Query.prototype = {
if(_gthis.isExclude.match(k)) { if(_gthis.isExclude.match(k)) {
oper = "!="; oper = "!=";
k = HxOverrides.substr(k,1,null); k = HxOverrides.substr(k,1,null);
} else if(_gthis.isAddition.match(k)) {
oper = "+=";
k = HxOverrides.substr(k,1,null);
} else { } else {
v = HxOverrides.substr(v,oper.length,null); v = HxOverrides.substr(v,oper.length,null);
} }
@ -353,6 +350,12 @@ xrfragment_Query.prototype = {
} }
return; return;
} else { } else {
if(_gthis.isRoot.match(k)) {
str = HxOverrides.substr(k,1,null);
filter["root"] = true;
} else if(filter["root"] == true) {
Reflect.deleteField(filter,"root");
}
filter["id"] = _gthis.isExclude.match(str) ? false : true; filter["id"] = _gthis.isExclude.match(str) ? false : true;
var key = _gthis.isExclude.match(str) ? HxOverrides.substr(str,1,null) : str; var key = _gthis.isExclude.match(str) ? HxOverrides.substr(str,1,null) : str;
q[key] = filter; q[key] = filter;

21
dist/xrfragment.py vendored
View File

@ -1338,14 +1338,14 @@ class xrfragment_Parser:
class xrfragment_Query: class xrfragment_Query:
_hx_class_name = "xrfragment.Query" _hx_class_name = "xrfragment.Query"
__slots__ = ("str", "q", "isProp", "isExclude", "isAddition", "isClass", "isNumber") __slots__ = ("str", "q", "isProp", "isExclude", "isRoot", "isClass", "isNumber")
_hx_fields = ["str", "q", "isProp", "isExclude", "isAddition", "isClass", "isNumber"] _hx_fields = ["str", "q", "isProp", "isExclude", "isRoot", "isClass", "isNumber"]
_hx_methods = ["toObject", "expandAliases", "get", "parse", "test", "testProperty"] _hx_methods = ["toObject", "expandAliases", "get", "parse", "test", "testProperty"]
def __init__(self,_hx_str): def __init__(self,_hx_str):
self.isNumber = EReg("^[0-9\\.]+$","") self.isNumber = EReg("^[0-9\\.]+$","")
self.isClass = EReg("^[-]?class$","") self.isClass = EReg("^[-]?class$","")
self.isAddition = EReg("^\\+","") self.isRoot = EReg("^/","")
self.isExclude = EReg("^-","") self.isExclude = EReg("^-","")
self.isProp = EReg("^.*:[><=!]?","") self.isProp = EReg("^.*:[><=!]?","")
self.q = _hx_AnonObject({}) self.q = _hx_AnonObject({})
@ -1409,13 +1409,7 @@ class xrfragment_Query:
oper = "!=" oper = "!="
k = HxString.substr(k,1,None) k = HxString.substr(k,1,None)
else: else:
_this = _gthis.isAddition v = HxString.substr(v,len(oper),None)
_this.matchObj = python_lib_Re.search(_this.pattern,k)
if (_this.matchObj is not None):
oper = "+="
k = HxString.substr(k,1,None)
else:
v = HxString.substr(v,len(oper),None)
if (len(oper) == 0): if (len(oper) == 0):
oper = "=" oper = "="
_this = _gthis.isClass _this = _gthis.isClass
@ -1438,6 +1432,13 @@ class xrfragment_Query:
setattr(q,(("_hx_" + k) if ((k in python_Boot.keywords)) else (("_hx_" + k) if (((((len(k) > 2) and ((ord(k[0]) == 95))) and ((ord(k[1]) == 95))) and ((ord(k[(len(k) - 1)]) != 95)))) else k)),_hx_filter) setattr(q,(("_hx_" + k) if ((k in python_Boot.keywords)) else (("_hx_" + k) if (((((len(k) > 2) and ((ord(k[0]) == 95))) and ((ord(k[1]) == 95))) and ((ord(k[(len(k) - 1)]) != 95)))) else k)),_hx_filter)
return return
else: else:
_this = _gthis.isRoot
_this.matchObj = python_lib_Re.search(_this.pattern,k)
if (_this.matchObj is not None):
_hx_str = HxString.substr(k,1,None)
setattr(_hx_filter,(("_hx_" + "root") if (("root" in python_Boot.keywords)) else (("_hx_" + "root") if (((((len("root") > 2) and ((ord("root"[0]) == 95))) and ((ord("root"[1]) == 95))) and ((ord("root"[(len("root") - 1)]) != 95)))) else "root")),True)
elif (Reflect.field(_hx_filter,"root") == True):
Reflect.deleteField(_hx_filter,"root")
_this = _gthis.isExclude _this = _gthis.isExclude
_this.matchObj = python_lib_Re.search(_this.pattern,_hx_str) _this.matchObj = python_lib_Re.search(_this.pattern,_hx_str)
value = (False if ((_this.matchObj is not None)) else True) value = (False if ((_this.matchObj is not None)) else True)

View File

@ -265,7 +265,7 @@ xrfragment_Parser.parse = function(key,value,resultMap) {
var xrfragment_Query = $hx_exports["xrfragment"]["Query"] = function(str) { var xrfragment_Query = $hx_exports["xrfragment"]["Query"] = function(str) {
this.isNumber = new EReg("^[0-9\\.]+$",""); this.isNumber = new EReg("^[0-9\\.]+$","");
this.isClass = new EReg("^[-]?class$",""); this.isClass = new EReg("^[-]?class$","");
this.isAddition = new EReg("^\\+",""); this.isRoot = new EReg("^/","");
this.isExclude = new EReg("^-",""); this.isExclude = new EReg("^-","");
this.isProp = new EReg("^.*:[><=!]?",""); this.isProp = new EReg("^.*:[><=!]?","");
this.q = { }; this.q = { };
@ -329,9 +329,6 @@ xrfragment_Query.prototype = {
if(_gthis.isExclude.match(k)) { if(_gthis.isExclude.match(k)) {
oper = "!="; oper = "!=";
k = HxOverrides.substr(k,1,null); k = HxOverrides.substr(k,1,null);
} else if(_gthis.isAddition.match(k)) {
oper = "+=";
k = HxOverrides.substr(k,1,null);
} else { } else {
v = HxOverrides.substr(v,oper.length,null); v = HxOverrides.substr(v,oper.length,null);
} }
@ -353,6 +350,12 @@ xrfragment_Query.prototype = {
} }
return; return;
} else { } else {
if(_gthis.isRoot.match(k)) {
str = HxOverrides.substr(k,1,null);
filter["root"] = true;
} else if(filter["root"] == true) {
Reflect.deleteField(filter,"root");
}
filter["id"] = _gthis.isExclude.match(str) ? false : true; filter["id"] = _gthis.isExclude.match(str) ? false : true;
var key = _gthis.isExclude.match(str) ? HxOverrides.substr(str,1,null) : str; var key = _gthis.isExclude.match(str) ? HxOverrides.substr(str,1,null) : str;
q[key] = filter; q[key] = filter;
@ -1066,7 +1069,7 @@ xrf.frag.href = function(v, opts){
quat: new THREE.Quaternion() quat: new THREE.Quaternion()
} }
// detect equirectangular image // detect equirectangular image
let texture = mesh.material.map let texture = mesh.material && mesh.material.map ? mesh.material.map : null
if( texture && texture.source.data.height == texture.source.data.width/2 ){ if( texture && texture.source.data.height == texture.source.data.width/2 ){
texture.mapping = THREE.ClampToEdgeWrapping texture.mapping = THREE.ClampToEdgeWrapping
texture.needsUpdate = true texture.needsUpdate = true
@ -1113,7 +1116,7 @@ xrf.frag.href = function(v, opts){
`, `,
}); });
mesh.material.needsUpdate = true mesh.material.needsUpdate = true
}else mesh.material = mesh.material.clone() }else if( mesh.material){ mesh.material = mesh.material.clone() }
let click = mesh.userData.XRF.href.exec = (e) => { let click = mesh.userData.XRF.href.exec = (e) => {
xrf xrf
@ -1128,8 +1131,10 @@ xrf.frag.href = function(v, opts){
let selected = (state) => () => { let selected = (state) => () => {
if( mesh.selected == state ) return // nothing changed if( mesh.selected == state ) return // nothing changed
if( mesh.material.uniforms ) mesh.material.uniforms.selected.value = state if( mesh.material ){
else mesh.material.color.r = mesh.material.color.g = mesh.material.color.b = state ? 2.0 : 1.0 if( mesh.material.uniforms ) mesh.material.uniforms.selected.value = state
else mesh.material.color.r = mesh.material.color.g = mesh.material.color.b = state ? 2.0 : 1.0
}
// update mouse cursor // update mouse cursor
if( !renderer.domElement.lastCursor ) if( !renderer.domElement.lastCursor )
renderer.domElement.lastCursor = renderer.domElement.style.cursor renderer.domElement.lastCursor = renderer.domElement.style.cursor
@ -1181,11 +1186,12 @@ const doPredefinedView = (opts) => {
const selectionOfInterest = (frag,scene,mesh) => { const selectionOfInterest = (frag,scene,mesh) => {
let id = frag.string let id = frag.string
// Selection of Interest if predefined_view matches object name if(!id) return id // important: ignore empty strings
if( mesh.selection ){ if( mesh.selection ){
scene.remove(mesh.selection) scene.remove(mesh.selection)
delete mesh.selection delete mesh.selection
} }
// Selection of Interest if predefined_view matches object name
if( id == mesh.name || id.substr(1) == mesh.userData.class ){ if( id == mesh.name || id.substr(1) == mesh.userData.class ){
xrf.emit('selection',{...opts,frag}) xrf.emit('selection',{...opts,frag})
.then( () => { .then( () => {
@ -1202,9 +1208,10 @@ const doPredefinedView = (opts) => {
} }
const predefinedView = (frag,scene,mesh) => { const predefinedView = (frag,scene,mesh) => {
let id = frag.string let id = frag.string
if( mesh.userData[`#${id}`] ){ if( !id ) return // prevent empty matches
let frag = xrf.URI.parse( mesh.userData[id], xrf.XRF.NAVIGATOR | xrf.XRF.PV_OVERRIDE | xrf.XRF.EMBEDDED ) if( mesh.userData[`#${id}`] ){ // get alias
frag = xrf.URI.parse( mesh.userData[`#${id}`], xrf.XRF.NAVIGATOR | xrf.XRF.PV_OVERRIDE | xrf.XRF.EMBEDDED )
for ( let k in frag ){ for ( let k in frag ){
let opts = {frag, model, camera: xrf.camera, scene: xrf.scene, renderer: xrf.renderer, THREE: xrf.THREE } let opts = {frag, model, camera: xrf.camera, scene: xrf.scene, renderer: xrf.renderer, THREE: xrf.THREE }
xrf.emit('predefinedView',{...opts,frag}) xrf.emit('predefinedView',{...opts,frag})
@ -1271,14 +1278,14 @@ xrf.frag.q = function(v, opts){
target.mesh.rotation.set(0,0,0) target.mesh.rotation.set(0,0,0)
} }
} }
// remove negative selectors // hide negative selectors
let remove = [] let negative = []
v.scene.traverse( (mesh) => { v.scene.traverse( (mesh) => {
for ( let i in v.query ) { for ( let i in v.query ) {
if( mesh.name == i && v.query[i].id === false ) remove.push(mesh) if( mesh.name == i && v.query[i].id === false ) negative.push(mesh)
} }
}) })
remove.map( (mesh) => mesh.parent.remove( mesh ) ) negative.map( (mesh) => mesh.visible = false )
} }
const showHide = () => { const showHide = () => {
@ -1326,7 +1333,7 @@ xrf.frag.src = function(v, opts){
xrf.eval.fragment(i, Object.assign(opts,{frag, model,scene})) xrf.eval.fragment(i, Object.assign(opts,{frag, model,scene}))
} }
if( frag.q.query ){ if( frag.q.query ){
let srcScene = frag.q.scene let srcScene = frag.q.scene // three/xrf/q.js initializes .scene
if( !srcScene || !srcScene.visible ) return if( !srcScene || !srcScene.visible ) return
console.log(" └ inserting "+i+" (srcScene)") console.log(" └ inserting "+i+" (srcScene)")
srcScene.position.set(0,0,0) srcScene.position.set(0,0,0)
@ -1334,6 +1341,7 @@ xrf.frag.src = function(v, opts){
srcScene.traverse( (m) => { srcScene.traverse( (m) => {
if( m.userData && (m.userData.src || m.userData.href) ) return ;//delete m.userData.src // prevent infinite recursion if( m.userData && (m.userData.src || m.userData.href) ) return ;//delete m.userData.src // prevent infinite recursion
xrf.eval.mesh(m,{scene,recursive:true}) xrf.eval.mesh(m,{scene,recursive:true})
m.name = mesh.name+"."+m.name // prefix meshname so predefined views don't affect objectnames anymore
}) })
if( srcScene.visible ) src.add( srcScene ) if( srcScene.visible ) src.add( srcScene )
} }

View File

@ -265,7 +265,7 @@ xrfragment_Parser.parse = function(key,value,resultMap) {
var xrfragment_Query = $hx_exports["xrfragment"]["Query"] = function(str) { var xrfragment_Query = $hx_exports["xrfragment"]["Query"] = function(str) {
this.isNumber = new EReg("^[0-9\\.]+$",""); this.isNumber = new EReg("^[0-9\\.]+$","");
this.isClass = new EReg("^[-]?class$",""); this.isClass = new EReg("^[-]?class$","");
this.isAddition = new EReg("^\\+",""); this.isRoot = new EReg("^/","");
this.isExclude = new EReg("^-",""); this.isExclude = new EReg("^-","");
this.isProp = new EReg("^.*:[><=!]?",""); this.isProp = new EReg("^.*:[><=!]?","");
this.q = { }; this.q = { };
@ -329,9 +329,6 @@ xrfragment_Query.prototype = {
if(_gthis.isExclude.match(k)) { if(_gthis.isExclude.match(k)) {
oper = "!="; oper = "!=";
k = HxOverrides.substr(k,1,null); k = HxOverrides.substr(k,1,null);
} else if(_gthis.isAddition.match(k)) {
oper = "+=";
k = HxOverrides.substr(k,1,null);
} else { } else {
v = HxOverrides.substr(v,oper.length,null); v = HxOverrides.substr(v,oper.length,null);
} }
@ -353,6 +350,12 @@ xrfragment_Query.prototype = {
} }
return; return;
} else { } else {
if(_gthis.isRoot.match(k)) {
str = HxOverrides.substr(k,1,null);
filter["root"] = true;
} else if(filter["root"] == true) {
Reflect.deleteField(filter,"root");
}
filter["id"] = _gthis.isExclude.match(str) ? false : true; filter["id"] = _gthis.isExclude.match(str) ? false : true;
var key = _gthis.isExclude.match(str) ? HxOverrides.substr(str,1,null) : str; var key = _gthis.isExclude.match(str) ? HxOverrides.substr(str,1,null) : str;
q[key] = filter; q[key] = filter;
@ -1066,7 +1069,7 @@ xrf.frag.href = function(v, opts){
quat: new THREE.Quaternion() quat: new THREE.Quaternion()
} }
// detect equirectangular image // detect equirectangular image
let texture = mesh.material.map let texture = mesh.material && mesh.material.map ? mesh.material.map : null
if( texture && texture.source.data.height == texture.source.data.width/2 ){ if( texture && texture.source.data.height == texture.source.data.width/2 ){
texture.mapping = THREE.ClampToEdgeWrapping texture.mapping = THREE.ClampToEdgeWrapping
texture.needsUpdate = true texture.needsUpdate = true
@ -1113,7 +1116,7 @@ xrf.frag.href = function(v, opts){
`, `,
}); });
mesh.material.needsUpdate = true mesh.material.needsUpdate = true
}else mesh.material = mesh.material.clone() }else if( mesh.material){ mesh.material = mesh.material.clone() }
let click = mesh.userData.XRF.href.exec = (e) => { let click = mesh.userData.XRF.href.exec = (e) => {
xrf xrf
@ -1128,8 +1131,10 @@ xrf.frag.href = function(v, opts){
let selected = (state) => () => { let selected = (state) => () => {
if( mesh.selected == state ) return // nothing changed if( mesh.selected == state ) return // nothing changed
if( mesh.material.uniforms ) mesh.material.uniforms.selected.value = state if( mesh.material ){
else mesh.material.color.r = mesh.material.color.g = mesh.material.color.b = state ? 2.0 : 1.0 if( mesh.material.uniforms ) mesh.material.uniforms.selected.value = state
else mesh.material.color.r = mesh.material.color.g = mesh.material.color.b = state ? 2.0 : 1.0
}
// update mouse cursor // update mouse cursor
if( !renderer.domElement.lastCursor ) if( !renderer.domElement.lastCursor )
renderer.domElement.lastCursor = renderer.domElement.style.cursor renderer.domElement.lastCursor = renderer.domElement.style.cursor
@ -1181,11 +1186,12 @@ const doPredefinedView = (opts) => {
const selectionOfInterest = (frag,scene,mesh) => { const selectionOfInterest = (frag,scene,mesh) => {
let id = frag.string let id = frag.string
// Selection of Interest if predefined_view matches object name if(!id) return id // important: ignore empty strings
if( mesh.selection ){ if( mesh.selection ){
scene.remove(mesh.selection) scene.remove(mesh.selection)
delete mesh.selection delete mesh.selection
} }
// Selection of Interest if predefined_view matches object name
if( id == mesh.name || id.substr(1) == mesh.userData.class ){ if( id == mesh.name || id.substr(1) == mesh.userData.class ){
xrf.emit('selection',{...opts,frag}) xrf.emit('selection',{...opts,frag})
.then( () => { .then( () => {
@ -1202,9 +1208,10 @@ const doPredefinedView = (opts) => {
} }
const predefinedView = (frag,scene,mesh) => { const predefinedView = (frag,scene,mesh) => {
let id = frag.string let id = frag.string
if( mesh.userData[`#${id}`] ){ if( !id ) return // prevent empty matches
let frag = xrf.URI.parse( mesh.userData[id], xrf.XRF.NAVIGATOR | xrf.XRF.PV_OVERRIDE | xrf.XRF.EMBEDDED ) if( mesh.userData[`#${id}`] ){ // get alias
frag = xrf.URI.parse( mesh.userData[`#${id}`], xrf.XRF.NAVIGATOR | xrf.XRF.PV_OVERRIDE | xrf.XRF.EMBEDDED )
for ( let k in frag ){ for ( let k in frag ){
let opts = {frag, model, camera: xrf.camera, scene: xrf.scene, renderer: xrf.renderer, THREE: xrf.THREE } let opts = {frag, model, camera: xrf.camera, scene: xrf.scene, renderer: xrf.renderer, THREE: xrf.THREE }
xrf.emit('predefinedView',{...opts,frag}) xrf.emit('predefinedView',{...opts,frag})
@ -1271,14 +1278,14 @@ xrf.frag.q = function(v, opts){
target.mesh.rotation.set(0,0,0) target.mesh.rotation.set(0,0,0)
} }
} }
// remove negative selectors // hide negative selectors
let remove = [] let negative = []
v.scene.traverse( (mesh) => { v.scene.traverse( (mesh) => {
for ( let i in v.query ) { for ( let i in v.query ) {
if( mesh.name == i && v.query[i].id === false ) remove.push(mesh) if( mesh.name == i && v.query[i].id === false ) negative.push(mesh)
} }
}) })
remove.map( (mesh) => mesh.parent.remove( mesh ) ) negative.map( (mesh) => mesh.visible = false )
} }
const showHide = () => { const showHide = () => {
@ -1326,7 +1333,7 @@ xrf.frag.src = function(v, opts){
xrf.eval.fragment(i, Object.assign(opts,{frag, model,scene})) xrf.eval.fragment(i, Object.assign(opts,{frag, model,scene}))
} }
if( frag.q.query ){ if( frag.q.query ){
let srcScene = frag.q.scene let srcScene = frag.q.scene // three/xrf/q.js initializes .scene
if( !srcScene || !srcScene.visible ) return if( !srcScene || !srcScene.visible ) return
console.log(" └ inserting "+i+" (srcScene)") console.log(" └ inserting "+i+" (srcScene)")
srcScene.position.set(0,0,0) srcScene.position.set(0,0,0)
@ -1334,6 +1341,7 @@ xrf.frag.src = function(v, opts){
srcScene.traverse( (m) => { srcScene.traverse( (m) => {
if( m.userData && (m.userData.src || m.userData.href) ) return ;//delete m.userData.src // prevent infinite recursion if( m.userData && (m.userData.src || m.userData.href) ) return ;//delete m.userData.src // prevent infinite recursion
xrf.eval.mesh(m,{scene,recursive:true}) xrf.eval.mesh(m,{scene,recursive:true})
m.name = mesh.name+"."+m.name // prefix meshname so predefined views don't affect objectnames anymore
}) })
if( srcScene.visible ) src.add( srcScene ) if( srcScene.visible ) src.add( srcScene )
} }

View File

@ -16,7 +16,8 @@ class Test {
static public function main():Void { static public function main():Void {
test( Spec.load("src/spec/url.json") ); test( Spec.load("src/spec/url.json") );
test( Spec.load("src/spec/query.class.json") ); test( Spec.load("src/spec/query.selectors.json") );
test( Spec.load("src/spec/query.root.json") );
test( Spec.load("src/spec/query.rules.json") ); test( Spec.load("src/spec/query.rules.json") );
//test( Spec.load("src/spec/tmp.json") ); //test( Spec.load("src/spec/tmp.json") );
if( errors > 1 ) trace("\n-----\n[ ] "+errors+" errors :/"); if( errors > 1 ) trace("\n-----\n[ ] "+errors+" errors :/");
@ -43,6 +44,10 @@ class Test {
if( item.expect.fn == "equal.xy" ) valid = equalXY(res,item); if( item.expect.fn == "equal.xy" ) valid = equalXY(res,item);
if( item.expect.fn == "equal.xyz" ) valid = equalXYZ(res,item); if( item.expect.fn == "equal.xyz" ) valid = equalXYZ(res,item);
if( item.expect.fn == "equal.multi" ) valid = equalMulti(res, item); if( item.expect.fn == "equal.multi" ) valid = equalMulti(res, item);
if( item.expect.fn == "testQueryRoot" ){
if( !item.expect.out ) valid = !q.get()[ item.expect.input[0] ].root;
else valid = item.expect.out == q.get()[ item.expect.input[0] ].root;
}
var ok:String = valid ? "[ ] " : "[ ] "; var ok:String = valid ? "[ ] " : "[ ] ";
trace( ok + item.fn + ": '" + item.data + "'" + (item.label ? " (" + (item.label?item.label:item.expect.fn) +")" : "")); trace( ok + item.fn + ": '" + item.data + "'" + (item.label ? " (" + (item.label?item.label:item.expect.fn) +")" : ""));
if( !valid ) errors += 1; if( !valid ) errors += 1;

2
src/spec/query.root.json Normal file
View File

@ -0,0 +1,2 @@
[
]

View File

@ -10,5 +10,7 @@
{"fn":"query","data":".foo -.foo bar:>5 .foo", "expect":{ "fn":"testProperty","input":["class","foo"],"out":true},"label":"class:foo"}, {"fn":"query","data":".foo -.foo bar:>5 .foo", "expect":{ "fn":"testProperty","input":["class","foo"],"out":true},"label":"class:foo"},
{"fn":"query","data":".foo -.foo .foo", "expect":{ "fn":"testProperty","input":["class","foo"],"out":true},"label":"class:foo"}, {"fn":"query","data":".foo -.foo .foo", "expect":{ "fn":"testProperty","input":["class","foo"],"out":true},"label":"class:foo"},
{"fn":"query","data":".foo -.foo .foo", "expect":{ "fn":"testProperty","input":["id","foo"],"out":false},"label":"!id:foo"}, {"fn":"query","data":".foo -.foo .foo", "expect":{ "fn":"testProperty","input":["id","foo"],"out":false},"label":"!id:foo"},
{"fn":"query","data":"foo -foo foo", "expect":{ "fn":"testProperty","input":["id","foo"],"out":true},"label":"id:foo?"} {"fn":"query","data":"foo -foo foo", "expect":{ "fn":"testProperty","input":["id","foo"],"out":true},"label":"id:foo?"},
{"fn":"query","data":"/foo", "expect":{ "fn":"testQueryRoot","input":["foo"],"out":true},"label":"foo should be root-only"},
{"fn":"query","data":"/foo foo", "expect":{ "fn":"testQueryRoot","input":["foo"],"out":false},"label":"foo should recursively selected"}
] ]

View File

@ -44,7 +44,7 @@ class Query {
private var q:haxe.DynamicAccess<Dynamic> = {}; private var q:haxe.DynamicAccess<Dynamic> = {};
private var isProp:EReg = ~/^.*:[><=!]?/; private var isProp:EReg = ~/^.*:[><=!]?/;
private var isExclude:EReg = ~/^-/; private var isExclude:EReg = ~/^-/;
private var isAddition:EReg = ~/^\+/; private var isRoot:EReg = ~/^\//;
private var isClass:EReg = ~/^[-]?class$/; private var isClass:EReg = ~/^[-]?class$/;
private var isNumber:EReg = ~/^[0-9\.]+$/; private var isNumber:EReg = ~/^[0-9\.]+$/;
@ -89,13 +89,9 @@ class Query {
if( str.indexOf("<=") != -1 ) oper = "<="; if( str.indexOf("<=") != -1 ) oper = "<=";
if( isExclude.match(k) ){ if( isExclude.match(k) ){
oper = "!="; oper = "!=";
k = k.substr(1); // convert "-foo" into "foo" k = k.substr(1); // convert "-foo" into "foo"
}else if( isAddition.match(k) ){
oper = "+=";
k = k.substr(1); // convert "+foo" into "foo"
}else v = v.substr(oper.length); // change ">=foo" into "foo" (strip operator) }else v = v.substr(oper.length); // change ">=foo" into "foo" (strip operator)
if( oper.length == 0 ) oper = "="; if( oper.length == 0 ) oper = "=";
if( isClass.match(k) ){ if( isClass.match(k) ){
filter[ prefix+ k ] = oper != "!="; filter[ prefix+ k ] = oper != "!=";
q.set(v,filter); q.set(v,filter);
@ -108,6 +104,10 @@ class Query {
} }
return; return;
}else{ // id }else{ // id
if( isRoot.match(k) ){
str = k.substr(1); // convert "/foo" to "foo"
filter[ "root" ] = true;
}else if( filter[ "root" ] == true ) filter.remove("root"); // undo root-only
filter[ "id" ] = isExclude.match(str) ? false: true; filter[ "id" ] = isExclude.match(str) ? false: true;
q.set( (isExclude.match(str) ? str.substr(1) : str ) ,filter ); q.set( (isExclude.match(str) ? str.substr(1) : str ) ,filter );
} }