Merge branch 'feat/non-euclidian'
This commit is contained in:
commit
12937d5b88
117 changed files with 371997 additions and 16470 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
|||
dist/*.pyc
|
||||
src/spec/tmp.json
|
||||
tags
|
||||
example/assets/*.blend
|
||||
|
|
|
|||
4
.vimrc
4
.vimrc
|
|
@ -1,4 +1,4 @@
|
|||
noremap <silent> <F8> :!haxe --no-output %<CR>
|
||||
noremap <silent> <F9> :!./make build_js<CR>
|
||||
noremap <silent> <F10> :!./make && echo OK && ./make tests<CR>
|
||||
noremap <silent> <F9> :!./make build js<CR>
|
||||
noremap <silent> <F10> :!./make build && ./make tests<CR>
|
||||
noremap <silent> <F11> :!./make tests \| less<CR>
|
||||
|
|
|
|||
|
|
@ -37,6 +37,10 @@ Pre-build libraries can be found in [/dist folder](dist)<br>
|
|||
If you really want to build from source:
|
||||
|
||||
```
|
||||
$ ./make install
|
||||
$ ./make build && ./make runtest
|
||||
$ nix-shell # nix-users: drops you into a dev-ready shell
|
||||
$ ./make install # debian-users: install deps via apt-get
|
||||
$ ./make build && ./make tests
|
||||
```
|
||||
|
||||
> NOTE #1: to rebundle the THREE/AFRAME javascripts during dev run `./make build js`
|
||||
> NOTE #2: to regenerate the parser in various languages (via haxe), run `./make build parser`
|
||||
|
|
|
|||
21
dist/utils.js
vendored
21
dist/utils.js
vendored
|
|
@ -267,7 +267,7 @@ function notify(scope){
|
|||
if( str.match(/error/g) ) opts.status = "danger"
|
||||
if( str.match(/warning/g) ) opts.status = "warning"
|
||||
}
|
||||
opts = Object.assign({ message: str , status, timeout:2000 },opts)
|
||||
opts = Object.assign({ message: str , status, timeout:4000 },opts)
|
||||
SnackBar( opts )
|
||||
}
|
||||
}
|
||||
|
|
@ -285,12 +285,25 @@ function download(){
|
|||
}
|
||||
|
||||
function embed(){
|
||||
// *TODO* this should be part of the XRF framework
|
||||
let camera = document.querySelector('[camera]').object3D.parent // *TODO* fix for threejs
|
||||
// *TODO* this should be part of the XRF Threejs framework
|
||||
if( typeof THREE == 'undefined' ) THREE = xrf.THREE
|
||||
let radToDeg = THREE.MathUtils.radToDeg
|
||||
let toDeg = (x) => x / (Math.PI / 180)
|
||||
let camera = document.querySelector('[camera]').object3D.parent // *TODO* fix for threejs
|
||||
|
||||
// *TODO* add camera direction
|
||||
let direction = new xrf.THREE.Vector3()
|
||||
camera.getWorldDirection(direction)
|
||||
const pitch = Math.asin(direction.y);
|
||||
const yaw = Math.atan2(direction.x, direction.z);
|
||||
const pitchInDegrees = pitch * 180 / Math.PI;
|
||||
const yawInDegrees = yaw * 180 / Math.PI;
|
||||
|
||||
let lastPos = `pos=${camera.position.x.toFixed(2)},${camera.position.y.toFixed(2)},${camera.position.z.toFixed(2)}`
|
||||
let newHash = document.location.hash.replace(/[&]?pos=[0-9\.-]+,[0-9\.-]+,[0-9\.-]+/,'')
|
||||
let newHash = document.location.hash.replace(/[&]?(pos|rot)=[0-9\.-]+,[0-9\.-]+,[0-9\.-]+/,'')
|
||||
newHash += `&${lastPos}`
|
||||
document.location.hash = newHash.replace(/&&/,'&')
|
||||
.replace(/#&/,'')
|
||||
// copy url to clipboard
|
||||
var dummy = document.createElement('input'),
|
||||
text = window.location.href;
|
||||
|
|
|
|||
2672
dist/xrfragment.aframe.js
vendored
2672
dist/xrfragment.aframe.js
vendored
File diff suppressed because one or more lines are too long
339
dist/xrfragment.js
vendored
339
dist/xrfragment.js
vendored
|
|
@ -72,6 +72,20 @@ Reflect.deleteField = function(o,field) {
|
|||
delete(o[field]);
|
||||
return true;
|
||||
};
|
||||
Reflect.copy = function(o) {
|
||||
if(o == null) {
|
||||
return null;
|
||||
}
|
||||
var o2 = { };
|
||||
var _g = 0;
|
||||
var _g1 = Reflect.fields(o);
|
||||
while(_g < _g1.length) {
|
||||
var f = _g1[_g];
|
||||
++_g;
|
||||
o2[f] = Reflect.field(o,f);
|
||||
}
|
||||
return o2;
|
||||
};
|
||||
var Std = function() { };
|
||||
Std.__name__ = true;
|
||||
Std.string = function(s) {
|
||||
|
|
@ -209,86 +223,22 @@ js_Boot.__string_rec = function(o,s) {
|
|||
return String(o);
|
||||
}
|
||||
};
|
||||
var xrfragment_Parser = $hx_exports["xrfragment"]["Parser"] = function() { };
|
||||
xrfragment_Parser.__name__ = true;
|
||||
xrfragment_Parser.parse = function(key,value,store) {
|
||||
var Frag_h = Object.create(null);
|
||||
Frag_h["#"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_PREDEFINED_VIEW | xrfragment_XRF.PV_EXECUTE;
|
||||
Frag_h["prio"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_INT;
|
||||
Frag_h["src"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL;
|
||||
Frag_h["href"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL | xrfragment_XRF.T_PREDEFINED_VIEW;
|
||||
Frag_h["tag"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING;
|
||||
Frag_h["pos"] = xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_VECTOR3 | xrfragment_XRF.T_STRING_OBJ | xrfragment_XRF.METADATA | xrfragment_XRF.NAVIGATOR;
|
||||
Frag_h["q"] = xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING | xrfragment_XRF.METADATA;
|
||||
Frag_h["scale"] = xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_VECTOR3 | xrfragment_XRF.METADATA;
|
||||
Frag_h["rot"] = xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_VECTOR3 | xrfragment_XRF.METADATA | xrfragment_XRF.NAVIGATOR;
|
||||
Frag_h["mov"] = xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_VECTOR3 | xrfragment_XRF.METADATA;
|
||||
Frag_h["show"] = xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_INT | xrfragment_XRF.METADATA;
|
||||
Frag_h["env"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING | xrfragment_XRF.METADATA;
|
||||
Frag_h["t"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_VECTOR2 | xrfragment_XRF.NAVIGATOR | xrfragment_XRF.METADATA;
|
||||
Frag_h["gravity"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR3 | xrfragment_XRF.METADATA;
|
||||
Frag_h["physics"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR3 | xrfragment_XRF.METADATA;
|
||||
Frag_h["fov"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_INT | xrfragment_XRF.NAVIGATOR | xrfragment_XRF.METADATA;
|
||||
Frag_h["clip"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR2 | xrfragment_XRF.NAVIGATOR | xrfragment_XRF.METADATA;
|
||||
Frag_h["fog"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR2 | xrfragment_XRF.NAVIGATOR | xrfragment_XRF.METADATA;
|
||||
Frag_h["bg"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR3 | xrfragment_XRF.NAVIGATOR | xrfragment_XRF.METADATA;
|
||||
Frag_h["namespace"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING;
|
||||
Frag_h["SPDX"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING;
|
||||
Frag_h["unit"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING;
|
||||
Frag_h["description"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING;
|
||||
Frag_h["session"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.NAVIGATOR | xrfragment_XRF.METADATA | xrfragment_XRF.PROMPT;
|
||||
var isPVDynamic = value.length == 0 && key.length > 0 && !Object.prototype.hasOwnProperty.call(Frag_h,key);
|
||||
var isPVDefault = value.length == 0 && key.length > 0 && key == "#";
|
||||
if(isPVDynamic) {
|
||||
var v = new xrfragment_XRF(key,xrfragment_XRF.PV_EXECUTE | xrfragment_XRF.NAVIGATOR);
|
||||
v.validate(key);
|
||||
store[key] = v;
|
||||
return true;
|
||||
}
|
||||
if(key.split(".").length > 1 && value.split(".").length > 1) {
|
||||
store[key] = new xrfragment_XRF(key,xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING | xrfragment_XRF.PROP_BIND);
|
||||
return true;
|
||||
}
|
||||
var v = new xrfragment_XRF(key,Frag_h[key]);
|
||||
if(Object.prototype.hasOwnProperty.call(Frag_h,key)) {
|
||||
if(!v.validate(value)) {
|
||||
console.log("src/xrfragment/Parser.hx:83:","⚠ fragment '" + key + "' has incompatible value (" + value + ")");
|
||||
return false;
|
||||
}
|
||||
store[key] = v;
|
||||
if(xrfragment_Parser.debug) {
|
||||
console.log("src/xrfragment/Parser.hx:87:","✔ " + key + ": " + v.string);
|
||||
}
|
||||
} else {
|
||||
if(typeof(value) == "string") {
|
||||
v.guessType(v,value);
|
||||
}
|
||||
v.noXRF = true;
|
||||
store[key] = v;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
var xrfragment_Query = $hx_exports["xrfragment"]["Query"] = function(str) {
|
||||
this.isNumber = new EReg("^[0-9\\.]+$","");
|
||||
this.isRoot = new EReg("^[-]?/","");
|
||||
this.isExclude = new EReg("^-","");
|
||||
this.isProp = new EReg("^.*:[><=!]?","");
|
||||
var xrfragment_Filter = $hx_exports["xrfragment"]["Filter"] = function(str) {
|
||||
this.q = { };
|
||||
this.str = "";
|
||||
if(str != null) {
|
||||
this.parse(str);
|
||||
}
|
||||
};
|
||||
xrfragment_Query.__name__ = true;
|
||||
xrfragment_Query.prototype = {
|
||||
xrfragment_Filter.__name__ = true;
|
||||
xrfragment_Filter.prototype = {
|
||||
toObject: function() {
|
||||
return this.q;
|
||||
return Reflect.copy(this.q);
|
||||
}
|
||||
,get: function() {
|
||||
return this.q;
|
||||
return Reflect.copy(this.q);
|
||||
}
|
||||
,parse: function(str) {
|
||||
var _gthis = this;
|
||||
var token = str.split(" ");
|
||||
var q = { };
|
||||
var process = function(str,prefix) {
|
||||
|
|
@ -296,59 +246,42 @@ xrfragment_Query.prototype = {
|
|||
prefix = "";
|
||||
}
|
||||
str = StringTools.trim(str);
|
||||
var k = str.split(":")[0];
|
||||
var v = str.split(":")[1];
|
||||
var k = str.split("=")[0];
|
||||
var v = str.split("=")[1];
|
||||
var filter = { };
|
||||
if(q[prefix + k]) {
|
||||
filter = q[prefix + k];
|
||||
}
|
||||
filter["rules"] = filter["rules"] != null ? filter["rules"] : [];
|
||||
if(_gthis.isProp.match(str)) {
|
||||
if(xrfragment_XRF.isProp.match(str)) {
|
||||
var oper = "";
|
||||
if(str.indexOf("*") != -1) {
|
||||
oper = "*";
|
||||
}
|
||||
if(str.indexOf(">") != -1) {
|
||||
oper = ">";
|
||||
}
|
||||
if(str.indexOf("<") != -1) {
|
||||
oper = "<";
|
||||
}
|
||||
if(str.indexOf(">=") != -1) {
|
||||
oper = ">=";
|
||||
}
|
||||
if(str.indexOf("<=") != -1) {
|
||||
oper = "<=";
|
||||
}
|
||||
if(_gthis.isExclude.match(k)) {
|
||||
oper = "!=";
|
||||
if(xrfragment_XRF.isExclude.match(k)) {
|
||||
k = HxOverrides.substr(k,1,null);
|
||||
} else {
|
||||
v = HxOverrides.substr(v,oper.length,null);
|
||||
}
|
||||
v = HxOverrides.substr(v,oper.length,null);
|
||||
if(oper.length == 0) {
|
||||
oper = "=";
|
||||
}
|
||||
var rule = { };
|
||||
if(_gthis.isNumber.match(v)) {
|
||||
if(xrfragment_XRF.isNumber.match(v)) {
|
||||
rule[oper] = parseFloat(v);
|
||||
} else {
|
||||
rule[oper] = v;
|
||||
}
|
||||
filter["rules"].push(rule);
|
||||
q[k] = filter;
|
||||
return;
|
||||
} else {
|
||||
filter["id"] = _gthis.isExclude.match(str) ? false : true;
|
||||
filter["root"] = _gthis.isRoot.match(str);
|
||||
if(_gthis.isExclude.match(str)) {
|
||||
str = HxOverrides.substr(str,1,null);
|
||||
}
|
||||
if(_gthis.isRoot.match(str)) {
|
||||
str = HxOverrides.substr(str,1,null);
|
||||
}
|
||||
q[str] = filter;
|
||||
q["expr"] = rule;
|
||||
}
|
||||
var value = xrfragment_XRF.isDeep.match(str) ? k.split("*").length - 1 : 0;
|
||||
q["deep"] = value;
|
||||
var value = xrfragment_XRF.isExclude.match(str) ? false : true;
|
||||
q["show"] = value;
|
||||
var value = k.replace(xrfragment_XRF.operators.r,"");
|
||||
q["key"] = value;
|
||||
q["value"] = v;
|
||||
};
|
||||
var _g = 0;
|
||||
var _g1 = token.length;
|
||||
|
|
@ -397,49 +330,75 @@ xrfragment_Query.prototype = {
|
|||
return v[property];
|
||||
}
|
||||
}
|
||||
var _g = 0;
|
||||
var _g1 = Reflect.fields(this.q);
|
||||
while(_g < _g1.length) {
|
||||
var k = _g1[_g];
|
||||
++_g;
|
||||
var filter = Reflect.field(this.q,k);
|
||||
if(filter.rules == null) {
|
||||
continue;
|
||||
}
|
||||
var rules = filter.rules;
|
||||
var _g2 = 0;
|
||||
while(_g2 < rules.length) {
|
||||
var rule = rules[_g2];
|
||||
++_g2;
|
||||
if(exclude) {
|
||||
if(Reflect.field(rule,"!=") != null && testprop((value == null ? "null" : "" + value) == Std.string(Reflect.field(rule,"!="))) && exclude) {
|
||||
++qualify;
|
||||
}
|
||||
} else {
|
||||
if(Reflect.field(rule,"*") != null && testprop(parseFloat(value) != null)) {
|
||||
++qualify;
|
||||
}
|
||||
if(Reflect.field(rule,">") != null && testprop(parseFloat(value) > parseFloat(Reflect.field(rule,">")))) {
|
||||
++qualify;
|
||||
}
|
||||
if(Reflect.field(rule,"<") != null && testprop(parseFloat(value) < parseFloat(Reflect.field(rule,"<")))) {
|
||||
++qualify;
|
||||
}
|
||||
if(Reflect.field(rule,">=") != null && testprop(parseFloat(value) >= parseFloat(Reflect.field(rule,">=")))) {
|
||||
++qualify;
|
||||
}
|
||||
if(Reflect.field(rule,"<=") != null && testprop(parseFloat(value) <= parseFloat(Reflect.field(rule,"<=")))) {
|
||||
++qualify;
|
||||
}
|
||||
if(Reflect.field(rule,"=") != null && (testprop(value == Reflect.field(rule,"=")) || testprop(parseFloat(value) == parseFloat(Reflect.field(rule,"="))))) {
|
||||
++qualify;
|
||||
}
|
||||
if(Reflect.field(this.q,"expr")) {
|
||||
var f = Reflect.field(this.q,"expr");
|
||||
if(!Reflect.field(this.q,"show")) {
|
||||
if(Reflect.field(f,"!=") != null && testprop((value == null ? "null" : "" + value) == Std.string(Reflect.field(f,"!="))) && exclude) {
|
||||
++qualify;
|
||||
}
|
||||
} else {
|
||||
if(Reflect.field(f,"*") != null && testprop(parseFloat(value) != null)) {
|
||||
++qualify;
|
||||
}
|
||||
if(Reflect.field(f,">") != null && testprop(parseFloat(value) >= parseFloat(Reflect.field(f,">")))) {
|
||||
++qualify;
|
||||
}
|
||||
if(Reflect.field(f,"<") != null && testprop(parseFloat(value) <= parseFloat(Reflect.field(f,"<")))) {
|
||||
++qualify;
|
||||
}
|
||||
if(Reflect.field(f,"=") != null && (testprop(value == Reflect.field(f,"=")) || testprop(parseFloat(value) == parseFloat(Reflect.field(f,"="))))) {
|
||||
++qualify;
|
||||
}
|
||||
}
|
||||
}
|
||||
return qualify > 0;
|
||||
}
|
||||
};
|
||||
var xrfragment_Parser = $hx_exports["xrfragment"]["Parser"] = function() { };
|
||||
xrfragment_Parser.__name__ = true;
|
||||
xrfragment_Parser.parse = function(key,value,store,index) {
|
||||
var Frag_h = Object.create(null);
|
||||
Frag_h["#"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_PREDEFINED_VIEW | xrfragment_XRF.PV_EXECUTE;
|
||||
Frag_h["src"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL;
|
||||
Frag_h["href"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL | xrfragment_XRF.T_PREDEFINED_VIEW;
|
||||
Frag_h["tag"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING;
|
||||
Frag_h["pos"] = xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR3 | xrfragment_XRF.T_STRING | xrfragment_XRF.T_STRING_OBJ | xrfragment_XRF.METADATA | xrfragment_XRF.NAVIGATOR;
|
||||
Frag_h["rot"] = xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR3 | xrfragment_XRF.METADATA | xrfragment_XRF.NAVIGATOR;
|
||||
Frag_h["t"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_FLOAT | xrfragment_XRF.T_VECTOR2 | xrfragment_XRF.T_STRING | xrfragment_XRF.NAVIGATOR | xrfragment_XRF.METADATA;
|
||||
Frag_h["tv"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_FLOAT | xrfragment_XRF.T_VECTOR2 | xrfragment_XRF.T_VECTOR3 | xrfragment_XRF.NAVIGATOR | xrfragment_XRF.METADATA;
|
||||
Frag_h["namespace"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING;
|
||||
Frag_h["SPDX"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING;
|
||||
Frag_h["unit"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING;
|
||||
Frag_h["description"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING;
|
||||
Frag_h["session"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.NAVIGATOR | xrfragment_XRF.METADATA | xrfragment_XRF.PROMPT;
|
||||
var keyStripped = key.replace(xrfragment_XRF.operators.r,"");
|
||||
var isPVDynamic = key.length > 0 && !Object.prototype.hasOwnProperty.call(Frag_h,key);
|
||||
var isPVDefault = value.length == 0 && key.length > 0 && key == "#";
|
||||
if(isPVDynamic) {
|
||||
var v = new xrfragment_XRF(key,xrfragment_XRF.PV_EXECUTE | xrfragment_XRF.NAVIGATOR,index);
|
||||
v.validate(value);
|
||||
store[keyStripped] = v;
|
||||
return true;
|
||||
}
|
||||
var v = new xrfragment_XRF(key,Frag_h[key],index);
|
||||
if(Object.prototype.hasOwnProperty.call(Frag_h,key)) {
|
||||
if(!v.validate(value)) {
|
||||
console.log("src/xrfragment/Parser.hx:66:","⚠ fragment '" + key + "' has incompatible value (" + value + ")");
|
||||
return false;
|
||||
}
|
||||
store[keyStripped] = v;
|
||||
if(xrfragment_Parser.debug) {
|
||||
console.log("src/xrfragment/Parser.hx:70:","✔ " + key + ": " + v.string);
|
||||
}
|
||||
} else {
|
||||
if(typeof(value) == "string") {
|
||||
v.guessType(v,value);
|
||||
}
|
||||
v.noXRF = true;
|
||||
store[keyStripped] = v;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
var xrfragment_URI = $hx_exports["xrfragment"]["URI"] = function() { };
|
||||
xrfragment_URI.__name__ = true;
|
||||
xrfragment_URI.parse = function(url,filter) {
|
||||
|
|
@ -461,7 +420,7 @@ xrfragment_URI.parse = function(url,filter) {
|
|||
var s = regexPlus.split(splitByEqual[1]).join(" ");
|
||||
value = decodeURIComponent(s.split("+").join(" "));
|
||||
}
|
||||
var ok = xrfragment_Parser.parse(key,value,store);
|
||||
var ok = xrfragment_Parser.parse(key,value,store,i);
|
||||
}
|
||||
if(filter != null && filter != 0) {
|
||||
var _g = 0;
|
||||
|
|
@ -477,9 +436,10 @@ xrfragment_URI.parse = function(url,filter) {
|
|||
}
|
||||
return store;
|
||||
};
|
||||
var xrfragment_XRF = $hx_exports["xrfragment"]["XRF"] = function(_fragment,_flags) {
|
||||
var xrfragment_XRF = $hx_exports["xrfragment"]["XRF"] = function(_fragment,_flags,_index) {
|
||||
this.fragment = _fragment;
|
||||
this.flags = _flags;
|
||||
this.index = _index;
|
||||
};
|
||||
xrfragment_XRF.__name__ = true;
|
||||
xrfragment_XRF.set = function(flag,flags) {
|
||||
|
|
@ -490,68 +450,58 @@ xrfragment_XRF.unset = function(flag,flags) {
|
|||
};
|
||||
xrfragment_XRF.prototype = {
|
||||
is: function(flag) {
|
||||
var v = this.flags;
|
||||
if(!(typeof(v) == "number" && ((v | 0) === v))) {
|
||||
this.flags = 0;
|
||||
}
|
||||
return (this.flags & flag) != 0;
|
||||
}
|
||||
,validate: function(value) {
|
||||
this.guessType(this,value);
|
||||
if(value.split("|").length > 1) {
|
||||
this.args = [];
|
||||
var args = value.split("|");
|
||||
var _g = 0;
|
||||
var _g1 = args.length;
|
||||
while(_g < _g1) {
|
||||
var i = _g++;
|
||||
var x = new xrfragment_XRF(this.fragment,this.flags);
|
||||
this.guessType(x,args[i]);
|
||||
this.args.push(x);
|
||||
}
|
||||
}
|
||||
if(this.fragment == "q") {
|
||||
this.query = new xrfragment_Query(value).get();
|
||||
}
|
||||
var ok = true;
|
||||
if(!((this.args) instanceof Array)) {
|
||||
if(this.is(xrfragment_XRF.T_VECTOR3) && !(typeof(this.x) == "number" && typeof(this.y) == "number" && typeof(this.z) == "number")) {
|
||||
ok = false;
|
||||
}
|
||||
if(this.is(xrfragment_XRF.T_VECTOR2) && !(typeof(this.x) == "number" && typeof(this.y) == "number")) {
|
||||
ok = false;
|
||||
}
|
||||
var tmp;
|
||||
if(this.is(xrfragment_XRF.T_INT)) {
|
||||
var v = this.int;
|
||||
tmp = !(typeof(v) == "number" && ((v | 0) === v));
|
||||
} else {
|
||||
tmp = false;
|
||||
}
|
||||
if(tmp) {
|
||||
ok = false;
|
||||
}
|
||||
if(!this.is(xrfragment_XRF.T_FLOAT) && this.is(xrfragment_XRF.T_VECTOR2) && !(typeof(this.x) == "number" && typeof(this.y) == "number")) {
|
||||
ok = false;
|
||||
}
|
||||
if(!(this.is(xrfragment_XRF.T_VECTOR2) || this.is(xrfragment_XRF.T_STRING)) && this.is(xrfragment_XRF.T_VECTOR3) && !(typeof(this.x) == "number" && typeof(this.y) == "number" && typeof(this.z) == "number")) {
|
||||
ok = false;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
,guessType: function(v,str) {
|
||||
v.string = str;
|
||||
if(str.split(",").length > 1) {
|
||||
var xyz = str.split(",");
|
||||
if(xyz.length > 0) {
|
||||
v.x = parseFloat(xyz[0]);
|
||||
}
|
||||
if(xyz.length > 1) {
|
||||
v.y = parseFloat(xyz[1]);
|
||||
}
|
||||
if(xyz.length > 2) {
|
||||
v.z = parseFloat(xyz[2]);
|
||||
}
|
||||
if(typeof(str) != "string") {
|
||||
return;
|
||||
}
|
||||
if(xrfragment_XRF.isColor.match(str)) {
|
||||
v.color = str;
|
||||
}
|
||||
if(xrfragment_XRF.isFloat.match(str)) {
|
||||
v.float = parseFloat(str);
|
||||
}
|
||||
if(xrfragment_XRF.isInt.match(str)) {
|
||||
v.int = Std.parseInt(str);
|
||||
if(str.length > 0) {
|
||||
if(str.split(",").length > 1) {
|
||||
var xyzw = str.split(",");
|
||||
if(xyzw.length > 0) {
|
||||
v.x = parseFloat(xyzw[0]);
|
||||
}
|
||||
if(xyzw.length > 1) {
|
||||
v.y = parseFloat(xyzw[1]);
|
||||
}
|
||||
if(xyzw.length > 2) {
|
||||
v.z = parseFloat(xyzw[2]);
|
||||
}
|
||||
if(xyzw.length > 3) {
|
||||
v.w = parseFloat(xyzw[3]);
|
||||
}
|
||||
}
|
||||
if(xrfragment_XRF.isColor.match(str)) {
|
||||
v.color = str;
|
||||
}
|
||||
if(xrfragment_XRF.isFloat.match(str)) {
|
||||
v.x = parseFloat(str);
|
||||
v.float = v.x;
|
||||
}
|
||||
if(xrfragment_XRF.isInt.match(str)) {
|
||||
v.int = Std.parseInt(str);
|
||||
v.x = v.int;
|
||||
}
|
||||
v.filter = new xrfragment_Filter(v.fragment + "=" + v.string);
|
||||
} else {
|
||||
v.filter = new xrfragment_Filter(v.fragment);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -583,11 +533,16 @@ xrfragment_XRF.T_STRING = 1048576;
|
|||
xrfragment_XRF.T_STRING_OBJ = 2097152;
|
||||
xrfragment_XRF.T_STRING_OBJ_PROP = 4194304;
|
||||
xrfragment_XRF.isColor = new EReg("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$","");
|
||||
xrfragment_XRF.isInt = new EReg("^[0-9]+$","");
|
||||
xrfragment_XRF.isFloat = new EReg("^[0-9]+\\.[0-9]+$","");
|
||||
xrfragment_XRF.isInt = new EReg("^[-0-9]+$","");
|
||||
xrfragment_XRF.isFloat = new EReg("^[-0-9]+\\.[0-9]+$","");
|
||||
xrfragment_XRF.isVector = new EReg("([,]+|\\w)","");
|
||||
xrfragment_XRF.isUrl = new EReg("(://)?\\..*","");
|
||||
xrfragment_XRF.isUrlOrPretypedView = new EReg("(^#|://)?\\..*","");
|
||||
xrfragment_XRF.isString = new EReg(".*","");
|
||||
xrfragment_XRF.operators = new EReg("(^-|[\\*]+)","");
|
||||
xrfragment_XRF.isProp = new EReg("^.*=[><=]?","");
|
||||
xrfragment_XRF.isExclude = new EReg("^-","");
|
||||
xrfragment_XRF.isDeep = new EReg("\\*","");
|
||||
xrfragment_XRF.isNumber = new EReg("^[0-9\\.]+$","");
|
||||
})({});
|
||||
var xrfragment = $hx_exports["xrfragment"];
|
||||
|
|
|
|||
870
dist/xrfragment.lua
vendored
870
dist/xrfragment.lua
vendored
File diff suppressed because it is too large
Load diff
158788
dist/xrfragment.module.js
vendored
158788
dist/xrfragment.module.js
vendored
File diff suppressed because it is too large
Load diff
706
dist/xrfragment.php/lib/Array_hx.php
vendored
706
dist/xrfragment.php/lib/Array_hx.php
vendored
|
|
@ -1,706 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
use \haxe\iterators\ArrayIterator as IteratorsArrayIterator;
|
||||
use \php\Boot;
|
||||
use \php\_Boot\HxClosure;
|
||||
use \haxe\iterators\ArrayKeyValueIterator;
|
||||
|
||||
final class Array_hx implements \JsonSerializable, \Countable, \IteratorAggregate, \ArrayAccess {
|
||||
/**
|
||||
* @var mixed[]
|
||||
*/
|
||||
public $arr;
|
||||
/**
|
||||
* @var int
|
||||
* The length of `this` Array.
|
||||
*/
|
||||
public $length;
|
||||
|
||||
/**
|
||||
* @param mixed[] $arr
|
||||
*
|
||||
* @return mixed[]|Array_hx
|
||||
*/
|
||||
public static function wrap ($arr) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:267: characters 3-23
|
||||
$a = new Array_hx();
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:268: characters 3-14
|
||||
$a->arr = $arr;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:269: characters 3-31
|
||||
$a->length = count($arr);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:270: characters 3-11
|
||||
return $a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Array.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:37: characters 9-36
|
||||
$this1 = [];
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:37: characters 3-36
|
||||
$this->arr = $this1;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:38: characters 3-13
|
||||
$this->length = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Array by appending the elements of `a` to the elements of
|
||||
* `this` Array.
|
||||
* This operation does not modify `this` Array.
|
||||
* If `a` is the empty Array `[]`, a copy of `this` Array is returned.
|
||||
* The length of the returned Array is equal to the sum of `this.length`
|
||||
* and `a.length`.
|
||||
* If `a` is `null`, the result is unspecified.
|
||||
*
|
||||
* @param mixed[]|Array_hx $a
|
||||
*
|
||||
* @return mixed[]|Array_hx
|
||||
*/
|
||||
public function concat ($a) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:42: characters 3-46
|
||||
return Array_hx::wrap(array_merge($this->arr, $a->arr));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether `this` Array contains `x`.
|
||||
* If `x` is found by checking standard equality, the function returns `true`, otherwise
|
||||
* the function returns `false`.
|
||||
*
|
||||
* @param mixed $x
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function contains ($x) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:60: characters 3-26
|
||||
return $this->indexOf($x) !== -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a shallow copy of `this` Array.
|
||||
* The elements are not copied and retain their identity, so
|
||||
* `a[i] == a.copy()[i]` is true for any valid `i`. However,
|
||||
* `a == a.copy()` is always false.
|
||||
*
|
||||
* @return mixed[]|Array_hx
|
||||
*/
|
||||
public function copy () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:46: characters 3-28
|
||||
return (clone $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function count () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:257: characters 3-16
|
||||
return $this->length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Array containing those elements of `this` for which `f`
|
||||
* returned true.
|
||||
* The individual elements are not duplicated and retain their identity.
|
||||
* If `f` is null, the result is unspecified.
|
||||
*
|
||||
* @param \Closure $f
|
||||
*
|
||||
* @return mixed[]|Array_hx
|
||||
*/
|
||||
public function filter ($f) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:50: characters 3-35
|
||||
$result = [];
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:51: characters 15-18
|
||||
$data = $this->arr;
|
||||
$_g_current = 0;
|
||||
$_g_length = count($data);
|
||||
$_g_data = $data;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:51: lines 51-55
|
||||
while ($_g_current < $_g_length) {
|
||||
$item = $_g_data[$_g_current++];
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:52: lines 52-54
|
||||
if ($f($item)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:53: characters 5-22
|
||||
$result[] = $item;
|
||||
}
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:56: characters 3-22
|
||||
return Array_hx::wrap($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Traversable
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:250: characters 3-38
|
||||
return new \ArrayIterator($this->arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns position of the first occurrence of `x` in `this` Array, searching front to back.
|
||||
* If `x` is found by checking standard equality, the function returns its index.
|
||||
* If `x` is not found, the function returns -1.
|
||||
* If `fromIndex` is specified, it will be used as the starting index to search from,
|
||||
* otherwise search starts with zero index. If it is negative, it will be taken as the
|
||||
* offset from the end of `this` Array to compute the starting index. If given or computed
|
||||
* starting index is less than 0, the whole array will be searched, if it is greater than
|
||||
* or equal to the length of `this` Array, the function returns -1.
|
||||
*
|
||||
* @param mixed $x
|
||||
* @param int $fromIndex
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function indexOf ($x, $fromIndex = null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:64: characters 7-69
|
||||
$tmp = null;
|
||||
if (($fromIndex === null) && !($x instanceof HxClosure)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:64: characters 53-69
|
||||
$value = $x;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:64: characters 7-69
|
||||
$tmp = !(is_int($value) || is_float($value));
|
||||
} else {
|
||||
$tmp = false;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:64: lines 64-71
|
||||
if ($tmp) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:65: characters 4-50
|
||||
$index = array_search($x, $this->arr, true);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:66: lines 66-70
|
||||
if ($index === false) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:67: characters 5-14
|
||||
return -1;
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:69: characters 5-17
|
||||
return $index;
|
||||
}
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:72: lines 72-79
|
||||
if ($fromIndex === null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:73: characters 4-17
|
||||
$fromIndex = 0;
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:75: lines 75-76
|
||||
if ($fromIndex < 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:76: characters 5-24
|
||||
$fromIndex += $this->length;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:77: lines 77-78
|
||||
if ($fromIndex < 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:78: characters 5-18
|
||||
$fromIndex = 0;
|
||||
}
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:80: lines 80-84
|
||||
while ($fromIndex < $this->length) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:81: lines 81-82
|
||||
if (Boot::equal($this->arr[$fromIndex], $x)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:82: characters 5-21
|
||||
return $fromIndex;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:83: characters 4-15
|
||||
++$fromIndex;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:85: characters 3-12
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the element `x` at the position `pos`.
|
||||
* This operation modifies `this` Array in place.
|
||||
* The offset is calculated like so:
|
||||
* - If `pos` exceeds `this.length`, the offset is `this.length`.
|
||||
* - If `pos` is negative, the offset is calculated from the end of `this`
|
||||
* Array, i.e. `this.length + pos`. If this yields a negative value, the
|
||||
* offset is 0.
|
||||
* - Otherwise, the offset is `pos`.
|
||||
* If the resulting offset does not exceed `this.length`, all elements from
|
||||
* and including that offset to the end of `this` Array are moved one index
|
||||
* ahead.
|
||||
*
|
||||
* @param int $pos
|
||||
* @param mixed $x
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function insert ($pos, $x) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:89: characters 3-11
|
||||
$this->length++;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:90: characters 3-56
|
||||
array_splice($this->arr, $pos, 0, [$x]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator of the Array values.
|
||||
*
|
||||
* @return IteratorsArrayIterator
|
||||
*/
|
||||
public function iterator () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:95: characters 3-48
|
||||
return new IteratorsArrayIterator($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of `this` Array, with `sep` separating
|
||||
* each element.
|
||||
* The result of this operation is equal to `Std.string(this[0]) + sep +
|
||||
* Std.string(this[1]) + sep + ... + sep + Std.string(this[this.length-1])`
|
||||
* If `this` is the empty Array `[]`, the result is the empty String `""`.
|
||||
* If `this` has exactly one element, the result is equal to a call to
|
||||
* `Std.string(this[0])`.
|
||||
* If `sep` is null, the result is unspecified.
|
||||
*
|
||||
* @param string $sep
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function join ($sep) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:104: characters 3-98
|
||||
return implode($sep, array_map((Boot::class??'null') . "::stringify", $this->arr));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:263: characters 3-13
|
||||
return $this->arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator of the Array indices and values.
|
||||
*
|
||||
* @return ArrayKeyValueIterator
|
||||
*/
|
||||
public function keyValueIterator () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:100: characters 3-41
|
||||
return new ArrayKeyValueIterator($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns position of the last occurrence of `x` in `this` Array, searching back to front.
|
||||
* If `x` is found by checking standard equality, the function returns its index.
|
||||
* If `x` is not found, the function returns -1.
|
||||
* If `fromIndex` is specified, it will be used as the starting index to search from,
|
||||
* otherwise search starts with the last element index. If it is negative, it will be
|
||||
* taken as the offset from the end of `this` Array to compute the starting index. If
|
||||
* given or computed starting index is greater than or equal to the length of `this` Array,
|
||||
* the whole array will be searched, if it is less than 0, the function returns -1.
|
||||
*
|
||||
* @param mixed $x
|
||||
* @param int $fromIndex
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function lastIndexOf ($x, $fromIndex = null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:108: lines 108-109
|
||||
if (($fromIndex === null) || ($fromIndex >= $this->length)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:109: characters 4-26
|
||||
$fromIndex = $this->length - 1;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:110: lines 110-111
|
||||
if ($fromIndex < 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:111: characters 4-23
|
||||
$fromIndex += $this->length;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:112: lines 112-116
|
||||
while ($fromIndex >= 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:113: lines 113-114
|
||||
if (Boot::equal($this->arr[$fromIndex], $x)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:114: characters 5-21
|
||||
return $fromIndex;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:115: characters 4-15
|
||||
--$fromIndex;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:117: characters 3-12
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Array by applying function `f` to all elements of `this`.
|
||||
* The order of elements is preserved.
|
||||
* If `f` is null, the result is unspecified.
|
||||
*
|
||||
* @param \Closure $f
|
||||
*
|
||||
* @return mixed[]|Array_hx
|
||||
*/
|
||||
public function map ($f) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:121: characters 3-35
|
||||
$result = [];
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:122: characters 15-18
|
||||
$data = $this->arr;
|
||||
$_g_current = 0;
|
||||
$_g_length = count($data);
|
||||
$_g_data = $data;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:122: lines 122-124
|
||||
while ($_g_current < $_g_length) {
|
||||
$item = $_g_data[$_g_current++];
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:123: characters 4-24
|
||||
$result[] = $f($item);
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:125: characters 3-22
|
||||
return Array_hx::wrap($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists ($offset) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:212: characters 3-25
|
||||
return $offset < $this->length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function &offsetGet ($offset) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:218: lines 218-222
|
||||
try {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:219: characters 4-22
|
||||
return $this->arr[$offset];
|
||||
} catch(\Throwable $_g) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:221: characters 4-15
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet ($offset, $value) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:228: lines 228-233
|
||||
if ($this->length <= $offset) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:229: characters 13-19
|
||||
$_g = $this->length;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:229: characters 22-32
|
||||
$_g1 = $offset + 1;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:229: lines 229-231
|
||||
while ($_g < $_g1) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:229: characters 13-32
|
||||
$i = $_g++;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:230: characters 5-18
|
||||
$this->arr[$i] = null;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:232: characters 4-23
|
||||
$this->length = $offset + 1;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:234: characters 3-22
|
||||
$this->arr[$offset] = $value;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:235: characters 3-35
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset ($offset) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:241: lines 241-244
|
||||
if (($offset >= 0) && ($offset < $this->length)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:242: characters 4-39
|
||||
array_splice($this->arr, $offset, 1);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:243: characters 4-12
|
||||
--$this->length;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the last element of `this` Array and returns it.
|
||||
* This operation modifies `this` Array in place.
|
||||
* If `this` has at least one element, `this.length` will decrease by 1.
|
||||
* If `this` is the empty Array `[]`, null is returned and the length
|
||||
* remains 0.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function pop () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:129: lines 129-130
|
||||
if ($this->length > 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:130: characters 4-12
|
||||
$this->length--;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:131: characters 3-31
|
||||
return array_pop($this->arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the element `x` at the end of `this` Array and returns the new
|
||||
* length of `this` Array.
|
||||
* This operation modifies `this` Array in place.
|
||||
* `this.length` increases by 1.
|
||||
*
|
||||
* @param mixed $x
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function push ($x) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:135: characters 3-20
|
||||
$this->arr[$this->length++] = $x;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:136: characters 3-16
|
||||
return $this->length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the first occurrence of `x` in `this` Array.
|
||||
* This operation modifies `this` Array in place.
|
||||
* If `x` is found by checking standard equality, it is removed from `this`
|
||||
* Array and all following elements are reindexed accordingly. The function
|
||||
* then returns true.
|
||||
* If `x` is not found, `this` Array is not changed and the function
|
||||
* returns false.
|
||||
*
|
||||
* @param mixed $x
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function remove ($x) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:140: characters 3-22
|
||||
$result = false;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:141: characters 16-20
|
||||
$_g = 0;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:141: characters 20-26
|
||||
$_g1 = $this->length;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:141: lines 141-148
|
||||
while ($_g < $_g1) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:141: characters 16-26
|
||||
$index = $_g++;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:142: lines 142-147
|
||||
if (Boot::equal($this->arr[$index], $x)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:143: characters 5-39
|
||||
array_splice($this->arr, $index, 1);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:144: characters 5-13
|
||||
$this->length--;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:145: characters 5-18
|
||||
$result = true;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:146: characters 5-10
|
||||
break;
|
||||
}
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:149: characters 3-16
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the length of the Array.
|
||||
* If `len` is shorter than the array's current size, the last
|
||||
* `length - len` elements will be removed. If `len` is longer, the Array
|
||||
* will be extended, with new elements set to a target-specific default
|
||||
* value:
|
||||
* - always null on dynamic targets
|
||||
* - 0, 0.0 or false for Int, Float and Bool respectively on static targets
|
||||
* - null for other types on static targets
|
||||
*
|
||||
* @param int $len
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resize ($len) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:201: lines 201-205
|
||||
if ($this->length < $len) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:202: characters 4-42
|
||||
$this->arr = array_pad($this->arr, $len, null);
|
||||
} else if ($this->length > $len) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:204: characters 4-47
|
||||
array_splice($this->arr, $len, $this->length - $len);
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:206: characters 3-15
|
||||
$this->length = $len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the order of elements of `this` Array.
|
||||
* This operation modifies `this` Array in place.
|
||||
* If `this.length < 2`, `this` remains unchanged.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function reverse () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:153: characters 3-34
|
||||
$this->arr = array_reverse($this->arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the first element of `this` Array and returns it.
|
||||
* This operation modifies `this` Array in place.
|
||||
* If `this` has at least one element, `this`.length and the index of each
|
||||
* remaining element is decreased by 1.
|
||||
* If `this` is the empty Array `[]`, `null` is returned and the length
|
||||
* remains 0.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function shift () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:157: lines 157-158
|
||||
if ($this->length > 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:158: characters 4-12
|
||||
$this->length--;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:159: characters 3-33
|
||||
return array_shift($this->arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a shallow copy of the range of `this` Array, starting at and
|
||||
* including `pos`, up to but not including `end`.
|
||||
* This operation does not modify `this` Array.
|
||||
* The elements are not copied and retain their identity.
|
||||
* If `end` is omitted or exceeds `this.length`, it defaults to the end of
|
||||
* `this` Array.
|
||||
* If `pos` or `end` are negative, their offsets are calculated from the
|
||||
* end of `this` Array by `this.length + pos` and `this.length + end`
|
||||
* respectively. If this yields a negative value, 0 is used instead.
|
||||
* If `pos` exceeds `this.length` or if `end` is less than or equals
|
||||
* `pos`, the result is `[]`.
|
||||
*
|
||||
* @param int $pos
|
||||
* @param int $end
|
||||
*
|
||||
* @return mixed[]|Array_hx
|
||||
*/
|
||||
public function slice ($pos, $end = null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:163: lines 163-164
|
||||
if ($pos < 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:164: characters 4-17
|
||||
$pos += $this->length;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:165: lines 165-166
|
||||
if ($pos < 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:166: characters 4-11
|
||||
$pos = 0;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:167: lines 167-177
|
||||
if ($end === null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:168: characters 4-45
|
||||
return Array_hx::wrap(array_slice($this->arr, $pos));
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:170: lines 170-171
|
||||
if ($end < 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:171: characters 5-18
|
||||
$end += $this->length;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:172: lines 172-176
|
||||
if ($end <= $pos) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:173: characters 5-14
|
||||
return new Array_hx();
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:175: characters 5-57
|
||||
return Array_hx::wrap(array_slice($this->arr, $pos, $end - $pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts `this` Array according to the comparison function `f`, where
|
||||
* `f(x,y)` returns 0 if x == y, a positive Int if x > y and a
|
||||
* negative Int if x < y.
|
||||
* This operation modifies `this` Array in place.
|
||||
* The sort operation is not guaranteed to be stable, which means that the
|
||||
* order of equal elements may not be retained. For a stable Array sorting
|
||||
* algorithm, `haxe.ds.ArraySort.sort()` can be used instead.
|
||||
* If `f` is null, the result is unspecified.
|
||||
*
|
||||
* @param \Closure $f
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sort ($f) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:181: characters 3-15
|
||||
usort($this->arr, $f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes `len` elements from `this` Array, starting at and including
|
||||
* `pos`, an returns them.
|
||||
* This operation modifies `this` Array in place.
|
||||
* If `len` is < 0 or `pos` exceeds `this`.length, an empty Array [] is
|
||||
* returned and `this` Array is unchanged.
|
||||
* If `pos` is negative, its value is calculated from the end of `this`
|
||||
* Array by `this.length + pos`. If this yields a negative value, 0 is
|
||||
* used instead.
|
||||
* If the sum of the resulting values for `len` and `pos` exceed
|
||||
* `this.length`, this operation will affect the elements from `pos` to the
|
||||
* end of `this` Array.
|
||||
* The length of the returned Array is equal to the new length of `this`
|
||||
* Array subtracted from the original length of `this` Array. In other
|
||||
* words, each element of the original `this` Array either remains in
|
||||
* `this` Array or becomes an element of the returned Array.
|
||||
*
|
||||
* @param int $pos
|
||||
* @param int $len
|
||||
*
|
||||
* @return mixed[]|Array_hx
|
||||
*/
|
||||
public function splice ($pos, $len) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:185: lines 185-186
|
||||
if ($len < 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:186: characters 4-13
|
||||
return new Array_hx();
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:187: characters 3-57
|
||||
$result = Array_hx::wrap(array_splice($this->arr, $pos, $len));
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:188: characters 3-26
|
||||
$this->length -= $result->length;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:189: characters 3-16
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of `this` Array.
|
||||
* The result will include the individual elements' String representations
|
||||
* separated by comma. The enclosing [ ] may be missing on some platforms,
|
||||
* use `Std.string()` to get a String representation that is consistent
|
||||
* across platforms.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toString () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:197: characters 10-54
|
||||
$arr = $this->arr;
|
||||
$strings = [];
|
||||
foreach ($arr as $key => $value) {
|
||||
$strings[$key] = Boot::stringify($value, 9);
|
||||
}
|
||||
return "[" . (implode(",", $strings)??'null') . "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the element `x` at the start of `this` Array.
|
||||
* This operation modifies `this` Array in place.
|
||||
* `this.length` and the index of each Array element increases by 1.
|
||||
*
|
||||
* @param mixed $x
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function unshift ($x) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Array.hx:193: characters 3-40
|
||||
$this->length = array_unshift($this->arr, $x);
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->toString();
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(Array_hx::class, 'Array');
|
||||
147
dist/xrfragment.php/lib/EReg.php
vendored
147
dist/xrfragment.php/lib/EReg.php
vendored
|
|
@ -1,147 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
use \php\Boot;
|
||||
use \haxe\Exception as HaxeException;
|
||||
|
||||
/**
|
||||
* The EReg class represents regular expressions.
|
||||
* While basic usage and patterns consistently work across platforms, some more
|
||||
* complex operations may yield different results. This is a necessary trade-
|
||||
* off to retain a certain level of performance.
|
||||
* EReg instances can be created by calling the constructor, or with the
|
||||
* special syntax `~/pattern/modifier`
|
||||
* EReg instances maintain an internal state, which is affected by several of
|
||||
* its methods.
|
||||
* A detailed explanation of the supported operations is available at
|
||||
* <https://haxe.org/manual/std-regex.html>
|
||||
*/
|
||||
final class EReg {
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $global;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $last;
|
||||
/**
|
||||
* @var array[]
|
||||
*/
|
||||
public $matches;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $options;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $pattern;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $re;
|
||||
|
||||
/**
|
||||
* Creates a new regular expression with pattern `r` and modifiers `opt`.
|
||||
* This is equivalent to the shorthand syntax `~/r/opt`
|
||||
* If `r` or `opt` are null, the result is unspecified.
|
||||
*
|
||||
* @param string $r
|
||||
* @param string $opt
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct ($r, $opt) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:37: characters 3-19
|
||||
$this->pattern = $r;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:38: characters 3-45
|
||||
$this->options = str_replace("g", "", $opt);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:39: characters 3-26
|
||||
$this->global = $this->options !== $opt;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:40: characters 3-49
|
||||
$this->options = str_replace("u", "", $this->options);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:41: characters 3-68
|
||||
$this->re = "\"" . (str_replace("\"", "\\\"", $r)??'null') . "\"" . ($this->options??'null');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function handlePregError () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:63: characters 3-36
|
||||
$e = preg_last_error();
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:64: lines 64-72
|
||||
if ($e === PREG_INTERNAL_ERROR) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:65: characters 4-9
|
||||
throw HaxeException::thrown("EReg: internal PCRE error");
|
||||
} else if ($e === PREG_BACKTRACK_LIMIT_ERROR) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:67: characters 4-9
|
||||
throw HaxeException::thrown("EReg: backtrack limit");
|
||||
} else if ($e === PREG_RECURSION_LIMIT_ERROR) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:69: characters 4-9
|
||||
throw HaxeException::thrown("EReg: recursion limit");
|
||||
} else if ($e === PREG_JIT_STACKLIMIT_ERROR) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:71: characters 4-9
|
||||
throw HaxeException::thrown("failed due to limited JIT stack space");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if `this` regular expression matches String `s`.
|
||||
* This method modifies the internal state.
|
||||
* If `s` is `null`, the result is unspecified.
|
||||
*
|
||||
* @param string $s
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function match ($s) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:45: characters 10-29
|
||||
$p = preg_match(($this->re . "u"), $s, $this->matches, PREG_OFFSET_CAPTURE, 0);
|
||||
if ($p === false) {
|
||||
$this->handlePregError();
|
||||
$p = preg_match($this->re, $s, $this->matches, PREG_OFFSET_CAPTURE);
|
||||
}
|
||||
if ($p > 0) {
|
||||
$this->last = $s;
|
||||
} else {
|
||||
$this->last = null;
|
||||
}
|
||||
return $p > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits String `s` at all substrings `this` EReg matches.
|
||||
* If a match is found at the start of `s`, the result contains a leading
|
||||
* empty String "" entry.
|
||||
* If a match is found at the end of `s`, the result contains a trailing
|
||||
* empty String "" entry.
|
||||
* If two matching substrings appear next to each other, the result
|
||||
* contains the empty String `""` between them.
|
||||
* By default, this method splits `s` into two parts at the first matched
|
||||
* substring. If the global g modifier is in place, `s` is split at each
|
||||
* matched substring.
|
||||
* If `s` is null, the result is unspecified.
|
||||
*
|
||||
* @param string $s
|
||||
*
|
||||
* @return string[]|\Array_hx
|
||||
*/
|
||||
public function split ($s) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:128: characters 3-96
|
||||
$parts = preg_split(($this->re . "u"), $s, ($this->global ? -1 : 2));
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:129: lines 129-132
|
||||
if ($parts === false) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:130: characters 4-21
|
||||
$this->handlePregError();
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:131: characters 4-55
|
||||
$parts = preg_split($this->re, $s, ($this->global ? -1 : 2));
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/EReg.hx:133: characters 3-48
|
||||
return \Array_hx::wrap($parts);
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(EReg::class, 'EReg');
|
||||
179
dist/xrfragment.php/lib/Reflect.php
vendored
179
dist/xrfragment.php/lib/Reflect.php
vendored
|
|
@ -1,179 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
use \php\Boot;
|
||||
use \php\_Boot\HxClass;
|
||||
|
||||
/**
|
||||
* The Reflect API is a way to manipulate values dynamically through an
|
||||
* abstract interface in an untyped manner. Use with care.
|
||||
* @see https://haxe.org/manual/std-reflection.html
|
||||
*/
|
||||
class Reflect {
|
||||
/**
|
||||
* Removes the field named `field` from structure `o`.
|
||||
* This method is only guaranteed to work on anonymous structures.
|
||||
* If `o` or `field` are null, the result is unspecified.
|
||||
*
|
||||
* @param mixed $o
|
||||
* @param string $field
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function deleteField ($o, $field) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:158: lines 158-163
|
||||
if (Reflect::hasField($o, $field)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:159: characters 4-40
|
||||
unset($o->{$field});
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:160: characters 4-15
|
||||
return true;
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:162: characters 4-16
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the field named `field` on object `o`.
|
||||
* If `o` is not an object or has no field named `field`, the result is
|
||||
* null.
|
||||
* If the field is defined as a property, its accessors are ignored. Refer
|
||||
* to `Reflect.getProperty` for a function supporting property accessors.
|
||||
* If `field` is null, the result is unspecified.
|
||||
*
|
||||
* @param mixed $o
|
||||
* @param string $field
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function field ($o, $field) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:50: lines 50-52
|
||||
if (is_string($o)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:51: characters 24-45
|
||||
$tmp = Boot::dynamicString($o);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:51: characters 4-53
|
||||
return $tmp->{$field};
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:53: lines 53-54
|
||||
if (!is_object($o)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:54: characters 4-15
|
||||
return null;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:56: lines 56-58
|
||||
if (($field === "") && (PHP_VERSION_ID < 70100)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:57: characters 4-56
|
||||
return (((array)($o))[$field] ?? null);
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:60: lines 60-62
|
||||
if (property_exists($o, $field)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:61: characters 4-33
|
||||
return $o->{$field};
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:63: lines 63-65
|
||||
if (method_exists($o, $field)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:64: characters 4-44
|
||||
return Boot::getInstanceClosure($o, $field);
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:67: lines 67-78
|
||||
if (($o instanceof HxClass)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:68: characters 4-54
|
||||
$phpClassName = $o->phpClassName;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:69: lines 69-71
|
||||
if (defined("" . ($phpClassName??'null') . "::" . ($field??'null'))) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:70: characters 5-52
|
||||
return constant("" . ($phpClassName??'null') . "::" . ($field??'null'));
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:72: lines 72-74
|
||||
if (property_exists($phpClassName, $field)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:73: characters 5-34
|
||||
return $o->{$field};
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:75: lines 75-77
|
||||
if (method_exists($phpClassName, $field)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:76: characters 5-54
|
||||
return Boot::getStaticClosure($phpClassName, $field);
|
||||
}
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:80: characters 3-14
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fields of structure `o`.
|
||||
* This method is only guaranteed to work on anonymous structures. Refer to
|
||||
* `Type.getInstanceFields` for a function supporting class instances.
|
||||
* If `o` is null, the result is unspecified.
|
||||
*
|
||||
* @param mixed $o
|
||||
*
|
||||
* @return string[]|\Array_hx
|
||||
*/
|
||||
public static function fields ($o) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:117: lines 117-119
|
||||
if (is_object($o)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:118: characters 4-77
|
||||
return \Array_hx::wrap(array_keys(get_object_vars($o)));
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:120: characters 3-12
|
||||
return new \Array_hx();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells if structure `o` has a field named `field`.
|
||||
* This is only guaranteed to work for anonymous structures. Refer to
|
||||
* `Type.getInstanceFields` for a function supporting class instances.
|
||||
* If `o` or `field` are null, the result is unspecified.
|
||||
*
|
||||
* @param mixed $o
|
||||
* @param string $field
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasField ($o, $field) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:34: lines 34-35
|
||||
if (!is_object($o)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:35: characters 4-16
|
||||
return false;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:36: lines 36-37
|
||||
if (property_exists($o, $field)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:37: characters 4-15
|
||||
return true;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:39: lines 39-44
|
||||
if (($o instanceof HxClass)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:40: characters 4-54
|
||||
$phpClassName = $o->phpClassName;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:41: lines 41-43
|
||||
if (!(property_exists($phpClassName, $field) || method_exists($phpClassName, $field))) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:43: characters 8-47
|
||||
return defined("" . ($phpClassName??'null') . "::" . ($field??'null'));
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:41: lines 41-43
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:46: characters 3-15
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the field named `field` of object `o` to value `value`.
|
||||
* If `o` has no field named `field`, this function is only guaranteed to
|
||||
* work for anonymous structures.
|
||||
* If `o` or `field` are null, the result is unspecified.
|
||||
*
|
||||
* @param mixed $o
|
||||
* @param string $field
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function setField ($o, $field, $value) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Reflect.hx:84: characters 3-35
|
||||
$o->{$field} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(Reflect::class, 'Reflect');
|
||||
125
dist/xrfragment.php/lib/Std.php
vendored
125
dist/xrfragment.php/lib/Std.php
vendored
|
|
@ -1,125 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
use \php\Boot;
|
||||
use \php\_Boot\HxString;
|
||||
|
||||
/**
|
||||
* The Std class provides standard methods for manipulating basic types.
|
||||
*/
|
||||
class Std {
|
||||
/**
|
||||
* Converts a `String` to a `Float`.
|
||||
* The parsing rules for `parseInt` apply here as well, with the exception of invalid input
|
||||
* resulting in a `NaN` value instead of null.
|
||||
* Additionally, decimal notation may contain a single `.` to denote the start of the fractions.
|
||||
*
|
||||
* @param string $x
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public static function parseFloat ($x) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:74: characters 3-35
|
||||
$result = floatval($x);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:75: lines 75-76
|
||||
if (!Boot::equal($result, 0)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:76: characters 4-17
|
||||
return $result;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:78: characters 3-22
|
||||
$x = ltrim($x);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:79: characters 3-53
|
||||
$firstCharIndex = (mb_substr($x, 0, 1) === "-" ? 1 : 0);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:80: characters 3-47
|
||||
$charCode = HxString::charCodeAt($x, $firstCharIndex);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:82: lines 82-84
|
||||
if ($charCode === 46) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:83: characters 4-47
|
||||
$charCode = HxString::charCodeAt($x, $firstCharIndex + 1);
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:86: lines 86-90
|
||||
if (($charCode !== null) && ($charCode >= 48) && ($charCode <= 57)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:87: characters 4-14
|
||||
return 0.0;
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:89: characters 4-20
|
||||
return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a `String` to an `Int`.
|
||||
* Leading whitespaces are ignored.
|
||||
* If `x` starts with 0x or 0X, hexadecimal notation is recognized where the following digits may
|
||||
* contain 0-9 and A-F.
|
||||
* Otherwise `x` is read as decimal number with 0-9 being allowed characters. `x` may also start with
|
||||
* a - to denote a negative value.
|
||||
* In decimal mode, parsing continues until an invalid character is detected, in which case the
|
||||
* result up to that point is returned. For hexadecimal notation, the effect of invalid characters
|
||||
* is unspecified.
|
||||
* Leading 0s that are not part of the 0x/0X hexadecimal notation are ignored, which means octal
|
||||
* notation is not supported.
|
||||
* If `x` is null, the result is unspecified.
|
||||
* If `x` cannot be parsed as integer, the result is `null`.
|
||||
*
|
||||
* @param string $x
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function parseInt ($x) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:55: lines 55-70
|
||||
if (is_numeric($x)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:56: characters 4-31
|
||||
return intval($x, 10);
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:58: characters 4-23
|
||||
$x = ltrim($x);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:59: characters 4-54
|
||||
$firstCharIndex = (mb_substr($x, 0, 1) === "-" ? 1 : 0);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:60: characters 4-53
|
||||
$firstCharCode = HxString::charCodeAt($x, $firstCharIndex);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:61: lines 61-63
|
||||
if (!(($firstCharCode !== null) && ($firstCharCode >= 48) && ($firstCharCode <= 57))) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:62: characters 5-16
|
||||
return null;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:64: characters 21-49
|
||||
$index = $firstCharIndex + 1;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:64: characters 4-50
|
||||
$secondChar = ($index < 0 ? "" : mb_substr($x, $index, 1));
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:65: lines 65-69
|
||||
if (($secondChar === "x") || ($secondChar === "X")) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:66: characters 5-31
|
||||
return intval($x, 0);
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:68: characters 5-32
|
||||
return intval($x, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts any value to a String.
|
||||
* If `s` is of `String`, `Int`, `Float` or `Bool`, its value is returned.
|
||||
* If `s` is an instance of a class and that class or one of its parent classes has
|
||||
* a `toString` method, that method is called. If no such method is present, the result
|
||||
* is unspecified.
|
||||
* If `s` is an enum constructor without argument, the constructor's name is returned. If
|
||||
* arguments exists, the constructor's name followed by the String representations of
|
||||
* the arguments is returned.
|
||||
* If `s` is a structure, the field names along with their values are returned. The field order
|
||||
* and the operator separating field names and values are unspecified.
|
||||
* If s is null, "null" is returned.
|
||||
*
|
||||
* @param mixed $s
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function string ($s) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/Std.hx:47: characters 3-27
|
||||
return Boot::stringify($s);
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(Std::class, 'Std');
|
||||
40
dist/xrfragment.php/lib/StringTools.php
vendored
40
dist/xrfragment.php/lib/StringTools.php
vendored
|
|
@ -1,40 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
use \php\Boot;
|
||||
|
||||
/**
|
||||
* This class provides advanced methods on Strings. It is ideally used with
|
||||
* `using StringTools` and then acts as an [extension](https://haxe.org/manual/lf-static-extension.html)
|
||||
* to the `String` class.
|
||||
* If the first argument to any of the methods is null, the result is
|
||||
* unspecified.
|
||||
*/
|
||||
class StringTools {
|
||||
/**
|
||||
* Replace all occurrences of the String `sub` in the String `s` by the
|
||||
* String `by`.
|
||||
* If `sub` is the empty String `""`, `by` is inserted after each character
|
||||
* of `s` except the last one. If `by` is also the empty String `""`, `s`
|
||||
* remains unchanged.
|
||||
* If `sub` or `by` are null, the result is unspecified.
|
||||
*
|
||||
* @param string $s
|
||||
* @param string $sub
|
||||
* @param string $by
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function replace ($s, $sub, $by) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/StringTools.hx:104: lines 104-106
|
||||
if ($sub === "") {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/StringTools.hx:105: characters 4-89
|
||||
return implode($by, preg_split("//u", $s, -1, PREG_SPLIT_NO_EMPTY));
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/StringTools.hx:107: characters 3-40
|
||||
return str_replace($sub, $by, $s);
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(StringTools::class, 'StringTools');
|
||||
125
dist/xrfragment.php/lib/haxe/Exception.php
vendored
125
dist/xrfragment.php/lib/haxe/Exception.php
vendored
|
|
@ -1,125 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
namespace haxe;
|
||||
|
||||
use \php\Boot;
|
||||
|
||||
/**
|
||||
* Base class for exceptions.
|
||||
* If this class (or derivatives) is used to catch an exception, then
|
||||
* `haxe.CallStack.exceptionStack()` will not return a stack for the exception
|
||||
* caught. Use `haxe.Exception.stack` property instead:
|
||||
* ```haxe
|
||||
* try {
|
||||
* throwSomething();
|
||||
* } catch(e:Exception) {
|
||||
* trace(e.stack);
|
||||
* }
|
||||
* ```
|
||||
* Custom exceptions should extend this class:
|
||||
* ```haxe
|
||||
* class MyException extends haxe.Exception {}
|
||||
* //...
|
||||
* throw new MyException('terrible exception');
|
||||
* ```
|
||||
* `haxe.Exception` is also a wildcard type to catch any exception:
|
||||
* ```haxe
|
||||
* try {
|
||||
* throw 'Catch me!';
|
||||
* } catch(e:haxe.Exception) {
|
||||
* trace(e.message); // Output: Catch me!
|
||||
* }
|
||||
* ```
|
||||
* To rethrow an exception just throw it again.
|
||||
* Haxe will try to rethrow an original native exception whenever possible.
|
||||
* ```haxe
|
||||
* try {
|
||||
* var a:Array<Int> = null;
|
||||
* a.push(1); // generates target-specific null-pointer exception
|
||||
* } catch(e:haxe.Exception) {
|
||||
* throw e; // rethrows native exception instead of haxe.Exception
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class Exception extends \Exception {
|
||||
/**
|
||||
* @var \Throwable
|
||||
*/
|
||||
public $__nativeException;
|
||||
/**
|
||||
* @var Exception
|
||||
*/
|
||||
public $__previousException;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $__skipStack;
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function thrown ($value) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/haxe/Exception.hx:30: lines 30-38
|
||||
if (($value instanceof Exception)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/haxe/Exception.hx:31: characters 4-35
|
||||
return $value->get_native();
|
||||
} else if (($value instanceof \Throwable)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/haxe/Exception.hx:33: characters 4-16
|
||||
return $value;
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/haxe/Exception.hx:35: characters 4-38
|
||||
$e = new ValueException($value);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/haxe/Exception.hx:36: characters 4-21
|
||||
$e->__skipStack = 1;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/haxe/Exception.hx:37: characters 4-12
|
||||
return $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Exception instance.
|
||||
* The `previous` argument could be used for exception chaining.
|
||||
* The `native` argument is for internal usage only.
|
||||
* There is no need to provide `native` argument manually and no need to keep it
|
||||
* upon extending `haxe.Exception` unless you know what you're doing.
|
||||
*
|
||||
* @param string $message
|
||||
* @param Exception $previous
|
||||
* @param mixed $native
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct ($message, $previous = null, $native = null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/haxe/Exception.hx:16: characters 39-40
|
||||
$this->__skipStack = 0;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/haxe/Exception.hx:42: characters 3-30
|
||||
parent::__construct($message, 0, $previous);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/haxe/Exception.hx:43: characters 3-38
|
||||
$this->__previousException = $previous;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/haxe/Exception.hx:44: lines 44-48
|
||||
if (($native !== null) && ($native instanceof \Throwable)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/haxe/Exception.hx:45: characters 4-30
|
||||
$this->__nativeException = $native;
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/haxe/Exception.hx:47: characters 4-33
|
||||
$this->__nativeException = $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
final public function get_native () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/_std/haxe/Exception.hx:72: characters 3-27
|
||||
return $this->__nativeException;
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(Exception::class, 'haxe.Exception');
|
||||
Boot::registerGetters('haxe\\Exception', [
|
||||
'native' => true
|
||||
]);
|
||||
88
dist/xrfragment.php/lib/haxe/Log.php
vendored
88
dist/xrfragment.php/lib/haxe/Log.php
vendored
|
|
@ -1,88 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
namespace haxe;
|
||||
|
||||
use \php\Boot;
|
||||
|
||||
/**
|
||||
* Log primarily provides the `trace()` method, which is invoked upon a call to
|
||||
* `trace()` in Haxe code.
|
||||
*/
|
||||
class Log {
|
||||
/**
|
||||
* @var \Closure
|
||||
* Outputs `v` in a platform-dependent way.
|
||||
* The second parameter `infos` is injected by the compiler and contains
|
||||
* information about the position where the `trace()` call was made.
|
||||
* This method can be rebound to a custom function:
|
||||
* var oldTrace = haxe.Log.trace; // store old function
|
||||
* haxe.Log.trace = function(v, ?infos) {
|
||||
* // handle trace
|
||||
* }
|
||||
* ...
|
||||
* haxe.Log.trace = oldTrace;
|
||||
* If it is bound to null, subsequent calls to `trace()` will cause an
|
||||
* exception.
|
||||
*/
|
||||
static public $trace;
|
||||
|
||||
/**
|
||||
* Format the output of `trace` before printing it.
|
||||
*
|
||||
* @param mixed $v
|
||||
* @param object $infos
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function formatOutput ($v, $infos) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/Log.hx:34: characters 3-27
|
||||
$str = \Std::string($v);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/Log.hx:35: lines 35-36
|
||||
if ($infos === null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/Log.hx:36: characters 4-14
|
||||
return $str;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/Log.hx:37: characters 3-54
|
||||
$pstr = ($infos->fileName??'null') . ":" . ($infos->lineNumber??'null');
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/Log.hx:38: lines 38-40
|
||||
if ($infos->customParams !== null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/Log.hx:39: lines 39-40
|
||||
$_g = 0;
|
||||
$_g1 = $infos->customParams;
|
||||
while ($_g < $_g1->length) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/Log.hx:39: characters 9-10
|
||||
$v = ($_g1->arr[$_g] ?? null);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/Log.hx:39: lines 39-40
|
||||
++$_g;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/Log.hx:40: characters 5-32
|
||||
$str = ($str??'null') . ", " . \Std::string($v);
|
||||
}
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/Log.hx:41: characters 3-27
|
||||
return ($pstr??'null') . ": " . ($str??'null');
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @access private
|
||||
*/
|
||||
static public function __hx__init ()
|
||||
{
|
||||
static $called = false;
|
||||
if ($called) return;
|
||||
$called = true;
|
||||
|
||||
|
||||
self::$trace = function ($v, $infos = null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/Log.hx:63: characters 3-36
|
||||
$str = Log::formatOutput($v, $infos);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/Log.hx:70: characters 3-19
|
||||
echo(\Std::string($str) . \PHP_EOL);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(Log::class, 'haxe.Log');
|
||||
Log::__hx__init();
|
||||
44
dist/xrfragment.php/lib/haxe/ValueException.php
vendored
44
dist/xrfragment.php/lib/haxe/ValueException.php
vendored
|
|
@ -1,44 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
namespace haxe;
|
||||
|
||||
use \php\Boot;
|
||||
|
||||
/**
|
||||
* An exception containing arbitrary value.
|
||||
* This class is automatically used for throwing values, which don't extend `haxe.Exception`
|
||||
* or native exception type.
|
||||
* For example:
|
||||
* ```haxe
|
||||
* throw "Terrible error";
|
||||
* ```
|
||||
* will be compiled to
|
||||
* ```haxe
|
||||
* throw new ValueException("Terrible error");
|
||||
* ```
|
||||
*/
|
||||
class ValueException extends Exception {
|
||||
/**
|
||||
* @var mixed
|
||||
* Thrown value.
|
||||
*/
|
||||
public $value;
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param Exception $previous
|
||||
* @param mixed $native
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct ($value, $previous = null, $native = null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/ValueException.hx:24: characters 3-100
|
||||
parent::__construct(\Std::string($value), $previous, $native);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/ValueException.hx:25: characters 3-21
|
||||
$this->value = $value;
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(ValueException::class, 'haxe.ValueException');
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
namespace haxe\iterators;
|
||||
|
||||
use \php\Boot;
|
||||
|
||||
/**
|
||||
* This iterator is used only when `Array<T>` is passed to `Iterable<T>`
|
||||
*/
|
||||
class ArrayIterator {
|
||||
/**
|
||||
* @var mixed[]|\Array_hx
|
||||
*/
|
||||
public $array;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $current;
|
||||
|
||||
/**
|
||||
* Create a new `ArrayIterator`.
|
||||
*
|
||||
* @param mixed[]|\Array_hx $array
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct ($array) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/iterators/ArrayIterator.hx:30: characters 20-21
|
||||
$this->current = 0;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/iterators/ArrayIterator.hx:37: characters 3-21
|
||||
$this->array = $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* See `Iterator.hasNext`
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasNext () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/iterators/ArrayIterator.hx:45: characters 3-32
|
||||
return $this->current < $this->array->length;
|
||||
}
|
||||
|
||||
/**
|
||||
* See `Iterator.next`
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function next () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/iterators/ArrayIterator.hx:53: characters 3-26
|
||||
return ($this->array->arr[$this->current++] ?? null);
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(ArrayIterator::class, 'haxe.iterators.ArrayIterator');
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
namespace haxe\iterators;
|
||||
|
||||
use \php\Boot;
|
||||
|
||||
class ArrayKeyValueIterator {
|
||||
/**
|
||||
* @var mixed[]|\Array_hx
|
||||
*/
|
||||
public $array;
|
||||
|
||||
/**
|
||||
* @param mixed[]|\Array_hx $array
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct ($array) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/haxe/iterators/ArrayKeyValueIterator.hx:32: characters 3-21
|
||||
$this->array = $array;
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(ArrayKeyValueIterator::class, 'haxe.iterators.ArrayKeyValueIterator');
|
||||
1190
dist/xrfragment.php/lib/php/Boot.php
vendored
1190
dist/xrfragment.php/lib/php/Boot.php
vendored
File diff suppressed because it is too large
Load diff
43
dist/xrfragment.php/lib/php/_Boot/HxAnon.php
vendored
43
dist/xrfragment.php/lib/php/_Boot/HxAnon.php
vendored
|
|
@ -1,43 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
namespace php\_Boot;
|
||||
|
||||
use \php\Boot;
|
||||
|
||||
/**
|
||||
* Anonymous objects implementation
|
||||
*/
|
||||
class HxAnon extends \StdClass {
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function __construct () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:950: lines 950-960
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param array $args
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call ($name, $args) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:958: characters 3-57
|
||||
return ($this->$name)(...$args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get ($name) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:953: characters 3-14
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(HxAnon::class, 'php._Boot.HxAnon');
|
||||
95
dist/xrfragment.php/lib/php/_Boot/HxClass.php
vendored
95
dist/xrfragment.php/lib/php/_Boot/HxClass.php
vendored
|
|
@ -1,95 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
namespace php\_Boot;
|
||||
|
||||
use \php\Boot;
|
||||
|
||||
/**
|
||||
* Class<T> implementation for Haxe->PHP internals.
|
||||
*/
|
||||
class HxClass {
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $phpClassName;
|
||||
|
||||
/**
|
||||
* @param string $phpClassName
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct ($phpClassName) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:667: characters 3-35
|
||||
$this->phpClassName = $phpClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method to call static methods of this class, when `HxClass` instance is in a `Dynamic` variable.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $args
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call ($method, $args) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:675: characters 3-111
|
||||
$callback = ((($this->phpClassName === "String" ? HxString::class : $this->phpClassName))??'null') . "::" . ($method??'null');
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:676: characters 3-53
|
||||
return \call_user_func_array($callback, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method to get static vars of this class, when `HxClass` instance is in a `Dynamic` variable.
|
||||
*
|
||||
* @param string $property
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get ($property) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:684: lines 684-692
|
||||
if (\defined("" . ($this->phpClassName??'null') . "::" . ($property??'null'))) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:685: characters 4-54
|
||||
return \constant("" . ($this->phpClassName??'null') . "::" . ($property??'null'));
|
||||
} else if (Boot::hasGetter($this->phpClassName, $property)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:687: characters 29-41
|
||||
$tmp = $this->phpClassName;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:687: characters 4-59
|
||||
return $tmp::{"get_" . ($property??'null')}();
|
||||
} else if (\method_exists($this->phpClassName, $property)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:689: characters 4-56
|
||||
return Boot::getStaticClosure($this->phpClassName, $property);
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:691: characters 33-45
|
||||
$tmp = $this->phpClassName;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:691: characters 4-56
|
||||
return $tmp::${$property};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method to set static vars of this class, when `HxClass` instance is in a `Dynamic` variable.
|
||||
*
|
||||
* @param string $property
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __set ($property, $value) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:700: lines 700-704
|
||||
if (Boot::hasSetter($this->phpClassName, $property)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:701: characters 22-34
|
||||
$tmp = $this->phpClassName;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:701: characters 4-59
|
||||
$tmp::{"set_" . ($property??'null')}($value);
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:703: characters 26-38
|
||||
$tmp = $this->phpClassName;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:703: characters 4-56
|
||||
$tmp::${$property} = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(HxClass::class, 'php._Boot.HxClass');
|
||||
114
dist/xrfragment.php/lib/php/_Boot/HxClosure.php
vendored
114
dist/xrfragment.php/lib/php/_Boot/HxClosure.php
vendored
|
|
@ -1,114 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
namespace php\_Boot;
|
||||
|
||||
use \php\Boot;
|
||||
use \haxe\Exception;
|
||||
|
||||
/**
|
||||
* Closures implementation
|
||||
*/
|
||||
class HxClosure {
|
||||
/**
|
||||
* @var mixed
|
||||
* A callable value, which can be invoked by PHP
|
||||
*/
|
||||
public $callable;
|
||||
/**
|
||||
* @var string
|
||||
* Method name for methods
|
||||
*/
|
||||
public $func;
|
||||
/**
|
||||
* @var mixed
|
||||
* `this` for instance methods; php class name for static methods
|
||||
*/
|
||||
public $target;
|
||||
|
||||
/**
|
||||
* @param mixed $target
|
||||
* @param string $func
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct ($target, $func) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:978: characters 3-23
|
||||
$this->target = $target;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:979: characters 3-19
|
||||
$this->func = $func;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:981: lines 981-983
|
||||
if (\is_null($target)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:982: characters 4-9
|
||||
throw Exception::thrown("Unable to create closure on `null`");
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:984: characters 3-104
|
||||
$this->callable = (($target instanceof HxAnon) ? $target->{$func} : [$target, $func]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see http://php.net/manual/en/language.oop5.magic.php#object.invoke
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:992: characters 3-71
|
||||
return \call_user_func_array($this->callable, \func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke this closure with `newThis` instead of `this`
|
||||
*
|
||||
* @param mixed $newThis
|
||||
* @param array $args
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function callWith ($newThis, $args) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:1019: characters 3-65
|
||||
return \call_user_func_array($this->getCallback($newThis), $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this is the same closure
|
||||
*
|
||||
* @param HxClosure $closure
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function equals ($closure) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:1012: characters 10-60
|
||||
if (Boot::equal($this->target, $closure->target)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:1012: characters 39-59
|
||||
return $this->func === $closure->func;
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:1012: characters 10-60
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates callable value for PHP
|
||||
*
|
||||
* @param mixed $eThis
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getCallback ($eThis = null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:999: lines 999-1001
|
||||
if ($eThis === null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:1000: characters 4-18
|
||||
$eThis = $this->target;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:1002: lines 1002-1004
|
||||
if (($eThis instanceof HxAnon)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:1003: characters 4-36
|
||||
return $eThis->{$this->func};
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:1005: characters 3-39
|
||||
return [$eThis, $this->func];
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(HxClosure::class, 'php._Boot.HxClosure');
|
||||
160
dist/xrfragment.php/lib/php/_Boot/HxDynamicStr.php
vendored
160
dist/xrfragment.php/lib/php/_Boot/HxDynamicStr.php
vendored
|
|
@ -1,160 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
namespace php\_Boot;
|
||||
|
||||
use \php\Boot;
|
||||
|
||||
/**
|
||||
* For Dynamic access which looks like String.
|
||||
* Instances of this class should not be saved anywhere.
|
||||
* Instead it should be used to immediately invoke a String field right after instance creation one time only.
|
||||
*/
|
||||
class HxDynamicStr extends HxClosure {
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
static public $hxString;
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @param string $method
|
||||
* @param array $args
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function invoke ($str, $method, $args) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:892: characters 3-34
|
||||
\array_unshift($args, $str);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:893: characters 3-69
|
||||
return \call_user_func_array((HxDynamicStr::$hxString??'null') . "::" . ($method??'null'), $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns HxDynamicStr instance if `value` is a string.
|
||||
* Otherwise returns `value` as-is.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function wrap ($value) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:884: lines 884-888
|
||||
if (\is_string($value)) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:885: characters 4-34
|
||||
return new HxDynamicStr($value);
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:887: characters 4-16
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct ($str) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:897: characters 3-19
|
||||
parent::__construct($str, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
* @param array $args
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call ($method, $args) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:913: characters 10-38
|
||||
\array_unshift($args, $this->target);
|
||||
return \call_user_func_array((HxDynamicStr::$hxString??'null') . "::" . ($method??'null'), $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get ($field) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:902: lines 902-908
|
||||
if ($field === "length") {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:904: characters 5-36
|
||||
return mb_strlen($this->target);
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:906: characters 5-17
|
||||
$this->func = $field;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:907: characters 5-16
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see http://php.net/manual/en/language.oop5.magic.php#object.invoke
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:921: characters 10-54
|
||||
$str = $this->target;
|
||||
$method = $this->func;
|
||||
$args = \func_get_args();
|
||||
\array_unshift($args, $str);
|
||||
return \call_user_func_array((HxDynamicStr::$hxString??'null') . "::" . ($method??'null'), $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke this closure with `newThis` instead of `this`
|
||||
*
|
||||
* @param mixed $newThis
|
||||
* @param array $args
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function callWith ($newThis, $args) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:938: lines 938-940
|
||||
if ($newThis === null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:939: characters 4-20
|
||||
$newThis = $this->target;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:941: characters 10-37
|
||||
$method = $this->func;
|
||||
\array_unshift($args, $newThis);
|
||||
return \call_user_func_array((HxDynamicStr::$hxString??'null') . "::" . ($method??'null'), $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates callable value for PHP
|
||||
*
|
||||
* @param mixed $eThis
|
||||
*
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getCallback ($eThis = null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:928: lines 928-930
|
||||
if ($eThis === null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:929: characters 4-51
|
||||
return [$this, $this->func];
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:931: characters 3-69
|
||||
return [new HxDynamicStr($eThis), $this->func];
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @access private
|
||||
*/
|
||||
static public function __hx__init ()
|
||||
{
|
||||
static $called = false;
|
||||
if ($called) return;
|
||||
$called = true;
|
||||
|
||||
|
||||
self::$hxString = Boot::getClass(HxString::class)->phpClassName;
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(HxDynamicStr::class, 'php._Boot.HxDynamicStr');
|
||||
HxDynamicStr::__hx__init();
|
||||
73
dist/xrfragment.php/lib/php/_Boot/HxEnum.php
vendored
73
dist/xrfragment.php/lib/php/_Boot/HxEnum.php
vendored
|
|
@ -1,73 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
namespace php\_Boot;
|
||||
|
||||
use \php\Boot;
|
||||
|
||||
/**
|
||||
* Base class for enum types
|
||||
*/
|
||||
class HxEnum {
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $index;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $params;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $tag;
|
||||
|
||||
/**
|
||||
* @param string $tag
|
||||
* @param int $index
|
||||
* @param array $arguments
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct ($tag, $index, $arguments = null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:721: characters 3-17
|
||||
$this->tag = $tag;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:722: characters 3-21
|
||||
$this->index = $index;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:723: characters 12-63
|
||||
$tmp = null;
|
||||
if ($arguments === null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:723: characters 33-50
|
||||
$this1 = [];
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:723: characters 12-63
|
||||
$tmp = $this1;
|
||||
} else {
|
||||
$tmp = $arguments;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:723: characters 3-63
|
||||
$this->params = $tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* PHP magic method to get string representation of this `Class`
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:738: characters 3-30
|
||||
return Boot::stringify($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string representation of this `Class`
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toString () {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:730: characters 3-22
|
||||
return $this->__toString();
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(HxEnum::class, 'php._Boot.HxEnum');
|
||||
294
dist/xrfragment.php/lib/php/_Boot/HxString.php
vendored
294
dist/xrfragment.php/lib/php/_Boot/HxString.php
vendored
|
|
@ -1,294 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
namespace php\_Boot;
|
||||
|
||||
use \php\Boot;
|
||||
|
||||
/**
|
||||
* `String` implementation
|
||||
*/
|
||||
class HxString {
|
||||
/**
|
||||
* @param string $str
|
||||
* @param int $index
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function charAt ($str, $index) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:759: characters 10-58
|
||||
if ($index < 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:759: characters 22-24
|
||||
return "";
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:759: characters 27-58
|
||||
return \mb_substr($str, $index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @param int $index
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function charCodeAt ($str, $index) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:763: lines 763-765
|
||||
if (($index < 0) || ($str === "")) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:764: characters 4-15
|
||||
return null;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:766: lines 766-768
|
||||
if ($index === 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:767: characters 11-30
|
||||
$code = \ord($str[0]);
|
||||
if ($code < 192) {
|
||||
return $code;
|
||||
} else if ($code < 224) {
|
||||
return (($code - 192) << 6) + \ord($str[1]) - 128;
|
||||
} else if ($code < 240) {
|
||||
return (($code - 224) << 12) + ((\ord($str[1]) - 128) << 6) + \ord($str[2]) - 128;
|
||||
} else {
|
||||
return (($code - 240) << 18) + ((\ord($str[1]) - 128) << 12) + ((\ord($str[2]) - 128) << 6) + \ord($str[3]) - 128;
|
||||
}
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:769: characters 3-46
|
||||
$char = \mb_substr($str, $index, 1);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:770: characters 10-50
|
||||
if ($char === "") {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:770: characters 23-27
|
||||
return null;
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:770: characters 30-50
|
||||
$code = \ord($char[0]);
|
||||
if ($code < 192) {
|
||||
return $code;
|
||||
} else if ($code < 224) {
|
||||
return (($code - 192) << 6) + \ord($char[1]) - 128;
|
||||
} else if ($code < 240) {
|
||||
return (($code - 224) << 12) + ((\ord($char[1]) - 128) << 6) + \ord($char[2]) - 128;
|
||||
} else {
|
||||
return (($code - 240) << 18) + ((\ord($char[1]) - 128) << 12) + ((\ord($char[2]) - 128) << 6) + \ord($char[3]) - 128;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function fromCharCode ($code) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:865: characters 3-29
|
||||
return \mb_chr($code);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @param string $search
|
||||
* @param int $startIndex
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function indexOf ($str, $search, $startIndex = null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:774: lines 774-787
|
||||
if ($startIndex === null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:775: characters 4-18
|
||||
$startIndex = 0;
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:777: characters 4-28
|
||||
$length = mb_strlen($str);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:778: lines 778-783
|
||||
if ($startIndex < 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:779: characters 5-25
|
||||
$startIndex += $length;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:780: lines 780-782
|
||||
if ($startIndex < 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:781: characters 6-20
|
||||
$startIndex = 0;
|
||||
}
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:784: lines 784-786
|
||||
if (($startIndex >= $length) && ($search !== "")) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:785: characters 5-14
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:788: lines 788-793
|
||||
$index = null;
|
||||
if ($search === "") {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:789: characters 4-28
|
||||
$length = mb_strlen($str);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:788: lines 788-793
|
||||
$index = ($startIndex > $length ? $length : $startIndex);
|
||||
} else {
|
||||
$index = \mb_strpos($str, $search, $startIndex);
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:794: characters 10-39
|
||||
if ($index === false) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:794: characters 28-30
|
||||
return -1;
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:794: characters 33-38
|
||||
return $index;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @param string $search
|
||||
* @param int $startIndex
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function lastIndexOf ($str, $search, $startIndex = null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:798: characters 3-26
|
||||
$start = $startIndex;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:799: lines 799-811
|
||||
if ($start === null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:800: characters 4-13
|
||||
$start = 0;
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:802: characters 4-28
|
||||
$length = mb_strlen($str);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:803: lines 803-810
|
||||
if ($start >= 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:804: characters 5-27
|
||||
$start -= $length;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:805: lines 805-807
|
||||
if ($start > 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:806: characters 6-15
|
||||
$start = 0;
|
||||
}
|
||||
} else if ($start < -$length) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:809: characters 5-20
|
||||
$start = -$length;
|
||||
}
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:812: lines 812-817
|
||||
$index = null;
|
||||
if ($search === "") {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:813: characters 4-28
|
||||
$length = mb_strlen($str);
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:812: lines 812-817
|
||||
$index = (($startIndex === null) || ($startIndex > $length) ? $length : $startIndex);
|
||||
} else {
|
||||
$index = \mb_strrpos($str, $search, $start);
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:818: lines 818-822
|
||||
if ($index === false) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:819: characters 4-13
|
||||
return -1;
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:821: characters 4-16
|
||||
return $index;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @param string $delimiter
|
||||
*
|
||||
* @return string[]|\Array_hx
|
||||
*/
|
||||
public static function split ($str, $delimiter) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:826: lines 826-831
|
||||
$arr = null;
|
||||
if ($delimiter === "") {
|
||||
$arr = \preg_split("//u", $str, -1, \PREG_SPLIT_NO_EMPTY);
|
||||
} else {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:829: characters 4-49
|
||||
$delimiter = \preg_quote($delimiter, "/");
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:826: lines 826-831
|
||||
$arr = \preg_split("/" . ($delimiter??'null') . "/", $str);
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:832: characters 3-41
|
||||
return \Array_hx::wrap($arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @param int $pos
|
||||
* @param int $len
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function substr ($str, $pos, $len = null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:836: characters 3-41
|
||||
return \mb_substr($str, $pos, $len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
* @param int $startIndex
|
||||
* @param int $endIndex
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function substring ($str, $startIndex, $endIndex = null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:840: lines 840-845
|
||||
if ($endIndex === null) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:841: lines 841-843
|
||||
if ($startIndex < 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:842: characters 5-19
|
||||
$startIndex = 0;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:844: characters 4-44
|
||||
return \mb_substr($str, $startIndex);
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:846: lines 846-848
|
||||
if ($endIndex < 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:847: characters 4-16
|
||||
$endIndex = 0;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:849: lines 849-851
|
||||
if ($startIndex < 0) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:850: characters 4-18
|
||||
$startIndex = 0;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:852: lines 852-856
|
||||
if ($startIndex > $endIndex) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:853: characters 4-23
|
||||
$tmp = $endIndex;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:854: characters 4-25
|
||||
$endIndex = $startIndex;
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:855: characters 4-20
|
||||
$startIndex = $tmp;
|
||||
}
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:857: characters 3-66
|
||||
return \mb_substr($str, $startIndex, $endIndex - $startIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function toLowerCase ($str) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:755: characters 3-35
|
||||
return \mb_strtolower($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function toString ($str) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:861: characters 3-13
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function toUpperCase ($str) {
|
||||
#/nix/store/ljakxdz94hcvn9b4k9y292dn5lhh20iy-haxe-4.2.5/lib/haxe/std/php/Boot.hx:751: characters 3-35
|
||||
return \mb_strtoupper($str);
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(HxString::class, 'php._Boot.HxString');
|
||||
63
dist/xrfragment.php/lib/php/_polyfills.php
vendored
63
dist/xrfragment.php/lib/php/_polyfills.php
vendored
|
|
@ -1,63 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Polyfills for some functions, which are required by Haxe-generated code, but not available in PHP 7.0.
|
||||
* No Haxe-generated code is available at this point.
|
||||
* No code should be executed from this file.
|
||||
* Symbols declarations are the only code allowed here.
|
||||
*/
|
||||
namespace { //Namespace declaration is required because this file is included under non-root namespace.
|
||||
|
||||
/**
|
||||
* @see http://php.net/manual/en/function.mb-chr.php
|
||||
*/
|
||||
if(!function_exists('mb_chr')) {
|
||||
function mb_chr($code, $encoding = null) {
|
||||
if($encoding && $encoding !== 'UTF-8') {
|
||||
throw new Exception("$encoding is not supported in mb_chr() polyfill.");
|
||||
}
|
||||
if (0x80 > $code %= 0x200000) {
|
||||
$s = chr($code);
|
||||
} elseif (0x800 > $code) {
|
||||
$s = chr(0xC0 | $code >> 6) . chr(0x80 | $code & 0x3F);
|
||||
} elseif (0x10000 > $code) {
|
||||
$s = chr(0xE0 | $code >> 12) . chr(0x80 | $code >> 6 & 0x3F) . chr(0x80 | $code & 0x3F);
|
||||
} else {
|
||||
$s = chr(0xF0 | $code >> 18) . chr(0x80 | $code >> 12 & 0x3F) . chr(0x80 | $code >> 6 & 0x3F) . chr(0x80 | $code & 0x3F);
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see http://php.net/manual/en/function.mb-ord.php
|
||||
*/
|
||||
if(!function_exists('mb_ord')) {
|
||||
function mb_ord($s, $encoding = null) {
|
||||
if($encoding && $encoding !== 'UTF-8') {
|
||||
throw new Exception("$encoding is not supported in mb_ord() polyfill.");
|
||||
}
|
||||
$code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
|
||||
if (0xF0 <= $code) {
|
||||
return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
|
||||
}
|
||||
if (0xE0 <= $code) {
|
||||
return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
|
||||
}
|
||||
if (0xC0 <= $code) {
|
||||
return (($code - 0xC0) << 6) + $s[2] - 0x80;
|
||||
}
|
||||
return $code;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see http://php.net/manual/en/function.mb-scrub.php
|
||||
*/
|
||||
if(!function_exists('mb_scrub')) {
|
||||
function mb_scrub($s, $encoding = null) {
|
||||
$encoding = null === $encoding ? mb_internal_encoding() : $encoding;
|
||||
return mb_convert_encoding($s, $encoding, $encoding);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
139
dist/xrfragment.php/lib/xrfragment/Parser.php
vendored
139
dist/xrfragment.php/lib/xrfragment/Parser.php
vendored
|
|
@ -1,139 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
namespace xrfragment;
|
||||
|
||||
use \php\_Boot\HxAnon;
|
||||
use \php\Boot;
|
||||
use \haxe\Log;
|
||||
use \php\_Boot\HxString;
|
||||
|
||||
class Parser {
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
static public $debug = false;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
static public $error = "";
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
* @param mixed $store
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function parse ($key, $value, $store) {
|
||||
#src/xrfragment/Parser.hx:17: characters 35-57
|
||||
$this1 = [];
|
||||
$Frag_data = $this1;
|
||||
#src/xrfragment/Parser.hx:20: characters 7-68
|
||||
$Frag_data["prio"] = XRF::$ASSET | XRF::$T_INT;
|
||||
#src/xrfragment/Parser.hx:21: characters 7-68
|
||||
$Frag_data["#"] = XRF::$ASSET | XRF::$T_PREDEFINED_VIEW;
|
||||
#src/xrfragment/Parser.hx:22: characters 7-68
|
||||
$Frag_data["class"] = XRF::$ASSET | XRF::$T_STRING;
|
||||
#src/xrfragment/Parser.hx:23: characters 7-68
|
||||
$Frag_data["src"] = XRF::$ASSET | XRF::$T_URL;
|
||||
#src/xrfragment/Parser.hx:26: characters 7-133
|
||||
$Frag_data["pos"] = XRF::$PV_OVERRIDE | XRF::$ROUNDROBIN | XRF::$T_VECTOR3 | XRF::$T_STRING_OBJ | XRF::$EMBEDDED | XRF::$NAVIGATOR;
|
||||
#src/xrfragment/Parser.hx:27: characters 7-97
|
||||
$Frag_data["href"] = XRF::$ASSET | XRF::$T_URL | XRF::$T_PREDEFINED_VIEW;
|
||||
#src/xrfragment/Parser.hx:30: characters 7-98
|
||||
$Frag_data["q"] = XRF::$PV_OVERRIDE | XRF::$T_STRING | XRF::$EMBEDDED;
|
||||
#src/xrfragment/Parser.hx:31: characters 7-119
|
||||
$Frag_data["scale"] = XRF::$QUERY_OPERATOR | XRF::$PV_OVERRIDE | XRF::$ROUNDROBIN | XRF::$T_VECTOR3 | XRF::$EMBEDDED;
|
||||
#src/xrfragment/Parser.hx:32: characters 7-135
|
||||
$Frag_data["rot"] = XRF::$QUERY_OPERATOR | XRF::$PV_OVERRIDE | XRF::$ROUNDROBIN | XRF::$T_VECTOR3 | XRF::$EMBEDDED | XRF::$NAVIGATOR;
|
||||
#src/xrfragment/Parser.hx:33: characters 7-119
|
||||
$Frag_data["translate"] = XRF::$QUERY_OPERATOR | XRF::$PV_OVERRIDE | XRF::$ROUNDROBIN | XRF::$T_VECTOR3 | XRF::$EMBEDDED;
|
||||
#src/xrfragment/Parser.hx:34: characters 7-119
|
||||
$Frag_data["visible"] = XRF::$QUERY_OPERATOR | XRF::$PV_OVERRIDE | XRF::$ROUNDROBIN | XRF::$T_INT | XRF::$EMBEDDED;
|
||||
#src/xrfragment/Parser.hx:35: characters 7-92
|
||||
$Frag_data["env"] = XRF::$ASSET | XRF::$PV_OVERRIDE | XRF::$T_STRING | XRF::$EMBEDDED;
|
||||
#src/xrfragment/Parser.hx:38: characters 7-125
|
||||
$Frag_data["t"] = XRF::$ASSET | XRF::$PV_OVERRIDE | XRF::$ROUNDROBIN | XRF::$T_VECTOR2 | XRF::$NAVIGATOR | XRF::$EMBEDDED;
|
||||
#src/xrfragment/Parser.hx:39: characters 7-93
|
||||
$Frag_data["gravity"] = XRF::$ASSET | XRF::$PV_OVERRIDE | XRF::$T_VECTOR3 | XRF::$EMBEDDED;
|
||||
#src/xrfragment/Parser.hx:40: characters 7-93
|
||||
$Frag_data["physics"] = XRF::$ASSET | XRF::$PV_OVERRIDE | XRF::$T_VECTOR3 | XRF::$EMBEDDED;
|
||||
#src/xrfragment/Parser.hx:43: characters 7-109
|
||||
$Frag_data["fov"] = XRF::$ASSET | XRF::$PV_OVERRIDE | XRF::$T_INT | XRF::$NAVIGATOR | XRF::$EMBEDDED;
|
||||
#src/xrfragment/Parser.hx:44: characters 7-109
|
||||
$Frag_data["clip"] = XRF::$ASSET | XRF::$PV_OVERRIDE | XRF::$T_VECTOR2 | XRF::$NAVIGATOR | XRF::$EMBEDDED;
|
||||
#src/xrfragment/Parser.hx:45: characters 7-109
|
||||
$Frag_data["fog"] = XRF::$ASSET | XRF::$PV_OVERRIDE | XRF::$T_STRING | XRF::$NAVIGATOR | XRF::$EMBEDDED;
|
||||
#src/xrfragment/Parser.hx:48: characters 7-92
|
||||
$Frag_data["namespace"] = XRF::$ASSET | XRF::$T_STRING;
|
||||
#src/xrfragment/Parser.hx:49: characters 7-92
|
||||
$Frag_data["SPDX"] = XRF::$ASSET | XRF::$T_STRING;
|
||||
#src/xrfragment/Parser.hx:50: characters 7-92
|
||||
$Frag_data["unit"] = XRF::$ASSET | XRF::$T_STRING;
|
||||
#src/xrfragment/Parser.hx:51: characters 7-92
|
||||
$Frag_data["description"] = XRF::$ASSET | XRF::$T_STRING;
|
||||
#src/xrfragment/Parser.hx:54: characters 7-114
|
||||
$Frag_data["session"] = XRF::$ASSET | XRF::$T_URL | XRF::$PV_OVERRIDE | XRF::$NAVIGATOR | XRF::$EMBEDDED | XRF::$PROMPT;
|
||||
#src/xrfragment/Parser.hx:67: lines 67-72
|
||||
if ((mb_strlen($value) === 0) && (mb_strlen($key) > 0) && !\array_key_exists($key, $Frag_data)) {
|
||||
#src/xrfragment/Parser.hx:68: characters 5-64
|
||||
$v = new XRF($key, XRF::$PV_EXECUTE | XRF::$NAVIGATOR);
|
||||
#src/xrfragment/Parser.hx:69: characters 9-24
|
||||
$v->validate($key);
|
||||
#src/xrfragment/Parser.hx:70: characters 5-23
|
||||
\Reflect::setField($store, $key, $v);
|
||||
#src/xrfragment/Parser.hx:71: characters 5-16
|
||||
return true;
|
||||
}
|
||||
#src/xrfragment/Parser.hx:73: lines 73-76
|
||||
if ((HxString::split($key, ".")->length > 1) && (HxString::split($value, ".")->length > 1)) {
|
||||
#src/xrfragment/Parser.hx:74: characters 5-95
|
||||
$value1 = new XRF($key, XRF::$ASSET | XRF::$PV_OVERRIDE | XRF::$T_STRING | XRF::$PROP_BIND);
|
||||
\Reflect::setField($store, $key, $value1);
|
||||
#src/xrfragment/Parser.hx:75: characters 5-16
|
||||
return true;
|
||||
}
|
||||
#src/xrfragment/Parser.hx:79: characters 7-47
|
||||
$v = new XRF($key, ($Frag_data[$key] ?? null));
|
||||
#src/xrfragment/Parser.hx:80: lines 80-90
|
||||
if (\array_key_exists($key, $Frag_data)) {
|
||||
#src/xrfragment/Parser.hx:81: lines 81-84
|
||||
if (!$v->validate($value)) {
|
||||
#src/xrfragment/Parser.hx:82: characters 11-16
|
||||
(Log::$trace)("⚠ fragment '" . ($key??'null') . "' has incompatible value (" . ($value??'null') . ")", new _HxAnon_Parser0("src/xrfragment/Parser.hx", 82, "xrfragment.Parser", "parse"));
|
||||
#src/xrfragment/Parser.hx:83: characters 11-23
|
||||
return false;
|
||||
}
|
||||
#src/xrfragment/Parser.hx:85: characters 9-27
|
||||
\Reflect::setField($store, $key, $v);
|
||||
#src/xrfragment/Parser.hx:86: characters 9-50
|
||||
if (Parser::$debug) {
|
||||
#src/xrfragment/Parser.hx:86: characters 21-26
|
||||
(Log::$trace)("✔ " . ($key??'null') . ": " . ($v->string??'null'), new _HxAnon_Parser0("src/xrfragment/Parser.hx", 86, "xrfragment.Parser", "parse"));
|
||||
}
|
||||
} else {
|
||||
#src/xrfragment/Parser.hx:88: characters 9-63
|
||||
if (is_string($value)) {
|
||||
#src/xrfragment/Parser.hx:88: characters 43-63
|
||||
$v->guessType($v, $value);
|
||||
}
|
||||
#src/xrfragment/Parser.hx:89: characters 9-29
|
||||
\Reflect::setField($store, "_" . ($key??'null'), $v);
|
||||
}
|
||||
#src/xrfragment/Parser.hx:92: characters 7-18
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class _HxAnon_Parser0 extends HxAnon {
|
||||
function __construct($fileName, $lineNumber, $className, $methodName) {
|
||||
$this->fileName = $fileName;
|
||||
$this->lineNumber = $lineNumber;
|
||||
$this->className = $className;
|
||||
$this->methodName = $methodName;
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(Parser::class, 'xrfragment.Parser');
|
||||
393
dist/xrfragment.php/lib/xrfragment/Query.php
vendored
393
dist/xrfragment.php/lib/xrfragment/Query.php
vendored
|
|
@ -1,393 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
namespace xrfragment;
|
||||
|
||||
use \php\_Boot\HxAnon;
|
||||
use \php\Boot;
|
||||
use \php\_Boot\HxString;
|
||||
|
||||
class Query {
|
||||
/**
|
||||
* @var \EReg
|
||||
*/
|
||||
public $isClass;
|
||||
/**
|
||||
* @var \EReg
|
||||
*/
|
||||
public $isExclude;
|
||||
/**
|
||||
* @var \EReg
|
||||
*/
|
||||
public $isNumber;
|
||||
/**
|
||||
* @var \EReg
|
||||
*/
|
||||
public $isProp;
|
||||
/**
|
||||
* @var \EReg
|
||||
*/
|
||||
public $isRoot;
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
public $q;
|
||||
/**
|
||||
* @var string
|
||||
* # Spec
|
||||
*
|
||||
* > version 1.0.0 [](https://github.com/coderofsalvation/xrfragment/actions) generated by `make doc` @ $(date +"%Y-%m-%dT%H:%M:%S%z")
|
||||
*
|
||||
* In case your programming language has no parser ([check here](https://github.com/coderofsalvation/xrfragment/tree/main/dist)) you can [crosscompile it](https://github.com/coderofsalvation/xrfragment/blob/main/build.hxml), or roll your own `Query.parse(str)` using the spec:
|
||||
*/
|
||||
public $str;
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct ($str) {
|
||||
#src/xrfragment/Query.hx:59: characters 36-49
|
||||
$this->isNumber = new \EReg("^[0-9\\.]+\$", "");
|
||||
#src/xrfragment/Query.hx:58: characters 36-50
|
||||
$this->isClass = new \EReg("^[-]?class\$", "");
|
||||
#src/xrfragment/Query.hx:57: characters 36-46
|
||||
$this->isRoot = new \EReg("^[-]?/", "");
|
||||
#src/xrfragment/Query.hx:56: characters 36-41
|
||||
$this->isExclude = new \EReg("^-", "");
|
||||
#src/xrfragment/Query.hx:55: characters 36-50
|
||||
$this->isProp = new \EReg("^.*:[><=!]?", "");
|
||||
#src/xrfragment/Query.hx:54: characters 47-49
|
||||
$this->q = new HxAnon();
|
||||
#src/xrfragment/Query.hx:53: characters 28-30
|
||||
$this->str = "";
|
||||
#src/xrfragment/Query.hx:62: characters 5-39
|
||||
if ($str !== null) {
|
||||
#src/xrfragment/Query.hx:62: characters 24-39
|
||||
$this->parse($str);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $token
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function expandAliases ($token) {
|
||||
#src/xrfragment/Query.hx:71: characters 5-33
|
||||
$classAlias = new \EReg("^(-)?\\.", "");
|
||||
#src/xrfragment/Query.hx:72: characters 12-85
|
||||
if ($classAlias->match($token)) {
|
||||
#src/xrfragment/Query.hx:72: characters 38-77
|
||||
return \StringTools::replace($token, ".", "class:");
|
||||
} else {
|
||||
#src/xrfragment/Query.hx:72: characters 80-85
|
||||
return $token;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function get () {
|
||||
#src/xrfragment/Query.hx:76: characters 5-18
|
||||
return $this->q;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $str
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function parse ($str) {
|
||||
#src/xrfragment/Query.hx:79: lines 79-126
|
||||
$_gthis = $this;
|
||||
#src/xrfragment/Query.hx:81: characters 5-32
|
||||
$token = HxString::split($str, " ");
|
||||
#src/xrfragment/Query.hx:82: characters 5-44
|
||||
$q = new HxAnon();
|
||||
#src/xrfragment/Query.hx:84: lines 84-123
|
||||
$process = function ($str, $prefix = "") use (&$_gthis, &$q) {
|
||||
if ($prefix === null) {
|
||||
$prefix = "";
|
||||
}
|
||||
#src/xrfragment/Query.hx:85: characters 7-34
|
||||
$str = \trim($str);
|
||||
#src/xrfragment/Query.hx:86: characters 7-40
|
||||
$k = (HxString::split($str, ":")->arr[0] ?? null);
|
||||
#src/xrfragment/Query.hx:87: characters 7-40
|
||||
$v = (HxString::split($str, ":")->arr[1] ?? null);
|
||||
#src/xrfragment/Query.hx:89: characters 7-51
|
||||
$filter = new HxAnon();
|
||||
#src/xrfragment/Query.hx:90: characters 7-53
|
||||
if (\Reflect::field($q, ($prefix??'null') . ($k??'null'))) {
|
||||
#src/xrfragment/Query.hx:90: characters 29-53
|
||||
$filter = \Reflect::field($q, ($prefix??'null') . ($k??'null'));
|
||||
}
|
||||
#src/xrfragment/Query.hx:91: characters 7-89
|
||||
$value = (\Reflect::field($filter, "rules") !== null ? \Reflect::field($filter, "rules") : new \Array_hx());
|
||||
\Reflect::setField($filter, "rules", $value);
|
||||
#src/xrfragment/Query.hx:93: lines 93-122
|
||||
if ($_gthis->isProp->match($str)) {
|
||||
#src/xrfragment/Query.hx:94: characters 9-30
|
||||
$oper = "";
|
||||
#src/xrfragment/Query.hx:95: characters 9-49
|
||||
if (HxString::indexOf($str, "*") !== -1) {
|
||||
#src/xrfragment/Query.hx:95: characters 39-49
|
||||
$oper = "*";
|
||||
}
|
||||
#src/xrfragment/Query.hx:96: characters 9-49
|
||||
if (HxString::indexOf($str, ">") !== -1) {
|
||||
#src/xrfragment/Query.hx:96: characters 39-49
|
||||
$oper = ">";
|
||||
}
|
||||
#src/xrfragment/Query.hx:97: characters 9-49
|
||||
if (HxString::indexOf($str, "<") !== -1) {
|
||||
#src/xrfragment/Query.hx:97: characters 39-49
|
||||
$oper = "<";
|
||||
}
|
||||
#src/xrfragment/Query.hx:98: characters 9-50
|
||||
if (HxString::indexOf($str, ">=") !== -1) {
|
||||
#src/xrfragment/Query.hx:98: characters 39-50
|
||||
$oper = ">=";
|
||||
}
|
||||
#src/xrfragment/Query.hx:99: characters 9-50
|
||||
if (HxString::indexOf($str, "<=") !== -1) {
|
||||
#src/xrfragment/Query.hx:99: characters 39-50
|
||||
$oper = "<=";
|
||||
}
|
||||
#src/xrfragment/Query.hx:100: lines 100-103
|
||||
if ($_gthis->isExclude->match($k)) {
|
||||
#src/xrfragment/Query.hx:101: characters 11-22
|
||||
$oper = "!=";
|
||||
#src/xrfragment/Query.hx:102: characters 15-26
|
||||
$k = \mb_substr($k, 1, null);
|
||||
} else {
|
||||
#src/xrfragment/Query.hx:103: characters 19-40
|
||||
$v = \mb_substr($v, mb_strlen($oper), null);
|
||||
}
|
||||
#src/xrfragment/Query.hx:104: characters 9-42
|
||||
if (mb_strlen($oper) === 0) {
|
||||
#src/xrfragment/Query.hx:104: characters 32-42
|
||||
$oper = "=";
|
||||
}
|
||||
#src/xrfragment/Query.hx:105: lines 105-114
|
||||
if ($_gthis->isClass->match($k)) {
|
||||
#src/xrfragment/Query.hx:106: characters 11-45
|
||||
$value = $oper !== "!=";
|
||||
\Reflect::setField($filter, ($prefix??'null') . ($k??'null'), $value);
|
||||
#src/xrfragment/Query.hx:107: characters 11-26
|
||||
\Reflect::setField($q, $v, $filter);
|
||||
} else {
|
||||
#src/xrfragment/Query.hx:109: characters 11-53
|
||||
$rule = new HxAnon();
|
||||
#src/xrfragment/Query.hx:110: lines 110-111
|
||||
if ($_gthis->isNumber->match($v)) {
|
||||
#src/xrfragment/Query.hx:110: characters 35-67
|
||||
$value = \Std::parseFloat($v);
|
||||
\Reflect::setField($rule, $oper, $value);
|
||||
} else {
|
||||
#src/xrfragment/Query.hx:111: characters 16-30
|
||||
\Reflect::setField($rule, $oper, $v);
|
||||
}
|
||||
#src/xrfragment/Query.hx:112: characters 11-39
|
||||
\Reflect::field($filter, "rules")->push($rule);
|
||||
#src/xrfragment/Query.hx:113: characters 11-29
|
||||
\Reflect::setField($q, $k, $filter);
|
||||
}
|
||||
#src/xrfragment/Query.hx:115: characters 9-15
|
||||
return;
|
||||
} else {
|
||||
#src/xrfragment/Query.hx:117: characters 9-62
|
||||
$value = ($_gthis->isExclude->match($str) ? false : true);
|
||||
\Reflect::setField($filter, "id", $value);
|
||||
#src/xrfragment/Query.hx:118: characters 9-63
|
||||
$value = $_gthis->isRoot->match($str);
|
||||
\Reflect::setField($filter, "root", $value);
|
||||
#src/xrfragment/Query.hx:119: characters 9-55
|
||||
if ($_gthis->isExclude->match($str)) {
|
||||
#src/xrfragment/Query.hx:119: characters 42-55
|
||||
$str = \mb_substr($str, 1, null);
|
||||
}
|
||||
#src/xrfragment/Query.hx:120: characters 9-55
|
||||
if ($_gthis->isRoot->match($str)) {
|
||||
#src/xrfragment/Query.hx:120: characters 42-55
|
||||
$str = \mb_substr($str, 1, null);
|
||||
}
|
||||
#src/xrfragment/Query.hx:121: characters 9-29
|
||||
\Reflect::setField($q, $str, $filter);
|
||||
}
|
||||
};
|
||||
#src/xrfragment/Query.hx:124: characters 15-19
|
||||
$_g = 0;
|
||||
#src/xrfragment/Query.hx:124: characters 19-31
|
||||
$_g1 = $token->length;
|
||||
#src/xrfragment/Query.hx:124: characters 5-68
|
||||
while ($_g < $_g1) {
|
||||
#src/xrfragment/Query.hx:124: characters 15-31
|
||||
$i = $_g++;
|
||||
#src/xrfragment/Query.hx:124: characters 34-68
|
||||
$process($this->expandAliases(($token->arr[$i] ?? null)));
|
||||
}
|
||||
#src/xrfragment/Query.hx:125: characters 5-22
|
||||
return $this->q = $q;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $obj
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function test ($obj = null) {
|
||||
#src/xrfragment/Query.hx:130: characters 5-30
|
||||
$qualify = false;
|
||||
#src/xrfragment/Query.hx:132: lines 132-135
|
||||
$_g = 0;
|
||||
$_g1 = \Reflect::fields($obj);
|
||||
while ($_g < $_g1->length) {
|
||||
#src/xrfragment/Query.hx:132: characters 11-12
|
||||
$k = ($_g1->arr[$_g] ?? null);
|
||||
#src/xrfragment/Query.hx:132: lines 132-135
|
||||
++$_g;
|
||||
#src/xrfragment/Query.hx:133: characters 7-57
|
||||
$v = \Std::string(\Reflect::field($obj, $k));
|
||||
#src/xrfragment/Query.hx:134: characters 7-47
|
||||
if ($this->testProperty($k, $v)) {
|
||||
#src/xrfragment/Query.hx:134: characters 33-47
|
||||
$qualify = true;
|
||||
}
|
||||
}
|
||||
#src/xrfragment/Query.hx:136: lines 136-139
|
||||
$_g = 0;
|
||||
$_g1 = \Reflect::fields($obj);
|
||||
while ($_g < $_g1->length) {
|
||||
#src/xrfragment/Query.hx:136: characters 11-12
|
||||
$k = ($_g1->arr[$_g] ?? null);
|
||||
#src/xrfragment/Query.hx:136: lines 136-139
|
||||
++$_g;
|
||||
#src/xrfragment/Query.hx:137: characters 7-57
|
||||
$v = \Std::string(\Reflect::field($obj, $k));
|
||||
#src/xrfragment/Query.hx:138: characters 7-54
|
||||
if ($this->testProperty($k, $v, true)) {
|
||||
#src/xrfragment/Query.hx:138: characters 39-54
|
||||
$qualify = false;
|
||||
}
|
||||
}
|
||||
#src/xrfragment/Query.hx:140: characters 5-19
|
||||
return $qualify;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $property
|
||||
* @param string $value
|
||||
* @param bool $exclude
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function testProperty ($property, $value, $exclude = null) {
|
||||
#src/xrfragment/Query.hx:145: characters 5-23
|
||||
$conds = 0;
|
||||
#src/xrfragment/Query.hx:146: characters 5-23
|
||||
$fails = 0;
|
||||
#src/xrfragment/Query.hx:147: characters 5-26
|
||||
$qualify = 0;
|
||||
#src/xrfragment/Query.hx:149: lines 149-153
|
||||
$testprop = function ($expr) use (&$conds, &$fails) {
|
||||
#src/xrfragment/Query.hx:150: characters 7-15
|
||||
$conds += 1;
|
||||
#src/xrfragment/Query.hx:151: characters 7-27
|
||||
$fails += ($expr ? 0 : 1);
|
||||
#src/xrfragment/Query.hx:152: characters 7-18
|
||||
return $expr;
|
||||
};
|
||||
#src/xrfragment/Query.hx:156: lines 156-159
|
||||
if (\Reflect::field($this->q, $value) !== null) {
|
||||
#src/xrfragment/Query.hx:157: characters 7-52
|
||||
$v = \Reflect::field($this->q, $value);
|
||||
#src/xrfragment/Query.hx:158: characters 7-59
|
||||
if (\Reflect::field($v, $property) !== null) {
|
||||
#src/xrfragment/Query.hx:158: characters 37-59
|
||||
return \Reflect::field($v, $property);
|
||||
}
|
||||
}
|
||||
#src/xrfragment/Query.hx:162: lines 162-183
|
||||
$_g = 0;
|
||||
$_g1 = \Reflect::fields($this->q);
|
||||
while ($_g < $_g1->length) {
|
||||
#src/xrfragment/Query.hx:162: characters 11-12
|
||||
$k = ($_g1->arr[$_g] ?? null);
|
||||
#src/xrfragment/Query.hx:162: lines 162-183
|
||||
++$_g;
|
||||
#src/xrfragment/Query.hx:163: characters 7-47
|
||||
$filter = \Reflect::field($this->q, $k);
|
||||
#src/xrfragment/Query.hx:164: characters 7-43
|
||||
if (Boot::dynamicField($filter, 'rules') === null) {
|
||||
#src/xrfragment/Query.hx:164: characters 35-43
|
||||
continue;
|
||||
}
|
||||
#src/xrfragment/Query.hx:165: characters 7-47
|
||||
$rules = Boot::dynamicField($filter, 'rules');
|
||||
#src/xrfragment/Query.hx:167: lines 167-182
|
||||
$_g2 = 0;
|
||||
while ($_g2 < $rules->length) {
|
||||
#src/xrfragment/Query.hx:167: characters 12-16
|
||||
$rule = ($rules->arr[$_g2] ?? null);
|
||||
#src/xrfragment/Query.hx:167: lines 167-182
|
||||
++$_g2;
|
||||
#src/xrfragment/Query.hx:169: lines 169-181
|
||||
if ($exclude) {
|
||||
#src/xrfragment/Query.hx:170: characters 11-145
|
||||
if ((\Reflect::field($rule, "!=") !== null) && $testprop(\Std::string($value) === \Std::string(\Reflect::field($rule, "!="))) && $exclude) {
|
||||
#src/xrfragment/Query.hx:170: characters 133-145
|
||||
++$qualify;
|
||||
}
|
||||
} else {
|
||||
#src/xrfragment/Query.hx:172: characters 11-141
|
||||
if ((\Reflect::field($rule, "*") !== null) && $testprop(\Std::parseFloat($value) !== null)) {
|
||||
#src/xrfragment/Query.hx:172: characters 129-141
|
||||
++$qualify;
|
||||
}
|
||||
#src/xrfragment/Query.hx:173: characters 11-143
|
||||
if ((\Reflect::field($rule, ">") !== null) && $testprop(\Std::parseFloat($value) > \Std::parseFloat(\Reflect::field($rule, ">")))) {
|
||||
#src/xrfragment/Query.hx:173: characters 131-143
|
||||
++$qualify;
|
||||
}
|
||||
#src/xrfragment/Query.hx:174: characters 11-143
|
||||
if ((\Reflect::field($rule, "<") !== null) && $testprop(\Std::parseFloat($value) < \Std::parseFloat(\Reflect::field($rule, "<")))) {
|
||||
#src/xrfragment/Query.hx:174: characters 131-143
|
||||
++$qualify;
|
||||
}
|
||||
#src/xrfragment/Query.hx:175: characters 11-143
|
||||
if ((\Reflect::field($rule, ">=") !== null) && $testprop(\Std::parseFloat($value) >= \Std::parseFloat(\Reflect::field($rule, ">=")))) {
|
||||
#src/xrfragment/Query.hx:175: characters 131-143
|
||||
++$qualify;
|
||||
}
|
||||
#src/xrfragment/Query.hx:176: characters 11-143
|
||||
if ((\Reflect::field($rule, "<=") !== null) && $testprop(\Std::parseFloat($value) <= \Std::parseFloat(\Reflect::field($rule, "<=")))) {
|
||||
#src/xrfragment/Query.hx:176: characters 131-143
|
||||
++$qualify;
|
||||
}
|
||||
#src/xrfragment/Query.hx:177: lines 177-180
|
||||
if ((\Reflect::field($rule, "=") !== null) && ($testprop($value === \Reflect::field($rule, "=")) || $testprop(Boot::equal(\Std::parseFloat($value), \Std::parseFloat(\Reflect::field($rule, "=")))))) {
|
||||
#src/xrfragment/Query.hx:180: characters 14-26
|
||||
++$qualify;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#src/xrfragment/Query.hx:184: characters 5-23
|
||||
return $qualify > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function toObject () {
|
||||
#src/xrfragment/Query.hx:66: characters 5-18
|
||||
return $this->q;
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(Query::class, 'xrfragment.Query');
|
||||
101
dist/xrfragment.php/lib/xrfragment/URI.php
vendored
101
dist/xrfragment.php/lib/xrfragment/URI.php
vendored
|
|
@ -1,101 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
namespace xrfragment;
|
||||
|
||||
use \php\_Boot\HxAnon;
|
||||
use \php\Boot;
|
||||
use \php\_Boot\HxString;
|
||||
|
||||
/**
|
||||
* # Spec
|
||||
*
|
||||
* > version 1.0.0 [](https://github.com/coderofsalvation/xrfragment/actions) generated by `make doc` @ $(date +"%Y-%m-%dT%H:%M:%S%z")
|
||||
*
|
||||
* ### XR Fragment URI Grammar
|
||||
*
|
||||
* ```
|
||||
* reserved = gen-delims / sub-delims
|
||||
* gen-delims = "#" / "&"
|
||||
* sub-delims = "," / "="
|
||||
* ```
|
||||
*
|
||||
* > Example: `://foo.com/my3d.asset#pos=1,0,0&prio=-5&t=0,100|100,200`
|
||||
*
|
||||
* | Explanation | |
|
||||
* |-|-|
|
||||
* | `pos=1,2,3` | vector/coordinate argument e.g. |
|
||||
* | `pos=1,2,3&rot=0,90,0&q=.foo` | combinators |
|
||||
*
|
||||
* In case your programming language has no parser ([check here](https://github.com/coderofsalvation/xrfragment/tree/main/dist)) you can [crosscompile it](https://github.com/coderofsalvation/xrfragment/blob/main/build.hxml), or roll your own `Parser.parse(k,v,store)` using the spec:
|
||||
*
|
||||
*/
|
||||
class URI {
|
||||
/**
|
||||
* @param string $url
|
||||
* @param int $filter
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function parse ($url, $filter) {
|
||||
#src/xrfragment/URI.hx:37: characters 7-50
|
||||
$store = new HxAnon();
|
||||
#src/xrfragment/URI.hx:38: characters 7-63
|
||||
if (($url === null) || (HxString::indexOf($url, "#") === -1)) {
|
||||
#src/xrfragment/URI.hx:38: characters 51-63
|
||||
return $store;
|
||||
}
|
||||
#src/xrfragment/URI.hx:39: characters 7-54
|
||||
$fragment = HxString::split($url, "#");
|
||||
#src/xrfragment/URI.hx:40: characters 7-62
|
||||
$splitArray = HxString::split(($fragment->arr[1] ?? null), "&");
|
||||
#src/xrfragment/URI.hx:41: characters 19-23
|
||||
$_g = 0;
|
||||
#src/xrfragment/URI.hx:41: characters 23-40
|
||||
$_g1 = $splitArray->length;
|
||||
#src/xrfragment/URI.hx:41: lines 41-51
|
||||
while ($_g < $_g1) {
|
||||
#src/xrfragment/URI.hx:41: characters 19-40
|
||||
$i = $_g++;
|
||||
#src/xrfragment/URI.hx:43: characters 9-53
|
||||
$splitByEqual = HxString::split(($splitArray->arr[$i] ?? null), "=");
|
||||
#src/xrfragment/URI.hx:44: characters 9-33
|
||||
$regexPlus = new \EReg("\\+", "g");
|
||||
#src/xrfragment/URI.hx:45: characters 9-42
|
||||
$key = ($splitByEqual->arr[0] ?? null);
|
||||
#src/xrfragment/URI.hx:46: characters 5-27
|
||||
$value = "";
|
||||
#src/xrfragment/URI.hx:47: lines 47-49
|
||||
if ($splitByEqual->length > 1) {
|
||||
#src/xrfragment/URI.hx:48: characters 19-84
|
||||
$value = \urldecode($regexPlus->split(($splitByEqual->arr[1] ?? null))->join(" "));
|
||||
}
|
||||
#src/xrfragment/URI.hx:50: characters 5-49
|
||||
$ok = Parser::parse($key, $value, $store);
|
||||
}
|
||||
#src/xrfragment/URI.hx:52: lines 52-59
|
||||
if (($filter !== null) && ($filter !== 0)) {
|
||||
#src/xrfragment/URI.hx:53: lines 53-58
|
||||
$_g = 0;
|
||||
$_g1 = \Reflect::fields($store);
|
||||
while ($_g < $_g1->length) {
|
||||
#src/xrfragment/URI.hx:53: characters 14-17
|
||||
$key = ($_g1->arr[$_g] ?? null);
|
||||
#src/xrfragment/URI.hx:53: lines 53-58
|
||||
++$_g;
|
||||
#src/xrfragment/URI.hx:54: characters 13-42
|
||||
$xrf = \Reflect::field($store, $key);
|
||||
#src/xrfragment/URI.hx:55: lines 55-57
|
||||
if (!$xrf->is($filter)) {
|
||||
#src/xrfragment/URI.hx:56: characters 8-25
|
||||
\Reflect::deleteField($store, $key);
|
||||
}
|
||||
}
|
||||
}
|
||||
#src/xrfragment/URI.hx:60: characters 7-19
|
||||
return $store;
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(URI::class, 'xrfragment.URI');
|
||||
334
dist/xrfragment.php/lib/xrfragment/XRF.php
vendored
334
dist/xrfragment.php/lib/xrfragment/XRF.php
vendored
|
|
@ -1,334 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
*/
|
||||
|
||||
namespace xrfragment;
|
||||
|
||||
use \php\Boot;
|
||||
use \php\_Boot\HxString;
|
||||
|
||||
class XRF {
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $ASSET = 1;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $EMBEDDED = 64;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $NAVIGATOR = 32;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $PROMPT = 8;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $PROP_BIND = 2;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $PV_EXECUTE = 256;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $PV_OVERRIDE = 128;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $QUERY_OPERATOR = 4;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $ROUNDROBIN = 16;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $T_COLOR = 8192;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $T_FLOAT = 32768;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $T_INT = 16384;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $T_PREDEFINED_VIEW = 524288;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $T_STRING = 1048576;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $T_STRING_OBJ = 2097152;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $T_STRING_OBJ_PROP = 4194304;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $T_URL = 262144;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $T_VECTOR2 = 65536;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
static public $T_VECTOR3 = 131072;
|
||||
/**
|
||||
* @var \EReg
|
||||
*/
|
||||
static public $isColor;
|
||||
/**
|
||||
* @var \EReg
|
||||
*/
|
||||
static public $isFloat;
|
||||
/**
|
||||
* @var \EReg
|
||||
*/
|
||||
static public $isInt;
|
||||
/**
|
||||
* @var \EReg
|
||||
*/
|
||||
static public $isString;
|
||||
/**
|
||||
* @var \EReg
|
||||
*/
|
||||
static public $isUrl;
|
||||
/**
|
||||
* @var \EReg
|
||||
*/
|
||||
static public $isUrlOrPretypedView;
|
||||
/**
|
||||
* @var \EReg
|
||||
*/
|
||||
static public $isVector;
|
||||
|
||||
/**
|
||||
* @var XRF[]|\Array_hx
|
||||
*/
|
||||
public $args;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $color;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $flags;
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
public $float;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $fragment;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $int;
|
||||
/**
|
||||
* @var Query
|
||||
*/
|
||||
public $query;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $string;
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
public $x;
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
public $y;
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
public $z;
|
||||
|
||||
/**
|
||||
* @param int $flag
|
||||
* @param int $flags
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function set ($flag, $flags) {
|
||||
#src/xrfragment/XRF.hx:70: characters 5-24
|
||||
return $flags | $flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $flag
|
||||
* @param int $flags
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function unset ($flag, $flags) {
|
||||
#src/xrfragment/XRF.hx:74: characters 5-25
|
||||
return $flags & ~$flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $_fragment
|
||||
* @param int $_flags
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct ($_fragment, $_flags) {
|
||||
#src/xrfragment/XRF.hx:61: characters 5-25
|
||||
$this->fragment = $_fragment;
|
||||
#src/xrfragment/XRF.hx:62: characters 5-22
|
||||
$this->flags = $_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param XRF $v
|
||||
* @param string $str
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function guessType ($v, $str) {
|
||||
#src/xrfragment/XRF.hx:103: characters 5-19
|
||||
$v->string = $str;
|
||||
#src/xrfragment/XRF.hx:104: lines 104-109
|
||||
if (HxString::split($str, ",")->length > 1) {
|
||||
#src/xrfragment/XRF.hx:105: characters 7-46
|
||||
$xyz = HxString::split($str, ",");
|
||||
#src/xrfragment/XRF.hx:106: characters 7-56
|
||||
if ($xyz->length > 0) {
|
||||
#src/xrfragment/XRF.hx:106: characters 28-56
|
||||
$v->x = \Std::parseFloat(($xyz->arr[0] ?? null));
|
||||
}
|
||||
#src/xrfragment/XRF.hx:107: characters 7-56
|
||||
if ($xyz->length > 1) {
|
||||
#src/xrfragment/XRF.hx:107: characters 28-56
|
||||
$v->y = \Std::parseFloat(($xyz->arr[1] ?? null));
|
||||
}
|
||||
#src/xrfragment/XRF.hx:108: characters 7-56
|
||||
if ($xyz->length > 2) {
|
||||
#src/xrfragment/XRF.hx:108: characters 28-56
|
||||
$v->z = \Std::parseFloat(($xyz->arr[2] ?? null));
|
||||
}
|
||||
}
|
||||
#src/xrfragment/XRF.hx:111: characters 5-43
|
||||
if (XRF::$isColor->match($str)) {
|
||||
#src/xrfragment/XRF.hx:111: characters 30-43
|
||||
$v->color = $str;
|
||||
}
|
||||
#src/xrfragment/XRF.hx:112: characters 5-59
|
||||
if (XRF::$isFloat->match($str)) {
|
||||
#src/xrfragment/XRF.hx:112: characters 30-59
|
||||
$v->float = \Std::parseFloat($str);
|
||||
}
|
||||
#src/xrfragment/XRF.hx:113: characters 5-57
|
||||
if (XRF::$isInt->match($str)) {
|
||||
#src/xrfragment/XRF.hx:113: characters 30-57
|
||||
$v->int = \Std::parseInt($str);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $flag
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is ($flag) {
|
||||
#src/xrfragment/XRF.hx:66: characters 5-31
|
||||
return ($this->flags & $flag) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function validate ($value) {
|
||||
#src/xrfragment/XRF.hx:78: characters 5-27
|
||||
$this->guessType($this, $value);
|
||||
#src/xrfragment/XRF.hx:80: lines 80-88
|
||||
if (HxString::split($value, "|")->length > 1) {
|
||||
#src/xrfragment/XRF.hx:81: characters 7-35
|
||||
$this->args = new \Array_hx();
|
||||
#src/xrfragment/XRF.hx:82: characters 7-49
|
||||
$args = HxString::split($value, "|");
|
||||
#src/xrfragment/XRF.hx:83: characters 17-21
|
||||
$_g = 0;
|
||||
#src/xrfragment/XRF.hx:83: characters 21-32
|
||||
$_g1 = $args->length;
|
||||
#src/xrfragment/XRF.hx:83: lines 83-87
|
||||
while ($_g < $_g1) {
|
||||
#src/xrfragment/XRF.hx:83: characters 17-32
|
||||
$i = $_g++;
|
||||
#src/xrfragment/XRF.hx:84: characters 9-45
|
||||
$x = new XRF($this->fragment, $this->flags);
|
||||
#src/xrfragment/XRF.hx:85: characters 9-30
|
||||
$this->guessType($x, ($args->arr[$i] ?? null));
|
||||
#src/xrfragment/XRF.hx:86: characters 9-28
|
||||
$_this = $this->args;
|
||||
$_this->arr[$_this->length++] = $x;
|
||||
}
|
||||
}
|
||||
#src/xrfragment/XRF.hx:90: characters 5-59
|
||||
if ($this->fragment === "q") {
|
||||
#src/xrfragment/XRF.hx:90: characters 27-59
|
||||
$this->query = (new Query($value))->get();
|
||||
}
|
||||
#src/xrfragment/XRF.hx:92: characters 5-24
|
||||
$ok = true;
|
||||
#src/xrfragment/XRF.hx:93: lines 93-97
|
||||
if (!($this->args instanceof \Array_hx)) {
|
||||
#src/xrfragment/XRF.hx:94: characters 7-115
|
||||
if ($this->is(XRF::$T_VECTOR3) && !((is_float($this->x) || is_int($this->x)) && (is_float($this->y) || is_int($this->y)) && (is_float($this->z) || is_int($this->z)))) {
|
||||
#src/xrfragment/XRF.hx:94: characters 105-115
|
||||
$ok = false;
|
||||
}
|
||||
#src/xrfragment/XRF.hx:95: characters 7-115
|
||||
if ($this->is(XRF::$T_VECTOR2) && !((is_float($this->x) || is_int($this->x)) && (is_float($this->y) || is_int($this->y)))) {
|
||||
#src/xrfragment/XRF.hx:95: characters 105-115
|
||||
$ok = false;
|
||||
}
|
||||
#src/xrfragment/XRF.hx:96: characters 7-63
|
||||
if ($this->is(XRF::$T_INT) && !Boot::isOfType($this->int, Boot::getClass('Int'))) {
|
||||
#src/xrfragment/XRF.hx:96: characters 53-63
|
||||
$ok = false;
|
||||
}
|
||||
}
|
||||
#src/xrfragment/XRF.hx:98: characters 5-14
|
||||
return $ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @access private
|
||||
*/
|
||||
static public function __hx__init ()
|
||||
{
|
||||
static $called = false;
|
||||
if ($called) return;
|
||||
$called = true;
|
||||
|
||||
|
||||
self::$isColor = new \EReg("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})\$", "");
|
||||
self::$isInt = new \EReg("^[0-9]+\$", "");
|
||||
self::$isFloat = new \EReg("^[0-9]+\\.[0-9]+\$", "");
|
||||
self::$isVector = new \EReg("([,]+|\\w)", "");
|
||||
self::$isUrl = new \EReg("(://)?\\..*", "");
|
||||
self::$isUrlOrPretypedView = new \EReg("(^#|://)?\\..*", "");
|
||||
self::$isString = new \EReg(".*", "");
|
||||
}
|
||||
}
|
||||
|
||||
Boot::registerClass(XRF::class, 'xrfragment.XRF');
|
||||
XRF::__hx__init();
|
||||
392
dist/xrfragment.py
vendored
392
dist/xrfragment.py
vendored
|
|
@ -63,7 +63,7 @@ class EReg:
|
|||
_hx_class_name = "EReg"
|
||||
__slots__ = ("pattern", "matchObj", "_hx_global")
|
||||
_hx_fields = ["pattern", "matchObj", "global"]
|
||||
_hx_methods = ["split"]
|
||||
_hx_methods = ["split", "replace"]
|
||||
|
||||
def __init__(self,r,opt):
|
||||
self.matchObj = None
|
||||
|
|
@ -107,12 +107,35 @@ class EReg:
|
|||
else:
|
||||
return [HxString.substring(s,0,self.matchObj.start()), HxString.substr(s,self.matchObj.end(),None)]
|
||||
|
||||
def replace(self,s,by):
|
||||
_this = by.split("$$")
|
||||
by = "_hx_#repl#__".join([python_Boot.toString1(x1,'') for x1 in _this])
|
||||
def _hx_local_0(x):
|
||||
res = by
|
||||
g = x.groups()
|
||||
_g = 0
|
||||
_g1 = len(g)
|
||||
while (_g < _g1):
|
||||
i = _g
|
||||
_g = (_g + 1)
|
||||
gs = g[i]
|
||||
if (gs is None):
|
||||
continue
|
||||
delimiter = ("$" + HxOverrides.stringOrNull(str((i + 1))))
|
||||
_this = (list(res) if ((delimiter == "")) else res.split(delimiter))
|
||||
res = gs.join([python_Boot.toString1(x1,'') for x1 in _this])
|
||||
_this = res.split("_hx_#repl#__")
|
||||
res = "$".join([python_Boot.toString1(x1,'') for x1 in _this])
|
||||
return res
|
||||
replace = _hx_local_0
|
||||
return python_lib_Re.sub(self.pattern,replace,s,(0 if (self._hx_global) else 1))
|
||||
|
||||
|
||||
|
||||
class Reflect:
|
||||
_hx_class_name = "Reflect"
|
||||
__slots__ = ()
|
||||
_hx_statics = ["field", "deleteField"]
|
||||
_hx_statics = ["field", "deleteField", "copy"]
|
||||
|
||||
@staticmethod
|
||||
def field(o,field):
|
||||
|
|
@ -129,6 +152,20 @@ class Reflect:
|
|||
o.__delattr__(field)
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def copy(o):
|
||||
if (o is None):
|
||||
return None
|
||||
o2 = _hx_AnonObject({})
|
||||
_g = 0
|
||||
_g1 = python_Boot.fields(o)
|
||||
while (_g < len(_g1)):
|
||||
f = (_g1[_g] if _g >= 0 and _g < len(_g1) else None)
|
||||
_g = (_g + 1)
|
||||
value = Reflect.field(o,f)
|
||||
setattr(o2,(("_hx_" + f) if ((f in python_Boot.keywords)) else (("_hx_" + f) if (((((len(f) > 2) and ((ord(f[0]) == 95))) and ((ord(f[1]) == 95))) and ((ord(f[(len(f) - 1)]) != 95)))) else f)),value)
|
||||
return o2
|
||||
|
||||
|
||||
class Std:
|
||||
_hx_class_name = "Std"
|
||||
|
|
@ -984,7 +1021,11 @@ class python_HaxeIterator:
|
|||
class python_internal_ArrayImpl:
|
||||
_hx_class_name = "python.internal.ArrayImpl"
|
||||
__slots__ = ()
|
||||
_hx_statics = ["concat", "copy", "iterator", "keyValueIterator", "indexOf", "lastIndexOf", "join", "toString", "pop", "push", "unshift", "remove", "contains", "shift", "slice", "sort", "splice", "map", "filter", "insert", "reverse", "_get"]
|
||||
_hx_statics = ["get_length", "concat", "copy", "iterator", "keyValueIterator", "indexOf", "lastIndexOf", "join", "toString", "pop", "push", "unshift", "remove", "contains", "shift", "slice", "sort", "splice", "map", "filter", "insert", "reverse", "_get"]
|
||||
|
||||
@staticmethod
|
||||
def get_length(x):
|
||||
return len(x)
|
||||
|
||||
@staticmethod
|
||||
def concat(a1,a2):
|
||||
|
|
@ -1120,7 +1161,7 @@ class python_internal_ArrayImpl:
|
|||
class HxOverrides:
|
||||
_hx_class_name = "HxOverrides"
|
||||
__slots__ = ()
|
||||
_hx_statics = ["eq", "stringOrNull", "push", "arrayGet"]
|
||||
_hx_statics = ["eq", "stringOrNull", "length", "arrayGet"]
|
||||
|
||||
@staticmethod
|
||||
def eq(a,b):
|
||||
|
|
@ -1136,12 +1177,12 @@ class HxOverrides:
|
|||
return s
|
||||
|
||||
@staticmethod
|
||||
def push(x,e):
|
||||
if isinstance(x,list):
|
||||
_this = x
|
||||
_this.append(e)
|
||||
return len(_this)
|
||||
return x.push(e)
|
||||
def length(x):
|
||||
if isinstance(x,str):
|
||||
return len(x)
|
||||
elif isinstance(x,list):
|
||||
return len(x)
|
||||
return x.length
|
||||
|
||||
@staticmethod
|
||||
def arrayGet(a,i):
|
||||
|
|
@ -1173,7 +1214,7 @@ class python_internal_MethodClosure:
|
|||
class HxString:
|
||||
_hx_class_name = "HxString"
|
||||
__slots__ = ()
|
||||
_hx_statics = ["split", "charCodeAt", "charAt", "lastIndexOf", "toUpperCase", "toLowerCase", "indexOf", "indexOfImpl", "toString", "substring", "substr"]
|
||||
_hx_statics = ["split", "charCodeAt", "charAt", "lastIndexOf", "toUpperCase", "toLowerCase", "indexOf", "indexOfImpl", "toString", "get_length", "substring", "substr"]
|
||||
|
||||
@staticmethod
|
||||
def split(s,d):
|
||||
|
|
@ -1252,6 +1293,10 @@ class HxString:
|
|||
def toString(s):
|
||||
return s
|
||||
|
||||
@staticmethod
|
||||
def get_length(s):
|
||||
return len(s)
|
||||
|
||||
@staticmethod
|
||||
def substring(s,startIndex,endIndex = None):
|
||||
if (startIndex < 0):
|
||||
|
|
@ -1280,159 +1325,73 @@ class HxString:
|
|||
return s[startIndex:(startIndex + _hx_len)]
|
||||
|
||||
|
||||
class xrfragment_Parser:
|
||||
_hx_class_name = "xrfragment.Parser"
|
||||
__slots__ = ()
|
||||
_hx_statics = ["error", "debug", "parse"]
|
||||
|
||||
@staticmethod
|
||||
def parse(key,value,store):
|
||||
Frag = haxe_ds_StringMap()
|
||||
Frag.h["#"] = ((xrfragment_XRF.ASSET | xrfragment_XRF.T_PREDEFINED_VIEW) | xrfragment_XRF.PV_EXECUTE)
|
||||
Frag.h["prio"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_INT)
|
||||
Frag.h["src"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_URL)
|
||||
Frag.h["href"] = ((xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) | xrfragment_XRF.T_PREDEFINED_VIEW)
|
||||
Frag.h["tag"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING)
|
||||
Frag.h["pos"] = (((((xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN) | xrfragment_XRF.T_VECTOR3) | xrfragment_XRF.T_STRING_OBJ) | xrfragment_XRF.METADATA) | xrfragment_XRF.NAVIGATOR)
|
||||
Frag.h["q"] = ((xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING) | xrfragment_XRF.METADATA)
|
||||
Frag.h["scale"] = ((((xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.ROUNDROBIN) | xrfragment_XRF.T_VECTOR3) | xrfragment_XRF.METADATA)
|
||||
Frag.h["rot"] = (((((xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.ROUNDROBIN) | xrfragment_XRF.T_VECTOR3) | xrfragment_XRF.METADATA) | xrfragment_XRF.NAVIGATOR)
|
||||
Frag.h["mov"] = ((((xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.ROUNDROBIN) | xrfragment_XRF.T_VECTOR3) | xrfragment_XRF.METADATA)
|
||||
Frag.h["show"] = ((((xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.ROUNDROBIN) | xrfragment_XRF.T_INT) | xrfragment_XRF.METADATA)
|
||||
Frag.h["env"] = (((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_STRING) | xrfragment_XRF.METADATA)
|
||||
Frag.h["t"] = (((((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.ROUNDROBIN) | xrfragment_XRF.T_VECTOR2) | xrfragment_XRF.NAVIGATOR) | xrfragment_XRF.METADATA)
|
||||
Frag.h["gravity"] = (((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_VECTOR3) | xrfragment_XRF.METADATA)
|
||||
Frag.h["physics"] = (((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_VECTOR3) | xrfragment_XRF.METADATA)
|
||||
Frag.h["fov"] = ((((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_INT) | xrfragment_XRF.NAVIGATOR) | xrfragment_XRF.METADATA)
|
||||
Frag.h["clip"] = ((((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_VECTOR2) | xrfragment_XRF.NAVIGATOR) | xrfragment_XRF.METADATA)
|
||||
Frag.h["fog"] = ((((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_VECTOR2) | xrfragment_XRF.NAVIGATOR) | xrfragment_XRF.METADATA)
|
||||
Frag.h["bg"] = ((((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_VECTOR3) | xrfragment_XRF.NAVIGATOR) | xrfragment_XRF.METADATA)
|
||||
Frag.h["namespace"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING)
|
||||
Frag.h["SPDX"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING)
|
||||
Frag.h["unit"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING)
|
||||
Frag.h["description"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING)
|
||||
Frag.h["session"] = (((((xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.NAVIGATOR) | xrfragment_XRF.METADATA) | xrfragment_XRF.PROMPT)
|
||||
isPVDynamic = (((len(value) == 0) and ((len(key) > 0))) and (not (key in Frag.h)))
|
||||
isPVDefault = (((len(value) == 0) and ((len(key) > 0))) and ((key == "#")))
|
||||
if isPVDynamic:
|
||||
v = xrfragment_XRF(key,(xrfragment_XRF.PV_EXECUTE | xrfragment_XRF.NAVIGATOR))
|
||||
v.validate(key)
|
||||
setattr(store,(("_hx_" + key) if ((key in python_Boot.keywords)) else (("_hx_" + key) if (((((len(key) > 2) and ((ord(key[0]) == 95))) and ((ord(key[1]) == 95))) and ((ord(key[(len(key) - 1)]) != 95)))) else key)),v)
|
||||
return True
|
||||
if ((len(key.split(".")) > 1) and ((len(value.split(".")) > 1))):
|
||||
value1 = xrfragment_XRF(key,(((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_STRING) | xrfragment_XRF.PROP_BIND))
|
||||
setattr(store,(("_hx_" + key) if ((key in python_Boot.keywords)) else (("_hx_" + key) if (((((len(key) > 2) and ((ord(key[0]) == 95))) and ((ord(key[1]) == 95))) and ((ord(key[(len(key) - 1)]) != 95)))) else key)),value1)
|
||||
return True
|
||||
v = xrfragment_XRF(key,Frag.h.get(key,None))
|
||||
if (key in Frag.h):
|
||||
if (not v.validate(value)):
|
||||
print(str((((("⚠ fragment '" + ("null" if key is None else key)) + "' has incompatible value (") + ("null" if value is None else value)) + ")")))
|
||||
return False
|
||||
setattr(store,(("_hx_" + key) if ((key in python_Boot.keywords)) else (("_hx_" + key) if (((((len(key) > 2) and ((ord(key[0]) == 95))) and ((ord(key[1]) == 95))) and ((ord(key[(len(key) - 1)]) != 95)))) else key)),v)
|
||||
if xrfragment_Parser.debug:
|
||||
print(str(((("✔ " + ("null" if key is None else key)) + ": ") + HxOverrides.stringOrNull(v.string))))
|
||||
else:
|
||||
if Std.isOfType(value,str):
|
||||
v.guessType(v,value)
|
||||
v.noXRF = True
|
||||
setattr(store,(("_hx_" + key) if ((key in python_Boot.keywords)) else (("_hx_" + key) if (((((len(key) > 2) and ((ord(key[0]) == 95))) and ((ord(key[1]) == 95))) and ((ord(key[(len(key) - 1)]) != 95)))) else key)),v)
|
||||
return True
|
||||
|
||||
|
||||
class xrfragment_Query:
|
||||
_hx_class_name = "xrfragment.Query"
|
||||
__slots__ = ("str", "q", "isProp", "isExclude", "isRoot", "isNumber")
|
||||
_hx_fields = ["str", "q", "isProp", "isExclude", "isRoot", "isNumber"]
|
||||
class xrfragment_Filter:
|
||||
_hx_class_name = "xrfragment.Filter"
|
||||
__slots__ = ("str", "q")
|
||||
_hx_fields = ["str", "q"]
|
||||
_hx_methods = ["toObject", "get", "parse", "test", "testProperty"]
|
||||
|
||||
def __init__(self,_hx_str):
|
||||
self.isNumber = EReg("^[0-9\\.]+$","")
|
||||
self.isRoot = EReg("^[-]?/","")
|
||||
self.isExclude = EReg("^-","")
|
||||
self.isProp = EReg("^.*:[><=!]?","")
|
||||
self.q = _hx_AnonObject({})
|
||||
self.str = ""
|
||||
if (_hx_str is not None):
|
||||
self.parse(_hx_str)
|
||||
|
||||
def toObject(self):
|
||||
return self.q
|
||||
return Reflect.copy(self.q)
|
||||
|
||||
def get(self):
|
||||
return self.q
|
||||
return Reflect.copy(self.q)
|
||||
|
||||
def parse(self,_hx_str):
|
||||
_gthis = self
|
||||
token = _hx_str.split(" ")
|
||||
q = _hx_AnonObject({})
|
||||
def _hx_local_0(_hx_str,prefix = None):
|
||||
if (prefix is None):
|
||||
prefix = ""
|
||||
_hx_str = StringTools.trim(_hx_str)
|
||||
k = HxOverrides.arrayGet(_hx_str.split(":"), 0)
|
||||
v = HxOverrides.arrayGet(_hx_str.split(":"), 1)
|
||||
k = HxOverrides.arrayGet(_hx_str.split("="), 0)
|
||||
v = HxOverrides.arrayGet(_hx_str.split("="), 1)
|
||||
_hx_filter = _hx_AnonObject({})
|
||||
if Reflect.field(q,(("null" if prefix is None else prefix) + ("null" if k is None else k))):
|
||||
_hx_filter = Reflect.field(q,(("null" if prefix is None else prefix) + ("null" if k is None else k)))
|
||||
value = (Reflect.field(_hx_filter,"rules") if ((Reflect.field(_hx_filter,"rules") is not None)) else list())
|
||||
setattr(_hx_filter,(("_hx_" + "rules") if (("rules" in python_Boot.keywords)) else (("_hx_" + "rules") if (((((len("rules") > 2) and ((ord("rules"[0]) == 95))) and ((ord("rules"[1]) == 95))) and ((ord("rules"[(len("rules") - 1)]) != 95)))) else "rules")),value)
|
||||
_this = _gthis.isProp
|
||||
_this = xrfragment_XRF.isProp
|
||||
_this.matchObj = python_lib_Re.search(_this.pattern,_hx_str)
|
||||
if (_this.matchObj is not None):
|
||||
oper = ""
|
||||
startIndex = None
|
||||
if (((_hx_str.find("*") if ((startIndex is None)) else HxString.indexOfImpl(_hx_str,"*",startIndex))) != -1):
|
||||
oper = "*"
|
||||
startIndex = None
|
||||
if (((_hx_str.find(">") if ((startIndex is None)) else HxString.indexOfImpl(_hx_str,">",startIndex))) != -1):
|
||||
oper = ">"
|
||||
startIndex = None
|
||||
if (((_hx_str.find("<") if ((startIndex is None)) else HxString.indexOfImpl(_hx_str,"<",startIndex))) != -1):
|
||||
oper = "<"
|
||||
startIndex = None
|
||||
if (((_hx_str.find(">=") if ((startIndex is None)) else HxString.indexOfImpl(_hx_str,">=",startIndex))) != -1):
|
||||
oper = ">="
|
||||
startIndex = None
|
||||
if (((_hx_str.find("<=") if ((startIndex is None)) else HxString.indexOfImpl(_hx_str,"<=",startIndex))) != -1):
|
||||
oper = "<="
|
||||
_this = _gthis.isExclude
|
||||
_this = xrfragment_XRF.isExclude
|
||||
_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)
|
||||
v = HxString.substr(v,len(oper),None)
|
||||
if (len(oper) == 0):
|
||||
oper = "="
|
||||
rule = _hx_AnonObject({})
|
||||
_this = _gthis.isNumber
|
||||
_this = xrfragment_XRF.isNumber
|
||||
_this.matchObj = python_lib_Re.search(_this.pattern,v)
|
||||
if (_this.matchObj is not None):
|
||||
value = Std.parseFloat(v)
|
||||
setattr(rule,(("_hx_" + oper) if ((oper in python_Boot.keywords)) else (("_hx_" + oper) if (((((len(oper) > 2) and ((ord(oper[0]) == 95))) and ((ord(oper[1]) == 95))) and ((ord(oper[(len(oper) - 1)]) != 95)))) else oper)),value)
|
||||
else:
|
||||
setattr(rule,(("_hx_" + oper) if ((oper in python_Boot.keywords)) else (("_hx_" + oper) if (((((len(oper) > 2) and ((ord(oper[0]) == 95))) and ((ord(oper[1]) == 95))) and ((ord(oper[(len(oper) - 1)]) != 95)))) else oper)),v)
|
||||
Reflect.field(Reflect.field(_hx_filter,"rules"),"push")(rule)
|
||||
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
|
||||
else:
|
||||
_this = _gthis.isExclude
|
||||
_this.matchObj = python_lib_Re.search(_this.pattern,_hx_str)
|
||||
value = (False if ((_this.matchObj is not None)) else True)
|
||||
setattr(_hx_filter,(("_hx_" + "id") if (("id" in python_Boot.keywords)) else (("_hx_" + "id") if (((((len("id") > 2) and ((ord("id"[0]) == 95))) and ((ord("id"[1]) == 95))) and ((ord("id"[(len("id") - 1)]) != 95)))) else "id")),value)
|
||||
_this = _gthis.isRoot
|
||||
_this.matchObj = python_lib_Re.search(_this.pattern,_hx_str)
|
||||
value = (_this.matchObj is not 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")),value)
|
||||
_this = _gthis.isExclude
|
||||
_this.matchObj = python_lib_Re.search(_this.pattern,_hx_str)
|
||||
if (_this.matchObj is not None):
|
||||
_hx_str = HxString.substr(_hx_str,1,None)
|
||||
_this = _gthis.isRoot
|
||||
_this.matchObj = python_lib_Re.search(_this.pattern,_hx_str)
|
||||
if (_this.matchObj is not None):
|
||||
_hx_str = HxString.substr(_hx_str,1,None)
|
||||
setattr(q,(("_hx_" + _hx_str) if ((_hx_str in python_Boot.keywords)) else (("_hx_" + _hx_str) if (((((len(_hx_str) > 2) and ((ord(_hx_str[0]) == 95))) and ((ord(_hx_str[1]) == 95))) and ((ord(_hx_str[(len(_hx_str) - 1)]) != 95)))) else _hx_str)),_hx_filter)
|
||||
setattr(q,(("_hx_" + "expr") if (("expr" in python_Boot.keywords)) else (("_hx_" + "expr") if (((((len("expr") > 2) and ((ord("expr"[0]) == 95))) and ((ord("expr"[1]) == 95))) and ((ord("expr"[(len("expr") - 1)]) != 95)))) else "expr")),rule)
|
||||
_this = xrfragment_XRF.isDeep
|
||||
_this.matchObj = python_lib_Re.search(_this.pattern,_hx_str)
|
||||
value = ((Reflect.field(k.split("*"),"length") - 1) if ((_this.matchObj is not None)) else 0)
|
||||
setattr(q,(("_hx_" + "deep") if (("deep" in python_Boot.keywords)) else (("_hx_" + "deep") if (((((len("deep") > 2) and ((ord("deep"[0]) == 95))) and ((ord("deep"[1]) == 95))) and ((ord("deep"[(len("deep") - 1)]) != 95)))) else "deep")),value)
|
||||
_this = xrfragment_XRF.isExclude
|
||||
_this.matchObj = python_lib_Re.search(_this.pattern,_hx_str)
|
||||
value = (False if ((_this.matchObj is not None)) else True)
|
||||
setattr(q,(("_hx_" + "show") if (("show" in python_Boot.keywords)) else (("_hx_" + "show") if (((((len("show") > 2) and ((ord("show"[0]) == 95))) and ((ord("show"[1]) == 95))) and ((ord("show"[(len("show") - 1)]) != 95)))) else "show")),value)
|
||||
value = xrfragment_XRF.operators.replace(k,"")
|
||||
setattr(q,(("_hx_" + "key") if (("key" in python_Boot.keywords)) else (("_hx_" + "key") if (((((len("key") > 2) and ((ord("key"[0]) == 95))) and ((ord("key"[1]) == 95))) and ((ord("key"[(len("key") - 1)]) != 95)))) else "key")),value)
|
||||
setattr(q,(("_hx_" + "value") if (("value" in python_Boot.keywords)) else (("_hx_" + "value") if (((((len("value") > 2) and ((ord("value"[0]) == 95))) and ((ord("value"[1]) == 95))) and ((ord("value"[(len("value") - 1)]) != 95)))) else "value")),v)
|
||||
process = _hx_local_0
|
||||
_g = 0
|
||||
_g1 = len(token)
|
||||
|
|
@ -1482,39 +1441,69 @@ class xrfragment_Query:
|
|||
v = Reflect.field(self.q,value)
|
||||
if (Reflect.field(v,property) is not None):
|
||||
return Reflect.field(v,property)
|
||||
_g = 0
|
||||
_g1 = python_Boot.fields(self.q)
|
||||
while (_g < len(_g1)):
|
||||
k = (_g1[_g] if _g >= 0 and _g < len(_g1) else None)
|
||||
_g = (_g + 1)
|
||||
_hx_filter = Reflect.field(self.q,k)
|
||||
if (Reflect.field(_hx_filter,"rules") is None):
|
||||
continue
|
||||
rules = Reflect.field(_hx_filter,"rules")
|
||||
_g2 = 0
|
||||
while (_g2 < len(rules)):
|
||||
rule = (rules[_g2] if _g2 >= 0 and _g2 < len(rules) else None)
|
||||
_g2 = (_g2 + 1)
|
||||
if exclude:
|
||||
if (((Reflect.field(rule,"!=") is not None) and testprop((Std.string(value) == Std.string(Reflect.field(rule,"!="))))) and exclude):
|
||||
qualify = (qualify + 1)
|
||||
else:
|
||||
if ((Reflect.field(rule,"*") is not None) and testprop((Std.parseFloat(value) is not None))):
|
||||
qualify = (qualify + 1)
|
||||
if ((Reflect.field(rule,">") is not None) and testprop((Std.parseFloat(value) > Std.parseFloat(Reflect.field(rule,">"))))):
|
||||
qualify = (qualify + 1)
|
||||
if ((Reflect.field(rule,"<") is not None) and testprop((Std.parseFloat(value) < Std.parseFloat(Reflect.field(rule,"<"))))):
|
||||
qualify = (qualify + 1)
|
||||
if ((Reflect.field(rule,">=") is not None) and testprop((Std.parseFloat(value) >= Std.parseFloat(Reflect.field(rule,">="))))):
|
||||
qualify = (qualify + 1)
|
||||
if ((Reflect.field(rule,"<=") is not None) and testprop((Std.parseFloat(value) <= Std.parseFloat(Reflect.field(rule,"<="))))):
|
||||
qualify = (qualify + 1)
|
||||
if ((Reflect.field(rule,"=") is not None) and ((testprop((value == Reflect.field(rule,"="))) or testprop((Std.parseFloat(value) == Std.parseFloat(Reflect.field(rule,"="))))))):
|
||||
qualify = (qualify + 1)
|
||||
if Reflect.field(self.q,"expr"):
|
||||
f = Reflect.field(self.q,"expr")
|
||||
if (not Reflect.field(self.q,"show")):
|
||||
if (((Reflect.field(f,"!=") is not None) and testprop((Std.string(value) == Std.string(Reflect.field(f,"!="))))) and exclude):
|
||||
qualify = (qualify + 1)
|
||||
else:
|
||||
if ((Reflect.field(f,"*") is not None) and testprop((Std.parseFloat(value) is not None))):
|
||||
qualify = (qualify + 1)
|
||||
if ((Reflect.field(f,">") is not None) and testprop((Std.parseFloat(value) >= Std.parseFloat(Reflect.field(f,">"))))):
|
||||
qualify = (qualify + 1)
|
||||
if ((Reflect.field(f,"<") is not None) and testprop((Std.parseFloat(value) <= Std.parseFloat(Reflect.field(f,"<"))))):
|
||||
qualify = (qualify + 1)
|
||||
if ((Reflect.field(f,"=") is not None) and ((testprop((value == Reflect.field(f,"="))) or testprop((Std.parseFloat(value) == Std.parseFloat(Reflect.field(f,"="))))))):
|
||||
qualify = (qualify + 1)
|
||||
return (qualify > 0)
|
||||
|
||||
|
||||
|
||||
class xrfragment_Parser:
|
||||
_hx_class_name = "xrfragment.Parser"
|
||||
__slots__ = ()
|
||||
_hx_statics = ["error", "debug", "parse"]
|
||||
|
||||
@staticmethod
|
||||
def parse(key,value,store,index = None):
|
||||
Frag = haxe_ds_StringMap()
|
||||
Frag.h["#"] = ((xrfragment_XRF.ASSET | xrfragment_XRF.T_PREDEFINED_VIEW) | xrfragment_XRF.PV_EXECUTE)
|
||||
Frag.h["src"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_URL)
|
||||
Frag.h["href"] = ((xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) | xrfragment_XRF.T_PREDEFINED_VIEW)
|
||||
Frag.h["tag"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING)
|
||||
Frag.h["pos"] = (((((xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR3) | xrfragment_XRF.T_STRING) | xrfragment_XRF.T_STRING_OBJ) | xrfragment_XRF.METADATA) | xrfragment_XRF.NAVIGATOR)
|
||||
Frag.h["rot"] = ((((xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_VECTOR3) | xrfragment_XRF.METADATA) | xrfragment_XRF.NAVIGATOR)
|
||||
Frag.h["t"] = ((((((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_FLOAT) | xrfragment_XRF.T_VECTOR2) | xrfragment_XRF.T_STRING) | xrfragment_XRF.NAVIGATOR) | xrfragment_XRF.METADATA)
|
||||
Frag.h["tv"] = ((((((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_FLOAT) | xrfragment_XRF.T_VECTOR2) | xrfragment_XRF.T_VECTOR3) | xrfragment_XRF.NAVIGATOR) | xrfragment_XRF.METADATA)
|
||||
Frag.h["namespace"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING)
|
||||
Frag.h["SPDX"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING)
|
||||
Frag.h["unit"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING)
|
||||
Frag.h["description"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING)
|
||||
Frag.h["session"] = (((((xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.NAVIGATOR) | xrfragment_XRF.METADATA) | xrfragment_XRF.PROMPT)
|
||||
keyStripped = xrfragment_XRF.operators.replace(key,"")
|
||||
isPVDynamic = ((len(key) > 0) and (not (key in Frag.h)))
|
||||
isPVDefault = (((len(value) == 0) and ((len(key) > 0))) and ((key == "#")))
|
||||
if isPVDynamic:
|
||||
v = xrfragment_XRF(key,(xrfragment_XRF.PV_EXECUTE | xrfragment_XRF.NAVIGATOR),index)
|
||||
v.validate(value)
|
||||
setattr(store,(("_hx_" + keyStripped) if ((keyStripped in python_Boot.keywords)) else (("_hx_" + keyStripped) if (((((len(keyStripped) > 2) and ((ord(keyStripped[0]) == 95))) and ((ord(keyStripped[1]) == 95))) and ((ord(keyStripped[(len(keyStripped) - 1)]) != 95)))) else keyStripped)),v)
|
||||
return True
|
||||
v = xrfragment_XRF(key,Frag.h.get(key,None),index)
|
||||
if (key in Frag.h):
|
||||
if (not v.validate(value)):
|
||||
print(str((((("⚠ fragment '" + ("null" if key is None else key)) + "' has incompatible value (") + ("null" if value is None else value)) + ")")))
|
||||
return False
|
||||
setattr(store,(("_hx_" + keyStripped) if ((keyStripped in python_Boot.keywords)) else (("_hx_" + keyStripped) if (((((len(keyStripped) > 2) and ((ord(keyStripped[0]) == 95))) and ((ord(keyStripped[1]) == 95))) and ((ord(keyStripped[(len(keyStripped) - 1)]) != 95)))) else keyStripped)),v)
|
||||
if xrfragment_Parser.debug:
|
||||
print(str(((("✔ " + ("null" if key is None else key)) + ": ") + HxOverrides.stringOrNull(v.string))))
|
||||
else:
|
||||
if Std.isOfType(value,str):
|
||||
v.guessType(v,value)
|
||||
v.noXRF = True
|
||||
setattr(store,(("_hx_" + keyStripped) if ((keyStripped in python_Boot.keywords)) else (("_hx_" + keyStripped) if (((((len(keyStripped) > 2) and ((ord(keyStripped[0]) == 95))) and ((ord(keyStripped[1]) == 95))) and ((ord(keyStripped[(len(keyStripped) - 1)]) != 95)))) else keyStripped)),v)
|
||||
return True
|
||||
|
||||
|
||||
class xrfragment_URI:
|
||||
_hx_class_name = "xrfragment.URI"
|
||||
__slots__ = ()
|
||||
|
|
@ -1547,7 +1536,7 @@ class xrfragment_URI:
|
|||
if (len(splitByEqual) > 1):
|
||||
_this1 = regexPlus.split((splitByEqual[1] if 1 < len(splitByEqual) else None))
|
||||
value = python_lib_urllib_Parse.unquote(" ".join([python_Boot.toString1(x1,'') for x1 in _this1]))
|
||||
ok = xrfragment_Parser.parse(key,value,store)
|
||||
ok = xrfragment_Parser.parse(key,value,store,i)
|
||||
if ((_hx_filter is not None) and ((_hx_filter != 0))):
|
||||
_g = 0
|
||||
_g1 = python_Boot.fields(store)
|
||||
|
|
@ -1562,76 +1551,72 @@ class xrfragment_URI:
|
|||
|
||||
class xrfragment_XRF:
|
||||
_hx_class_name = "xrfragment.XRF"
|
||||
__slots__ = ("fragment", "flags", "x", "y", "z", "color", "string", "int", "float", "args", "query", "noXRF")
|
||||
_hx_fields = ["fragment", "flags", "x", "y", "z", "color", "string", "int", "float", "args", "query", "noXRF"]
|
||||
__slots__ = ("fragment", "flags", "index", "x", "y", "z", "w", "color", "string", "int", "float", "filter", "noXRF")
|
||||
_hx_fields = ["fragment", "flags", "index", "x", "y", "z", "w", "color", "string", "int", "float", "filter", "noXRF"]
|
||||
_hx_methods = ["is", "validate", "guessType"]
|
||||
_hx_statics = ["ASSET", "PROP_BIND", "QUERY_OPERATOR", "PROMPT", "ROUNDROBIN", "NAVIGATOR", "METADATA", "PV_OVERRIDE", "PV_EXECUTE", "T_COLOR", "T_INT", "T_FLOAT", "T_VECTOR2", "T_VECTOR3", "T_URL", "T_PREDEFINED_VIEW", "T_STRING", "T_STRING_OBJ", "T_STRING_OBJ_PROP", "isColor", "isInt", "isFloat", "isVector", "isUrl", "isUrlOrPretypedView", "isString", "set", "unset"]
|
||||
_hx_statics = ["ASSET", "PROP_BIND", "QUERY_OPERATOR", "PROMPT", "ROUNDROBIN", "NAVIGATOR", "METADATA", "PV_OVERRIDE", "PV_EXECUTE", "T_COLOR", "T_INT", "T_FLOAT", "T_VECTOR2", "T_VECTOR3", "T_URL", "T_PREDEFINED_VIEW", "T_STRING", "T_STRING_OBJ", "T_STRING_OBJ_PROP", "isColor", "isInt", "isFloat", "isVector", "isUrl", "isUrlOrPretypedView", "isString", "operators", "isProp", "isExclude", "isDeep", "isNumber", "set", "unset"]
|
||||
|
||||
def __init__(self,_fragment,_flags):
|
||||
def __init__(self,_fragment,_flags,_index = None):
|
||||
self.noXRF = None
|
||||
self.query = None
|
||||
self.args = None
|
||||
self.filter = None
|
||||
self.float = None
|
||||
self.int = None
|
||||
self.string = None
|
||||
self.color = None
|
||||
self.w = None
|
||||
self.z = None
|
||||
self.y = None
|
||||
self.x = None
|
||||
self.fragment = _fragment
|
||||
self.flags = _flags
|
||||
self.index = _index
|
||||
|
||||
def _hx_is(self,flag):
|
||||
if (not Std.isOfType(self.flags,Int)):
|
||||
self.flags = 0
|
||||
return (((self.flags & flag)) != 0)
|
||||
|
||||
def validate(self,value):
|
||||
self.guessType(self,value)
|
||||
if (len(value.split("|")) > 1):
|
||||
self.args = list()
|
||||
args = value.split("|")
|
||||
_g = 0
|
||||
_g1 = len(args)
|
||||
while (_g < _g1):
|
||||
i = _g
|
||||
_g = (_g + 1)
|
||||
x = xrfragment_XRF(self.fragment,self.flags)
|
||||
self.guessType(x,(args[i] if i >= 0 and i < len(args) else None))
|
||||
_this = self.args
|
||||
_this.append(x)
|
||||
if (self.fragment == "q"):
|
||||
self.query = xrfragment_Query(value).get()
|
||||
ok = True
|
||||
if (not Std.isOfType(self.args,list)):
|
||||
if (self._hx_is(xrfragment_XRF.T_VECTOR3) and (not (((Std.isOfType(self.x,Float) and Std.isOfType(self.y,Float)) and Std.isOfType(self.z,Float))))):
|
||||
ok = False
|
||||
if (self._hx_is(xrfragment_XRF.T_VECTOR2) and (not ((Std.isOfType(self.x,Float) and Std.isOfType(self.y,Float))))):
|
||||
ok = False
|
||||
if (self._hx_is(xrfragment_XRF.T_INT) and (not Std.isOfType(self.int,Int))):
|
||||
ok = False
|
||||
if (((not self._hx_is(xrfragment_XRF.T_FLOAT)) and self._hx_is(xrfragment_XRF.T_VECTOR2)) and (not ((Std.isOfType(self.x,Float) and Std.isOfType(self.y,Float))))):
|
||||
ok = False
|
||||
if (((not ((self._hx_is(xrfragment_XRF.T_VECTOR2) or self._hx_is(xrfragment_XRF.T_STRING)))) and self._hx_is(xrfragment_XRF.T_VECTOR3)) and (not (((Std.isOfType(self.x,Float) and Std.isOfType(self.y,Float)) and Std.isOfType(self.z,Float))))):
|
||||
ok = False
|
||||
return ok
|
||||
|
||||
def guessType(self,v,_hx_str):
|
||||
v.string = _hx_str
|
||||
if (len(_hx_str.split(",")) > 1):
|
||||
xyz = _hx_str.split(",")
|
||||
if (len(xyz) > 0):
|
||||
v.x = Std.parseFloat((xyz[0] if 0 < len(xyz) else None))
|
||||
if (len(xyz) > 1):
|
||||
v.y = Std.parseFloat((xyz[1] if 1 < len(xyz) else None))
|
||||
if (len(xyz) > 2):
|
||||
v.z = Std.parseFloat((xyz[2] if 2 < len(xyz) else None))
|
||||
_this = xrfragment_XRF.isColor
|
||||
_this.matchObj = python_lib_Re.search(_this.pattern,_hx_str)
|
||||
if (_this.matchObj is not None):
|
||||
v.color = _hx_str
|
||||
_this = xrfragment_XRF.isFloat
|
||||
_this.matchObj = python_lib_Re.search(_this.pattern,_hx_str)
|
||||
if (_this.matchObj is not None):
|
||||
v.float = Std.parseFloat(_hx_str)
|
||||
_this = xrfragment_XRF.isInt
|
||||
_this.matchObj = python_lib_Re.search(_this.pattern,_hx_str)
|
||||
if (_this.matchObj is not None):
|
||||
v.int = Std.parseInt(_hx_str)
|
||||
if (not Std.isOfType(_hx_str,str)):
|
||||
return
|
||||
if (len(_hx_str) > 0):
|
||||
if (len(_hx_str.split(",")) > 1):
|
||||
xyzw = _hx_str.split(",")
|
||||
if (len(xyzw) > 0):
|
||||
v.x = Std.parseFloat((xyzw[0] if 0 < len(xyzw) else None))
|
||||
if (len(xyzw) > 1):
|
||||
v.y = Std.parseFloat((xyzw[1] if 1 < len(xyzw) else None))
|
||||
if (len(xyzw) > 2):
|
||||
v.z = Std.parseFloat((xyzw[2] if 2 < len(xyzw) else None))
|
||||
if (len(xyzw) > 3):
|
||||
v.w = Std.parseFloat((xyzw[3] if 3 < len(xyzw) else None))
|
||||
_this = xrfragment_XRF.isColor
|
||||
_this.matchObj = python_lib_Re.search(_this.pattern,_hx_str)
|
||||
if (_this.matchObj is not None):
|
||||
v.color = _hx_str
|
||||
_this = xrfragment_XRF.isFloat
|
||||
_this.matchObj = python_lib_Re.search(_this.pattern,_hx_str)
|
||||
if (_this.matchObj is not None):
|
||||
v.x = Std.parseFloat(_hx_str)
|
||||
v.float = v.x
|
||||
_this = xrfragment_XRF.isInt
|
||||
_this.matchObj = python_lib_Re.search(_this.pattern,_hx_str)
|
||||
if (_this.matchObj is not None):
|
||||
v.int = Std.parseInt(_hx_str)
|
||||
v.x = v.int
|
||||
v.filter = xrfragment_Filter(((HxOverrides.stringOrNull(v.fragment) + "=") + HxOverrides.stringOrNull(v.string)))
|
||||
else:
|
||||
v.filter = xrfragment_Filter(v.fragment)
|
||||
|
||||
@staticmethod
|
||||
def set(flag,flags):
|
||||
|
|
@ -1671,9 +1656,14 @@ xrfragment_XRF.T_STRING = 1048576
|
|||
xrfragment_XRF.T_STRING_OBJ = 2097152
|
||||
xrfragment_XRF.T_STRING_OBJ_PROP = 4194304
|
||||
xrfragment_XRF.isColor = EReg("^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$","")
|
||||
xrfragment_XRF.isInt = EReg("^[0-9]+$","")
|
||||
xrfragment_XRF.isFloat = EReg("^[0-9]+\\.[0-9]+$","")
|
||||
xrfragment_XRF.isInt = EReg("^[-0-9]+$","")
|
||||
xrfragment_XRF.isFloat = EReg("^[-0-9]+\\.[0-9]+$","")
|
||||
xrfragment_XRF.isVector = EReg("([,]+|\\w)","")
|
||||
xrfragment_XRF.isUrl = EReg("(://)?\\..*","")
|
||||
xrfragment_XRF.isUrlOrPretypedView = EReg("(^#|://)?\\..*","")
|
||||
xrfragment_XRF.isString = EReg(".*","")
|
||||
xrfragment_XRF.isString = EReg(".*","")
|
||||
xrfragment_XRF.operators = EReg("(^-|[\\*]+)","")
|
||||
xrfragment_XRF.isProp = EReg("^.*=[><=]?","")
|
||||
xrfragment_XRF.isExclude = EReg("^-","")
|
||||
xrfragment_XRF.isDeep = EReg("\\*","")
|
||||
xrfragment_XRF.isNumber = EReg("^[0-9\\.]+$","")
|
||||
2471
dist/xrfragment.three.js
vendored
2471
dist/xrfragment.three.js
vendored
File diff suppressed because one or more lines are too long
2471
dist/xrfragment.three.module.js
vendored
2471
dist/xrfragment.three.module.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -94,8 +94,8 @@ value: draft-XRFRAGMENTS-leonvankammen-00
|
|||
.# Abstract
|
||||
|
||||
This draft is a specification for 4D URLs & [hypermediatic](https://github.com/coderofsalvation/hypermediatic) navigation, which links together space, time & text together, for hypermedia browsers with- or without a network-connection.<br>
|
||||
The specification promotes spatial addressibility, sharing, navigation, query-ing and annotating interactive (text)objects across for (XR) Browsers.<br>
|
||||
XR Fragments allows us to enrich existing dataformats, by recursive use of existing proven technologies like [URI Fragments](https://en.wikipedia.org/wiki/URI_fragment) and BibTags notation.<br>
|
||||
The specification promotes spatial addressibility, sharing, navigation, filtering and databinding objects for (XR) Browsers.<br>
|
||||
XR Fragments allows us to better use existing metadata inside 3D scene(files), by connecting it to proven technologies like [URI Fragments](https://en.wikipedia.org/wiki/URI_fragment).
|
||||
|
||||
> Almost every idea in this document is demonstrated at [https://xrfragment.org](https://xrfragment.org)
|
||||
|
||||
|
|
@ -103,34 +103,38 @@ XR Fragments allows us to enrich existing dataformats, by recursive use of exist
|
|||
|
||||
# Introduction
|
||||
|
||||
How can we add more features to existing text & 3D scenes, without introducing new dataformats?<br>
|
||||
How can we add more control to existing text & 3D scenes, without introducing new dataformats?<br>
|
||||
Historically, there's many attempts to create the ultimate markuplanguage or 3D fileformat.<br>
|
||||
The lowest common denominator is: describing/tagging/naming nodes using **plain text**.<br>
|
||||
XR Fragments allows us to enrich/connect existing dataformats, by introducing existing technologies/ideas:<br>
|
||||
The lowest common denominator is: designers describing/tagging/naming things using **plain text**.<br>
|
||||
XR Fragments exploits the fact that all 3D models already contain such metadata:
|
||||
|
||||
**XR Fragments allows controlling of metadata in 3D scene(files) using URLs**
|
||||
|
||||
Or more detailed:
|
||||
|
||||
1. addressibility and [hypermediatic](https://github.com/coderofsalvation/hypermediatic) navigation of 3D scenes/objects: [URI Fragments](https://en.wikipedia.org/wiki/URI_fragment) + src/href spatial metadata
|
||||
1. Interlinking text/& 3D by collapsing space into a Word Graph (XRWG) to show [visible links](#visible-links) (and augmenting text with [bibs](https://github.com/coderofsalvation/tagbibs) / [BibTags](https://en.wikipedia.org/wiki/BibTeX) appendices (see [visual-meta](https://visual-meta.info) e.g.)
|
||||
1. Interlinking (text)objects by collapsing space into a Word Graph (XRWG) to show [visible links](#visible-links)
|
||||
1. unlocking spatial potential of the (originally 2D) hashtag (which jumps to a chapter) for navigating XR documents
|
||||
|
||||
> NOTE: The chapters in this document are ordered from highlevel to lowlevel (technical) as much as possible
|
||||
|
||||
# Core principle
|
||||
|
||||
XR Fragments strives to serve (nontechnical/fuzzy) humans first, and machine(implementations) later, by ensuring hasslefree text-vs-thought feedback loops.<br>
|
||||
This also means that the repair-ability of machine-matters should be human friendly too (not too complex).<br>
|
||||
**XR Fragments allows controlling of metadata in 3D scene(files) using URLs**
|
||||
|
||||
XR Fragments tries to seek to connect the world of text (semantical web / RDF), and the world of pixels.<br>
|
||||
Instead of combining them (in a game-editor e.g.), XR Fragments is opting for a more integrated path **towards** them, by describing how to make browsers **4D URL-ready**:
|
||||
Instead of combining them (in a game-editor e.g.), XR Fragments **integrates all**, by collecting metadata into an XRWG and control it via URL:
|
||||
|
||||
| principle | XR 4D URL | HTML 2D URL |
|
||||
|----------------------|-------------------------------------------------|---------------------------------------|
|
||||
| the XRWG | wordgraph (collapses 3D scene to tags) | Ctrl-F (find) |
|
||||
| the hashbus | hashtags map to camera/scene-projections | hashtags map to document positions |
|
||||
| spacetime hashtags | positions camera, triggers scene-preset/time | jumps/scrolls to chapter |
|
||||
| the hashbus | hashtags alter camera/scene/object-projections | hashtags alter document positions |
|
||||
| src metadata | renders content and offers sourceportation | renders content |
|
||||
| href metadata | teleports to other XR document | jumps to other HTML document |
|
||||
| href metadata | repositions camera or animation-range | jumps to camera |
|
||||
| href metadata | draws visible connection(s) for XRWG 'tag' | |
|
||||
| href metadata | triggers predefined view | Media fragments |
|
||||
| href metadata | triggers camera/scene/object/projections | n/a |
|
||||
| href metadata | draws visible connection(s) for XRWG 'tag' | n/a |
|
||||
| href metadata | filters certain (in)visible objects | n/a |
|
||||
|
||||
> XR Fragments does not look at XR (or the web) thru the lens of HTML.<br>But approaches things from a higherlevel feedbackloop/hypermedia browser-perspective:
|
||||
|
||||
|
|
@ -142,13 +146,16 @@ Instead of combining them (in a game-editor e.g.), XR Fragments is opting for a
|
|||
│ 2D URL: ://library.com /document ?search #chapter │
|
||||
│ │
|
||||
│ 4D URL: ://park.com /4Dscene.fbx ──> ?misc ──> #view ───> hashbus │
|
||||
│ │ #query │ │
|
||||
│ │ #filter │ │
|
||||
│ │ #tag │ │
|
||||
│ │ #material │ │
|
||||
│ │ #animation │ │
|
||||
│ │ #texture │ │
|
||||
│ │ #variable │ │
|
||||
│ │ │ │
|
||||
│ XRWG <─────────────────────<────────────+ │
|
||||
│ │ │ │
|
||||
│ ├─ objects ───────────────>────────────│ │
|
||||
│ └─ text ───────────────>────────────+ │
|
||||
│ └─ objects ──────────────>────────────+ │
|
||||
│ │
|
||||
│ │
|
||||
+──────────────────────────────────────────────────────────────────────────────────────────────+
|
||||
|
|
@ -180,36 +187,63 @@ sub-delims = "," / "="
|
|||
| Demo | Explanation |
|
||||
|-------------------------------|---------------------------------|
|
||||
| `pos=1,2,3` | vector/coordinate argument e.g. |
|
||||
| `pos=1,2,3&rot=0,90,0&q=.foo` | combinators |
|
||||
| `pos=1,2,3&rot=0,90,0&foo` | combinators |
|
||||
|
||||
> this is already implemented in all browsers
|
||||
|
||||
# List of URI Fragments
|
||||
|
||||
| fragment | type | example | info |
|
||||
|--------------|----------|-------------------|----------------------------------------------------------------------|
|
||||
| `#pos` | vector3 | `#pos=0.5,0,0` | positions camera (or XR floor) to xyz-coord 0.5,0,0, |
|
||||
| `#rot` | vector3 | `#rot=0,90,0` | rotates camera to xyz-coord 0.5,0,0 |
|
||||
| `#t` | vector3 | `#t=1,500,1000` | play animation-loop range between frame 500 and 1000, at normal speed|
|
||||
| `#......` | string | `#.cubes` `#cube` | predefined views, XRWG fragments and ID fragments |
|
||||
| fragment | type | example | info |
|
||||
|-------------------|------------|--------------------|----------------------------------------------------------------------|
|
||||
| `#pos` | vector3 | `#pos=0.5,0,0` | positions camera (or XR floor) to xyz-coord 0.5,0,0, |
|
||||
| `#rot` | vector3 | `#rot=0,90,0` | rotates camera to xyz-coord 0.5,0,0 |
|
||||
| `#t` | timevector | `#t=2,2000,1` | play animation-loop range between frame 2 and 2000 at (normal) speed 1 |
|
||||
|
||||
> xyz coordinates are similar to ones found in SVG Media Fragments
|
||||
|
||||
# List of metadata for 3D nodes
|
||||
## List of metadata for 3D nodes
|
||||
|
||||
| key | type | example (JSON) | function | existing compatibility |
|
||||
|--------------|----------|------------------------|---------------------|----------------------------------------|
|
||||
| `href` | string | `"href": "b.gltf"` | XR teleport | custom property in 3D fileformats |
|
||||
| `src` | string | `"src": "#cube"` | XR embed / teleport | custom property in 3D fileformats |
|
||||
| `tag` | string | `"tag": "cubes geo"` | tag object (for query-use / XRWG highlighting) | custom property in 3D fileformats |
|
||||
| `tag` | string | `"tag": "cubes geo"` | tag object (for filter-use / XRWG highlighting) | custom property in 3D fileformats |
|
||||
|
||||
Supported popular compatible 3D fileformats: `.gltf`, `.obj`, `.fbx`, `.usdz`, `.json` (THREE.js), `.dae` and so on.
|
||||
> Supported popular compatible 3D fileformats: `.gltf`, `.obj`, `.fbx`, `.usdz`, `.json` (THREE.js), `.dae` and so on.
|
||||
|
||||
## vector datatypes
|
||||
|
||||
| type | syntax | example | info |
|
||||
|------
|
||||
| vector2 | x,y | 2,3.0 | 2-dimensional vector |
|
||||
| vector3 | x,y,z | 2,3.0,4 | 3-dimensional vector |
|
||||
| timevector | speed | 1 | 1D timeline: play |
|
||||
| | | 0 | 1D timeline: stop |
|
||||
| | x,speed | 1,2 | 1D timeline: play at offset `1` at (normal) speed `2` |
|
||||
| | | 0,0 | 1D timeline: stop (stopoffset-startoffset == 0) |
|
||||
| | | 0,1 | 1D timeline: unpause with (normal) speed `1` |
|
||||
| | | 1..100,1 | 1D timeline: play (loop) between offset `1` and `100` at normal speed (`1`) |
|
||||
| | x,y,xspeed,yspeed | 0,0.5,0,0 | 2D timeline: stop uv-coordinate at `0,0.5` |
|
||||
| | | 0,0.5,0.2,0 | 2D timeline: play uv-coordinate at offset `0,0.5` and scroll `x` (=u) `0.2` within each second |
|
||||
| | | 0,0..0.5,0.2,0 | 2D timeline: play uv-coordinate between offset `0,0` and `0,0.5` (loop) and scroll `x` (=u) `0.2` within each second |
|
||||
| | x,y,z,xspeed,yspeed,zspeed | 0,0.5,1,0.2,0,2 | XD timeline: play uv-coordinate at `0,0.5` and scroll `x` (=u) `0.2` within each second and pass `1` and `2` as custom data to shader uniforms `za` and `zb` |
|
||||
|
||||
> NOTE: XR Fragments are optional but also file- and protocol-agnostic, which means that programmatic 3D scene(nodes) can also use the mechanism/metadata.
|
||||
|
||||
## Dynamic XR Fragments (+databindings)
|
||||
|
||||
These are automatic fragment-to-metadata mappings, which only trigger if the 3D scene metadata matches a specific identifier (`aliasname` e.g.)
|
||||
|
||||
| fragment | type | example | info |
|
||||
|------------------------|----------|-------------------|-------------------------------------------------------------------------------|
|
||||
| `#<aliasname>` | string | `#cubes` | evaluate predefined views (`#cubes: #foo&bar` e.g.) |
|
||||
| `#<tag_or_objectname>` | string | `#person` | focus object(s) with `tag: person` or name `person` by looking up XRWG |
|
||||
| `#<cameraname>` | string | `#cam01` | set camera as active camera |
|
||||
| `#<objectname>=<material>` | string=string | `#car=metallic`| set material of car to material with name `metallic` |
|
||||
| | string=string | `#product=metallic`| set material of objects tagged with `product` to material with name `metallic` |
|
||||
| `#<objectname>=<mediafrag>` | string=[media frag](https://www.w3.org/TR/media-frags/#valid-uri) | `#foo=0,1`| play media `src` using [media fragment URI](https://www.w3.org/TR/media-frags/#valid-uri) |
|
||||
| `#<objectname>=<timevector>` | string=timevector | `#sky=0,0.5,0.1,0`| sets 1D/2D/3D time(line) vectors (uv-position e.g.) to `0,0.5` (and autoscroll x with max `0.1` every second)|
|
||||
| | | `#music=1,2`| play media of object (`src: podcast.mp3` e.g.) from beginning (`1`) at double speed (`2`) |
|
||||
|
||||
# Spatial Referencing 3D
|
||||
|
||||
|
||||
XR Fragments assume the following objectname-to-URIFragment mapping:
|
||||
|
||||
```
|
||||
|
|
@ -245,7 +279,7 @@ For example, to render a portal with a preview-version of the scene, create an 3
|
|||
|
||||
| fragment | type | functionality |
|
||||
|----------|--------|------------------------------|
|
||||
| <b>#pos</b>=0,0,0 | vector3 | (re)position camera |
|
||||
| <b>#pos</b>=0,0,0 | vector3 or string| (re)position camera based on coordinates directly, or indirectly using objectname (its worldposition) |
|
||||
| <b>#t</b>=0,100 | vector3 | set playback speed, and (re)position looprange of scene-animation or `src`-mediacontent |
|
||||
| <b>#rot</b>=0,90,0 | vector3 | rotate camera |
|
||||
|
||||
|
|
@ -256,7 +290,7 @@ For example, to render a portal with a preview-version of the scene, create an 3
|
|||
1. set the position of the camera accordingly to the vector3 values of `#pos`
|
||||
1. `rot` sets the rotation of the camera (only for non-VR/AR headsets)
|
||||
1. `t` sets the playbackspeed and animation-range of the current scene animation(s) or `src`-mediacontent (video/audioframes e.g., use `t=0,7,7` to 'STOP' at frame 7 e.g.)
|
||||
1. in case an `href` does not mention any `pos`-coordinate, `pos=0,0,0` will be assumed
|
||||
1. after scene load: in case an `href` does not mention any `pos`-coordinate, `pos=0,0,0` will be assumed
|
||||
|
||||
Here's an ascii representation of a 3D scene-graph which contains 3D objects `◻` and their metadata:
|
||||
|
||||
|
|
@ -291,27 +325,27 @@ The URL-processing-flow for hypermedia browsers goes like this:
|
|||
5. IF a `#cube` matches anything else in the XR Word Graph (XRWG) draw wires to them (text or related objects).
|
||||
|
||||
|
||||
# Embedding XR content (src-instancing)
|
||||
# Embedding XR content using src
|
||||
|
||||
`src` is the 3D version of the <a target="_blank" href="https://www.w3.org/html/wiki/Elements/iframe">iframe</a>.<br>
|
||||
It instances content (in objects) in the current scene/asset.
|
||||
|
||||
| fragment | type | example value |
|
||||
|----------|------|---------------|
|
||||
|`src`| string (uri, hashtag/query) | `#cube`<br>`#sometag`<br>#q=-ball_inside_cube`<br>`#q=-/sky -rain`<br>`#q=-.language .english`<br>`#q=price:>2 price:<5`<br>`https://linux.org/penguin.png`<br>`https://linux.world/distrowatch.gltf#t=1,100`<br>`linuxapp://conference/nixworkshop/apply.gltf#q=flyer`<br>`androidapp://page1?tutorial#pos=0,0,1&t1,100`|
|
||||
|`src`| string (uri, hashtag/filter) | `#cube`<br>`#sometag`<br>#cube&-ball_inside_cube`<br>`#-sky&-rain`<br>`#-language&english`<br>`#price=>5`<br>`https://linux.org/penguin.png`<br>`https://linux.world/distrowatch.gltf#t=1,100`<br>`linuxapp://conference/nixworkshop/apply.gltf#-cta&cta_apply`<br>`androidapp://page1?tutorial#pos=0,0,1&t1,100`<br>`foo.mp3#0,0,0`|
|
||||
|
||||
Here's an ascii representation of a 3D scene-graph with 3D objects `◻` which embeds remote & local 3D objects `◻` with/out using queries:
|
||||
Here's an ascii representation of a 3D scene-graph with 3D objects `◻` which embeds remote & local 3D objects `◻` with/out using filters:
|
||||
|
||||
```
|
||||
+────────────────────────────────────────────────────────+ +─────────────────────────+
|
||||
│ │ │ │
|
||||
│ index.gltf │ │ ocean.com/aquarium.fbx │
|
||||
│ │ │ │ │ │
|
||||
│ │ │ │ ├ room │
|
||||
│ ├── ◻ canvas │ │ └── ◻ fishbowl │
|
||||
│ │ └ src: painting.png │ │ ├─ ◻ bass │
|
||||
│ │ │ │ └─ ◻ tuna │
|
||||
│ ├── ◻ aquariumcube │ │ │
|
||||
│ │ └ src: ://rescue.com/fish.gltf#bass%20tuna │ +─────────────────────────+
|
||||
│ │ └ src: ://rescue.com/fish.gltf#fishbowl │ +─────────────────────────+
|
||||
│ │ │
|
||||
│ ├── ◻ bedroom │
|
||||
│ │ └ src: #canvas │
|
||||
|
|
@ -323,35 +357,39 @@ Here's an ascii representation of a 3D scene-graph with 3D objects `◻` which e
|
|||
```
|
||||
|
||||
An XR Fragment-compatible browser viewing this scene, lazy-loads and projects `painting.png` onto the (plane) object called `canvas` (which is copy-instanced in the bed and livingroom).<br>
|
||||
Also, after lazy-loading `ocean.com/aquarium.gltf`, only the queried objects `bass` and `tuna` will be instanced inside `aquariumcube`.<br>
|
||||
Also, after lazy-loading `ocean.com/aquarium.gltf`, only the queried objects `fishbowl` (and `bass` and `tuna`) will be instanced inside `aquariumcube`.<br>
|
||||
Resizing will be happen accordingly to its placeholder object `aquariumcube`, see chapter Scaling.<br>
|
||||
|
||||
> Instead of cherrypicking objects with `#bass&tuna` thru `src`, queries can be used to import the whole scene (and filter out certain objects). See next chapter below.
|
||||
> Instead of cherrypicking a rootobject `#fishbowl` with `src`, additional filters can be used to include/exclude certain objects. See next chapter on filtering below.
|
||||
|
||||
**Specification**:
|
||||
|
||||
1. local/remote content is instanced by the `src` (query) value (and attaches it to the placeholder mesh containing the `src` property)
|
||||
1. <b>local</b> `src` values (URL **starting** with `#`, like `#cube&foo`) means **only** the mentioned objectnames will be copied to the instanced scene (from the current scene) while preserving their names (to support recursive selectors). [(example code)](https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/src.js)
|
||||
1. <b>local</b> `src` values indicating a query (`#q=`), means that all included objects (from the current scene) will be copied to the instanced scene (before applying the query) while preserving their names (to support recursive selectors). [(example code)](https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/src.js)
|
||||
1. the instanced scene (from a `src` value) should be <b>scaled accordingly</b> to its placeholder object or <b>scaled relatively</b> based on the scale-property (of a geometry-less placeholder, an 'empty'-object in blender e.g.). For more info see Chapter Scaling.
|
||||
1. <b>external</b> `src` values should be served with appropriate mimetype (so the XR Fragment-compatible browser will now how to render it). The bare minimum supported mimetypes are:
|
||||
1. `src` values should make its placeholder object invisible, and only flush its children when the resolved content can succesfully be retrieved (see [broken links](#links))
|
||||
1. <b>external</b> `src` values should respect the fallback link mechanism (see [broken links](#broken-links)
|
||||
1. when the placeholder object is a 2D plane, but the mimetype is 3D, then render the spatial content on that plane via a stencil buffer.
|
||||
1. src-values are non-recursive: when linking to an external object (`src: foo.fbx#bar`), then `src`-metadata on object `bar` should be ignored.
|
||||
1. clicking on external `src`-values always allow sourceportation: teleporting to the origin URI to which the object belongs.
|
||||
1. when only one object was cherrypicked (`#cube` e.g.), set its position to `0,0,0`
|
||||
1. local/remote content is instanced by the `src` (filter) value (and attaches it to the placeholder mesh containing the `src` property)
|
||||
2. by default all objects are loaded into the instanced src (scene) object (but not shown yet)
|
||||
2. <b>local</b> `src` values (`#...` e.g.) starting with a non-negating filter (`#cube` e.g.) will (deep)reparent that object (with name `cube`) as the new root of the scene at position 0,0,0
|
||||
3. <b>local</b> `src` values should respect (negative) filters (`#-foo&price=>3`)
|
||||
4. the instanced scene (from a `src` value) should be <b>scaled accordingly</b> to its placeholder object or <b>scaled relatively</b> based on the scale-property (of a geometry-less placeholder, an 'empty'-object in blender e.g.). For more info see Chapter Scaling.
|
||||
5. <b>external</b> `src` values should be served with appropriate mimetype (so the XR Fragment-compatible browser will now how to render it). The bare minimum supported mimetypes are:
|
||||
6. `src` values should make its placeholder object invisible, and only flush its children when the resolved content can succesfully be retrieved (see [broken links](#links))
|
||||
7. <b>external</b> `src` values should respect the fallback link mechanism (see [broken links](#broken-links)
|
||||
8. when the placeholder object is a 2D plane, but the mimetype is 3D, then render the spatial content on that plane via a stencil buffer.
|
||||
9. src-values are non-recursive: when linking to an external object (`src: foo.fbx#bar`), then `src`-metadata on object `bar` should be ignored.
|
||||
10. an external `src`-value should always allow a sourceportation icon within 3 meter: teleporting to the origin URI to which the object belongs.
|
||||
11. when only one object was cherrypicked (`#cube` e.g.), set its position to `0,0,0`
|
||||
12. when the enduser clicks an href with `#t=1,0,0` (play) will be applied to all src mediacontent with a timeline (mp4/mp3 e.g.)
|
||||
13. a non-euclidian portal can be rendered for flat 3D objects (using stencil buffer e.g.) in case ofspatial `src`-values (an object `#world3` or URL `world3.fbx` e.g.).
|
||||
|
||||
* `model/gltf-binary`
|
||||
* `model/gltf+json`
|
||||
* `image/png`
|
||||
* `image/jpg`
|
||||
* `text/plain;charset=utf-8;bib=^@`
|
||||
* `text/plain;charset=utf-8`
|
||||
|
||||
[» example implementation](https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/src.js)<br>
|
||||
[» example 3D asset](https://github.com/coderofsalvation/xrfragment/blob/main/example/assets/src.gltf#L192)<br>
|
||||
[» discussion](https://github.com/coderofsalvation/xrfragment/issues/4)<br>
|
||||
|
||||
# Navigating content (internal/outbound href portals)
|
||||
# Navigating content href portals
|
||||
|
||||
navigation, portals & mutations
|
||||
|
||||
|
|
@ -367,16 +405,24 @@ navigation, portals & mutations
|
|||
|
||||
4. URL navigation should always be reflected in the client (in case of javascript: see [[here](https://github.com/coderofsalvation/xrfragment/blob/dev/src/3rd/js/three/navigator.js) for an example navigator).
|
||||
|
||||
5. In XR mode, the navigator back/forward-buttons should be always visible (using a wearable e.g., see [[here](https://github.com/coderofsalvation/xrfragment/blob/dev/example/aframe/sandbox/index.html#L26-L29) for an example wearable)
|
||||
7. In XR mode, the navigator back/forward-buttons should be always visible (using a wearable e.g., see [[here](https://github.com/coderofsalvation/xrfragment/blob/dev/example/aframe/sandbox/index.html#L26-L29) for an example wearable)
|
||||
|
||||
6. in case of navigating to a new [[pos)ition, ''first'' navigate to the ''current position'' so that the ''back-button'' of the ''browser-history'' always refers to the previous position (see [[here](https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/href.js#L97))
|
||||
8. in case of navigating to a new [[pos)ition, ''first'' navigate to the ''current position'' so that the ''back-button'' of the ''browser-history'' always refers to the previous position (see [[here](https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/href.js#L97))
|
||||
|
||||
7. portal-rendering: a 2:1 ratio texture-material indicates an equirectangular projection
|
||||
9. ignore previous rule in special cases, like clicking an `href` using camera-portal collision (the back-button would cause a teleport-loop)
|
||||
|
||||
[» example implementation](https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/href.js)<br>
|
||||
[» example 3D asset](https://github.com/coderofsalvation/xrfragment/blob/main/example/assets/href.gltf#L192)<br>
|
||||
[» discussion](https://github.com/coderofsalvation/xrfragment/issues/1)<br>
|
||||
|
||||
## Walking surfaces
|
||||
|
||||
XR Fragment-compatible viewers can infer this data based scanning the scene for:
|
||||
|
||||
1. materialless (nameless & textureless) mesh-objects (without `src` and `href`)
|
||||
|
||||
> optionally the viewer can offer thumbstick, mouse or joystick teleport-tools for non-roomscale VR/AR setups.
|
||||
|
||||
## UX spec
|
||||
|
||||
End-users should always have read/write access to:
|
||||
|
|
@ -407,58 +453,98 @@ How does the scale of the object (with the embedded properties) impact the scale
|
|||
|
||||
> TODO: needs intermediate visuals to make things more obvious
|
||||
|
||||
# XR Fragment queries
|
||||
# XR Fragment: pos
|
||||
|
||||
# XR Fragment: rot
|
||||
|
||||
# XR Fragment: t
|
||||
|
||||
controls the animation(s) of the scene (or `src` resource which contains a timeline)
|
||||
|
||||
| fragment | type | functionality |
|
||||
| <b>#t</b>=1,1,100 | [[vector3|vector]] (default:`#t=1,0,0`) | speed,framestart,framestop |
|
||||
|
||||
* playposition is reset to framestart, when framestart or framestop is greater than 0 |
|
||||
|
||||
| Example Value | Explanation |
|
||||
|-|-|
|
||||
| `1,1,100` | play loop between frame 1 and 100 |
|
||||
| `1,1,0` | play once from frame 1 (oneshot) |
|
||||
| `1,0,0` | play (previously set looprange if any) |
|
||||
| `0,0,0` | pause |
|
||||
| `1,1,1` | play and auto-loop between begin and end of duration |
|
||||
| `-1,0,0` | reverse playback speed |
|
||||
| `2.3,0,0` | set (forward) playback speed to 2.3 (no restart) |
|
||||
| `-2.3,0,0` | set (reverse) playback speed to -2.3 ( no restart)|
|
||||
| `-2.3,100,0` | set (reverse) playback speed to -2.3 restarting from frame 100 |
|
||||
|
||||
[[» example implementation|https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/t.js]]<br>
|
||||
[[» discussion|https://github.com/coderofsalvation/xrfragment/issues/10]]<br>
|
||||
|
||||
# XR audio/video integration
|
||||
|
||||
To play global audio/video items:
|
||||
|
||||
1. add a `src: foo.mp3` or `src: bar.mp4` metadata to a 3D object (`cube` e.g.)
|
||||
1. to disable auto-play and global timeline ([[#t=|t]]) control: hardcode a [[#t=|t]] XR Fragment: (`src: bar.mp3#t=0,0,0` e.g.)
|
||||
1. to play it, add `href: #cube` somewhere else
|
||||
1. when the enduser clicks the `href`, `#t=1,0,0` (play) will be applied to the `src` value
|
||||
1. to play a single animation, add href: #animationname=1,0,0 somewhere else
|
||||
|
||||
> NOTE: hardcoded framestart/framestop uses sampleRate/fps of embedded audio/video, otherwise the global fps applies. For more info see [[#t|t]].
|
||||
|
||||
# XR Fragment filters
|
||||
|
||||
Include, exclude, hide/shows objects using space-separated strings:
|
||||
|
||||
| example | outcome |
|
||||
|----------------------------------|------------------------------------------------------------------------------------|
|
||||
| `#q=-sky` | show everything except object named `sky` |
|
||||
| `#q=-tag:language tag:english` | hide everything with tag `language`, but show all tag `english` objects |
|
||||
| `#q=price:>2 price:<5` | of all objects with property `price`, show only objects with value between 2 and 5 |
|
||||
| `#-sky` | show everything except object named `sky` |
|
||||
| `#-language&english` | hide everything with tag `language`, but show all tag `english` objects |
|
||||
| `#-price&price=>10` | hide all objects with property `price`, then only show object with price above 10 |
|
||||
|
||||
It's simple but powerful syntax which allows filtering the scene using searchengine prompt-style feeling:
|
||||
|
||||
1. queries are a way to traverse a scene, and filter objects based on their tag- or property-values.
|
||||
1. words like `german` match tag-metadata of 3D objects like `"tag":"german"`
|
||||
1. words like `german` match (XR Text) objects with (Bib(s)TeX) tags like `#KarlHeinz@german` or `@german{KarlHeinz, ...` e.g.
|
||||
1. filters are a way to traverse a scene, and filter objects based on their name, tag- or property-values.
|
||||
|
||||
* see [an (outdated) example video here](https://coderofsalvation.github.io/xrfragment.media/queries.mp4)
|
||||
* see [an (outdated) example video here](https://coderofsalvation.github.io/xrfragment.media/queries.mp4) which used a dedicated `q=` variable (now deprecated and usable directly)
|
||||
|
||||
## including/excluding
|
||||
|
||||
By default, selectors work like photoshop-layers: they scan for matching layer(name/properties) within the scene-graph.
|
||||
Each matched object (not their children) will be toggled (in)visible when selecting.
|
||||
|
||||
| operator | info |
|
||||
|----------|-------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `-` | removes/hides object(s) |
|
||||
| `:` | indicates an object-embedded custom property key/value |
|
||||
| `>` `<` | compare float or int number |
|
||||
| `/` | reference to root-scene.<br>Useful in case of (preventing) showing/hiding objects in nested scenes (instanced by `src`) (*) |
|
||||
| `-` | hides object(s) (`#-myobject&-objects` e.g. |
|
||||
| `=` | indicates an object-embedded custom property key/value (`#price=4&category=foo` e.g.) |
|
||||
| `=>` `=<`| compare float or int number (`#price=>4` e.g.) |
|
||||
| `*` | deepselect: automatically select children of selected object, including local (nonremote) embedded objects (starting with `#`)|
|
||||
|
||||
> \* = `#q=-/cube` hides object `cube` only in the root-scene (not nested `cube` objects)<br> `#q=-cube` hides both object `cube` in the root-scene <b>AND</b> nested `skybox` objects |
|
||||
> NOTE 1: after an external embedded object has been instanced (`src: https://y.com/bar.fbx#room` e.g.), filters do not affect them anymore (reason: local tag/name collisions can be mitigated easily, but not in case of remote content).
|
||||
|
||||
> NOTE 2: depending on the used 3D framework, toggling objects (in)visible should happen by enabling/disableing writing to the colorbuffer (to allow children being still visible while their parents are invisible).
|
||||
|
||||
[» example implementation](https://github.com/coderofsalvation/xrfragment/blob/main/src/3rd/js/three/xrf/q.js)
|
||||
[» example 3D asset](https://github.com/coderofsalvation/xrfragment/blob/main/example/assets/query.gltf#L192)
|
||||
[» example 3D asset](https://github.com/coderofsalvation/xrfragment/blob/main/example/assets/filter.gltf#L192)
|
||||
[» discussion](https://github.com/coderofsalvation/xrfragment/issues/3)
|
||||
|
||||
## Query Parser
|
||||
## Filter Parser
|
||||
|
||||
Here's how to write a query parser:
|
||||
Here's how to write a filter parser:
|
||||
|
||||
1. create an associative array/object to store query-arguments as objects
|
||||
1. detect object id's & properties `foo:1` and `foo` (reference regex: `/^.*:[><=!]?/` )
|
||||
1. detect excluders like `-foo`,`-foo:1`,`-.foo`,`-/foo` (reference regex: `/^-/` )
|
||||
1. detect root selectors like `/foo` (reference regex: `/^[-]?\//` )
|
||||
1. detect number values like `foo:1` (reference regex: `/^[0-9\.]+$/` )
|
||||
1. for every query token split string on `:`
|
||||
1. create an empty array `rules`
|
||||
1. then strip key-operator: convert "-foo" into "foo"
|
||||
1. add operator and value to rule-array
|
||||
1. therefore we we set `id` to `true` or `false` (false=excluder `-`)
|
||||
1. create an associative array/object to store filter-arguments as objects
|
||||
1. detect object id's & properties `foo=1` and `foo` (reference regex= `~/^.*=[><=]?/` )
|
||||
1. detect excluders like `-foo`,`-foo=1`,`-.foo`,`-/foo` (reference regex= `/^-/` )
|
||||
1. detect root selectors like `/foo` (reference regex= `/^[-]?\//` )
|
||||
1. detect number values like `foo=1` (reference regex= `/^[0-9\.]+$/` )
|
||||
1. detect operators so you can easily strip keys (reference regex= `/(^-|\*$)/` )
|
||||
1. detect exclude keys like `-foo` (reference regex= `/^-/` )
|
||||
1. for every filter token split string on `=`
|
||||
1. and we set `root` to `true` or `false` (true=`/` root selector is present)
|
||||
1. we convert key '/foo' into 'foo'
|
||||
1. finally we add the key/value to the store like `store.foo = {id:false,root:true}` e.g.
|
||||
1. therefore we we set `show` to `true` or `false` (false=excluder `-`)
|
||||
|
||||
> An example query-parser (which compiles to many languages) can be [found here](https://github.com/coderofsalvation/xrfragment/blob/main/src/xrfragment/Query.hx)
|
||||
> An example filter-parser (which compiles to many languages) can be [found here](https://github.com/coderofsalvation/xrfragment/blob/main/src/xrfragment/Filter.hx)
|
||||
|
||||
# Visible links
|
||||
|
||||
|
|
@ -789,12 +875,12 @@ For example:
|
|||
│ │
|
||||
│ index.gltf │
|
||||
│ │ │
|
||||
│ │ #: #q=-offlinetext │
|
||||
│ │ #: #-offlinetext │
|
||||
│ │ │
|
||||
│ ├── ◻ buttonA │
|
||||
│ │ └ href: http://foo.io/campagne.fbx │
|
||||
│ │ └ href@404: ipfs://foo.io/campagne.fbx │
|
||||
│ │ └ href@400: #q=clienterrortext │
|
||||
│ │ └ href@400: #clienterrortext │
|
||||
│ │ └ ◻ offlinetext │
|
||||
│ │ │
|
||||
│ └── ◻ embeddedObject <--------- the meshdata inside embeddedObject will (not)
|
||||
|
|
@ -816,11 +902,11 @@ Consider 3D scenes linking to eachother using these `href` values:
|
|||
* `href: university.edu/projects.gltf#math`
|
||||
|
||||
These links would all show visible links to math-tagged objects in the scene.<br>
|
||||
To filter out non-related objects one could take it a step further using queries:
|
||||
To filter out non-related objects one could take it a step further using filters:
|
||||
|
||||
* `href: schoolA.edu/projects.gltf#math&q=-topics math`
|
||||
* `href: schoolB.edu/projects.gltf#math&q=-courses math`
|
||||
* `href: university.edu/projects.gltf#math&q=-theme math`
|
||||
* `href: schoolA.edu/projects.gltf#math&-topics math`
|
||||
* `href: schoolB.edu/projects.gltf#math&-courses math`
|
||||
* `href: university.edu/projects.gltf#math&-theme math`
|
||||
|
||||
> This would hide all object tagged with `topic`, `courses` or `theme` (including math) so that later only objects tagged with `math` will be visible
|
||||
|
||||
|
|
@ -854,6 +940,15 @@ This document has no IANA actions.
|
|||
* [NLNET](https://nlnet.nl)
|
||||
* [Future of Text](https://futureoftext.org)
|
||||
* [visual-meta.info](https://visual-meta.info)
|
||||
* Michiel Leenaars
|
||||
* Gerben van der Broeke
|
||||
* Mauve
|
||||
* Jens Finkhäuser
|
||||
* Marc Belmont
|
||||
* Tim Gerritsen
|
||||
* Frode Hegland
|
||||
* Brandel Zackernuk
|
||||
* Mark Anderson
|
||||
|
||||
# Appendix: Definitions
|
||||
|
||||
|
|
@ -872,7 +967,7 @@ This document has no IANA actions.
|
|||
|placeholder object | a 3D object which with src-metadata (which will be replaced by the src-data.) |
|
||||
|src | (HTML-piggybacked) metadata of a 3D object which instances content |
|
||||
|href | (HTML-piggybacked) metadata of a 3D object which links to content |
|
||||
|query | an URI Fragment-operator which queries object(s) from a scene like `#q=cube` |
|
||||
|filter | URI Fragment(s) which show/hide object(s) in a scene based on name/tag/property (`#cube&-price=>3`) |
|
||||
|visual-meta | [visual-meta](https://visual.meta.info) data appended to text/books/papers which is indirectly visible/editable in XR. |
|
||||
|requestless metadata | metadata which never spawns new requests (unlike RDF/HTML, which can cause framerate-dropping, hence not used a lot in games) |
|
||||
|FPS | frames per second in spatial experiences (games,VR,AR e.g.), should be as high as possible |
|
||||
|
|
@ -880,6 +975,7 @@ This document has no IANA actions.
|
|||
|extrospective | outward sensemaking ("I'm fairly sure John is a person who lives in oklahoma") |
|
||||
|`◻` | ascii representation of an 3D object/mesh |
|
||||
|(un)obtrusive | obtrusive: wrapping human text/thought in XML/HTML/JSON obfuscates human text into a salad of machine-symbols and words |
|
||||
|flat 3D object | a 3D object of which all verticies share a plane |
|
||||
|BibTeX | simple tagging/citing/referencing standard for plaintext |
|
||||
|BibTag | a BibTeX tag |
|
||||
|(hashtag)bibs | an easy to speak/type/scan tagging SDL ([see here](https://github.com/coderofsalvation/hashtagbibs) which expands to BibTex/JSON/XML |
|
||||
|
|
|
|||
BIN
example/aframe/sandbox/arrow.jpg
Normal file
BIN
example/aframe/sandbox/arrow.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
BIN
example/aframe/sandbox/assetsfoo.glb
Normal file
BIN
example/aframe/sandbox/assetsfoo.glb
Normal file
Binary file not shown.
BIN
example/aframe/sandbox/equirect.jpg
Normal file
BIN
example/aframe/sandbox/equirect.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 153 KiB |
|
|
@ -1 +0,0 @@
|
|||
assets/example.gltf
|
||||
BIN
example/aframe/sandbox/gradient2.png
Normal file
BIN
example/aframe/sandbox/gradient2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
1
example/aframe/sandbox/index.glb
Symbolic link
1
example/aframe/sandbox/index.glb
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
assets/index.glb
|
||||
|
|
@ -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>
|
||||
|
|
@ -30,58 +30,55 @@
|
|||
<textarea style="display:none"></textarea>
|
||||
<canvas id="qrcode" style="display:none" width="300" height="300"></canvas>
|
||||
|
||||
<a-scene light="defaultLightsEnabled: false">
|
||||
<a-entity id="player" wasd-controls look-controls>
|
||||
<a-entity id="left-hand" laser-controls="hand: left" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: #floor">
|
||||
<a-entity rotation="-90 0 0" position="0 0.1 0" id="navigator">
|
||||
<a-scene renderer="colorManagement: true; highRefreshRate:true" light="defaultLightsEnabled: false">
|
||||
<a-entity id="player">
|
||||
<a-entity camera="fov:90" position="0 1.6 0" wasd-controls look-controls id="camera"></a-entity>
|
||||
<a-entity id="left-hand" laser-controls="hand: left" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: .floor">
|
||||
<a-entity rotation="-35 0 0" position="0 0.1 0" id="navigator">
|
||||
<a-entity id="back" xrf-button="label: <; width:0.05; action: history.back()" position="-0.025 0 0" class="ray"></a-entity>
|
||||
<a-entity id="next" xrf-button="label: >; width:0.05; action: history.forward()" position=" 0.025 0 0" class="ray"></a-entity>
|
||||
</a-entity>
|
||||
</a-entity>
|
||||
<a-entity id="right-hand" laser-controls="hand: right" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: #floor"></a-entity>
|
||||
<a-entity camera="fov:90" position="0 1.6 0" id="camera"></a-entity>
|
||||
<a-entity id="right-hand" laser-controls="hand: right" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #player; collisionEntities: .floor"></a-entity>
|
||||
</a-entity>
|
||||
|
||||
<a-entity id="home" xrf="index.gltf#pos=0,0,0"></a-entity>
|
||||
<a-plane id="floor" position="0 0 0" rotation="-90 0 0" width="100" height="100" material="visible:false"></a-plane>
|
||||
<a-entity id="home" xrf="index.glb"></a-entity>
|
||||
</a-scene>
|
||||
|
||||
<script>
|
||||
window.$ = (s) => document.querySelector(s)
|
||||
window.notify = notify(window)
|
||||
window.embed = embed
|
||||
|
||||
console.log = ( (log) => function(str){
|
||||
if( String(str).match(/:.*#/) ) window.notify(str)
|
||||
log(str)
|
||||
})(console.log)
|
||||
|
||||
if( document.location.search.length > 2 )
|
||||
$('#home').setAttribute('xrf', document.location.search.substr(1)+document.location.hash )
|
||||
|
||||
// allow iframe to open url
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.data && event.data.url) {
|
||||
window.open(event.data.url, '_blank');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$('a-scene').addEventListener('XRF', () => {
|
||||
window.notify = notify(window)
|
||||
window.embed = embed
|
||||
window.notify('loading '+document.location.search.substr(1))
|
||||
|
||||
// reroute console messages to snackbar notifications
|
||||
console.log = ( (log) => function(str){
|
||||
if( String(str).match(/(:.*#|note:)/) ) window.notify(str)
|
||||
log(str)
|
||||
})(console.log)
|
||||
|
||||
let XRF = window.AFRAME.XRF
|
||||
setupConsole( $('textarea') )
|
||||
setupUrlBar( $('input#uri'), XRF )
|
||||
|
||||
// example listener, to prompt surfing to external asset
|
||||
XRF.addEventListener('href',(e) => {
|
||||
if( e.click ){
|
||||
const { mesh, model, camera, scene, renderer, THREE} = e.XRF
|
||||
const url = e.xrf.string
|
||||
const isExtern = url[0] != '#'
|
||||
const notIsHome = url != $('#home').getAttribute("xrf")
|
||||
const promise = e.promise() // promisify event
|
||||
document.querySelector('#model').setAttribute('href',url.replace(/.*\?/,'') )
|
||||
if( !renderer.xr.isPresenting ){
|
||||
if( isExtern && notIsHome ){
|
||||
if( !confirm("teleport to "+url+" ?") ) return promise.reject('teleport rejected')
|
||||
}
|
||||
}
|
||||
promise.resolve()
|
||||
}
|
||||
})
|
||||
// on localhost enable debugging mode for developer convenience
|
||||
let loc = document.location
|
||||
if( loc.host.match(/^localhost/) ){
|
||||
$('a-scene').setAttribute('stats')
|
||||
XRF.debug = 1
|
||||
}
|
||||
|
||||
// add screenshot component with camera to capture bigger size equirects
|
||||
// document.querySelector('a-scene').components.screenshot.capture('perspective')
|
||||
|
|
|
|||
BIN
example/aframe/sandbox/sky.jpg
Normal file
BIN
example/aframe/sandbox/sky.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
BIN
example/assets/AnimatedCube.bin
Normal file
BIN
example/assets/AnimatedCube.bin
Normal file
Binary file not shown.
262
example/assets/AnimatedCube.gltf
Normal file
262
example/assets/AnimatedCube.gltf
Normal file
|
|
@ -0,0 +1,262 @@
|
|||
{
|
||||
"accessors" : [
|
||||
{
|
||||
"bufferView" : 0,
|
||||
"byteOffset" : 0,
|
||||
"componentType" : 5126,
|
||||
"count" : 3,
|
||||
"max" : [
|
||||
2.000000
|
||||
],
|
||||
"min" : [
|
||||
0.000000
|
||||
],
|
||||
"type" : "SCALAR"
|
||||
},
|
||||
{
|
||||
"bufferView" : 1,
|
||||
"byteOffset" : 0,
|
||||
"componentType" : 5126,
|
||||
"count" : 3,
|
||||
"max" : [
|
||||
0.000000,
|
||||
1.000000,
|
||||
0.000000,
|
||||
1.000000
|
||||
],
|
||||
"min" : [
|
||||
0.000000,
|
||||
-8.742278e-008,
|
||||
0.000000,
|
||||
-1.000000
|
||||
],
|
||||
"type" : "VEC4"
|
||||
},
|
||||
{
|
||||
"bufferView" : 2,
|
||||
"byteOffset" : 0,
|
||||
"componentType" : 5123,
|
||||
"count" : 36,
|
||||
"max" : [
|
||||
35
|
||||
],
|
||||
"min" : [
|
||||
0
|
||||
],
|
||||
"type" : "SCALAR"
|
||||
},
|
||||
{
|
||||
"bufferView" : 3,
|
||||
"byteOffset" : 0,
|
||||
"componentType" : 5126,
|
||||
"count" : 36,
|
||||
"max" : [
|
||||
1.000000,
|
||||
1.000000,
|
||||
1.000001
|
||||
],
|
||||
"min" : [
|
||||
-1.000000,
|
||||
-1.000000,
|
||||
-1.000000
|
||||
],
|
||||
"type" : "VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView" : 4,
|
||||
"byteOffset" : 0,
|
||||
"componentType" : 5126,
|
||||
"count" : 36,
|
||||
"max" : [
|
||||
1.000000,
|
||||
1.000000,
|
||||
1.000000
|
||||
],
|
||||
"min" : [
|
||||
-1.000000,
|
||||
-1.000000,
|
||||
-1.000000
|
||||
],
|
||||
"type" : "VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView" : 5,
|
||||
"byteOffset" : 0,
|
||||
"componentType" : 5126,
|
||||
"count" : 36,
|
||||
"max" : [
|
||||
1.000000,
|
||||
-0.000000,
|
||||
-0.000000,
|
||||
1.000000
|
||||
],
|
||||
"min" : [
|
||||
0.000000,
|
||||
-0.000000,
|
||||
-1.000000,
|
||||
-1.000000
|
||||
],
|
||||
"type" : "VEC4"
|
||||
},
|
||||
{
|
||||
"bufferView" : 6,
|
||||
"byteOffset" : 0,
|
||||
"componentType" : 5126,
|
||||
"count" : 36,
|
||||
"max" : [
|
||||
1.000000,
|
||||
1.000000
|
||||
],
|
||||
"min" : [
|
||||
-1.000000,
|
||||
-1.000000
|
||||
],
|
||||
"type" : "VEC2"
|
||||
}
|
||||
],
|
||||
"animations" : [
|
||||
{
|
||||
"channels" : [
|
||||
{
|
||||
"sampler" : 0,
|
||||
"target" : {
|
||||
"node" : 0,
|
||||
"path" : "rotation"
|
||||
}
|
||||
}
|
||||
],
|
||||
"name" : "animation_AnimatedCube",
|
||||
"samplers" : [
|
||||
{
|
||||
"input" : 0,
|
||||
"interpolation" : "LINEAR",
|
||||
"output" : 1
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"asset" : {
|
||||
"generator" : "VKTS glTF 2.0 exporter",
|
||||
"version" : "2.0"
|
||||
},
|
||||
"bufferViews" : [
|
||||
{
|
||||
"buffer" : 0,
|
||||
"byteLength" : 12,
|
||||
"byteOffset" : 0
|
||||
},
|
||||
{
|
||||
"buffer" : 0,
|
||||
"byteLength" : 48,
|
||||
"byteOffset" : 12
|
||||
},
|
||||
{
|
||||
"buffer" : 0,
|
||||
"byteLength" : 72,
|
||||
"byteOffset" : 60,
|
||||
"target" : 34963
|
||||
},
|
||||
{
|
||||
"buffer" : 0,
|
||||
"byteLength" : 432,
|
||||
"byteOffset" : 132,
|
||||
"target" : 34962
|
||||
},
|
||||
{
|
||||
"buffer" : 0,
|
||||
"byteLength" : 432,
|
||||
"byteOffset" : 564,
|
||||
"target" : 34962
|
||||
},
|
||||
{
|
||||
"buffer" : 0,
|
||||
"byteLength" : 576,
|
||||
"byteOffset" : 996,
|
||||
"target" : 34962
|
||||
},
|
||||
{
|
||||
"buffer" : 0,
|
||||
"byteLength" : 288,
|
||||
"byteOffset" : 1572,
|
||||
"target" : 34962
|
||||
}
|
||||
],
|
||||
"buffers" : [
|
||||
{
|
||||
"byteLength" : 1860,
|
||||
"uri" : "AnimatedCube.bin"
|
||||
}
|
||||
],
|
||||
"images" : [
|
||||
{
|
||||
"uri" : "AnimatedCube_BaseColor.png"
|
||||
},
|
||||
{
|
||||
"uri" : "AnimatedCube_MetallicRoughness.png"
|
||||
}
|
||||
],
|
||||
"materials" : [
|
||||
{
|
||||
"name" : "AnimatedCube",
|
||||
"pbrMetallicRoughness" : {
|
||||
"baseColorTexture" : {
|
||||
"index" : 0
|
||||
},
|
||||
"metallicRoughnessTexture" : {
|
||||
"index" : 1
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"meshes" : [
|
||||
{
|
||||
"name" : "AnimatedCube",
|
||||
"primitives" : [
|
||||
{
|
||||
"attributes" : {
|
||||
"NORMAL" : 4,
|
||||
"POSITION" : 3,
|
||||
"TANGENT" : 5,
|
||||
"TEXCOORD_0" : 6
|
||||
},
|
||||
"indices" : 2,
|
||||
"material" : 0,
|
||||
"mode" : 4
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"nodes" : [
|
||||
{
|
||||
"mesh" : 0,
|
||||
"name" : "AnimatedCube",
|
||||
"rotation" : [
|
||||
0.000000,
|
||||
-1.000000,
|
||||
0.000000,
|
||||
0.000000
|
||||
]
|
||||
}
|
||||
],
|
||||
"samplers" : [
|
||||
{}
|
||||
],
|
||||
"scene" : 0,
|
||||
"scenes" : [
|
||||
{
|
||||
"nodes" : [
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"textures" : [
|
||||
{
|
||||
"sampler" : 0,
|
||||
"source" : 0
|
||||
},
|
||||
{
|
||||
"sampler" : 0,
|
||||
"source" : 1
|
||||
}
|
||||
]
|
||||
}
|
||||
160
example/assets/AnimatedCube_NLA.gltf
Normal file
160
example/assets/AnimatedCube_NLA.gltf
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
{
|
||||
"asset":{
|
||||
"generator":"Khronos glTF Blender I/O v3.5.30",
|
||||
"version":"2.0"
|
||||
},
|
||||
"scene":0,
|
||||
"scenes":[
|
||||
{
|
||||
"name":"Scene",
|
||||
"nodes":[
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"nodes":[
|
||||
{
|
||||
"mesh":0,
|
||||
"name":"AnimatedCube"
|
||||
}
|
||||
],
|
||||
"animations":[
|
||||
{
|
||||
"channels":[
|
||||
{
|
||||
"sampler":0,
|
||||
"target":{
|
||||
"node":0,
|
||||
"path":"rotation"
|
||||
}
|
||||
}
|
||||
],
|
||||
"name":"walk",
|
||||
"samplers":[
|
||||
{
|
||||
"input":4,
|
||||
"interpolation":"LINEAR",
|
||||
"output":5
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"materials":[
|
||||
{
|
||||
"name":"AnimatedCube",
|
||||
"pbrMetallicRoughness":{}
|
||||
}
|
||||
],
|
||||
"meshes":[
|
||||
{
|
||||
"name":"AnimatedCube",
|
||||
"primitives":[
|
||||
{
|
||||
"attributes":{
|
||||
"POSITION":0,
|
||||
"TEXCOORD_0":1,
|
||||
"NORMAL":2
|
||||
},
|
||||
"indices":3,
|
||||
"material":0
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"accessors":[
|
||||
{
|
||||
"bufferView":0,
|
||||
"componentType":5126,
|
||||
"count":36,
|
||||
"max":[
|
||||
1,
|
||||
1,
|
||||
1.0000009536743164
|
||||
],
|
||||
"min":[
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
],
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":1,
|
||||
"componentType":5126,
|
||||
"count":36,
|
||||
"type":"VEC2"
|
||||
},
|
||||
{
|
||||
"bufferView":2,
|
||||
"componentType":5126,
|
||||
"count":36,
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":3,
|
||||
"componentType":5123,
|
||||
"count":36,
|
||||
"type":"SCALAR"
|
||||
},
|
||||
{
|
||||
"bufferView":4,
|
||||
"componentType":5126,
|
||||
"count":3,
|
||||
"max":[
|
||||
2
|
||||
],
|
||||
"min":[
|
||||
0
|
||||
],
|
||||
"type":"SCALAR"
|
||||
},
|
||||
{
|
||||
"bufferView":5,
|
||||
"componentType":5126,
|
||||
"count":3,
|
||||
"type":"VEC4"
|
||||
}
|
||||
],
|
||||
"bufferViews":[
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":432,
|
||||
"byteOffset":0,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":288,
|
||||
"byteOffset":432,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":432,
|
||||
"byteOffset":720,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":72,
|
||||
"byteOffset":1152,
|
||||
"target":34963
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":12,
|
||||
"byteOffset":1224
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":48,
|
||||
"byteOffset":1236
|
||||
}
|
||||
],
|
||||
"buffers":[
|
||||
{
|
||||
"byteLength":1284,
|
||||
"uri":"data:application/octet-stream;base64,AACAPwAAgL8AAIA/AACAvwAAgL8AAIC/AACAPwAAgL8AAIC/AACAvwAAgD8AAIC/7/9/PwAAgD8IAIA/AACAPwAAgD/v/3+/AACAPwAAgD/v/3+/AACAPwAAgL8AAIA/AACAPwAAgL8AAIC/7/9/PwAAgD8IAIA/AACAvwAAgL8AAIA/AACAPwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAPwAAgL8AAIC/AACAvwAAgD8AAIC/AACAPwAAgD/v/3+/AACAPwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIA/7/9/PwAAgD8IAIA/AACAPwAAgD/v/3+/7/9/PwAAgD8IAIA/AACAPwAAgL8AAIA/7/9/PwAAgD8IAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIC/AACAPwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AAAAAAAAAAAAAIC/AACAPwAAAAAAAIA/AAAAAAAAAAAAAIA/AACAvwAAgD8AAAAAAACAPwAAAAAAAAAAAACAvwAAgD8AAIC/AACAPwAAAAAAAACAAACAvwAAgD8AAIC/AAAAAAAAAAAAAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAIC/AACAPwAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAgL8AAIA/AAAAAAAAAAAAAACAAACAvwAAgD8AAIC/AACAPwAAAAAAAACAAAAAAAAAAAAAAIC/AACAPwAAAAAAAACAAAAAAAAAAIAAAIC/AAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AAAAAAAAAAAAAIC/AAAAAAAAgL8AAIA/AAAAAAAAgL8AAACAAAAAAAAAgL8AAACAAAAAAAAAgL8AAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAACAPwAAAAAAAACAAACAPwAAAAAAAACAAACAPwAAAAAAAACAAAAAAAAAAIAAAIA/AAAAAAAAAIAAAIA/AAAAAAAAAIAAAIA/AACAvwAAAAAAAACAAACAvwAAAAAAAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAgL8AAACAAAAAAAAAgL8AAACAAAAAAAAAgL8AAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AACAvwAAAAAAAACAAACAvwAAAAAAAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAAAAAAAAAgD8AAABAAAAAAAAAAAAAAACAAACAPwAAAIAAAIC/AAAAAC69OzMAAAAALr27MwAAAIAAAIA/"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ input[type="submit"] {
|
|||
}
|
||||
|
||||
#overlay{
|
||||
background: #FFF;
|
||||
background: #FFFb;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
|
@ -130,6 +130,7 @@ a#model{
|
|||
}
|
||||
|
||||
html.a-fullscreen a.btn-foot {
|
||||
line-height:36px;
|
||||
margin-right:10px;
|
||||
}
|
||||
|
||||
|
|
|
|||
BIN
example/assets/index.fbx
Normal file
BIN
example/assets/index.fbx
Normal file
Binary file not shown.
BIN
example/assets/index.glb
Normal file
BIN
example/assets/index.glb
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
164
example/assets/index.mtl
Normal file
164
example/assets/index.mtl
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
# Blender MTL File: 'None'
|
||||
# Material Count: 16
|
||||
|
||||
newmtl None
|
||||
Ns 500
|
||||
Ka 0.8 0.8 0.8
|
||||
Kd 0.8 0.8 0.8
|
||||
Ks 0.8 0.8 0.8
|
||||
d 1
|
||||
illum 2
|
||||
|
||||
newmtl environmentMap.002
|
||||
Ns 359.999993
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.800000 0.800000 0.800000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
|
||||
newmtl environmentMap.004
|
||||
Ns 359.999993
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.800000 0.800000 0.800000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
|
||||
newmtl floorstone.003
|
||||
Ns 349.173522
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.370787 0.337474 0.425554
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 3
|
||||
map_Ke .
|
||||
|
||||
newmtl floorstone.004
|
||||
Ns 349.173522
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.370787 0.337474 0.425554
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 3
|
||||
map_Ke .
|
||||
|
||||
newmtl glass.002
|
||||
Ns 1000.000000
|
||||
Ka 0.963543 0.963543 0.963543
|
||||
Kd 1.000000 1.000000 1.000000
|
||||
Ks 0.234677 0.234677 0.234677
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.450000
|
||||
d 0.143627
|
||||
illum 6
|
||||
|
||||
newmtl hotspot
|
||||
Ns 359.999993
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.800000 0.800000 0.800000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
|
||||
newmtl placeholder.003
|
||||
Ns 854.195174
|
||||
Ka 0.886364 0.886364 0.886364
|
||||
Kd 1.000000 1.000000 1.000000
|
||||
Ks 0.327273 0.327273 0.327273
|
||||
Ke 0.113646 0.000000 35.199997
|
||||
Ni 1.450000
|
||||
d 0.159091
|
||||
illum 6
|
||||
|
||||
newmtl placeholder.004
|
||||
Ns 854.195174
|
||||
Ka 0.886364 0.886364 0.886364
|
||||
Kd 1.000000 1.000000 1.000000
|
||||
Ks 0.327273 0.327273 0.327273
|
||||
Ke 0.000000 0.330810 35.199997
|
||||
Ni 1.450000
|
||||
d 0.159091
|
||||
illum 6
|
||||
|
||||
newmtl portal_bg.004
|
||||
Ns 0.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.000000 0.000000 0.000000
|
||||
Ks 0.068182 0.068182 0.068182
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 0.222727
|
||||
illum 6
|
||||
|
||||
newmtl portal_bg.005
|
||||
Ns 0.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.000000 0.000000 0.000000
|
||||
Ks 0.068182 0.068182 0.068182
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 0.222727
|
||||
illum 6
|
||||
|
||||
newmtl portal_bg.006
|
||||
Ns 0.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.000000 0.000000 0.000000
|
||||
Ks 0.068182 0.068182 0.068182
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 0.222727
|
||||
illum 6
|
||||
|
||||
newmtl text.004
|
||||
Ns 854.195174
|
||||
Ka 0.886364 0.886364 0.886364
|
||||
Kd 1.000000 1.000000 1.000000
|
||||
Ks 0.327273 0.327273 0.327273
|
||||
Ke 1.000000 1.000000 1.000000
|
||||
Ni 1.450000
|
||||
d 1.000000
|
||||
illum 3
|
||||
|
||||
newmtl text.005
|
||||
Ns 0.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.080782 0.080782 0.080782
|
||||
Ks 0.068182 0.068182 0.068182
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 3
|
||||
|
||||
newmtl text.006
|
||||
Ns 854.195174
|
||||
Ka 0.886364 0.886364 0.886364
|
||||
Kd 0.518619 0.518619 0.518619
|
||||
Ks 0.327273 0.327273 0.327273
|
||||
Ke 1.000000 1.000000 1.000000
|
||||
Ni 1.450000
|
||||
d 1.000000
|
||||
illum 3
|
||||
|
||||
newmtl vaporgradient.002
|
||||
Ns 951.107117
|
||||
Ka 0.827273 0.827273 0.827273
|
||||
Kd 0.800000 0.800000 0.800000
|
||||
Ks 0.327273 0.327273 0.327273
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.450000
|
||||
d 1.000000
|
||||
illum 3
|
||||
map_Kd .
|
||||
map_Ke .
|
||||
194201
example/assets/index.obj
Normal file
194201
example/assets/index.obj
Normal file
File diff suppressed because it is too large
Load diff
70
example/assets/index.py
Normal file
70
example/assets/index.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#
|
||||
# This is a convenient way to convert the scene to lowpoly
|
||||
# (by adding decimate-modifiers)
|
||||
# and then exporting a gltf to to <blenderdocument>.glb
|
||||
#
|
||||
# All this is done automatically when saving the blender file
|
||||
#
|
||||
import bpy
|
||||
import os
|
||||
from bpy_extras.io_utils import ImportHelper
|
||||
|
||||
# uncomment below in case you want to hardcode the exported filename
|
||||
data = {
|
||||
#gltf_file="/some/path/foo.index.glb"
|
||||
}
|
||||
|
||||
def notify(message = "", title = "Message Box", icon = 'INFO'):
|
||||
def draw(self, context):
|
||||
self.layout.label(text=message)
|
||||
bpy.context.window_manager.popup_menu(draw, title = title, icon = icon)
|
||||
|
||||
# redirect print to all consoles
|
||||
def print(data):
|
||||
for window in bpy.context.window_manager.windows:
|
||||
screen = window.screen
|
||||
for area in screen.areas:
|
||||
if area.type == 'CONSOLE':
|
||||
override = {'window': window, 'screen': screen, 'area': area}
|
||||
bpy.ops.console.scrollback_append(override, text=str(data), type="OUTPUT")
|
||||
|
||||
|
||||
# Function to add Decimate Modifier to objects without one (except those in the exclusion list)
|
||||
def add_decimate_modifier_to_objects():
|
||||
for obj in bpy.data.objects:
|
||||
print(obj.type)
|
||||
if obj is not None and (obj.type == 'FONT' or (obj.type == 'MESH' and len(obj.data.polygons) > 8)):
|
||||
if not obj.modifiers.get("Decimate"):
|
||||
#if obj.name not in exclusion_list and "Decimate" not in obj.modifiers:
|
||||
print("adding decimate-modifier to:"+obj.name)
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
bpy.data.objects[obj.name].select_set(True)
|
||||
|
||||
# Add Decimate Modifier with ratio 0.5
|
||||
bpy.ops.object.modifier_add(type='DECIMATE')
|
||||
bpy.context.object.modifiers["Decimate"].ratio = 0.5
|
||||
|
||||
# Function to be called on file save
|
||||
def on_save_handler(blenderdoc):
|
||||
if 'gltf_file' not in data:
|
||||
gltf_file = bpy.data.filepath.replace('.blend','.glb')
|
||||
else:
|
||||
gltf_file = data['gltf_file']
|
||||
|
||||
add_decimate_modifier_to_objects()
|
||||
|
||||
# Export to glTF with specified settings and apply modifiers
|
||||
bpy.ops.export_scene.gltf(
|
||||
filepath=gltf_file,
|
||||
export_format='GLB',
|
||||
export_extras=True,
|
||||
export_lights=True,
|
||||
export_apply=True,
|
||||
export_force_sampling=False,
|
||||
)
|
||||
notify(os.path.basename(gltf_file),"OK export")
|
||||
|
||||
# Register the handler
|
||||
bpy.app.handlers.save_post.clear()
|
||||
bpy.app.handlers.save_post.append(on_save_handler)
|
||||
print("sourced gltf_export_on_save")
|
||||
|
|
@ -267,7 +267,7 @@ export function notify(scope){
|
|||
if( str.match(/error/g) ) opts.status = "danger"
|
||||
if( str.match(/warning/g) ) opts.status = "warning"
|
||||
}
|
||||
opts = Object.assign({ message: str , status, timeout:2000 },opts)
|
||||
opts = Object.assign({ message: str , status, timeout:4000 },opts)
|
||||
SnackBar( opts )
|
||||
}
|
||||
}
|
||||
|
|
@ -285,12 +285,25 @@ export function download(){
|
|||
}
|
||||
|
||||
export function embed(){
|
||||
// *TODO* this should be part of the XRF framework
|
||||
let camera = document.querySelector('[camera]').object3D.parent // *TODO* fix for threejs
|
||||
// *TODO* this should be part of the XRF Threejs framework
|
||||
if( typeof THREE == 'undefined' ) THREE = xrf.THREE
|
||||
let radToDeg = THREE.MathUtils.radToDeg
|
||||
let toDeg = (x) => x / (Math.PI / 180)
|
||||
let camera = document.querySelector('[camera]').object3D.parent // *TODO* fix for threejs
|
||||
|
||||
// *TODO* add camera direction
|
||||
let direction = new xrf.THREE.Vector3()
|
||||
camera.getWorldDirection(direction)
|
||||
const pitch = Math.asin(direction.y);
|
||||
const yaw = Math.atan2(direction.x, direction.z);
|
||||
const pitchInDegrees = pitch * 180 / Math.PI;
|
||||
const yawInDegrees = yaw * 180 / Math.PI;
|
||||
|
||||
let lastPos = `pos=${camera.position.x.toFixed(2)},${camera.position.y.toFixed(2)},${camera.position.z.toFixed(2)}`
|
||||
let newHash = document.location.hash.replace(/[&]?pos=[0-9\.-]+,[0-9\.-]+,[0-9\.-]+/,'')
|
||||
let newHash = document.location.hash.replace(/[&]?(pos|rot)=[0-9\.-]+,[0-9\.-]+,[0-9\.-]+/,'')
|
||||
newHash += `&${lastPos}`
|
||||
document.location.hash = newHash.replace(/&&/,'&')
|
||||
.replace(/#&/,'')
|
||||
// copy url to clipboard
|
||||
var dummy = document.createElement('input'),
|
||||
text = window.location.href;
|
||||
|
|
|
|||
BIN
example/assets/podcast.mp3
Normal file
BIN
example/assets/podcast.mp3
Normal file
Binary file not shown.
BIN
example/assets/test.mp3
Normal file
BIN
example/assets/test.mp3
Normal file
Binary file not shown.
BIN
example/assets/test.ogg
Normal file
BIN
example/assets/test.ogg
Normal file
Binary file not shown.
86
index.html
86
index.html
File diff suppressed because one or more lines are too long
80
make
80
make
|
|
@ -2,6 +2,7 @@
|
|||
set -e
|
||||
|
||||
try(){ set +e; "$@" 2>/dev/null; set -e; }
|
||||
trace(){ set -x; "$@"; set +x; }
|
||||
|
||||
install(){
|
||||
which haxe || {
|
||||
|
|
@ -26,8 +27,8 @@ install(){
|
|||
|
||||
tests(){
|
||||
{
|
||||
which python3 && python3 test/generated/test.py src/spec/*.json | awk '{ print "py: "$0 } END{ print "\n"}'
|
||||
which node && node test/generated/test.js src/spec/*.json | awk '{ print "js: "$0 } END{ print "\n"}'
|
||||
which python3 && python3 test/generated/test.py src/spec/*.json | awk '{ print "py: "$0 } END{ print "\n"}'
|
||||
} | awk '$2 ~ /src/ { $2=sprintf("%-30s",$2); print $0; next; } 1' | tee /tmp/log.txt
|
||||
grep error /tmp/log.txt && exit 1 || exit 0
|
||||
}
|
||||
|
|
@ -51,36 +52,55 @@ server(){
|
|||
}
|
||||
|
||||
build(){
|
||||
try rm dist/*
|
||||
haxe build.hxml
|
||||
ok=$?
|
||||
sed -i 's|.*nonlocal .*||g' dist/xrfragment.py
|
||||
echo build OK
|
||||
build_js
|
||||
}
|
||||
|
||||
build_js(){
|
||||
# prepend license to vanilla lib
|
||||
#echo "// https://xrfragment.org\n// SPDX-License-Identifier: MPL-2.0\n$(cat dist/xrfragment.js)" > dist/xrfragment.js
|
||||
# add js module
|
||||
cat dist/xrfragment.js > dist/xrfragment.module.js
|
||||
echo "export default xrfragment;" >> dist/xrfragment.module.js
|
||||
# add THREE
|
||||
cat dist/xrfragment.js \
|
||||
src/3rd/js/*.js \
|
||||
src/3rd/js/three/*.js \
|
||||
src/3rd/js/three/xrmacro/*.js \
|
||||
src/3rd/js/three/xrf/*.js > dist/xrfragment.three.js
|
||||
# add THREE module
|
||||
cat dist/xrfragment.three.js > dist/xrfragment.three.module.js
|
||||
echo "export default xrf;" >> dist/xrfragment.three.module.js
|
||||
# add AFRAME
|
||||
cat dist/xrfragment.three.js \
|
||||
src/3rd/js/aframe/*.js > dist/xrfragment.aframe.js
|
||||
# convert ESM to normal browser js
|
||||
sed 's/export //g' example/assets/js/utils.js > dist/utils.js
|
||||
ls -la dist | grep js
|
||||
exit $ok
|
||||
parser(){
|
||||
try rm dist/*
|
||||
haxe build.hxml || exit 1
|
||||
sed -i 's|.*nonlocal .*||g' dist/xrfragment.py
|
||||
ls -lah dist/*
|
||||
echo -e "[OK] parser build\n"
|
||||
return $ok
|
||||
}
|
||||
|
||||
js(){
|
||||
# add js module
|
||||
cat dist/xrfragment.js >> dist/xrfragment.module.js
|
||||
echo "export default xrfragment;" >> dist/xrfragment.module.js
|
||||
# add THREE
|
||||
cat dist/xrfragment.js \
|
||||
src/3rd/js/*.js \
|
||||
src/3rd/js/three/*.js \
|
||||
src/3rd/js/three/xrmacro/env.js \
|
||||
src/3rd/js/three/xrf/*.js \
|
||||
src/3rd/js/three/util/*.js \
|
||||
src/3rd/js/three/xrf/dynamic/*.js \
|
||||
src/3rd/js/three/xrf/src/*.js > dist/xrfragment.three.js
|
||||
# add THREE module
|
||||
cat dist/xrfragment.three.js > dist/xrfragment.three.module.js
|
||||
echo "export default xrf;" >> dist/xrfragment.three.module.js
|
||||
# add AFRAME
|
||||
cat dist/xrfragment.three.js \
|
||||
src/3rd/js/aframe/*.js > dist/xrfragment.aframe.js
|
||||
# convert ESM to normal browser js
|
||||
sed 's/export //g' example/assets/js/utils.js > dist/utils.js
|
||||
# add license headers
|
||||
for file in dist/xrfragment.{aframe,module,three,three.module}.js; do
|
||||
awk 'BEGIN{
|
||||
print "/*"
|
||||
print " * generated at $(date)"
|
||||
print " * https://xrfragment.org"
|
||||
print " * SPDX-License-Identifier: MPL-2.0"
|
||||
print " */"
|
||||
system("cat '$file'")
|
||||
}' > /tmp/tmp.js
|
||||
mv /tmp/tmp.js $file
|
||||
done
|
||||
ls -la dist | grep js
|
||||
return $ok
|
||||
}
|
||||
|
||||
test -z $1 && { parser && js; }
|
||||
test -z $1 || "$@"
|
||||
}
|
||||
|
||||
test -z $1 && build
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
# nativeBuildInputs is usually what you want -- tools you need to run
|
||||
nativeBuildInputs = with pkgs.buildPackages; [
|
||||
|
||||
nodejs
|
||||
haxe
|
||||
mmark
|
||||
xml2rfc
|
||||
|
||||
|
|
|
|||
|
|
@ -12,18 +12,19 @@ XRWG.cleankey = (word) => String(word).replace(/[^0-9\.a-zA-Z_]/g,'')
|
|||
XRWG.get = (v,k) => XRWG.find( (x) => x[ k || 'word'] == v )
|
||||
|
||||
XRWG.match = (str,types,level) => {
|
||||
level = level || 1000
|
||||
if( XRWG.length == 0 ) XRWG.generate(xrf)
|
||||
level = level == undefined ? 1000 : level
|
||||
types = types || []
|
||||
let res = XRWG.filter( (n) => {
|
||||
types.map( (type) => n[type] ? n = false : false )
|
||||
return n
|
||||
})
|
||||
str = str.toLowerCase()
|
||||
if( level <10 ) res = res.filter( (n) => n.key == str )
|
||||
if( level <20 ) res = res.filter( (n) => n.word == str || n.key == str )
|
||||
if( level <30 ) res = res.filter( (n) => n.word.match(str) || n.key == str )
|
||||
if( level <40 ) res = res.filter( (n) => n.word.match(str) || n.key == str || String(n.value||'').match(str) )
|
||||
if( level <1001 ) res = res.filter( (n) => n.word.match(str) != null || n.key.match(str) != null || String(n.value||'').match(str) != null)
|
||||
if( level <10 ) res = res.filter( (n) => n.key == str )
|
||||
if( level >=10 ) res = res.filter( (n) => n.word == str || n.key == str )
|
||||
if( level >30 ) res = res.filter( (n) => n.word.match(str) || n.key == str )
|
||||
if( level >40 ) res = res.filter( (n) => n.word.match(str) || n.key == str || String(n.value||'').match(str) )
|
||||
if( level >999 ) res = res.filter( (n) => n.word.match(str) != null || n.key.match(str) != null || String(n.value||'').match(str) != null)
|
||||
return res
|
||||
}
|
||||
|
||||
|
|
@ -42,7 +43,7 @@ XRWG.generate = (opts) => {
|
|||
node = { word: XRWG.cleankey(key), key, nodes:[spatialNode] }
|
||||
if( spatialNode.userData[key] ) node.value = spatialNode.userData[key]
|
||||
node[type] = true
|
||||
xrf.emit('XRWG',node)
|
||||
xrf.emit('XRWGnode',node)
|
||||
XRWG.push( node )
|
||||
}
|
||||
}
|
||||
|
|
@ -64,5 +65,5 @@ XRWG.generate = (opts) => {
|
|||
// sort by n
|
||||
XRWG.sort( (a,b) => a.nodes.length - b.nodes.length )
|
||||
XRWG = XRWG.reverse() // the cleankey/get functions e.g. will persist
|
||||
console.dir(XRWG)
|
||||
xrf.emit('XRWG',XRWG)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,15 @@ window.AFRAME.registerComponent('xrf', {
|
|||
},
|
||||
init: function () {
|
||||
if( !AFRAME.XRF ){
|
||||
document.querySelector('a-scene').addEventListener('loaded', () => {
|
||||
|
||||
//window.addEventListener('popstate', clear )
|
||||
//window.addEventListener('pushstate', clear )
|
||||
let camera = document.querySelector('[camera]')
|
||||
// start with black
|
||||
camera.setAttribute('xrf-fade','')
|
||||
AFRAME.fade = camera.components['xrf-fade']
|
||||
|
||||
if( document.location.host.match(/localhost/) ) document.querySelector('a-scene').setAttribute("stats",'')
|
||||
|
||||
document.querySelector('a-scene').addEventListener('loaded', () => {
|
||||
|
||||
// enable XR fragments
|
||||
let aScene = document.querySelector('a-scene')
|
||||
|
|
@ -15,7 +20,6 @@ window.AFRAME.registerComponent('xrf', {
|
|||
camera: aScene.camera,
|
||||
scene: aScene.object3D,
|
||||
renderer: aScene.renderer,
|
||||
debug: true,
|
||||
loaders: {
|
||||
gltf: THREE.GLTFLoader, // which 3D assets (exts) to check for XR fragments?
|
||||
glb: THREE.GLTFLoader
|
||||
|
|
@ -23,26 +27,83 @@ window.AFRAME.registerComponent('xrf', {
|
|||
})
|
||||
if( !XRF.camera ) throw 'xrfragment: no camera detected, please declare <a-entity camera..> ABOVE entities with xrf-attributes'
|
||||
|
||||
// override the camera-related XR Fragments so the camera-rig is affected
|
||||
let camOverride = (xrf,v,opts) => {
|
||||
opts.camera = document.querySelector('[camera]').object3D.parent
|
||||
xrf(v,opts)
|
||||
}
|
||||
xrf.addEventListener('navigateLoaded', () => {
|
||||
setTimeout( () => AFRAME.fade.out(),500)
|
||||
|
||||
xrf.pos = camOverride
|
||||
xrf.href = camOverride
|
||||
// *TODO* this does not really belong here perhaps
|
||||
let blinkControls = document.querySelector('[blink-controls]')
|
||||
if( blinkControls ){
|
||||
let els = xrf.getCollisionMeshes()
|
||||
let invisible = false
|
||||
els.map( (mesh) => {
|
||||
if( !invisible ){
|
||||
invisible = mesh.material.clone()
|
||||
invisible.visible = false
|
||||
}
|
||||
mesh.material = invisible
|
||||
let el = document.createElement("a-entity")
|
||||
el.setAttribute("xrf-get", mesh.name )
|
||||
el.setAttribute("class","floor")
|
||||
$('a-scene').appendChild(el)
|
||||
})
|
||||
blinkControls.components['blink-controls'].update({collisionEntities:true})
|
||||
}
|
||||
})
|
||||
|
||||
// in order to set the rotation programmatically
|
||||
// we need to disable look-controls
|
||||
xrf.rot = (xrf,v,opts) => {
|
||||
let {frag,renderer} = opts;
|
||||
if( frag.q ) return // camera was not targeted for rotation
|
||||
let look = document.querySelector('[look-controls]')
|
||||
if( look ) look.removeAttribute("look-controls")
|
||||
// camOverride(xrf,v,opts)
|
||||
// *TODO* make look-controls compatible, because simply
|
||||
// adding the look-controls will revert to the old rotation (cached somehow?)
|
||||
//setTimeout( () => look.setAttribute("look-controls",""), 100 )
|
||||
xrf.addEventListener('href', (opts) => {
|
||||
if( opts.click){
|
||||
let p = opts.promise()
|
||||
let url = opts.xrf.string
|
||||
let isLocal = url.match(/^#/)
|
||||
let hasPos = url.match(/pos=/)
|
||||
if( isLocal && hasPos ){
|
||||
// local teleports only
|
||||
let fastFadeMs = 200
|
||||
AFRAME.fade.in(fastFadeMs)
|
||||
setTimeout( () => {
|
||||
p.resolve()
|
||||
AFRAME.fade.out(fastFadeMs)
|
||||
}, fastFadeMs)
|
||||
}else if( !isLocal ){
|
||||
AFRAME.fade.in()
|
||||
setTimeout( () => {
|
||||
p.resolve()
|
||||
setTimeout( () => AFRAME.fade.out(), 1000 ) // allow one second to load textures e.g.
|
||||
}, AFRAME.fade.data.fadetime )
|
||||
}else p.resolve()
|
||||
}
|
||||
})
|
||||
|
||||
// patch wasd-controls to affect camera-rig
|
||||
if( camera.components['wasd-controls'] ){
|
||||
camera.components['wasd-controls'].tick = function(time,delta){
|
||||
var data = this.data;
|
||||
var el = this.el;
|
||||
var velocity = this.velocity;
|
||||
function isEmptyObject(keys) {
|
||||
var key;
|
||||
for (key in keys) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!velocity[data.adAxis] && !velocity[data.wsAxis] &&
|
||||
isEmptyObject(this.keys)) { return; }
|
||||
|
||||
// Update velocity.
|
||||
delta = delta / 1000;
|
||||
this.updateVelocity(delta);
|
||||
|
||||
if (!velocity[data.adAxis] && !velocity[data.wsAxis]) { return; }
|
||||
|
||||
|
||||
// Transform direction relative to heading.
|
||||
let directionVector = this.getMovementVector(delta)
|
||||
var rotationEuler = new THREE.Euler(0, 0, 0, 'YXZ');
|
||||
rotationEuler.set(THREE.MathUtils.degToRad(0), THREE.MathUtils.degToRad(xrf.camera.rotation.y + 45), 0);
|
||||
directionVector.applyEuler(rotationEuler);
|
||||
// Get movement vector and translate position to camera-rig (not camera)
|
||||
xrf.camera.position.add(directionVector);
|
||||
}.bind( camera.components['wasd-controls'] )
|
||||
}
|
||||
|
||||
// convert href's to a-entity's so AFRAME
|
||||
|
|
@ -53,30 +114,20 @@ window.AFRAME.registerComponent('xrf', {
|
|||
el.setAttribute("xrf-get",mesh.name ) // turn into AFRAME entity
|
||||
el.setAttribute("class","ray") // expose to raycaster
|
||||
el.setAttribute("pressable", '') // detect hand-controller click
|
||||
// add click
|
||||
// respond to cursor via laser-controls (https://aframe.io/docs/1.4.0/components/laser-controls.html)
|
||||
el.addEventListener("click", clickHandler )
|
||||
el.addEventListener("mouseenter", mesh.userData.XRF.href.selected(true) )
|
||||
el.addEventListener("mouseleave", mesh.userData.XRF.href.selected(false) )
|
||||
el.addEventListener("pressedstarted", clickHandler )
|
||||
// this.el.addEventListener("buttondown", console.dir )
|
||||
// this.el.addEventListener("touchstart", console.dir )
|
||||
// this.el.addEventListener("triggerdown", console.dir )
|
||||
// this.el.addEventListener("gripdown", console.dir )
|
||||
// this.el.addEventListener("abuttondown", console.dir )
|
||||
// this.el.addEventListener("pinchended", console.dir )
|
||||
|
||||
$('a-scene').appendChild(el)
|
||||
}
|
||||
xrf.addEventListener('interactionReady', AFRAME.XRF.clickableMeshToEntity )
|
||||
|
||||
// cleanup xrf-get objects when resetting scene
|
||||
xrf.reset = ((reset) => () => {
|
||||
reset()
|
||||
console.log("aframe reset")
|
||||
xrf.addEventListener('reset', (opts) => {
|
||||
let els = [...document.querySelectorAll('[xrf-get]')]
|
||||
els.map( (el) => document.querySelector('a-scene').removeChild(el) )
|
||||
})(XRF.reset)
|
||||
|
||||
// undo lookup-control shenanigans (which blocks updating camerarig position in VR)
|
||||
aScene.addEventListener('enter-vr', () => document.querySelector('[camera]').object3D.parent.matrixAutoUpdate = true )
|
||||
})
|
||||
|
||||
AFRAME.XRF.navigator.to(this.data)
|
||||
.then( (model) => {
|
||||
|
|
|
|||
27
src/3rd/js/aframe/xrf-fade.js
Normal file
27
src/3rd/js/aframe/xrf-fade.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
AFRAME.registerComponent('xrf-fade', {
|
||||
schema:{
|
||||
fadetime:{type:"number", default: 1000},
|
||||
color:{type:"color", default:"black"},
|
||||
opacity:{type:"float",default:1.0}
|
||||
},
|
||||
init: function(){
|
||||
let fb = this.fb = document.createElement("a-box")
|
||||
fb.setAttribute("scale", "1 1 1")
|
||||
fb.setAttribute("material", `color: ${this.data.color}; transparent: true; side: back; shader: flat; opacity:1`)
|
||||
this.el.appendChild(fb)
|
||||
},
|
||||
out: function(fadetime){
|
||||
if( fadetime != undefined ) this.data.fadetime = fadetime
|
||||
if( this.data.opacity == 0 ) return
|
||||
this.data.opacity = 0.0
|
||||
this.fb.setAttribute("animation", `property: components.material.material.opacity; dur: ${this.data.fadetime}; from: 1; to: ${this.data.opacity}`)
|
||||
setTimeout( () => this.fb.object3D.visible = false, this.data.fadetime )
|
||||
},
|
||||
"in": function(fadetime){
|
||||
if( fadetime != undefined ) this.data.fadetime = fadetime
|
||||
if( this.data.opacity == 1 ) return
|
||||
this.data.opacity = 1.0
|
||||
this.fb.object3D.visible = true
|
||||
this.fb.setAttribute("animation", `property: components.material.material.opacity; dur: ${this.data.fadetime}; from: 0; to: ${this.data.opacity}`)
|
||||
}
|
||||
});
|
||||
|
|
@ -26,25 +26,29 @@ AFRAME.registerComponent('xrf-gaze',{
|
|||
init:function(data){
|
||||
this.immersive = false;
|
||||
let enabled = () => AFRAME.utils.device.isMobile()
|
||||
let setVisible = () => document.querySelector('[cursor]').setAttribute('visible', enabled() )
|
||||
let setVisible = () => {
|
||||
let cursor = document.querySelector('[cursor]')
|
||||
if( cursor ) cursor.setAttribute('visible', enabled() )
|
||||
}
|
||||
|
||||
this.setGazer(enabled())
|
||||
if( enabled() ) setVisible();
|
||||
setVisible();
|
||||
|
||||
document.querySelector("a-scene").addEventListener('exit-vr', () => {
|
||||
this.immersive = false;
|
||||
setVisible()
|
||||
})
|
||||
|
||||
document.querySelector("a-scene").addEventListener('enter-vr', () => {
|
||||
this.immersive = true;
|
||||
setVisible()
|
||||
if( !document.querySelector("#cursor") ) return
|
||||
})
|
||||
|
||||
|
||||
let highlightMesh = (state) => (e) => {
|
||||
if( !e.target.object3D ) return
|
||||
let obj = e.target.object3D.children[0]
|
||||
if( obj.userData && obj.userData.XRF && obj.userData.XRF.href )
|
||||
if( obj && obj.userData && obj.userData.XRF && obj.userData.XRF.href )
|
||||
obj.userData.XRF.href.selected( state )()
|
||||
}
|
||||
this.el.addEventListener("mouseenter", highlightMesh(true) )
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
window.AFRAME.registerComponent('xrf-get', {
|
||||
schema: {
|
||||
name: {type: 'string'},
|
||||
clone: {type: 'boolean', default:false}
|
||||
clone: {type: 'boolean', default:false},
|
||||
reparent: {type: 'boolean', default:false}
|
||||
},
|
||||
|
||||
init: function () {
|
||||
|
|
@ -13,30 +14,40 @@ window.AFRAME.registerComponent('xrf-get', {
|
|||
|
||||
setTimeout( () => {
|
||||
|
||||
if( !this.mesh && this.el.className == "ray" ){
|
||||
if( !this.mesh ){
|
||||
let scene = AFRAME.XRF.scene
|
||||
let mesh = this.mesh = scene.getObjectByName(meshname);
|
||||
if( !this.el.className.match(/ray/) ) this.el.className += " ray"
|
||||
if (!mesh){
|
||||
console.error("mesh with name '"+meshname+"' not found in model")
|
||||
return;
|
||||
}
|
||||
// convert to worldcoordinates
|
||||
mesh.getWorldPosition(mesh.position)
|
||||
mesh.getWorldScale(mesh.scale)
|
||||
mesh.getWorldQuaternion(mesh.quaternion)
|
||||
// we don't want to re-parent gltf-meshes
|
||||
mesh.isXRF = true // mark for deletion by xrf
|
||||
if( this.data.reparent ){
|
||||
const world = {
|
||||
pos: new THREE.Vector3(),
|
||||
scale: new THREE.Vector3(),
|
||||
quat: new THREE.Quaternion()
|
||||
}
|
||||
mesh.getWorldPosition(world.pos)
|
||||
mesh.getWorldScale(world.scale)
|
||||
mesh.getWorldQuaternion(world.quat);
|
||||
mesh.position.copy(world.pos)
|
||||
mesh.scale.copy(world.scale)
|
||||
mesh.setRotationFromQuaternion(world.quat);
|
||||
}else{
|
||||
// add() will reparent the mesh so lets create a dummy
|
||||
this.el.object3D.add = (a) => a
|
||||
}
|
||||
this.el.setObject3D('mesh',mesh)
|
||||
// normalize position
|
||||
//this.el.object3D.position.copy( mesh.position )
|
||||
//mesh.position.fromArray([0,0,0])
|
||||
if( !this.el.id ) this.el.setAttribute("id",`xrf-${mesh.name}`)
|
||||
|
||||
}
|
||||
},500)
|
||||
}else console.warn("xrf-get ignore: "+JSON.stringify(this.data))
|
||||
}, evt && evt.timeout ? evt.timeout: 500)
|
||||
|
||||
})
|
||||
|
||||
this.el.emit("update")
|
||||
this.el.emit("update",{timeout:0})
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@
|
|||
var xrf = {}
|
||||
|
||||
xrf.init = function(opts){
|
||||
opts = opts || {}
|
||||
opts = opts || {}
|
||||
xrf.debug = parseInt( ( document.location.hash.match(/debug=([0-9])/) || [0,'0'] )[1] )
|
||||
xrf.Parser.debug = xrf.debug
|
||||
xrf.detectCameraRig(opts)
|
||||
for ( let i in opts ) xrf[i] = opts[i]
|
||||
xrf.emit('init',opts)
|
||||
return xrf
|
||||
|
|
@ -16,6 +18,20 @@ xrf.query = function(){
|
|||
alert("queries are not implemented (yet) for this particular framework")
|
||||
}
|
||||
|
||||
xrf.detectCameraRig = function(opts){
|
||||
if( opts.camera ){ // detect rig (if any)
|
||||
let getCam = ((cam) => () => cam)(opts.camera)
|
||||
let offsetY = 0
|
||||
while( opts.camera.parent.type != "Scene" ){
|
||||
offsetY += opts.camera.position.y
|
||||
opts.camera = opts.camera.parent
|
||||
opts.camera.getCam = getCam
|
||||
opts.camera.updateProjectionMatrix = () => opts.camera.getCam().updateProjectionMatrix()
|
||||
}
|
||||
opts.camera.offsetY = offsetY
|
||||
}
|
||||
}
|
||||
|
||||
xrf.roundrobin = (frag, store) => {
|
||||
if( !frag.args || frag.args.length == 0 ) return 0
|
||||
if( !store.rr ) store.rr = {}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* (promise-able) EVENTS
|
||||
* (promise-able) EVENTS (optionally continue after listeners are finished using .then)
|
||||
*
|
||||
* example:
|
||||
*
|
||||
|
|
@ -14,18 +14,33 @@
|
|||
* xrf.emit('foo',123).then(...).catch(...).finally(...)
|
||||
*/
|
||||
|
||||
xrf.addEventListener = function(eventName, callback) {
|
||||
if( !this._listeners ) this._listeners = []
|
||||
if (!this._listeners[eventName]) {
|
||||
// create a new array for this event name if it doesn't exist yet
|
||||
this._listeners[eventName] = [];
|
||||
}
|
||||
// add the callback to the listeners array for this event name
|
||||
this._listeners[eventName].push(callback);
|
||||
xrf.addEventListener = function(eventName, callback, scene) {
|
||||
if( !this._listeners ) this._listeners = []
|
||||
if (!this._listeners[eventName]) {
|
||||
// create a new array for this event name if it doesn't exist yet
|
||||
this._listeners[eventName] = [];
|
||||
}
|
||||
if( scene ) callback.scene = scene
|
||||
// add the callback to the listeners array for this event name
|
||||
this._listeners[eventName].push(callback);
|
||||
return () => {
|
||||
this._listeners[eventName] = this._listeners[eventName].filter( (c) => c != callback )
|
||||
}
|
||||
};
|
||||
|
||||
xrf.emit = function(eventName, data){
|
||||
if( typeof data != 'object' ) throw 'emit() requires passing objects'
|
||||
if( xrf.debug && ( eventName != "render" || xrf.debug == eventName ) ){
|
||||
let label = String(`xrf.emit('${eventName}')`).padEnd(35," ");
|
||||
label += data.mesh && data.mesh.name ? '#'+data.mesh.name : ''
|
||||
console.groupCollapsed(label)
|
||||
console.info(data)
|
||||
console.groupEnd(label)
|
||||
if( xrf.debug > 1 ) debugger
|
||||
}
|
||||
// forward to THREEjs eventbus if any
|
||||
if( data.scene ) data.scene.dispatchEvent( eventName, data )
|
||||
if( data.mesh ) data.mesh.dispatchEvent( eventName, data )
|
||||
return xrf.emit.promise(eventName,data)
|
||||
}
|
||||
|
||||
|
|
@ -40,15 +55,27 @@ xrf.emit.normal = function(eventName, data) {
|
|||
};
|
||||
|
||||
xrf.emit.promise = function(e, opts){
|
||||
opts.XRF = xrf // always pass root XRF obj
|
||||
return new Promise( (resolve, reject) => {
|
||||
opts.promise = () => {
|
||||
opts.promise.halted = true
|
||||
return { resolve, reject }
|
||||
opts.promises = opts.promises || []
|
||||
opts.promises.push(0)
|
||||
return {
|
||||
resolve: ((index) => () => {
|
||||
opts.promises[index] = 1
|
||||
let succesful = opts.promises.reduce( (a,b) => a+b )
|
||||
if( succesful == opts.promises.length ) resolve(opts)
|
||||
})(opts.promises.length-1),
|
||||
reject: console.error
|
||||
}
|
||||
}
|
||||
xrf.emit.normal(e, opts)
|
||||
delete opts.XRF
|
||||
if( !opts.promise.halted ) resolve()
|
||||
if( !opts.promises ) resolve(opts)
|
||||
delete opts.promise
|
||||
})
|
||||
}
|
||||
|
||||
xrf.addEventListener('reset', () => {
|
||||
// *TODO* do this nicely
|
||||
// xrf._listeners['renderPost'] = []
|
||||
// xrf._listeners['render'] = []
|
||||
})
|
||||
|
|
|
|||
2
src/3rd/js/rasterizeHTML.min.js
vendored
2
src/3rd/js/rasterizeHTML.min.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -8,7 +8,7 @@ let pub = function( url, model, flags ){ // evaluate fragments in url
|
|||
if( !url.match(/#/) ) url = `#${url}`
|
||||
model = model || xrf.model
|
||||
let { THREE, camera } = xrf
|
||||
let frag = xrf.URI.parse( url, flags != undefined ? flags : xrf.XRF.NAVIGATOR )
|
||||
let frag = xrf.URI.parse( url, flags )
|
||||
let opts = {frag, mesh:xrf.camera, model, camera: xrf.camera, scene: xrf.scene, renderer: xrf.renderer, THREE: xrf.THREE, hashbus: xrf.hashbus }
|
||||
xrf.emit('hashbus',opts)
|
||||
.then( () => {
|
||||
|
|
@ -26,7 +26,7 @@ pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) insid
|
|||
for( let k in frag ){
|
||||
let opts = {frag, mesh, model, camera: xrf.camera, scene: model.scene, renderer: xrf.renderer, THREE: xrf.THREE, hashbus: xrf.hashbus }
|
||||
mesh.userData.XRF = frag // allow fragment impl to access XRF obj already
|
||||
xrf.emit('mesh',opts)
|
||||
xrf.emit('frag2mesh',opts)
|
||||
.then( () => pub.fragment(k,opts) )
|
||||
}
|
||||
}
|
||||
|
|
@ -35,13 +35,47 @@ pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) insid
|
|||
pub.fragment = (k, opts ) => { // evaluate one fragment
|
||||
let frag = opts.frag[k];
|
||||
|
||||
if( frag.is( xrf.XRF.PV_EXECUTE ) ) pub.XRWG({...opts,frag})
|
||||
|
||||
// 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( xrf[k] ) xrf[k]( func, frag, opts)
|
||||
else func( frag, opts)
|
||||
if( typeof xrf[k] == 'function' ) xrf[k]( func, frag, opts)
|
||||
else func( frag, opts)
|
||||
})
|
||||
}
|
||||
|
||||
pub.XRWG = (opts) => {
|
||||
let {frag,scene,model,renderer} = opts
|
||||
|
||||
// if this query was triggered by an src-value, lets filter it
|
||||
const isSRC = opts.embedded && opts.embedded.fragment == 'src'
|
||||
if( !isSRC ){ // spec : https://xrfragment.org/#src
|
||||
for ( let i in frag ) {
|
||||
let v = frag[i]
|
||||
let id = v.string || v.fragment
|
||||
if( id == '#' || !id ) return
|
||||
let match = xrf.XRWG.match(id)
|
||||
|
||||
if( v.is( xrf.XRF.PV_EXECUTE ) ){
|
||||
scene.XRF_PV_ORIGIN = v.string
|
||||
// evaluate aliases
|
||||
match.map( (w) => {
|
||||
if( w.key == `#${id}` ){
|
||||
if( w.value && w.value[0] == '#' ){
|
||||
// if value is alias, execute fragment value
|
||||
xrf.hashbus.pub( w.value, xrf.model, xrf.XRF.METADATA | xrf.XRF.PV_OVERRIDE | xrf.XRF.NAVIGATOR )
|
||||
}
|
||||
}
|
||||
})
|
||||
xrf.emit('dynamicKey',{ ...opts,v,frag,id,match,scene })
|
||||
}else{
|
||||
xrf.emit('dynamicKeyValue',{ ...opts,v,frag,id,match,scene })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
xrf.hashbus = { pub }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
xrf.frag = {}
|
||||
xrf.model = {}
|
||||
xrf.mixers = []
|
||||
|
||||
xrf.init = ((init) => function(opts){
|
||||
let scene = new opts.THREE.Group()
|
||||
|
|
@ -8,21 +9,26 @@ xrf.init = ((init) => function(opts){
|
|||
init(opts)
|
||||
if( opts.loaders ) Object.values(opts.loaders).map( xrf.patchLoader )
|
||||
|
||||
xrf.patchRenderer(opts.renderer)
|
||||
xrf.patchRenderer(opts)
|
||||
xrf.navigator.init()
|
||||
// return xrfragment lib as 'xrf' query functor (like jquery)
|
||||
for ( let i in xrf ) xrf.query[i] = xrf[i]
|
||||
return xrf.query
|
||||
})(xrf.init)
|
||||
|
||||
xrf.patchRenderer = function(renderer){
|
||||
xrf.patchRenderer = function(opts){
|
||||
let {renderer,camera} = opts
|
||||
renderer.xr.addEventListener( 'sessionstart', () => xrf.baseReferenceSpace = renderer.xr.getReferenceSpace() );
|
||||
renderer.xr.enabled = true;
|
||||
xrf.clock = new xrf.THREE.Clock()
|
||||
renderer.render = ((render) => function(scene,camera){
|
||||
if( xrf.model && xrf.model.render )
|
||||
xrf.model.render(scene,camera)
|
||||
// update clock
|
||||
let time = xrf.clock.getDelta()
|
||||
xrf.emit('render',{scene,camera,time,render}) // allow fragments to do something at renderframe
|
||||
render(scene,camera)
|
||||
xrf.emit('renderPost',{scene,camera,time,render,renderer}) // allow fragments to do something after renderframe
|
||||
})(renderer.render.bind(renderer))
|
||||
|
||||
}
|
||||
|
||||
xrf.patchLoader = function(loader){
|
||||
|
|
@ -46,30 +52,11 @@ xrf.parseModel = function(model,url){
|
|||
let file = xrf.getFile(url)
|
||||
model.file = file
|
||||
// eval embedded XR fragments
|
||||
model.scene.traverse( (mesh) => xrf.hashbus.pub.mesh(mesh,model) )
|
||||
// add animations
|
||||
model.clock = new xrf.THREE.Clock();
|
||||
model.mixer = new xrf.THREE.AnimationMixer(model.scene)
|
||||
model.animations.map( (anim) => {
|
||||
anim.action = model.mixer.clipAction( anim )
|
||||
//anim.action.setLoop(0)
|
||||
anim.action.play()
|
||||
model.scene.traverse( (mesh) => {
|
||||
xrf.hashbus.pub.mesh(mesh,model)
|
||||
})
|
||||
|
||||
let tmp = new xrf.THREE.Vector3()
|
||||
model.render = function(){
|
||||
let time = model.clock.getDelta()
|
||||
model.mixer.update( time )
|
||||
|
||||
// update focusline
|
||||
xrf.focusLine.material.color.r = (1.0 + Math.sin( model.clock.getElapsedTime()*10 ))/2
|
||||
xrf.focusLine.material.dashSize = 0.2 + 0.02*Math.sin( model.clock.getElapsedTime() )
|
||||
xrf.focusLine.material.gapSize = 0.1 + 0.02*Math.sin( model.clock.getElapsedTime() *3 )
|
||||
xrf.focusLine.material.opacity = (0.25 + 0.15*Math.sin( model.clock.getElapsedTime() * 3 )) * xrf.focusLine.opacity;
|
||||
if( xrf.focusLine.opacity > 0.0 ) xrf.focusLine.opacity -= time*0.2
|
||||
if( xrf.focusLine.opacity < 0.0 ) xrf.focusLine.opacity = 0
|
||||
}
|
||||
|
||||
model.animations.map( (a) => console.log("anim: "+a.name) )
|
||||
xrf.emit('parseModel',{model,url,file})
|
||||
}
|
||||
|
||||
xrf.getLastModel = () => xrf.model.last
|
||||
|
|
@ -87,11 +74,18 @@ xrf.reset = () => {
|
|||
return true
|
||||
};
|
||||
let nodes = []
|
||||
xrf.scene.traverse( (child) => child.isXRF ? nodes.push(child) : false )
|
||||
xrf.scene.traverse( (n) => n.audio && (n.audio.remove()) )
|
||||
xrf.scene.traverse( (child) => child.isXRF && (nodes.push(child)) )
|
||||
nodes.map( disposeObject ) // leave non-XRF objects intact
|
||||
xrf.interactive = xrf.InteractiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
|
||||
xrf.interactive = xrf.interactiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
|
||||
xrf.add( xrf.interactive )
|
||||
xrf.layers = 0
|
||||
|
||||
// reset certain events
|
||||
xrf.emit('reset',{})
|
||||
// remove mixers
|
||||
xrf.mixers.map( (m) => m.stop())
|
||||
xrf.mixers = []
|
||||
}
|
||||
|
||||
xrf.parseUrl = (url) => {
|
||||
|
|
@ -108,3 +102,8 @@ xrf.add = (object) => {
|
|||
xrf.scene.add(object)
|
||||
}
|
||||
|
||||
xrf.hasNoMaterial = (mesh) => {
|
||||
const hasTexture = mesh.material && mesh.material.map
|
||||
const hasMaterialName = mesh.material && mesh.material.name.length > 0
|
||||
return mesh.geometry && !hasMaterialName && !hasTexture
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ xrf.navigator.to = (url,flags,loader,data) => {
|
|||
if( !url ) throw 'xrf.navigator.to(..) no url given'
|
||||
|
||||
let hashbus = xrf.hashbus
|
||||
xrf.emit('navigate', {url,loader,data})
|
||||
|
||||
return new Promise( (resolve,reject) => {
|
||||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||
|
|
@ -33,15 +34,15 @@ xrf.navigator.to = (url,flags,loader,data) => {
|
|||
// spec: 1. generate the XRWG
|
||||
xrf.XRWG.generate({model,scene:model.scene})
|
||||
// spec: 1. execute the default predefined view '#' (if exist) (https://xrfragment.org/#predefined_view)
|
||||
xrf.frag.defaultPredefinedView({model,scene:model.scene})
|
||||
xrf.frag.defaultPredefinedViews({model,scene:model.scene})
|
||||
// spec: 2. init metadata
|
||||
let frag = hashbus.pub( url, model ) // and eval URI XR fragments
|
||||
// spec: predefined view(s) from URL (https://xrfragment.org/#predefined_view)
|
||||
setTimeout( () => { // give external objects some slack
|
||||
xrf.frag.updatePredefinedView({model,scene:model.scene,frag})
|
||||
},2000)
|
||||
let frag = hashbus.pub( url, model) // and eval URI XR fragments
|
||||
hashbus.pub.XRWG({model,scene:model.scene,frag})
|
||||
|
||||
xrf.add( model.scene )
|
||||
xrf.navigator.updateHash(hash)
|
||||
xrf.emit('navigateLoaded',{url,model})
|
||||
resolve(model)
|
||||
}
|
||||
|
||||
|
|
|
|||
9
src/3rd/js/three/util/collision.js
Normal file
9
src/3rd/js/three/util/collision.js
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
xrf.getCollisionMeshes = () => {
|
||||
let meshes = []
|
||||
xrf.scene.traverse( (n) => {
|
||||
if( !n.userData.href && !n.userData.src && xrf.hasNoMaterial(n) ){
|
||||
meshes.push(n)
|
||||
}
|
||||
})
|
||||
return meshes
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
// wrapper to survive in/outside modules
|
||||
|
||||
xrf.InteractiveGroup = function(THREE,renderer,camera){
|
||||
xrf.interactiveGroup = function(THREE,renderer,camera){
|
||||
|
||||
let {
|
||||
Group,
|
||||
|
|
@ -13,7 +13,7 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
const _event = { type: '', data: _pointer };
|
||||
let object = {selected:false}
|
||||
|
||||
class InteractiveGroup extends Group {
|
||||
class interactive extends Group {
|
||||
|
||||
constructor( renderer, camera ) {
|
||||
|
||||
|
|
@ -71,9 +71,9 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
element.addEventListener( 'pointerup', onPointerEvent );
|
||||
element.addEventListener( 'pointermove', onPointerEvent );
|
||||
element.addEventListener( 'mousedown', onPointerEvent );
|
||||
element.addEventListener( 'mouseup', onPointerEvent );
|
||||
element.addEventListener( 'mousemove', onPointerEvent );
|
||||
element.addEventListener( 'click', onPointerEvent );
|
||||
element.addEventListener( 'mouseup', onPointerEvent );
|
||||
|
||||
// WebXR Controller Events
|
||||
// TODO: Dispatch pointerevents too
|
||||
|
|
@ -131,12 +131,12 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
}
|
||||
|
||||
add(obj){
|
||||
Group.prototype.add.call( this, obj )
|
||||
this.objects = ([]).concat( this.children )
|
||||
add(obj, unparent){
|
||||
if( unparent ) Group.prototype.add.call( this, obj )
|
||||
this.objects.push(obj)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new InteractiveGroup(renderer,camera)
|
||||
return new interactive(renderer,camera)
|
||||
}
|
||||
64
src/3rd/js/three/xrf/dynamic/XRWG-lines.js
Normal file
64
src/3rd/js/three/xrf/dynamic/XRWG-lines.js
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
xrf.addEventListener('dynamicKey', (opts) => {
|
||||
let {scene,id,match,v} = opts
|
||||
if( !scene ) return
|
||||
let remove = []
|
||||
// erase previous lines
|
||||
xrf.focusLine.lines.map( (line) => line.parent && (line.parent.remove(line)) )
|
||||
xrf.focusLine.points = []
|
||||
xrf.focusLine.lines = []
|
||||
|
||||
// drawlines
|
||||
match.map( (w) => {
|
||||
w.nodes.map( (mesh) => xrf.drawLineToMesh({ ...opts, mesh}) )
|
||||
})
|
||||
})
|
||||
|
||||
xrf.drawLineToMesh = (opts) => {
|
||||
let {scene,mesh,frag,id} = opts
|
||||
const THREE = xrf.THREE
|
||||
let oldSelection
|
||||
// Selection of Interest if predefined_view matches object name
|
||||
if( mesh.visible && mesh.material){
|
||||
xrf.emit('focus',{...opts,frag})
|
||||
.then( () => {
|
||||
const color = new THREE.Color();
|
||||
const colors = []
|
||||
let from = new THREE.Vector3()
|
||||
|
||||
let getCenterPoint = (mesh) => {
|
||||
var geometry = mesh.geometry;
|
||||
geometry.computeBoundingBox();
|
||||
var center = new THREE.Vector3();
|
||||
geometry.boundingBox.getCenter( center );
|
||||
mesh.localToWorld( center );
|
||||
return center;
|
||||
}
|
||||
|
||||
let cam = xrf.camera.getCam ? xrf.camera.getCam() : xrf.camera // *FIXME* camerarig/rig are conflicting
|
||||
cam.updateMatrixWorld(true); // always keeps me diving into the docs :]
|
||||
cam.getWorldPosition(from)
|
||||
from.y = 0.5 // originate from the heart chakra! :p
|
||||
const points = [from, getCenterPoint(mesh) ]
|
||||
const geometry = new THREE.BufferGeometry().setFromPoints( points );
|
||||
let line = new THREE.Line( geometry, xrf.focusLine.material );
|
||||
line.isXRF = true
|
||||
line.computeLineDistances();
|
||||
xrf.focusLine.lines.push(line)
|
||||
xrf.focusLine.points.push(from)
|
||||
xrf.focusLine.opacity = 1
|
||||
scene.add(line)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
xrf.addEventListener('render', (opts) => {
|
||||
// update focusline
|
||||
let {time,model} = opts
|
||||
if( !xrf.clock ) return
|
||||
xrf.focusLine.material.color.r = (1.0 + Math.sin( xrf.clock.getElapsedTime()*10 ))/2
|
||||
xrf.focusLine.material.dashSize = 0.2 + 0.02*Math.sin( xrf.clock.getElapsedTime() )
|
||||
xrf.focusLine.material.gapSize = 0.1 + 0.02*Math.sin( xrf.clock.getElapsedTime() *3 )
|
||||
xrf.focusLine.material.opacity = (0.25 + 0.15*Math.sin( xrf.clock.getElapsedTime() * 3 )) * xrf.focusLine.opacity;
|
||||
if( xrf.focusLine.opacity > 0.0 ) xrf.focusLine.opacity -= time*0.2
|
||||
if( xrf.focusLine.opacity < 0.0 ) xrf.focusLine.opacity = 0
|
||||
})
|
||||
123
src/3rd/js/three/xrf/dynamic/filter.js
Normal file
123
src/3rd/js/three/xrf/dynamic/filter.js
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* TODO: refactor/fix this (queries are being refactored to filters)
|
||||
*/
|
||||
|
||||
|
||||
xrf.addEventListener('dynamicKey', (opts) => {
|
||||
let {scene,id,match,v} = opts
|
||||
if( v.filter ){
|
||||
let frags = {}
|
||||
frags[ v.filter.key ] = v
|
||||
xrf.filter.scene({frag:frags,scene})
|
||||
}
|
||||
})
|
||||
|
||||
// spec: https://xrfragment.org/#filters
|
||||
xrf.filter = function(query, cb){
|
||||
let result = []
|
||||
if( !query ) return result
|
||||
if( query[0] != '#' ) query = '#'+query
|
||||
// *TODO* jquery like utility func
|
||||
return result
|
||||
}
|
||||
|
||||
xrf.filter.scene = function(opts){
|
||||
let {scene,frag} = opts
|
||||
|
||||
scene = xrf.filter
|
||||
.sort(frag) // get (sorted) filters from XR Fragments
|
||||
.process(frag,scene,opts) // show/hide things
|
||||
|
||||
scene.visible = true // always enable scene
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// opts = {copyScene:true} in case you want a copy of the scene (not filter the current scene inplace)
|
||||
xrf.filter.process = function(frag,scene,opts){
|
||||
const cleanupKey = (k) => k.replace(/[-\*\/]/g,'')
|
||||
let firstFilter = frag.filters.length ? frag.filters[0].filter.get() : false
|
||||
const hasName = (m,name,filter) => m.name == name
|
||||
const hasNameOrTag = (m,name_or_tag,filter) => hasName(m,name_or_tag) ||
|
||||
String(m.userData['tag']).match( new RegExp("(^| )"+name_or_tag) )
|
||||
|
||||
// utility functions
|
||||
const getOrCloneMaterial = (o) => {
|
||||
if( o.material ){
|
||||
if( o.material.isXRF ) return o.material
|
||||
o.material = o.material.clone()
|
||||
o.material.isXRF = true
|
||||
return o.material
|
||||
}
|
||||
return {}
|
||||
}
|
||||
const setVisible = (n,visible,filter,processed) => {
|
||||
if( processed && processed[n.uuid] ) return
|
||||
getOrCloneMaterial(n).visible = visible
|
||||
if( filter.deep ) n.traverse( (m) => getOrCloneMaterial(m).visible = visible )
|
||||
if( processed ) processed[n.uuid] == true
|
||||
}
|
||||
|
||||
// spec 2: https://xrfragment.org/doc/RFC_XR_Macros.html#embedding-xr-content-using-src
|
||||
// reparent scene based on objectname in case it matches a (non-negating) selector
|
||||
if( opts.reparent && firstFilter && !firstFilter.value && firstFilter.show === true ){
|
||||
let obj
|
||||
frag.target = firstFilter
|
||||
scene.traverse( (n) => hasName(n, firstFilter.key,firstFilter) && (obj = n) )
|
||||
console.log("reparent "+firstFilter.key+" "+((opts.copyScene)?"copy":"inplace"))
|
||||
if(obj ){
|
||||
obj.position.set(0,0,0)
|
||||
if( opts.copyScene ){
|
||||
opts.copyScene = new xrf.THREE.Scene()
|
||||
opts.copyScene.children[0] = obj
|
||||
scene = opts.copyScene
|
||||
}else{
|
||||
// empty current scene and add obj
|
||||
while( scene.children.length > 0 ) scene.children[0].removeFromParent()
|
||||
scene.add( obj )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// then show/hide things based on secondary selectors
|
||||
// we don't use the XRWG (everything) because we process only the given (sub)scene
|
||||
frag.filters.map( (v) => {
|
||||
const filter = v.filter.get()
|
||||
const name_or_tag = cleanupKey(v.fragment)
|
||||
let processed = {}
|
||||
let extembeds = {}
|
||||
|
||||
// hide external objects temporarely
|
||||
scene.traverse( (m) => {
|
||||
if( m.isSRCExternal ){
|
||||
m.traverse( (n) => (extembeds[ n.uuid ] = m) && (m.visible = false) )
|
||||
}
|
||||
})
|
||||
|
||||
scene.traverseVisible( (m) => {
|
||||
// filter on value(expression) #foo=>3 e.g. *TODO* do this in XRWG
|
||||
if( filter.value && m.userData[filter.key] ){
|
||||
const visible = v.filter.testProperty(filter.key, m.userData[filter.key], filter.show === false )
|
||||
setVisible(m,visible,filter,processed)
|
||||
return
|
||||
}
|
||||
if( hasNameOrTag(m,name_or_tag,filter ) ){
|
||||
setVisible(m,filter.show,filter)
|
||||
}
|
||||
})
|
||||
|
||||
// show external objects again
|
||||
for ( let i in extembeds ) extembeds[i].visible = true
|
||||
})
|
||||
|
||||
return scene
|
||||
}
|
||||
|
||||
23
src/3rd/js/three/xrf/dynamic/index.js
Normal file
23
src/3rd/js/three/xrf/dynamic/index.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
xrf.frag.defaultPredefinedViews = (opts) => {
|
||||
let {scene,model} = opts;
|
||||
scene.traverse( (n) => {
|
||||
if( n.userData && n.userData['#'] ){
|
||||
let frag = xrf.URI.parse( n.userData['#'] )
|
||||
xrf.hashbus.pub( n.userData['#'] ) // evaluate static XR fragments
|
||||
xrf.hashbus.pub.XRWG({frag,model,scene}) // evaluate dynamic XR fragment using XRWG (see spec)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// react to enduser typing url
|
||||
xrf.addEventListener('hash', (opts) => {
|
||||
let frag = xrf.URI.parse( opts.hash )
|
||||
xrf.hashbus.pub.XRWG({frag,scene:xrf.scene})
|
||||
})
|
||||
|
||||
// clicking href url with predefined view
|
||||
xrf.addEventListener('href', (opts) => {
|
||||
if( !opts.click || opts.xrf.string[0] != '#' ) return
|
||||
let frag = xrf.URI.parse( opts.xrf.string, xrf.XRF.NAVIGATOR | xrf.XRF.PV_OVERRIDE | xrf.XRF.METADATA )
|
||||
xrf.hashbus.pub.XRWG({frag,scene:xrf.scene,href:opts.xrf})
|
||||
})
|
||||
30
src/3rd/js/three/xrf/dynamic/uvscroll.js
Normal file
30
src/3rd/js/three/xrf/dynamic/uvscroll.js
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
xrf.addEventListener('dynamicKeyValue', (opts) => {
|
||||
let {scene,match,v} = opts
|
||||
let objname = v.fragment
|
||||
let autoscroll = v.z > 0 || v.w > 0
|
||||
|
||||
scene.traverse( (mesh) => {
|
||||
if( mesh.name == objname ){
|
||||
if( !mesh.geometry ) return console.warn(`mesh '${objname}' has no uvcoordinates to offset`)
|
||||
let uv = mesh.geometry.getAttribute("uv")
|
||||
if( !uv.old ) uv.old = uv.clone()
|
||||
|
||||
for( let i = 0; i < uv.count; i++ ){
|
||||
uv.setXY(i, uv.old.getX(i) + v.x, uv.old.getY(i) + v.y )
|
||||
}
|
||||
|
||||
if( autoscroll ){
|
||||
if( mesh.removeUVListener ) mesh.removeUVListener()
|
||||
mesh.removeUVListener = xrf.addEventListener('render', (opts) => {
|
||||
let {time} = opts
|
||||
for( let i = 0; i < uv.count; i++ ){
|
||||
uv.setXY(i, uv.getX(i) + v.z * time, uv.getY(i) + v.w * time)
|
||||
}
|
||||
uv.needsUpdate = true
|
||||
})
|
||||
}
|
||||
|
||||
uv.needsUpdate = true
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
@ -29,78 +29,27 @@
|
|||
*/
|
||||
|
||||
xrf.frag.href = function(v, opts){
|
||||
opts.embedded = v // indicate embedded XR fragment
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
|
||||
if( mesh.userData.XRF.href.exec ) return // mesh already initialized
|
||||
|
||||
const world = {
|
||||
pos: new THREE.Vector3(),
|
||||
scale: new THREE.Vector3(),
|
||||
quat: new THREE.Quaternion()
|
||||
}
|
||||
// detect equirectangular image
|
||||
let texture = mesh.material && mesh.material.map ? mesh.material.map : null
|
||||
if( texture && texture.source.data.height == texture.source.data.width/2 ){
|
||||
texture.mapping = THREE.ClampToEdgeWrapping
|
||||
texture.needsUpdate = true
|
||||
|
||||
// poor man's equi-portal
|
||||
mesh.material = new THREE.ShaderMaterial( {
|
||||
side: THREE.DoubleSide,
|
||||
uniforms: {
|
||||
pano: { value: texture },
|
||||
selected: { value: false },
|
||||
},
|
||||
vertexShader: `
|
||||
vec3 portalPosition;
|
||||
varying vec3 vWorldPosition;
|
||||
varying float vDistanceToCenter;
|
||||
varying float vDistance;
|
||||
void main() {
|
||||
vDistanceToCenter = clamp(length(position - vec3(0.0, 0.0, 0.0)), 0.0, 1.0);
|
||||
portalPosition = (modelMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
|
||||
vDistance = length(portalPosition - cameraPosition);
|
||||
vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||
}
|
||||
`,
|
||||
fragmentShader: `
|
||||
#define RECIPROCAL_PI2 0.15915494
|
||||
uniform sampler2D pano;
|
||||
uniform bool selected;
|
||||
varying float vDistanceToCenter;
|
||||
varying float vDistance;
|
||||
varying vec3 vWorldPosition;
|
||||
void main() {
|
||||
vec3 direction = normalize(vWorldPosition - cameraPosition );
|
||||
vec2 sampleUV;
|
||||
sampleUV.y = -clamp(direction.y * 0.5 + 0.5, 0.0, 1.0);
|
||||
sampleUV.x = atan(direction.z, -direction.x) * -RECIPROCAL_PI2;
|
||||
sampleUV.x += 0.33; // adjust focus to AFRAME's a-scene.components.screenshot.capture()
|
||||
vec4 color = texture2D(pano, sampleUV);
|
||||
// Convert color to grayscale (lazy lite approach to not having to match tonemapping/shaderstacking of THREE.js)
|
||||
float luminance = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
|
||||
vec4 grayscale_color = selected ? color : vec4(vec3(luminance) + vec3(0.33), color.a);
|
||||
gl_FragColor = grayscale_color;
|
||||
}
|
||||
`,
|
||||
});
|
||||
mesh.material.needsUpdate = true
|
||||
}else if( mesh.material){ mesh.material = mesh.material.clone() }
|
||||
|
||||
let click = mesh.userData.XRF.href.exec = (e) => {
|
||||
|
||||
let isLocal = v.string[0] == '#'
|
||||
let lastPos = `pos=${camera.position.x.toFixed(2)},${camera.position.y.toFixed(2)},${camera.position.z.toFixed(2)}`
|
||||
|
||||
let lastPos = `pos=${camera.position.x.toFixed(2)},${camera.position.y.toFixed(2)},${camera.position.z.toFixed(2)}`
|
||||
xrf
|
||||
.emit('href',{click:true,mesh,xrf:v}) // let all listeners agree
|
||||
.then( () => {
|
||||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(v.string)
|
||||
//if( !file.match(/\./) || file.match(/\.html/) ){
|
||||
// debugger
|
||||
// let inIframe
|
||||
// try { inIframe = window.self !== window.top; } catch (e) { inIframe = true; }
|
||||
// return inIframe ? window.parent.postMessage({ url: v.string }, '*') : window.open( v.string, '_blank')
|
||||
//}
|
||||
const flags = v.string[0] == '#' ? xrf.XRF.PV_OVERRIDE : undefined
|
||||
let toFrag = xrf.URI.parse( v.string, xrf.XRF.NAVIGATOR | xrf.XRF.PV_OVERRIDE | xrf.XRF.METADATA )
|
||||
// always keep a trail of last positions before we navigate
|
||||
if( !document.location.hash.match(lastPos) ) xrf.navigator.to(`#${lastPos}`)
|
||||
// always commit current location (keep a trail of last positions before we navigate)
|
||||
if( !e.nocommit && !document.location.hash.match(lastPos) ) xrf.navigator.to(`#${lastPos}`)
|
||||
xrf.navigator.to(v.string) // let's surf to HREF!
|
||||
})
|
||||
.catch( console.error )
|
||||
|
|
@ -112,7 +61,12 @@ xrf.frag.href = function(v, opts){
|
|||
let newState = o.name == mesh.name ? state : false
|
||||
if( o.material ){
|
||||
if( o.material.uniforms ) o.material.uniforms.selected.value = newState
|
||||
if( o.material.emissive ) o.material.emissive.r = o.material.emissive.g = o.material.emissive.b = newState ? 2.0 : 1.0
|
||||
//if( o.material.emissive ) o.material.emissive.r = o.material.emissive.g = o.material.emissive.b = newState ? 2.0 : 1.0
|
||||
if( o.material.emissive ){
|
||||
if( !o.material.emissive.original ) o.material.emissive.original = o.material.emissive.clone()
|
||||
o.material.emissive.r = o.material.emissive.g = o.material.emissive.b =
|
||||
newState ? o.material.emissive.original.r + 0.5 : o.material.emissive.original.r
|
||||
}
|
||||
}
|
||||
})
|
||||
// update mouse cursor
|
||||
|
|
@ -127,16 +81,13 @@ xrf.frag.href = function(v, opts){
|
|||
|
||||
mesh.addEventListener('click', click )
|
||||
mesh.addEventListener('mousemove', selected(true) )
|
||||
mesh.addEventListener('mouseenter', selected(true) )
|
||||
mesh.addEventListener('mouseleave', selected(false) )
|
||||
|
||||
if( mesh.material ) mesh.material = mesh.material.clone() // clone, so we can individually highlight meshes
|
||||
|
||||
// lazy add mesh (because we're inside a recursive traverse)
|
||||
setTimeout( (mesh) => {
|
||||
mesh.getWorldPosition(world.pos)
|
||||
mesh.getWorldScale(world.scale)
|
||||
mesh.getWorldQuaternion(world.quat);
|
||||
mesh.position.copy(world.pos)
|
||||
mesh.scale.copy(world.scale)
|
||||
mesh.setRotationFromQuaternion(world.quat);
|
||||
xrf.interactive.add(mesh)
|
||||
xrf.emit('interactionReady', {mesh,xrf:v,clickHandler: mesh.userData.XRF.href.exec })
|
||||
}, 0, mesh )
|
||||
|
|
|
|||
|
|
@ -1,6 +1,18 @@
|
|||
xrf.frag.pos = function(v, opts){
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
camera.position.x = v.x
|
||||
camera.position.y = v.y
|
||||
camera.position.z = v.z
|
||||
|
||||
|
||||
// spec: indirect coordinate using objectname: https://xrfragment.org/#navigating%203D
|
||||
if( v.x == undefined ){
|
||||
let obj = scene.getObjectByName(v.string)
|
||||
if( !obj ) return
|
||||
let pos = obj.position.clone()
|
||||
obj.getWorldPosition(pos)
|
||||
camera.position.copy(pos)
|
||||
}else{
|
||||
// spec: direct coordinate: https://xrfragment.org/#navigating%203D
|
||||
camera.position.x = v.x
|
||||
camera.position.y = v.y
|
||||
camera.position.z = v.z
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,125 +0,0 @@
|
|||
xrf.frag.defaultPredefinedView = (opts) => {
|
||||
let {scene,model} = opts;
|
||||
let frag = {}
|
||||
xrf.Parser.parse("#","",frag)
|
||||
xrf.frag.updatePredefinedView({frag,model,scene})
|
||||
}
|
||||
|
||||
xrf.frag.updatePredefinedView = (opts) => {
|
||||
let {frag,scene,model,renderer} = opts
|
||||
|
||||
// spec: https://xrfragment.org/#Selection%20of%20interest
|
||||
const selectionOfInterest = (frag,scene,mesh) => {
|
||||
let id = frag.string
|
||||
let oldSelection
|
||||
if(!id) return id // important: ignore empty strings
|
||||
// Selection of Interest if predefined_view matches object name
|
||||
if( mesh.visible && mesh.material){
|
||||
xrf.emit('focus',{...opts,frag})
|
||||
.then( () => {
|
||||
const color = new THREE.Color();
|
||||
const colors = []
|
||||
let from = new THREE.Vector3()
|
||||
|
||||
let getCenterPoint = (mesh) => {
|
||||
var geometry = mesh.geometry;
|
||||
geometry.computeBoundingBox();
|
||||
var center = new THREE.Vector3();
|
||||
geometry.boundingBox.getCenter( center );
|
||||
mesh.localToWorld( center );
|
||||
return center;
|
||||
}
|
||||
|
||||
xrf.camera.updateMatrixWorld(true); // always keeps me diving into the docs :]
|
||||
xrf.camera.getWorldPosition(from)
|
||||
from.y -= 0.5 // originate from the heart chakra! :p
|
||||
const points = [from, getCenterPoint(mesh) ]
|
||||
const geometry = new THREE.BufferGeometry().setFromPoints( points );
|
||||
let line = new THREE.Line( geometry, xrf.focusLine.material );
|
||||
line.isXRF = true
|
||||
line.computeLineDistances();
|
||||
xrf.focusLine.lines.push(line)
|
||||
xrf.focusLine.points.push(from)
|
||||
xrf.focusLine.opacity = 1
|
||||
scene.add(line)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//// spec: https://xrfragment.org/#predefined_view
|
||||
//const predefinedView = (frag,scene,mesh) => {
|
||||
// let id = frag.string || frag.fragment
|
||||
// id = `#${id}`
|
||||
// if( id == '##' ) id = '#'; // default predefined view
|
||||
// if( !id ) return // prevent empty matches
|
||||
// if( mesh.userData[id] ){ // get alias
|
||||
// frag = xrf.URI.parse( mesh.userData[id], xrf.XRF.NAVIGATOR | xrf.XRF.PV_OVERRIDE | xrf.XRF.METADATA )
|
||||
// xrf.emit('predefinedView',{...opts,frag})
|
||||
// .then( () => {
|
||||
// for ( let k in frag ){
|
||||
// let opts = {frag, model, camera: xrf.camera, scene: xrf.scene, renderer: xrf.renderer, THREE: xrf.THREE }
|
||||
// if( frag[k].is( xrf.XRF.PV_EXECUTE ) && scene.XRF_PV_ORIGIN != k ){ // cyclic detection
|
||||
// highlightInScene(frag[k],scene) // recurse predefined views
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
//}
|
||||
|
||||
const highlightInScene = (v,scene) => {
|
||||
if( !scene ) return
|
||||
let remove = []
|
||||
let id = v.string || v.fragment
|
||||
if( id == '#' ) return
|
||||
let match = xrf.XRWG.match(id)
|
||||
console.dir({id,match,XRWG:xrf.XRWG})
|
||||
// erase previous lines
|
||||
xrf.focusLine.lines.map( (line) => scene.remove(line) )
|
||||
xrf.focusLine.points = []
|
||||
xrf.focusLine.lines = []
|
||||
|
||||
scene.traverse( (n) => n.selection ? remove.push(n) : false )
|
||||
remove.map( (n) => scene.remove(n.selection) )
|
||||
// create new selections
|
||||
match.map( (w) => {
|
||||
if( w.key == `#${id}` ){
|
||||
if( w.value && w.value[0] == '#' ){
|
||||
// if value is alias, execute fragment value
|
||||
xrf.hashbus.pub( w.value, xrf.model, xrf.XRF.METADATA | xrf.XRF.PV_OVERRIDE | xrf.XRF.NAVIGATOR )
|
||||
}
|
||||
}
|
||||
w.nodes.map( (mesh) => selectionOfInterest( v, scene, mesh ) )
|
||||
})
|
||||
}
|
||||
|
||||
// if this query was triggered by an src-value, lets filter it
|
||||
const isSRC = opts.embedded && opts.embedded.fragment == 'src'
|
||||
if( isSRC ){ // spec : https://xrfragment.org/#src
|
||||
console.log("filtering predefined view of src")
|
||||
console.dir(frag)
|
||||
}else{
|
||||
console.log("updatePredefinedView")
|
||||
console.dir(frag)
|
||||
for ( let i in frag ) {
|
||||
let v = frag[i]
|
||||
if( v.is( xrf.XRF.PV_EXECUTE ) ){
|
||||
scene.XRF_PV_ORIGIN = v.string
|
||||
// wait for nested instances to arrive at the scene ?
|
||||
highlightInScene(v,scene)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// react to enduser typing url
|
||||
xrf.addEventListener('hash', (opts) => {
|
||||
let frag = xrf.URI.parse( opts.hash, xrf.XRF.NAVIGATOR | xrf.XRF.PV_OVERRIDE | xrf.XRF.METADATA )
|
||||
xrf.frag.updatePredefinedView({frag,scene:xrf.scene})
|
||||
})
|
||||
|
||||
// clicking href url with predefined view
|
||||
xrf.addEventListener('href', (opts) => {
|
||||
if( !opts.click || opts.xrf.string[0] != '#' ) return
|
||||
let frag = xrf.URI.parse( opts.xrf.string, xrf.XRF.NAVIGATOR | xrf.XRF.PV_OVERRIDE | xrf.XRF.METADATA )
|
||||
xrf.frag.updatePredefinedView({frag,scene:xrf.scene,href:opts.xrf})
|
||||
})
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
// spec: https://xrfragment.org/#queries
|
||||
|
||||
xrf.frag.q = 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.q.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.frag.q.filter(scene,frag) // spec : https://xrfragment.org/#queries
|
||||
}
|
||||
|
||||
xrf.frag.q.filter = 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].rules != undefined && q[i].rules.length && !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])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -1,84 +1,106 @@
|
|||
// *TODO* use webgl instancing
|
||||
|
||||
xrf.frag.src = function(v, opts){
|
||||
|
||||
opts.embedded = v // indicate embedded XR fragment
|
||||
let { mesh, model, camera, scene, renderer, THREE, hashbus, frag} = opts
|
||||
|
||||
console.log(" └ instancing src")
|
||||
let src;
|
||||
let url = v.string
|
||||
let vfrag = xrfragment.URI.parse(url)
|
||||
opts.isPlane = mesh.geometry && mesh.geometry.attributes.uv && mesh.geometry.attributes.uv.count == 4
|
||||
let srcFrag = opts.srcFrag = xrfragment.URI.parse(url)
|
||||
opts.isLocal = v.string[0] == '#'
|
||||
opts.isPortal = xrf.frag.src.renderAsPortal(mesh)
|
||||
|
||||
const addScene = (scene,url,frag) => {
|
||||
src = xrf.frag.src.filterScene(scene,{...opts,frag})
|
||||
xrf.frag.src.scale( src, opts, url )
|
||||
xrf.frag.src.eval( src, opts, url )
|
||||
enableSourcePortation(src)
|
||||
mesh.add(src)
|
||||
mesh.traverse( (n) => n.isSRC = n.isXRF = true )
|
||||
if( mesh.material ) mesh.material.visible = false
|
||||
}
|
||||
|
||||
const enableSourcePortation = (src) => {
|
||||
if( vfrag.href || v.string[0] == '#' ) return
|
||||
let scale = new THREE.Vector3()
|
||||
let size = new THREE.Vector3()
|
||||
mesh.getWorldScale(scale)
|
||||
new THREE.Box3().setFromObject(src).getSize(size)
|
||||
const geo = new THREE.SphereGeometry( Math.max(size.x, size.y, size.z) / scale.x, 10, 10 )
|
||||
const mat = new THREE.MeshBasicMaterial()
|
||||
mat.transparent = true
|
||||
mat.roughness = 0.05
|
||||
mat.metalness = 1
|
||||
mat.opacity = 0
|
||||
const cube = new THREE.Mesh( geo, mat )
|
||||
console.log("todo: sourceportate")
|
||||
//mesh.add(cube)
|
||||
}
|
||||
|
||||
const externalSRC = (url,frag,src) => {
|
||||
fetch(url, { method: 'HEAD' })
|
||||
.then( (res) => {
|
||||
console.log(`loading src ${url}`)
|
||||
let mimetype = res.headers.get('Content-type')
|
||||
if( url.replace(/#.*/,'').match(/\.(gltf|glb)$/) ) mimetype = 'gltf'
|
||||
//if( url.match(/\.(fbx|stl|obj)$/) ) mimetype =
|
||||
console.log("src mimetype: "+mimetype)
|
||||
opts = { ...opts, src, frag }
|
||||
return xrf.frag.src.type[ mimetype ] ? xrf.frag.src.type[ mimetype ](url,opts) : xrf.frag.src.type.unknown(url,opts)
|
||||
})
|
||||
.then( (model) => {
|
||||
if( model && model.scene ) addScene(model.scene, url, frag )
|
||||
})
|
||||
.finally( () => { })
|
||||
.catch( console.error )
|
||||
}
|
||||
|
||||
if( url[0] == "#" ) addScene(scene,url,vfrag) // current file
|
||||
else externalSRC(url,vfrag) // external file
|
||||
if( opts.isLocal ){
|
||||
xrf.frag.src.localSRC(url,srcFrag,opts) // local
|
||||
}else xrf.frag.src.externalSRC(url,srcFrag,opts) // external file
|
||||
}
|
||||
|
||||
xrf.frag.src.eval = function(scene, opts, url){
|
||||
let { mesh, model, camera, renderer, THREE, hashbus} = opts
|
||||
if( url ){
|
||||
console.log(mesh.name+" url="+url)
|
||||
//let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||
//let frag = xrfragment.URI.parse(url)
|
||||
//// scale URI XR Fragments (queries) inside src-value
|
||||
//for( var i in frag ){
|
||||
// hashbus.pub.fragment(i, Object.assign(opts,{frag, model:{scene},scene}))
|
||||
//}
|
||||
//hashbus.pub( '#', {scene} ) // execute the default projection '#' (if exist)
|
||||
//hashbus.pub( url, {scene} ) // and eval URI XR fragments
|
||||
xrf.frag.src.addModel = (model,url,frag,opts) => {
|
||||
let {mesh} = opts
|
||||
let scene = model.scene
|
||||
scene = xrf.frag.src.filterScene(scene,{...opts,frag}) // get filtered scene
|
||||
if( mesh.material && !mesh.userData.src ) mesh.material.visible = false // hide placeholder object
|
||||
//enableSourcePortation(scene)
|
||||
if( xrf.frag.src.renderAsPortal(mesh) ){
|
||||
// only add remote objects, because
|
||||
// local scene-objects are already added to scene
|
||||
xrf.portalNonEuclidian({...opts,model,scene:model.scene})
|
||||
if( !opts.isLocal ) xrf.scene.add(scene)
|
||||
}else{
|
||||
xrf.frag.src.scale( scene, opts, url ) // scale scene
|
||||
mesh.add(scene)
|
||||
xrf.emit('parseModel', {...opts, scene, model})
|
||||
}
|
||||
// flag everything isSRC & isXRF
|
||||
mesh.traverse( (n) => { n.isSRC = n.isXRF = n[ opts.isLocal ? 'isSRCLocal' : 'isSRCExternal' ] = true })
|
||||
}
|
||||
|
||||
xrf.frag.src.renderAsPortal = (mesh) => {
|
||||
// *TODO* should support better isFlat(mesh) check
|
||||
const isPlane = mesh.geometry && mesh.geometry.attributes.uv && mesh.geometry.attributes.uv.count == 4
|
||||
return xrf.hasNoMaterial(mesh) && isPlane
|
||||
}
|
||||
|
||||
xrf.frag.src.enableSourcePortation = (src) => {
|
||||
// show sourceportation clickable plane
|
||||
if( srcFrag.href || v.string[0] == '#' ) return
|
||||
let scale = new THREE.Vector3()
|
||||
let size = new THREE.Vector3()
|
||||
mesh.getWorldScale(scale)
|
||||
new THREE.Box3().setFromObject(src).getSize(size)
|
||||
const geo = new THREE.SphereGeometry( Math.max(size.x, size.y, size.z) / scale.x, 10, 10 )
|
||||
const mat = new THREE.MeshBasicMaterial()
|
||||
mat.transparent = true
|
||||
mat.roughness = 0.05
|
||||
mat.metalness = 1
|
||||
mat.opacity = 0
|
||||
const cube = new THREE.Mesh( geo, mat )
|
||||
console.log("todo: sourceportate")
|
||||
return xrf.frag.src
|
||||
}
|
||||
|
||||
xrf.frag.src.externalSRC = (url,frag,opts) => {
|
||||
fetch(url, { method: 'HEAD' })
|
||||
.then( (res) => {
|
||||
console.log(`loading src ${url}`)
|
||||
let mimetype = res.headers.get('Content-type')
|
||||
if( url.replace(/#.*/,'').match(/\.(gltf|glb)$/) ) mimetype = 'gltf'
|
||||
//if( url.match(/\.(fbx|stl|obj)$/) ) mimetype =
|
||||
opts = { ...opts, frag, mimetype }
|
||||
return xrf.frag.src.type[ mimetype ] ? xrf.frag.src.type[ mimetype ](url,opts) : xrf.frag.src.type.unknown(url,opts)
|
||||
})
|
||||
.then( (model) => {
|
||||
if( model && model.scene ) xrf.frag.src.addModel(model, url, frag, opts )
|
||||
})
|
||||
.finally( () => { })
|
||||
.catch( console.error )
|
||||
return xrf.frag.src
|
||||
}
|
||||
|
||||
xrf.frag.src.localSRC = (url,frag,opts) => {
|
||||
let {model,mesh,scene} = opts
|
||||
setTimeout( () => {
|
||||
if( mesh.material ) mesh.material = mesh.material.clone() // clone, so we can individually highlight meshes
|
||||
let _model = {
|
||||
animations: model.animations,
|
||||
scene: scene.clone() // *TODO* opts.isPortal ? scene : scene.clone()
|
||||
}
|
||||
_model.scenes = [_model.scene]
|
||||
xrf.frag.src.addModel(_model,url,frag, opts) // current file
|
||||
},500 )
|
||||
}
|
||||
|
||||
// scale embedded XR fragments https://xrfragment.org/#scaling%20of%20instanced%20objects
|
||||
xrf.frag.src.scale = function(scene, opts, url){
|
||||
let { mesh, model, camera, renderer, THREE} = opts
|
||||
|
||||
// remove invisible objects (hidden by selectors) which might corrupt boundingbox size-detection
|
||||
let cleanScene = scene.clone()
|
||||
if( !cleanScene ) debugger
|
||||
let remove = []
|
||||
const notVisible = (n) => !n.visible || (n.material && !n.material.visible)
|
||||
cleanScene.traverse( (n) => notVisible(n) && n.children.length == 0 && (remove.push(n)) )
|
||||
remove.map( (n) => n.removeFromParent() )
|
||||
|
||||
let restrictTo3DBoundingBox = mesh.geometry
|
||||
if( restrictTo3DBoundingBox ){
|
||||
// spec 3 of https://xrfragment.org/#src
|
||||
|
|
@ -86,27 +108,14 @@ xrf.frag.src.scale = function(scene, opts, url){
|
|||
// normalize instanced objectsize to boundingbox
|
||||
let sizeFrom = new THREE.Vector3()
|
||||
let sizeTo = new THREE.Vector3()
|
||||
|
||||
let empty = new THREE.Object3D()
|
||||
|
||||
// *TODO* exclude invisible objects from boundingbox size-detection
|
||||
//
|
||||
// THREE.Box3.prototype.expandByObject = (function(expandByObject){
|
||||
// return function(object,precise){
|
||||
// return expandByObject.call(this, object.visible ? object : empty, precise)
|
||||
// }
|
||||
// })(THREE.Box3.prototype.expandByObject)
|
||||
|
||||
new THREE.Box3().setFromObject(mesh).getSize(sizeTo)
|
||||
new THREE.Box3().setFromObject(scene).getSize(sizeFrom)
|
||||
new THREE.Box3().setFromObject(cleanScene).getSize(sizeFrom)
|
||||
let ratio = sizeFrom.divide(sizeTo)
|
||||
scene.scale.multiplyScalar( 1.0 / Math.max(ratio.x, ratio.y, ratio.z));
|
||||
// let factor = getMax(sizeTo) < getMax(sizeFrom) ? getMax(sizeTo) / getMax(sizeFrom) : getMax(sizeFrom) / getMax(sizeTo)
|
||||
// scene.scale.multiplyScalar( factor )
|
||||
}else{
|
||||
// spec 4 of https://xrfragment.org/#src
|
||||
// spec 2 of https://xrfragment.org/#scaling%20of%20instanced%20objects
|
||||
console.log("normal scale: "+url)
|
||||
scene.scale.multiply( mesh.scale )
|
||||
}
|
||||
scene.isXRF = model.scene.isSRC = true
|
||||
|
|
@ -114,31 +123,16 @@ 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)
|
||||
if( !frag.q ){
|
||||
src = new THREE.Group()
|
||||
if( Object.keys(frag).length > 0 ){
|
||||
for( var i in frag ){
|
||||
if( scene.getObjectByName(i) ){
|
||||
src.add( obj = scene.getObjectByName(i).clone(true) )
|
||||
}
|
||||
hashbus.pub.fragment(i, Object.assign(opts,{frag, model,scene}))
|
||||
}
|
||||
}else src = scene.clone(true)
|
||||
if( src.children.length == 1 ) obj.position.set(0,0,0);
|
||||
}
|
||||
|
||||
// filtering of objects using query
|
||||
if( frag.q ){
|
||||
src = scene.clone(true);
|
||||
xrf.frag.q.filter(src,frag)
|
||||
scene = xrf.filter.scene({scene,frag,reparent:true}) // *TODO* ,copyScene: opts.isPortal})
|
||||
|
||||
if( !opts.isLocal ){
|
||||
scene.traverse( (m) => {
|
||||
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
|
||||
})
|
||||
}
|
||||
src.traverse( (m) => {
|
||||
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
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -153,72 +147,6 @@ xrf.frag.src.type = {}
|
|||
|
||||
xrf.frag.src.type['unknown'] = function( url, opts ){
|
||||
return new Promise( (resolve,reject) => {
|
||||
reject(`${url} mimetype not supported (yet)`)
|
||||
reject(`${url} mimetype '${opts.mimetype}' not found or supported (yet)`)
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* mimetype: model/gltf+json
|
||||
*/
|
||||
|
||||
xrf.frag.src.type['gltf'] = function( url, opts ){
|
||||
return new Promise( (resolve,reject) => {
|
||||
let {mesh,src} = opts
|
||||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||
let loader
|
||||
|
||||
const Loader = xrf.loaders[ext]
|
||||
if( !Loader ) throw 'xrfragment: no loader passed to xrfragment for extension .'+ext
|
||||
if( !dir.match("://") ){ // force relative path
|
||||
dir = dir[0] == './' ? dir : `./${dir}`
|
||||
loader = new Loader().setPath( dir )
|
||||
}else loader = new Loader()
|
||||
|
||||
loader.load(url, (model) => {
|
||||
resolve(model)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* mimetype: image/png
|
||||
* mimetype: image/jpg
|
||||
* mimetype: image/gif
|
||||
*/
|
||||
|
||||
xrf.frag.src.type['image/png'] = function(url,opts){
|
||||
let {mesh} = opts
|
||||
let restrictTo3DBoundingBox = mesh.geometry
|
||||
const texture = new THREE.TextureLoader().load( url );
|
||||
texture.colorSpace = THREE.SRGBColorSpace;
|
||||
|
||||
//const geometry = new THREE.BoxGeometry();
|
||||
const material = new THREE.MeshBasicMaterial({
|
||||
map: texture,
|
||||
transparent: url.match(/(png|gif)/) ? true : false,
|
||||
side: THREE.DoubleSide,
|
||||
color: 0xFFFFFF,
|
||||
opacity:1
|
||||
});
|
||||
|
||||
// stretch image by pinning uv-coordinates to corners
|
||||
if( mesh.geometry ){
|
||||
if( mesh.geometry.attributes.uv ){ // buffergeometries
|
||||
let uv = mesh.geometry.attributes.uv;
|
||||
// i u v
|
||||
uv.setXY(0, 0, 0 )
|
||||
uv.setXY(1, 1, 0 )
|
||||
uv.setXY(2, 0, 1 )
|
||||
uv.setXY(3, 1, 1 )
|
||||
}else {
|
||||
console.warn("xrfragment: uv's of ${url} might be off for non-buffer-geometries *TODO*")
|
||||
//if( geometry.faceVertexUvs ){
|
||||
// *TODO* force uv's of dynamically created geometries (in threejs)
|
||||
//}
|
||||
}
|
||||
}
|
||||
mesh.material = material
|
||||
}
|
||||
xrf.frag.src.type['image/gif'] = xrf.frag.src.type['image/png']
|
||||
xrf.frag.src.type['image/jpg'] = xrf.frag.src.type['image/png']
|
||||
|
||||
|
|
|
|||
83
src/3rd/js/three/xrf/src/audio.js
Normal file
83
src/3rd/js/three/xrf/src/audio.js
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* mimetype: audio/aac
|
||||
* mimetype: audio/mpeg
|
||||
* mimetype: audio/ogg
|
||||
* mimetype: audio/weba
|
||||
* mimetype: audio/wav
|
||||
*/
|
||||
|
||||
let loadAudio = (mimetype) => function(url,opts){
|
||||
let {mesh,src,camera,THREE} = opts
|
||||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||
let frag = xrf.URI.parse( url )
|
||||
|
||||
/* WebAudio: setup context via THREEjs */
|
||||
if( !camera.listener ){
|
||||
camera.listener = new THREE.AudioListener();
|
||||
// *FIXME* camera vs camerarig conflict
|
||||
(camera.getCam ? camera.getCam() : camera).add( camera.listener );
|
||||
}
|
||||
|
||||
let isPositionalAudio = !(mesh.position.x == 0 && mesh.position.y == 0 && mesh.position.z == 0)
|
||||
const audioLoader = new THREE.AudioLoader();
|
||||
let sound = isPositionalAudio ? new THREE.PositionalAudio( camera.listener)
|
||||
: new THREE.Audio( camera.listener )
|
||||
|
||||
audioLoader.load( url.replace(/#.*/,''), function( buffer ) {
|
||||
|
||||
sound.setBuffer( buffer );
|
||||
sound.setLoop(false);
|
||||
sound.setVolume(1.0);
|
||||
if( isPositionalAudio ){
|
||||
sound.setRefDistance( mesh.scale.x);
|
||||
sound.setRolloffFactor(20.0)
|
||||
//sound.setDirectionalCone( 360, 360, 0.01 );
|
||||
}
|
||||
|
||||
sound.playXRF = (t) => {
|
||||
mesh.add(sound)
|
||||
try{
|
||||
if( sound.isPlaying && t.y != undefined ) sound.stop()
|
||||
if( sound.isPlaying && t.y == undefined ) sound.pause()
|
||||
|
||||
let hardcodedLoop = frag.t != undefined
|
||||
t = hardcodedLoop ? { ...frag.t, x: t.x} : t // override with hardcoded metadata except playstate (x)
|
||||
if( t && t.x != 0 ){
|
||||
// *TODO* https://stackoverflow.com/questions/12484052/how-can-i-reverse-playback-in-web-audio-api-but-keep-a-forward-version-as-well
|
||||
t.x = Math.abs(t.x)
|
||||
sound.setPlaybackRate( t.x ) // WebAudio does not support negative playback
|
||||
// setting loop
|
||||
if( t.z ) sound.setLoop( true )
|
||||
// apply embedded audio/video samplerate/fps or global mixer fps
|
||||
let loopStart = hardcodedLoop ? t.y : t.y * buffer.sampleRate;
|
||||
let loopEnd = hardcodedLoop ? t.z : t.z * buffer.sampleRate;
|
||||
let timeStart = loopStart > 0 ? loopStart : (t.y == undefined ? xrf.model.mixer.time : t.y)
|
||||
|
||||
if( t.z > 0 ) sound.setLoopEnd( loopEnd )
|
||||
if( t.y != undefined ){
|
||||
sound.setLoopStart( loopStart )
|
||||
sound.offset = loopStart
|
||||
}
|
||||
sound.play()
|
||||
}
|
||||
}catch(e){ console.warn(e) }
|
||||
}
|
||||
mesh.audio = sound
|
||||
});
|
||||
}
|
||||
|
||||
let audioMimeTypes = [
|
||||
'audio/wav',
|
||||
'audio/mpeg',
|
||||
'audio/mp3',
|
||||
'audio/weba',
|
||||
'audio/aac',
|
||||
'application/ogg'
|
||||
]
|
||||
audioMimeTypes.map( (mimetype) => xrf.frag.src.type[ mimetype ] = loadAudio(mimetype) )
|
||||
|
||||
// listen to t XR fragment changes
|
||||
xrf.addEventListener('t', (opts) => {
|
||||
let t = opts.frag.t
|
||||
xrf.scene.traverse( (n) => n.audio && n.audio.playXRF && (n.audio.playXRF(t)) )
|
||||
})
|
||||
23
src/3rd/js/three/xrf/src/gltf.js
Normal file
23
src/3rd/js/three/xrf/src/gltf.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* mimetype: model/gltf+json
|
||||
*/
|
||||
|
||||
xrf.frag.src.type['gltf'] = function( url, opts ){
|
||||
return new Promise( (resolve,reject) => {
|
||||
let {mesh,src} = opts
|
||||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||
let loader
|
||||
|
||||
const Loader = xrf.loaders[ext]
|
||||
if( !Loader ) throw 'xrfragment: no loader passed to xrfragment for extension .'+ext
|
||||
if( !dir.match("://") ){ // force relative path
|
||||
dir = dir[0] == './' ? dir : `./${dir}`
|
||||
loader = new Loader().setPath( dir )
|
||||
}else loader = new Loader()
|
||||
|
||||
loader.load(url, (model) => {
|
||||
resolve(model)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
12
src/3rd/js/three/xrf/src/html.js
Normal file
12
src/3rd/js/three/xrf/src/html.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
let loadHTML = (mimetype) => function(url,opts){
|
||||
let {mesh,src,camera} = opts
|
||||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||
let frag = xrf.URI.parse( url )
|
||||
console.warn("todo: html viewer for src not implemented")
|
||||
}
|
||||
|
||||
let htmlMimeTypes = [
|
||||
'text/html'
|
||||
]
|
||||
htmlMimeTypes.map( (mimetype) => xrf.frag.src.type[ mimetype ] = loadHTML(mimetype) )
|
||||
50
src/3rd/js/three/xrf/src/image.js
Normal file
50
src/3rd/js/three/xrf/src/image.js
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* mimetype: image/png
|
||||
* mimetype: image/jpg
|
||||
* mimetype: image/gif
|
||||
*/
|
||||
|
||||
xrf.frag.src.type['image/png'] = function(url,opts){
|
||||
let {mesh,THREE} = opts
|
||||
let restrictTo3DBoundingBox = mesh.geometry
|
||||
|
||||
mesh.material = new xrf.THREE.MeshBasicMaterial({
|
||||
map: null,
|
||||
transparent: url.match(/(png|gif)/) ? true : false,
|
||||
side: THREE.DoubleSide,
|
||||
color: 0xFFFFFF,
|
||||
opacity:1
|
||||
});
|
||||
|
||||
let renderImage = (texture) => {
|
||||
let img = {w: texture.source.data.width, h: texture.source.data.height}
|
||||
|
||||
// stretch image by pinning uv-coordinates to corners
|
||||
if( mesh.geometry ){
|
||||
if( mesh.geometry.attributes.uv ){ // buffergeometries
|
||||
let uv = mesh.geometry.attributes.uv;
|
||||
}else {
|
||||
console.warn("xrfragment: uv's of ${url} might be off for non-buffer-geometries *TODO*")
|
||||
//if( geometry.faceVertexUvs ){
|
||||
// *TODO* force uv's of dynamically created geometries (in threejs)
|
||||
//}
|
||||
}
|
||||
}
|
||||
mesh.material.map = texture
|
||||
mesh.needsUpdate = true
|
||||
}
|
||||
|
||||
let onLoad = (texture) => {
|
||||
texture.colorSpace = THREE.SRGBColorSpace;
|
||||
texture.wrapS = THREE.RepeatWrapping;
|
||||
texture.wrapT = THREE.RepeatWrapping;
|
||||
renderImage(texture)
|
||||
}
|
||||
|
||||
new THREE.TextureLoader().load( url, onLoad, null, console.error );
|
||||
|
||||
}
|
||||
|
||||
xrf.frag.src.type['image/gif'] = xrf.frag.src.type['image/png']
|
||||
xrf.frag.src.type['image/jpeg'] = xrf.frag.src.type['image/png']
|
||||
|
||||
197
src/3rd/js/three/xrf/src/non-euclidian.js
Normal file
197
src/3rd/js/three/xrf/src/non-euclidian.js
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
// spec 8: https://xrfragment.org/doc/RFC_XR_Macros.html#embedding-xr-content-using-src
|
||||
|
||||
xrf.portalNonEuclidian = function(opts){
|
||||
let { frag, mesh, model, camera, scene, renderer} = opts
|
||||
|
||||
|
||||
mesh.portal = {
|
||||
pos: mesh.position.clone(),
|
||||
posWorld: new xrf.THREE.Vector3(),
|
||||
posWorldCamera: new xrf.THREE.Vector3(),
|
||||
stencilRef: xrf.portalNonEuclidian.stencilRef,
|
||||
needUpdate: false,
|
||||
stencilObject: false,
|
||||
cameraDirection: new THREE.Vector3(),
|
||||
cameraPosition: new THREE.Vector3(),
|
||||
raycaster: new THREE.Raycaster(),
|
||||
isLocal: opts.isLocal,
|
||||
isLens: false,
|
||||
isInside: false,
|
||||
setStencil: (stencilRef) => mesh.portal.stencilObjects.traverse( (n) => showPortal(n, stencilRef == 0) && n.stencil && n.stencil(stencilRef) ),
|
||||
positionObjectsIfNeeded: (pos,scale) => !mesh.portal.isLens && mesh.portal.stencilObjects.traverse( (n) => n.positionAtStencil && (n.positionAtStencil(pos,scale)) )
|
||||
}
|
||||
|
||||
// allow objects to flip between original and stencil position (which puts them behind stencilplane)
|
||||
const addStencilFeature = (n) => {
|
||||
if( n.stencil ) return n // run once
|
||||
|
||||
n.stencil = (sRef ) => xrf.portalNonEuclidian.selectStencil(n, sRef )
|
||||
n.positionAtStencil = (pos,scale) => (newPos,newScale) => {
|
||||
n.position.copy( newPos || pos )
|
||||
n.scale.copy( scale )
|
||||
n.updateMatrixWorld(true)
|
||||
}
|
||||
// curry function
|
||||
n.positionAtStencil = n.positionAtStencil( n.position.clone(), n.scale.clone() )
|
||||
return n
|
||||
}
|
||||
|
||||
this.setupStencilObjects = (scene,opts) => {
|
||||
// collect related objects to render inside stencilplane
|
||||
let stencilObject = scene
|
||||
if( opts.srcFrag.target ){
|
||||
stencilObject = scene.getObjectByName( opts.srcFrag.target.key )
|
||||
// spec: if src-object is child of portal (then portal is lens, and should include all children )
|
||||
mesh.traverse( (n) => n.name == opts.srcFrag.target.key && (stencilObject = n) && (mesh.portal.isLens = true) )
|
||||
}
|
||||
|
||||
if( !stencilObject ) return console.warn(`no objects were found (src:${mesh.userData.src}) for (portal)object name '${mesh.name}'`)
|
||||
mesh.portal.stencilObject = stencilObject
|
||||
|
||||
// spec: if src points to child, act as lens
|
||||
if( !mesh.portal.isLocal || mesh.portal.isLens ) stencilObject.visible = false
|
||||
|
||||
let stencilObjects = [stencilObject]
|
||||
stencilObjects = stencilObjects
|
||||
.filter( (n) => !n.portal ) // filter out (self)references to portals (prevent recursion)
|
||||
.map(addStencilFeature)
|
||||
|
||||
// put it into a scene (without .add() because it reparents objects) so we can render it separately
|
||||
mesh.portal.stencilObjects = new xrf.THREE.Scene()
|
||||
mesh.portal.stencilObjects.children = stencilObjects
|
||||
|
||||
xrf.portalNonEuclidian.stencilRef += 1 // each portal has unique stencil id
|
||||
console.log(`enabling portal for object '${mesh.name}' (stencilRef:${mesh.portal.stencilRef})`)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
// enable the stencil-material of the stencil objects to prevent stackoverflow (portal in portal rendering)
|
||||
const showPortal = (n,show) => {
|
||||
if( n.portal ) n.visible = show
|
||||
return true
|
||||
}
|
||||
|
||||
this.setupListeners = () => {
|
||||
|
||||
mesh.onAfterRender = function(renderer, scene, camera, geometry, material, group ){
|
||||
mesh.portal.needUpdate = true
|
||||
}
|
||||
|
||||
xrf.addEventListener('renderPost', (opts) => {
|
||||
let {scene,camera,time,render,renderer} = opts
|
||||
|
||||
if( mesh.portal.needUpdate && mesh.portal && mesh.portal.stencilObjects ){
|
||||
let cameraDirection = mesh.portal.cameraDirection
|
||||
let cameraPosition = mesh.portal.cameraPosition
|
||||
let stencilRef = mesh.portal.stencilRef
|
||||
let newPos = mesh.portal.posWorld
|
||||
let stencilObject = mesh.portal.stencilObject
|
||||
let newScale = mesh.scale
|
||||
let raycaster = mesh.portal.raycaster
|
||||
|
||||
let cam = xrf.camera.getCam ? xrf.camera.getCam() : camera
|
||||
cam.getWorldPosition(cameraPosition)
|
||||
cam.getWorldDirection(cameraDirection)
|
||||
if( cameraPosition.distanceTo(newPos) > 20.0 ) return // dont render far portals
|
||||
|
||||
// init
|
||||
if( !mesh.portal.isLocal || mesh.portal.isLens ) stencilObject.visible = true
|
||||
mesh.portal.setStencil(stencilRef)
|
||||
renderer.autoClear = false
|
||||
renderer.autoClearDepth = false
|
||||
renderer.autoClearColor = false
|
||||
renderer.autoClearStencil = false
|
||||
// render
|
||||
render( mesh.portal.stencilObjects, camera )
|
||||
// de-init
|
||||
renderer.autoClear = true
|
||||
renderer.autoClearDepth = true
|
||||
renderer.autoClearColor = true
|
||||
renderer.autoClearStencil = true
|
||||
mesh.portal.setStencil(0)
|
||||
if( !mesh.portal.isLocal || mesh.portal.isLens ) stencilObject.visible = false
|
||||
|
||||
|
||||
// trigger href upon camera collide
|
||||
if( mesh.userData.XRF.href ){
|
||||
raycaster.far = 0.35
|
||||
raycaster.set(cameraPosition, cameraDirection )
|
||||
intersects = raycaster.intersectObjects([mesh], false)
|
||||
if (intersects.length > 0 && !mesh.portal.teleporting ){
|
||||
mesh.portal.teleporting = true
|
||||
mesh.userData.XRF.href.exec({nocommit:true})
|
||||
setTimeout( () => mesh.portal.teleporting = false, 500) // dont flip back and forth
|
||||
}
|
||||
}
|
||||
}
|
||||
mesh.portal.needUpdate = false
|
||||
})
|
||||
|
||||
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
// turn mesh into stencilplane
|
||||
xrf
|
||||
.portalNonEuclidian
|
||||
.setMaterial(mesh)
|
||||
.getWorldPosition(mesh.portal.posWorld)
|
||||
|
||||
this
|
||||
.setupListeners()
|
||||
.setupStencilObjects(scene,opts)
|
||||
|
||||
// move portal objects to portalposition
|
||||
if( mesh.portal.stencilObjects ) mesh.portal.positionObjectsIfNeeded(mesh.portal.posWorld, mesh.scale)
|
||||
}
|
||||
|
||||
xrf.portalNonEuclidian.selectStencil = (n, stencilRef, nested) => {
|
||||
if( n.material ){
|
||||
n.material.stencilRef = stencilRef
|
||||
n.material.stencilWrite = stencilRef > 0
|
||||
n.material.stencilFunc = xrf.THREE.EqualStencilFunc;
|
||||
}
|
||||
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: 'orange' });
|
||||
mesh.material.depthWrite = false;
|
||||
mesh.material.colorWrite = false;
|
||||
mesh.material.stencilWrite = true;
|
||||
mesh.material.stencilRef = xrf.portalNonEuclidian.stencilRef;
|
||||
// mesh.renderOrder = 0;//xrf.portalNonEuclidian.stencilRef;
|
||||
mesh.material.stencilFunc = xrf.THREE.AlwaysStencilFunc;
|
||||
mesh.material.stencilZPass = xrf.THREE.ReplaceStencilOp;
|
||||
mesh.material.stencilZFail = xrf.THREE.ReplaceStencilOp;
|
||||
//n.material.depthFunc = stencilRef > 0 ? xrf.THREE.AlwaysDepth : xrf.THREE.LessEqualDepth
|
||||
//mesh.material.depthTest = false;
|
||||
return mesh
|
||||
}
|
||||
|
||||
xrf.addEventListener('parseModel',(opts) => {
|
||||
const scene = opts.model.scene
|
||||
//for( let i in scene.children ) scene.children[i].renderOrder = 10 // render outer layers last (worldspheres e.g.)
|
||||
})
|
||||
|
||||
|
||||
// (re)set portalObjects when entering/leaving a portal
|
||||
let updatePortals = (opts) => {
|
||||
xrf.scene.traverse( (n) => {
|
||||
if( !n.portal ) return
|
||||
// move objects back to the portal
|
||||
if( n.portal.isInside ) n.portal.positionObjectsIfNeeded( n.portal.posWorld, n.scale )
|
||||
n.portal.isInside = false
|
||||
})
|
||||
if( opts.mesh && opts.mesh.portal && opts.click ){
|
||||
opts.mesh.portal.isInside = true
|
||||
opts.mesh.portal.positionObjectsIfNeeded() // move objects back to original pos (since we are teleporting there)
|
||||
}
|
||||
}
|
||||
|
||||
xrf.addEventListener('href', (opts) => opts.click && updatePortals(opts) )
|
||||
xrf.addEventListener('navigate', updatePortals )
|
||||
|
||||
xrf.portalNonEuclidian.stencilRef = 1
|
||||
47
src/3rd/js/three/xrf/src/video.js
Normal file
47
src/3rd/js/three/xrf/src/video.js
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
|
||||
let loadVideo = (mimetype) => function(url,opts){
|
||||
let {mesh,src,camera} = opts
|
||||
let {urlObj,dir,file,hash,ext} = xrf.parseUrl(url)
|
||||
const THREE = xrf.THREE
|
||||
let frag = xrf.URI.parse( url )
|
||||
|
||||
let video = mesh.video = document.createElement('video')
|
||||
video.setAttribute("crossOrigin","anonymous")
|
||||
video.setAttribute("playsinline",'')
|
||||
video.addEventListener('loadedmetadata', function(){
|
||||
let texture = new THREE.VideoTexture( video );
|
||||
texture.colorSpace = THREE.SRGBColorSpace;
|
||||
let mat = new xrf.THREE.MeshBasicMaterial()
|
||||
mat.map = texture
|
||||
mesh.material = mat
|
||||
// set range
|
||||
//video.addEventListener('timeupdate', function timeupdate() {
|
||||
// if (frag.t && video.currentTime < frag.t.y || video.currentTime >= frag.t.z ) {
|
||||
// video.currentTime = frag.t.y
|
||||
// }
|
||||
//},false)
|
||||
})
|
||||
|
||||
video.src = url
|
||||
video.playXRF = (t) => {
|
||||
video.t = t
|
||||
if( t.x == 0 ) video.pause()
|
||||
else{
|
||||
video.playbackRate = Math.abs( t.x ) // html5 video does not support reverseplay :/
|
||||
video.play()
|
||||
}
|
||||
if( t.y != undefined ) video.time = t.y
|
||||
}
|
||||
}
|
||||
|
||||
let videoMimeTypes = [
|
||||
'video/ogg',
|
||||
'video/mp4'
|
||||
]
|
||||
videoMimeTypes.map( (mimetype) => xrf.frag.src.type[ mimetype ] = loadVideo(mimetype) )
|
||||
|
||||
// listen to t XR fragment changes
|
||||
xrf.addEventListener('t', (opts) => {
|
||||
let t = opts.frag.t
|
||||
xrf.scene.traverse( (n) => n.video && (n.video.playXRF(t)) )
|
||||
})
|
||||
|
|
@ -1,46 +1,163 @@
|
|||
xrf.frag.t = function(v, opts){
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
console.log(` └ setting animation loop to ${v.x} ${v.y} ${v.z}` )
|
||||
if( !model.mixer ) return
|
||||
if( !model.animations || model.animations[0] == undefined ) return console.warn('no animation in scene')
|
||||
|
||||
model.mixer.t = v
|
||||
let duration = model.animations[0].duration
|
||||
let frames = model.animations[0].tracks[0].times.length
|
||||
let mixer = model.mixer
|
||||
mixer.loop = mixer.loop || {frameStart:0,frameStop:99999999,speed: 1}
|
||||
let fps = frames / duration
|
||||
xrf.mixers.map ( (mixer) => {
|
||||
|
||||
mixer.t = v
|
||||
|
||||
// update speed
|
||||
mixer.timeScale = mixer.loop.speed = v.x
|
||||
mixer.loop.speedAbs = Math.abs(v.x)
|
||||
|
||||
mixer.loop.speed = v.x
|
||||
mixer.loop.speedAbs = Math.abs(v.x)
|
||||
mixer.loop.frameStart = v.y || mixer.loop.frameStart
|
||||
mixer.loop.frameStop = v.z || mixer.loop.frameStop
|
||||
// always recalculate time using frameStart/Stop
|
||||
mixer.loop.timeStart = mixer.loop.frameStart / (fps * mixer.loop.speedAbs)
|
||||
mixer.loop.timeStop = mixer.loop.frameStop / (fps * mixer.loop.speedAbs)
|
||||
|
||||
// update speed
|
||||
mixer.timeScale = mixer.loop.speed
|
||||
if( v.y != undefined || v.z != undefined ) mixer.updateLoop( v )
|
||||
|
||||
let updateTime = (time) => {
|
||||
mixer.setTime(time)
|
||||
mixer.time = Math.abs(mixer.time)
|
||||
mixer.update(0) // (forgetting) this little buddy costed me lots of time :]
|
||||
// play animations
|
||||
mixer.play( v )
|
||||
})
|
||||
}
|
||||
|
||||
xrf.frag.t.default = {
|
||||
x:0, // (play from) offset (in seconds)
|
||||
y:0 // optional: (stop at) offset (in seconds)
|
||||
}
|
||||
|
||||
// setup animation mixer for global scene & src scenes
|
||||
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}
|
||||
mixer.i = xrf.mixers.length
|
||||
mixer.actions = []
|
||||
|
||||
model.animations.map( (anim) => {
|
||||
anim.optimize()
|
||||
console.log("action: "+anim.name)
|
||||
mixer.actions.push( mixer.clipAction( anim, model.scene ) )
|
||||
})
|
||||
|
||||
|
||||
mixer.checkZombies = (animations) => {
|
||||
if( mixer.zombieCheck ) return // fire only once
|
||||
animations.map( (anim) => {
|
||||
// collect zombie animations and warn user
|
||||
let zombies = anim.tracks.map( (t) => {
|
||||
let name = t.name.replace(/\..*/,'')
|
||||
let obj = model.scene.getObjectByName(name)
|
||||
return !model.scene.getObjectByName(name) ? {anim:anim.name,obj:name} : undefined
|
||||
})
|
||||
if( zombies.length > 0 && mixer.i == 0 ){ // only warn for zombies in main scene (because src-scenes might be filtered anyways)
|
||||
zombies
|
||||
.filter( (z) => z ) // filter out undefined
|
||||
.map( (z) => console.warn(`gltf: object '${z.obj}' not found (anim: '${z.anim}'`) )
|
||||
console.warn(`TIP: remove dots in objectnames in blender (which adds dots when duplicating)`)
|
||||
}
|
||||
})
|
||||
mixer.zombieCheck = true
|
||||
}
|
||||
|
||||
if( v.y > 0 || v.z > 0 ) updateTime( mixer.loop.timeStart )
|
||||
mixer.play = (t) => {
|
||||
mixer.isPlaying = t.x != 0
|
||||
mixer.updateLoop(t)
|
||||
xrf.emit( mixer.isPlaying === false ? 'stop' : 'play',{isPlaying: mixer.isPlaying})
|
||||
}
|
||||
|
||||
mixer.stop = () => {
|
||||
mixer.play(false)
|
||||
}
|
||||
|
||||
mixer.updateLoop = (t) => {
|
||||
mixer.loop.timeStart = t.y != undefined ? t.y : mixer.loop.timeStart
|
||||
mixer.loop.timeStop = t.z != undefined ? t.z : mixer.loop.timeStop
|
||||
mixer.actions.map( (action) => {
|
||||
if( mixer.loop.timeStart != undefined ){
|
||||
action.time = mixer.loop.timeStart
|
||||
action.setLoop( THREE.LoopOnce, )
|
||||
action.timeScale = mixer.timeScale
|
||||
action.enabled = true
|
||||
if( t.x != 0 ){
|
||||
action.play()
|
||||
}
|
||||
}
|
||||
})
|
||||
mixer.setTime(mixer.loop.timeStart)
|
||||
mixer.time = Math.abs( mixer.loop.timeStart )
|
||||
mixer.update(0)
|
||||
mixer.checkZombies( model.animations)
|
||||
}
|
||||
|
||||
// update loop when needed
|
||||
if( !mixer.update.patched ){
|
||||
let update = mixer.update
|
||||
mixer.update = function(time){
|
||||
mixer.time = Math.abs(mixer.time)
|
||||
if( time == 0 ) return update.call(mixer,time)
|
||||
if( time == 0 ) return update.call(this,time)
|
||||
|
||||
if( mixer.loop.speed > 0.0 && mixer.time > mixer.loop.timeStop * mixer.loop.speedAbs ){
|
||||
setTimeout( (time) => updateTime(time),0,mixer.loop.timeStart) // prevent recursion
|
||||
// loop jump
|
||||
if( mixer.loop.speed > 0.0 && (mixer.loop.timeStop > 0 && mixer.time > mixer.loop.timeStop) ){
|
||||
setTimeout( (time,anims) => mixer.updateLoop(time), 0, mixer.loop.timeStart ) // prevent recursion
|
||||
}
|
||||
return update.call( mixer, time )
|
||||
return update.call( this, time )
|
||||
}
|
||||
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)
|
||||
})
|
||||
|
||||
if( document.location.hash.match(/t=/) ){
|
||||
let url = document.location.href
|
||||
let playAfterUserGesture = () => {
|
||||
xrf.hashbus.pub(url) // re-post t fragment on the hashbus again
|
||||
window.removeEventListener('click',playAfterUserGesture)
|
||||
window.removeEventListener('touchstart',playAfterUserGesture)
|
||||
}
|
||||
window.addEventListener('click', playAfterUserGesture )
|
||||
window.addEventListener('touchstart', playAfterUserGesture )
|
||||
}
|
||||
|
||||
xrf.addEventListener('render', (opts) => {
|
||||
let model = xrf.model
|
||||
let {time} = opts
|
||||
if( !model ) return
|
||||
if( xrf.mixers.length ){
|
||||
xrf.mixers.map( (m) => m.isPlaying && (m.update( time )) )
|
||||
|
||||
// update active camera in case selected by dynamicKey in URI
|
||||
if( xrf.model.camera && model.mixer.isPlaying ){
|
||||
|
||||
let cam = xrf.camera.getCam()
|
||||
// cam.fov = model.cameras[0].fov (why is blender not exporting radians?)
|
||||
cam.far = model.cameras[0].far
|
||||
cam.near = model.cameras[0].near
|
||||
|
||||
let rig = xrf.camera
|
||||
rig.position.copy( model.cameras[0].position )
|
||||
rig.position.y -= rig.offsetY // VR/AR compensate camera rig
|
||||
//rig.rotation.copy( model.cameras[0].rotation )
|
||||
|
||||
rig.updateProjectionMatrix()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
xrf.addEventListener('dynamicKey', (opts) => {
|
||||
// select active camera if any
|
||||
let {id,match,v} = opts
|
||||
match.map( (w) => {
|
||||
w.nodes.map( (node) => {
|
||||
if( node.isCamera ){
|
||||
console.log("setting camera to "+node.name)
|
||||
xrf.model.camera = node
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
xrf.addEventListener('env', (opts) => {
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
if( frag.env && !scene.environment ){
|
||||
let env = scene.getObjectByName(frag.env.string)
|
||||
if( !env ) env = xrf.scene.getObjectByName(frag.env.string) // repurpose from parent scene
|
||||
if( !env ) return console.warn("xrf.env "+frag.env.string+" not found")
|
||||
env.material.map.mapping = THREE.EquirectangularReflectionMapping;
|
||||
scene.environment = env.material.map
|
||||
//let env = scene.getObjectByName(frag.env.string)
|
||||
//if( !env ) env = xrf.scene.getObjectByName(frag.env.string) // repurpose from parent scene
|
||||
//if( !env ) return console.warn("xrf.env "+frag.env.string+" not found")
|
||||
//env.material.map.mapping = THREE.EquirectangularReflectionMapping;
|
||||
//scene.environment = env.material.map
|
||||
//scene.texture = env.material.map
|
||||
renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
||||
renderer.toneMappingExposure = 2;
|
||||
// renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
||||
// renderer.toneMappingExposure = 2;
|
||||
console.log(` └ applied image '${frag.env.string}' as environment map`)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
xrf.macros = {}
|
||||
|
||||
xrf.addEventListener('mesh', (opts) => {
|
||||
xrf.addEventListener('frag2mesh', (opts) => {
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE, hashbus} = opts
|
||||
|
||||
for( let k in frag ){
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
xrf.addEventListener('pos', (opts) => {
|
||||
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
|
||||
if( frag.pos && frag.q ){
|
||||
// apply roundrobin (if any)
|
||||
if( v.args ) v = v.args[ xrf.roundrobin(v,model) ]
|
||||
//if( frag.pos && frag.q ){
|
||||
// // apply roundrobin (if any)
|
||||
// if( v.args ) v = v.args[ xrf.roundrobin(v,model) ]
|
||||
|
||||
frag.q.getObjects().map( (o) => {
|
||||
// if object has no parent (name == 'Scene') use absolute positioning, otherwise relative to parent
|
||||
o.position.x = o.parent.name == 'Scene' ? v.x : o.positionOriginal.x + v.x
|
||||
o.position.y = o.parent.name == 'Scene' ? v.z : o.positionOriginal.y + v.z
|
||||
o.position.z = o.parent.name == 'Scene' ? v.y : o.positionOriginal.z + v.y
|
||||
})
|
||||
}
|
||||
// frag.q.getObjects().map( (o) => {
|
||||
// // if object has no parent (name == 'Scene') use absolute positioning, otherwise relative to parent
|
||||
// o.position.x = o.parent.name == 'Scene' ? v.x : o.positionOriginal.x + v.x
|
||||
// o.position.y = o.parent.name == 'Scene' ? v.z : o.positionOriginal.y + v.z
|
||||
// o.position.z = o.parent.name == 'Scene' ? v.y : o.positionOriginal.z + v.y
|
||||
// })
|
||||
//}
|
||||
})
|
||||
|
|
|
|||
167
src/Test.hx
167
src/Test.hx
|
|
@ -1,4 +1,4 @@
|
|||
import xrfragment.Query;
|
||||
import xrfragment.Filter;
|
||||
import xrfragment.URI;
|
||||
import xrfragment.XRF;
|
||||
|
||||
|
|
@ -15,42 +15,50 @@ class Test {
|
|||
static var errors:Int = 0;
|
||||
|
||||
static public function main():Void {
|
||||
test( Spec.load("src/spec/url.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( "url.json", Spec.load("src/spec/url.json") );
|
||||
test( "pos.json", Spec.load("src/spec/pos.json") );
|
||||
test( "t.json", Spec.load("src/spec/t.json") );
|
||||
test( "filter.selectors.json", Spec.load("src/spec/filter.selectors.json") );
|
||||
//test( Spec.load("src/spec/tmp.json") );
|
||||
if( errors > 1 ) trace("\n-----\n[ ❌] "+errors+" errors :/");
|
||||
}
|
||||
|
||||
static public function test(spec:Array<Dynamic>):Void {
|
||||
var Query = xrfragment.Query;
|
||||
static public function test( topic:String, spec:Array<Dynamic>):Void {
|
||||
trace("\n[.] running "+topic);
|
||||
var Filter = xrfragment.Filter;
|
||||
for( i in 0...spec.length ){
|
||||
var q:Query = null;
|
||||
var f:Filter = null;
|
||||
var res:haxe.DynamicAccess<Dynamic> = null;
|
||||
var valid:Bool = false;
|
||||
var item:Dynamic = spec[i];
|
||||
if( item.fn == "query" ) q = new Query(item.data);
|
||||
if( item.fn == "url" ) res = URI.parse(item.data,0);
|
||||
if( item.expect.fn == "test" ) valid = item.expect.out == q.test( item.expect.input[0] );
|
||||
if( item.expect.fn == "testProperty" ) valid = item.expect.out == q.testProperty( item.expect.input[0], item.expect.input[1] );
|
||||
if( item.expect.fn == "testPropertyExclude" ) valid = item.expect.out == q.testProperty( item.expect.input[0], item.expect.input[1], true );
|
||||
f = new Filter(item.data);
|
||||
res = URI.parse(item.data,null);
|
||||
if( item.expect.fn == "test" ) valid = item.expect.out == f.test( item.expect.input[0] );
|
||||
if( item.expect.fn == "testProperty" ) valid = item.expect.out == f.testProperty( item.expect.input[0], item.expect.input[1] );
|
||||
if( item.expect.fn == "testPropertyInt" ) valid = item.expect.out == f.testProperty( item.expect.input[0], item.expect.input[1] );
|
||||
if( item.expect.fn == "testPropertyExclude" ) valid = item.expect.out == f.testProperty( item.expect.input[0], item.expect.input[1], true );
|
||||
if( item.expect.fn == "testParsed" ) valid = item.expect.out == res.exists(item.expect.input);
|
||||
if( item.expect.fn == "testPredefinedView" ) valid = res.exists(item.expect.input) && item.expect.out == res.get(item.expect.input).is( XRF.PV_EXECUTE) ;
|
||||
if( item.expect.fn == "testPropertyAssign" ) valid = res.exists(item.expect.input) && item.expect.out == res.get(item.expect.input).is( XRF.PROP_BIND) ;
|
||||
if( item.expect.fn == "testBrowserOverride" ) valid = item.expect.out == (URI.parse(item.data,XRF.NAVIGATOR)).exists(item.expect.input);
|
||||
if( item.expect.fn == "testEmbedOverride" ) valid = item.expect.out == (URI.parse(item.data,XRF.METADATA)).exists(item.expect.input);
|
||||
if( item.expect.fn == "equal.string" ) valid = res.get(item.expect.input) && item.expect.out == res.get(item.expect.input).string;
|
||||
if( item.expect.fn == "equal.x" ) valid = equalX(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.multi" ) valid = equalMulti(res, item);
|
||||
if( item.expect.fn == "testQueryRoot" ) valid = item.expect.out == q.get()[ item.expect.input[0] ].root;
|
||||
if( item.expect.fn == "testFilterRoot" ) valid = res.exists(item.expect.input[0]) && res.get(item.expect.input[0]).filter.get().root == item.expect.out;
|
||||
if( item.expect.fn == "testFilterDeep" ) valid = res.exists(item.expect.input[0]) && res.get(item.expect.input[0]).filter.get().deep == item.expect.out;
|
||||
var ok:String = valid ? "[ ✔ ] " : "[ ❌] ";
|
||||
trace( ok + item.fn + ": '" + item.data + "'" + (item.label ? " (" + (item.label?item.label:item.expect.fn) +")" : ""));
|
||||
if( !valid ) errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static public function equalX(res:haxe.DynamicAccess<Dynamic>, item:Dynamic):Bool {
|
||||
if( !item.expect.out && !res.get(item.expect.input) ) return true;
|
||||
else return res.get(item.expect.input) && item.expect.out == (Std.string(res.get(item.expect.input).x) );
|
||||
}
|
||||
|
||||
static public function equalXY(res:haxe.DynamicAccess<Dynamic>, item:Dynamic):Bool {
|
||||
if( !item.expect.out && !res.get(item.expect.input) ) return true;
|
||||
else return res.get(item.expect.input) && item.expect.out == (Std.string(res.get(item.expect.input).x) +","+ Std.string(res.get(item.expect.input).y) );
|
||||
|
|
@ -61,17 +69,6 @@ class Test {
|
|||
else return res.get(item.expect.input) && item.expect.out == (Std.string(res.get(item.expect.input).x) +","+ Std.string(res.get(item.expect.input).y)+","+ Std.string(res.get(item.expect.input).z));
|
||||
}
|
||||
|
||||
static public function equalMulti(res:haxe.DynamicAccess<Dynamic>, item:Dynamic):Bool {
|
||||
var target:Dynamic = res.get(item.expect.input);
|
||||
var str:String = "";
|
||||
if( !target ) return false;
|
||||
for( i in 0...target.args.length ){
|
||||
str = str + "|" + target.args[i].string;
|
||||
}
|
||||
str = str.substr(1);
|
||||
return item.expect.out ? str == item.expect.out : false;
|
||||
}
|
||||
|
||||
static public function testUrl():Void {
|
||||
var Uri = xrfragment.URI;
|
||||
var url:String = "http://foo.com?foo=1#bar=flop&a=1,2&b=c|d|1,2,3";
|
||||
|
|
@ -79,114 +76,18 @@ class Test {
|
|||
trace( Uri.parse(url,0) );
|
||||
}
|
||||
|
||||
static public function testQuery():Void {
|
||||
var Query = xrfragment.Query;
|
||||
static public function testFilter():Void {
|
||||
var Filter = xrfragment.Filter;
|
||||
|
||||
trace( (new Query("foo or bar")).toObject() );
|
||||
trace( (new Query("class:fopoer or bar foo:bar")).toObject().or[0] );
|
||||
trace( (new Query("-skybox class:foo")).toObject().or[0] );
|
||||
trace( (new Query("foo/flop moo or bar")).toObject().or[0] );
|
||||
trace( (new Query("-foo/flop moo or bar")).toObject().or[0] );
|
||||
trace( (new Query("price:>4 moo or bar")).toObject().or[0] );
|
||||
trace( (new Query("price:>=4 moo or bar")).toObject().or[0] );
|
||||
trace( (new Query("price:<=4 moo or bar")).toObject().or[0] );
|
||||
trace( (new Query("price:!=4 moo or bar")).toObject().or[0] );
|
||||
|
||||
var q:Dynamic = new Query("price:!=4 moo or bar");
|
||||
var obj:Dynamic = q.toObject();
|
||||
q.test( "price", 4);
|
||||
var ok = !q.selected("slkklskdf");
|
||||
if( !ok ) throw 'node should not be allowed';
|
||||
|
||||
q = new Query("price:!=3 moo or bar");
|
||||
var obj:Dynamic = q.toObject();
|
||||
q.test( "price", 4);
|
||||
var ok = q.selected("slkklskdf");
|
||||
if( !ok ) throw 'non-mentioned node should be allowed';
|
||||
|
||||
q = new Query("moo or bar");
|
||||
var obj:Dynamic = q.toObject();
|
||||
var ok = !q.selected("slkklskdf");
|
||||
if( !ok ) throw 'node should not be allowed';
|
||||
obj = q.toObject();
|
||||
var ok = q.selected("moo");
|
||||
if( !ok ) throw 'moo should be allowed';
|
||||
var ok = q.selected("bar");
|
||||
if( !ok ) throw 'bar should be allowed';
|
||||
|
||||
q = new Query("price:>3 moo or bar");
|
||||
var obj:Dynamic = q.toObject();
|
||||
q.test( "price", 4);
|
||||
var ok = q.selected("foo");
|
||||
if( !ok ) throw 'node should be allowed';
|
||||
var ok = q.selected("bar");
|
||||
if( !ok ) throw 'node should be allowed';
|
||||
var ok = q.selected("moo");
|
||||
if( !ok ) throw 'node should be allowed';
|
||||
|
||||
q = new Query("price:>3 price:<10 -bar");
|
||||
var obj:Dynamic = q.toObject();
|
||||
q.test( "price", 4);
|
||||
var ok = q.selected("foo");
|
||||
if( !ok ) throw 'node should be allowed';
|
||||
var ok = !q.selected("bar");
|
||||
if( !ok ) throw 'bar should not be allowed';
|
||||
q.test("price", 20);
|
||||
var ok = !q.selected("foo");
|
||||
if( !ok ) throw 'price 20 should not be allowed';
|
||||
|
||||
q = new Query("-bar");
|
||||
var obj:Dynamic = q.toObject();
|
||||
var ok = q.selected("foo");
|
||||
if( !ok ) throw 'node should be allowed';
|
||||
var ok = !q.selected("bar");
|
||||
if( !ok ) throw 'bar should not be allowed';
|
||||
|
||||
q = new Query("title:*");
|
||||
var obj:Dynamic = q.toObject();
|
||||
var ok = !q.selected("foo");
|
||||
if( !ok ) throw 'node should not be allowed';
|
||||
q.test("foo","bar");
|
||||
var ok = !q.selected("foo");
|
||||
if( !ok ) throw 'node should not be allowed';
|
||||
q.test("title","bar");
|
||||
var ok = q.selected("foo");
|
||||
if( !ok ) throw 'node should be allowed';
|
||||
|
||||
q = new Query("-bar +bar");
|
||||
var obj:Dynamic = q.toObject();
|
||||
var ok = q.selected("foo");
|
||||
if( !ok ) throw 'node should be allowed';
|
||||
var ok = q.selected("bar");
|
||||
if( !ok ) throw 'bar should be allowed';
|
||||
|
||||
q = new Query("?discount");
|
||||
var obj:Dynamic = q.toObject();
|
||||
q.test("?discount","-foo");
|
||||
var ok = !q.selected("foo");
|
||||
if( !ok ) throw 'foo should not be allowed';
|
||||
|
||||
q = new Query("?");
|
||||
q.test("?","-foo");
|
||||
var ok = !q.selected("foo");
|
||||
if( !ok ) throw 'foo should not be allowed';
|
||||
|
||||
q = new Query("?");
|
||||
var ok = q.selected("foo");
|
||||
if( !ok ) throw 'foo should not be allowed';
|
||||
|
||||
q = new Query("?discount");
|
||||
q.test("?discount","-foo");
|
||||
var ok = !q.selected("foo");
|
||||
if( !ok ) throw 'foo should not be allowed';
|
||||
|
||||
q = new Query("?discount +foo");
|
||||
var obj:Dynamic = q.toObject();
|
||||
q.test("?discount","-foo");
|
||||
var ok = !q.selected("foo");
|
||||
if( !ok ) throw 'foo should not be allowed';
|
||||
var ok = !q.selected("foo");
|
||||
if( !ok ) throw 'foo should not be allowed';
|
||||
trace( (new Filter("foo or bar")).toObject() );
|
||||
trace( (new Filter("class:fopoer or bar foo:bar")).toObject().or[0] );
|
||||
trace( (new Filter("-skybox class:foo")).toObject().or[0] );
|
||||
trace( (new Filter("foo/flop moo or bar")).toObject().or[0] );
|
||||
trace( (new Filter("-foo/flop moo or bar")).toObject().or[0] );
|
||||
trace( (new Filter("price:>4 moo or bar")).toObject().or[0] );
|
||||
trace( (new Filter("price:>=4 moo or bar")).toObject().or[0] );
|
||||
trace( (new Filter("price:<=4 moo or bar")).toObject().or[0] );
|
||||
trace( (new Filter("price:!=4 moo or bar")).toObject().or[0] );
|
||||
|
||||
trace("all tests passed");
|
||||
}
|
||||
|
|
|
|||
15
src/spec/filter.selectors.json
Normal file
15
src/spec/filter.selectors.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[
|
||||
{"fn":"url","data":"http://foo.com?foo=1#foo*&-sometag&-someid&myid", "expect":{ "fn":"testParsed", "input":"myid","out":true},"label":"myid exists"},
|
||||
{"fn":"url","data":"http://foo.com?foo=1#tag=bar", "expect":{ "fn":"testParsed", "input":"tag", "out":true},"label":"tag exists"},
|
||||
{"fn":"url","data":"http://foo.com?foo=1#-tag=bar", "expect":{ "fn":"testParsed", "input":"tag", "out":true},"label":"tag exists"},
|
||||
{"fn":"url","data":"http://foo.com?foo=1#price=>2", "expect":{ "fn":"testParsed", "input":"price","out":true},"label":"filter test"},
|
||||
{"fn":"filter","data":"tag=bar", "expect":{ "fn":"testProperty","input":["tag","bar"],"out":true}},
|
||||
{"fn":"filter","data":"-tag=foo", "expect":{ "fn":"testProperty","input":["tag","foo"],"out":false}},
|
||||
{"fn":"filter","data":"-tag*=foo", "expect":{ "fn":"testProperty","input":["tag","foo"],"out":false}},
|
||||
{"fn":"filter","data":"-tag=>2", "expect":{ "fn":"testProperty","input":["tag","3"],"out":false}},
|
||||
{"fn":"filter","data":"price=>2", "expect":{ "fn":"testProperty","input":["price","1"],"out":false}},
|
||||
{"fn":"filter","data":"price=<2", "expect":{ "fn":"testProperty","input":["price","5"],"out":false}},
|
||||
{"fn":"filter","data":"price=<2", "expect":{ "fn":"testProperty","input":["price","1"],"out":true}},
|
||||
{"fn":"url","data":"#foo*", "expect":{ "fn":"testFilterDeep","input":["foo"],"out":1},"label":"foo should be deep"},
|
||||
{"fn":"url","data":"#foo**", "expect":{ "fn":"testFilterDeep","input":["foo"],"out":2},"label":"foo should be deep incl. embeds"}
|
||||
]
|
||||
6
src/spec/pos.json
Normal file
6
src/spec/pos.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[
|
||||
{"fn":"url","data":"http://foo.com?foo=1#pos=1.2,2.2", "expect":{ "fn":"equal.string", "input":"pos","out":"1.2,2.2"},"label":"equal.string"},
|
||||
{"fn":"url","data":"http://foo.com?foo=1#pos=1.2,2.2,3", "expect":{ "fn":"equal.xyz", "input":"pos","out":"1.2,2.2,3"},"label":"equal.xyz"},
|
||||
{"fn":"url","data":"http://foo.com?foo=1#pos=1,2,3", "expect":{ "fn":"equal.xyz", "input":"pos","out":"1,2,3"},"label":"pos equal.xyz"},
|
||||
{"fn":"url","data":"http://foo.com?foo=1#pos=world2", "expect":{ "fn":"equal.string", "input":"pos","out":"world2"},"label":"pos equal.xyz"}
|
||||
]
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
[
|
||||
]
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
[
|
||||
{"fn":"query","data":"price:>=5", "expect":{ "fn":"testProperty","input":["price","10"],"out":true}},
|
||||
{"fn":"query","data":"price:>=15", "expect":{ "fn":"testProperty","input":["price","10"],"out":false}},
|
||||
{"fn":"query","data":"price:>=5", "expect":{ "fn":"testProperty","input":["price","4"],"out":false}},
|
||||
{"fn":"query","data":"price:>=5", "expect":{ "fn":"testProperty","input":["price","0"],"out":false}},
|
||||
{"fn":"query","data":"price:>=2", "expect":{ "fn":"testProperty","input":["price","2"],"out":true}},
|
||||
{"fn":"query","data":"price:>=5 price:0", "expect":{ "fn":"testProperty","input":["price","1"],"out":false},"label":"price=1"},
|
||||
{"fn":"query","data":"price:>=5 price:0", "expect":{ "fn":"testProperty","input":["price","0"],"out":true},"label":"price=0"},
|
||||
{"fn":"query","data":"price:>=5 price:0", "expect":{ "fn":"testProperty","input":["price","6"],"out":true},"label":"price=6"},
|
||||
{"fn":"query","data":"tag:foo", "expect":{ "fn":"testProperty","input":["tag","foo"],"out":true}},
|
||||
{"fn":"query","data":"-tag:foo", "expect":{ "fn":"testProperty","input":["tag","foo"],"out":false}},
|
||||
{"fn":"query","data":"-tag:foo", "expect":{ "fn":"testPropertyExclude","input":["tag","foo"],"out":true},"label":"testExclude"},
|
||||
{"fn":"query","data":".foo price:5 -tag:foo", "expect":{ "fn":"test","input":[{"price":5}],"out":true}},
|
||||
{"fn":"query","data":".foo price:5 -tag:foo", "expect":{ "fn":"test","input":[{"tag":"foo","price":5}],"out":false}}
|
||||
]
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
[
|
||||
{"fn":"query","data":"tag:bar", "expect":{ "fn":"testProperty","input":["tag","bar"],"out":true}},
|
||||
{"fn":"query","data":"tag:bar -tag:foo", "expect":{ "fn":"testProperty","input":["tag","foo"],"out":false}},
|
||||
{"fn":"query","data":"tag:bar -tag:foo tag:foo", "expect":{ "fn":"testProperty","input":["tag","foo"],"out":true}},
|
||||
{"fn":"query","data":"tag:bar -tag:bar tag:bar", "expect":{ "fn":"testProperty","input":["tag","bar"],"out":true}},
|
||||
{"fn":"query","data":"tag:foo -tag:foo tag:foo", "expect":{ "fn":"testProperty","input":["tag","foo"],"out":true},"label":"tag:foo"},
|
||||
{"fn":"query","data":"tag:foo -tag:foo bar:5 tag:foo", "expect":{ "fn":"testProperty","input":["tag","foo"],"out":true},"label":"tag:foo"},
|
||||
{"fn":"query","data":"tag:foo -tag:foo bar:>5 tag:foo", "expect":{ "fn":"testProperty","input":["tag","foo"],"out":true},"label":"tag:foo"},
|
||||
{"fn":"query","data":"tag:foo -tag:foo bar:>5 tag:foo", "expect":{ "fn":"testProperty","input":["tag","foo"],"out":true},"label":"tag:foo"},
|
||||
{"fn":"query","data":"tag:foo -tag:foo tag:foo", "expect":{ "fn":"testProperty","input":["tag","foo"],"out":true},"label":"tag:foo"},
|
||||
{"fn":"query","data":"tag:foo -tag:foo tag:foo", "expect":{ "fn":"testProperty","input":["id","foo"],"out":true},"label":"id:foo"},
|
||||
{"fn":"query","data":"tag: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"}
|
||||
]
|
||||
10
src/spec/t.json
Normal file
10
src/spec/t.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[
|
||||
{"fn":"url","data":"http://foo.com?foo=1#t=1", "expect":{ "fn":"equal.x", "input":"t","out":"1"},"label":"a equal.x"},
|
||||
{"fn":"url","data":"http://foo.com?foo=1#t=-1", "expect":{ "fn":"equal.x", "input":"t","out":"-1"},"label":"a equal.x"},
|
||||
{"fn":"url","data":"http://foo.com?foo=1#t=-1.02", "expect":{ "fn":"equal.x", "input":"t","out":"-1.02"},"label":"a equal.x"},
|
||||
{"fn":"url","data":"http://foo.com?foo=1#t=1,2,3", "expect":{ "fn":"equal.xy", "input":"t","out":"1,2"},"label":"a equal.xy"},
|
||||
{"fn":"url","data":"http://foo.com?foo=1#t=1,2,3", "expect":{ "fn":"equal.xyz", "input":"t","out":"1,2,3"},"label":"a equal.xyz"},
|
||||
{"fn":"url","data":"http://foo.com?foo=1#t=1,-2,3", "expect":{ "fn":"equal.xyz", "input":"t","out":"1,-2,3"},"label":"a equal.xyz"},
|
||||
{"fn":"url","data":"http://foo.com?foo=1#t=1,100", "expect":{ "fn":"equal.xy", "input":"t","out":"1,100"},"label":"a equal.xy"},
|
||||
{"fn":"url","data":"http://foo.com?foo=1#t=2,500", "expect":{ "fn":"testBrowserOverride", "input":"t","out":true},"label":"browser URI can override t (defined in asset)"}
|
||||
]
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue