From 7f991c6d2644a557e6bf97563a7483a5cafc4b3a Mon Sep 17 00:00:00 2001 From: Leon van Kammen Date: Thu, 20 Apr 2023 18:49:18 +0200 Subject: [PATCH] THREEjs wip --- dist/xrfragment.js | 23 +- dist/xrfragment.lua | 99 +++-- dist/xrfragment.py | 21 +- example/assets/example1.gltf | 659 +++++++++++++++++++++++++++++++ example/threejs.basic/index.html | 233 +++++++++++ example/threejs.basic/main.css | 91 +++++ serve | 3 + src/Test.hx | 2 + src/spec/url.json | 4 +- src/xrfragment/Parser.hx | 23 +- src/xrfragment/XRF.hx | 4 +- test/generated/test.js | 35 +- test/generated/test.py | 29 +- 13 files changed, 1122 insertions(+), 104 deletions(-) create mode 100644 example/assets/example1.gltf create mode 100644 example/threejs.basic/index.html create mode 100644 example/threejs.basic/main.css create mode 100755 serve diff --git a/dist/xrfragment.js b/dist/xrfragment.js index f988839..8a84d99 100644 --- a/dist/xrfragment.js +++ b/dist/xrfragment.js @@ -216,16 +216,12 @@ var xrfragment_Parser = $hx_exports["xrfragment"]["Parser"] = function() { }; xrfragment_Parser.__name__ = true; xrfragment_Parser.parse = function(key,value,resultMap) { var Frag_h = Object.create(null); - Frag_h["prio"] = xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_INT; + Frag_h["prio"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_INT; Frag_h["#"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_PREDEFINED_VIEW; - Frag_h["class"] = xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_STRING; - Frag_h["src"] = xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_URL; - Frag_h["src_audio"] = xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_URL; - Frag_h["src_shader"] = xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_URL; - Frag_h["src_env"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL; - Frag_h["src_env_audio"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL; + Frag_h["class"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING; + Frag_h["src"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL; Frag_h["pos"] = xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_VECTOR3 | xrfragment_XRF.T_STRING_OBJ; - Frag_h["href"] = xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_URL | xrfragment_XRF.T_PREDEFINED_VIEW; + Frag_h["href"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL | xrfragment_XRF.T_PREDEFINED_VIEW; Frag_h["q"] = xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING; Frag_h["scale"] = xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_INT; Frag_h["rot"] = xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_VECTOR3; @@ -235,7 +231,6 @@ xrfragment_Parser.parse = function(key,value,resultMap) { Frag_h["gravity"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR3; Frag_h["physics"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR3; Frag_h["scroll"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING; - Frag_h["."] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING; Frag_h["fov"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_INT | xrfragment_XRF.BROWSER_OVERRIDE; Frag_h["clip"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR2 | xrfragment_XRF.BROWSER_OVERRIDE; Frag_h["fog"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING | xrfragment_XRF.BROWSER_OVERRIDE; @@ -248,15 +243,19 @@ xrfragment_Parser.parse = function(key,value,resultMap) { resultMap[key] = new xrfragment_XRF(key,xrfragment_XRF.PV_EXECUTE | xrfragment_XRF.BROWSER_OVERRIDE); return true; } + if(key.split(".").length > 1 && value.split(".").length > 1) { + resultMap[key] = new xrfragment_XRF(key,xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING | xrfragment_XRF.PROP_BIND); + return true; + } if(Object.prototype.hasOwnProperty.call(Frag_h,key)) { var v = new xrfragment_XRF(key,Frag_h[key]); if(!v.validate(value)) { - console.log("src/xrfragment/Parser.hx:79:","[ i ] fragment '" + key + "' has incompatible value (" + value + ")"); + console.log("src/xrfragment/Parser.hx:74:","[ i ] fragment '" + key + "' has incompatible value (" + value + ")"); return false; } resultMap[key] = v; } else { - console.log("src/xrfragment/Parser.hx:83:","[ i ] fragment '" + key + "' does not exist or has no type typed (yet)"); + console.log("src/xrfragment/Parser.hx:78:","[ i ] fragment '" + key + "' does not exist or has no type typed (yet)"); return false; } return true; @@ -557,7 +556,7 @@ Array.__name__ = true; js_Boot.__toStr = ({ }).toString; xrfragment_Parser.error = ""; xrfragment_XRF.ASSET = 1; -xrfragment_XRF.ASSET_OBJ = 2; +xrfragment_XRF.PROP_BIND = 2; xrfragment_XRF.QUERY_OPERATOR = 4; xrfragment_XRF.PROMPT = 8; xrfragment_XRF.ROUNDROBIN = 16; diff --git a/dist/xrfragment.lua b/dist/xrfragment.lua index 506f257..4982e68 100644 --- a/dist/xrfragment.lua +++ b/dist/xrfragment.lua @@ -1408,7 +1408,7 @@ _hx_exports["xrfragment"]["Parser"] = __xrfragment_Parser __xrfragment_Parser.__name__ = true __xrfragment_Parser.parse = function(key,value,resultMap) local Frag_h = ({}); - local value1 = _hx_bit.bor(__xrfragment_XRF.ASSET_OBJ,__xrfragment_XRF.T_INT); + local value1 = _hx_bit.bor(__xrfragment_XRF.ASSET,__xrfragment_XRF.T_INT); if (value1 == nil) then Frag_h.prio = __haxe_ds_StringMap.tnull; else @@ -1420,49 +1420,25 @@ __xrfragment_Parser.parse = function(key,value,resultMap) else Frag_h["#"] = value1; end; - local value1 = _hx_bit.bor(__xrfragment_XRF.ASSET_OBJ,__xrfragment_XRF.T_STRING); + local value1 = _hx_bit.bor(__xrfragment_XRF.ASSET,__xrfragment_XRF.T_STRING); if (value1 == nil) then Frag_h.class = __haxe_ds_StringMap.tnull; else Frag_h.class = value1; end; - local value1 = _hx_bit.bor(__xrfragment_XRF.ASSET_OBJ,__xrfragment_XRF.T_URL); + local value1 = _hx_bit.bor(__xrfragment_XRF.ASSET,__xrfragment_XRF.T_URL); if (value1 == nil) then Frag_h.src = __haxe_ds_StringMap.tnull; else Frag_h.src = value1; end; - local value1 = _hx_bit.bor(__xrfragment_XRF.ASSET_OBJ,__xrfragment_XRF.T_URL); - if (value1 == nil) then - Frag_h.src_audio = __haxe_ds_StringMap.tnull; - else - Frag_h.src_audio = value1; - end; - local value1 = _hx_bit.bor(__xrfragment_XRF.ASSET_OBJ,__xrfragment_XRF.T_URL); - if (value1 == nil) then - Frag_h.src_shader = __haxe_ds_StringMap.tnull; - else - Frag_h.src_shader = value1; - end; - local value1 = _hx_bit.bor(__xrfragment_XRF.ASSET,__xrfragment_XRF.T_URL); - if (value1 == nil) then - Frag_h.src_env = __haxe_ds_StringMap.tnull; - else - Frag_h.src_env = value1; - end; - local value1 = _hx_bit.bor(__xrfragment_XRF.ASSET,__xrfragment_XRF.T_URL); - if (value1 == nil) then - Frag_h.src_env_audio = __haxe_ds_StringMap.tnull; - else - Frag_h.src_env_audio = value1; - end; local value1 = _hx_bit.bor(_hx_bit.bor(_hx_bit.bor(__xrfragment_XRF.PV_OVERRIDE,__xrfragment_XRF.ROUNDROBIN),__xrfragment_XRF.T_VECTOR3),__xrfragment_XRF.T_STRING_OBJ); if (value1 == nil) then Frag_h.pos = __haxe_ds_StringMap.tnull; else Frag_h.pos = value1; end; - local value1 = _hx_bit.bor(_hx_bit.bor(__xrfragment_XRF.ASSET_OBJ,__xrfragment_XRF.T_URL),__xrfragment_XRF.T_PREDEFINED_VIEW); + local value1 = _hx_bit.bor(_hx_bit.bor(__xrfragment_XRF.ASSET,__xrfragment_XRF.T_URL),__xrfragment_XRF.T_PREDEFINED_VIEW); if (value1 == nil) then Frag_h.href = __haxe_ds_StringMap.tnull; else @@ -1522,12 +1498,6 @@ __xrfragment_Parser.parse = function(key,value,resultMap) else Frag_h.scroll = value1; end; - local value1 = _hx_bit.bor(_hx_bit.bor(__xrfragment_XRF.ASSET,__xrfragment_XRF.PV_OVERRIDE),__xrfragment_XRF.T_STRING); - if (value1 == nil) then - Frag_h["."] = __haxe_ds_StringMap.tnull; - else - Frag_h["."] = value1; - end; local value1 = _hx_bit.bor(_hx_bit.bor(_hx_bit.bor(__xrfragment_XRF.ASSET,__xrfragment_XRF.PV_OVERRIDE),__xrfragment_XRF.T_INT),__xrfragment_XRF.BROWSER_OVERRIDE); if (value1 == nil) then Frag_h.fov = __haxe_ds_StringMap.tnull; @@ -1581,6 +1551,61 @@ __xrfragment_Parser.parse = function(key,value,resultMap) resultMap[key] = value; do return true end; end; + local tmp; + local idx = 1; + local ret = _hx_tab_array({}, 0); + while (idx ~= nil) do + local newidx = 0; + if (__lua_lib_luautf8_Utf8.len(".") > 0) then + newidx = __lua_lib_luautf8_Utf8.find(key, ".", idx, true); + else + if (idx >= __lua_lib_luautf8_Utf8.len(key)) then + newidx = nil; + else + newidx = idx + 1; + end; + end; + if (newidx ~= nil) then + local match = __lua_lib_luautf8_Utf8.sub(key, idx, newidx - 1); + ret:push(match); + idx = newidx + __lua_lib_luautf8_Utf8.len("."); + else + ret:push(__lua_lib_luautf8_Utf8.sub(key, idx, __lua_lib_luautf8_Utf8.len(key))); + idx = nil; + end; + end; + if (ret.length > 1) then + local idx = 1; + local ret = _hx_tab_array({}, 0); + while (idx ~= nil) do + local newidx = 0; + if (__lua_lib_luautf8_Utf8.len(".") > 0) then + newidx = __lua_lib_luautf8_Utf8.find(value, ".", idx, true); + else + if (idx >= __lua_lib_luautf8_Utf8.len(value)) then + newidx = nil; + else + newidx = idx + 1; + end; + end; + if (newidx ~= nil) then + local match = __lua_lib_luautf8_Utf8.sub(value, idx, newidx - 1); + ret:push(match); + idx = newidx + __lua_lib_luautf8_Utf8.len("."); + else + ret:push(__lua_lib_luautf8_Utf8.sub(value, idx, __lua_lib_luautf8_Utf8.len(value))); + idx = nil; + end; + end; + tmp = ret.length > 1; + else + tmp = false; + end; + if (tmp) then + local value = __xrfragment_XRF.new(key, _hx_bit.bor(_hx_bit.bor(_hx_bit.bor(__xrfragment_XRF.ASSET,__xrfragment_XRF.PV_OVERRIDE),__xrfragment_XRF.T_STRING),__xrfragment_XRF.PROP_BIND)); + resultMap[key] = value; + do return true end; + end; if (Frag_h[key] ~= nil) then local ret = Frag_h[key]; if (ret == __haxe_ds_StringMap.tnull) then @@ -1588,12 +1613,12 @@ __xrfragment_Parser.parse = function(key,value,resultMap) end; local v = __xrfragment_XRF.new(key, ret); if (not v:validate(value)) then - __haxe_Log.trace(Std.string(Std.string(Std.string(Std.string("[ i ] fragment '") .. Std.string(key)) .. Std.string("' has incompatible value (")) .. Std.string(value)) .. Std.string(")"), _hx_o({__fields__={fileName=true,lineNumber=true,className=true,methodName=true},fileName="src/xrfragment/Parser.hx",lineNumber=79,className="xrfragment.Parser",methodName="parse"})); + __haxe_Log.trace(Std.string(Std.string(Std.string(Std.string("[ i ] fragment '") .. Std.string(key)) .. Std.string("' has incompatible value (")) .. Std.string(value)) .. Std.string(")"), _hx_o({__fields__={fileName=true,lineNumber=true,className=true,methodName=true},fileName="src/xrfragment/Parser.hx",lineNumber=74,className="xrfragment.Parser",methodName="parse"})); do return false end; end; resultMap[key] = v; else - __haxe_Log.trace(Std.string(Std.string("[ i ] fragment '") .. Std.string(key)) .. Std.string("' does not exist or has no type typed (yet)"), _hx_o({__fields__={fileName=true,lineNumber=true,className=true,methodName=true},fileName="src/xrfragment/Parser.hx",lineNumber=83,className="xrfragment.Parser",methodName="parse"})); + __haxe_Log.trace(Std.string(Std.string("[ i ] fragment '") .. Std.string(key)) .. Std.string("' does not exist or has no type typed (yet)"), _hx_o({__fields__={fileName=true,lineNumber=true,className=true,methodName=true},fileName="src/xrfragment/Parser.hx",lineNumber=78,className="xrfragment.Parser",methodName="parse"})); do return false end; end; do return true end; @@ -2323,7 +2348,7 @@ local _hx_static_init = function() __xrfragment_XRF.ASSET = 1; - __xrfragment_XRF.ASSET_OBJ = 2; + __xrfragment_XRF.PROP_BIND = 2; __xrfragment_XRF.QUERY_OPERATOR = 4; diff --git a/dist/xrfragment.py b/dist/xrfragment.py index 62a4eb8..065bd77 100644 --- a/dist/xrfragment.py +++ b/dist/xrfragment.py @@ -1293,16 +1293,12 @@ class xrfragment_Parser: @staticmethod def parse(key,value,resultMap): Frag = haxe_ds_StringMap() - Frag.h["prio"] = (xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_INT) + Frag.h["prio"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_INT) Frag.h["#"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_PREDEFINED_VIEW) - Frag.h["class"] = (xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_STRING) - Frag.h["src"] = (xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_URL) - Frag.h["src_audio"] = (xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_URL) - Frag.h["src_shader"] = (xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_URL) - Frag.h["src_env"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) - Frag.h["src_env_audio"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) + Frag.h["class"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING) + Frag.h["src"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) Frag.h["pos"] = (((xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN) | xrfragment_XRF.T_VECTOR3) | xrfragment_XRF.T_STRING_OBJ) - Frag.h["href"] = ((xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_URL) | xrfragment_XRF.T_PREDEFINED_VIEW) + Frag.h["href"] = ((xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) | xrfragment_XRF.T_PREDEFINED_VIEW) Frag.h["q"] = (xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING) Frag.h["scale"] = (((xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.ROUNDROBIN) | xrfragment_XRF.T_INT) Frag.h["rot"] = (((xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.ROUNDROBIN) | xrfragment_XRF.T_VECTOR3) @@ -1312,7 +1308,6 @@ class xrfragment_Parser: Frag.h["gravity"] = ((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_VECTOR3) Frag.h["physics"] = ((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_VECTOR3) Frag.h["scroll"] = ((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_STRING) - Frag.h["."] = ((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_STRING) Frag.h["fov"] = (((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_INT) | xrfragment_XRF.BROWSER_OVERRIDE) Frag.h["clip"] = (((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_VECTOR2) | xrfragment_XRF.BROWSER_OVERRIDE) Frag.h["fog"] = (((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_STRING) | xrfragment_XRF.BROWSER_OVERRIDE) @@ -1325,6 +1320,10 @@ class xrfragment_Parser: value1 = xrfragment_XRF(key,(xrfragment_XRF.PV_EXECUTE | xrfragment_XRF.BROWSER_OVERRIDE)) setattr(resultMap,(("_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 + 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(resultMap,(("_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 if (key in Frag.h): v = xrfragment_XRF(key,Frag.h.get(key,None)) if (not v.validate(value)): @@ -1564,7 +1563,7 @@ class xrfragment_XRF: __slots__ = ("fragment", "flags", "x", "y", "z", "color", "string", "int", "float", "args", "query") _hx_fields = ["fragment", "flags", "x", "y", "z", "color", "string", "int", "float", "args", "query"] _hx_methods = ["is", "validate", "guessType"] - _hx_statics = ["ASSET", "ASSET_OBJ", "QUERY_OPERATOR", "PROMPT", "ROUNDROBIN", "BROWSER_OVERRIDE", "PV_OVERRIDE", "PV_EXECUTE", "T_INT", "T_VECTOR2", "T_VECTOR3", "T_URL", "T_PREDEFINED_VIEW", "T_STRING", "T_STRING_OBJ", "isColor", "isInt", "isFloat"] + _hx_statics = ["ASSET", "PROP_BIND", "QUERY_OPERATOR", "PROMPT", "ROUNDROBIN", "BROWSER_OVERRIDE", "PV_OVERRIDE", "PV_EXECUTE", "T_INT", "T_VECTOR2", "T_VECTOR3", "T_URL", "T_PREDEFINED_VIEW", "T_STRING", "T_STRING_OBJ", "isColor", "isInt", "isFloat"] def __init__(self,_fragment,_flags): self.query = None @@ -1641,7 +1640,7 @@ python_Boot.keywords = set(["and", "del", "from", "not", "with", "as", "elif", " python_Boot.prefixLength = len("_hx_") xrfragment_Parser.error = "" xrfragment_XRF.ASSET = 1 -xrfragment_XRF.ASSET_OBJ = 2 +xrfragment_XRF.PROP_BIND = 2 xrfragment_XRF.QUERY_OPERATOR = 4 xrfragment_XRF.PROMPT = 8 xrfragment_XRF.ROUNDROBIN = 16 diff --git a/example/assets/example1.gltf b/example/assets/example1.gltf new file mode 100644 index 0000000..6243aa3 --- /dev/null +++ b/example/assets/example1.gltf @@ -0,0 +1,659 @@ +{ + "asset" : { + "generator" : "Khronos glTF Blender I/O v3.3.32", + "version" : "2.0" + }, + "extensionsUsed" : [ + "KHR_materials_specular", + "KHR_materials_ior" + ], + "scene" : 0, + "scenes" : [ + { + "extras" : { + "sid_settings" : { + "compositor_reset" : 1 + }, + "unit" : "1m" + }, + "name" : "Scene", + "nodes" : [ + 0, + 1, + 2, + 3, + 4, + 5 + ] + } + ], + "nodes" : [ + { + "mesh" : 0, + "name" : "background", + "scale" : [ + -23.58001708984375, + -23.58001708984375, + -23.58001708984375 + ] + }, + { + "mesh" : 1, + "name" : "line.002", + "rotation" : [ + 0, + 0, + -0.49615588784217834, + 0.8682334423065186 + ], + "scale" : [ + 0.018205316737294197, + 0.46953850984573364, + 0.018205316737294197 + ], + "translation" : [ + 2.5721938610076904, + 0.7182676792144775, + -0.39330875873565674 + ] + }, + { + "mesh" : 2, + "name" : "Cube", + "scale" : [ + 0.3472398519515991, + 0.8892746567726135, + 0.3472398519515991 + ], + "translation" : [ + -1.5526816844940186, + 0.979434609413147, + 0 + ] + }, + { + "mesh" : 3, + "name" : "Cylinder", + "scale" : [ + 3.5802836418151855, + 0.1508091539144516, + 3.5802836418151855 + ] + }, + { + "mesh" : 4, + "name" : "Sphere", + "scale" : [ + 3.474874258041382, + 3.474874258041382, + 3.474874258041382 + ], + "translation" : [ + 0, + 0.1271827667951584, + 0 + ] + }, + { + "mesh" : 5, + "name" : "Cube.002", + "scale" : [ + -36.627506256103516, + -36.627506256103516, + -36.627506256103516 + ] + } + ], + "materials" : [ + { + "doubleSided" : true, + "emissiveFactor" : [ + 1, + 1, + 1 + ], + "name" : "white", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0.800000011920929, + 0.800000011920929, + 0.800000011920929, + 1 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.5 + } + }, + { + "alphaMode" : "BLEND", + "doubleSided" : true, + "name" : "line1.001", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 0, + 0, + 0, + 0 + ], + "metallicFactor" : 0, + "roughnessFactor" : 0.5 + } + }, + { + "doubleSided" : true, + "emissiveFactor" : [ + 1, + 1, + 1 + ], + "emissiveTexture" : { + "index" : 0 + }, + "extensions" : { + "KHR_materials_specular" : { + "specularColorFactor" : [ + 0.7760806404086199, + 0.7760806404086199, + 0.7760806404086199 + ] + }, + "KHR_materials_ior" : { + "ior" : 1.4500000476837158 + } + }, + "name" : "Material.001", + "pbrMetallicRoughness" : { + "baseColorTexture" : { + "index" : 1 + }, + "metallicFactor" : 0.907216489315033, + "roughnessFactor" : 0.4303186535835266 + } + }, + { + "alphaMode" : "BLEND", + "extensions" : { + "KHR_materials_specular" : { + "specularColorFactor" : [ + 1.6990655378546355, + 1.6990655378546355, + 1.6990655378546355 + ] + }, + "KHR_materials_ior" : { + "ior" : 1.4500000476837158 + } + }, + "name" : "glass", + "pbrMetallicRoughness" : { + "baseColorFactor" : [ + 1, + 1, + 1, + 0.4845360517501831 + ], + "metallicFactor" : 0.8453608155250549, + "roughnessFactor" : 0.19072163105010986 + } + } + ], + "meshes" : [ + { + "name" : "Cube.002", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0, + "NORMAL" : 1, + "TEXCOORD_0" : 2 + }, + "indices" : 3, + "material" : 0 + } + ] + }, + { + "name" : "Cylinder.003", + "primitives" : [ + { + "attributes" : { + "POSITION" : 4, + "NORMAL" : 5, + "TEXCOORD_0" : 6 + }, + "indices" : 7, + "material" : 1 + } + ] + }, + { + "name" : "Cube.001", + "primitives" : [ + { + "attributes" : { + "POSITION" : 8, + "NORMAL" : 9, + "TEXCOORD_0" : 10 + }, + "indices" : 11, + "material" : 2 + } + ] + }, + { + "name" : "Cylinder", + "primitives" : [ + { + "attributes" : { + "POSITION" : 12, + "NORMAL" : 13, + "TEXCOORD_0" : 14 + }, + "indices" : 7 + } + ] + }, + { + "name" : "Sphere", + "primitives" : [ + { + "attributes" : { + "POSITION" : 15, + "NORMAL" : 16, + "TEXCOORD_0" : 17 + }, + "indices" : 18, + "material" : 3 + } + ] + }, + { + "name" : "Cube.003", + "primitives" : [ + { + "attributes" : { + "POSITION" : 19, + "NORMAL" : 20, + "TEXCOORD_0" : 21 + }, + "indices" : 22, + "material" : 0 + } + ] + } + ], + "textures" : [ + { + "sampler" : 0, + "source" : 0 + }, + { + "sampler" : 0, + "source" : 0 + } + ], + "images" : [ + { + "bufferView" : 12, + "mimeType" : "image/png", + "name" : "gradient2" + } + ], + "accessors" : [ + { + "bufferView" : 0, + "componentType" : 5126, + "count" : 14, + "max" : [ + 1, + 1, + 1 + ], + "min" : [ + -1, + -1, + -1 + ], + "type" : "VEC3" + }, + { + "bufferView" : 1, + "componentType" : 5126, + "count" : 14, + "type" : "VEC3" + }, + { + "bufferView" : 2, + "componentType" : 5126, + "count" : 14, + "type" : "VEC2" + }, + { + "bufferView" : 3, + "componentType" : 5123, + "count" : 36, + "type" : "SCALAR" + }, + { + "bufferView" : 4, + "componentType" : 5126, + "count" : 192, + "max" : [ + 1, + 1, + 1 + ], + "min" : [ + -1, + -1, + -1 + ], + "type" : "VEC3" + }, + { + "bufferView" : 5, + "componentType" : 5126, + "count" : 192, + "type" : "VEC3" + }, + { + "bufferView" : 6, + "componentType" : 5126, + "count" : 192, + "type" : "VEC2" + }, + { + "bufferView" : 7, + "componentType" : 5123, + "count" : 372, + "type" : "SCALAR" + }, + { + "bufferView" : 8, + "componentType" : 5126, + "count" : 176, + "max" : [ + 6.374702453613281, + 2.015418529510498, + 6.933889389038086 + ], + "min" : [ + -1, + -1, + -4.945398330688477 + ], + "type" : "VEC3" + }, + { + "bufferView" : 9, + "componentType" : 5126, + "count" : 176, + "type" : "VEC3" + }, + { + "bufferView" : 10, + "componentType" : 5126, + "count" : 176, + "type" : "VEC2" + }, + { + "bufferView" : 11, + "componentType" : 5123, + "count" : 258, + "type" : "SCALAR" + }, + { + "bufferView" : 13, + "componentType" : 5126, + "count" : 192, + "max" : [ + 1, + 1, + 1 + ], + "min" : [ + -1, + -1, + -1 + ], + "type" : "VEC3" + }, + { + "bufferView" : 14, + "componentType" : 5126, + "count" : 192, + "type" : "VEC3" + }, + { + "bufferView" : 15, + "componentType" : 5126, + "count" : 192, + "type" : "VEC2" + }, + { + "bufferView" : 16, + "componentType" : 5126, + "count" : 296, + "max" : [ + 0.9999997019767761, + 1, + 0.9999993443489075 + ], + "min" : [ + -0.9999990463256836, + 0, + -1 + ], + "type" : "VEC3" + }, + { + "bufferView" : 17, + "componentType" : 5126, + "count" : 296, + "type" : "VEC3" + }, + { + "bufferView" : 18, + "componentType" : 5126, + "count" : 296, + "type" : "VEC2" + }, + { + "bufferView" : 19, + "componentType" : 5123, + "count" : 1440, + "type" : "SCALAR" + }, + { + "bufferView" : 20, + "componentType" : 5126, + "count" : 24, + "max" : [ + 1, + 1, + 1 + ], + "min" : [ + -1, + -1, + -1 + ], + "type" : "VEC3" + }, + { + "bufferView" : 21, + "componentType" : 5126, + "count" : 24, + "type" : "VEC3" + }, + { + "bufferView" : 22, + "componentType" : 5126, + "count" : 24, + "type" : "VEC2" + }, + { + "bufferView" : 23, + "componentType" : 5123, + "count" : 36, + "type" : "SCALAR" + } + ], + "bufferViews" : [ + { + "buffer" : 0, + "byteLength" : 168, + "byteOffset" : 0, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 168, + "byteOffset" : 168, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 112, + "byteOffset" : 336, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 72, + "byteOffset" : 448, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 2304, + "byteOffset" : 520, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 2304, + "byteOffset" : 2824, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1536, + "byteOffset" : 5128, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 744, + "byteOffset" : 6664, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 2112, + "byteOffset" : 7408, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 2112, + "byteOffset" : 9520, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1408, + "byteOffset" : 11632, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 516, + "byteOffset" : 13040, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 1978, + "byteOffset" : 13556 + }, + { + "buffer" : 0, + "byteLength" : 2304, + "byteOffset" : 15536, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 2304, + "byteOffset" : 17840, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 1536, + "byteOffset" : 20144, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 3552, + "byteOffset" : 21680, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 3552, + "byteOffset" : 25232, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 2368, + "byteOffset" : 28784, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 2880, + "byteOffset" : 31152, + "target" : 34963 + }, + { + "buffer" : 0, + "byteLength" : 288, + "byteOffset" : 34032, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 288, + "byteOffset" : 34320, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 192, + "byteOffset" : 34608, + "target" : 34962 + }, + { + "buffer" : 0, + "byteLength" : 72, + "byteOffset" : 34800, + "target" : 34963 + } + ], + "samplers" : [ + { + "magFilter" : 9729, + "minFilter" : 9987 + } + ], + "buffers" : [ + { + "byteLength" : 34872, + "uri" : "data:application/octet-stream;base64,AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAPwAAgL8AAIC/AACAPwAAgD8AAIC/O80TvzvNE787zRM/O80TvzvNE787zRM/O80TvzvNE787zRM/O80TvzvNEz87zRM/O80TvzvNEz87zRM/O80TvzvNEz87zRM/O80TvzvNE787zRO/O80TvzvNE787zRO/O80TvzvNEz87zRO/O80TvzvNEz87zRO/O80TPzvNE787zRM/O80TPzvNEz87zRM/O80TPzvNE787zRO/O80TPzvNEz87zRO/AAAAPgAAgD4AAMA+AAAAAAAAwD4AAIA/AAAgPwAAAAAAACA/AACAPwAAYD8AAIA+AAAAPgAAAD8AAMA+AABAPwAAID8AAEA/AABgPwAAAD8AAMA+AACAPgAAID8AAIA+AADAPgAAAD8AACA/AAAAPwIABAAIAAIACAAHAAcACAANAAcADQAMAAwADQALAAwACwAKAAoACwADAAoAAwABAAYADAAKAAYACgAAAA0ACQAFAA0ABQALAAAAAAAAAIC/AACAvwAAAAAAAIC/AACAvwAAAAAAAIC/AACAvwAAAAAAAIA/AACAvwAAAAAAAIA/AACAvwAAAAAAAIA/AACAv8LFRz4AAIC/vhR7v8LFRz4AAIC/vhR7v8LFRz4AAIC/vhR7v8LFRz4AAIA/vhR7v8LFRz4AAIA/vhR7v8LFRz4AAIA/vhR7vxbvwz4AAIC/XoNsvxbvwz4AAIC/XoNsvxbvwz4AAIC/XoNsvxbvwz4AAIA/XoNsvxbvwz4AAIA/XoNsvxbvwz4AAIA/XoNsv9o5Dj8AAIC/MdtUv9o5Dj8AAIC/MdtUv9o5Dj8AAIC/MdtUv9o5Dj8AAIA/MdtUv9o5Dj8AAIA/MdtUv9o5Dj8AAIA/MdtUv/MENT8AAIC/8wQ1v/MENT8AAIC/8wQ1v/MENT8AAIC/8wQ1v/MENT8AAIA/8wQ1v/MENT8AAIA/8wQ1v/MENT8AAIA/8wQ1vzHbVD8AAIC/2jkOvzHbVD8AAIC/2jkOvzHbVD8AAIC/2jkOvzHbVD8AAIA/2jkOvzHbVD8AAIA/2jkOvzHbVD8AAIA/2jkOv16DbD8AAIC/Fu/Dvl6DbD8AAIC/Fu/Dvl6DbD8AAIC/Fu/Dvl6DbD8AAIA/Fu/Dvl6DbD8AAIA/Fu/Dvl6DbD8AAIA/Fu/Dvr4Uez8AAIC/wsVHvr4Uez8AAIC/wsVHvr4Uez8AAIC/wsVHvr4Uez8AAIA/wsVHvr4Uez8AAIA/wsVHvr4Uez8AAIA/wsVHvgAAgD8AAIC/AAAAgAAAgD8AAIC/AAAAgAAAgD8AAIC/AAAAgAAAgD8AAIA/AAAAgAAAgD8AAIA/AAAAgAAAgD8AAIA/AAAAgL4Uez8AAIC/wsVHPr4Uez8AAIC/wsVHPr4Uez8AAIC/wsVHPr4Uez8AAIA/wsVHPr4Uez8AAIA/wsVHPr4Uez8AAIA/wsVHPl6DbD8AAIC/Fu/DPl6DbD8AAIC/Fu/DPl6DbD8AAIC/Fu/DPl6DbD8AAIA/Fu/DPl6DbD8AAIA/Fu/DPl6DbD8AAIA/Fu/DPjHbVD8AAIC/2jkOPzHbVD8AAIC/2jkOPzHbVD8AAIC/2jkOPzHbVD8AAIA/2jkOPzHbVD8AAIA/2jkOPzHbVD8AAIA/2jkOP/MENT8AAIC/8wQ1P/MENT8AAIC/8wQ1P/MENT8AAIC/8wQ1P/MENT8AAIA/8wQ1P/MENT8AAIA/8wQ1P/MENT8AAIA/8wQ1P9o5Dj8AAIC/MdtUP9o5Dj8AAIC/MdtUP9o5Dj8AAIC/MdtUP9o5Dj8AAIA/MdtUP9o5Dj8AAIA/MdtUP9o5Dj8AAIA/MdtUPxbvwz4AAIC/XoNsPxbvwz4AAIC/XoNsPxbvwz4AAIC/XoNsPxbvwz4AAIA/XoNsPxbvwz4AAIA/XoNsPxbvwz4AAIA/XoNsP8LFRz4AAIC/vhR7P8LFRz4AAIC/vhR7P8LFRz4AAIC/vhR7P8LFRz4AAIA/vhR7P8LFRz4AAIA/vhR7P8LFRz4AAIA/vhR7PwAAAAAAAIC/AACAPwAAAAAAAIC/AACAPwAAAAAAAIC/AACAPwAAAAAAAIA/AACAPwAAAAAAAIA/AACAPwAAAAAAAIA/AACAP8LFR74AAIC/vhR7P8LFR74AAIC/vhR7P8LFR74AAIC/vhR7P8LFR74AAIA/vhR7P8LFR74AAIA/vhR7P8LFR74AAIA/vhR7Pxbvw74AAIC/XoNsPxbvw74AAIC/XoNsPxbvw74AAIC/XoNsPxbvw74AAIA/XoNsPxbvw74AAIA/XoNsPxbvw74AAIA/XoNsP9o5Dr8AAIC/MdtUP9o5Dr8AAIC/MdtUP9o5Dr8AAIC/MdtUP9o5Dr8AAIA/MdtUP9o5Dr8AAIA/MdtUP9o5Dr8AAIA/MdtUP/MENb8AAIC/8wQ1P/MENb8AAIC/8wQ1P/MENb8AAIC/8wQ1P/MENb8AAIA/8wQ1P/MENb8AAIA/8wQ1P/MENb8AAIA/8wQ1PzHbVL8AAIC/2jkOPzHbVL8AAIC/2jkOPzHbVL8AAIC/2jkOPzHbVL8AAIA/2jkOPzHbVL8AAIA/2jkOPzHbVL8AAIA/2jkOP16DbL8AAIC/Fu/DPl6DbL8AAIC/Fu/DPl6DbL8AAIC/Fu/DPl6DbL8AAIA/Fu/DPl6DbL8AAIA/Fu/DPl6DbL8AAIA/Fu/DPr4Ue78AAIC/wsVHPr4Ue78AAIC/wsVHPr4Ue78AAIC/wsVHPr4Ue78AAIA/wsVHPr4Ue78AAIA/wsVHPr4Ue78AAIA/wsVHPgAAgL8AAIC/AAAAgAAAgL8AAIC/AAAAgAAAgL8AAIC/AAAAgAAAgL8AAIA/AAAAgAAAgL8AAIA/AAAAgAAAgL8AAIA/AAAAgL4Ue78AAIC/wsVHvr4Ue78AAIC/wsVHvr4Ue78AAIC/wsVHvr4Ue78AAIA/wsVHvr4Ue78AAIA/wsVHvr4Ue78AAIA/wsVHvl6DbL8AAIC/Fu/Dvl6DbL8AAIC/Fu/Dvl6DbL8AAIC/Fu/Dvl6DbL8AAIA/Fu/Dvl6DbL8AAIA/Fu/Dvl6DbL8AAIA/Fu/DvjHbVL8AAIC/2jkOvzHbVL8AAIC/2jkOvzHbVL8AAIC/2jkOvzHbVL8AAIA/2jkOvzHbVL8AAIA/2jkOvzHbVL8AAIA/2jkOv/MENb8AAIC/8wQ1v/MENb8AAIC/8wQ1v/MENb8AAIC/8wQ1v/MENb8AAIA/8wQ1v/MENb8AAIA/8wQ1v/MENb8AAIA/8wQ1v9o5Dr8AAIC/MdtUv9o5Dr8AAIC/MdtUv9o5Dr8AAIC/MdtUv9o5Dr8AAIA/MdtUv9o5Dr8AAIA/MdtUv9o5Dr8AAIA/MdtUvxbvw74AAIC/XoNsvxbvw74AAIC/XoNsvxbvw74AAIC/XoNsvxbvw74AAIA/XoNsvxbvw74AAIA/XoNsvxbvw74AAIA/XoNsv8LFR74AAIC/vhR7v8LFR74AAIC/vhR7v8LFR74AAIC/vhR7v8LFR74AAIA/vhR7v8LFR74AAIA/vhR7v8LFR74AAIA/vhR7v0q9yL0AAAAAbcR+v88GpLIAAIC/AAAAgEq9yD0AAAAAbcR+v0q9yL0AAAAAbcR+v84GpDL//38/AAAAgEq9yD0AAAAAbcR+v88GpLIAAIC/AAAAgEq9yD0AAAAAbcR+vzCglD4AAAAAC/p0v84GpDL//38/AAAAgEq9yD0AAAAAbcR+vzCglD4AAAAAC/p0v88GpLIAAIC/AAAAgDCglD4AAAAAC/p0v+la8T4AAAAAmMVhv84GpDL//38/AAAAgDCglD4AAAAAC/p0v+la8T4AAAAAmMVhv88GpLIAAIC/AAAAgOla8T4AAAAAmMVhv5pnIj8AAAAAAuRFv84GpDL//38/AAAAgOla8T4AAAAAmMVhv5pnIj8AAAAAAuRFv88GpLIAAIC/AAAAgJpnIj8AAAAAAuRFvwLkRT8AAAAAmmciv84GpDL//38/AAAAgJpnIj8AAAAAAuRFvwLkRT8AAAAAmmciv88GpLIAAIC/AAAAgALkRT8AAAAAmmciv5jFYT8AAAAA6Vrxvs4GpDL//38/AAAAgALkRT8AAAAAmmciv5jFYT8AAAAA6Vrxvs8GpLIAAIC/AAAAgJjFYT8AAAAA6Vrxvgv6dD8AAAAAMKCUvs4GpDL//38/AAAAgJjFYT8AAAAA6Vrxvgv6dD8AAAAAMKCUvs8GpLIAAIC/AAAAgAv6dD8AAAAAMKCUvm3Efj8AAAAASr3Ivc4GpDL//38/AAAAgAv6dD8AAAAAMKCUvm3Efj8AAAAASr3Ivc8GpLIAAIC/AAAAgG3Efj8AAAAASr3IvW3Efj8AAAAASr3IPc4GpDL//38/AAAAgG3Efj8AAAAASr3IvW3Efj8AAAAASr3IPc8GpLIAAIC/AAAAgAv6dD8AAAAAMKCUPm3Efj8AAAAASr3IPc4GpDL//38/AAAAgAv6dD8AAAAAMKCUPm3Efj8AAAAASr3IPc8GpLIAAIC/AAAAgJjFYT8AAAAA6VrxPgv6dD8AAAAAMKCUPs4GpDL//38/AAAAgJjFYT8AAAAA6VrxPgv6dD8AAAAAMKCUPs8GpLIAAIC/AAAAgALkRT8AAAAAmmciP5jFYT8AAAAA6VrxPs4GpDL//38/AAAAgALkRT8AAAAAmmciP5jFYT8AAAAA6VrxPs8GpLIAAIC/AAAAgJpnIj8AAAAAAuRFPwLkRT8AAAAAmmciP84GpDL//38/AAAAgJpnIj8AAAAAAuRFPwLkRT8AAAAAmmciP88GpLIAAIC/AAAAgOla8T4AAAAAmMVhP5pnIj8AAAAAAuRFP84GpDL//38/AAAAgOla8T4AAAAAmMVhP5pnIj8AAAAAAuRFP88GpLIAAIC/AAAAgDCglD4AAAAAC/p0P+la8T4AAAAAmMVhP84GpDL//38/AAAAgDCglD4AAAAAC/p0P+la8T4AAAAAmMVhP88GpLIAAIC/AAAAgEq9yD0AAAAAbcR+PzCglD4AAAAAC/p0P84GpDL//38/AAAAgEq9yD0AAAAAbcR+PzCglD4AAAAAC/p0P0q9yL0AAAAAbcR+P88GpLIAAIC/AAAAgEq9yD0AAAAAbcR+P0q9yL0AAAAAbcR+P84GpDL//38/AAAAgEq9yD0AAAAAbcR+PzCglL4AAAAAC/p0P0q9yL0AAAAAbcR+P88GpLIAAIC/AAAAgDCglL4AAAAAC/p0P0q9yL0AAAAAbcR+P84GpDL//38/AAAAgOla8b4AAAAAmMVhPzCglL4AAAAAC/p0P88GpLIAAIC/AAAAgOla8b4AAAAAmMVhPzCglL4AAAAAC/p0P84GpDL//38/AAAAgJpnIr8AAAAAAuRFP+la8b4AAAAAmMVhP88GpLIAAIC/AAAAgJpnIr8AAAAAAuRFP+la8b4AAAAAmMVhP84GpDL//38/AAAAgALkRb8AAAAAmmciP5pnIr8AAAAAAuRFP88GpLIAAIC/AAAAgALkRb8AAAAAmmciP5pnIr8AAAAAAuRFP84GpDL//38/AAAAgJjFYb8AAAAA6VrxPgLkRb8AAAAAmmciP88GpLIAAIC/AAAAgJjFYb8AAAAA6VrxPgLkRb8AAAAAmmciP84GpDL//38/AAAAgAv6dL8AAAAAMKCUPpjFYb8AAAAA6VrxPs8GpLIAAIC/AAAAgAv6dL8AAAAAMKCUPpjFYb8AAAAA6VrxPs4GpDL//38/AAAAgG3Efr8AAAAASr3IPQv6dL8AAAAAMKCUPs8GpLIAAIC/AAAAgG3Efr8AAAAASr3IPQv6dL8AAAAAMKCUPs4GpDL//38/AAAAgG3Efr8AAAAASr3IvW3Efr8AAAAASr3IPc8GpLIAAIC/AAAAgG3Efr8AAAAASr3IvW3Efr8AAAAASr3IPc4GpDL//38/AAAAgG3Efr8AAAAASr3IvQv6dL8AAAAAMKCUvs8GpLIAAIC/AAAAgG3Efr8AAAAASr3IvQv6dL8AAAAAMKCUvs4GpDL//38/AAAAgAv6dL8AAAAAMKCUvpjFYb8AAAAA6Vrxvs8GpLIAAIC/AAAAgAv6dL8AAAAAMKCUvpjFYb8AAAAA6Vrxvs4GpDL//38/AAAAgJjFYb8AAAAA6VrxvgLkRb8AAAAAmmciv88GpLIAAIC/AAAAgJjFYb8AAAAA6VrxvgLkRb8AAAAAmmciv84GpDL//38/AAAAgALkRb8AAAAAmmciv5pnIr8AAAAAAuRFv88GpLIAAIC/AAAAgALkRb8AAAAAmmciv5pnIr8AAAAAAuRFv84GpDL//38/AAAAgJpnIr8AAAAAAuRFv+la8b4AAAAAmMVhv88GpLIAAIC/AAAAgJpnIr8AAAAAAuRFv+la8b4AAAAAmMVhv84GpDL//38/AAAAgOla8b4AAAAAmMVhvzCglL4AAAAAC/p0v88GpLIAAIC/AAAAgOla8b4AAAAAmMVhvzCglL4AAAAAC/p0v84GpDL//38/AAAAgDCglL4AAAAAC/p0v0q9yL0AAAAAbcR+v88GpLIAAIC/AAAAgDCglL4AAAAAC/p0v0q9yL0AAAAAbcR+v84GpDL//38/AAAAgAAAAAAAAAA/AABAP1yPAj8AAIA/AAAAPwAAAAAAAAAAAACAPlyPAj8AAIA/AAAAAIH8Sz+VvQM/AAB4PwAAAD8AAHg/AAAAPwP5lz6VvQM/AAB4PwAAAAAAAHg/AAAAABeDVz+iPAc/AABwPwAAAD8AAHA/AAAAPy4Grz6iPAc/AABwPwAAAAAAAHA/AAAAAF0iYj8d6gw/AABoPwAAAD8AAGg/AAAAP7pExD4d6gw/AABoPwAAAAAAAGg/AAAAANRxaz8sjhQ/AABgPwAAAD8AAGA/AAAAP6jj1j4sjhQ/AABgPwAAAAAAAGA/AAAAAOMVcz+j3R0/AABYPwAAAD8AAFg/AAAAP8Yr5j6j3R0/AABYPwAAAAAAAFg/AAAAAF7DeD/pfCg/AABQPwAAAD8AAFA/AAAAP7yG8T7pfCg/AABQPwAAAAAAAFA/AAAAAGtCfD9+AzQ/AABIPwAAAD8AAEg/AAAAP9aE+D5+AzQ/AABIPwAAAAAAAEg/AAAAAKRwfT8AAEA/AABAPwAAAD8AAEA/AAAAP0jh+j4AAEA/AABAPwAAAAAAAEA/AAAAAGtCfD+C/Es/AAA4PwAAAD8AADg/AAAAP9aE+D6C/Es/AAA4PwAAAAAAADg/AAAAAF7DeD8Xg1c/AAAwPwAAAD8AADA/AAAAP7yG8T4Xg1c/AAAwPwAAAAAAADA/AAAAAOMVcz9dImI/AAAoPwAAAD8AACg/AAAAP8Yr5j5dImI/AAAoPwAAAAAAACg/AAAAANRxaz/UcWs/AAAgPwAAAD8AACA/AAAAP6jj1j7UcWs/AAAgPwAAAAAAACA/AAAAAF0iYj/jFXM/AAAYPwAAAD8AABg/AAAAP7pExD7jFXM/AAAYPwAAAAAAABg/AAAAABeDVz9ew3g/AAAQPwAAAD8AABA/AAAAPy4Grz5ew3g/AAAQPwAAAAAAABA/AAAAAIH8Sz9rQnw/AAAIPwAAAD8AAAg/AAAAPwP5lz5rQnw/AAAIPwAAAAAAAAg/AAAAAAAAAD8AAAA/AABAP6RwfT8AAAA/AAAAPwAAAD8AAAAAAACAPqRwfT8AAAA/AAAAAAAA8D4AAAA/AADwPgAAAD9/AzQ/a0J8PwAA8D4AAAAAAADwPgAAAAD6DVA+a0J8PwAA4D4AAAA/AADgPgAAAD/pfCg/XsN4PwAA4D4AAAAAAADgPgAAAACk8yE+XsN4PwAA0D4AAAA/AADQPgAAAD+j3R0/4xVzPwAA0D4AAAAAAADQPgAAAAAW7e494xVzPwAAwD4AAAA/AADAPgAAAD8sjhQ/1HFrPwAAwD4AAAAAAADAPgAAAABicaQ91HFrPwAAsD4AAAA/AACwPgAAAD8d6gw/XSJiPwAAsD4AAAAAAACwPgAAAADUoU49XSJiPwAAoD4AAAA/AACgPgAAAD+iPAc/F4NXPwAAoD4AAAAAAACgPgAAAAA4lOc8F4NXPwAAkD4AAAA/AACQPgAAAD+VvQM/gvxLPwAAkD4AAAAAAACQPgAAAABAZW88gvxLPwAAgD4AAAA/AACAPgAAAD9cjwI/AABAPwAAgD4AAAAAAACAPgAAAAAQ1yM8AABAPwAAYD4AAAA/AABgPgAAAD+VvQM/fgM0PwAAYD4AAAAAAABgPgAAAABAZW88fgM0PwAAQD4AAAA/AABAPgAAAD+iPAc/6XwoPwAAQD4AAAAAAABAPgAAAAA4lOc86XwoPwAAID4AAAA/AAAgPgAAAD8d6gw/o90dPwAAID4AAAAAAAAgPgAAAADUoU49o90dPwAAAD4AAAA/AAAAPgAAAD8sjhQ/LI4UPwAAAD4AAAAAAAAAPgAAAABicaQ9LI4UPwAAwD0AAAA/AADAPQAAAD+j3R0/HeoMPwAAwD0AAAAAAADAPQAAAAAW7e49HeoMPwAAgD0AAAA/AACAPQAAAD/pfCg/ojwHPwAAgD0AAAAAAACAPQAAAACk8yE+ojwHPwAAAD0AAAA/AAAAPQAAAD9/AzQ/lb0DPwAAAD0AAAAAAAAAPQAAAAD6DVA+lb0DPwIABQAKAAIACgAHAAgACwAQAAgAEAANAA4AEQAWAA4AFgATABQAFwAcABQAHAAZABoAHQAiABoAIgAfACAAIwAoACAAKAAlACYAKQAuACYALgArACwALwA0ACwANAAxADIANQA7ADIAOwA4ADcAOgBBADcAQQA+AD0AQABHAD0ARwBEAEMARgBNAEMATQBKAEkATABTAEkAUwBQAE8AUgBZAE8AWQBWAFUAWABfAFUAXwBcAFsAXgBlAFsAZQBiAGAAYwBqAGAAagBnAGYAaQBwAGYAcABtAGwAbwB2AGwAdgBzAHIAdQB8AHIAfAB5AHgAewCCAHgAggB/AH4AgQCIAH4AiACFAIQAhwCOAIQAjgCLAIoAjQCUAIoAlACRAJAAkwCZAJAAmQCWAJcAmgCfAJcAnwCcAJ0AoAClAJ0ApQCiAKMApgCrAKMAqwCoAKkArACxAKkAsQCuAK8AsgC3AK8AtwC0AA8ACQAEAAQAvwC5ALkAswCtAK0ApwChAKEAmwCVAJUAjwCJAIkAgwB9AH0AdwBxAHEAawBkAGQAXQBXAFcAUQBLAEsARQA/AD8AOQAzADMALQAnACcAIQAbABsAFQAPAA8ABAC5ALkArQChAKEAlQCJAIkAfQBxAHEAZABXAFcASwA/AD8AMwAnACcAGwAPAA8AuQChAKEAiQBxAHEAVwA/AD8AJwAPAA8AoQBxAHEAPwAPALUAuAC9ALUAvQC6ALsAvgADALsAAwAAALwAAQAGAAYADAASABIAGAAeAB4AJAAqACoAMAA2ADYAPABCAEIASABOAE4AVABaAFoAYQBoAGgAbgB0AHQAegCAAIAAhgCMAIwAkgCYAJgAngCkAKQAqgCwALAAtgC8ALwABgASABIAHgAqACoANgBCAEIATgBaAFoAaAB0AHQAgACMAIwAmACkAKQAsAC8ALwAEgAqACoAQgBaAFoAdACMAIwApAC8ALwAKgBaAFoAjAC8AAAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL+e/ABAAACAPwAAgL+e/ABAAACAPwAAgL+e/ABAAACAPwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL+e/ABAAACAvwAAgL+e/ABAAACAvwAAgL+e/ABAAACAvwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD+e/ABAAACAPwAAgD+e/ABAAACAPwAAgD+e/ABAAACAPwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD+e/ABAAACAvwAAgD+e/ABAAACAvwAAgD+e/ABAAACAv6o7IkAvtmO/RfrJv6o7IkAvtmO/RfrJv6o7IkAvtmO/RfrJv6o7IkDuztk+RfrJv6o7IkDuztk+RfrJv6o7IkDuztk+RfrJv6o7IkAvtmO/tECewKo7IkAvtmO/tECewKo7IkAvtmO/tECewKo7IkDuztk+tECewKo7IkDuztk+tECewKo7IkDuztk+tECewPjfvEAvtmO/RfrJv/jfvEAvtmO/RfrJv/jfvEAvtmO/RfrJv/jfvEDuztk+RfrJv/jfvEDuztk+RfrJv/jfvEDuztk+RfrJv/jfvEAvtmO/tECewPjfvEAvtmO/tECewPjfvEAvtmO/tECewPjfvEDuztk+tECewPjfvEDuztk+tECewPjfvEDuztk+tECewGoxfUCIQG6/bzEGQGoxfUCIQG6/bzEGQGoxfUCIQG6/bzEGQAGyjUCIQG6/1ioJQAGyjUCIQG6/1ioJQAGyjUCIQG6/1ioJQMI2nECIQG6/w/kRQMI2nECIQG6/w/kRQMI2nECIQG6/w/kRQCOYqUCIQG6/kkcgQCOYqUCIQG6/kkcgQCOYqUCIQG6/kkcgQINStUCIQG6/iYczQINStUCIQG6/iYczQINStUCIQG6/iYczQH7yvkCIQG6/R/xKQH7yvkCIQG6/R/xKQH7yvkCIQG6/R/xKQGUZxkCIQG6/Cr9lQGUZxkCIQG6/Cr9lQGUZxkCIQG6/Cr9lQN2AykCIQG6/RmSBQN2AykCIQG6/RmSBQN2AykCIQG6/RmSBQJD9y0CIQG6/kn2QQJD9y0CIQG6/kn2QQJD9y0CIQG6/kn2QQN2AykCIQG6/3pafQN2AykCIQG6/3pafQN2AykCIQG6/3pafQGUZxkCIQG6/nxuuQGUZxkCIQG6/nxuuQGUZxkCIQG6/nxuuQH7yvkCIQG6/AH27QH7yvkCIQG6/AH27QH7yvkCIQG6/AH27QINStUCIQG6/YDfHQINStUCIQG6/YDfHQINStUCIQG6/YDfHQCOYqUCIQG6/W9fQQCOYqUCIQG6/W9fQQCOYqUCIQG6/W9fQQMI2nECIQG6/Qv7XQMI2nECIQG6/Qv7XQMI2nECIQG6/Qv7XQAGyjUCIQG6/uWXcQAGyjUCIQG6/uWXcQAGyjUCIQG6/uWXcQGoxfUCIQG6/bOLdQGoxfUCIQG6/bOLdQGoxfUCIQG6/bOLdQNP+XkCIQG6/uWXcQNP+XkCIQG6/uWXcQNP+XkCIQG6/uWXcQFD1QUCIQG6/Qv7XQFD1QUCIQG6/Qv7XQFD1QUCIQG6/Qv7XQI4yJ0CIQG6/W9fQQI4yJ0CIQG6/W9fQQI4yJ0CIQG6/W9fQQNC9D0CIQG6/YDfHQNC9D0CIQG6/YDfHQNC9D0CIQG6/YDfHQLH7+D+IQG6/AH27QLH7+D+IQG6/AH27QLH7+D+IQG6/AH27QBNg3D+IQG6/nxuuQBNg3D+IQG6/nxuuQBNg3D+IQG6/nxuuQDfCyj+IQG6/3pafQDfCyj+IQG6/3pafQDfCyj+IQG6/3pafQGvPxD+IQG6/kn2QQGvPxD+IQG6/kn2QQGvPxD+IQG6/kn2QQDfCyj+IQG6/RmSBQDfCyj+IQG6/RmSBQDfCyj+IQG6/RmSBQBNg3D+IQG6/Cr9lQBNg3D+IQG6/Cr9lQBNg3D+IQG6/Cr9lQLH7+D+IQG6/R/xKQLH7+D+IQG6/R/xKQLH7+D+IQG6/R/xKQNC9D0CIQG6/iYczQNC9D0CIQG6/iYczQNC9D0CIQG6/iYczQI4yJ0CIQG6/kkcgQI4yJ0CIQG6/kkcgQI4yJ0CIQG6/kkcgQFD1QUCIQG6/w/kRQFD1QUCIQG6/w/kRQFD1QUCIQG6/w/kRQNP+XkCIQG6/1ioJQNP+XkCIQG6/1ioJQNP+XkCIQG6/1ioJQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQGoxfUBYRnU/kn2QQAAAgL8AAAAAAAAAgAAAAAAAAIC/AAAAgAAAAAAAAAAAAACAPwAAgL8AAAAAAAAAgAAAAAAAAAAAAACAPwAAAAAAAIA/AAAAgAAAgL8AAAAAAAAAgAAAAAAAAIC/AAAAgAAAAAAAAAAAAACAvwAAgL8AAAAAAAAAgAAAAAAAAAAAAACAvwAAAAAAAIA/AAAAgAAAAAAAAIC/AAAAgAAAAAAAAAAAAACAPwAAgD8AAAAAAAAAgAAAAAAAAAAAAACAPwAAAAAAAIA/AAAAgAAAgD8AAAAAAAAAgAAAAAAAAIC/AAAAgAAAAAAAAAAAAACAvwAAgD8AAAAAAAAAgAAAAAAAAAAAAACAvwAAAAAAAIA/AAAAgAAAgD8AAAAAAAAAgAAAgL8AAAAAAAAAgAAAAAAAAIC/AAAAgAAAAAAAAAAAAACAPwAAgL8AAAAAAAAAgAAAAAAAAAAAAACAPwAAAAAAAIA/AAAAgAAAgL8AAAAAAAAAgAAAAAAAAIC/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AADgPv//3z4AAAA/AADQPvD/fz0AANA+AAAAPgAA0D78/z8+AADQPgAAgD4AANA+/v+fPgAA0D7+/78+AADQPgAA4D7//88+AAAAPwAAwD7w/389AADAPgAAAD7//78+/P8/PgAAwD4AAIA+AADAPv7/nz4AAMA+/v+/PgAAwD4AAOA+/v+/PgAAAD8AALA+8P9/PQAAsD4AAAA+AACwPvz/Pz4AALA+AACAPgAAsD7+/58+AACwPv7/vz4AALA+AADgPv7/rz4AAAA/AACgPvD/fz0AAKA+AAAAPgAAoD78/z8+AACgPgAAgD4AAKA+/v+fPgAAoD7+/78+AACgPgAA4D7//58+AAAAPwAAkD7w/389AACQPgAAAD7//48+/P8/PgAAkD4AAIA+AACQPv7/nz4AAJA+/v+/PgAAkD4AAOA+/v+PPgAAAD8AAIA+8P9/Pf7/fz4AAAA+/v9/Pvz/Pz4AAIA+AACAPgAAgD7+/58+AACAPv7/vz7+/38+AADgPv7/fz4AAAA/AABgPvD/fz0AAGA+AAAAPgAAYD78/z8+AABgPgAAgD4AAGA+/v+fPgIAYD7+/78+AABgPgAA4D78/18+AAAAPwAAQD7w/389AABAPgAAAD7+/z8+/P8/PgAAQD4AAIA+AABAPv7/nz4AAEA+/v+/PgAAQD4AAOA+/v8/PgAAAD8CACA+8P9/Pf7/Hz4AAAA+/v8fPvj/Pz4CACA+AACAPv7/Hz7+/58+AgAgPv7/vz7+/x8+AADgPvz/Hz4AAAA/AAAAPvD/fz0AAAA+AAAAPvz//z34/z8+AAAAPgAAgD78//89/v+fPgAAAD7+/78+/P//PQAA4D74//89AAAAPwAAwD3w/389AADAPQAAAD78/789+P8/PgAAwD38/38+AADAPf7/nz4AAMA9/P+/Pvz/vz0AAOA+9P+/PQAAAD8AAIA98P9/PQAAgD0AAAA+AACAPfj/Pz4EAIA9AACAPgAAgD38/58+BACAPfz/vz4AAIA9AADgPvD/fz0AAAA/AAAAPfD/fz3w//88+P//PfD//zz4/z8+AAAAPQAAgD7w//88/v+fPgAAAD3+/78+8P//PAAA4D7g//88AAAAPwAAAADw/389AACAP/D/fz0AAAAA+P//PQAAgD/4//89AAAAAPj/Pz4AAIA/+P8/PgAAAAD8/38+AACAP/z/fz4AAAAA/v+fPgAAgD/+/58+AAAAAPz/vz4AAIA//P+/PgAAAAAAAOA+AACAPwAA4D4AAAAAAAAAPwAAgD8AAAA/AAB4P/D/fz3//3c/+P//Pf//dz/4/z8+AAB4P/z/fz7//3c//P+fPgAAeD/8/78+//93P/7/3z7+/3c/AAAAPwAAcD/w/389AABwP/j//z3//28/+P8/PgAAcD/8/38+//9vP/z/nz4AAHA//P+/Pv//bz/+/98+/v9vPwAAAD8AAGg/8P9/PQAAaD/4//89//9nP/j/Pz4AAGg//P9/PgAAaD/8/58+AABoP/z/vz4AAGg//v/fPv//Zz8AAAA/AABgP/D/fz0AAGA/+P//Pf7/Xz/4/z8+AABgP/z/fz7//18//P+fPgAAYD/8/78+//9fP/7/3z7+/18/AAAAPwAAWD/w/389AABYP/j//z3//1c/9P8/PgAAWD/8/38+//9XP/z/nz4AAFg//P+/Pv//Vz/+/98+/v9XPwAAAD8AAFA/4P9/PQAAUD/4//89//9PP/T/Pz4AAFA//P9/Pv//Tz/8/58+AABQP/z/vz7//08//v/fPv7/Tz8AAAA/AABIP+D/fz3//0c/+P//Pf//Rz/0/z8+AABIPwAAgD7//0c//P+fPgAASD/8/78+//9HP/7/3z7+/0c/AAAAPwAAQD/g/389//8/P/j//z0AAEA//P9/PgAAQD/8/78+JwEBAAgAJwEIAAkAAgAnAQkAAgAJAAoAAwACAAoAAwAKAAsAJAFDAAQAJQEkAQQAJQEEAAUAAAAlAQUAAAAFAAYAJgEAAAYAJgEGAAcAAQAmAQcAAQAHAAgACAAHAA8ACAAPABAACQAIABAACQAQABEACgAJABEACgARABIACwAKABIACwASABMABABCAAwABQAEAAwABQAMAA0ABgAFAA0ABgANAA4ABwAGAA4ABwAOAA8ADQAMABQADQAUABUADgANABUADgAVABYADwAOABYADwAWABcAEAAPABcAEAAXABgAEQAQABgAEQAYABkAEgARABkAEgAZABoAEwASABoAEwAaABsADABBABQAGQAYACAAGQAgACEAGgAZACEAGgAhACIAGwAaACIAGwAiACMAFABAABwAFQAUABwAFQAcAB0AFgAVAB0AFgAdAB4AFwAWAB4AFwAeAB8AGAAXAB8AGAAfACAAHQAcACQAHQAkACUAHgAdACUAHgAlACYAHwAeACYAHwAmACcAIAAfACcAIAAnACgAIQAgACgAIQAoACkAIgAhACkAIgApACoAIwAiACoAIwAqACsAHAA/ACQAKQAoAFAAKQBQAFEAKgApAFEAKgBRAFIAKwAqAFIAKwBSAFMAJAA+AEwAJQAkAEwAJQBMAE0AJgAlAE0AJgBNAE4AJwAmAE4AJwBOAE8AKAAnAE8AKABPAFAATgBNAFUATgBVAFYATwBOAFYATwBWAFcAUABPAFcAUABXAFgAUQBQAFgAUQBYAFkAUgBRAFkAUgBZAFoAUwBSAFoAUwBaAFsATAA9AFQATQBMAFQATQBUAFUAWgBZAGEAWgBhAGIAWwBaAGIAWwBiAGMAVAA8AFwAVQBUAFwAVQBcAF0AVgBVAF0AVgBdAF4AVwBWAF4AVwBeAF8AWABXAF8AWABfAGAAWQBYAGAAWQBgAGEAXwBeAGYAXwBmAGcAYABfAGcAYABnAGgAYQBgAGgAYQBoAGkAYgBhAGkAYgBpAGoAYwBiAGoAYwBqAGsAXAA7AGQAXQBcAGQAXQBkAGUAXgBdAGUAXgBlAGYAawBqAHIAawByAHMAZAA6AGwAZQBkAGwAZQBsAG0AZgBlAG0AZgBtAG4AZwBmAG4AZwBuAG8AaABnAG8AaABvAHAAaQBoAHAAaQBwAHEAagBpAHEAagBxAHIAbwBuAHYAbwB2AHcAcABvAHcAcAB3AHgAcQBwAHgAcQB4AHkAcgBxAHkAcgB5AHoAcwByAHoAcwB6AHsAbAA5AHQAbQBsAHQAbQB0AHUAbgBtAHUAbgB1AHYAewB6AIIAewCCAIMAdAA4AHwAdQB0AHwAdQB8AH0AdgB1AH0AdgB9AH4AdwB2AH4AdwB+AH8AeAB3AH8AeAB/AIAAeQB4AIAAeQCAAIEAegB5AIEAegCBAIIAgAB/AIcAgACHAIgAgQCAAIgAgQCIAIkAggCBAIkAggCJAIoAgwCCAIoAgwCKAIsAfAA3AIQAfQB8AIQAfQCEAIUAfgB9AIUAfgCFAIYAfwB+AIYAfwCGAIcAhAA2AIwAhQCEAIwAhQCMAI0AhgCFAI0AhgCNAI4AhwCGAI4AhwCOAI8AiACHAI8AiACPAJAAiQCIAJAAiQCQAJEAigCJAJEAigCRAJIAiwCKAJIAiwCSAJMAkACPAJcAkACXAJgAkQCQAJgAkQCYAJkAkgCRAJkAkgCZAJoAkwCSAJoAkwCaAJsAjAA1AJQAjQCMAJQAjQCUAJUAjgCNAJUAjgCVAJYAjwCOAJYAjwCWAJcAlQCUAJwAlQCcAJ0AlgCVAJ0AlgCdAJ4AlwCWAJ4AlwCeAJ8AmACXAJ8AmACfAKAAmQCYAKAAmQCgAKEAmgCZAKEAmgChAKIAmwCaAKIAmwCiAKMAlAA0AJwAoQCgAKgAoQCoAKkAogChAKkAogCpAKoAowCiAKoAowCqAKsAnAAzAKQAnQCcAKQAnQCkAKUAngCdAKUAngClAKYAnwCeAKYAnwCmAKcAoACfAKcAoACnAKgApgClAK0ApgCtAK4ApwCmAK4ApwCuAK8AqACnAK8AqACvALAAqQCoALAAqQCwALEAqgCpALEAqgCxALIAqwCqALIAqwCyALMApAAyAKwApQCkAKwApQCsAK0AsgCxALkAsgC5ALoAswCyALoAswC6ALsArAAxALQArQCsALQArQC0ALUArgCtALUArgC1ALYArwCuALYArwC2ALcAsACvALcAsAC3ALgAsQCwALgAsQC4ALkAtgC1AL0AtgC9AL4AtwC2AL4AtwC+AL8AuAC3AL8AuAC/AMAAuQC4AMAAuQDAAMEAugC5AMEAugDBAMIAuwC6AMIAuwDCAMMAtAAwALwAtQC0ALwAtQC8AL0AwgDBAMkAwgDJAMoAwwDCAMoAwwDKAMsAvAAvAMQAvQC8AMQAvQDEAMUAvgC9AMUAvgDFAMYAvwC+AMYAvwDGAMcAwAC/AMcAwADHAMgAwQDAAMgAwQDIAMkAxwDGAM4AxwDOAM8AyADHAM8AyADPANAAyQDIANAAyQDQANEAygDJANEAygDRANIAywDKANIAywDSANMAxAAuAMwAxQDEAMwAxQDMAM0AxgDFAM0AxgDNAM4A0wDSANoA0wDaANsAzAAtANQAzQDMANQAzQDUANUAzgDNANUAzgDVANYAzwDOANYAzwDWANcA0ADPANcA0ADXANgA0QDQANgA0QDYANkA0gDRANkA0gDZANoA1wDWAOAA1wDgAOIA2ADXAOIA2ADiAOQA2QDYAOQA2QDkAOYA2gDZAOYA2gDmAOgA2wDaAOgA2wDoAOoA1AAsANwA1QDUANwA1QDcAN4A1gDVAN4A1gDeAOAA6wDpAPIA6wDyAPMA3QBLAOwA3wDdAOwA3wDsAO0A4QDfAO0A4QDtAO4A4wDhAO4A4wDuAO8A5QDjAO8A5QDvAPAA5wDlAPAA5wDwAPEA6QDnAPEA6QDxAPIA8ADvAPcA8AD3APgA8QDwAPgA8QD4APkA8gDxAPkA8gD5APoA8wDyAPoA8wD6APsA7ABKAPQA7QDsAPQA7QD0APUA7gDtAPUA7gD1APYA7wDuAPYA7wD2APcA9QD0APwA9QD8AP0A9gD1AP0A9gD9AP4A9wD2AP4A9wD+AP8A+AD3AP8A+AD/AAAB+QD4AAAB+QAAAQEB+gD5AAEB+gABAQIB+wD6AAIB+wACAQMB9ABJAPwAAQEAAQgBAQEIAQkBAgEBAQkBAgEJAQoBAwECAQoBAwEKAQsB/ABIAAQB/QD8AAQB/QAEAQUB/gD9AAUB/gAFAQYB/wD+AAYB/wAGAQcBAAH/AAcBAAEHAQgBBQEEAQwBBQEMAQ0BBgEFAQ0BBgENAQ4BBwEGAQ4BBwEOAQ8BCAEHAQ8BCAEPARABCQEIARABCQEQAREBCgEJAREBCgERARIBCwEKARIBCwESARMBBAFHAAwBEQEQARgBEQEYARkBEgERARkBEgEZARoBEwESARoBEwEaARsBDAFGABQBDQEMARQBDQEUARUBDgENARUBDgEVARYBDwEOARYBDwEWARcBEAEPARcBEAEXARgBFgEVAR0BFgEdAR4BFwEWAR4BFwEeAR8BGAEXAR8BGAEfASABGQEYASABGQEgASEBGgEZASEBGgEhASIBGwEaASIBGwEiASMBFAFFABwBFQEUARwBFQEcAR0BIgEhAScBIgEnAQIAIwEiAQIAIwECAAMAHAFEACQBHQEcASQBHQEkASUBHgEdASUBHgElAQAAHwEeAQAAHwEAACYBIAEfASYBIAEmAQEAIQEgAQEAIQEBACcBAACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIC/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgD8AAIA/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIC/AACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAvwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAvwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIA/AACAPwAAAAAAAACAAAAAAAAAAAAAAIA/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAAAAAAAAgL8AAACAAAAAAAAAAAAAAIC/AACAPwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAgD8AAACAAACAPwAAAAAAAACAAADAPgAAgD8AAAA+AACAPgAAwD4AAAAAAAAgPwAAgD8AACA/AAAAAAAAYD8AAIA+AADAPgAAQD8AAAA+AAAAPwAAwD4AAEA/AAAgPwAAQD8AACA/AABAPwAAYD8AAAA/AADAPgAAgD4AAMA+AACAPgAAwD4AAIA+AAAgPwAAgD4AACA/AACAPgAAID8AAIA+AADAPgAAAD8AAMA+AAAAPwAAwD4AAAA/AAAgPwAAAD8AACA/AAAAPwAAID8AAAA/AAADAAkAAAAJAAYACAAKABUACAAVABMAFAAXABEAFAARAA4ADQAPAAQADQAEAAIABwASAAwABwAMAAEAFgALAAUAFgAFABAA" + } + ] +} diff --git a/example/threejs.basic/index.html b/example/threejs.basic/index.html new file mode 100644 index 0000000..79d461e --- /dev/null +++ b/example/threejs.basic/index.html @@ -0,0 +1,233 @@ + + + + three.js vr - sandbox + + + + + + + + + + + + + + diff --git a/example/threejs.basic/main.css b/example/threejs.basic/main.css new file mode 100644 index 0000000..d496122 --- /dev/null +++ b/example/threejs.basic/main.css @@ -0,0 +1,91 @@ +body { + margin: 0; + background-color: #000; + color: #fff; + font-family: Monospace; + font-size: 13px; + line-height: 24px; + overscroll-behavior: none; +} + +a { + color: #ff0; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +button { + cursor: pointer; + text-transform: uppercase; +} + +#info { + position: absolute; + top: 0px; + width: 100%; + padding: 10px; + box-sizing: border-box; + text-align: center; + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; + pointer-events: none; + z-index: 1; /* TODO Solve this in HTML */ +} + +a, button, input, select { + pointer-events: auto; +} + +.lil-gui { + z-index: 2 !important; /* TODO Solve this in HTML */ +} + +@media all and ( max-width: 640px ) { + .lil-gui.root { + right: auto; + top: auto; + max-height: 50%; + max-width: 80%; + bottom: 0; + left: 0; + } +} + +#overlay { + position: absolute; + font-size: 16px; + z-index: 2; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + background: rgba(0,0,0,0.7); +} + + #overlay button { + background: transparent; + border: 0; + border: 1px solid rgb(255, 255, 255); + border-radius: 4px; + color: #ffffff; + padding: 12px 18px; + text-transform: uppercase; + cursor: pointer; + } + +#notSupported { + width: 50%; + margin: auto; + background-color: #f00; + margin-top: 20px; + padding: 10px; +} diff --git a/serve b/serve new file mode 100755 index 0000000..e59f5c4 --- /dev/null +++ b/serve @@ -0,0 +1,3 @@ +#!/bin/bash +[[ ! -f cert.pem ]] && openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem +http-server -c-1 -S -C cert.pem . diff --git a/src/Test.hx b/src/Test.hx index c52b645..6f5f87f 100644 --- a/src/Test.hx +++ b/src/Test.hx @@ -37,6 +37,8 @@ class Test { 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 == "testBrowserOverride" ) valid = item.expect.out == (URI.parse(item.data,true)).exists(item.expect.input); + 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,true)).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.xy" ) valid = equalXY(res,item); if( item.expect.fn == "equal.xyz" ) valid = equalXYZ(res,item); diff --git a/src/spec/url.json b/src/spec/url.json index e20af12..8490e38 100644 --- a/src/spec/url.json +++ b/src/spec/url.json @@ -8,5 +8,7 @@ {"fn":"url","data":"http://foo.com?foo=1#q=-bar", "expect":{ "fn":"testBrowserOverride", "input":"q","out":false},"label":"browser URI cannot override q (defined in asset)"}, {"fn":"url","data":"http://foo.com?foo=1#mypredefinedview", "expect":{ "fn":"testPredefinedView", "input":"mypredefinedview","out":true},"label":"test predefined view executed"}, {"fn":"url","data":"http://foo.com?foo=1#mypredefinedview&another", "expect":{ "fn":"testPredefinedView", "input":"another","out":true},"label":"test predefined view executed (multiple)"}, - {"fn":"url","data":"http://foo.com?foo=1#mypredefinedview&another", "expect":{ "fn":"testPredefinedView", "input":"mypredefinedview","out":true},"label":"test predefined view executed (multiple)"} + {"fn":"url","data":"http://foo.com?foo=1#mypredefinedview&another", "expect":{ "fn":"testPredefinedView", "input":"mypredefinedview","out":true},"label":"test predefined view executed (multiple)"}, + {"fn":"url","data":"#cube.position.x=music.position.x", "expect":{ "fn":"testPropertyAssign", "input":"cube.position.x","out":true},"label":"test data assign"}, + {"fn":"url","data":"#cube.position.x=@music.position.x", "expect":{ "fn":"testPropertyAssign", "input":"cube.position.x","out":true},"label":"test one-way data bind"} ] diff --git a/src/xrfragment/Parser.hx b/src/xrfragment/Parser.hx index b7771e7..b9b8838 100644 --- a/src/xrfragment/Parser.hx +++ b/src/xrfragment/Parser.hx @@ -14,18 +14,14 @@ class Parser { var Frag:Map = new Map(); // category: asset loading linking - Frag.set("prio", XRF.ASSET_OBJ | XRF.T_INT ); + Frag.set("prio", XRF.ASSET | XRF.T_INT ); Frag.set("#", XRF.ASSET | XRF.T_PREDEFINED_VIEW ); - Frag.set("class", XRF.ASSET_OBJ | XRF.T_STRING ); - Frag.set("src", XRF.ASSET_OBJ | XRF.T_URL ); - Frag.set("src_audio", XRF.ASSET_OBJ | XRF.T_URL ); - Frag.set("src_shader", XRF.ASSET_OBJ | XRF.T_URL ); - Frag.set("src_env", XRF.ASSET | XRF.T_URL ); - Frag.set("src_env_audio", XRF.ASSET | XRF.T_URL ); + Frag.set("class", XRF.ASSET | XRF.T_STRING ); + Frag.set("src", XRF.ASSET | XRF.T_URL ); // category: href navigation / portals / teleporting Frag.set("pos", XRF.PV_OVERRIDE | XRF.ROUNDROBIN | XRF.T_VECTOR3 | XRF.T_STRING_OBJ ); - Frag.set("href", XRF.ASSET_OBJ | XRF.T_URL | XRF.T_PREDEFINED_VIEW ); + Frag.set("href", XRF.ASSET | XRF.T_URL | XRF.T_PREDEFINED_VIEW ); // category: query selector | object manipulation Frag.set("q", XRF.PV_OVERRIDE | XRF.T_STRING ); @@ -39,7 +35,6 @@ class Parser { Frag.set("gravity", XRF.ASSET | XRF.PV_OVERRIDE | XRF.T_VECTOR3 ); Frag.set("physics", XRF.ASSET | XRF.PV_OVERRIDE | XRF.T_VECTOR3 ); Frag.set("scroll", XRF.ASSET | XRF.PV_OVERRIDE | XRF.T_STRING ); - Frag.set(".", XRF.ASSET | XRF.PV_OVERRIDE | XRF.T_STRING ); // category: device / viewport settings Frag.set("fov", XRF.ASSET | XRF.PV_OVERRIDE | XRF.T_INT | XRF.BROWSER_OVERRIDE ); @@ -62,15 +57,15 @@ class Parser { * the gist of it: */ - // special cases: predefined views & assign/binds + // dynamic fragments cases: predefined views & assign/binds if( value.length == 0 && !Frag.exists(key) ){ resultMap.set(key, new XRF(key, XRF.PV_EXECUTE | XRF.BROWSER_OVERRIDE ) ); return true; } - //if( key.split(".").length > 1 && value.split(".").length > 1 ){ - // resultMap.set(key, new XRF(key, T_STRING_OBJ_PROP ) ); - // return true; - //} + if( key.split(".").length > 1 && value.split(".").length > 1 ){ + resultMap.set(key, new XRF(key, XRF.ASSET | XRF.PV_OVERRIDE | XRF.T_STRING | XRF.PROP_BIND ) ); + return true; + } // regular fragments: if( Frag.exists(key) ){ // 1. check if param exist diff --git a/src/xrfragment/XRF.hx b/src/xrfragment/XRF.hx index f17fc59..fd7013d 100644 --- a/src/xrfragment/XRF.hx +++ b/src/xrfragment/XRF.hx @@ -9,8 +9,8 @@ class XRF { // public static inline readonly ASSET // scope types (powers of 2) - public static var ASSET:Int = 1; // fragment is immutable (typed in asset) globally - public static var ASSET_OBJ:Int = 2; // fragment is immutable (typed in object in asset) + public static var ASSET:Int = 1; // fragment is immutable + public static var PROP_BIND:Int = 2; // fragment binds/controls one property with another public static var QUERY_OPERATOR:Int = 4; // fragment will be applied to result of queryselecto public static var PROMPT:Int = 8; // ask user whether this fragment value can be changed public static var ROUNDROBIN:Int = 16; // evaluation of this (multi) value can be roundrobined diff --git a/test/generated/test.js b/test/generated/test.js index 6a2e2c2..26a17eb 100644 --- a/test/generated/test.js +++ b/test/generated/test.js @@ -136,7 +136,7 @@ StringTools.replace = function(s,sub,by) { var Test = function() { }; Test.__name__ = true; Test.main = function() { - Test.test([{ fn : "url", expect : { fn : "equal.xyz", input : "pos", out : false}, label : "equal.xyz: should trigger incompatible type)", data : "http://foo.com?foo=1#pos=1.2,2.2"},{ fn : "url", expect : { fn : "equal.xyz", input : "pos", out : "1.2,2.2,3"}, label : "equal.xyz", data : "http://foo.com?foo=1#pos=1.2,2.2,3"},{ fn : "url", expect : { fn : "equal.xy", input : "t", out : "1,100"}, label : "a equal.xy", data : "http://foo.com?foo=1#t=1,100"},{ fn : "url", expect : { fn : "testParsed", input : "prio", out : false}, label : "should trigger incompatible type", data : "http://foo.com?foo=1#prio=foo"},{ fn : "url", expect : { fn : "equal.multi", input : "pos", out : "c|d|1,2,3"}, label : "b equal.multi", data : "http://foo.com?foo=1#pos=c|d|1,2,3"},{ fn : "url", expect : { fn : "testBrowserOverride", input : "t", out : true}, label : "browser URI can override t (defined in asset)", data : "http://foo.com?foo=1#t=2,500"},{ fn : "url", expect : { fn : "testBrowserOverride", input : "q", out : false}, label : "browser URI cannot override q (defined in asset)", data : "http://foo.com?foo=1#q=-bar"},{ fn : "url", expect : { fn : "testPredefinedView", input : "mypredefinedview", out : true}, label : "test predefined view executed", data : "http://foo.com?foo=1#mypredefinedview"},{ fn : "url", expect : { fn : "testPredefinedView", input : "another", out : true}, label : "test predefined view executed (multiple)", data : "http://foo.com?foo=1#mypredefinedview&another"},{ fn : "url", expect : { fn : "testPredefinedView", input : "mypredefinedview", out : true}, label : "test predefined view executed (multiple)", data : "http://foo.com?foo=1#mypredefinedview&another"}]); + Test.test([{ fn : "url", expect : { fn : "equal.xyz", input : "pos", out : false}, label : "equal.xyz: should trigger incompatible type)", data : "http://foo.com?foo=1#pos=1.2,2.2"},{ fn : "url", expect : { fn : "equal.xyz", input : "pos", out : "1.2,2.2,3"}, label : "equal.xyz", data : "http://foo.com?foo=1#pos=1.2,2.2,3"},{ fn : "url", expect : { fn : "equal.xy", input : "t", out : "1,100"}, label : "a equal.xy", data : "http://foo.com?foo=1#t=1,100"},{ fn : "url", expect : { fn : "testParsed", input : "prio", out : false}, label : "should trigger incompatible type", data : "http://foo.com?foo=1#prio=foo"},{ fn : "url", expect : { fn : "equal.multi", input : "pos", out : "c|d|1,2,3"}, label : "b equal.multi", data : "http://foo.com?foo=1#pos=c|d|1,2,3"},{ fn : "url", expect : { fn : "testBrowserOverride", input : "t", out : true}, label : "browser URI can override t (defined in asset)", data : "http://foo.com?foo=1#t=2,500"},{ fn : "url", expect : { fn : "testBrowserOverride", input : "q", out : false}, label : "browser URI cannot override q (defined in asset)", data : "http://foo.com?foo=1#q=-bar"},{ fn : "url", expect : { fn : "testPredefinedView", input : "mypredefinedview", out : true}, label : "test predefined view executed", data : "http://foo.com?foo=1#mypredefinedview"},{ fn : "url", expect : { fn : "testPredefinedView", input : "another", out : true}, label : "test predefined view executed (multiple)", data : "http://foo.com?foo=1#mypredefinedview&another"},{ fn : "url", expect : { fn : "testPredefinedView", input : "mypredefinedview", out : true}, label : "test predefined view executed (multiple)", data : "http://foo.com?foo=1#mypredefinedview&another"},{ fn : "url", expect : { fn : "testPropertyAssign", input : "cube.position.x", out : true}, label : "test data assign", data : "#cube.position.x=music.position.x"},{ fn : "url", expect : { fn : "testPropertyAssign", input : "cube.position.x", out : true}, label : "test one-way data bind", data : "#cube.position.x=@music.position.x"}]); Test.test([{ fn : "query", expect : { fn : "testProperty", input : ["class","bar"], out : true}, data : "class:bar"},{ fn : "query", expect : { fn : "testProperty", input : ["class","bar"], out : true}, label : ".bar shorthand", data : ".bar"},{ fn : "query", expect : { fn : "testProperty", input : ["class","foo"], out : false}, data : ".bar -.foo"},{ fn : "query", expect : { fn : "testProperty", input : ["class","foo"], out : true}, data : ".bar -.foo .foo"},{ fn : "query", expect : { fn : "testProperty", input : ["class","bar"], out : true}, data : ".bar -.bar .bar"},{ fn : "query", expect : { fn : "testProperty", input : ["class","foo"], out : true}, label : "class:foo", data : ".foo -.foo .foo"},{ fn : "query", expect : { fn : "testProperty", input : ["class","foo"], out : true}, label : "class:foo", data : ".foo -.foo bar:5 .foo"},{ fn : "query", expect : { fn : "testProperty", input : ["class","foo"], out : true}, label : "class:foo", data : ".foo -.foo bar:>5 .foo"},{ fn : "query", expect : { fn : "testProperty", input : ["class","foo"], out : true}, label : "class:foo", data : ".foo -.foo bar:>5 .foo"},{ fn : "query", expect : { fn : "testProperty", input : ["class","foo"], out : true}, label : "class:foo", data : ".foo -.foo .foo"},{ fn : "query", expect : { fn : "testProperty", input : ["id","foo"], out : false}, label : "!id:foo", data : ".foo -.foo .foo"},{ fn : "query", expect : { fn : "testProperty", input : ["id","foo"], out : true}, label : "id:foo?", data : "foo -foo foo"}]); Test.test([{ fn : "query", expect : { fn : "testProperty", input : ["price","10"], out : true}, data : "price:>=5"},{ fn : "query", expect : { fn : "testProperty", input : ["price","10"], out : false}, data : "price:>=15"},{ fn : "query", expect : { fn : "testProperty", input : ["price","4"], out : false}, data : "price:>=5"},{ fn : "query", expect : { fn : "testProperty", input : ["price","0"], out : false}, data : "price:>=5"},{ fn : "query", expect : { fn : "testProperty", input : ["price","1"], out : false}, label : "price=1", data : "price:>=5 price:0"},{ fn : "query", expect : { fn : "testProperty", input : ["price","0"], out : true}, label : "price=0", data : "price:>=5 price:0"},{ fn : "query", expect : { fn : "testProperty", input : ["price","6"], out : true}, label : "price=6", data : "price:>=5 price:0"},{ fn : "query", expect : { fn : "testProperty", input : ["tag","foo"], out : true}, data : "tag:foo"},{ fn : "query", expect : { fn : "testProperty", input : ["tag","foo"], out : false}, data : "-tag:foo"},{ fn : "query", expect : { fn : "testPropertyExclude", input : ["tag","foo"], out : true}, label : "testExclude", data : "-tag:foo"},{ fn : "query", expect : { fn : "test", input : [{ price : 5}], out : true}, data : ".foo price:5 -tag:foo"},{ fn : "query", expect : { fn : "test", input : [{ tag : "foo", price : 5}], out : false}, data : ".foo price:5 -tag:foo"}]); if(Test.errors > 1) { @@ -179,6 +179,14 @@ Test.test = function(spec) { var this1 = xrfragment_URI.parse(item.data,true); valid = item1 == Object.prototype.hasOwnProperty.call(this1,item.expect.input); } + if(item.expect.fn == "testPropertyAssign") { + valid = Object.prototype.hasOwnProperty.call(res,item.expect.input) && item.expect.out == res[item.expect.input].is(xrfragment_XRF.PROP_BIND); + } + if(item.expect.fn == "testBrowserOverride") { + var item2 = item.expect.out; + var this2 = xrfragment_URI.parse(item.data,true); + valid = item2 == Object.prototype.hasOwnProperty.call(this2,item.expect.input); + } if(item.expect.fn == "equal.string") { valid = res[item.expect.input] && item.expect.out == res[item.expect.input].string; } @@ -192,7 +200,7 @@ Test.test = function(spec) { valid = Test.equalMulti(res,item); } var ok = valid ? "[ ✔ ] " : "[ ❌] "; - console.log("src/Test.hx:45:",ok + Std.string(item.fn) + ": '" + Std.string(item.data) + "'" + (item.label ? " (" + (item.label ? item.label : item.expect.fn) + ")" : "")); + console.log("src/Test.hx:47:",ok + Std.string(item.fn) + ": '" + Std.string(item.data) + "'" + (item.label ? " (" + (item.label ? item.label : item.expect.fn) + ")" : "")); if(!valid) { Test.errors += 1; } @@ -318,16 +326,12 @@ var xrfragment_Parser = $hx_exports["xrfragment"]["Parser"] = function() { }; xrfragment_Parser.__name__ = true; xrfragment_Parser.parse = function(key,value,resultMap) { var Frag_h = Object.create(null); - Frag_h["prio"] = xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_INT; + Frag_h["prio"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_INT; Frag_h["#"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_PREDEFINED_VIEW; - Frag_h["class"] = xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_STRING; - Frag_h["src"] = xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_URL; - Frag_h["src_audio"] = xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_URL; - Frag_h["src_shader"] = xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_URL; - Frag_h["src_env"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL; - Frag_h["src_env_audio"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL; + Frag_h["class"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING; + Frag_h["src"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL; Frag_h["pos"] = xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_VECTOR3 | xrfragment_XRF.T_STRING_OBJ; - Frag_h["href"] = xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_URL | xrfragment_XRF.T_PREDEFINED_VIEW; + Frag_h["href"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL | xrfragment_XRF.T_PREDEFINED_VIEW; Frag_h["q"] = xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING; Frag_h["scale"] = xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_INT; Frag_h["rot"] = xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_VECTOR3; @@ -337,7 +341,6 @@ xrfragment_Parser.parse = function(key,value,resultMap) { Frag_h["gravity"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR3; Frag_h["physics"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR3; Frag_h["scroll"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING; - Frag_h["."] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING; Frag_h["fov"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_INT | xrfragment_XRF.BROWSER_OVERRIDE; Frag_h["clip"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR2 | xrfragment_XRF.BROWSER_OVERRIDE; Frag_h["fog"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING | xrfragment_XRF.BROWSER_OVERRIDE; @@ -350,15 +353,19 @@ xrfragment_Parser.parse = function(key,value,resultMap) { resultMap[key] = new xrfragment_XRF(key,xrfragment_XRF.PV_EXECUTE | xrfragment_XRF.BROWSER_OVERRIDE); return true; } + if(key.split(".").length > 1 && value.split(".").length > 1) { + resultMap[key] = new xrfragment_XRF(key,xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING | xrfragment_XRF.PROP_BIND); + return true; + } if(Object.prototype.hasOwnProperty.call(Frag_h,key)) { var v = new xrfragment_XRF(key,Frag_h[key]); if(!v.validate(value)) { - console.log("src/xrfragment/Parser.hx:79:","[ i ] fragment '" + key + "' has incompatible value (" + value + ")"); + console.log("src/xrfragment/Parser.hx:74:","[ i ] fragment '" + key + "' has incompatible value (" + value + ")"); return false; } resultMap[key] = v; } else { - console.log("src/xrfragment/Parser.hx:83:","[ i ] fragment '" + key + "' does not exist or has no type typed (yet)"); + console.log("src/xrfragment/Parser.hx:78:","[ i ] fragment '" + key + "' does not exist or has no type typed (yet)"); return false; } return true; @@ -660,7 +667,7 @@ js_Boot.__toStr = ({ }).toString; Test.errors = 0; xrfragment_Parser.error = ""; xrfragment_XRF.ASSET = 1; -xrfragment_XRF.ASSET_OBJ = 2; +xrfragment_XRF.PROP_BIND = 2; xrfragment_XRF.QUERY_OPERATOR = 4; xrfragment_XRF.PROMPT = 8; xrfragment_XRF.ROUNDROBIN = 16; diff --git a/test/generated/test.py b/test/generated/test.py index 9e5559f..2c68850 100644 --- a/test/generated/test.py +++ b/test/generated/test.py @@ -390,7 +390,7 @@ class Test: @staticmethod def main(): - Test.test([_hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xyz", 'input': "pos", 'out': False}), 'label': "equal.xyz: should trigger incompatible type)", 'data': "http://foo.com?foo=1#pos=1.2,2.2"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xyz", 'input': "pos", 'out': "1.2,2.2,3"}), 'label': "equal.xyz", 'data': "http://foo.com?foo=1#pos=1.2,2.2,3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xy", 'input': "t", 'out': "1,100"}), 'label': "a equal.xy", 'data': "http://foo.com?foo=1#t=1,100"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testParsed", 'input': "prio", 'out': False}), 'label': "should trigger incompatible type", 'data': "http://foo.com?foo=1#prio=foo"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.multi", 'input': "pos", 'out': "c|d|1,2,3"}), 'label': "b equal.multi", 'data': "http://foo.com?foo=1#pos=c|d|1,2,3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testBrowserOverride", 'input': "t", 'out': True}), 'label': "browser URI can override t (defined in asset)", 'data': "http://foo.com?foo=1#t=2,500"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testBrowserOverride", 'input': "q", 'out': False}), 'label': "browser URI cannot override q (defined in asset)", 'data': "http://foo.com?foo=1#q=-bar"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testPredefinedView", 'input': "mypredefinedview", 'out': True}), 'label': "test predefined view executed", 'data': "http://foo.com?foo=1#mypredefinedview"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testPredefinedView", 'input': "another", 'out': True}), 'label': "test predefined view executed (multiple)", 'data': "http://foo.com?foo=1#mypredefinedview&another"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testPredefinedView", 'input': "mypredefinedview", 'out': True}), 'label': "test predefined view executed (multiple)", 'data': "http://foo.com?foo=1#mypredefinedview&another"})]) + Test.test([_hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xyz", 'input': "pos", 'out': False}), 'label': "equal.xyz: should trigger incompatible type)", 'data': "http://foo.com?foo=1#pos=1.2,2.2"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xyz", 'input': "pos", 'out': "1.2,2.2,3"}), 'label': "equal.xyz", 'data': "http://foo.com?foo=1#pos=1.2,2.2,3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xy", 'input': "t", 'out': "1,100"}), 'label': "a equal.xy", 'data': "http://foo.com?foo=1#t=1,100"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testParsed", 'input': "prio", 'out': False}), 'label': "should trigger incompatible type", 'data': "http://foo.com?foo=1#prio=foo"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.multi", 'input': "pos", 'out': "c|d|1,2,3"}), 'label': "b equal.multi", 'data': "http://foo.com?foo=1#pos=c|d|1,2,3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testBrowserOverride", 'input': "t", 'out': True}), 'label': "browser URI can override t (defined in asset)", 'data': "http://foo.com?foo=1#t=2,500"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testBrowserOverride", 'input': "q", 'out': False}), 'label': "browser URI cannot override q (defined in asset)", 'data': "http://foo.com?foo=1#q=-bar"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testPredefinedView", 'input': "mypredefinedview", 'out': True}), 'label': "test predefined view executed", 'data': "http://foo.com?foo=1#mypredefinedview"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testPredefinedView", 'input': "another", 'out': True}), 'label': "test predefined view executed (multiple)", 'data': "http://foo.com?foo=1#mypredefinedview&another"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testPredefinedView", 'input': "mypredefinedview", 'out': True}), 'label': "test predefined view executed (multiple)", 'data': "http://foo.com?foo=1#mypredefinedview&another"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testPropertyAssign", 'input': "cube.position.x", 'out': True}), 'label': "test data assign", 'data': "#cube.position.x=music.position.x"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "testPropertyAssign", 'input': "cube.position.x", 'out': True}), 'label': "test one-way data bind", 'data': "#cube.position.x=@music.position.x"})]) Test.test([_hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "bar"], 'out': True}), 'data': "class:bar"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "bar"], 'out': True}), 'label': ".bar shorthand", 'data': ".bar"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "foo"], 'out': False}), 'data': ".bar -.foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "foo"], 'out': True}), 'data': ".bar -.foo .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "bar"], 'out': True}), 'data': ".bar -.bar .bar"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "foo"], 'out': True}), 'label': "class:foo", 'data': ".foo -.foo .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "foo"], 'out': True}), 'label': "class:foo", 'data': ".foo -.foo bar:5 .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "foo"], 'out': True}), 'label': "class:foo", 'data': ".foo -.foo bar:>5 .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "foo"], 'out': True}), 'label': "class:foo", 'data': ".foo -.foo bar:>5 .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["class", "foo"], 'out': True}), 'label': "class:foo", 'data': ".foo -.foo .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["id", "foo"], 'out': False}), 'label': "!id:foo", 'data': ".foo -.foo .foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["id", "foo"], 'out': True}), 'label': "id:foo?", 'data': "foo -foo foo"})]) Test.test([_hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "10"], 'out': True}), 'data': "price:>=5"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "10"], 'out': False}), 'data': "price:>=15"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "4"], 'out': False}), 'data': "price:>=5"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "0"], 'out': False}), 'data': "price:>=5"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "1"], 'out': False}), 'label': "price=1", 'data': "price:>=5 price:0"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "0"], 'out': True}), 'label': "price=0", 'data': "price:>=5 price:0"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["price", "6"], 'out': True}), 'label': "price=6", 'data': "price:>=5 price:0"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["tag", "foo"], 'out': True}), 'data': "tag:foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testProperty", 'input': ["tag", "foo"], 'out': False}), 'data': "-tag:foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "testPropertyExclude", 'input': ["tag", "foo"], 'out': True}), 'label': "testExclude", 'data': "-tag:foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': [_hx_AnonObject({'price': 5})], 'out': True}), 'data': ".foo price:5 -tag:foo"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "test", 'input': [_hx_AnonObject({'tag': "foo", 'price': 5})], 'out': False}), 'data': ".foo price:5 -tag:foo"})]) if (Test.errors > 1): @@ -424,6 +424,10 @@ class Test: valid = (python_Boot.hasField(res,Reflect.field(Reflect.field(item,"expect"),"input")) and (HxOverrides.eq(Reflect.field(Reflect.field(item,"expect"),"out"),Reflect.field(Reflect.field(res,Reflect.field(Reflect.field(item,"expect"),"input")),"is")(xrfragment_XRF.PV_EXECUTE)))) if (Reflect.field(Reflect.field(item,"expect"),"fn") == "testBrowserOverride"): valid = (Reflect.field(Reflect.field(item,"expect"),"out") == python_Boot.hasField(xrfragment_URI.parse(Reflect.field(item,"data"),True),Reflect.field(Reflect.field(item,"expect"),"input"))) + if (Reflect.field(Reflect.field(item,"expect"),"fn") == "testPropertyAssign"): + valid = (python_Boot.hasField(res,Reflect.field(Reflect.field(item,"expect"),"input")) and (HxOverrides.eq(Reflect.field(Reflect.field(item,"expect"),"out"),Reflect.field(Reflect.field(res,Reflect.field(Reflect.field(item,"expect"),"input")),"is")(xrfragment_XRF.PROP_BIND)))) + if (Reflect.field(Reflect.field(item,"expect"),"fn") == "testBrowserOverride"): + valid = (Reflect.field(Reflect.field(item,"expect"),"out") == python_Boot.hasField(xrfragment_URI.parse(Reflect.field(item,"data"),True),Reflect.field(Reflect.field(item,"expect"),"input"))) if (Reflect.field(Reflect.field(item,"expect"),"fn") == "equal.string"): valid = (Reflect.field(res,Reflect.field(Reflect.field(item,"expect"),"input")) and (HxOverrides.eq(Reflect.field(Reflect.field(item,"expect"),"out"),Reflect.field(Reflect.field(res,Reflect.field(Reflect.field(item,"expect"),"input")),"string")))) if (Reflect.field(Reflect.field(item,"expect"),"fn") == "equal.xy"): @@ -1403,16 +1407,12 @@ class xrfragment_Parser: @staticmethod def parse(key,value,resultMap): Frag = haxe_ds_StringMap() - Frag.h["prio"] = (xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_INT) + Frag.h["prio"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_INT) Frag.h["#"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_PREDEFINED_VIEW) - Frag.h["class"] = (xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_STRING) - Frag.h["src"] = (xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_URL) - Frag.h["src_audio"] = (xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_URL) - Frag.h["src_shader"] = (xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_URL) - Frag.h["src_env"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) - Frag.h["src_env_audio"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) + Frag.h["class"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING) + Frag.h["src"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) Frag.h["pos"] = (((xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN) | xrfragment_XRF.T_VECTOR3) | xrfragment_XRF.T_STRING_OBJ) - Frag.h["href"] = ((xrfragment_XRF.ASSET_OBJ | xrfragment_XRF.T_URL) | xrfragment_XRF.T_PREDEFINED_VIEW) + Frag.h["href"] = ((xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) | xrfragment_XRF.T_PREDEFINED_VIEW) Frag.h["q"] = (xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING) Frag.h["scale"] = (((xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.ROUNDROBIN) | xrfragment_XRF.T_INT) Frag.h["rot"] = (((xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.ROUNDROBIN) | xrfragment_XRF.T_VECTOR3) @@ -1422,7 +1422,6 @@ class xrfragment_Parser: Frag.h["gravity"] = ((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_VECTOR3) Frag.h["physics"] = ((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_VECTOR3) Frag.h["scroll"] = ((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_STRING) - Frag.h["."] = ((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_STRING) Frag.h["fov"] = (((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_INT) | xrfragment_XRF.BROWSER_OVERRIDE) Frag.h["clip"] = (((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_VECTOR2) | xrfragment_XRF.BROWSER_OVERRIDE) Frag.h["fog"] = (((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.T_STRING) | xrfragment_XRF.BROWSER_OVERRIDE) @@ -1435,6 +1434,10 @@ class xrfragment_Parser: value1 = xrfragment_XRF(key,(xrfragment_XRF.PV_EXECUTE | xrfragment_XRF.BROWSER_OVERRIDE)) setattr(resultMap,(("_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 + 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(resultMap,(("_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 if (key in Frag.h): v = xrfragment_XRF(key,Frag.h.get(key,None)) if (not v.validate(value)): @@ -1589,8 +1592,8 @@ class xrfragment_Query: fails = 0 qualify = 0 def _hx_local_2(expr): - nonlocal conds nonlocal fails + nonlocal conds conds = (conds + 1) fails = (fails + (0 if expr else 1)) return expr @@ -1674,7 +1677,7 @@ class xrfragment_XRF: __slots__ = ("fragment", "flags", "x", "y", "z", "color", "string", "int", "float", "args", "query") _hx_fields = ["fragment", "flags", "x", "y", "z", "color", "string", "int", "float", "args", "query"] _hx_methods = ["is", "validate", "guessType"] - _hx_statics = ["ASSET", "ASSET_OBJ", "QUERY_OPERATOR", "PROMPT", "ROUNDROBIN", "BROWSER_OVERRIDE", "PV_OVERRIDE", "PV_EXECUTE", "T_INT", "T_VECTOR2", "T_VECTOR3", "T_URL", "T_PREDEFINED_VIEW", "T_STRING", "T_STRING_OBJ", "isColor", "isInt", "isFloat"] + _hx_statics = ["ASSET", "PROP_BIND", "QUERY_OPERATOR", "PROMPT", "ROUNDROBIN", "BROWSER_OVERRIDE", "PV_OVERRIDE", "PV_EXECUTE", "T_INT", "T_VECTOR2", "T_VECTOR3", "T_URL", "T_PREDEFINED_VIEW", "T_STRING", "T_STRING_OBJ", "isColor", "isInt", "isFloat"] def __init__(self,_fragment,_flags): self.query = None @@ -1752,7 +1755,7 @@ python_Boot.keywords = set(["and", "del", "from", "not", "with", "as", "elif", " python_Boot.prefixLength = len("_hx_") xrfragment_Parser.error = "" xrfragment_XRF.ASSET = 1 -xrfragment_XRF.ASSET_OBJ = 2 +xrfragment_XRF.PROP_BIND = 2 xrfragment_XRF.QUERY_OPERATOR = 4 xrfragment_XRF.PROMPT = 8 xrfragment_XRF.ROUNDROBIN = 16