diff --git a/dist/xrfragment.js b/dist/xrfragment.js index f88668e..fd0844d 100644 --- a/dist/xrfragment.js +++ b/dist/xrfragment.js @@ -231,15 +231,14 @@ xrfragment_Parser.parse = function(key,value,resultMap) { Frag_h["t"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_VECTOR2 | xrfragment_XRF.BROWSER_OVERRIDE; 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["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; Frag_h["namespace"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING; - Frag_h["SPFX"] = 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["src_session"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.BROWSER_OVERRIDE | xrfragment_XRF.PROMPT; + Frag_h["session"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.BROWSER_OVERRIDE | xrfragment_XRF.PROMPT; if(value.length == 0 && !Object.prototype.hasOwnProperty.call(Frag_h,key)) { resultMap[key] = new xrfragment_XRF(key,xrfragment_XRF.PV_EXECUTE | xrfragment_XRF.BROWSER_OVERRIDE); return true; @@ -251,12 +250,12 @@ xrfragment_Parser.parse = function(key,value,resultMap) { 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:75:","[ 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:79:","[ 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; diff --git a/dist/xrfragment.lua b/dist/xrfragment.lua index cba91ef..7ce7cc9 100644 --- a/dist/xrfragment.lua +++ b/dist/xrfragment.lua @@ -1498,12 +1498,6 @@ __xrfragment_Parser.parse = function(key,value,resultMap) else Frag_h.physics = 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.scroll = __haxe_ds_StringMap.tnull; - else - Frag_h.scroll = 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; @@ -1530,9 +1524,9 @@ __xrfragment_Parser.parse = function(key,value,resultMap) end; local value1 = _hx_bit.bor(__xrfragment_XRF.ASSET,__xrfragment_XRF.T_STRING); if (value1 == nil) then - Frag_h.SPFX = __haxe_ds_StringMap.tnull; + Frag_h.SPDX = __haxe_ds_StringMap.tnull; else - Frag_h.SPFX = value1; + Frag_h.SPDX = value1; end; local value1 = _hx_bit.bor(__xrfragment_XRF.ASSET,__xrfragment_XRF.T_STRING); if (value1 == nil) then @@ -1548,9 +1542,9 @@ __xrfragment_Parser.parse = function(key,value,resultMap) end; local value1 = _hx_bit.bor(_hx_bit.bor(_hx_bit.bor(_hx_bit.bor(__xrfragment_XRF.ASSET,__xrfragment_XRF.T_URL),__xrfragment_XRF.PV_OVERRIDE),__xrfragment_XRF.BROWSER_OVERRIDE),__xrfragment_XRF.PROMPT); if (value1 == nil) then - Frag_h.src_session = __haxe_ds_StringMap.tnull; + Frag_h.session = __haxe_ds_StringMap.tnull; else - Frag_h.src_session = value1; + Frag_h.session = value1; end; if ((__lua_lib_luautf8_Utf8.len(value) == 0) and (Frag_h[key] == nil)) then local value = __xrfragment_XRF.new(key, _hx_bit.bor(__xrfragment_XRF.PV_EXECUTE,__xrfragment_XRF.BROWSER_OVERRIDE)); @@ -1619,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=75,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=79,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; diff --git a/dist/xrfragment.module.js b/dist/xrfragment.module.js index e8323c0..32e27aa 100644 --- a/dist/xrfragment.module.js +++ b/dist/xrfragment.module.js @@ -231,15 +231,14 @@ xrfragment_Parser.parse = function(key,value,resultMap) { Frag_h["t"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_VECTOR2 | xrfragment_XRF.BROWSER_OVERRIDE; 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["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; Frag_h["namespace"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING; - Frag_h["SPFX"] = 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["src_session"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.BROWSER_OVERRIDE | xrfragment_XRF.PROMPT; + Frag_h["session"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.BROWSER_OVERRIDE | xrfragment_XRF.PROMPT; if(value.length == 0 && !Object.prototype.hasOwnProperty.call(Frag_h,key)) { resultMap[key] = new xrfragment_XRF(key,xrfragment_XRF.PV_EXECUTE | xrfragment_XRF.BROWSER_OVERRIDE); return true; @@ -251,12 +250,12 @@ xrfragment_Parser.parse = function(key,value,resultMap) { 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:75:","[ 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:79:","[ 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; diff --git a/dist/xrfragment.py b/dist/xrfragment.py index ec4c2b3..5567101 100644 --- a/dist/xrfragment.py +++ b/dist/xrfragment.py @@ -1308,15 +1308,14 @@ class xrfragment_Parser: Frag.h["t"] = ((((xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.ROUNDROBIN) | xrfragment_XRF.T_VECTOR2) | xrfragment_XRF.BROWSER_OVERRIDE) 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["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) Frag.h["namespace"] = (xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING) - Frag.h["SPFX"] = (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["src_session"] = ((((xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.BROWSER_OVERRIDE) | xrfragment_XRF.PROMPT) + Frag.h["session"] = ((((xrfragment_XRF.ASSET | xrfragment_XRF.T_URL) | xrfragment_XRF.PV_OVERRIDE) | xrfragment_XRF.BROWSER_OVERRIDE) | xrfragment_XRF.PROMPT) if ((len(value) == 0) and (not (key in Frag.h))): 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) diff --git a/doc/fragments.awk b/doc/fragments.awk new file mode 100644 index 0000000..9257573 --- /dev/null +++ b/doc/fragments.awk @@ -0,0 +1,27 @@ +BEGIN{ + print "| fragment | type | scope |" + print "|----------|------|-------|" +} + +/category:/ { + $1=$2="" + sub(/^[[:space:]]+/, "", $0 ) # remove leading spaces + sub(/[[:space:]]+$/, "", $0 ) # remove trailing spaces + scope=$0 +} + + +/Frag.*XRF\.*/ { + gsub(/.*\("/,"",$1) + gsub(/".*/,"",$1) + type="string" + frag=$1 + $1="" + if( $0 ~ /T_INT/ ) type="int" + if( $0 ~ /T_STRING_OBJ/ ) type="[string object](string object)" + if( $0 ~ /T_VECTOR2/ ) type="[vector2](#vector2)" + if( $0 ~ /T_VECTOR3/ ) type="[vector3](#vector3)" + if( $0 ~ /T_URL/ ) type="[url](#url)" + if( $0 ~ /T_PREDEFINED_VIEW/ ) type="[predefined view](#prefined%20view)" + print "| **"frag"** |" type "|" scope "|" +} diff --git a/index.html b/index.html index b74f0d7..c84cdfb 100644 --- a/index.html +++ b/index.html @@ -1128,7 +1128,7 @@ Error message and password prompt
  • AFRAME template
  • -
  • Draft of '↪ URI.Parse'
  • +
  • Draft of 'List of fragments'
  • Examples
  • @@ -1215,7 +1215,7 @@ Error message and password prompt {"created":"20230425164931250","title":"$:/state/folded/GLSL shader template","text":"show","modified":"20230425164939576"}, {"created":"20230424142403302","text":"checked","title":"$:/state/import/select-all","modified":"20230424142404392"}, {"created":"20230423163640468","title":"$:/state/notebook-sidebar","text":"yes","modified":"20230427175800205"}, -{"created":"20230423163641722","title":"$:/state/notebook-sidebar-section","text":"Reference","modified":"20230427182750528"}, +{"created":"20230423163641722","title":"$:/state/notebook-sidebar-section","text":"$:/core/ui/SideBar/Recent","modified":"20230427204332510"}, {"created":"20230427102758222","title":"$:/state/plugin-info--1887569658-$:/plugins/ihm/tidgraph--50210113","text":"documentation","modified":"20230427102759911"}, {"created":"20230427092525294","title":"$:/state/plugin-info--391242618-$:/plugins/tiddlywiki/browser-storage","text":"yes","modified":"20230427092525375"}, {"created":"20230427093219686","title":"$:/state/plugin-info--391242618-$:/plugins/tiddlywiki/browser-storage--605768392","text":"settings","modified":"20230427094141558"}, @@ -1232,7 +1232,7 @@ Error message and password prompt {"created":"20230427151522031","title":"$:/state/tab/moresidebar-1850697562","text":"$:/core/ui/MoreSideBar/All","modified":"20230427151523774"}, {"created":"20230423164446212","title":"$:/state/tabs/controlpanel/toolbars-1345989671","text":"$:/core/ui/ControlPanel/Toolbars/PageControls","modified":"20230427180259900"}, {"title":"$:/status/RequireReloadDueToPluginChange","text":"no"}, -{"created":"20230427182000484","title":"$:/StoryList","text":"","list":"[[XR Fragments]]","modified":"20230427182743909"}, +{"created":"20230427204335247","title":"$:/StoryList","text":"","list":"[[XR Fragments]]","modified":"20230427204342807"}, {"created":"20230423163445948","title":"$:/theme","text":"$:/themes/nico/notebook","modified":"20230423163445948"}, {"text":"{\n \"tiddlers\": {\n \"$:/themes/nico/notebook/LICENSE\": {\n \"title\": \"$:/themes/nico/notebook/LICENSE\",\n \"created\": \"20200419141443144\",\n \"modified\": \"20210118213330307\",\n \"tags\": \"\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\\nMIT License Copyright (c) 2020 [[Nicolas Petton|https://nicolas.petton.fr]] nicolas@petton.fr\\n\\nPermission is hereby granted, free of charge, to any person obtaining a copy\\nof this software and associated documentation files (the \\\"Software\\\"), to deal\\nin the Software without restriction, including without limitation the rights\\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\\ncopies of the Software, and to permit persons to whom the Software is furnished\\nto do so, subject to the following conditions:\\n\\nThe above copyright notice and this permission notice (including the next\\nparagraph) shall be included in all copies or substantial portions of the\\nSoftware.\\n\\nTHE SOFTWARE IS PROVIDED \\\"AS IS\\\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS\\nOR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF\\nOR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\\n\"\n },\n \"$:/themes/nico/notebook/themetweaks\": {\n \"title\": \"$:/themes/nico/notebook/themetweaks\",\n \"created\": \"20201217172915960\",\n \"modified\": \"20210123211851680\",\n \"tags\": \"$:/tags/ControlPanel/Appearance\",\n \"caption\": \"{{$:/language/ThemeTweaks/ThemeTweaks}}\",\n \"text\": \"\\\\define lingo-base() $:/language/ThemeTweaks/\\n\\nYou can tweak certain aspects of the ''Notebook'' theme.\\n\\n! \u003C\u003Clingo Options>>\\n\\n|\u003C$link to=\\\"$:/themes/nico/notebook/options/stickytitles\\\">\u003C\u003Clingo Options/StickyTitles>>\u003C/$link>\u003Cbr>//\u003C\u003Clingo Options/StickyTitles/Hint>>// |\u003C$select tiddler=\\\"$:/themes/nico/notebook/options/stickytitles\\\">\u003Coption value=\\\"no\\\">{{$:/language/No}}\u003C/option>\u003Coption value=\\\"yes\\\">{{$:/language/Yes}}\u003C/option>\u003C/$select> |\\n|\u003C$link to=\\\"$:/themes/tiddlywiki/vanilla/options/codewrapping\\\">\u003C\u003Clingo Options/CodeWrapping>>\u003C/$link> |\u003C$select tiddler=\\\"$:/themes/tiddlywiki/vanilla/options/codewrapping\\\">\u003Coption value=\\\"pre\\\">{{$:/language/No}}\u003C/option>\u003Coption value=\\\"pre-wrap\\\">{{$:/language/Yes}}\u003C/option>\u003C/$select> |\\n|\u003C$link to=\\\"$:/themes/nico/notebook/options/reveal-tiddler-controls-on-hover\\\">Reveal tiddler controls on mouseover\u003C/$link> |\u003C$select tiddler=\\\"$:/themes/nico/notebook/options/reveal-tiddler-controls-on-hover\\\">\u003Coption value=\\\"no\\\">{{$:/language/No}}\u003C/option>\u003Coption value=\\\"yes\\\">{{$:/language/Yes}}\u003C/option>\u003C/$select> |\\n\\n! \u003C\u003Clingo Settings>>\\n\\n|\u003C$link to=\\\"$:/themes/nico/notebook/settings/fontfamily\\\">\u003C\u003Clingo Settings/FontFamily>>\u003C/$link> |\u003C$edit-text tiddler=\\\"$:/themes/nico/notebook/settings/fontfamily\\\" default=\\\"\\\" tag=\\\"input\\\"/> | |\\n|\u003C$link to=\\\"$:/themes/nico/notebook/settings/codefontfamily\\\">\u003C\u003Clingo Settings/CodeFontFamily>>\u003C/$link> |\u003C$edit-text tiddler=\\\"$:/themes/nico/notebook/settings/codefontfamily\\\" default=\\\"\\\" tag=\\\"input\\\"/> | |\\n|\u003C$link to=\\\"$:/themes/nico/notebook/settings/editorfontfamily\\\">\u003C\u003Clingo Settings/EditorFontFamily>>\u003C/$link> |\u003C$edit-text tiddler=\\\"$:/themes/nico/notebook/settings/editorfontfamily\\\" default=\\\"\\\" tag=\\\"input\\\"/> | |\\n\\n! \u003C\u003Clingo Metrics>>\\n\\n|\u003C$link to=\\\"$:/themes/tiddlywiki/vanilla/metrics/fontsize\\\">\u003C\u003Clingo Metrics/FontSize>>\u003C/$link> |\u003C$edit-text tiddler=\\\"$:/themes/tiddlywiki/vanilla/metrics/fontsize\\\" default=\\\"\\\" tag=\\\"input\\\"/> |\\n|\u003C$link to=\\\"$:/themes/tiddlywiki/vanilla/metrics/lineheight\\\">\u003C\u003Clingo Metrics/LineHeight>>\u003C/$link> |\u003C$edit-text tiddler=\\\"$:/themes/tiddlywiki/vanilla/metrics/lineheight\\\" default=\\\"\\\" tag=\\\"input\\\"/> |\\n|\u003C$link to=\\\"$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize\\\">\u003C\u003Clingo Metrics/BodyFontSize>>\u003C/$link> |\u003C$edit-text tiddler=\\\"$:/themes/nico/notebook/metrics/bodyfontsize\\\" default=\\\"\\\" tag=\\\"input\\\"/> |\\n|\u003C$link to=\\\"$:/themes/tiddlywiki/vanilla/metrics/bodylineheight\\\">\u003C\u003Clingo Metrics/BodyLineHeight>>\u003C/$link> |\u003C$edit-text tiddler=\\\"$:/themes/nico/notebook/metrics/bodylineheight\\\" default=\\\"\\\" tag=\\\"input\\\"/> |\\n|\u003C$link to=\\\"$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint\\\">\u003C\u003Clingo Metrics/SidebarBreakpoint>>\u003C/$link>\u003Cbr>//\u003C\u003Clingo Metrics/SidebarBreakpoint/Hint>>// |^\u003C$edit-text tiddler=\\\"$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint\\\" default=\\\"\\\" tag=\\\"input\\\"/> |\\n|\u003C$link to=\\\"$:/themes/nico/notebook/metrics/sidebar-width\\\">\u003C\u003Clingo Metrics/SidebarWidth>>\u003C/$link>\u003Cbr>//\u003C\u003Clingo Metrics/SidebarWidth/Hint>>// |^\u003C$edit-text tiddler=\\\"$:/themes/nico/notebook/metrics/sidebar-width\\\" default=\\\"\\\" tag=\\\"input\\\"/> |\\n|\u003C$link to=\\\"$:/themes/nico/notebook/metrics/story-width\\\">\u003C\u003Clingo Metrics/StoryWidth>>\u003C/$link>\u003Cbr>//\u003C\u003Clingo Metrics/StoryWidth/Hint>>// |^\u003C$edit-text tiddler=\\\"$:/themes/nico/notebook/metrics/story-width\\\" default=\\\"\\\" tag=\\\"input\\\"/> |\\n\\n\"\n },\n \"$:/themes/nico/notebook/base\": {\n \"title\": \"$:/themes/nico/notebook/base\",\n \"created\": \"20200419141443144\",\n \"modified\": \"20210120224227503\",\n \"tags\": \"$:/tags/Stylesheet\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\\\\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline\\n\\n\\\\define if-sidebar(text)\\n \u003C$reveal state=\\\"$:/state/notebook-sidebar\\\" type=\\\"match\\\" text=\\\"yes\\\">\\n $text$\\n \u003C/$reveal>\\n\\\\end\\n\\n\\\\define if-reveal-tiddler-controls-on-hover(text)\\n \u003C$reveal state=\\\"$:/themes/nico/notebook/options/reveal-tiddler-controls-on-hover\\\" type=\\\"match\\\" text=\\\"yes\\\">\\n $text$\\n \u003C/$reveal>\\n\\\\end\\n \\n/* Top and bottom bars */\\n\\n/* Hide the top-right bar */\\n.tc-topbar.tc-topbar-right {\\n display: none;\\n}\\n\\ndiv.tc-sidebar-header {\\n padding: 0;\\n min-height: 0;\\n}\\n\\n.tc-story-river {\\n padding: 6px 0 !important;\\n width: 100% !important;\\n max-width: {{$:/themes/nico/notebook/metrics/story-width}} !important;\\n margin: 0 auto !important;\\n margin-top: 34px !important;\\n}\\n\\ndiv.tc-tiddler-frame {\\n width: 100%;\\n margin: 20px 0;\\n background: \u003C\u003Ccolour tiddler-background>>;\\n box-shadow: 0 5px 20px rgba(0,0,0, 0.12);\\n border-radius: 6px;\\n padding: 42px 60px 60px 60px;\\n}\\n\\nh1.tc-site-title {\\n margin-top: 14px;\\n font-size: 1.5em !important;\\n}\\n\\n.nc-bar {\\n padding: 10px;\\n height: {{$:/themes/nico/notebook/metrics/topbar-height}};\\n background: \u003C\u003Ccolour page-background>>;\\n display: flex;\\n justify-content: space-between;\\n}\\n\\n.nc-topbar-wrapper {\\n position: fixed;\\n top: 0;\\n left: 0;\\n right: 0;\\n /* The z-index needs to be above the z-index used in tiddlers in zoomin view */\\n z-index: 501;\\n}\\n\\n.nc-bar.nc-topbar {\\n top: 0;\\n background: \u003C\u003Ccolour page-background>>ee;\\n max-width: calc({{$:/themes/nico/notebook/metrics/story-width}} + 40px);\\n padding: 10px 20px;\\n margin: 0 auto;\\n}\\n\\n.nc-bar.nc-bottombar {\\n position: fixed;\\n bottom: 0;\\n left: 0;\\n right: 0;\\n /* The z-index needs to be above the z-index used in tiddlers in zoomin view */\\n z-index: 501;\\n}\\n\\n.nc-bar .left svg {\\n fill: \u003C\u003Ccolour sidebar-controls-foreground>>;\\n}\\n\\n.nc-bar input[type=\\\"search\\\"] {\\n width: 200px;\\n padding: .6em 1em;\\n margin-top: -.2em;\\n background: \u003C\u003Ccolour sidebar-button-foreground>>44;\\n color: \u003C\u003Ccolour foreground>>cc;\\n transition: all ease-in .2s;\\n border: 1px solid transparent;\\n outline: 0;\\n}\\n\\n.nc-bar input[type=\\\"search\\\"]:focus {\\n width: 300px;\\n background: \u003C\u003Ccolour tiddler-background>>;\\n color: \u003C\u003Ccolour foreground>>;\\n border: 1px solid \u003C\u003Ccolour primary>>;\\n box-shadow: 0 0 .2rem 0 \u003C\u003Ccolour primary>>;\\n}\\n\\ninput[type=\\\"search\\\"]::-webkit-search-cancel-button {\\n -webkit-appearance: auto;\\n}\\n\\n.nc-bar .tc-block-dropdown.tc-search-drop-down {\\n margin-left: 0;\\n width: 400px;\\n border: 0;\\n box-shadow: 0 0 6px 0 rgba(0,0,0,.2);\\n border-radius: 6px;\\n padding: 20px 0;\\n}\\n\\n.nc-bar p {\\n margin: 0;\\n}\\n\\n.nc-bar .tc-page-controls {\\n margin-top: 0;\\n}\\n\\n.nc-bar .tc-page-controls button {\\n margin-right: .8em;\\n}\\n\\n.nc-bar .tc-page-controls button .tc-btn-text {\\n font-size: 14px;\\n}\\n\\n.nc-bar .tc-block-dropdown {\\n max-height: 70vh;\\n overflow: auto;\\n}\\n\\n@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\\n .nc-topbar {\\n display: none;\\n }\\n\\n .tc-story-river {\\n padding: 0 !important;\\n margin-top: 0 !important;\\n margin-bottom: 60px !important;\\n }\\n\\n div.tc-tiddler-frame {\\n margin: 0;\\n box-shadow: none;\\n border-radius: 0;\\n border-top: 0;\\n }\\n}\\n\\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\\n .nc-bottombar {\\n display: none;\\n }\\n}\\n\\n@media(max-width: 1100px) {\\n .nc-bar input[type=\\\"search\\\"] {\\n width: 200px;\\n }\\n}\\n\\n/* Sidebar */\\n\\n@keyframes sidebar-appear {\\n 0% {\\n left: -{{$:/themes/nico/notebook/metrics/sidebar-width}};\\n }\\n 100% {\\n left: 0;\\n }\\n}\\n\\n\u003C\u003Cif-sidebar \\\"\\\"\\\"\\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\\n .nc-sidebar {\\n animation: sidebar-appear .14s;\\n padding-top: 10px;\\n }\\n}\\n\\\"\\\"\\\">>\\n\\n.nc-sidebar {\\n background: \u003C\u003Ccolour tiddler-background>>;\\n border-right: 1px solid \u003C\u003Ccolour tiddler-border>>;\\n width: {{$:/themes/nico/notebook/metrics/sidebar-width}};\\n overflow-y: auto;\\n overflow-x: hidden;\\n z-index: 500;\\n}\\n\\n.nc-sidebar .segment {\\n border-bottom: 1px solid rgba(0,0,0,.1);\\n}\\n\\n.nc-sidebar ol {\\n margin: 0;\\n padding: 0;\\n list-style: none;\\n line-height: 1.8em;\\n}\\n\\n.nc-sidebar ol ol {\\n padding-left: 18px;\\n}\\n\\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\\n .mobile-only {\\n display: none;\\n }\\n}\\n\\n@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\\n .desktop-only {\\n display: none;\\n }\\n}\\n\\n.nc-sidebar h1.tc-site-title {\\n margin: 0;\\n}\\n\\n.nc-sidebar p {\\n margin: 6px 0;\\n}\\n\\n.nc-sidebar .tc-site-subtitle {\\n color: \u003C\u003Ccolour site-title-foreground>>;\\n}\\n\\n.nc-sidebar .section .label {\\n padding: 2px 0;\\n color: \u003C\u003Ccolour site-title-foreground>>;\\n fill: \u003C\u003Ccolour site-title-foreground>>;\\n font-weight: bold;\\n line-height: 1.6em;\\n display: block;\\n width: 100%;\\n text-align: left;\\n padding: 8px 15px;\\n border-radius: 0;\\n}\\n\\n.nc-sidebar .section:not(.open) .label:hover {\\n background: rgba(0,0,0,.06);\\n}\\n\\n.nc-sidebar .section.open .label {\\n color: \u003C\u003Ccolour tiddler-background>>;\\n fill: \u003C\u003Ccolour tiddler-background>>;\\n background: \u003C\u003Ccolour primary>>;\\n border-bottom: 1px solid rgba(0,0,0,.1);\\n}\\n\\n.nc-sidebar .section .label .caret {\\n display: inline-block;\\n width: 15px;\\n float: right;\\n}\\n\\n.nc-sidebar .content {\\n padding: 6px 15px;\\n font-size: 1em;\\n}\\n\\n.nc-sidebar .tc-tiddlylink {\\n color: \u003C\u003Ccolour primary>>;\\n}\\n\\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\\n .nc-sidebar {\\n position: fixed;\\n left: 0;\\n top: 0;\\n bottom: 0;\\n }\\n}\\n\\n\u003C\u003Cif-sidebar \\\"\\\"\\\"\\n@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\\n @keyframes sidebar-slide {\\n 0% {\\n left: -100vw;\\n }\\n 100% {\\n left: 0;\\n }\\n }\\n .nc-sidebar {\\n overflow: auto;\\n position: fixed;\\n width: 100%;\\n left: 0;\\n top: 0;\\n bottom: 48px;\\n z-index: 3000;\\n animation: sidebar-slide ease-in .2s;\\n animation-fill-mode: forwards;\\n }\\n}\\n\\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\\n .tc-page-container {\\n margin-left: {{$:/themes/nico/notebook/metrics/sidebar-width}} !important;\\n }\\n\\n .nc-topbar-wrapper {\\n left: {{$:/themes/nico/notebook/metrics/sidebar-width}};\\n }\\n}\\n\\\"\\\"\\\">>\\n\\n/* Animate the hamburger button */\\n\\n@keyframes menu-bars-1 {\\n 0% {}\\n 100% {\\n transform: rotate(-45deg) translateY(-10px) translateX(-6px);\\n fill: \u003C\u003Ccolour foreground>>;\\n }\\n}\\n\\n@keyframes menu-bars-2 {\\n 0% {}\\n 100% { opacity: 0; }\\n}\\n\\n@keyframes menu-bars-3 {\\n 0% {}\\n 100% {\\n transform: rotate(45deg) translateY(6px) translateX(2px);\\n fill: \u003C\u003Ccolour foreground>>;\\n }\\n}\\n\\n.sidebar-toggle {\\n /* position: fixed; */\\n /* top: 6px; */\\n /* left: 6px; */\\n /* z-index: 600; */\\n /* padding: 4px; */\\n /* border-radius: 8px; */\\n margin-right: 10px;\\n transition: all ease-in-out .2s;\\n fill: \u003C\u003Ccolour sidebar-controls-foreground>>;\\n}\\n\\n.sidebar-toggle:hover,\\n.sidebar-toggle.open {\\n fill: \u003C\u003Ccolour sidebar-controls-foreground-hover>>;\\n}\\n\\n/* @media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) { */\\n/* .sidebar-toggle { */\\n/* top: auto; */\\n/* bottom: 10px; */\\n/* left: 10px; */\\n/* } */\\n/* } */\\n\\n.sidebar-toggle .bars .bar {\\n transform: rotate(0) translateY(0) translateX(0);\\n opacity: 1;\\n transform-origin: 20px 10px;\\n transition: transform 0.4s ease-in-out, opacity 0.2s ease-in-out, fill .4s ease-in-out;\\n}\\n\\n.sidebar-toggle .bars .bar:nth-of-type(3) {\\n transform-origin: 20px 20px;\\n}\\n\\n.sidebar-toggle.open .bars .bar:nth-of-type(1) {\\n animation: menu-bars-1 .6s;\\n animation-fill-mode: forwards;\\n}\\n.sidebar-toggle.open .bars .bar:nth-of-type(2) {\\n animation: menu-bars-2 .6s;\\n animation-fill-mode: forwards;\\n}\\n.sidebar-toggle.open .bars .bar:nth-of-type(3) {\\n animation: menu-bars-3 .6s;\\n animation-fill-mode: forwards;\\n}\\n\\n@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\\n div.tc-tiddler-frame {\\n padding: 14px;\\n }\\n}\\n\\n/* Inputs */\\n\\ninput, textarea {\\n transition: border .14s ease-in-out;\\n background: \u003C\u003Ccolour tiddler-editor-background>>;\\n border: 1px solid \u003C\u003Ccolour tiddler-editor-border>>;\\n padding: .5em;\\n border-radius: 4px;\\n}\\n\\ninput:focus, textarea:focus {\\n box-shadow: 0 0 0.2rem 0 \u003C\u003Ccolour primary>>;\\n outline: 0;\\n border-color: \u003C\u003Ccolour primary>>;\\n}\\n\\nbutton {\\n border-radius: 1.5em;\\n border: 1px solid #ccc;\\n background: \u003C\u003Ccolour tiddler-background>>;\\n padding: .3em 1em;\\n cursor: pointer;\\n transition: box-shadow ease-in .1s;\\n color: \u003C\u003Ccolor foreground>>;\\n}\\n\\nbutton:focus, button:active {\\n outline: 0 none;\\n}\\n\\nbutton.tc-btn-invisible {\\n border-radius: 0;\\n}\\n\\n.tc-editor-toolbar button,\\n.tc-editor-toolbar button.tc-btn-invisible {\\n border-radius: 3px;\\n background: \u003C\u003Ccolour tiddler-editor-background>>;\\n color: \u003C\u003Ccolour foreground>>;\\n fill: \u003C\u003Ccolour foreground>>;\\n border: 1px solid \u003C\u003Ccolour tiddler-editor-border>>;\\n}\\n\\n.tc-editor-toolbar button:hover,\\n.tc-editor-toolbar button:active {\\n border-color: \u003C\u003Ccolour primary>>;\\n background: \u003C\u003Ccolour primary>>;\\n color: \u003C\u003Ccolour background>>;\\n fill: \u003C\u003Ccolour background>>;\\n}\\n\\n.tc-tiddler-frame input.tc-edit-texteditor,\\n.tc-tiddler-frame textarea.tc-edit-texteditor,\\n.tc-tiddler-frame iframe.tc-edit-texteditor {\\n transition: border .14s ease-in-out;\\n border: 1px solid \u003C\u003Ccolour tiddler-editor-border>>;\\n background: \u003C\u003Ccolour tiddler-editor-background>>;\\n padding: 4px;\\n border-radius: 4px;\\n}\\n\\n.tc-tiddler-frame input.tc-edit-texteditor:focus,\\n.tc-tiddler-frame textarea.tc-edit-texteditor:focus,\\n.tc-tiddler-frame iframe.tc-edit-texteditor:focus {\\n box-shadow: 0 0 0.2rem 0 \u003C\u003Ccolour primary>>;\\n outline: 0;\\n border-color: \u003C\u003Ccolour primary>>;\\n}\\n\\n.tc-tiddler-controls .tc-btn-text {\\n font-size: 16px;\\n}\\n\\n\u003C\u003Cif-reveal-tiddler-controls-on-hover \\\"\\\"\\\"\\n@media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\\n .tc-tiddler-frame .tc-tiddler-controls svg {\\n opacity: 0;\\n transition: all .2s ease-in;\\n }\\n\\n .tc-tiddler-controls svg.tc-image-close-button,\\n .tc-tiddler-controls .py-toggle-todo-button svg,\\n .tc-tiddler-controls svg.tc-image-done-button,\\n .tc-tiddler-frame .tc-tiddler-controls:hover svg {\\n opacity: 1;\\n }\\n\\n .tc-tiddler-controls .py-toggle-todo-button .done svg {\\n fill: #2da562;\\n }\\n}\\n\\\"\\\"\\\">>\\n\\nbutton.tc-tag-label, span.tc-tag-label {\\n padding: 0.3em 1em !important;\\n}\\n\\n/* Fonts */\\n\\nhtml, body {\\n font-family: {{$:/themes/nico/notebook/settings/fontfamily}};\\n}\\n\\n.tc-tiddler-frame input.tc-edit-texteditor,\\n.tc-tiddler-frame textarea.tc-edit-texteditor,\\n.tc-tiddler-frame iframe.tc-edit-texteditor {\\n font-family: {{$:/themes/nico/notebook/settings/editorfontfamily}};\\n}\\n\\npre, code {\\n font-family: {{$:/themes/nico/notebook/settings/codefontfamily}};\\n}\\n\\n.tc-titlebar, .tc-site-title {\\n font-size: 28px !important;\\n line-height: 34px !important;\\n font-weight: 600 !important;\\n letter-spacing: -0.5px !important;\\n}\\n\\nh1, h2, h3, h4, h5, h6 {\\n font-weight: 600;\\n}\\n\\n.tc-tiddler-body h1,\\n.tc-tiddler-body h2,\\n.tc-tiddler-preview-preview h1,\\n.tc-tiddler-preview-preview h2 {\\n font-weight: bold;\\n}\\n\\ndiv.tc-tiddler-frame .tc-tiddler-body {\\n font-size: {{$:/themes/nico/notebook/metrics/bodyfontsize}};\\n line-height: {{$:/themes/nico/notebook/metrics/bodylineheight}};\\n}\\n\\n/* Tabs */\\n\\ndiv.tc-tab-buttons {\\n margin-bottom: -4px;\\n}\\n\\ndiv.tc-tab-buttons button {\\n font-weight: bold;\\n font-size: 1.2em;\\n line-height: 1em;\\n padding: .6em .8em .4em .8em;\\n border: 0;\\n border-radius: 0;\\n background: transparent;\\n cursor: pointer;\\n transition: background ease-in .2s;\\n}\\n\\ndiv.tc-tab-buttons button:hover {\\n background: rgba(0,0,0,.03);\\n}\\n\\ndiv.tc-tab-buttons button.tc-tab-selected {\\n border: 0;\\n background: transparent;\\n border-bottom: 4px solid \u003C\u003Ccolour primary>>;\\n}\\n\\n/* Dropdowns */\\n\\n@keyframes pop {\\n 0% {\\n transform: scale(0.8);\\n opacity: 0;\\n }\\n\\n 80% {\\n transform: scale(1.03);\\n opacity: 1;\\n }\\n\\n 100% {\\n transform: scale(1);\\n opacity: 1;\\n }\\n}\\n\\n.tc-drop-down {\\n box-shadow: 0 0 10px rgba(0,0,0,.2);\\n border-radius: 6px;\\n padding: 10px 0 !important;\\n animation: pop .15s ease-in forwards;\\n}\\n\\n.tc-drop-down a, .tc-drop-down button {\\n padding: 3px 15px !important;\\n}\\n\\n.tc-search-results {\\n line-height: 2em;\\n}\\n\\n.tc-search-results em {\\n font-weight: bold;\\n font-style: normal;\\n}\\n\\n/* Draft list */\\n\\n.tc-drafts-list {\\n font-size: .9em;\\n left: auto;\\n right: 0;\\n}\\n\\n.tc-drafts-list a {\\n padding: 6px 12px;\\n font-weight: bold;\\n border-top-left-radius: 6px;\\n border-top-right-radius: 6px;\\n display: inline-block;\\n}\\n\\n.nc-refs {\\n color: #888;\\n font-size: .9em;\\n}\\n\\n.nc-refs h4 {\\n margin-bottom: 4px;\\n}\\n\\n.nc-post-created {\\n color: #acacac;\\n font-size: .8em;\\n}\\n\"\n },\n \"$:/themes/nico/notebook/changelog\": {\n \"title\": \"$:/themes/nico/notebook/changelog\",\n \"caption\": \"ChangeLog\",\n \"created\": \"20201217180707912\",\n \"modified\": \"20210202214001915\",\n \"tags\": \"\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"! 1.4.1\\n\\n!! Fixes\\n\\n* Fix the transclusion mode of sidebar sections\\n* Fix section title rendering for tiddlers without a caption field\\n* Fix the colour of links in the sidebar when using Notebook palettes with Vanilla\\n\\n! 1.4.0\\n\\n!! Features\\n\\n* New redesigned topbar layout\\n* Add a configuration setting for the story width\\n* Add support for keyboard navigation in the search dropdown\\n\\n! 1.3.6\\n\\n!! Improvements\\n\\n* Improve the style of tabs\\n* New animation for drop-downs\\n* Use a lighter page background colour in the beige palette\\n\\n!! Fixes\\n\\n* Fix the default ctrl+shift+F shortcut for focusing the search input\\n\\n! 1.3.5\\n\\n!! Features\\n\\n* Add an option to reveal tiddler controls on mouseover\\n\\n! 1.3.4\\n\\n!! Improvements\\n\\n* Add a keyboard shortcut (alt+shift+s) to toggle Notebook sidebar\\n* Add missing colours to tiddler editor fields in the dark palette\\n\\n!! Fixes\\n\\n* Fix the size of toolbar button labels when the $:/config/Toolbar/Text is set to yes\\n\\n! 1.3.3\\n\\n!! Improvements\\n\\n* Make the sidebar more generic by using the default sidebar sections\\n\\n! 1.3.2\\n\\n!! Improvements\\n\\n* Add colours for messages in the dark palette\\n* Add colours for notification in the dark palette\\n* Set colours for messages in the beige palette\\n\\n! 1.3.1\\n\\n!! Features\\n\\n* New font family settings distinct from the Vanilla theme\\n\\n!! Improvements\\n\\n* Use a slightly lighter colour as the search input background\\n* Improve contrast of sidebar buttons in the dark palette\\n\\n!! Fixes\\n\\n* Fix tiddler control button colours in all three palettes\\n* Fix tab colours in palette-dark\\n\\n! 1.3.0\\n\\n!! Improvements\\n\\n* New dark colour palette\\n* Use a darker color for tiddler subtitles\\n* Add back the WebKit search cancel button in search inputs\\n\\n!! Fixes\\n\\n* Fix the z-index of the topbar for the zoomin story view\\n* Fix the font weight of tiddler titles in edit mode\\n\\n! 1.2.0\\n\\n!! Improvements\\n\\n* Better support for dark colour palettes\\n\\n!! Fixes\\n\\n* Fix rendering of overflowing/wrapping text in the sidebar\\n\\n! 1.1.0\\n\\n!! Features\\n\\n* New theme tweaks tab dedicated to Notebook in the control panel\\n* Inputs in the edit template are now styled consistently with other inputs\\n\\n!! Fixes\\n\\n* Fixes the position of sticky tiddler titles when the option is turned on\\n\"\n },\n \"$:/config/ShortcutInfo/notebook-focus-search\": {\n \"title\": \"$:/config/ShortcutInfo/notebook-focus-search\",\n \"text\": \"Focus on the topbar search field\"\n },\n \"$:/config/shortcuts/notebook-focus-search\": {\n \"title\": \"$:/config/shortcuts/notebook-focus-search\",\n \"text\": \"ctrl+shift+F\"\n },\n \"$:/config/Search/AutoFocus\": {\n \"title\": \"$:/config/Search/AutoFocus\",\n \"text\": \"false\"\n },\n \"$:/config/shortcuts/sidebar-search\": {\n \"title\": \"$:/config/shortcuts/sidebar-search\",\n \"text\": \"\"\n },\n \"$:/themes/nico/notebook/images/bars\": {\n \"title\": \"$:/themes/nico/notebook/images/bars\",\n \"created\": \"20200428212322206\",\n \"modified\": \"20201210210231235\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\u003Csvg class=\\\"bars\\\" height=\\\"21pt\\\" viewBox=\\\"0 0 42 42\\\" enable-background=\\\"new 0 0 32 22.5\\\" version=\\\"1.1\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n \u003Cg class=\\\"svg-menu-toggle\\\" sketch:type=\\\"MSLayerGroup\\\">\\n \u003Crect class=\\\"bar\\\" x=\\\"8\\\" y=\\\"28\\\" width=\\\"26\\\" height=\\\"4\\\">\u003C/rect>\\n \u003Crect class=\\\"bar\\\" x=\\\"8\\\" y=\\\"19\\\" width=\\\"26\\\" height=\\\"4\\\">\u003C/rect>\\n \u003Crect class=\\\"bar\\\" x=\\\"8\\\" y=\\\"10\\\" width=\\\"26\\\" height=\\\"4\\\">\u003C/rect>\\n \u003C/g>\\n\u003C/svg>\\n\"\n },\n \"$:/themes/nico/notebook/images/caret-down\": {\n \"title\": \"$:/themes/nico/notebook/images/caret-down\",\n \"created\": \"20200429194348688\",\n \"modified\": \"20201210210230919\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\u003Csvg width=\\\"6pt\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" viewBox=\\\"0 0 320 512\\\">\u003Cpath d=\\\"M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z\\\"/>\u003C/svg>\\n\"\n },\n \"$:/themes/nico/notebook/images/caret-right\": {\n \"title\": \"$:/themes/nico/notebook/images/caret-right\",\n \"created\": \"20200429194305719\",\n \"modified\": \"20201210210230909\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\u003Csvg width=\\\"4pt\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" viewBox=\\\"0 0 192 512\\\">\u003Cpath d=\\\"M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z\\\"/>\u003C/svg>\\n\"\n },\n \"$:/themes/nico/notebook/images/color-switch\": {\n \"title\": \"$:/themes/nico/notebook/images/color-switch\",\n \"created\": \"20201210170859810\",\n \"creator\": \"nico\",\n \"modified\": \"20201210205606403\",\n \"modifier\": \"nico\",\n \"tags\": \"\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\u003Csvg width=\\\"20px\\\" height=\\\"20px\\\" viewBox=\\\"0 0 16 16\\\" class=\\\"bi bi-circle-half\\\" fill=\\\"currentColor\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\">\\n \u003Cpath fill-rule=\\\"evenodd\\\" d=\\\"M8 15V1a7 7 0 1 1 0 14zm0 1A8 8 0 1 1 8 0a8 8 0 0 1 0 16z\\\"/>\\n\u003C/svg\\n\"\n },\n \"$:/themes/nico/notebook/metrics/bodyfontsize\": {\n \"title\": \"$:/themes/nico/notebook/metrics/bodyfontsize\",\n \"created\": \"20200428203454207\",\n \"modified\": \"20201210205606363\",\n \"tags\": \"\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"15px\\n\"\n },\n \"$:/themes/nico/notebook/metrics/bodylineheight\": {\n \"title\": \"$:/themes/nico/notebook/metrics/bodylineheight\",\n \"created\": \"20200428203454207\",\n \"modified\": \"20201210205606363\",\n \"tags\": \"\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"22px\"\n },\n \"$:/themes/nico/notebook/metrics/sidebar-width\": {\n \"title\": \"$:/themes/nico/notebook/metrics/sidebar-width\",\n \"created\": \"20200429144554294\",\n \"modified\": \"20201210210231246\",\n \"tags\": \"\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"350px\\n\"\n },\n \"$:/themes/nico/notebook/metrics/story-width\": {\n \"title\": \"$:/themes/nico/notebook/metrics/story-width\",\n \"created\": \"20210123210054185\",\n \"modified\": \"20210123211911688\",\n \"tags\": \"\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"800px\\n\"\n },\n \"$:/themes/nico/notebook/metrics/topbar-height\": {\n \"title\": \"$:/themes/nico/notebook/metrics/topbar-height\",\n \"created\": \"20200428203454207\",\n \"modified\": \"20201210205606363\",\n \"tags\": \"\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"52px\\n\"\n },\n \"$:/themes/nico/notebook/options/stickytitles\": {\n \"title\": \"$:/themes/nico/notebook/options/stickytitles\",\n \"text\": \"no\"\n },\n \"$:/themes/nico/notebook/options/codewrapping\": {\n \"title\": \"$:/themes/nico/notebook/options/codewrapping\",\n \"text\": \"pre-wrap\"\n },\n \"$:/themes/nico/notebook/options/reveal-tiddler-controls-on-hover\": {\n \"title\": \"$:/themes/nico/notebook/options/reveal-tiddler-controls-on-hover\",\n \"text\": \"no\"\n },\n \"$:/core/ui/PageTemplate/sidebar\": {\n \"title\": \"$:/core/ui/PageTemplate/sidebar\",\n \"created\": \"20200430072116835\",\n \"modified\": \"20201217174129501\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\\\\whitespace trim\\n\\\\define config-title()\\n$:/config/SideBarSegments/Visibility/$(listItem)$\\n\\\\end\\n\\nOverwritten by $:/themes/nico/notebook so that the default sidebar does not get rendered.\\n\"\n },\n \"$:/themes/tiddlywiki/vanilla/themetweaks\": {\n \"title\": \"$:/themes/tiddlywiki/vanilla/themetweaks\",\n \"caption\": \"{{$:/language/ThemeTweaks/ThemeTweaks}}\",\n \"created\": \"20201217163834291\",\n \"modified\": \"20201217163914434\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"Overwritten by $:/themes/nico/notebook so that the Vanilla theme tweaks do not appear in the control panel. \"\n },\n \"$:/themes/nico/notebook/palettes/palette-beige\": {\n \"title\": \"$:/themes/nico/notebook/palettes/palette-beige\",\n \"text\": \"alert-background: #ffe476\\nalert-border: #b99e2f\\nalert-highlight: #881122\\nalert-muted-foreground: #b99e2f\\nbackground: #ffffff\\nblockquote-bar: \u003C\u003Ccolour muted-foreground>>\\nbutton-background:\\nbutton-foreground:\\nbutton-border:\\ncode-background: #f7f7f9\\ncode-border: #e1e1e8\\ncode-foreground: #dd1144\\ndirty-indicator: #c63636\\ndownload-background: #66cccc\\ndownload-foreground: \u003C\u003Ccolour background>>\\ndragger-background: \u003C\u003Ccolour foreground>>\\ndragger-foreground: \u003C\u003Ccolour background>>\\ndropdown-background: \u003C\u003Ccolour background>>\\ndropdown-border: #ddd\\ndropdown-tab-background-selected: #fff\\ndropdown-tab-background: #ececec\\ndropzone-background: #da8548\\nexternal-link-background-hover: inherit\\nexternal-link-background-visited: inherit\\nexternal-link-background: inherit\\nexternal-link-foreground-hover: inherit\\nexternal-link-foreground-visited: #0000aa\\nexternal-link-foreground: #0000ee\\nforeground: #3F3B3B\\nmessage-background: #e6f5e8\\nmessage-border: #2b5532\\nmessage-foreground: #2b5532\\nmodal-backdrop: \u003C\u003Ccolour foreground>>\\nmodal-background: \u003C\u003Ccolour background>>\\nmodal-border: #999999\\nmodal-footer-background: #f5f5f5\\nmodal-footer-border: #dddddd\\nmodal-header-border: #eeeeee\\nmuted-foreground: #999999\\nnotification-background: #ffffdd\\nnotification-border: #999999\\npage-background: #f5f5ee\\npre-background: #f6f6f6\\npre-border: #cccccc\\nprimary: #7f4bca\\nselect-tag-background:\\nselect-tag-foreground:\\nsidebar-button-foreground: #a6a69c\\nsidebar-controls-foreground-hover: #000000\\nsidebar-controls-foreground: \u003C\u003Ccolour sidebar-button-foreground>>\\nsidebar-foreground-shadow: rgba(255,255,255, 0.8)\\nsidebar-foreground: #acacac\\nsidebar-muted-foreground-hover: #444444\\nsidebar-muted-foreground: #c0c0c0\\nsidebar-tab-background-selected: #ffffff\\nsidebar-tab-background: \u003C\u003Ccolour tab-background>>\\nsidebar-tab-border-selected: \u003C\u003Ccolour tab-border-selected>>\\nsidebar-tab-border: \u003C\u003Ccolour tab-border>>\\nsidebar-tab-divider: \u003C\u003Ccolour tab-divider>>\\nsidebar-tab-foreground-selected: \u003C\u003Ccolour tab-foreground-selected>>\\nsidebar-tab-foreground: \u003C\u003Ccolour tab-foreground>>\\nsidebar-tiddler-link-foreground-hover: \u003C\u003Ccolour primary>>\\nsidebar-tiddler-link-foreground: \u003C\u003Ccolour tab-foreground>>\\nsite-title-foreground: #353748\\nstatic-alert-foreground: #aaaaaa\\ntab-background-selected: #ffffff\\ntab-background: #eeeeee\\ntab-border-selected: #cccccc\\ntab-border: #cccccc\\ntab-divider: #d8d8d8\\ntab-foreground-selected: \u003C\u003Ccolour foreground>>\\ntab-foreground: #888888\\ntable-border: #dddddd\\ntable-footer-background: #a8a8a8\\ntable-header-background: #f0f0f0\\ntag-background: #ffeedd\\ntag-foreground: #000\\ntiddler-background: \u003C\u003Ccolour background>>\\ntiddler-border: #dbdbc7;\\ntiddler-controls-foreground-hover: #888888;\\ntiddler-controls-foreground-selected: #888888;\\ntiddler-controls-foreground: #cccccc\\ntiddler-editor-background: \u003C\u003Ccolour background>>\\ntiddler-editor-border-image: #ffffff\\ntiddler-editor-border: rgba(0,0,0,.2)\\ntiddler-editor-fields-even: #e0e8e0\\ntiddler-editor-fields-odd: #f0f4f0\\ntiddler-info-background: #f8f8f8\\ntiddler-info-border: #dddddd\\ntiddler-info-tab-background: #f8f8f8\\ntiddler-link-background: \u003C\u003Ccolour background>>\\ntiddler-link-foreground: \u003C\u003Ccolour primary>>\\ntiddler-subtitle-foreground: #aaaaaa\\ntiddler-title-foreground: #333\\ntoolbar-new-button:\\ntoolbar-options-button:\\ntoolbar-save-button:\\ntoolbar-info-button:\\ntoolbar-edit-button:\\ntoolbar-close-button:\\ntoolbar-delete-button:\\ntoolbar-cancel-button:\\ntoolbar-done-button:\\nuntagged-background: #999999\\nvery-muted-foreground: #888888\\n\",\n \"type\": \"application/x-tiddler-dictionary\",\n \"description\": \"A beige colour palette for Notebook\",\n \"name\": \"Notebook Beige\",\n \"tags\": \"$:/tags/Palette $:/tags/notebook/Palette\"\n },\n \"$:/themes/nico/notebook/palettes/palette-dark\": {\n \"title\": \"$:/themes/nico/notebook/palettes/palette-dark\",\n \"text\": \"alert-background: #643b43\\nalert-border: #3f181f\\nalert-highlight: #881122\\nalert-muted-foreground: #bc8b94\\nbackground: #383e49\\nblockquote-bar: \u003C\u003Ccolour muted-foreground>>\\nbutton-background:\\nbutton-border:\\nbutton-foreground:\\ncode-background: #2c323b\\ncode-border: #111\\ncode-foreground: #dd1144\\ndirty-indicator: #c63636\\ndownload-background: #98be65\\ndownload-foreground: \u003C\u003Ccolour background>>\\ndragger-background: \u003C\u003Ccolour foreground>>\\ndragger-foreground: \u003C\u003Ccolour background>>\\ndropdown-background: \u003C\u003Ccolour background>>\\ndropdown-border: #111\\ndropdown-tab-background-selected: #fff\\ndropdown-tab-background: #ececec\\ndropzone-background: #da8548\\nexternal-link-background-hover: inherit\\nexternal-link-background-visited: inherit\\nexternal-link-background: inherit\\nexternal-link-foreground-hover: inherit\\nexternal-link-foreground-visited: #61afef\\nexternal-link-foreground: #c678dd\\nforeground: #c8ced8\\nmessage-background: #2c323e\\nmessage-border: #111\\nmessage-foreground: #d5e2f1\\nmodal-backdrop: \u003C\u003Ccolour foreground>>\\nmodal-background: \u003C\u003Ccolour background>>\\nmodal-border: #999999\\nmodal-footer-background: #f5f5f5\\nmodal-footer-border: #dddddd\\nmodal-header-border: #eeeeee\\nmuted-foreground: #999999\\nnotification-background: #3a5e39\\nnotification-border: #192c19\\npage-background: #262b33\\npre-background: \u003C\u003Ccolour page-background>>\\npre-border: \u003C\u003Ccolour tiddler-border>>\\nprimary: #bf93ff\\nselect-tag-background:\\nselect-tag-foreground:\\nsidebar-button-foreground: #5e646f\\nsidebar-controls-foreground-hover: #cad2e5\\nsidebar-controls-foreground: \u003C\u003Ccolour sidebar-button-foreground>>\\nsidebar-foreground-shadow: rgba(255,255,255, 0.8)\\nsidebar-foreground: #cad2e5\\nsidebar-muted-foreground-hover: #444444\\nsidebar-muted-foreground: #c0c0c0\\nsidebar-tab-background-selected: \u003C\u003Ccolour tab-background-selected>>\\nsidebar-tab-background: \u003C\u003Ccolour tab-background>>\\nsidebar-tab-border-selected: \u003C\u003Ccolour tab-border-selected>>\\nsidebar-tab-border: \u003C\u003Ccolour tab-border>>\\nsidebar-tab-divider: \u003C\u003Ccolour tab-divider>>\\nsidebar-tab-foreground-selected: \u003C\u003Ccolour tab-foreground-selected>>\\nsidebar-tab-foreground: \u003C\u003Ccolour tab-foreground>>\\nsidebar-tiddler-link-foreground-hover: \u003C\u003Ccolour primary>>\\nsidebar-tiddler-link-foreground: \u003C\u003Ccolour tab-foreground>>\\nsite-title-foreground: \u003C\u003Ccolour foreground>>\\nstatic-alert-foreground: #aaaaaa\\ntab-background-selected: \u003C\u003Ccolour background>>\\ntab-background: \u003C\u003Ccolour page-background>>\\ntab-border-selected: \u003C\u003Ccolour foreground>>\\ntab-border: #cad2e5\\ntab-divider: #cad2e5\\ntab-foreground-selected: #ecf2ff\\ntab-foreground: #cad2e5\\ntable-border: #aaaaaa\\ntable-footer-background: #a8a8a8\\ntable-header-background: #262b33\\ntag-background: #fcb671\\ntag-foreground: #000\\ntiddler-background: \u003C\u003Ccolour background>>\\ntiddler-border: #111\\ntiddler-controls-foreground-hover: #cad2e5\\ntiddler-controls-foreground-selected: #cad2e5\\ntiddler-controls-foreground: #5e646f\\ntiddler-editor-background: \u003C\u003Ccolour background>>\\ntiddler-editor-border-image: #ffffff\\ntiddler-editor-border: rgba(255, 255, 255, 0.3)\\ntiddler-editor-fields-even: \u003C\u003Ccolour background>>\\ntiddler-editor-fields-odd: #2c323b\\ntiddler-info-background: #f8f8f8\\ntiddler-info-border: #dddddd\\ntiddler-info-tab-background: #f8f8f8\\ntiddler-link-background: \u003C\u003Ccolour background>>\\ntiddler-link-foreground: \u003C\u003Ccolour primary>>\\ntiddler-subtitle-foreground: #aaaaaa\\ntiddler-title-foreground: \u003C\u003Ccolour foreground>>\\ntoolbar-cancel-button:\\ntoolbar-close-button:\\ntoolbar-delete-button:\\ntoolbar-done-button:\\ntoolbar-edit-button:\\ntoolbar-info-button:\\ntoolbar-new-button:\\ntoolbar-options-button:\\ntoolbar-save-button:\\nuntagged-background: #999999\\nvery-muted-foreground: #888888\\n\",\n \"type\": \"application/x-tiddler-dictionary\",\n \"description\": \"A dark colour palette for Notebook\",\n \"name\": \"Notebook Dark\",\n \"tags\": \"$:/tags/Palette $:/tags/notebook/Palette\"\n },\n \"$:/themes/nico/notebook/palettes/palette-grey\": {\n \"title\": \"$:/themes/nico/notebook/palettes/palette-grey\",\n \"text\": \"alert-background: #ffe476\\nalert-border: #b99e2f\\nalert-highlight: #881122\\nalert-muted-foreground: #b99e2f\\nbackground: #ffffff\\nblockquote-bar: \u003C\u003Ccolour muted-foreground>>\\nbutton-background:\\nbutton-foreground:\\nbutton-border:\\ncode-background: #f7f7f9\\ncode-border: #e1e1e8\\ncode-foreground: #dd1144\\ndirty-indicator: #c63636\\ndownload-background: #66cccc\\ndownload-foreground: \u003C\u003Ccolour background>>\\ndragger-background: \u003C\u003Ccolour foreground>>\\ndragger-foreground: \u003C\u003Ccolour background>>\\ndropdown-background: \u003C\u003Ccolour background>>\\ndropdown-border: #ddd\\ndropdown-tab-background-selected: #fff\\ndropdown-tab-background: #ececec\\ndropzone-background: #da8548\\nexternal-link-background-hover: inherit\\nexternal-link-background-visited: inherit\\nexternal-link-background: inherit\\nexternal-link-foreground-hover: inherit\\nexternal-link-foreground-visited: #0000aa\\nexternal-link-foreground: #0000ee\\nforeground: #283c46\\nmessage-background: #ecf2ff\\nmessage-border: #cfd6e6\\nmessage-foreground: #547599\\nmodal-backdrop: \u003C\u003Ccolour foreground>>\\nmodal-background: \u003C\u003Ccolour background>>\\nmodal-border: #999999\\nmodal-footer-background: #f5f5f5\\nmodal-footer-border: #dddddd\\nmodal-header-border: #eeeeee\\nmuted-foreground: #999999\\nnotification-background: #ffffdd\\nnotification-border: #999999\\npage-background: #f4f4f4\\npre-background: #f6f6f6\\npre-border: #cccccc\\nprimary: #127edd\\nselect-tag-background:\\nselect-tag-foreground:\\nsidebar-button-foreground: #a6a69c\\nsidebar-controls-foreground-hover: #000000\\nsidebar-controls-foreground: \u003C\u003Ccolour sidebar-button-foreground>>\\nsidebar-foreground-shadow: rgba(255,255,255, 0.8)\\nsidebar-foreground: #acacac\\nsidebar-muted-foreground-hover: #444444\\nsidebar-muted-foreground: #c0c0c0\\nsidebar-tab-background-selected: #ffffff\\nsidebar-tab-background: \u003C\u003Ccolour tab-background>>\\nsidebar-tab-border-selected: \u003C\u003Ccolour tab-border-selected>>\\nsidebar-tab-border: \u003C\u003Ccolour tab-border>>\\nsidebar-tab-divider: \u003C\u003Ccolour tab-divider>>\\nsidebar-tab-foreground-selected: \u003C\u003Ccolour tab-foreground-selected>>\\nsidebar-tab-foreground: \u003C\u003Ccolour tab-foreground>>\\nsidebar-tiddler-link-foreground-hover: \u003C\u003Ccolour primary>>\\nsidebar-tiddler-link-foreground: \u003C\u003Ccolour tab-foreground>>\\nsite-title-foreground: #353748\\nstatic-alert-foreground: #aaaaaa\\ntab-background-selected: #ffffff\\ntab-background: #eeeeee\\ntab-border-selected: #cccccc\\ntab-border: #cccccc\\ntab-divider: #d8d8d8\\ntab-foreground-selected: \u003C\u003Ccolour foreground>>\\ntab-foreground: #888888\\ntable-border: #dddddd\\ntable-footer-background: #a8a8a8\\ntable-header-background: #f0f0f0\\ntag-background: #ffeedd\\ntag-foreground: #000\\ntiddler-background: \u003C\u003Ccolour background>>\\ntiddler-border: #ddd\\ntiddler-controls-foreground-hover: #888888;\\ntiddler-controls-foreground-selected: #888888;\\ntiddler-controls-foreground: #cccccc\\ntiddler-editor-background: \u003C\u003Ccolour background>>\\ntiddler-editor-border-image: #ffffff\\ntiddler-editor-border: rgba(0,0,0,.2)\\ntiddler-editor-fields-even: #e0e8e0\\ntiddler-editor-fields-odd: #f0f4f0\\ntiddler-info-background: #f8f8f8\\ntiddler-info-border: #dddddd\\ntiddler-info-tab-background: #f8f8f8\\ntiddler-link-background: \u003C\u003Ccolour background>>\\ntiddler-link-foreground: \u003C\u003Ccolour primary>>\\ntiddler-subtitle-foreground: #aaaaaa\\ntiddler-title-foreground: #333\\ntoolbar-new-button:\\ntoolbar-options-button:\\ntoolbar-save-button:\\ntoolbar-info-button:\\ntoolbar-edit-button:\\ntoolbar-close-button:\\ntoolbar-delete-button:\\ntoolbar-cancel-button:\\ntoolbar-done-button:\\nuntagged-background: #999999\\nvery-muted-foreground: #888888\\n\",\n \"type\": \"application/x-tiddler-dictionary\",\n \"description\": \"A grey color palette for Notebook\",\n \"name\": \"Notebook Grey\",\n \"tags\": \"$:/tags/Palette $:/tags/notebook/Palette\"\n },\n \"$:/themes/nico/notebook/settings/codefontfamily\": {\n \"title\": \"$:/themes/nico/notebook/settings/codefontfamily\",\n \"created\": \"20210101213404232\",\n \"modified\": \"20210101214210227\",\n \"tags\": \"\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\\\"Fira Mono\\\",\\\"Liberation Mono\\\",Menlo,Courier,monospace\\n\"\n },\n \"$:/themes/nico/notebook/settings/fontfamily\": {\n \"title\": \"$:/themes/nico/notebook/settings/fontfamily\",\n \"created\": \"20210101213404232\",\n \"modified\": \"20210101213411800\",\n \"tags\": \"\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\\\"Segoe UI\\\",Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\",\\\"Segoe UI Symbol\\\"\\n\"\n },\n \"$:/themes/nico/notebook/shortcuts/notebook-focus-search\": {\n \"title\": \"$:/themes/nico/notebook/shortcuts/notebook-focus-search\",\n \"created\": \"20201210122048919\",\n \"key\": \"((notebook-focus-search))\",\n \"modified\": \"20210115130024907\",\n \"tags\": \"$:/tags/KeyboardShortcut\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\u003C$action-sendmessage $message=\\\"tm-focus-selector\\\" $param=\\\".nc-topbar input\\\"/>\\n\"\n },\n \"$:/themes/nico/notebook/shortcuts/toggle-sidebar\": {\n \"title\": \"$:/themes/nico/notebook/shortcuts/toggle-sidebar\",\n \"created\": \"20210115130000707\",\n \"key\": \"((toggle-sidebar))\",\n \"modified\": \"20210115130021883\",\n \"tags\": \"$:/tags/KeyboardShortcut\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\u003C$list\\n filter=\\\"[[$:/state/notebook-sidebar]is[missing]] [{$:/state/notebook-sidebar}removeprefix[yes]]\\\"\\n emptyMessage=\\\"\\\"\\\"\u003C$action-setfield $tiddler=\\\"$:/state/notebook-sidebar\\\" text=\\\"yes\\\"/>\\\"\\\"\\\"\\n>\\n \u003C$action-setfield $tiddler=\\\"$:/state/notebook-sidebar\\\" text=\\\"no\\\"/>\\n\u003C/$list>\\n\"\n },\n \"$:/themes/nico/notebook/stickytitles\": {\n \"title\": \"$:/themes/nico/notebook/stickytitles\",\n \"created\": \"20201217172915960\",\n \"modified\": \"20201217180034682\",\n \"tags\": \"$:/tags/Stylesheet\",\n \"text\": \"\u003C$reveal state=\\\"$:/themes/nico/notebook/options/stickytitles\\\" type=\\\"match\\\" text=\\\"yes\\\">\\n\\n.tc-tiddler-title {\\n position: -webkit-sticky;\\n position: -moz-sticky;\\n position: -o-sticky;\\n position: -ms-sticky;\\n position: sticky;\\n top: {{$:/themes/nico/notebook/metrics/topbar-height}};\\n background: \u003C\u003Ccolour tiddler-background>>;\\n z-index: 500;\\n}\\n\\n@media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) {\\n .tc-tiddler-title {\\n top: 0;\\n }\\n}\\n\\n\u003C$list filter=\\\"[range[100]]\\\">\\n`.tc-story-river .tc-tiddler-frame:nth-child(100n+`\u003C$text text=\u003C\u003CcurrentTiddler>>/>`) {\\nz-index: `\u003C$text text={{{ [[200]subtract\u003CcurrentTiddler>] }}}/>`;\\n}\\n`\\n\u003C/$list>\\n\u003C/$reveal>\\n\"\n },\n \"$:/themes/nico/notebook/tags/Sidebar\": {\n \"title\": \"$:/themes/nico/notebook/tags/Sidebar\",\n \"created\": \"20200429164516951\",\n \"list\": \"$:/themes/nico/notebook/ui/Buttons/menu $:/themes/nico/notebook/ui/Sidebar/Headings $:/themes/nico/notebook/ui/Sidebar/Search $:/themes/nico/notebook/Sidebar/Sections\",\n \"modified\": \"20201210205606504\",\n \"type\": \"text/vnd.tiddlywiki\"\n },\n \"$:/themes/nico/notebook/tags/SidebarSection\": {\n \"title\": \"$:/themes/nico/notebook/tags/SidebarSection\",\n \"created\": \"20200429201017275\",\n \"list\": \"$:/themes/nico/notebook/ui/Sidebar/Open $:/themes/nico/notebook/ui/Sidebar/Recent $:/themes/nico/notebook/ui/Sidebar/Tools $:/themes/nico/notebook/ui/Sidebar/More\",\n \"modified\": \"20201210215658901\",\n \"type\": \"text/vnd.tiddlywiki\"\n },\n \"$:/themes/nico/notebook/ui/Bottombar\": {\n \"title\": \"$:/themes/nico/notebook/ui/Bottombar\",\n \"created\": \"20200429113453340\",\n \"modified\": \"20201210210230886\",\n \"tags\": \"$:/tags/PageTemplate\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\u003C$reveal state=\\\"$:/state/notebook-bottombar\\\" type=\\\"match\\\" text=\\\"yes\\\" default=\\\"yes\\\" retain=\\\"yes\\\" animate=\\\"yes\\\">\\n \u003Cdiv class=\\\"nc-bar nc-bottombar\\\">\\n \u003C$list filter=\\\"[all[shadows+tiddlers]tag[$:/tags/NotebookTopbar]!has[draft.of]]\\\" variable=\\\"listItem\\\">\\n \u003C$reveal type=\\\"nomatch\\\" state=\u003C\u003Cconfig-title>> text=\\\"hide\\\" tag=\\\"div\\\">\\n \u003C$transclude tiddler=\u003C\u003ClistItem>> mode=\\\"block\\\"/>\\n \u003C/$reveal>\\n \u003C/$list>\\n \u003Cdiv class=\\\"left\\\">\\n {{$:/themes/nico/notebook/ui/Buttons/menu}}\\n \u003C/div>\\n \u003Cdiv class=\\\"right\\\">\\n {{$:/core/ui/SideBarSegments/page-controls}}\\n \u003C/div>\\n \u003C/div>\\n\u003C/$reveal>\\n\\n\"\n },\n \"$:/themes/nico/notebook/ui/Buttons/SwitchPalette\": {\n \"title\": \"$:/themes/nico/notebook/ui/Buttons/SwitchPalette\",\n \"created\": \"20201210171047824\",\n \"description\": \"Toggle between grey/beige colour palette\",\n \"modified\": \"20210118213335643\",\n \"tags\": \"$:/tags/PageControls\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\u003Cspan class=\\\"desktop-only\\\">\\n \u003C$vars\\n palettes=\\\"[all[tiddlers+shadows]tag[$:/tags/notebook/Palette]]\\\"\\n popupTiddler=\u003C\u003Cqualify \\\"$:/state/notebook/palette-dropdown\\\">>\\n >\\n \u003C$button\\n popup=\u003C\u003CpopupTiddler>>\\n tooltip=\\\"Switch colours\\\"\\n aria-label=\\\"Switch colours\\\"\\n class=\u003C\u003Ctv-config-toolbar-class>>\\n >\\n \u003C$list filter=\\\"[\u003Ctv-config-toolbar-icons>match[yes]]\\\">\\n\\t{{$:/themes/nico/notebook/images/color-switch}}\\n \u003C/$list>\\n\\n \u003C$list filter=\\\"[\u003Ctv-config-toolbar-text>match[yes]]\\\">\\n\\t\u003Cspan class=\\\"tc-btn-text\\\">Switch colours\u003C/span>\\n \u003C/$list>\\n\\n \u003C$reveal state=\u003C\u003CpopupTiddler>> type=\\\"popup\\\" position=\\\"belowleft\\\" class=\\\"tc-drop-down\\\">\\n\\t\u003C$list filter=\u003C\u003Cpalettes>>>\\n\\t \u003C$button class=\\\"tc-btn-invisible\\\">\\n\\t {{!!name}}\\n\\t \u003C$action-setfield $tiddler=\\\"$:/palette\\\" text={{!!title}}/>\\n\\t \u003C/$button>\\n\\t\u003C/$list>\\n \u003C/$reveal>\\n\\n \u003C/$button>\\n \u003C/$vars>\\n\u003C/span>\\n\"\n },\n \"$:/themes/nico/notebook/ui/Buttons/menu\": {\n \"title\": \"$:/themes/nico/notebook/ui/Buttons/menu\",\n \"created\": \"20200429115248943\",\n \"modified\": \"20210124211756417\",\n \"tags\": \"\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\u003C$reveal state=\\\"$:/state/notebook-sidebar\\\" type=\\\"match\\\" text=\\\"yes\\\" default=\\\"no\\\" retain=\\\"yes\\\" animate=\\\"no\\\">\\n \u003C$button set=\\\"$:/state/notebook-sidebar\\\" setTo=\\\"no\\\" tooltip=\\\"Toggle menu\\\" class=\\\"tc-btn-invisible sidebar-toggle open\\\">\\n {{$:/themes/nico/notebook/images/bars}}\\n \u003C/$button>\\n\u003C/$reveal>\\n\\n\u003C$reveal type=\\\"nomatch\\\" state=\\\"$:/state/notebook-sidebar\\\" text=\\\"yes\\\">\\n \u003C$button set=\\\"$:/state/notebook-sidebar\\\" setTo=\\\"yes\\\" tooltip=\\\"Toggle menu\\\" class=\\\"tc-btn-invisible sidebar-toggle\\\">\\n {{$:/themes/nico/notebook/images/bars}}\\n \u003C/$button>\\n\u003C/$reveal>\\n\"\n },\n \"$:/themes/nico/notebook/ui/Search\": {\n \"title\": \"$:/themes/nico/notebook/ui/Search\",\n \"created\": \"20200429191943257\",\n \"modified\": \"20210126170723413\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\\\\define advanced-search-actions()\\n\u003C$action-setfield $tiddler=\\\"$:/temp/advancedsearch/input\\\" text={{$:/temp/notebook-search}}/>\\n\u003C$action-setfield $tiddler=\\\"$:/temp/advancedsearch/refresh\\\" text=\\\"yes\\\"/>\\n\u003C$action-navigate $to=\\\"$:/AdvancedSearch\\\"/>\\n\\\\end\\n\\n\\\\define input-accept-actions()\\n\u003C$list filter=\\\"[\u003C__tiddler__>get[text]!is[missing]] ~[\u003C__tiddler__>get[text]is[shadow]]\\\">\\n \u003C$action-navigate $to={{{ [\u003C__tiddler__>get[text]] }}}/>\\n \u003C$action-deletetiddler $filter=\\\"[[$:/temp/search]] [\u003CsearchTiddler>] [\u003CsearchListState>]\\\"/>\\n\u003C/$list>\\n\\\\end\\n\\n\\\\define cancel-search-actions()\\n\u003C$list filter=\\\"[\u003CsearchTiddler>get[text]!match{$:/temp/search}]\\\" emptyMessage=\\\"\\\"\\\"\u003C$action-deletetiddler $filter=\\\"[[$:/temp/search]] [\u003CsearchTiddler>] [\u003CsearchListState>]\\\"/>\\\"\\\"\\\">\\n \u003C$action-setfield $tiddler=\\\"$:/temp/search\\\" text={{{ [\u003CsearchTiddler>get[text]] }}}/>\\n \u003C$action-setfield $tiddler=\\\"$:/temp/search/refresh\\\" text=\\\"yes\\\"/>\u003C/$list>\\n\\\\end\\n\\n\u003C$vars editTiddler=\\\"$:/temp/search\\\"\\n searchTiddler=\\\"$:/temp/search/input\\\"\\n searchListState=\u003C\u003Cqualify \\\"$:/state/search-list/selected-item\\\">>>\\n \u003C$macrocall $name=\\\"keyboard-driven-input\\\"\\n\\t tiddler=\u003C\u003CeditTiddler>>\\n\\t storeTitle=\u003C\u003CsearchTiddler>>\\n\\t selectionStateTitle=\u003C\u003CsearchListState>>\\n\\t refreshTitle=\\\"$:/temp/search/refresh\\\"\\n\\t type=\\\"search\\\"\\n\\t tag=\\\"input\\\"\\n\\t focus={{$:/config/Search/AutoFocus}}\\n\\t focusPopup=\\\"$:/state/popup/notebook-search\\\"\\n\\t class=\\\"tc-popup-handle\\\"\\n\\t filterMinLength={{$:/config/Search/MinLength}}\\n\\t placeholder=\\\"Search...\\\"\\n\\t inputAcceptActions=\u003C\u003Cinput-accept-actions>>\\n\\t inputCancelActions=\u003C\u003Ccancel-search-actions>>\\n\\t cancelPopups=\\\"yes\\\"\\n\\t configTiddlerFilter=\\\"[[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}]\\\"\\n\\t />\\n \u003C$button\\n tooltip={{$:/language/Buttons/AdvancedSearch/Hint}}\\n aria-label={{$:/language/Buttons/AdvancedSearch/Caption}}\\n class=\\\"tc-btn-invisible tc-page-controls\\\"\\n >\\n {{$:/core/images/advanced-search-button}}\\n \u003C\u003Cadvanced-search-actions>>\\n \u003C/$button>\\n \u003C$reveal tag=\\\"div\\\" class=\\\"tc-block-dropdown-wrapper\\\" state=\\\"$:/state/popup/notebook-search\\\" type=\\\"nomatch\\\" text=\\\"\\\" default=\\\"\\\">\\n \u003C$list filter=\\\"[\u003CsearchTiddler>get[text]minlength{$:/config/Search/MinLength}limit[1]]\\\" emptyMessage=\\\"\\\" variable=\\\"listItem\\\">\\n \u003Cdiv class=\\\"tc-block-dropdown tc-search-drop-down\\\">\\n \u003C$tiddler tiddler=\u003C\u003CconfigTiddler>>>\\n {{$:/themes/nico/notebook/ui/Sidebar/SearchResults}}\\n \u003C/$tiddler>\\n \u003C/div>\\n \u003C/$list>\\n \u003C/$reveal>\\n\u003C/$vars>\\n\"\n },\n \"$:/themes/nico/notebook/ui/Sidebar/Headings\": {\n \"title\": \"$:/themes/nico/notebook/ui/Sidebar/Headings\",\n \"created\": \"20200429160014174\",\n \"modified\": \"20201210210231267\",\n \"tags\": \"$:/themes/nico/notebook/tags/Sidebar\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\u003Cdiv class=\\\"segment\\\">\\n \u003Cdiv class=\\\"content\\\">\\n \u003Ch1 class=\\\"tc-site-title\\\">\\n {{$:/SiteTitle}}\\n \u003C/h1>\\n \u003Cdiv class=\\\"tc-site-subtitle\\\">\\n {{$:/SiteSubtitle}}\\n \u003C/div>\\n \u003C/div>\\n\u003C/div>\\n\"\n },\n \"$:/themes/nico/notebook/ui/Sidebar/Search\": {\n \"title\": \"$:/themes/nico/notebook/ui/Sidebar/Search\",\n \"created\": \"20200429191943257\",\n \"modified\": \"20210124220152702\",\n \"tags\": \"$:/themes/nico/notebook/tags/Sidebar\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\u003Cdiv class=\\\"mobile-only\\\">\\n \u003Cdiv class=\\\"segment\\\">\\n \u003Cdiv class=\\\"content search\\\">\\n {{$:/themes/nico/notebook/ui/Search}}\\n \u003C/div>\\n \u003C/div>\\n\u003C/div>\\n\"\n },\n \"$:/themes/nico/notebook/ui/Sidebar/SearchResults\": {\n \"title\": \"$:/themes/nico/notebook/ui/Sidebar/SearchResults\",\n \"created\": \"20200429191943257\",\n \"modified\": \"20210126164631418\",\n \"tags\": \"\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\\\\define searchResultList()\\n \u003Csmall>{{$:/language/Search/Matches/Title}}\u003C/small>\\n\\n \u003C$list filter=\\\"[!is[system]search:title{$(searchTiddler)$}sort[title]limit[250]]\\\">\\n \u003Cspan class={{{[\u003CcurrentTiddler>addsuffix[-primaryList]] -[\u003CsearchListState>get[text]] +[then[]else[tc-list-item-selected]] }}}>\\n \u003C$transclude tiddler=\\\"$:/core/ui/ListItemTemplate\\\"/>\\n \u003C/span>\\n \u003C/$list>\\n\\n \u003Csmall>{{$:/language/Search/Matches/All}}\u003C/small>\\n\\n \u003C$list filter=\\\"[!is[system]search{$(searchTiddler)$}sort[title]limit[250]]\\\">\\n \u003Cspan class={{{[\u003CcurrentTiddler>addsuffix[-secondaryList]] -[\u003CsearchListState>get[text]] +[then[]else[tc-list-item-selected]] }}}>\\n \u003C$transclude tiddler=\\\"$:/core/ui/ListItemTemplate\\\"/>\\n \u003C/span>\\n \u003C/$list>\\n\\\\end\\n\\n\u003Cdiv class=\\\"tc-search-results\\\">\\n \u003C\u003CsearchResultList>>\\n\u003C/div>\\n\"\n },\n \"$:/themes/nico/notebook/ui/Sidebar/SectionTemplate\": {\n \"title\": \"$:/themes/nico/notebook/ui/Sidebar/SectionTemplate\",\n \"created\": \"20200429161226897\",\n \"modified\": \"20210202213859460\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\\\\define sidebarHeading()\\n\u003C$vars tv-wikilinks=\\\"no\\\">\\n \u003C$transclude field=\\\"caption\\\">\\n \u003C$view field=\\\"title\\\"/>\\n \u003C/$transclude>\\n\u003C/$vars>\\n\\\\end\\n\\n\u003C$reveal state=\\\"$:/state/notebook-sidebar-section\\\" type=\\\"match\\\" text=\u003C\u003CcurrentTiddler>> default=\\\"no\\\" animate=\\\"no\\\">\\n \u003Cdiv class=\\\"segment section open\\\">\\n \u003C$button set=\\\"$:/state/notebook-sidebar-section\\\" setTo=\\\"\\\" class=\\\"tc-btn-invisible label\\\">\\n \u003C\u003CsidebarHeading>>\\n \u003Cspan class=\\\"caret\\\">{{$:/themes/nico/notebook/images/caret-down}}\u003C/span>\\n \u003C/$button>\\n \u003Cdiv class=\\\"content\\\">\\n \u003C$transclude $tiddler=\u003C\u003CcurrentTiddler>> mode=\\\"block\\\"/>\\n \u003C/div>\\n \u003C/div>\\n\u003C/$reveal>\\n\u003C$reveal state=\\\"$:/state/notebook-sidebar-section\\\" type=\\\"nomatch\\\" text=\u003C\u003CcurrentTiddler>> default=\\\"yes\\\" animate=\\\"no\\\">\\n \u003Cdiv class=\\\"segment section\\\">\\n \u003C$button set=\\\"$:/state/notebook-sidebar-section\\\" setTo=\u003C\u003CcurrentTiddler>> class=\\\"tc-btn-invisible label\\\">\\n \u003C\u003CsidebarHeading>>\\n \u003Cspan class=\\\"caret\\\">{{$:/themes/nico/notebook/images/caret-right}}\u003C/span>\\n \u003C/$button>\\n \u003C/div>\\n\u003C/$reveal>\\n\"\n },\n \"$:/themes/nico/notebook/ui/Sidebar/Sections\": {\n \"title\": \"$:/themes/nico/notebook/ui/Sidebar/Sections\",\n \"created\": \"20200429163239707\",\n \"modified\": \"20210112213620486\",\n \"tags\": \"$:/themes/nico/notebook/tags/Sidebar\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\u003C$list filter=\\\"[all[shadows+tiddlers]!has[draft.of]tag[$:/tags/SideBar]]\\\">\\n {{||$:/themes/nico/notebook/ui/Sidebar/SectionTemplate}}\\n\u003C/$list>\\n\"\n },\n \"$:/themes/nico/notebook/ui/Sidebar\": {\n \"title\": \"$:/themes/nico/notebook/ui/Sidebar\",\n \"created\": \"20200428201218885\",\n \"modified\": \"20210112213605486\",\n \"tags\": \"$:/tags/PageTemplate\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\\\\whitespace trim\\n\\\\define config-title()\\n$:/config/SideBarSegments/Visibility/$(listItem)$\\n\\\\end\\n\\n\u003C$reveal state=\\\"$:/state/notebook-sidebar\\\" type=\\\"match\\\" text=\\\"yes\\\" default=\\\"no\\\" retain=\\\"yes\\\" animate=\\\"no\\\">\\n \u003C$scrollable fallthrough=\\\"no\\\">\\n \u003Cdiv class=\\\"nc-sidebar\\\">\\n \u003C$list filter=\\\"[all[shadows+tiddlers]tag[$:/themes/nico/notebook/tags/Sidebar]!has[draft.of]]\\\" variable=\\\"listItem\\\">\\n \u003C$reveal type=\\\"nomatch\\\" state=\u003C\u003Cconfig-title>> text=\\\"hide\\\" tag=\\\"div\\\">\\n \u003C$transclude tiddler=\u003C\u003ClistItem>> mode=\\\"inline\\\"/>\\n \u003C/$reveal>\\n \u003C/$list>\\n \u003C/div>\\n \u003C/$scrollable>\\n\u003C/$reveal>\\n\\n\"\n },\n \"$:/themes/nico/notebook/ui/Topbar\": {\n \"title\": \"$:/themes/nico/notebook/ui/Topbar\",\n \"created\": \"20200428203101797\",\n \"modified\": \"20210124213834458\",\n \"tags\": \"$:/tags/PageTemplate\",\n \"type\": \"text/vnd.tiddlywiki\",\n \"text\": \"\u003C$reveal state=\\\"$:/state/notebook-topbar\\\" type=\\\"match\\\" text=\\\"yes\\\" default=\\\"yes\\\" retain=\\\"yes\\\" animate=\\\"yes\\\">\\n \u003Cdiv class=\\\"nc-topbar-wrapper\\\">\\n \u003Cdiv class=\\\"nc-bar nc-topbar tc-adjust-top-of-scroll\\\">\\n \u003C$list filter=\\\"[all[shadows+tiddlers]tag[$:/tags/NotebookTopbar]!has[draft.of]]\\\" variable=\\\"listItem\\\">\\n \u003C$reveal type=\\\"nomatch\\\" state=\u003C\u003Cconfig-title>> text=\\\"hide\\\" tag=\\\"div\\\">\\n \u003C$transclude tiddler=\u003C\u003ClistItem>> mode=\\\"block\\\"/>\\n \u003C/$reveal>\\n \u003C/$list>\\n \u003Cdiv class=\\\"left\\\">\\n\\t{{$:/themes/nico/notebook/ui/Buttons/menu}}\\n {{$:/themes/nico/notebook/ui/Search}}\\n \u003C/div>\\n \u003Cdiv class=\\\"right\\\">\\n {{$:/core/ui/SideBarSegments/page-controls}}\\n \u003C/div>\\n \u003C/div>\\n \u003C/div>\\n\u003C/$reveal>\\n\\n\"\n }\n }\n}","bag":"default","revision":"0","version":"1.4.1","type":"application/json","title":"$:/themes/nico/notebook","source":"https://github.com/NicolasPetton/Notebook","plugin-type":"theme","name":"Notebook theme","list":"LICENSE changelog","description":"A clean, uncluttered TiddlyWiki theme","dependents":"$:/themes/tiddlywiki/vanilla $:/plugins/nico/notebook-mobile","core-version":">=5.1.22","author":"NicolasPetton"}, {"created":"20200429144554294","title":"$:/themes/nico/notebook/metrics/sidebar-width","modified":"20230423163514560","tags":"","type":"text/vnd.tiddlywiki","text":"300px"}, @@ -1250,11 +1250,11 @@ Error message and password prompt {"created":"20230426064319911","text":"\n\u003C!-- shader-doodle.js -->\n\u003Cscript>\n'use strict';(function(z,A){\"object\"===typeof exports&&\"undefined\"!==typeof module?A(exports):\"function\"===typeof define&&define.amd?define([\"exports\"],A):(z=z||self,A(z.ShaderDoodle={}))})(this,function(z){function A(a){function b(a){console.log(a);e.add(a.targetElement)}function d(b){e.has(b.targetElement)?e.delete(b.targetElement):(b=a.createBufferSource(),b.buffer=a.createBuffer(1,1,a.sampleRate),b.connect(a.destination),b.start(0),\"function\"===typeof a.resume&&a.resume().then(c),f())}function c(){v.forEach(a=>\n{a()})}function f(){p.forEach(a=>{a.removeEventListener(\"touchstart\",d);a.removeEventListener(\"touchmove\",b);a.removeEventListener(\"touchend\",d);a.removeEventListener(\"mouseup\",d)});p.clear();e.clear()}let e=new Set,p=new Set,v=[];return{onStart:function(b){\"running\"===a.state?(console.log(\"already\"),b()):v.push(b)},register:function(a){a.addEventListener(\"touchstart\",d);a.addEventListener(\"touchmove\",b);a.addEventListener(\"touchend\",d);a.addEventListener(\"mouseup\",d);p.add(a)},dispose:f}}function ca(){function a(a){d[0].value[0]=\na.alpha;d[0].value[1]=a.beta;d[0].value[2]=a.gamma}let b=!1,d=JSON.parse(JSON.stringify(L));return{get ustate(){return d},setup:function(){b||(b=!0,\"object\"===typeof DeviceOrientationEvent&&\"function\"===typeof DeviceOrientationEvent.requestPermission?DeviceOrientationEvent.requestPermission().then(b=>{\"granted\"===b&&window.addEventListener(\"deviceorientation\",a)}).catch(console.error):window.addEventListener(\"deviceorientation\",a))},dispose:function(){window.removeEventListener(\"deviceorientation\",\na)}}}function da(a){let b={},d=a.getExtension.bind(a);return{get:function(a){if(void 0!==b[a])return b[a];let c=d(a)||d(\"MOZ_\".concat(a))||d(\"WEBKIT_\".concat(a));null===c&&console.warn(\"\u003Cshader-doodle /> \".concat(a,\" extension not supported.\"));return b[a]=c}}}function C(){function a(a,b){if(a>n||b>h)a=Math.max(a,n),b=Math.max(b,h),a!==n&&(n=a,c.width=Math.floor(1*n)),b!==h&&(h=b,c.height=Math.floor(1*h))}function b(a){let b=l?(a-l)/1E3:0;l=a;k[0].value+=b;k[1].value=b;k[3].value++;a=new Date;k[2].value[0]=\na.getFullYear();k[2].value[1]=a.getMonth()+1;k[2].value[2]=a.getDate();k[2].value[3]=3600*a.getHours()+60*a.getMinutes()+a.getSeconds()+.001*a.getMilliseconds()}function d(f){if(m.size){b(f);var u=[...k,...e.ustate];m.forEach(b=>b.render(c,a,n,h,1,u));q=requestAnimationFrame(d)}else q=void 0}let c=document.createElementNS(\"http://www.w3.org/1999/xhtml\",\"canvas\"),f=c.getContext(\"webgl\")||c.getContext(\"experimental-webgl\"),e=ca(),p=new (window.AudioContext||window.webkitAudioContext),v=new A(p);p.onStart=\nv.onStart;f.blendFunc(f.SRC_ALPHA,f.ONE_MINUS_SRC_ALPHA);f.enable(f.BLEND);let n=0,h=0,q,l,m=new Set,k=JSON.parse(JSON.stringify(M)),w=da(f);w.get(\"OES_texture_float\");w.get(\"OES_texture_float_linear\");w.get(\"OES_texture_half_float\");w.get(\"OES_texture_half_float_linear\");f.clearColor(0,0,0,0);return Object.freeze({get gl(){return f},get wa(){return p},addSurface:function(a){v.register(a.dom);a.addClick(e.setup);m.add(a);q||(q=requestAnimationFrame(d))},removeSurface:function(a){m.delete(a)},addUniform:function(a,\nb,c){for(let d=0;d\u003Ck.length;d++)if(k[d].name===a){k[d].value=b;k[d].type=c;return}k.push({name:a,value:b,type:c,toyname:a})},setUniform:function(a,b){for(let c=0;c\u003Ck.length;c++)if(k[c].name===a){k[c].value=b;break}},dispose:function(){m.forEach(a=>a.dispose());m.clear();m=void 0;cancelAnimationFrame(q);e.dispose();v.dispose()}})}function ea(a,b){let d={},c=a.getProgramParameter(b,a.ACTIVE_ATTRIBUTES);for(let f=0;f\u003Cc;f++){let {name:c}=a.getActiveAttrib(b,f);d[c]=a.getAttribLocation(b,c)}return d}function N(a){function b(b){a.texParameteri(a.TEXTURE_2D,\na.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE);a.texParameteri(a.TEXTURE_2D,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE);a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MIN_FILTER,b?a.NEAREST:a.LINEAR);a.texParameteri(a.TEXTURE_2D,a.TEXTURE_MAG_FILTER,b?a.NEAREST:a.LINEAR)}let d,c,f=a.createFramebuffer();a.bindFramebuffer(a.FRAMEBUFFER,f);let e=a.createTexture();if(!e)throw Error(\"createTexture returned null\");a.bindTexture(a.TEXTURE_2D,e);b(!0);a.framebufferTexture2D(a.FRAMEBUFFER,a.COLOR_ATTACHMENT0,a.TEXTURE_2D,e,0);return{get handle(){return f},\nget texture(){return e},updateTexture:b,bind:function(){a.bindFramebuffer(a.FRAMEBUFFER,f);a.viewport(0,0,d,c)},updateResolution:function(b,f){if(b!==d||f!==c)d=b,c=f,a.bindTexture(a.TEXTURE_2D,e),a.texImage2D(a.TEXTURE_2D,0,a.RGBA,b,f,0,a.RGBA,a.FLOAT,null)},dispose:function(){a.deleteFramebuffer(f);a.deleteTexture(e)}}}function O(a,b,d){b=a.createShader(b);a.shaderSource(b,d);a.compileShader(b);if(!a.getShaderParameter(b,a.COMPILE_STATUS)){let c=a.getShaderInfoLog(b);a.deleteShader(b);console.warn(c,\n\"\\nin shader:\\n\",d)}return b}function H(a,b){if(a.length!==b.length)return!1;for(let d=0,c=a.length;d\u003Cc;d++)if(a[d]!==b[d])return!1;return!0}function I(a,b){for(let d=0,c=b.length;d\u003Cc;d++)a[d]=b[d]}function fa(a,b,d,c){a[0]!==c&&(d.uniform1f(b,c),a[0]=c)}function ha(a,b,d,c){H(a,c)||(d.uniform2fv(b,c),I(a,c))}function ia(a,b,d,c){H(a,c)||(d.uniform3fv(b,c),I(a,c))}function ja(a,b,d,c){H(a,c)||(d.uniform4fv(b,c),I(a,c))}function ka(a,b,d,c){a[0]!==c&&(d.uniform1i(b,c),a[0]=c)}function la(a){switch(a){case 5126:return fa;\ncase 35664:return ha;case 35665:return ia;case 35666:return ja;case 35678:case 36198:return ka}}function ma(a,b,d){let c=[],f=la(b.type);return{get location(){return d},get name(){return b.name},setValue:function(...b){f(c,d,a,...b)}}}function na(a,b){let d={},c=a.getProgramParameter(b,a.ACTIVE_UNIFORMS);for(let e=0;e\u003Cc;e++){var f=a.getActiveUniform(b,e);let c=a.getUniformLocation(b,f.name);f=ma(a,f,c);d[f.name]=f}return d}function oa(a,b){if(b){let b=a.match(P);a=a.replace(\"mainImage\",\"main\");a=\na.replace(P,\"()\");a=(b?\"#define \".concat(b[1],\" gl_FragColor\\n#define \").concat(b[2],\" gl_FragCoord.xy\\n\"):\"\")+a}a=pa(qa,b)+a;return\"precision highp float;\\n\"+a}function ra(a,b,d,c,f=!1){function e(a){let b=r[F(a,f,\"name\")];b&&b.setValue(F(a,f,\"value\"))}function p(b){b.forEach(e);t.forEach(a=>a.update(e));k&&r.u_prevbuffer&&(b=r.u_prevbuffer)&&(b.setValue(w),a.activeTexture(a[\"TEXTURE\".concat(w)]),a.bindTexture(a.TEXTURE_2D,k.texture),k.updateTexture());g.forEach(b=>{r[b.name].setValue(b.u);a.activeTexture(a[\"TEXTURE\".concat(b.u)]);\na.bindTexture(a.TEXTURE_2D,b.fbo.texture);b.fbo.updateTexture()})}let v=sa++,n=a.createProgram(),h=a.createBuffer();b=O(a,a.VERTEX_SHADER,b);d=O(a,a.FRAGMENT_SHADER,oa(d,f));a.attachShader(n,b);a.attachShader(n,d);a.linkProgram(n);let q,l,m,k,w,u=ea(a,n),r=na(a,n),g=new Set,t=new Set,x=0;if(!a.getProgramParameter(n,a.LINK_STATUS)){let b=a.getProgramInfoLog(n);console.warn(b)}a.detachShader(n,b);a.detachShader(n,d);a.deleteShader(b);a.deleteShader(d);b=u.position;a.bindBuffer(a.ARRAY_BUFFER,h);a.bufferData(a.ARRAY_BUFFER,\nc,a.STATIC_DRAW);a.enableVertexAttribArray(b);a.vertexAttribPointer(b,2,a.FLOAT,!1,0,0);return{get id(){return v},get nodes(){return g},get fbo(){return m},get name(){return q},get u(){return l},render:function(b,c,d){g.size&&g.forEach(a=>a.render(b,c,d));if(m){if(k){let a=m;m=k;k=a;k.bind();k.updateResolution(b,c)}m.updateResolution(b,c);m.bind()}else a.bindFramebuffer(a.FRAMEBUFFER,null),a.viewport(0,0,b,c);a.clear(a.COLOR_BUFFER_BIT);a.useProgram(n);p(d);a.drawArrays(a.TRIANGLES,0,6)},addNode:function(a,\nb,c){a.toFbo(b,x++,c);g.add(a)},removeNode:function(a){g.delete(a)},addTexture:function(a){t.add(a)},removeTexture:function(a){t.delete(a)},getTexUnit:function(){return x++},update:p,toFbo:function(b,c,d){q=b;l=c;m=N(a);d&&(k=N(a),w=x++)},dispose:function(){t.forEach(a=>a.dispose());t.clear();a.deleteProgram(n)}}}function Q(a){if(!a)return[0,0];let b=(a.tagName||\"\").toLowerCase();return\"video\"===b?[a.videoWidth,a.videoHeight]:\"img\"===b?[a.naturalWidth,a.naturalHeight]:[a.width,a.height]}function R(a,\nb,d={}){function c(){a.getParameter(a.ACTIVE_TEXTURE)!==b&&a.activeTexture(a[\"TEXTURE\".concat(b)])}function f(){h.forEach(b=>{a.texParameteri(p,b[0],b[1])})}function e(b){if(\"object\"===typeof b){Object.assign(n,b);c();a.bindTexture(p,v);var {level:d,internalFormat:e,offsetX:h,offsetY:r,width:g,height:t,border:m,format:B,type:D,flipY:z,buffer:y,pixels:A}=n;f();a.pixelStorei(a.UNPACK_FLIP_Y_WEBGL,z);if(A){let [c,d]=Q(A);if(0===c||0===d){console.warn(\"Texture size is invalid \".concat(c,\" x \").concat(d,\n\". Update is skipped;\"));return}{({pixels:b}=n);var J=a.getTexParameter(p,a.TEXTURE_WRAP_S);let c=a.getTexParameter(p,a.TEXTURE_WRAP_T),d=a.getTexParameter(p,a.TEXTURE_MIN_FILTER),f=G(b.width)&&G(b.height);(J=J!==a.CLAMP_TO_EDGE||c!==a.CLAMP_TO_EDGE||d!==a.LINEAR&&d!==a.NEAREST)&&!f&&(l||(l=document.createElement(\"canvas\"),l.width=2**Math.floor(Math.log(b.width)/Math.LN2),l.height=2**Math.floor(Math.log(b.height)/Math.LN2),console.warn(\"Texture is not power of two \".concat(b.width,\" x \").concat(b.height,\n\". Resized to \").concat(l.width,\" x \").concat(l.height,\";\"))),l.getContext(\"2d\").drawImage(b,0,0,l.width,l.height));q=J&&l||b}}\"number\"===typeof h&&\"number\"===typeof r?q?a.texSubImage2D(p,d,h,r,B,D,q):a.texSubImage2D(p,d,h,r,g,t,B,D,y):q?a.texImage2D(p,d,e,B,D,q):a.texImage2D(p,d,e,g,t,m,B,D,y);q&&G(q.width)&&G(q.height)&&(b=a.getTexParameter(p,a.TEXTURE_MIN_FILTER),b!==a.LINEAR&&b!==a.NEAREST&&a.generateMipmap(p))}}let p=a.TEXTURE_2D,v=a.createTexture(),n={},h=[],q,l;e(Object.assign({level:0,internalFormat:a.RGBA,\noffsetX:null,offsetY:null,width:1,height:1,border:0,format:a.RGBA,type:a.UNSIGNED_BYTE,flipY:!0,buffer:ta,pixels:null},\"object\"===typeof d?d:{}));return{setParameters:function(b){c();h.length=0;b.forEach(b=>{h.push(b);a.texParameteri(p,b[0],b[1])})},shallow:function(){c();a.bindTexture(p,v);f()},update:e,dispose:function(){a.deleteTexture(v)}}}function ua(a){return new Promise((b,d)=>{let c=new XMLHttpRequest;c.open(\"GET\",a,!0);c.responseType=\"arraybuffer\";c.onreadystatechange=()=>{c.readyState===\nXMLHttpRequest.DONE&&(200===c.status||206===c.status?b(c.response):(console.log(c),d(c.status)))};c.send()})}function va(a,b){return new Promise((d,c)=>{b.decodeAudioData(a,d,c)})}function wa(a,b,d,c,f,e,p,v){async function n(){g=l.createBufferSource();g.buffer=await va(await ua(c),l);g.loop=e;g.start();t=!0}function h(){let a=document.querySelector(c);a&&a instanceof HTMLAudioElement&&(r=a,g=l.createMediaElementSource(a))}function q(a,b){a.connect(m);m.connect(b)}f=a.gl;let l=a.wa,m=l.createAnalyser();\nm.fftSize=1024;let k=new Uint8Array(m.frequencyBinCount),w=new Uint8Array(m.frequencyBinCount),u=R(f,b,{internalFormat:f.LUMINANCE,width:w.length,height:2,format:f.LUMINANCE,buffer:null});u.setParameters([[f.TEXTURE_WRAP_S,f.CLAMP_TO_EDGE],[f.TEXTURE_WRAP_T,f.CLAMP_TO_EDGE],[f.TEXTURE_MIN_FILTER,f.NEAREST]]);let r,g,t=!1,x=[{name:d,value:b}];\"#\"===c[0]?h():c&&n();g&&q(g,l.destination);return{dispose:function(){u.dispose()},update:function(a){x.forEach(a);if(t||r&&2\u003Cr.readyState&&!r.paused&&!r.ended&&\nr.currentTime)m.getByteFrequencyData(k),m.getByteTimeDomainData(w),u.update({offsetX:0,offsetY:0,height:1,buffer:k}),u.update({offsetX:0,offsetY:1,height:1,buffer:w})}}}function S(a,b){var d=Object.keys(a);if(Object.getOwnPropertySymbols){var c=Object.getOwnPropertySymbols(a);b&&(c=c.filter(function(b){return Object.getOwnPropertyDescriptor(a,b).enumerable}));d.push.apply(d,c)}return d}function T(a){let b=document.createElement(\"div\");b.style.width=b.style.height=\"1px\";b.style.overflow=\"hidden\";b.style.position=\n\"absolute\";b.style.opacity=\"0\";b.style.pointerEvents=\"none\";b.style.zIndex=\"-1000\";b.appendChild(a);document.body.appendChild(b)}function xa(a,b,d,c,f,e,p,v,n,h){function q(){t=0;g=new Image;g.crossOrigin=\"anonymous\";g.onload=l;g.onerror=()=>{console.warn(\"failed loading src: \".concat(c))};g.src=c}function l(){k();r.setParameters([[u.TEXTURE_WRAP_S,e],[u.TEXTURE_WRAP_T,p],[u.TEXTURE_MIN_FILTER,v],[u.TEXTURE_MAG_FILTER,n]]);r.update({pixels:g})}function m(){t=2;let a=navigator.getUserMedia||navigator.webkitGetUserMedia||\nnavigator.mozGetUserMedia,b=a=>{g=document.createElement(\"video\");g.width=320;g.height=240;g.autoplay=!0;g.srcObject=a;T(g)},c=()=>{navigator.mediaDevices.getUserMedia({video:!0}).then(b).catch(a=>console.log(a.name+\": \"+a.message))},d=()=>{a({video:!0},b,a=>a)};navigator.mediaDevices&&navigator.mediaDevices.getUserMedia?c():a&&d()}function k(){if(g){let [a,b]=Q(g);x[1].value[0]=a;x[1].value[1]=b}}function w(){return(2===t||1===t)&&g instanceof HTMLVideoElement}let u=a.gl,r=R(u,b),g,t,x=[{name:d,\nvalue:b},{name:d+\"_resolution\",value:[0,0]}],B=!1;if(f)m();else if(ya.test(c))t=1,g=document.createElement(\"video\"),g.autoplay=!0,g.muted=!0,g.loop=!0,g.playsInline=!0,g.crossOrigin=\"anonymous\",g.src=c,T(g),g.play();else if(za.test(c))q();else{try{g=document.querySelector(c)}catch(D){console.warn(\"src: \".concat(c,\": invalid selector\"))}g?g instanceof HTMLImageElement?(t=0,g.complete?l():g.addEventListener(\"load\",l)):g instanceof HTMLVideoElement?t=1:g instanceof HTMLCanvasElement?(t=3,l()):g instanceof\nK?(g=g.surface.dom,t=3,l()):console.warn(\"src: \".concat(c,\": element is not a valid texture source\")):console.warn(\"src: \".concat(c,\": no element could be selected\"))}return{dispose:function(){r.dispose()},update:function(a){x.forEach(a);h||w()&&g.readyState===g.HAVE_ENOUGH_DATA?(w()&&(B||(B=!0,k(),r.setParameters([[u.TEXTURE_WRAP_S,u.CLAMP_TO_EDGE],[u.TEXTURE_WRAP_T,u.CLAMP_TO_EDGE],[u.TEXTURE_MIN_FILTER,u.LINEAR]]))),r.update({pixels:g})):r.shallow()}}}function Aa(a){function b(a){n.forEach(a=>\n\"function\"===typeof a&&a());k=!0;a=U(a);let {top:b,left:c,height:d}=q;h[2].value[0]=h[2].value[2]=a[0]-Math.floor(c);h[2].value[1]=h[2].value[3]=Math.floor(d)-(a[1]-Math.floor(b))}function d(a){if(!m){a=U(a);let {top:b,left:c,height:d}=q;h[1].value[0]=a[0]-Math.floor(c);h[1].value[1]=Math.floor(d)-(a[1]-Math.floor(b));k&&(h[2].value[0]=h[1].value[0],h[2].value[1]=h[1].value[1]);m=!0}}function c(a){k=!1;1===Math.sign(h[2].value[2])&&(h[2].value[2]*=-1);1===Math.sign(h[2].value[3])&&(h[2].value[3]*=\n-1)}function f(){let b=e.getBoundingClientRect();l=0\u003C=b.top+b.height&&0\u003C=b.left+b.width&&b.bottom-b.height\u003C=(window.innerHeight||document.documentElement.clientHeight)&&b.right-b.width\u003C=(window.innerWidth||document.documentElement.clientWidth);let c=0\u003Ca.height?a.height:b.height,d=0\u003Ca.width?a.width:b.width;d!==h[0].value[0]&&(e.width=h[0].value[0]=d);c!==h[0].value[1]&&(e.height=h[0].value[1]=c);q=b}let e=a.canvas instanceof HTMLCanvasElement?a.canvas:document.createElementNS(\"http://www.w3.org/1999/xhtml\",\n\"canvas\"),p=e.getContext(\"2d\"),v=a.program,n=new Set,h=JSON.parse(JSON.stringify(V)),q={},l,m,k;e.addEventListener(\"mousedown\",b);e.addEventListener(\"mousemove\",d);e.addEventListener(\"mouseup\",c);e.addEventListener(\"mouseout\",c);e.addEventListener(\"touchstart\",b);e.addEventListener(\"touchmove\",d);e.addEventListener(\"touchend\",c);f();return Object.freeze({get dom(){return e},render:function(a,b,c,d,e,k){f();m=!1;if(l&&v){var g=h[0].value[0]||0;c=h[0].value[1]||0;b(g,c);v.render(g,c,[...k,...h]);b=\ng*e;e*=c;p.clearRect(0,0,b,e);p.drawImage(a,0,d-e,b,e,0,0,b,e)}},addClick:function(a){n.add(a)},dispose:function(){n.clear();e.removeEventListener(\"mousedown\",b);e.removeEventListener(\"mousemove\",d);e.removeEventListener(\"mouseup\",c);e.removeEventListener(\"mouseout\",c);e.removeEventListener(\"touchstart\",b);e.removeEventListener(\"touchmove\",d);e.removeEventListener(\"touchend\",c)}})}var W={render(a,b){return\"\".concat(this.css(a,b),\"\\n \").concat(this.html())},map(a){return{canvas:a.querySelector(\"canvas\")}},\nhtml(a){return\"\u003Ccanvas>\u003C/canvas>\"},css(a,b){return\"\u003Cstyle>\\n :host {\\n position: relative;\\n display: inline-block;\\n width: \".concat(a||250,\"px;\\n height: \").concat(b||250,\"px;\\n }\\n :host > canvas {\\n position: absolute;\\n top: 0;\\n left: 0;\\n height: 100%;\\n width: 100%;\\n border-radius: inherit;\\n }\\n \u003C/style>\")}};let M=[{name:\"u_time\",toyname:\"iTime\",type:\"float\",value:0},{name:\"u_delta\",toyname:\"iTimeDelta\",\ntype:\"float\",value:0},{name:\"u_date\",toyname:\"iDate\",type:\"vec4\",value:[0,0,0,0]},{name:\"u_frame\",toyname:\"iFrame\",type:\"int\",value:0}],V=[{name:\"u_resolution\",toyname:\"iResolution\",type:\"vec2\",value:[0,0]},{name:\"u_mouse\",toyname:\"iCurrentMouse\",type:\"vec2\",value:[0,0]},{name:\"u_mousedrag\",toyname:\"iMouse\",type:\"vec4\",value:[0,0,0,0]}],L=[{name:\"u_orientation\",toyname:\"iOrientation\",type:\"vec3\",value:[0,0,0]}],qa=[...M,...L,...V],P=/\\(\\s*out\\s+vec4\\s+(\\S+)\\s*,\\s*in\\s+vec2\\s+(\\S+)\\s*\\)/,y;C.singleton=\nfunction(){y||(y=C());return y};C.resetSingleton=function(){y&&y.dispose();y=C()};class E extends HTMLElement{get renderer(){return C.singleton()}get name(){return this.getAttribute(\"name\")}set name(a){this.setAttribute(\"name\",a)}}var F=(a,b,d)=>{if(!b)return a[d];b=\"toy\".concat(d);return a.hasOwnProperty(b)?a[b]:a[d]},pa=(a,b)=>Object.values(a).reduce((a,c)=>a+\"uniform \".concat(F(c,b,\"type\"),\" \").concat(F(c,b,\"name\"),\";\\n\"),\"\");let sa=0;var Ba=a=>new Promise((b,d)=>{let c=new XMLHttpRequest;c.open(\"GET\",\na);c.onreadystatechange=()=>{c.readyState===XMLHttpRequest.DONE&&(200===c.status?b(c.responseText):d(c.status))};c.send()}),X=async a=>a.src?Ba(a.src):a.text;let Y=new Float32Array([-1,1,1,1,1,-1,-1,1,1,-1,-1,-1]),Ca=0;class Z extends E{disconnectedCallback(){this.program.dispose();this.program=void 0}get shadertoy(){return this.hasAttribute(\"shadertoy\")}set shadertoy(a){a?this.setAttribute(\"shadertoy\",\"\"):this.removeAttribute(\"shadertoy\")}get prevbuffer(){return this.hasAttribute(\"prevbuffer\")}set prevbuffer(a){a?\nthis.setAttribute(\"prevbuffer\",\"\"):this.removeAttribute(\"prevbuffer\")}get vertices(){let a=this.getAttribute(\"vertices\");if(!a)return Y;a=JSON.parse(a);return Array.isArray(a)?new Float32Array(a):Y}set vertices(a){a&&Array.isArray(a)&&this.setAttribute(\"vertices\",JSON.stringify(a))}async init(a){a&&!this.name&&(this.name=\"\".concat(\"u_node\").concat(Ca++));let b=[],d,c;for(let a=0;a\u003Cthis.children.length;a++){let e=this.children[a];if(e instanceof E)b.push(e);else switch(e.getAttribute(\"type\")){case \"x-shader/x-fragment\":c=\nawait X(e);break;case \"x-shader/x-vertex\":d=await X(e)}}this.program=ra(this.renderer.gl,d||\"attribute vec2 position;\\nvoid main() {\\n gl_Position = vec4(position, 0.0, 1.0);\\n}\",c,this.vertices,this.shadertoy);b.forEach(a=>{a.init(this.program)});a&&a.addNode(this.program,this.name,this.prevbuffer)}}customElements.get(\"sd-node\")||customElements.define(\"sd-node\",Z);let ta=new Uint8Array([0,0,0,255]),G=a=>!(a&a-1)&&!!a,Da=0;class Ea extends E{disconnectedCallback(){this.program.removeTexture(this.texture);\nthis.texture.dispose()}get src(){return this.getAttribute(\"src\")}set src(a){this.setAttribute(\"src\",a)}get autoplay(){return this.hasAttribute(\"autoplay\")}set autoplay(a){a?this.setAttribute(\"autoplay\",\"\"):this.removeAttribute(\"autoplay\")}get loop(){return this.hasAttribute(\"loop\")}set loop(a){a?this.setAttribute(\"loop\",\"\"):this.removeAttribute(\"loop\")}get crossOrigin(){return this.getAttribute(\"crossorigin\")}set crossOrigin(a){this.setAttribute(\"crossorigin\",a)}get mic(){return this.hasAttribute(\"mic\")}set mic(a){a?\nthis.setAttribute(\"mic\",\"\"):this.removeAttribute(\"mic\")}init(a){this.name||(this.name=\"\".concat(\"u_audio\").concat(Da++));this.src&&(this.program=a,this.texture=wa(this.renderer,a.getTexUnit(),this.name,this.src,this.mic,this.loop,this.autoplay,this.crossOrigin),a.addTexture(this.texture))}}customElements.get(\"sd-audio\")||customElements.define(\"sd-audio\",Ea);let za=/\\w+\\.(jpg|jpeg|png|gif|bmp)(?=\\?|$)/i,ya=/\\w+\\.(mp4|3gp|webm|ogv)(?=\\?|$)/i,aa={NEAREST:9728,LINEAR:9729},Fa=function(a){for(var b=1;b\u003C\narguments.length;b++){var d=null!=arguments[b]?arguments[b]:{};b%2?S(d,!0).forEach(function(b){var c=d[b];b in a?Object.defineProperty(a,b,{value:c,enumerable:!0,configurable:!0,writable:!0}):a[b]=c}):Object.getOwnPropertyDescriptors?Object.defineProperties(a,Object.getOwnPropertyDescriptors(d)):S(d).forEach(function(b){Object.defineProperty(a,b,Object.getOwnPropertyDescriptor(d,b))})}return a}({},aa,{NEAREST_MIPMAP_NEAREST:9984,LINEAR_MIPMAP_NEAREST:9985,NEAREST_MIPMAP_LINEAR:9986,LINEAR_MIPMAP_LINEAR:9987}),\nba={REPEAT:10497,MIRRORED_REPEAT:33648,CLAMP_TO_EDGE:33071},Ga=0;class Ha extends E{static get observedAttributes(){return\"mag-filter min-filter name src wrap-s wrap-t\".split(\" \")}disconnectedCallback(){this.program.removeTexture(this.texture);this.texture.dispose()}get forceUpdate(){return this.hasAttribute(\"force-update\")}set forceUpdate(a){a?this.setAttribute(\"force-update\",\"\"):this.removeAttribute(\"force-update\")}get magFilter(){return aa[this.getAttribute(\"mag-filter\")]||9729}get minFilter(){return Fa[this.getAttribute(\"min-filter\")]||\n9987}get src(){return this.getAttribute(\"src\")}set src(a){this.setAttribute(\"src\",a)}get webcam(){return this.hasAttribute(\"webcam\")}set webcam(a){a?this.setAttribute(\"webcam\",\"\"):this.removeAttribute(\"webcam\")}get wrapS(){return ba[this.getAttribute(\"wrap-s\")]||10497}get wrapT(){return ba[this.getAttribute(\"wrap-t\")]||10497}init(a){this.name||(this.name=\"\".concat(\"u_texture\").concat(Ga++));if(this.src||this.webcam)this.program=a,this.texture=xa(this.renderer,a.getTexUnit(),this.name,this.src,this.webcam,\nthis.wrapS,this.wrapT,this.minFilter,this.magFilter,this.forceUpdate),a.addTexture(this.texture)}}customElements.get(\"sd-texture\")||customElements.define(\"sd-texture\",Ha);class Ia extends E{disconnectedCallback(){}get x(){return parseFloat(this.getAttribute(\"x\"))}set x(a){null!=a?this.setAttribute(\"x\",a):this.removeAttribute(\"x\")}get y(){return parseFloat(this.getAttribute(\"y\"))}set y(a){null!=a?this.setAttribute(\"y\",a):this.removeAttribute(\"y\")}get z(){return parseFloat(this.getAttribute(\"z\"))}set z(a){null!=\na?this.setAttribute(\"z\",a):this.removeAttribute(\"z\")}get w(){return parseFloat(this.getAttribute(\"w\"))}set w(a){null!=a?this.setAttribute(\"w\",a):this.removeAttribute(\"w\")}getValue(){switch(this.type){case \"vec2\":return[this.x,this.y];case \"vec3\":return[this.x,this.y,this.z];case \"vec4\":return[this.x,this.y,this.z,this.w];default:return this.x}}get type(){return this.getAttribute(\"type\")}set type(a){null!=a?this.setAttribute(\"type\",a):this.removeAttribute(\"type\")}static get observedAttributes(){return[\"x\",\n\"y\",\"z\",\"w\"]}attributeChangedCallback(a,b,d){switch(a){case \"x\":case \"y\":case \"z\":case \"w\":null!=d&&this.renderer.setUniform(this.name,this.getValue())}}init(a){this.name?(this.program=a,this.renderer.addUniform(this.name,this.getValue(),this.type)):console.warn(\"sd-uniform created without a name.\")}}customElements.get(\"sd-uniform\")||customElements.define(\"sd-uniform\",Ia);let Ja=new Set([\"touchstart\",\"touchmove\",\"touchend\"]);var U=a=>{a=Ja.has(a.type)&&\"object\"===typeof a.touches[0]?a.touches[0]:\na;return[a.clientX||0,a.clientY||0]};class K extends Z{static get observedAttributes(){return[\"height\",\"width\"]}constructor(){super();this.shadow=this.attachShadow({mode:\"open\"})}connectedCallback(){this.shadow.innerHTML=W.render(this.width,this.height);this.canvas=W.map(this.shadow).canvas;setTimeout(()=>{try{this.init()}catch(a){console.error(a&&a.message||\"Error in shader-doodle.\")}})}disconnectedCallback(){super.disconnectedCallback();this.renderer.removeSurface(this.surface);this.surface.dispose();\nthis.surface=void 0}attributeChangedCallback(a){let b=this.shadow.styleSheets;if((\"height\"===a||\"width\"===a)&&0\u003Cb.length){let d=this[a];b[0].cssRules[0].style[a]=Number.isInteger(d)?\"\".concat(d,\"px\"):\"250px\"}}get height(){let a=parseInt(this.getAttribute(\"height\"));return Number.isInteger(a)?a:void 0}set height(a){let b=parseInt(a);Number.isInteger(b)&&this.setAttribute(\"height\",a)}get width(){let a=parseInt(this.getAttribute(\"width\"));return Number.isInteger(a)?a:void 0}set width(a){a=parseInt(a);\nNumber.isInteger(a)&&this.setAttribute(\"width\",a)}async init(){await super.init();this.surface=Aa(this);this.renderer.addSurface(this.surface)}}customElements.get(\"shader-doodle\")||customElements.define(\"shader-doodle\",K);z.ShaderDoodleElement=K;Object.defineProperty(z,\"__esModule\",{value:!0})})\n\u003C/script>","tags":"$:/tags/RawMarkup","title":"$:/webxr-notebook/shader-doodle.js","modified":"20230426064515285"}, {"created":"20230427155228509","text":"\n\u003C!-- dist/xrfragment.js -->\n\u003Cscript>\nvar $hx_exports = typeof exports != \"undefined\" ? exports : typeof window != \"undefined\" ? window : typeof self != \"undefined\" ? self : this;\n(function ($global) { \"use strict\";\n$hx_exports[\"xrfragment\"] = $hx_exports[\"xrfragment\"] || {};\nvar EReg = function(r,opt) {\n\tthis.r = new RegExp(r,opt.split(\"u\").join(\"\"));\n};\nEReg.__name__ = true;\nEReg.prototype = {\n\tmatch: function(s) {\n\t\tif(this.r.global) {\n\t\t\tthis.r.lastIndex = 0;\n\t\t}\n\t\tthis.r.m = this.r.exec(s);\n\t\tthis.r.s = s;\n\t\treturn this.r.m != null;\n\t}\n\t,split: function(s) {\n\t\tvar d = \"#__delim__#\";\n\t\treturn s.replace(this.r,d).split(d);\n\t}\n};\nvar HxOverrides = function() { };\nHxOverrides.__name__ = true;\nHxOverrides.cca = function(s,index) {\n\tvar x = s.charCodeAt(index);\n\tif(x != x) {\n\t\treturn undefined;\n\t}\n\treturn x;\n};\nHxOverrides.substr = function(s,pos,len) {\n\tif(len == null) {\n\t\tlen = s.length;\n\t} else if(len \u003C 0) {\n\t\tif(pos == 0) {\n\t\t\tlen = s.length + len;\n\t\t} else {\n\t\t\treturn \"\";\n\t\t}\n\t}\n\treturn s.substr(pos,len);\n};\nHxOverrides.now = function() {\n\treturn Date.now();\n};\nMath.__name__ = true;\nvar Reflect = function() { };\nReflect.__name__ = true;\nReflect.field = function(o,field) {\n\ttry {\n\t\treturn o[field];\n\t} catch( _g ) {\n\t\treturn null;\n\t}\n};\nReflect.fields = function(o) {\n\tvar a = [];\n\tif(o != null) {\n\t\tvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\t\tfor( var f in o ) {\n\t\tif(f != \"__id__\" && f != \"hx__closures__\" && hasOwnProperty.call(o,f)) {\n\t\t\ta.push(f);\n\t\t}\n\t\t}\n\t}\n\treturn a;\n};\nReflect.deleteField = function(o,field) {\n\tif(!Object.prototype.hasOwnProperty.call(o,field)) {\n\t\treturn false;\n\t}\n\tdelete(o[field]);\n\treturn true;\n};\nvar Std = function() { };\nStd.__name__ = true;\nStd.string = function(s) {\n\treturn js_Boot.__string_rec(s,\"\");\n};\nStd.parseInt = function(x) {\n\tif(x != null) {\n\t\tvar _g = 0;\n\t\tvar _g1 = x.length;\n\t\twhile(_g \u003C _g1) {\n\t\t\tvar i = _g++;\n\t\t\tvar c = x.charCodeAt(i);\n\t\t\tif(c \u003C= 8 || c >= 14 && c != 32 && c != 45) {\n\t\t\t\tvar nc = x.charCodeAt(i + 1);\n\t\t\t\tvar v = parseInt(x,nc == 120 || nc == 88 ? 16 : 10);\n\t\t\t\tif(isNaN(v)) {\n\t\t\t\t\treturn null;\n\t\t\t\t} else {\n\t\t\t\t\treturn v;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn null;\n};\nvar StringTools = function() { };\nStringTools.__name__ = true;\nStringTools.isSpace = function(s,pos) {\n\tvar c = HxOverrides.cca(s,pos);\n\tif(!(c > 8 && c \u003C 14)) {\n\t\treturn c == 32;\n\t} else {\n\t\treturn true;\n\t}\n};\nStringTools.ltrim = function(s) {\n\tvar l = s.length;\n\tvar r = 0;\n\twhile(r \u003C l && StringTools.isSpace(s,r)) ++r;\n\tif(r > 0) {\n\t\treturn HxOverrides.substr(s,r,l - r);\n\t} else {\n\t\treturn s;\n\t}\n};\nStringTools.rtrim = function(s) {\n\tvar l = s.length;\n\tvar r = 0;\n\twhile(r \u003C l && StringTools.isSpace(s,l - r - 1)) ++r;\n\tif(r > 0) {\n\t\treturn HxOverrides.substr(s,0,l - r);\n\t} else {\n\t\treturn s;\n\t}\n};\nStringTools.trim = function(s) {\n\treturn StringTools.ltrim(StringTools.rtrim(s));\n};\nStringTools.replace = function(s,sub,by) {\n\treturn s.split(sub).join(by);\n};\nvar haxe_iterators_ArrayIterator = function(array) {\n\tthis.current = 0;\n\tthis.array = array;\n};\nhaxe_iterators_ArrayIterator.__name__ = true;\nhaxe_iterators_ArrayIterator.prototype = {\n\thasNext: function() {\n\t\treturn this.current \u003C this.array.length;\n\t}\n\t,next: function() {\n\t\treturn this.array[this.current++];\n\t}\n};\nvar js_Boot = function() { };\njs_Boot.__name__ = true;\njs_Boot.__string_rec = function(o,s) {\n\tif(o == null) {\n\t\treturn \"null\";\n\t}\n\tif(s.length >= 5) {\n\t\treturn \"\u003C...>\";\n\t}\n\tvar t = typeof(o);\n\tif(t == \"function\" && (o.__name__ || o.__ename__)) {\n\t\tt = \"object\";\n\t}\n\tswitch(t) {\n\tcase \"function\":\n\t\treturn \"\u003Cfunction>\";\n\tcase \"object\":\n\t\tif(((o) instanceof Array)) {\n\t\t\tvar str = \"[\";\n\t\t\ts += \"\\t\";\n\t\t\tvar _g = 0;\n\t\t\tvar _g1 = o.length;\n\t\t\twhile(_g \u003C _g1) {\n\t\t\t\tvar i = _g++;\n\t\t\t\tstr += (i > 0 ? \",\" : \"\") + js_Boot.__string_rec(o[i],s);\n\t\t\t}\n\t\t\tstr += \"]\";\n\t\t\treturn str;\n\t\t}\n\t\tvar tostr;\n\t\ttry {\n\t\t\ttostr = o.toString;\n\t\t} catch( _g ) {\n\t\t\treturn \"???\";\n\t\t}\n\t\tif(tostr != null && tostr != Object.toString && typeof(tostr) == \"function\") {\n\t\t\tvar s2 = o.toString();\n\t\t\tif(s2 != \"[object Object]\") {\n\t\t\t\treturn s2;\n\t\t\t}\n\t\t}\n\t\tvar str = \"{\\n\";\n\t\ts += \"\\t\";\n\t\tvar hasp = o.hasOwnProperty != null;\n\t\tvar k = null;\n\t\tfor( k in o ) {\n\t\tif(hasp && !o.hasOwnProperty(k)) {\n\t\t\tcontinue;\n\t\t}\n\t\tif(k == \"prototype\" || k == \"__class__\" || k == \"__super__\" || k == \"__interfaces__\" || k == \"__properties__\") {\n\t\t\tcontinue;\n\t\t}\n\t\tif(str.length != 2) {\n\t\t\tstr += \", \\n\";\n\t\t}\n\t\tstr += s + k + \" : \" + js_Boot.__string_rec(o[k],s);\n\t\t}\n\t\ts = s.substring(1);\n\t\tstr += \"\\n\" + s + \"}\";\n\t\treturn str;\n\tcase \"string\":\n\t\treturn o;\n\tdefault:\n\t\treturn String(o);\n\t}\n};\nvar xrfragment_Parser = $hx_exports[\"xrfragment\"][\"Parser\"] = function() { };\nxrfragment_Parser.__name__ = true;\nxrfragment_Parser.parse = function(key,value,resultMap) {\n\tvar Frag_h = Object.create(null);\n\tFrag_h[\"prio\"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_INT;\n\tFrag_h[\"#\"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_PREDEFINED_VIEW;\n\tFrag_h[\"class\"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING;\n\tFrag_h[\"src\"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL;\n\tFrag_h[\"pos\"] = xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_VECTOR3 | xrfragment_XRF.T_STRING_OBJ;\n\tFrag_h[\"href\"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL | xrfragment_XRF.T_PREDEFINED_VIEW;\n\tFrag_h[\"q\"] = xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING;\n\tFrag_h[\"scale\"] = xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_INT;\n\tFrag_h[\"rot\"] = xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_VECTOR3;\n\tFrag_h[\"translate\"] = xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_VECTOR3;\n\tFrag_h[\"visible\"] = xrfragment_XRF.QUERY_OPERATOR | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_INT;\n\tFrag_h[\"env\"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING;\n\tFrag_h[\"t\"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.ROUNDROBIN | xrfragment_XRF.T_VECTOR2 | xrfragment_XRF.BROWSER_OVERRIDE;\n\tFrag_h[\"gravity\"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR3;\n\tFrag_h[\"physics\"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR3;\n\tFrag_h[\"scroll\"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING;\n\tFrag_h[\"fov\"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_INT | xrfragment_XRF.BROWSER_OVERRIDE;\n\tFrag_h[\"clip\"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_VECTOR2 | xrfragment_XRF.BROWSER_OVERRIDE;\n\tFrag_h[\"fog\"] = xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING | xrfragment_XRF.BROWSER_OVERRIDE;\n\tFrag_h[\"namespace\"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING;\n\tFrag_h[\"SPFX\"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING;\n\tFrag_h[\"unit\"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING;\n\tFrag_h[\"description\"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_STRING;\n\tFrag_h[\"src_session\"] = xrfragment_XRF.ASSET | xrfragment_XRF.T_URL | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.BROWSER_OVERRIDE | xrfragment_XRF.PROMPT;\n\tif(value.length == 0 && !Object.prototype.hasOwnProperty.call(Frag_h,key)) {\n\t\tresultMap[key] = new xrfragment_XRF(key,xrfragment_XRF.PV_EXECUTE | xrfragment_XRF.BROWSER_OVERRIDE);\n\t\treturn true;\n\t}\n\tif(key.split(\".\").length > 1 && value.split(\".\").length > 1) {\n\t\tresultMap[key] = new xrfragment_XRF(key,xrfragment_XRF.ASSET | xrfragment_XRF.PV_OVERRIDE | xrfragment_XRF.T_STRING | xrfragment_XRF.PROP_BIND);\n\t\treturn true;\n\t}\n\tif(Object.prototype.hasOwnProperty.call(Frag_h,key)) {\n\t\tvar v = new xrfragment_XRF(key,Frag_h[key]);\n\t\tif(!v.validate(value)) {\n\t\t\tconsole.log(\"src/xrfragment/Parser.hx:75:\",\"[ i ] fragment '\" + key + \"' has incompatible value (\" + value + \")\");\n\t\t\treturn false;\n\t\t}\n\t\tresultMap[key] = v;\n\t} else {\n\t\tconsole.log(\"src/xrfragment/Parser.hx:79:\",\"[ i ] fragment '\" + key + \"' does not exist or has no type typed (yet)\");\n\t\treturn false;\n\t}\n\treturn true;\n};\nvar xrfragment_Query = $hx_exports[\"xrfragment\"][\"Query\"] = function(str) {\n\tthis.isNumber = new EReg(\"^[0-9\\\\.]+$\",\"\");\n\tthis.isClass = new EReg(\"^[-]?class$\",\"\");\n\tthis.isExclude = new EReg(\"^-\",\"\");\n\tthis.isProp = new EReg(\"^.*:[>\u003C=!]?\",\"\");\n\tthis.q = { };\n\tthis.str = \"\";\n\tif(str != null) {\n\t\tthis.parse(str);\n\t}\n};\nxrfragment_Query.__name__ = true;\nxrfragment_Query.prototype = {\n\ttoObject: function() {\n\t\treturn this.q;\n\t}\n\t,expandAliases: function(token) {\n\t\tvar classAlias = new EReg(\"^(-)?\\\\.\",\"\");\n\t\tif(classAlias.match(token)) {\n\t\t\treturn StringTools.replace(token,\".\",\"class:\");\n\t\t} else {\n\t\t\treturn token;\n\t\t}\n\t}\n\t,get: function() {\n\t\treturn this.q;\n\t}\n\t,parse: function(str,recurse) {\n\t\tif(recurse == null) {\n\t\t\trecurse = false;\n\t\t}\n\t\tvar _gthis = this;\n\t\tvar token = str.split(\" \");\n\t\tvar q = { };\n\t\tvar process = function(str,prefix) {\n\t\t\tif(prefix == null) {\n\t\t\t\tprefix = \"\";\n\t\t\t}\n\t\t\tstr = StringTools.trim(str);\n\t\t\tvar k = str.split(\":\")[0];\n\t\t\tvar v = str.split(\":\")[1];\n\t\t\tvar filter = { };\n\t\t\tif(q[prefix + k]) {\n\t\t\t\tfilter = q[prefix + k];\n\t\t\t}\n\t\t\tfilter[\"rules\"] = filter[\"rules\"] != null ? filter[\"rules\"] : [];\n\t\t\tif(_gthis.isProp.match(str)) {\n\t\t\t\tvar oper = \"\";\n\t\t\t\tif(str.indexOf(\"*\") != -1) {\n\t\t\t\t\toper = \"*\";\n\t\t\t\t}\n\t\t\t\tif(str.indexOf(\">\") != -1) {\n\t\t\t\t\toper = \">\";\n\t\t\t\t}\n\t\t\t\tif(str.indexOf(\"\u003C\") != -1) {\n\t\t\t\t\toper = \"\u003C\";\n\t\t\t\t}\n\t\t\t\tif(str.indexOf(\">=\") != -1) {\n\t\t\t\t\toper = \">=\";\n\t\t\t\t}\n\t\t\t\tif(str.indexOf(\"\u003C=\") != -1) {\n\t\t\t\t\toper = \"\u003C=\";\n\t\t\t\t}\n\t\t\t\tif(_gthis.isExclude.match(k)) {\n\t\t\t\t\toper = \"!=\";\n\t\t\t\t\tk = HxOverrides.substr(k,1,null);\n\t\t\t\t} else {\n\t\t\t\t\tv = HxOverrides.substr(v,oper.length,null);\n\t\t\t\t}\n\t\t\t\tif(oper.length == 0) {\n\t\t\t\t\toper = \"=\";\n\t\t\t\t}\n\t\t\t\tif(_gthis.isClass.match(k)) {\n\t\t\t\t\tfilter[prefix + k] = oper != \"!=\";\n\t\t\t\t\tq[v] = filter;\n\t\t\t\t} else {\n\t\t\t\t\tvar rule = { };\n\t\t\t\t\tif(_gthis.isNumber.match(v)) {\n\t\t\t\t\t\trule[oper] = parseFloat(v);\n\t\t\t\t\t} else {\n\t\t\t\t\t\trule[oper] = v;\n\t\t\t\t\t}\n\t\t\t\t\tfilter[\"rules\"].push(rule);\n\t\t\t\t\tq[k] = filter;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tfilter[\"id\"] = _gthis.isExclude.match(str) ? false : true;\n\t\t\t\tvar key = _gthis.isExclude.match(str) ? HxOverrides.substr(str,1,null) : str;\n\t\t\t\tq[key] = filter;\n\t\t\t}\n\t\t};\n\t\tvar _g = 0;\n\t\tvar _g1 = token.length;\n\t\twhile(_g \u003C _g1) {\n\t\t\tvar i = _g++;\n\t\t\tprocess(this.expandAliases(token[i]));\n\t\t}\n\t\treturn this.q = q;\n\t}\n\t,test: function(obj) {\n\t\tvar qualify = false;\n\t\tvar _g = 0;\n\t\tvar _g1 = Reflect.fields(obj);\n\t\twhile(_g \u003C _g1.length) {\n\t\t\tvar k = _g1[_g];\n\t\t\t++_g;\n\t\t\tvar v = Std.string(Reflect.field(obj,k));\n\t\t\tif(this.testProperty(k,v)) {\n\t\t\t\tqualify = true;\n\t\t\t}\n\t\t}\n\t\tvar _g = 0;\n\t\tvar _g1 = Reflect.fields(obj);\n\t\twhile(_g \u003C _g1.length) {\n\t\t\tvar k = _g1[_g];\n\t\t\t++_g;\n\t\t\tvar v = Std.string(Reflect.field(obj,k));\n\t\t\tif(this.testProperty(k,v,true)) {\n\t\t\t\tqualify = false;\n\t\t\t}\n\t\t}\n\t\treturn qualify;\n\t}\n\t,testProperty: function(property,value,exclude) {\n\t\tvar conds = 0;\n\t\tvar fails = 0;\n\t\tvar qualify = 0;\n\t\tvar testprop = function(expr) {\n\t\t\tconds += 1;\n\t\t\tfails += expr ? 0 : 1;\n\t\t\treturn expr;\n\t\t};\n\t\tif(this.q[value] != null) {\n\t\t\tvar v = this.q[value];\n\t\t\tif(v[property] != null) {\n\t\t\t\treturn v[property];\n\t\t\t}\n\t\t}\n\t\tvar _g = 0;\n\t\tvar _g1 = Reflect.fields(this.q);\n\t\twhile(_g \u003C _g1.length) {\n\t\t\tvar k = _g1[_g];\n\t\t\t++_g;\n\t\t\tvar filter = Reflect.field(this.q,k);\n\t\t\tif(filter.rules == null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvar rules = filter.rules;\n\t\t\tvar _g2 = 0;\n\t\t\twhile(_g2 \u003C rules.length) {\n\t\t\t\tvar rule = rules[_g2];\n\t\t\t\t++_g2;\n\t\t\t\tif(exclude) {\n\t\t\t\t\tif(Reflect.field(rule,\"!=\") != null && testprop((value == null ? \"null\" : \"\" + value) == Std.string(Reflect.field(rule,\"!=\"))) && exclude) {\n\t\t\t\t\t\t++qualify;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif(Reflect.field(rule,\"*\") != null && testprop(parseFloat(value) != null)) {\n\t\t\t\t\t\t++qualify;\n\t\t\t\t\t}\n\t\t\t\t\tif(Reflect.field(rule,\">\") != null && testprop(parseFloat(value) > parseFloat(Reflect.field(rule,\">\")))) {\n\t\t\t\t\t\t++qualify;\n\t\t\t\t\t}\n\t\t\t\t\tif(Reflect.field(rule,\"\u003C\") != null && testprop(parseFloat(value) \u003C parseFloat(Reflect.field(rule,\"\u003C\")))) {\n\t\t\t\t\t\t++qualify;\n\t\t\t\t\t}\n\t\t\t\t\tif(Reflect.field(rule,\">=\") != null && testprop(parseFloat(value) >= parseFloat(Reflect.field(rule,\">=\")))) {\n\t\t\t\t\t\t++qualify;\n\t\t\t\t\t}\n\t\t\t\t\tif(Reflect.field(rule,\"\u003C=\") != null && testprop(parseFloat(value) \u003C= parseFloat(Reflect.field(rule,\"\u003C=\")))) {\n\t\t\t\t\t\t++qualify;\n\t\t\t\t\t}\n\t\t\t\t\tif(Reflect.field(rule,\"=\") != null && (testprop(value == Reflect.field(rule,\"=\")) || testprop(parseFloat(value) == parseFloat(Reflect.field(rule,\"=\"))))) {\n\t\t\t\t\t\t++qualify;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn qualify > 0;\n\t}\n};\nvar xrfragment_URI = $hx_exports[\"xrfragment\"][\"URI\"] = function() { };\nxrfragment_URI.__name__ = true;\nxrfragment_URI.parse = function(qs,browser_override) {\n\tvar fragment = qs.split(\"#\");\n\tvar splitArray = fragment[1].split(\"&\");\n\tvar resultMap = { };\n\tvar _g = 0;\n\tvar _g1 = splitArray.length;\n\twhile(_g \u003C _g1) {\n\t\tvar i = _g++;\n\t\tvar splitByEqual = splitArray[i].split(\"=\");\n\t\tvar regexPlus = new EReg(\"\\\\+\",\"g\");\n\t\tvar key = splitByEqual[0];\n\t\tvar value = \"\";\n\t\tif(splitByEqual.length > 1) {\n\t\t\tvar s = regexPlus.split(splitByEqual[1]).join(\" \");\n\t\t\tvalue = decodeURIComponent(s.split(\"+\").join(\" \"));\n\t\t}\n\t\tvar ok = xrfragment_Parser.parse(key,value,resultMap);\n\t}\n\tif(browser_override) {\n\t\tvar _g = 0;\n\t\tvar _g1 = Reflect.fields(resultMap);\n\t\twhile(_g \u003C _g1.length) {\n\t\t\tvar key = _g1[_g];\n\t\t\t++_g;\n\t\t\tvar xrf = resultMap[key];\n\t\t\tif(!xrf.is(xrfragment_XRF.BROWSER_OVERRIDE)) {\n\t\t\t\tReflect.deleteField(resultMap,key);\n\t\t\t}\n\t\t}\n\t}\n\treturn resultMap;\n};\nvar xrfragment_XRF = function(_fragment,_flags) {\n\tthis.fragment = _fragment;\n\tthis.flags = _flags;\n};\nxrfragment_XRF.__name__ = true;\nxrfragment_XRF.prototype = {\n\tis: function(flag) {\n\t\treturn (this.flags & flag) != 0;\n\t}\n\t,validate: function(value) {\n\t\tthis.guessType(this,value);\n\t\tif(value.split(\"|\").length > 1) {\n\t\t\tthis.args = [];\n\t\t\tvar args = value.split(\"|\");\n\t\t\tvar _g = 0;\n\t\t\tvar _g1 = args.length;\n\t\t\twhile(_g \u003C _g1) {\n\t\t\t\tvar i = _g++;\n\t\t\t\tvar x = new xrfragment_XRF(this.fragment,this.flags);\n\t\t\t\tthis.guessType(x,args[i]);\n\t\t\t\tthis.args.push(x);\n\t\t\t}\n\t\t}\n\t\tif(this.fragment == \"q\") {\n\t\t\tthis.query = new xrfragment_Query(value).get();\n\t\t}\n\t\tvar ok = true;\n\t\tif(!((this.args) instanceof Array)) {\n\t\t\tif(this.is(xrfragment_XRF.T_VECTOR3) && !(typeof(this.x) == \"number\" && typeof(this.y) == \"number\" && typeof(this.z) == \"number\")) {\n\t\t\t\tok = false;\n\t\t\t}\n\t\t\tif(this.is(xrfragment_XRF.T_VECTOR2) && !(typeof(this.x) == \"number\" && typeof(this.y) == \"number\")) {\n\t\t\t\tok = false;\n\t\t\t}\n\t\t\tvar tmp;\n\t\t\tif(this.is(xrfragment_XRF.T_INT)) {\n\t\t\t\tvar v = this.int;\n\t\t\t\ttmp = !(typeof(v) == \"number\" && ((v | 0) === v));\n\t\t\t} else {\n\t\t\t\ttmp = false;\n\t\t\t}\n\t\t\tif(tmp) {\n\t\t\t\tok = false;\n\t\t\t}\n\t\t}\n\t\treturn ok;\n\t}\n\t,guessType: function(v,str) {\n\t\tv.string = str;\n\t\tif(str.split(\",\").length > 1) {\n\t\t\tvar xyz = str.split(\",\");\n\t\t\tif(xyz.length > 0) {\n\t\t\t\tv.x = parseFloat(xyz[0]);\n\t\t\t}\n\t\t\tif(xyz.length > 1) {\n\t\t\t\tv.y = parseFloat(xyz[1]);\n\t\t\t}\n\t\t\tif(xyz.length > 2) {\n\t\t\t\tv.z = parseFloat(xyz[2]);\n\t\t\t}\n\t\t}\n\t\tif(xrfragment_XRF.isColor.match(str)) {\n\t\t\tv.color = str;\n\t\t}\n\t\tif(xrfragment_XRF.isFloat.match(str)) {\n\t\t\tv.float = parseFloat(str);\n\t\t}\n\t\tif(xrfragment_XRF.isInt.match(str)) {\n\t\t\tv.int = Std.parseInt(str);\n\t\t}\n\t}\n};\nif(typeof(performance) != \"undefined\" ? typeof(performance.now) == \"function\" : false) {\n\tHxOverrides.now = performance.now.bind(performance);\n}\nString.__name__ = true;\nArray.__name__ = true;\njs_Boot.__toStr = ({ }).toString;\nxrfragment_Parser.error = \"\";\nxrfragment_XRF.ASSET = 1;\nxrfragment_XRF.PROP_BIND = 2;\nxrfragment_XRF.QUERY_OPERATOR = 4;\nxrfragment_XRF.PROMPT = 8;\nxrfragment_XRF.ROUNDROBIN = 16;\nxrfragment_XRF.BROWSER_OVERRIDE = 32;\nxrfragment_XRF.PV_OVERRIDE = 64;\nxrfragment_XRF.PV_EXECUTE = 128;\nxrfragment_XRF.T_INT = 512;\nxrfragment_XRF.T_VECTOR2 = 2048;\nxrfragment_XRF.T_VECTOR3 = 4096;\nxrfragment_XRF.T_URL = 8192;\nxrfragment_XRF.T_PREDEFINED_VIEW = 16384;\nxrfragment_XRF.T_STRING = 32768;\nxrfragment_XRF.T_STRING_OBJ = 65536;\nxrfragment_XRF.isColor = new EReg(\"^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$\",\"\");\nxrfragment_XRF.isInt = new EReg(\"^[0-9]+$\",\"\");\nxrfragment_XRF.isFloat = new EReg(\"^[0-9]+\\\\.[0-9]+$\",\"\");\n})({});\nvar xrfragment = $hx_exports[\"xrfragment\"];\n\n\u003C/script>","tags":"$:/tags/RawMarkup","title":"$:/xrfragment/xrfragment.js","modified":"20230427155406561"}, {"created":"20230424093140723","text":"\u003C\u003Cscript>> \u003C!-- enables script-tag -->\n\n\u003Cdiv class=\"scene\">\n\t\u003Ca-scene embedded>\n\t\t\u003Ca-box position=\"-1 0.5 -3\" rotation=\"0 45 0\" color=\"#4CC3D9\">\u003C/a-box>\n\t\t\u003Ca-sphere position=\"0 1.25 -5\" radius=\"1.25\" color=\"#EF2D5E\">\u003C/a-sphere>\n\t\t\u003Ca-cylinder position=\"1 0.75 -3\" radius=\"0.5\" height=\"1.5\" color=\"#FFC65D\">\u003C/a-cylinder>\n\t\t\u003Ca-plane position=\"0 0 -4\" rotation=\"-90 0 0\" width=\"4\" height=\"4\" color=\"#7BC8A4\">\u003C/a-plane>\n\t\t\u003Ca-sky color=\"#444\">\u003C/a-sky>\n\t\u003C/a-scene>\n\u003C/div>\n\n\u003Cscript>\n(function(){\n\t\n\tlog(\"hello world\")\n let $scene = $('a-scene')\n\t\n $scene.addEventListener('loaded', () => {\n\t\t$scene.renderer.render = ( (render) => ( scene, cam ) => {\n \t\trender(scene,cam)\t\n\t\t\tif( !$scene.renderer ) return log(\"no renderer\")\n\t\t\tlet info = $scene.renderer.info.render\n\t\t\tlog(\"frame : \" + info.frame,2)\n\t\t\tlog(\"triangle: \" + info.triangles,4)\n\t\t\tlog(\"calls : \" + info.calls,3)\t\t\n\t\t})($scene.renderer.render.bind($scene.renderer) )\n })\t\n\t\n})()\n\u003C/script>","tags":"AFRAME VR THREE WebXR","title":"AFRAME template","modified":"20230427103455960","type":"text/vnd.tiddlywiki"}, -{"modified":"20230427182606509","title":"Draft of '↪ URI.Parse'"}, +{"modified":"20230427204137692","title":"Draft of 'List of fragments'"}, {"created":"20230427151153103","text":"\u003C\u003Ctoc-selective-expandable 'Examples' sort[title]>>","tags":"$:/tags/SideBar","title":"Examples","modified":"20230427152839062","list-after":"Reference"}, {"created":"20230427124155325","text":"\u003Ciframe src=\"./example/explorer.html#t=1,100\" frameborder=\"0\" style=\"width:100%; height:90vh\"/>","tags":"Examples","title":"Fragment Explorer","modified":"20230427155205004"}, {"created":"20230425160210102","text":"\u003Cshader-doodle>\n \u003Csd-node name=\"motionblur\" prevbuffer>\n \u003Csd-node name=\"rotate\">\n \u003Csd-node name=\"basic_gl\">\n \u003Cscript type=\"x-shader/x-fragment\">\n void main() {\n vec2 st = gl_FragCoord.xy / u_resolution.xy;\n vec3 color = vec3(st.x, st.y, abs(sin(u_time)));\n\n gl_FragColor = vec4(color, 1.);\n }\n \u003C/script>\n \u003C/sd-node>\n \u003Cscript type=\"x-shader/x-fragment\">\n uniform sampler2D basic_gl;\n\n const float PI = 3.1415926;\n\n void main() {\n vec2 st = gl_FragCoord.xy / u_resolution.xy;\n\n float angle = 2. * PI * (.5 + .5 * cos(u_time));\n float scale = .7 + .4 * cos(u_time);\n\n mat2 rotation = mat2(cos(angle), -sin(angle), sin(angle), cos(angle));\n vec2 p = (st - vec2(.5)) * rotation / scale + vec2(.5);\n\n gl_FragColor = p.x \u003C 0. || p.x > 1. || p.y \u003C 0. || p.y > 1.\n ? vec4(0., 0., 0., 1.)\n : texture2D(basic_gl, p);\n }\n \u003C/script>\n \u003C/sd-node>\n \u003Cscript type=\"x-shader/x-fragment\">\n uniform sampler2D rotate, u_prevbuffer;\n\n void main () {\n vec2 st = gl_FragCoord.xy / u_resolution.xy;\n gl_FragColor = vec4(mix(\n texture2D(rotate, st),\n texture2D(u_prevbuffer, st),\n .8\n ).rgb, 1.);\n }\n \u003C/script>\n \u003C/sd-node>\n \u003Cscript type=\"x-shader/x-fragment\">\n uniform sampler2D motionblur;\n\n void main() {\n vec2 st = gl_FragCoord.xy / u_resolution.xy;\n gl_FragColor = texture2D(motionblur, st);\n }\n \u003C/script>\n\u003C/shader-doodle>","tags":"GLSL","title":"GLSL template","modified":"20230425170513931","type":"text/vnd.tiddlywiki"}, -{"created":"20230427172131986","text":"> WARNING: unfinished (formatting-errors coming up) :]\n\nThese **optional** attributes can be hardcoded inside the 3D asset (glTF):\n\n### Asset-linking fragments\n\n| attribute | (example) value | info\n|-|-|-|\n| `#` | `#q=.default&t=1,100` | \u003Cb class=\"st\">asset\u003C/b>default **predefined view**. It hints the client to execute these hardcoded XR fragments before rendering. This is useful for hiding certain objects at startup, setting default fov,animationloop etc.\u003Cbr>\u003Cbr>**Global:**\u003Cbr>![](https://i.imgur.com/vs7UUut.png)\u003Cbr>\u003Cbr>**Object-specific:**\u003Cbr>![](https://i.imgur.com/NteFN4X.png)|\n| `src` | `://b.com/my.gltf`\u003Cbr>`my.gltf`\u003Cbr>or self-reference:\u003Cbr>`#`\u003Cbr>`#q=pyramid`\u003Cbr>(instancing objects) | \u003Cb class=\"st\">asset\u003C/b>Replaces current object in asset (empty or a lowpoly preview) with a lazyloaded asset (supports fallbacks, selfrefencing and queries).\u003Cbr> It is up to the client when to render the asset (based on scene vertcount, or distance to object e.g.)\u003Cbr>\u003Cbr>TODO: decide whether this should supersede src_audio & src_audio_env and also map .mp4/.jpg/.png urls to first 4 vertexes (plane) |\n| `#class` | `foo` | \u003Cb class=\"st\">asset\u003C/b>allows client to match this object for queries like `q=.foo` or `q=pyramid -.foo`|\n| `prio` | `1` (default) till `-10` | \u003Cb class=\"st\">asset\u003C/b>allow client to ignore lower-prio objects in the renderloop, to compensate frame-drop/cpu/gpu-overload scenario's |\n| `#*` | `#price=10` | \u003Cb class=\"st\">asset\u003C/b>allows client to match queries like `q=price\u003C11` |\n| `#*` | `desktop`:`fov=90&clip=0.2,1`\u003Cbr>`welcome`:`q=welcome&opacity=1`\u003Cbr>`toggle`:`desktop\\|welcome`|\u003Cb class=\"st\">asset\u003Cb class=\"rr\">roundrobin\u003C/b>\u003C/b> \u003Cb>predefined view(s)\u003C/b> will be executed when clicking a `href` destination (`://my.gltf#pos=0,0,0&desktop&welcome` e.g.) which will set the camera frustum (to `near=0.2` `far=1`) and shows the welcome-object (which had opacity 9) |\n\n### Fallback / multiprotocol links\n\n| attribute | (example) value | info\n|-|-|-|\n| (src\\|href)_(statuscode):\u003Cbr>\u003Cbr>`src_404`\u003Cbr>`href_403`\u003Cbr>`src_audio_404`\u003Cbr>`src_...` | `https://archive.org1/23.gltf`\u003Cbr>`ipfs://afe898a9f/23.gltf`\u003Cbr>`please_login`| fallback handling: redirect to fallback url or trigger \u003Cb>predefined view\u003C/b> (`please_login`:`#q=.needlogin&opacity=1`) |\n\n> This seems to be a safe solution based on discussions at WhatWG [lessons](https://github.com/whatwg/html/issues/4584) and [proposal](https://github.com/whatwg/html/issues/4584) (outcome: dont repurpose protocol-token, re-use http codes). CORS policy issues should be redirected to 404 too (so a `not_found` predefined view can be triggered e.d.)\n\n\n### External audiovisual fragments\n\n| fragment | example value | info |\n|-|-|-|\n|`src` | `://information.mp3#t=0,100` | \u003Cb class=\"st\">asset\u003C/b> audio (podcast/presentation/forest background) which loops by default. If object is positioned at 0,0,0 it will be played as nonspatial (stereo) audio (or ambisonics/dolby atmos based on filecontents). |\n|`src` | `vert.glsl\\|frag.glsl`\u003Cbr>`shader.wgsl` | \u003Cb class=\"st\">asset\u003C/b>Applies shader as material of current object.\u003Cbr>These are limited to simple standalone shaders with require the client to only send a `iTime`, `iTimeDelta` and `iResolution` uniform.\u003Cbr>\u003Cbr>|\n|`src` |`://env.jpg`\u003Cbr> | \u003Cb class=\"st\">asset\u003C/b>Lazyloads & applies the image to the current object (id `forest` e.g.). You can also hide it and use later (see `env` below e.g.), by setting the scale to 0,0,0 of this object or add `q=-myobject` to the \u003Cb>predefined view\u003C/b>.\u003Cbr>\u003Cbr>This also allows to embed multiple env-maps inside a (glTF) asset and switch them using `href` pos (`href: #pos=0,2,2&env=forest`)\u003Cbr>\u003Cbr>`unlit` means lights/environment will not affect the material (=maximum brightness) |\n| `env` | `forest\\|1\\|cubemap`\u003Cbr>\u003Cbr>format: `a\\|b\\|c`\u003Cbr>`a` = <texture\\|object\\|unlit> \u003Cbr>`b` = [intensity=1]\u003Cbr>`c` = [type=equirect]|\u003Cb class=\"st\">asset\u003C/b>when placed on the **root scene-node**, it applies the current PBR environmentMap based on the material of another node. |\n\n### HREF Navigation / portals\n\n| fragment | href value | result |\n|-|-|-|\n|`href`|`#pos=1,1,0`\u003Cbr>`#pos=1,1,0&rot=90,0,0`\u003Cbr>`#pos=pyramid`\u003Cbr>`#pos=lastvisit\\|pyramid`\u003CBr>`://somefile.gltf#pos=1,1,0`\u003Cbr> | \u003Cb class=\"st\">asset\u003C/b>`pos` and `rot` positions/rotates the user (camera) to a particular coordinate or entity (mountain e.g.)\u003Cbr>\u003Cbr>NOTE 1: a **file URI** fully replaces the current scene and assumes `pos=0,0,0&rot=0,0,0` by default\u003Cbr>\u003Cbr>NOTE 2: navigation does not happen when using queries (`q=`). Because queries will apply `pos` and `rot` to the targeted object(s) instead.\u003Cbr>\u003CBr>See [HREFS as portals](#HREF-as-portals)-illustration above for portal-rendering\u003Cbr>\u003Cbr>» solution abducted from [this](https://i.imgur.com/E3En0gJ.png) and [this](https://i.imgur.com/lpnTz3A.png) survey result|\n|`pos` |`#pos=0,0,1`\u003Cbr>`#pos=myobject` | \u003Cb class=\"st\">asset\u003Cspan class=\"dn\">URI browser\u003C/span>\u003C/b> \u003Cb class=\"st\">asset\u003Cb class=\"rr\">roundrobin\u003C/b>\u003C/b> moves the camera(rig) (the enduser) to a certain xyz vector in the scene (or to an empty object inside the asset)\u003Cbr>only object-positions (myobject) are allowed when updated by \u003Cb class=\"dn\">URI browser\u003C/b> |\n\n### Object manipulation \n\n| XR Fragments | result |\n|-|-|\n`#scale=1`\u003Cbr>`#q=car&scale=1`\u003Cbr>`#q=.cars&scale=0\\|1&opacity=0\\|1`\u003Cbr>`#q=flipboard&rot=0,0,0\\|180,0,0`\u003Cbr>`#pos=0,0,0\\|90,0,0\\|180,0,0\\|1s`| \u003Cb class=\"dn\">URI browser\u003C/b>instructs the client to set the (next) `pos`,`rot`, `opacity` or `scale` of the scene (or object(s) in case of query), each time the user interacts with the object\u003Cbr>\u003Cbr>By adding `1s` as the last value, tweening is applied (with a 1 sec duration, see animation fragments)|\n|`#src= ://cars.gltf#scale=2&pos=2,1,0&rot=120,0,0&q=mazda2`| \u003Cspan class=\"st\">asset\u003C/span>position,scale & rotate lazyloaded object(s) (only the mazda2) from `cars.gltf`\u003Cbr>\u003Cbr>See `src` for more info. |\n\n» solution was abducted from [this](https://i.imgur.com/iQ0slYQ.png) survey result\n\n\n### Query selectors\n\n» abducted from [this](https://i.imgur.com/iQ0slYQ.png) survey result\n\n> NOTE: because of security-reasons, queries should only be executed when specified inside the asset (typing a `q`-parameter in the browser url-bar should be ignored by the browser).\n\nSpace-separated multiple selectors are allowed, as well as minus (`-`) for negative selectors (which are processed after positive selectors) .\n\n| URL | result |\n|-|-|\n| `foo.com/beach.gltf#q=-sun` | \u003Cspan class=\"dn\">URI browser\u003C/span>don't show a particular light (because current scene already has lights) |\n| `foo.com/product.gltf#q=foo` | \u003Cspan class=\"dn\">URI browser\u003C/span>show **only** object from product.gltf with id `foo` |\n| `foo.com/product.gltf#q=.discount` | \u003Cspan class=\"dn\">URI browser\u003C/span>show **only** objects which have custom property `class: 'discount'` |\n| `foo.com/product.gltf#q=.discount .new` | \u003Cspan class=\"dn\">URI browser\u003C/span>show **only** objects which have `class: 'discount'` or `class: 'new'` |\n|`foo.com/paintings.gltf#q=year:2010 .discount -stock:\u003C3` | \u003Cspan class=\"dn\">URI browser\u003C/span>only show objects with `year: 2010` or `class: 'discount'` but not `stock: 1` e.g. |\n\n> Hint see the \u003Cb class=\"st\">asset\u003C/b> `#` fragment to specify a default query \n\n### XR Fragment: Animation\n\n» abducted from [this](https://i.imgur.com/4GmYPs2.png) survey result\n\n| Fragment (example) | result |\n|-|-|\n|`t=0,100` | \u003Cb class=\"st\">asset\u003Cspan class=\"dn\">URI browser\u003C/span>\u003C/b> \u003Cb class=\"st\">asset\u003Cb class=\"rr\">roundrobin\u003C/b>\u003C/b> play (all) animations from the beginning (and loop between 0-100) |\n|`href`:`#q=foo&pos=0,0,0\\|0,1,0\\|1s`\u003Cbr>`#`:`#opacity=0\\|1\\|1s` | \u003Cb class=\"st\">asset\u003Cspan class=\"dn\">URI browser\u003C/span>\u003C/b>animate position/opacity of certain queried (or this) object.\u003Cbr>\u003Cbr>format: from\\|to\\|\\[...]\\|[duration]\u003Cbr>\u003Cbr>NOTE: more then 2 values are possible in case of `href`, and will be **roundrobin'ed** upon each interaction |\n|`#`:`#gravity=0,-9.8,0`\u003Cbr>`#`:`#physics=0.2,1` | \u003Cb class=\"st\">asset\u003C/b>bare minimum to specify asset/URI browser objects so collisions can be managed by client.\u003Cbr>By default all meshes are asset, and turn URI browser when `physics` are set (\u003Cfriction>,\u003Cdensity>) which will adhere to the global `gravity` settings. |\n| `#scroll=0,5`\u003Cbr>`#scroll=0,1`\u003Cbr>`#scroll=0,1\\|xy`\u003Cbr>`#scroll=1,0\\|2s`\u003Cbr>`#scroll=1,0\\|2s\\|x`\u003Cbr>`#q=balloon&scroll=0,1`| \u003Cb>NOTE: deprecated for binds (see below)\u003C/b> \u003Cb class=\"st\">asset\u003Cspan class=\"dn\">URI browser\u003C/span>\u003C/b>Scroll to specific x,y material-offset of this (or a queried `balloon` object):\u003Cbr>\u003Cbr>`\u003Cint>,\u003Cint>` sets defaults scrollposition to x [y] (range 0..1 uvcoordinates)\u003Cbr>\u003Cbr>`xy` or `x` or `y` overrides scrollsettings by enabling interactive scrolling when controllers start interacting.\u003Cbr>\u003Cbr>Finally, `0,0\\|1s` or `1,1\\|2s` e.g. instructs the client to automatically scroll the material of this entity (with 1 or 2 second roundtrips ).\u003Cbr>\u003Cbr>ps. this might be dropped by the next-feature |\n| `#cube.position.x=1`\u003Cbr>`#cube.position.x=music.position.x`\u003Cbr>`#cube.position.x=@music.position.x` | \u003Cb class=\"st\">asset\u003Cspan class=\"dn\">URI browser\u003C/span>\u003C/b> \u003Cb class=\"st\">asset\u003Cb class=\"rr\">roundrobin\u003C/b>\u003C/b>\u003Cbr>data assigning or one-way binding (`@`).\u003Cbr>\u003Cbr>Flexible way to animate objects (cube) using animation-data (of empty object). \u003Cbr>\u003Cbr>possible properties: \u003Cbr>`position.x/y/z`\u003Cbr>`rotation.x/y/z`\u003Cbr>`material.map.offset.x/y/rotation`\u003Cbr>`material.map.r/g/b`\u003Cbr>`material.map.env.intensity`\u003Cbr>|\n\n\n\n### Device/viewport \n\n> Note: these fragments are not evaluated when defined in linked assets (loaded with `src` xrfragment e.g.)\n \n| URL | result |\n|-|-|\n| `#fov=90`\u003Cbr>`#clip=1,100`\u003Cbr> | \u003Cb class=\"st\">asset\u003Cspan class=\"dn\">URI browser\u003C/span>\u003C/b> \u003Cb class=\"se\">session\u003C/b>specify camera clipping/fov (differs for 2D/AR/VR).|\n|`foo.com/office.gltf#desktop`\u003Cbr>`foo.com/office.gltf#smartphone` e.g. | \u003Cb class=\"st\">asset\u003Cspan class=\"dn\">URI browser\u003C/span>\u003C/b>\u003Cbr>evaluate a \u003Cb class=\"st\">asset\u003C/b> fragment-alias **inside** the glTF (`#desktop: 'cam.fov=90&scale=0.6&q=-logo -sky -.sale'`)|\n|`foo.com/office.gltf#fog=5m\\|FFAACC` | specify a linear fog which lets the user see 5 meter far and set the backgroundcolor to #FFAACC |\n\n\n\n### Author / metadata\n\n| Fragment | info |\n|-|-|\n| `#namespace=XXX` | \u003Cb class=\"st\">asset\u003Cspan class=\"dn\">URI browser\u003C/span>\u003C/b> this defines the prefix for all xrfragment keys. For example if `#namespace=NL_` is defined inside the \u003Cb class=\"st\">asset\u003C/span>\u003C/b> then the xrfragments (like `description`) will be expected to with that prefix (`NL_description`).\u003Cbr>This is basically an extra preset-layer on top of **predefined views** which can facilitate ISO Alpha-2 countrycodes or when xrfragment-keys collide with already existing custom properties.\u003Cbr>\u003Cbr>NOTE: the `namespace` xrfragment is not affected by itself (`NL_namespace` is ignored e.g.) | \n| `#SPFX=GPL-3.0-or-later`|\u003Cb class=\"st\">asset\u003C/b> |\n| `#unit` | `1m`\u003Cbr>`1in`\u003Cbr>`10000mm` | \u003Cb class=\"st\">asset\u003C/b>Synchronizes reallife-size across assets, using inches- OR meter-coordinates.\u003Cbr>\u003Cbr>» abducted from [this](https://i.imgur.com/cfAk6Pt.png) survey result | \n|`#description=This is a museum in Holland showing all Van Gogh paintings` |\u003Cb class=\"st\">asset\u003C/b> allow client to provide context before visiting destination |\n \n### Multiparty\n\n| Fragment | info |\n|-|-| \n|`#src_session=matrix://matrix.org/#myroom&room.key=123` \u003Cbr>`#src_session_404=wss://irc.unrealircd.org/#myroom&room.key=123`\u003Cbr>`#src_session=://f9839849e9ef9e:987/session.json`\u003Cbr>\u003Cbr>The `_(code)` suffixes can be used as fallback mechanism (piggybacking http statuscodes, 404 meaning 'not found' e.g.)| \u003Cb class=\"se\">session\u003C/b>The purpose of `session` allows adding multiparty communication-layers on top of the current scene.\u003Cbr>\u003Cbr>By default XR fragments focus on local-first.\u003Cbr>However,>However, in theory shared experiences could be facilitated by hinting a session/room to the client.\u003Cbr>\u003Cbr>The [matrix-js-sdk](https://github.com/matrix-org/matrix-js-sdk) or [websocket capable IRC-servers](https://www.unrealircd.org/docs/WebSocket_support) can be used as a pubsub to share teleports e.g. (`\"the conference is starting in 5 mins at https://foo.gltf?#teleport=0,1,0\"`)\u003Cbr>\u003Cbr>WebRTC is out of scope here |\n\n\n\n","tags":"Reference","title":"List of fragments","modified":"20230427180533268","type":"text/markdown"}, +{"created":"20230427172131986","text":"| fragment | type | scope |\n|----------|------|-------|\n| **prio** |int|asset loading linking|\n| **#** |[predefined view](#prefined%20view)|asset loading linking|\n| **class** |string|asset loading linking|\n| **src** |[url](#url)|asset loading linking|\n| **pos** |[vector3](#vector3)|href navigation / portals / teleporting|\n| **href** |[predefined view](#prefined%20view)|href navigation / portals / teleporting|\n| **q** |string|query selector / object manipulation|\n| **scale** |int|query selector / object manipulation|\n| **rot** |[vector3](#vector3)|query selector / object manipulation|\n| **translate** |[vector3](#vector3)|query selector / object manipulation|\n| **visible** |int|query selector / object manipulation|\n| **env** |string|query selector / object manipulation|\n| **t** |[vector2](#vector2)|animation|\n| **gravity** |[vector3](#vector3)|animation|\n| **physics** |[vector3](#vector3)|animation|\n| **fov** |int|device / viewport settings|\n| **clip** |[vector2](#vector2)|device / viewport settings|\n| **fog** |string|device / viewport settings|\n| **namespace** |string|author / metadata|\n| **SPDX** |string|author / metadata|\n| **unit** |string|author / metadata|\n| **description** |string|author / metadata|\n| **session** |[url](#url)|multiparty|\n","tags":"Reference","title":"List of fragments","modified":"20230427204322544","type":"text/markdown"}, {"created":"20230427150512404","text":"\u003C\u003Ctoc-selective-expandable 'Reference' sort[title]>>","tags":"$:/tags/SideBar","title":"Reference","modified":"20230427151056587","list-before":"$:/core/ui/SideBar/Open"}, {"created":"20230426160615931","text":"\u003Cdiv class=\"scene\">\u003C/div>\n\n\u003C\u003Cscript>>\n\u003Cscript>\n $scene = document.querySelector(\".scene\")\n\tscene = new THREE.Scene();\n camera = new THREE.PerspectiveCamera( 75, $scene.offsetWidth / $scene.offsetHeight, 0.1, 1000 );\n\n\trenderer = new THREE.WebGLRenderer();\n renderer.setSize( $scene.offsetWidth, $scene.offsetHeight );\n $scene.appendChild( renderer.domElement );\n\t\n\tvar geometry = new THREE.BoxGeometry( 1, 1, 1 );\n\tvar material = new THREE.MeshBasicMaterial( { color: 0x0a84ff } );\n\tvar cube = new THREE.Mesh( geometry, material );\n\tscene.add( cube );\n\tscene.background = new THREE.Color( 0x18181c );\n\n\tcamera.position.z = 2;\n\n\tfunction animate() {\n\t\trequestAnimationFrame( animate );\n\n\t\tcube.rotation.x += 0.004;\n\t\tcube.rotation.y += 0.004;\n\n\t\trenderer.render( scene, camera );\n\t}\n\n\tanimate();\t\n\tlog(\"hello world\")\n\u003C/script>","title":"THREE template","modified":"20230427103421550","tags":"THREE WebXR"}, {"created":"20230425154949623","text":"\u003Cscript async src=\"https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js\">\u003C/script>\n\n\u003Cscript type=\"importmap\">\n{\n\t\"imports\": {\n\t\t\"three\": \"https://unpkg.com/three@0.151.3/build/three.module.js\",\n\t\t\t\"three/addons/\": \"https://unpkg.com/three@0.151.3/examples/jsm/\"\n\t}\n}\n\u003C/script>\n\n\u003Cscript type=\"module\">\nimport * as THREE from 'three';\n\nimport { BoxLineGeometry } from 'three/addons/geometries/BoxLineGeometry.js';\nimport { VRButton } from 'three/addons/webxr/VRButton.js';\nimport { XRControllerModelFactory } from 'three/addons/webxr/XRControllerModelFactory.js';\n\nlet camera, scene, raycaster, renderer;\nlet controller1, controller2;\nlet controllerGrip1, controllerGrip2;\n\nlet room, marker, floor, baseReferenceSpace;\n\nlet INTERSECTION;\nconst tempMatrix = new THREE.Matrix4();\n\ninit();\nanimate();\n\nfunction init() {\n\n\tscene = new THREE.Scene();\n\tscene.background = new THREE.Color( 0x505050 );\n\n\tcamera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.1, 10 );\n\tcamera.position.set( 0, 1, 3 );\n\n\troom = new THREE.LineSegments(\n\t\t\tnew BoxLineGeometry( 6, 6, 6, 10, 10, 10 ).translate( 0, 3, 0 ),\n\t\t\tnew THREE.LineBasicMaterial( { color: 0x808080 } )\n\t\t\t);\n\tscene.add( room );\n\n\tscene.add( new THREE.HemisphereLight( 0x606060, 0x404040 ) );\n\n\tconst light = new THREE.DirectionalLight( 0xffffff );\n\tlight.position.set( 1, 1, 1 ).normalize();\n\tscene.add( light );\n\n\tmarker = new THREE.Mesh(\n\t\t\tnew THREE.CircleGeometry( 0.25, 32 ).rotateX( - Math.PI / 2 ),\n\t\t\tnew THREE.MeshBasicMaterial( { color: 0x808080 } )\n\t\t\t);\n\tscene.add( marker );\n\n\tfloor = new THREE.Mesh(\n\t\t\tnew THREE.PlaneGeometry( 4.8, 4.8, 2, 2 ).rotateX( - Math.PI / 2 ),\n\t\t\tnew THREE.MeshBasicMaterial( { color: 0x808080, transparent: true, opacity: 0.25 } )\n\t\t\t);\n\tscene.add( floor );\n\n\traycaster = new THREE.Raycaster();\n\n\trenderer = new THREE.WebGLRenderer( { antialias: true } );\n\trenderer.setPixelRatio( window.devicePixelRatio );\n\trenderer.setSize( window.innerWidth, window.innerHeight );\n\trenderer.outputEncoding = THREE.sRGBEncoding;\n\n\trenderer.xr.addEventListener( 'sessionstart', () => baseReferenceSpace = renderer.xr.getReferenceSpace() );\n\trenderer.xr.enabled = true;\n\n\tdocument.body.appendChild( renderer.domElement );\n\tdocument.body.appendChild( VRButton.createButton( renderer ) );\n\n\t// controllers\n\n\tfunction onSelectStart() {\n\n\t\tthis.userData.isSelecting = true;\n\n\t}\n\n\tfunction onSelectEnd() {\n\n\t\tthis.userData.isSelecting = false;\n\n\t\tif ( INTERSECTION ) {\n\n\t\t\tconst offsetPosition = { x: - INTERSECTION.x, y: - INTERSECTION.y, z: - INTERSECTION.z, w: 1 };\n\t\t\tconst offsetRotation = new THREE.Quaternion();\n\t\t\tconst transform = new XRRigidTransform( offsetPosition, offsetRotation );\n\t\t\tconst teleportSpaceOffset = baseReferenceSpace.getOffsetReferenceSpace( transform );\n\n\t\t\trenderer.xr.setReferenceSpace( teleportSpaceOffset );\n\n\t\t}\n\n\t}\n\n\tcontroller1 = renderer.xr.getController( 0 );\n\tcontroller1.addEventListener( 'selectstart', onSelectStart );\n\tcontroller1.addEventListener( 'selectend', onSelectEnd );\n\tcontroller1.addEventListener( 'connected', function ( event ) {\n\n\t\t\tthis.add( buildController( event.data ) );\n\n\t\t\t} );\n\tcontroller1.addEventListener( 'disconnected', function () {\n\n\t\t\tthis.remove( this.children[ 0 ] );\n\n\t\t\t} );\n\tscene.add( controller1 );\n\n\tcontroller2 = renderer.xr.getController( 1 );\n\tcontroller2.addEventListener( 'selectstart', onSelectStart );\n\tcontroller2.addEventListener( 'selectend', onSelectEnd );\n\tcontroller2.addEventListener( 'connected', function ( event ) {\n\n\t\t\tthis.add( buildController( event.data ) );\n\n\t\t\t} );\n\tcontroller2.addEventListener( 'disconnected', function () {\n\n\t\t\tthis.remove( this.children[ 0 ] );\n\n\t\t\t} );\n\tscene.add( controller2 );\n\n\t// The XRControllerModelFactory will automatically fetch controller models\n\t// that match what the user is holding as closely as possible. The models\n\t// should be attached to the object returned from getControllerGrip in\n\t// order to match the orientation of the held device.\n\n\tconst controllerModelFactory = new XRControllerModelFactory();\n\n\tcontrollerGrip1 = renderer.xr.getControllerGrip( 0 );\n\tcontrollerGrip1.add( controllerModelFactory.createControllerModel( controllerGrip1 ) );\n\tscene.add( controllerGrip1 );\n\n\tcontrollerGrip2 = renderer.xr.getControllerGrip( 1 );\n\tcontrollerGrip2.add( controllerModelFactory.createControllerModel( controllerGrip2 ) );\n\tscene.add( controllerGrip2 );\n\n\t//\n\n\twindow.addEventListener( 'resize', onWindowResize, false );\n\n}\n\nfunction buildController( data ) {\n\n\tlet geometry, material;\n\n\tswitch ( data.targetRayMode ) {\n\n\t\tcase 'tracked-pointer':\n\n\t\t\tgeometry = new THREE.BufferGeometry();\n\t\t\tgeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( [ 0, 0, 0, 0, 0, - 1 ], 3 ) );\n\t\t\tgeometry.setAttribute( 'color', new THREE.Float32BufferAttribute( [ 0.5, 0.5, 0.5, 0, 0, 0 ], 3 ) );\n\n\t\t\tmaterial = new THREE.LineBasicMaterial( { vertexColors: true, blending: THREE.AdditiveBlending } );\n\n\t\t\treturn new THREE.Line( geometry, material );\n\n\t\tcase 'gaze':\n\n\t\t\tgeometry = new THREE.RingGeometry( 0.02, 0.04, 32 ).translate( 0, 0, - 1 );\n\t\t\tmaterial = new THREE.MeshBasicMaterial( { opacity: 0.5, transparent: true } );\n\t\t\treturn new THREE.Mesh( geometry, material );\n\n\t}\n\n}\n\nfunction onWindowResize() {\n\n\tcamera.aspect = window.innerWidth / window.innerHeight;\n\tcamera.updateProjectionMatrix();\n\n\trenderer.setSize( window.innerWidth, window.innerHeight );\n\n}\n\n//\n\nfunction animate() {\n\trenderer.setAnimationLoop( render );\n}\n\nfunction render() {\n\n\tINTERSECTION = undefined;\n\n\tif ( controller1.userData.isSelecting === true ) {\n\t\ttempMatrix.identity().extractRotation( controller1.matrixWorld );\n\t\traycaster.ray.origin.setFromMatrixPosition( controller1.matrixWorld );\n\t\traycaster.ray.direction.set( 0, 0, - 1 ).applyMatrix4( tempMatrix );\n\t\tconst intersects = raycaster.intersectObjects( [ floor ] );\n\t\tif ( intersects.length > 0 ) {\n\t\t\tINTERSECTION = intersects[ 0 ].point;\n\t\t}\n\t} else if ( controller2.userData.isSelecting === true ) {\n\t\ttempMatrix.identity().extractRotation( controller2.matrixWorld );\n\t\traycaster.ray.origin.setFromMatrixPosition( controller2.matrixWorld );\n\t\traycaster.ray.direction.set( 0, 0, - 1 ).applyMatrix4( tempMatrix );\n\t\tconst intersects = raycaster.intersectObjects( [ floor ] );\n\t\tif ( intersects.length > 0 ) {\n\t\t\tINTERSECTION = intersects[ 0 ].point;\n\t\t}\n\t}\n\n\tif ( INTERSECTION ) marker.position.copy( INTERSECTION );\n\tmarker.visible = INTERSECTION !== undefined;\n\trenderer.render( scene, camera );\n\n}\n\n\u003C/script>\n","tags":"THREE VR WebXR","title":"THREE template #online","modified":"20230427103521658","type":"text/html"}, diff --git a/src/xrfragment/Parser.hx b/src/xrfragment/Parser.hx index 9e07556..0f9a965 100644 --- a/src/xrfragment/Parser.hx +++ b/src/xrfragment/Parser.hx @@ -23,7 +23,7 @@ class Parser { Frag.set("pos", XRF.PV_OVERRIDE | XRF.ROUNDROBIN | XRF.T_VECTOR3 | XRF.T_STRING_OBJ ); Frag.set("href", XRF.ASSET | XRF.T_URL | XRF.T_PREDEFINED_VIEW ); - // category: query selector | object manipulation + // category: query selector / object manipulation Frag.set("q", XRF.PV_OVERRIDE | XRF.T_STRING ); Frag.set("scale", XRF.QUERY_OPERATOR | XRF.PV_OVERRIDE | XRF.ROUNDROBIN | XRF.T_INT ); Frag.set("rot", XRF.QUERY_OPERATOR | XRF.PV_OVERRIDE | XRF.ROUNDROBIN | XRF.T_VECTOR3 ); @@ -35,7 +35,6 @@ class Parser { Frag.set("t", XRF.ASSET | XRF.PV_OVERRIDE | XRF.ROUNDROBIN | XRF.T_VECTOR2 | XRF.BROWSER_OVERRIDE ); 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 ); // category: device / viewport settings Frag.set("fov", XRF.ASSET | XRF.PV_OVERRIDE | XRF.T_INT | XRF.BROWSER_OVERRIDE ); @@ -44,12 +43,12 @@ class Parser { // category: author / metadata Frag.set("namespace", XRF.ASSET | XRF.T_STRING ); - Frag.set("SPFX", XRF.ASSET | XRF.T_STRING ); + Frag.set("SPDX", XRF.ASSET | XRF.T_STRING ); Frag.set("unit", XRF.ASSET | XRF.T_STRING ); Frag.set("description", XRF.ASSET | XRF.T_STRING ); // category: multiparty - Frag.set("src_session", XRF.ASSET | XRF.T_URL | XRF.PV_OVERRIDE | XRF.BROWSER_OVERRIDE | XRF.PROMPT ); + Frag.set("session", XRF.ASSET | XRF.T_URL | XRF.PV_OVERRIDE | XRF.BROWSER_OVERRIDE | XRF.PROMPT ); /** * # XR Fragments parser