diff --git a/public/deep_space/materials/background.json b/public/deep_space/materials/background.json new file mode 100644 index 0000000..dcbf4ce --- /dev/null +++ b/public/deep_space/materials/background.json @@ -0,0 +1,23 @@ +{ + "passes" : + [ + { + "blending" : "translucent", + "constantshadervalues" : + { + "Alpha" : 1, + "Amount" : 1, + "Bright" : 1, + "Power" : 1, + "Speed" : 0.0099999997764825821, + "Speed0" : 0.0099999997764825821, + "Speed1" : 0.019999999552965164, + "Speed2" : 0.039999999105930328 + }, + "depthtest" : "disabled", + "depthwrite" : "disabled", + "shader" : "flowimage", + "textures" : [ "flowmask", "galaxy_layer_2", "galaxy_layer_1", "galaxy_layer_0" ] + } + ] +} \ No newline at end of file diff --git a/public/deep_space/materials/flowmask.png b/public/deep_space/materials/flowmask.png new file mode 100644 index 0000000..bf26606 Binary files /dev/null and b/public/deep_space/materials/flowmask.png differ diff --git a/public/deep_space/materials/flowmask.tex b/public/deep_space/materials/flowmask.tex new file mode 100644 index 0000000..78f40d2 Binary files /dev/null and b/public/deep_space/materials/flowmask.tex differ diff --git a/public/deep_space/materials/flowmask.tex-json b/public/deep_space/materials/flowmask.tex-json new file mode 100644 index 0000000..0f3f474 --- /dev/null +++ b/public/deep_space/materials/flowmask.tex-json @@ -0,0 +1,5 @@ +{ + "nonpoweroftwo" : true, + "format": "rgba8888", + "clampuvs": true +} \ No newline at end of file diff --git a/public/deep_space/materials/galaxy_2_base.json b/public/deep_space/materials/galaxy_2_base.json new file mode 100644 index 0000000..f9aeb1f --- /dev/null +++ b/public/deep_space/materials/galaxy_2_base.json @@ -0,0 +1,11 @@ +{ + "passes" : + [ + { + "depthtest" : "disabled", + "depthwrite" : "disabled", + "shader" : "genericimage", + "textures" : [ "galaxy_2_base" ] + } + ] +} \ No newline at end of file diff --git a/public/deep_space/materials/galaxy_2_base.png b/public/deep_space/materials/galaxy_2_base.png new file mode 100644 index 0000000..0e6f58a Binary files /dev/null and b/public/deep_space/materials/galaxy_2_base.png differ diff --git a/public/deep_space/materials/galaxy_2_base.tex b/public/deep_space/materials/galaxy_2_base.tex new file mode 100644 index 0000000..6c0dd01 Binary files /dev/null and b/public/deep_space/materials/galaxy_2_base.tex differ diff --git a/public/deep_space/materials/galaxy_2_base.tex-json b/public/deep_space/materials/galaxy_2_base.tex-json new file mode 100644 index 0000000..9668ba9 --- /dev/null +++ b/public/deep_space/materials/galaxy_2_base.tex-json @@ -0,0 +1,3 @@ +{ + "nonpoweroftwo" : true +} \ No newline at end of file diff --git a/public/deep_space/materials/galaxy_layer_0.png b/public/deep_space/materials/galaxy_layer_0.png new file mode 100644 index 0000000..8acd917 Binary files /dev/null and b/public/deep_space/materials/galaxy_layer_0.png differ diff --git a/public/deep_space/materials/galaxy_layer_0.tex b/public/deep_space/materials/galaxy_layer_0.tex new file mode 100644 index 0000000..0103ab7 Binary files /dev/null and b/public/deep_space/materials/galaxy_layer_0.tex differ diff --git a/public/deep_space/materials/galaxy_layer_0.tex-json b/public/deep_space/materials/galaxy_layer_0.tex-json new file mode 100644 index 0000000..790175d --- /dev/null +++ b/public/deep_space/materials/galaxy_layer_0.tex-json @@ -0,0 +1,5 @@ +{ + "nonpoweroftwo" : true, + "clampuvs": true, + "nomip": true +} \ No newline at end of file diff --git a/public/deep_space/materials/galaxy_layer_1.png b/public/deep_space/materials/galaxy_layer_1.png new file mode 100644 index 0000000..bac1b1c Binary files /dev/null and b/public/deep_space/materials/galaxy_layer_1.png differ diff --git a/public/deep_space/materials/galaxy_layer_1.tex b/public/deep_space/materials/galaxy_layer_1.tex new file mode 100644 index 0000000..9977945 Binary files /dev/null and b/public/deep_space/materials/galaxy_layer_1.tex differ diff --git a/public/deep_space/materials/galaxy_layer_1.tex-json b/public/deep_space/materials/galaxy_layer_1.tex-json new file mode 100644 index 0000000..790175d --- /dev/null +++ b/public/deep_space/materials/galaxy_layer_1.tex-json @@ -0,0 +1,5 @@ +{ + "nonpoweroftwo" : true, + "clampuvs": true, + "nomip": true +} \ No newline at end of file diff --git a/public/deep_space/materials/galaxy_layer_2.png b/public/deep_space/materials/galaxy_layer_2.png new file mode 100644 index 0000000..75013a1 Binary files /dev/null and b/public/deep_space/materials/galaxy_layer_2.png differ diff --git a/public/deep_space/materials/galaxy_layer_2.tex b/public/deep_space/materials/galaxy_layer_2.tex new file mode 100644 index 0000000..498da66 Binary files /dev/null and b/public/deep_space/materials/galaxy_layer_2.tex differ diff --git a/public/deep_space/materials/galaxy_layer_2.tex-json b/public/deep_space/materials/galaxy_layer_2.tex-json new file mode 100644 index 0000000..790175d --- /dev/null +++ b/public/deep_space/materials/galaxy_layer_2.tex-json @@ -0,0 +1,5 @@ +{ + "nonpoweroftwo" : true, + "clampuvs": true, + "nomip": true +} \ No newline at end of file diff --git a/public/deep_space/models/background.json b/public/deep_space/models/background.json new file mode 100644 index 0000000..2bee7ac --- /dev/null +++ b/public/deep_space/models/background.json @@ -0,0 +1,5 @@ +{ + "height" : 1080, + "material" : "materials/background.json", + "width" : 1920 +} \ No newline at end of file diff --git a/public/deep_space/models/galaxy_2_base.json b/public/deep_space/models/galaxy_2_base.json new file mode 100644 index 0000000..aa3ad60 --- /dev/null +++ b/public/deep_space/models/galaxy_2_base.json @@ -0,0 +1,5 @@ +{ + "height" : 1080, + "material" : "materials/galaxy_2_base.json", + "width" : 1920 +} \ No newline at end of file diff --git a/public/deep_space/preview.jpg b/public/deep_space/preview.jpg new file mode 100644 index 0000000..7c6a16d Binary files /dev/null and b/public/deep_space/preview.jpg differ diff --git a/public/deep_space/project.json b/public/deep_space/project.json new file mode 100644 index 0000000..bea04ff --- /dev/null +++ b/public/deep_space/project.json @@ -0,0 +1,40 @@ +{ + "file" : "scene.json", + "authorsteamid": "76561197975619619", + "official" : true, + "general" : + { + "properties" : + { + "schemecolor" : + { + "value" : "0.608 0.36 0.412", + "text" : "ui_browse_properties_scheme_color", + "type" : "color" + } + } + }, + "preview" : "preview.jpg", + "templateoptions" : + [ + { + "configured" : true, + "description" : "Replace the background image. It should contain water of some sort that you want to animate. The recommended image size is 1920 x 1080 pixels.", + "destination" : "materials/background.png", + "last" : "C:/Users/Kristjan/Desktop/spacewp/galaxy_2_bg.png", + "name" : "Background image", + "type" : "replacetexture" + }, + { + "configured" : true, + "description" : "Replace the water flow mask. The image can generally be a lot smaller than your background image, like 480 x 270. The red channel defines horizontal water flow, the green channel controls vertical water flow. Make sure to check out the tutorial!", + "destination" : "materials/flowmask.png", + "last" : "C:/Users/Kristjan/Desktop/spacewp/galaxy_2_flow.png", + "name" : "Water flow mask", + "type" : "replacetexture" + } + ], + "title" : "Deep Space", + "type" : "scene", + "visibility" : "public" +} \ No newline at end of file diff --git a/public/deep_space/scene.json b/public/deep_space/scene.json new file mode 100644 index 0000000..40f0b7a --- /dev/null +++ b/public/deep_space/scene.json @@ -0,0 +1,40 @@ +{ + "camera" : + { + "center" : "0.000 0.000 -1.000", + "eye" : "0.000 0.000 0.000", + "up" : "0.000 1.000 0.000" + }, + "general" : + { + "ambientcolor" : "0.300 0.300 0.300", + "bloom" : false, + "norecompile" : true, + "clearcolor" : "0.700 0.700 0.700", + "orthogonalprojection" : + { + "height" : 1080, + "width" : 1920 + }, + "skylightcolor" : "0.300 0.300 0.300" + }, + "objects" : + [ + { + "angles" : "0.000 0.000 0.000", + "id" : 1, + "image" : "models/galaxy_2_base.json", + "name" : "galaxy_2_base", + "origin" : "960.000 540.000 0.000", + "scale" : "1.100 1.100 1.000" + }, + { + "angles" : "0.000 0.000 -0.064", + "id" : 2, + "image" : "models/background.json", + "name" : "Background", + "origin" : "928.116 552.332 0.000", + "scale" : "1.117 1.117 1.000" + } + ] +} \ No newline at end of file diff --git a/public/deep_space/shaders/blobsSM40/2d8d53395a18425269b8c4fd621994c97f308576.dxs b/public/deep_space/shaders/blobsSM40/2d8d53395a18425269b8c4fd621994c97f308576.dxs new file mode 100644 index 0000000..ef6a74a Binary files /dev/null and b/public/deep_space/shaders/blobsSM40/2d8d53395a18425269b8c4fd621994c97f308576.dxs differ diff --git a/public/deep_space/shaders/blobsSM40/3cb603471882a938e2e25c54f01645be54947d48.dxs b/public/deep_space/shaders/blobsSM40/3cb603471882a938e2e25c54f01645be54947d48.dxs new file mode 100644 index 0000000..f6cf245 Binary files /dev/null and b/public/deep_space/shaders/blobsSM40/3cb603471882a938e2e25c54f01645be54947d48.dxs differ diff --git a/public/deep_space/shaders/blobsSM40/422a30b4df4ec463964cf888c05b24432113f90e.dxs b/public/deep_space/shaders/blobsSM40/422a30b4df4ec463964cf888c05b24432113f90e.dxs new file mode 100644 index 0000000..c0f0726 Binary files /dev/null and b/public/deep_space/shaders/blobsSM40/422a30b4df4ec463964cf888c05b24432113f90e.dxs differ diff --git a/public/deep_space/shaders/blobsSM40/45396e652b869332beb9d50c9ff53a265df5637e.dxs b/public/deep_space/shaders/blobsSM40/45396e652b869332beb9d50c9ff53a265df5637e.dxs new file mode 100644 index 0000000..1a9c170 Binary files /dev/null and b/public/deep_space/shaders/blobsSM40/45396e652b869332beb9d50c9ff53a265df5637e.dxs differ diff --git a/public/deep_space/shaders/blobsSM40/b636d0285516caccbecf0e72368150170f9048ed.dxs b/public/deep_space/shaders/blobsSM40/b636d0285516caccbecf0e72368150170f9048ed.dxs new file mode 100644 index 0000000..e983ec6 Binary files /dev/null and b/public/deep_space/shaders/blobsSM40/b636d0285516caccbecf0e72368150170f9048ed.dxs differ diff --git a/public/deep_space/shaders/blobsSM40/e1eab682cab487da1131036ac4197cd11b2d9331.dxs b/public/deep_space/shaders/blobsSM40/e1eab682cab487da1131036ac4197cd11b2d9331.dxs new file mode 100644 index 0000000..f0ba4f5 Binary files /dev/null and b/public/deep_space/shaders/blobsSM40/e1eab682cab487da1131036ac4197cd11b2d9331.dxs differ diff --git a/public/deep_space/shaders/flowimage.frag b/public/deep_space/shaders/flowimage.frag new file mode 100644 index 0000000..8c7f0f5 --- /dev/null +++ b/public/deep_space/shaders/flowimage.frag @@ -0,0 +1,49 @@ + +#include "common_fragment.h" + +uniform sampler2D g_Texture0; +uniform sampler2D g_Texture1; +uniform sampler2D g_Texture2; +uniform sampler2D g_Texture3; +uniform sampler2D g_Texture4; +uniform sampler2D g_Texture5; +uniform sampler2D g_Texture6; + +uniform float g_Brightness; // {"material":"Bright","default":1,"range":[0,2]} +uniform float g_Time; +uniform float g_FlowAmp; // {"material":"Amount","default":1,"range":[0.01, 1]} + +varying vec2 v_TexCoord; +varying vec4 v_Cycles01; +varying vec4 v_Cycles23; +//varying vec4 v_Cycles45; +varying vec4 v_Blend0123; +//varying vec2 v_Blend45; + +void blendLayers(vec4 samp, inout vec4 albedo) { + albedo.rgb = mix(albedo.rgb, samp.rgb, samp.a); + albedo.a = max(albedo.a, samp.a); +} + +void main() { + vec3 flowColors = texSample2D(g_Texture0, v_TexCoord.xy).rgb; + vec2 flowMask = (flowColors.rg - vec2(0.5, 0.5)) * 2.0; + + vec4 flowUVOffset0 = vec4(flowMask * g_FlowAmp * 0.1 * v_Cycles01.x, flowMask * g_FlowAmp * 0.1 * v_Cycles01.y); + vec4 flowUVOffset1 = vec4(flowMask * g_FlowAmp * 0.1 * v_Cycles01.z, flowMask * g_FlowAmp * 0.1 * v_Cycles01.w); + vec4 flowUVOffset2 = vec4(flowMask * g_FlowAmp * 0.1 * v_Cycles23.x, flowMask * g_FlowAmp * 0.1 * v_Cycles23.y); + + vec4 albedo = mix(texSample2D(g_Texture1, v_TexCoord.xy + flowUVOffset0.xy), + texSample2D(g_Texture1, v_TexCoord.xy + flowUVOffset0.zw), + v_Blend0123.x); + + blendLayers(mix(texSample2D(g_Texture2, v_TexCoord.xy + flowUVOffset1.xy), + texSample2D(g_Texture2, v_TexCoord.xy + flowUVOffset1.zw), + v_Blend0123.y), albedo); + blendLayers(mix(texSample2D(g_Texture3, v_TexCoord.xy + flowUVOffset2.xy), + texSample2D(g_Texture3, v_TexCoord.xy + flowUVOffset2.zw), + v_Blend0123.z), albedo); + + albedo.rgb *= g_Brightness; + gl_FragColor = albedo; +} diff --git a/public/deep_space/shaders/flowimage.vert b/public/deep_space/shaders/flowimage.vert new file mode 100644 index 0000000..128c809 --- /dev/null +++ b/public/deep_space/shaders/flowimage.vert @@ -0,0 +1,46 @@ + +#include "common_vertex.h" + +uniform mat4 g_ModelViewProjectionMatrix; +uniform float g_Time; + +uniform float g_FlowSpeed0; // {"material":"Speed0","default":0.01,"range":[0.01, 1]} +uniform float g_FlowSpeed1; // {"material":"Speed1","default":0.01,"range":[0.01, 1]} +uniform float g_FlowSpeed2; // {"material":"Speed2","default":0.01,"range":[0.01, 1]} +uniform float g_FlowSpeed3; // {"material":"Speed3","default":0.01,"range":[0.01, 1]} +//uniform float g_FlowSpeed4; // {"material":"Speed4","default":0.01,"range":[0.01, 1]} +//uniform float g_FlowSpeed5; // {"material":"Speed5","default":0.01,"range":[0.01, 1]} + +attribute vec3 a_Position; +attribute vec2 a_TexCoord; + +varying vec2 v_TexCoord; +varying vec4 v_Cycles01; +varying vec4 v_Cycles23; +//varying vec4 v_Cycles45; +varying vec4 v_Blend0123; +//varying vec2 v_Blend45; + +void main() { + gl_Position = mul(vec4(a_Position, 1.0), g_ModelViewProjectionMatrix); + v_TexCoord = a_TexCoord; + + + v_Cycles01.xy = vec2(frac(g_Time * g_FlowSpeed0), frac(g_Time * g_FlowSpeed0 + 0.5)); + v_Blend0123.x = 2 * abs(v_Cycles01.x - 0.5); + + v_Cycles01.zw = vec2(frac(g_Time * g_FlowSpeed1), frac(g_Time * g_FlowSpeed1 + 0.5)); + v_Blend0123.y = 2 * abs(v_Cycles01.z - 0.5); + + v_Cycles23.xy = vec2(frac(g_Time * g_FlowSpeed2 + 0.3333), frac(g_Time * g_FlowSpeed2 + 0.5 + 0.3333)); + v_Blend0123.z = 2 * abs(v_Cycles23.x - 0.5); + + v_Cycles23.zw = vec2(frac(g_Time * g_FlowSpeed3 + 0.71), frac(g_Time * g_FlowSpeed3 + 0.5 + 0.71)); + v_Blend0123.w = 2 * abs(v_Cycles23.z - 0.5); + + //v_Cycles45.xy = vec2(frac(g_Time * g_FlowSpeed4), frac(g_Time * g_FlowSpeed4 + 0.5)); + //v_Blend45.x = 2 * abs(v_Cycles45.x - 0.5); + // + //v_Cycles45.zw = vec2(frac(g_Time * g_FlowSpeed5), frac(g_Time * g_FlowSpeed5 + 0.5)); + //v_Blend45.y = 2 * abs(v_Cycles45.z - 0.5); +} diff --git a/public/deep_space/shaders/swayimage.frag b/public/deep_space/shaders/swayimage.frag new file mode 100644 index 0000000..3eefd11 --- /dev/null +++ b/public/deep_space/shaders/swayimage.frag @@ -0,0 +1,37 @@ + +#include "common_fragment.h" + +uniform sampler2D g_Texture0; +uniform sampler2D g_Texture1; + +uniform float g_Brightness; // {"material":"Bright","default":1,"range":[0,2]} +uniform float g_Time; +uniform float g_SwaySpeed; // {"material":"Speed","default":0.1,"range":[0.01, 1]} +uniform float g_SwayAmp; // {"material":"Amount","default":0.2,"range":[0.01, 1]} + +varying vec2 v_TexCoord; + +void main() { + //vec2 flowMask = (texSample2D(g_Texture1, v_TexCoord.xy).rg - vec2(0.506, 0.482)) * 2.0; + + //vec2 cycles = vec2(frac(g_Time * g_FlowSpeed), frac(g_Time * g_FlowSpeed + 0.5)); + //float blend = 2 * abs(cycles.x - 0.5); + + vec3 swayMask = texSample2D(g_Texture1, v_TexCoord.xy).rgb; + + float phase = v_TexCoord.x * 10 + swayMask.b; //(v_TexCoord.x * 10 + v_TexCoord.y + swayMask.b) * 10; + vec4 baseTime = vec4(g_Time * 30.0, g_Time * 27.0, g_Time * 21.0, g_Time * 7.0) * g_SwaySpeed + phase; + vec4 sines = sin(baseTime); + + float amt = dot(sines, vec4(1, 1, 1, 1)); + + vec2 swayOffset = swayMask.xy * amt * g_SwayAmp * 0.01; + + vec4 albedo = texSample2D(g_Texture0, v_TexCoord.xy + swayOffset); + + albedo.rgb *= g_Brightness; + //albedo.a *= g_UserAlpha; + //albedo.rgb = pow(albedo.rgb, g_Power); + + gl_FragColor = albedo; +} diff --git a/public/deep_space/shaders/swayimage.vert b/public/deep_space/shaders/swayimage.vert new file mode 100644 index 0000000..4324a17 --- /dev/null +++ b/public/deep_space/shaders/swayimage.vert @@ -0,0 +1,15 @@ + +#include "common_vertex.h" + +uniform mat4 g_ModelViewProjectionMatrix; +uniform float g_Time; + +attribute vec3 a_Position; +attribute vec2 a_TexCoord; + +varying vec2 v_TexCoord; + +void main() { + gl_Position = mul(vec4(a_Position, 1.0), g_ModelViewProjectionMatrix); + v_TexCoord = a_TexCoord; +} diff --git a/public/themes/dusty sphere/License.txt b/public/themes/dusty sphere/License.txt new file mode 100644 index 0000000..6efccd2 --- /dev/null +++ b/public/themes/dusty sphere/License.txt @@ -0,0 +1,10 @@ +Copyright (c) 2020 by Tamino Martinius (https://codepen.io/Zaku/pen/vFDdw) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*********************************************************************************************************** + diff --git a/public/themes/dusty sphere/LivelyInfo.json b/public/themes/dusty sphere/LivelyInfo.json new file mode 100644 index 0000000..04f7ae0 --- /dev/null +++ b/public/themes/dusty sphere/LivelyInfo.json @@ -0,0 +1,14 @@ +{ + "AppVersion": "0.8.0.0", + "Title": "Sphere [Customisable]", + "Thumbnail": "lively_t.jpg", + "Preview": "lively_p.gif", + "Desc": "Dusty particle sphere.", + "Author": "Tamino Martinius", + "License": null, + "Contact": "https://codepen.io/Zaku/pen/vFDdw", + "Type": 1, + "FileName": "index.html", + "Arguments": null, + "IsAbsolutePath": false +} \ No newline at end of file diff --git a/public/themes/dusty sphere/LivelyProperties.backup.json b/public/themes/dusty sphere/LivelyProperties.backup.json new file mode 100644 index 0000000..63a3f21 --- /dev/null +++ b/public/themes/dusty sphere/LivelyProperties.backup.json @@ -0,0 +1,47 @@ +{ + "iPerspective": { + "max": 1000, + "min": 150, + "tick": 851, + "text": "View", + "type": "slider", + "value": 346 + }, + "iFramesToRotate": { + "max": 2000, + "min": 50, + "tick": 1951, + "text": "Rotation", + "type": "slider", + "value": 2000 + }, + "fGrowDuration": { + "max": 200, + "min": 10, + "tick": 191, + "text": "Grow Duration", + "type": "slider", + "value": 41 + }, + "fWaitDuration": { + "max": 200, + "min": 10, + "tick": 191, + "text": "Wait Duration", + "type": "slider", + "value": 110 + }, + "iNewParticlePerFrame": { + "max": 5, + "min": 1, + "tick": 5, + "text": "Particle/Frame", + "type": "slider", + "value": 2 + }, + "aColor": { + "text": "Color", + "type": "color", + "value": "#FFFF00" + } +} \ No newline at end of file diff --git a/public/themes/dusty sphere/LivelyProperties.json b/public/themes/dusty sphere/LivelyProperties.json new file mode 100644 index 0000000..3f5e16c --- /dev/null +++ b/public/themes/dusty sphere/LivelyProperties.json @@ -0,0 +1,49 @@ +{ + "iPerspective": { + "max": 1000, + "min": 150, + "tick": 851, + "text": "View", + "type": "slider", + "value": 346 + }, + /* + "iFramesToRotate": { + "max": 2000, + "min": 50, + "tick": 1951, + "text": "Rotation", + "type": "slider", + "value": 2000 + }, + */ + "fGrowDuration": { + "max": 200, + "min": 10, + "tick": 191, + "text": "Grow Duration", + "type": "slider", + "value": 41 + }, + "fWaitDuration": { + "max": 200, + "min": 10, + "tick": 191, + "text": "Wait Duration", + "type": "slider", + "value": 110 + }, + "iNewParticlePerFrame": { + "max": 5, + "min": 1, + "tick": 5, + "text": "Particle/Frame", + "type": "slider", + "value": 2 + }, + "aColor": { + "text": "Color", + "type": "color", + "value": "#FFFF00" + } +} \ No newline at end of file diff --git a/public/themes/dusty sphere/css/style.css b/public/themes/dusty sphere/css/style.css new file mode 100644 index 0000000..365aa59 --- /dev/null +++ b/public/themes/dusty sphere/css/style.css @@ -0,0 +1,9 @@ +body, html { + background-color: #000; + color: #fff; + width: 100%; + height: 100%; + margin: 0; + padding: 0; + overflow: hidden; +} \ No newline at end of file diff --git a/public/themes/dusty sphere/index.html b/public/themes/dusty sphere/index.html new file mode 100644 index 0000000..82999d8 --- /dev/null +++ b/public/themes/dusty sphere/index.html @@ -0,0 +1,18 @@ + + + + + CodePen - Dusty Particle Sphere + + + + + + + + + + + + + diff --git a/public/themes/dusty sphere/js/Stats.js b/public/themes/dusty sphere/js/Stats.js new file mode 100644 index 0000000..d64f44a --- /dev/null +++ b/public/themes/dusty sphere/js/Stats.js @@ -0,0 +1,143 @@ +/** + * @author mrdoob / http://mrdoob.com/ + */ + +var Stats = function () { + + var startTime = Date.now(), prevTime = startTime; + var ms = 0, msMin = Infinity, msMax = 0; + var fps = 0, fpsMin = Infinity, fpsMax = 0; + var frames = 0, mode = 0; + + var container = document.createElement( 'div' ); + container.id = 'stats'; + container.addEventListener( 'mousedown', function ( event ) { event.preventDefault(); setMode( ++ mode % 2 ) }, false ); + container.style.cssText = 'width:80px;opacity:0.9;cursor:pointer'; + + var fpsDiv = document.createElement( 'div' ); + fpsDiv.id = 'fps'; + fpsDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#002'; + container.appendChild( fpsDiv ); + + var fpsText = document.createElement( 'div' ); + fpsText.id = 'fpsText'; + fpsText.style.cssText = 'color:#0ff;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px'; + fpsText.innerHTML = 'FPS'; + fpsDiv.appendChild( fpsText ); + + var fpsGraph = document.createElement( 'div' ); + fpsGraph.id = 'fpsGraph'; + fpsGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0ff'; + fpsDiv.appendChild( fpsGraph ); + + while ( fpsGraph.children.length < 74 ) { + + var bar = document.createElement( 'span' ); + bar.style.cssText = 'width:1px;height:30px;float:left;background-color:#113'; + fpsGraph.appendChild( bar ); + + } + + var msDiv = document.createElement( 'div' ); + msDiv.id = 'ms'; + msDiv.style.cssText = 'padding:0 0 3px 3px;text-align:left;background-color:#020;display:none'; + container.appendChild( msDiv ); + + var msText = document.createElement( 'div' ); + msText.id = 'msText'; + msText.style.cssText = 'color:#0f0;font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px'; + msText.innerHTML = 'MS'; + msDiv.appendChild( msText ); + + var msGraph = document.createElement( 'div' ); + msGraph.id = 'msGraph'; + msGraph.style.cssText = 'position:relative;width:74px;height:30px;background-color:#0f0'; + msDiv.appendChild( msGraph ); + + while ( msGraph.children.length < 74 ) { + + var bar = document.createElement( 'span' ); + bar.style.cssText = 'width:1px;height:30px;float:left;background-color:#131'; + msGraph.appendChild( bar ); + + } + + var setMode = function ( value ) { + + mode = value; + + switch ( mode ) { + + case 0: + fpsDiv.style.display = 'block'; + msDiv.style.display = 'none'; + break; + case 1: + fpsDiv.style.display = 'none'; + msDiv.style.display = 'block'; + break; + } + + } + + var updateGraph = function ( dom, value ) { + + var child = dom.appendChild( dom.firstChild ); + child.style.height = value + 'px'; + + } + + return { + + REVISION: 11, + + domElement: container, + + setMode: setMode, + + begin: function () { + + startTime = Date.now(); + + }, + + end: function () { + + var time = Date.now(); + + ms = time - startTime; + msMin = Math.min( msMin, ms ); + msMax = Math.max( msMax, ms ); + + msText.textContent = ms + ' MS (' + msMin + '-' + msMax + ')'; + updateGraph( msGraph, Math.min( 30, 30 - ( ms / 200 ) * 30 ) ); + + frames ++; + + if ( time > prevTime + 1000 ) { + + fps = Math.round( ( frames * 1000 ) / ( time - prevTime ) ); + fpsMin = Math.min( fpsMin, fps ); + fpsMax = Math.max( fpsMax, fps ); + + fpsText.textContent = fps + ' FPS (' + fpsMin + '-' + fpsMax + ')'; + updateGraph( fpsGraph, Math.min( 30, 30 - ( fps / 100 ) * 30 ) ); + + prevTime = time; + frames = 0; + + } + + return time; + + }, + + update: function () { + + startTime = this.end(); + + } + + } + +}; diff --git a/public/themes/dusty sphere/js/dat.gui.min.js b/public/themes/dusty sphere/js/dat.gui.min.js new file mode 100644 index 0000000..17e4a3c --- /dev/null +++ b/public/themes/dusty sphere/js/dat.gui.min.js @@ -0,0 +1,94 @@ +/** + * dat-gui JavaScript Controller Library + * http://code.google.com/p/dat-gui + * + * Copyright 2011 Data Arts Team, Google Creative Lab + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ +var dat=dat||{};dat.gui=dat.gui||{};dat.utils=dat.utils||{};dat.controllers=dat.controllers||{};dat.dom=dat.dom||{};dat.color=dat.color||{};dat.utils.css=function(){return{load:function(e,a){var a=a||document,c=a.createElement("link");c.type="text/css";c.rel="stylesheet";c.href=e;a.getElementsByTagName("head")[0].appendChild(c)},inject:function(e,a){var a=a||document,c=document.createElement("style");c.type="text/css";c.innerHTML=e;a.getElementsByTagName("head")[0].appendChild(c)}}}(); +dat.utils.common=function(){var e=Array.prototype.forEach,a=Array.prototype.slice;return{BREAK:{},extend:function(c){this.each(a.call(arguments,1),function(a){for(var f in a)this.isUndefined(a[f])||(c[f]=a[f])},this);return c},defaults:function(c){this.each(a.call(arguments,1),function(a){for(var f in a)this.isUndefined(c[f])&&(c[f]=a[f])},this);return c},compose:function(){var c=a.call(arguments);return function(){for(var d=a.call(arguments),f=c.length-1;f>=0;f--)d=[c[f].apply(this,d)];return d[0]}}, +each:function(a,d,f){if(e&&a.forEach===e)a.forEach(d,f);else if(a.length===a.length+0)for(var b=0,n=a.length;b-1?d.length-d.indexOf(".")-1:0};c.superclass=e;a.extend(c.prototype,e.prototype,{setValue:function(a){if(this.__min!==void 0&&athis.__max)a=this.__max;this.__step!==void 0&&a%this.__step!=0&&(a=Math.round(a/this.__step)*this.__step);return c.superclass.prototype.setValue.call(this,a)},min:function(a){this.__min=a;return this},max:function(a){this.__max=a;return this},step:function(a){this.__step=a;return this}});return c}(dat.controllers.Controller,dat.utils.common); +dat.controllers.NumberControllerBox=function(e,a,c){var d=function(f,b,e){function h(){var a=parseFloat(l.__input.value);c.isNaN(a)||l.setValue(a)}function j(a){var b=o-a.clientY;l.setValue(l.getValue()+b*l.__impliedStep);o=a.clientY}function m(){a.unbind(window,"mousemove",j);a.unbind(window,"mouseup",m)}this.__truncationSuspended=false;d.superclass.call(this,f,b,e);var l=this,o;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"change",h); +a.bind(this.__input,"blur",function(){h();l.__onFinishChange&&l.__onFinishChange.call(l,l.getValue())});a.bind(this.__input,"mousedown",function(b){a.bind(window,"mousemove",j);a.bind(window,"mouseup",m);o=b.clientY});a.bind(this.__input,"keydown",function(a){if(a.keyCode===13)l.__truncationSuspended=true,this.blur(),l.__truncationSuspended=false});this.updateDisplay();this.domElement.appendChild(this.__input)};d.superclass=e;c.extend(d.prototype,e.prototype,{updateDisplay:function(){var a=this.__input, +b;if(this.__truncationSuspended)b=this.getValue();else{b=this.getValue();var c=Math.pow(10,this.__precision);b=Math.round(b*c)/c}a.value=b;return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.NumberController,dat.dom.dom,dat.utils.common); +dat.controllers.NumberControllerSlider=function(e,a,c,d,f){var b=function(d,c,f,e,l){function o(b){b.preventDefault();var d=a.getOffset(g.__background),c=a.getWidth(g.__background);g.setValue(g.__min+(g.__max-g.__min)*((b.clientX-d.left)/(d.left+c-d.left)));return false}function y(){a.unbind(window,"mousemove",o);a.unbind(window,"mouseup",y);g.__onFinishChange&&g.__onFinishChange.call(g,g.getValue())}b.superclass.call(this,d,c,{min:f,max:e,step:l});var g=this;this.__background=document.createElement("div"); +this.__foreground=document.createElement("div");a.bind(this.__background,"mousedown",function(b){a.bind(window,"mousemove",o);a.bind(window,"mouseup",y);o(b)});a.addClass(this.__background,"slider");a.addClass(this.__foreground,"slider-fg");this.updateDisplay();this.__background.appendChild(this.__foreground);this.domElement.appendChild(this.__background)};b.superclass=e;b.useDefaultStyles=function(){c.inject(f)};d.extend(b.prototype,e.prototype,{updateDisplay:function(){this.__foreground.style.width= +(this.getValue()-this.__min)/(this.__max-this.__min)*100+"%";return b.superclass.prototype.updateDisplay.call(this)}});return b}(dat.controllers.NumberController,dat.dom.dom,dat.utils.css,dat.utils.common,".slider {\n box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);\n height: 1em;\n border-radius: 1em;\n background-color: #eee;\n padding: 0 0.5em;\n overflow: hidden;\n}\n\n.slider-fg {\n padding: 1px 0 2px 0;\n background-color: #aaa;\n height: 1em;\n margin-left: -0.5em;\n padding-right: 0.5em;\n border-radius: 1em 0 0 1em;\n}\n\n.slider-fg:after {\n display: inline-block;\n border-radius: 1em;\n background-color: #fff;\n border: 1px solid #aaa;\n content: '';\n float: right;\n margin-right: -1em;\n margin-top: -1px;\n height: 0.9em;\n width: 0.9em;\n}"); +dat.controllers.FunctionController=function(e,a,c){var d=function(c,b,e){d.superclass.call(this,c,b);var h=this;this.__button=document.createElement("div");this.__button.innerHTML=e===void 0?"Fire":e;a.bind(this.__button,"click",function(a){a.preventDefault();h.fire();return false});a.addClass(this.__button,"button");this.domElement.appendChild(this.__button)};d.superclass=e;c.extend(d.prototype,e.prototype,{fire:function(){this.__onChange&&this.__onChange.call(this);this.__onFinishChange&&this.__onFinishChange.call(this, +this.getValue());this.getValue().call(this.object)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common); +dat.controllers.BooleanController=function(e,a,c){var d=function(c,b){d.superclass.call(this,c,b);var e=this;this.__prev=this.getValue();this.__checkbox=document.createElement("input");this.__checkbox.setAttribute("type","checkbox");a.bind(this.__checkbox,"change",function(){e.setValue(!e.__prev)},false);this.domElement.appendChild(this.__checkbox);this.updateDisplay()};d.superclass=e;c.extend(d.prototype,e.prototype,{setValue:function(a){a=d.superclass.prototype.setValue.call(this,a);this.__onFinishChange&& +this.__onFinishChange.call(this,this.getValue());this.__prev=this.getValue();return a},updateDisplay:function(){this.getValue()===true?(this.__checkbox.setAttribute("checked","checked"),this.__checkbox.checked=true):this.__checkbox.checked=false;return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common); +dat.color.toString=function(e){return function(a){if(a.a==1||e.isUndefined(a.a)){for(a=a.hex.toString(16);a.length<6;)a="0"+a;return"#"+a}else return"rgba("+Math.round(a.r)+","+Math.round(a.g)+","+Math.round(a.b)+","+a.a+")"}}(dat.utils.common); +dat.color.interpret=function(e,a){var c,d,f=[{litmus:a.isString,conversions:{THREE_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i);return a===null?false:{space:"HEX",hex:parseInt("0x"+a[1].toString()+a[1].toString()+a[2].toString()+a[2].toString()+a[3].toString()+a[3].toString())}},write:e},SIX_CHAR_HEX:{read:function(a){a=a.match(/^#([A-F0-9]{6})$/i);return a===null?false:{space:"HEX",hex:parseInt("0x"+a[1].toString())}},write:e},CSS_RGB:{read:function(a){a=a.match(/^rgb\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/); +return a===null?false:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3])}},write:e},CSS_RGBA:{read:function(a){a=a.match(/^rgba\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\,\s*(.+)\s*\)/);return a===null?false:{space:"RGB",r:parseFloat(a[1]),g:parseFloat(a[2]),b:parseFloat(a[3]),a:parseFloat(a[4])}},write:e}}},{litmus:a.isNumber,conversions:{HEX:{read:function(a){return{space:"HEX",hex:a,conversionName:"HEX"}},write:function(a){return a.hex}}}},{litmus:a.isArray,conversions:{RGB_ARRAY:{read:function(a){return a.length!= +3?false:{space:"RGB",r:a[0],g:a[1],b:a[2]}},write:function(a){return[a.r,a.g,a.b]}},RGBA_ARRAY:{read:function(a){return a.length!=4?false:{space:"RGB",r:a[0],g:a[1],b:a[2],a:a[3]}},write:function(a){return[a.r,a.g,a.b,a.a]}}}},{litmus:a.isObject,conversions:{RGBA_OBJ:{read:function(b){return a.isNumber(b.r)&&a.isNumber(b.g)&&a.isNumber(b.b)&&a.isNumber(b.a)?{space:"RGB",r:b.r,g:b.g,b:b.b,a:b.a}:false},write:function(a){return{r:a.r,g:a.g,b:a.b,a:a.a}}},RGB_OBJ:{read:function(b){return a.isNumber(b.r)&& +a.isNumber(b.g)&&a.isNumber(b.b)?{space:"RGB",r:b.r,g:b.g,b:b.b}:false},write:function(a){return{r:a.r,g:a.g,b:a.b}}},HSVA_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)&&a.isNumber(b.a)?{space:"HSV",h:b.h,s:b.s,v:b.v,a:b.a}:false},write:function(a){return{h:a.h,s:a.s,v:a.v,a:a.a}}},HSV_OBJ:{read:function(b){return a.isNumber(b.h)&&a.isNumber(b.s)&&a.isNumber(b.v)?{space:"HSV",h:b.h,s:b.s,v:b.v}:false},write:function(a){return{h:a.h,s:a.s,v:a.v}}}}}];return function(){d= +false;var b=arguments.length>1?a.toArray(arguments):arguments[0];a.each(f,function(e){if(e.litmus(b))return a.each(e.conversions,function(e,f){c=e.read(b);if(d===false&&c!==false)return d=c,c.conversionName=f,c.conversion=e,a.BREAK}),a.BREAK});return d}}(dat.color.toString,dat.utils.common); +dat.GUI=dat.gui.GUI=function(e,a,c,d,f,b,n,h,j,m,l,o,y,g,i){function q(a,b,r,c){if(b[r]===void 0)throw Error("Object "+b+' has no property "'+r+'"');c.color?b=new l(b,r):(b=[b,r].concat(c.factoryArgs),b=d.apply(a,b));if(c.before instanceof f)c.before=c.before.__li;t(a,b);g.addClass(b.domElement,"c");r=document.createElement("span");g.addClass(r,"property-name");r.innerHTML=b.property;var e=document.createElement("div");e.appendChild(r);e.appendChild(b.domElement);c=s(a,e,c.before);g.addClass(c,k.CLASS_CONTROLLER_ROW); +g.addClass(c,typeof b.getValue());p(a,c,b);a.__controllers.push(b);return b}function s(a,b,d){var c=document.createElement("li");b&&c.appendChild(b);d?a.__ul.insertBefore(c,params.before):a.__ul.appendChild(c);a.onResize();return c}function p(a,d,c){c.__li=d;c.__gui=a;i.extend(c,{options:function(b){if(arguments.length>1)return c.remove(),q(a,c.object,c.property,{before:c.__li.nextElementSibling,factoryArgs:[i.toArray(arguments)]});if(i.isArray(b)||i.isObject(b))return c.remove(),q(a,c.object,c.property, +{before:c.__li.nextElementSibling,factoryArgs:[b]})},name:function(a){c.__li.firstElementChild.firstElementChild.innerHTML=a;return c},listen:function(){c.__gui.listen(c);return c},remove:function(){c.__gui.remove(c);return c}});if(c instanceof j){var e=new h(c.object,c.property,{min:c.__min,max:c.__max,step:c.__step});i.each(["updateDisplay","onChange","onFinishChange"],function(a){var b=c[a],H=e[a];c[a]=e[a]=function(){var a=Array.prototype.slice.call(arguments);b.apply(c,a);return H.apply(e,a)}}); +g.addClass(d,"has-slider");c.domElement.insertBefore(e.domElement,c.domElement.firstElementChild)}else if(c instanceof h){var f=function(b){return i.isNumber(c.__min)&&i.isNumber(c.__max)?(c.remove(),q(a,c.object,c.property,{before:c.__li.nextElementSibling,factoryArgs:[c.__min,c.__max,c.__step]})):b};c.min=i.compose(f,c.min);c.max=i.compose(f,c.max)}else if(c instanceof b)g.bind(d,"click",function(){g.fakeEvent(c.__checkbox,"click")}),g.bind(c.__checkbox,"click",function(a){a.stopPropagation()}); +else if(c instanceof n)g.bind(d,"click",function(){g.fakeEvent(c.__button,"click")}),g.bind(d,"mouseover",function(){g.addClass(c.__button,"hover")}),g.bind(d,"mouseout",function(){g.removeClass(c.__button,"hover")});else if(c instanceof l)g.addClass(d,"color"),c.updateDisplay=i.compose(function(a){d.style.borderLeftColor=c.__color.toString();return a},c.updateDisplay),c.updateDisplay();c.setValue=i.compose(function(b){a.getRoot().__preset_select&&c.isModified()&&B(a.getRoot(),true);return b},c.setValue)} +function t(a,b){var c=a.getRoot(),d=c.__rememberedObjects.indexOf(b.object);if(d!=-1){var e=c.__rememberedObjectIndecesToControllers[d];e===void 0&&(e={},c.__rememberedObjectIndecesToControllers[d]=e);e[b.property]=b;if(c.load&&c.load.remembered){c=c.load.remembered;if(c[a.preset])c=c[a.preset];else if(c[w])c=c[w];else return;if(c[d]&&c[d][b.property]!==void 0)d=c[d][b.property],b.initialValue=d,b.setValue(d)}}}function I(a){var b=a.__save_row=document.createElement("li");g.addClass(a.domElement, +"has-save");a.__ul.insertBefore(b,a.__ul.firstChild);g.addClass(b,"save-row");var c=document.createElement("span");c.innerHTML=" ";g.addClass(c,"button gears");var d=document.createElement("span");d.innerHTML="Save";g.addClass(d,"button");g.addClass(d,"save");var e=document.createElement("span");e.innerHTML="New";g.addClass(e,"button");g.addClass(e,"save-as");var f=document.createElement("span");f.innerHTML="Revert";g.addClass(f,"button");g.addClass(f,"revert");var m=a.__preset_select=document.createElement("select"); +a.load&&a.load.remembered?i.each(a.load.remembered,function(b,c){C(a,c,c==a.preset)}):C(a,w,false);g.bind(m,"change",function(){for(var b=0;b0){a.preset=this.preset;if(!a.remembered)a.remembered={};a.remembered[this.preset]=z(this)}a.folders={};i.each(this.__folders,function(b, +c){a.folders[c]=b.getSaveObject()});return a},save:function(){if(!this.load.remembered)this.load.remembered={};this.load.remembered[this.preset]=z(this);B(this,false)},saveAs:function(a){if(!this.load.remembered)this.load.remembered={},this.load.remembered[w]=z(this,true);this.load.remembered[a]=z(this);this.preset=a;C(this,a,true)},revert:function(a){i.each(this.__controllers,function(b){this.getRoot().load.remembered?t(a||this.getRoot(),b):b.setValue(b.initialValue)},this);i.each(this.__folders, +function(a){a.revert(a)});a||B(this.getRoot(),false)},listen:function(a){var b=this.__listening.length==0;this.__listening.push(a);b&&E(this.__listening)}});return k}(dat.utils.css,'
\n\n Here\'s the new load parameter for your GUI\'s constructor:\n\n \n\n
\n\n Automatically save\n values to localStorage on exit.\n\n
The values saved to localStorage will\n override those passed to dat.GUI\'s constructor. This makes it\n easier to work incrementally, but localStorage is fragile,\n and your friends may not see the same values you do.\n \n
\n \n
\n\n
', +".dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.dg.ac{position:fixed;top:0;left:0;right:0;height:0;z-index:0}.dg:not(.ac) .main{overflow:hidden}.dg.main{-webkit-transition:opacity 0.1s linear;-o-transition:opacity 0.1s linear;-moz-transition:opacity 0.1s linear;transition:opacity 0.1s linear}.dg.main.taller-than-window{overflow-y:auto}.dg.main.taller-than-window .close-button{opacity:1;margin-top:-1px;border-top:1px solid #2c2c2c}.dg.main ul.closed .close-button{opacity:1 !important}.dg.main:hover .close-button,.dg.main .close-button.drag{opacity:1}.dg.main .close-button{-webkit-transition:opacity 0.1s linear;-o-transition:opacity 0.1s linear;-moz-transition:opacity 0.1s linear;transition:opacity 0.1s linear;border:0;position:absolute;line-height:19px;height:20px;cursor:pointer;text-align:center;background-color:#000}.dg.main .close-button:hover{background-color:#111}.dg.a{float:right;margin-right:15px;overflow-x:hidden}.dg.a.has-save ul{margin-top:27px}.dg.a.has-save ul.closed{margin-top:0}.dg.a .save-row{position:fixed;top:0;z-index:1002}.dg li{-webkit-transition:height 0.1s ease-out;-o-transition:height 0.1s ease-out;-moz-transition:height 0.1s ease-out;transition:height 0.1s ease-out}.dg li:not(.folder){cursor:auto;height:27px;line-height:27px;overflow:hidden;padding:0 4px 0 5px}.dg li.folder{padding:0;border-left:4px solid rgba(0,0,0,0)}.dg li.title{cursor:pointer;margin-left:-4px}.dg .closed li:not(.title),.dg .closed ul li,.dg .closed ul li > *{height:0;overflow:hidden;border:0}.dg .cr{clear:both;padding-left:3px;height:27px}.dg .property-name{cursor:default;float:left;clear:left;width:40%;overflow:hidden;text-overflow:ellipsis}.dg .c{float:left;width:60%}.dg .c input[type=text]{border:0;margin-top:4px;padding:3px;width:100%;float:right}.dg .has-slider input[type=text]{width:30%;margin-left:0}.dg .slider{float:left;width:66%;margin-left:-5px;margin-right:0;height:19px;margin-top:4px}.dg .slider-fg{height:100%}.dg .c input[type=checkbox]{margin-top:9px}.dg .c select{margin-top:5px}.dg .cr.function,.dg .cr.function .property-name,.dg .cr.function *,.dg .cr.boolean,.dg .cr.boolean *{cursor:pointer}.dg .selector{display:none;position:absolute;margin-left:-9px;margin-top:23px;z-index:10}.dg .c:hover .selector,.dg .selector.drag{display:block}.dg li.save-row{padding:0}.dg li.save-row .button{display:inline-block;padding:0px 6px}.dg.dialogue{background-color:#222;width:460px;padding:15px;font-size:13px;line-height:15px}#dg-new-constructor{padding:10px;color:#222;font-family:Monaco, monospace;font-size:10px;border:0;resize:none;box-shadow:inset 1px 1px 1px #888;word-wrap:break-word;margin:12px 0;display:block;width:440px;overflow-y:scroll;height:100px;position:relative}#dg-local-explain{display:none;font-size:11px;line-height:17px;border-radius:3px;background-color:#333;padding:8px;margin-top:10px}#dg-local-explain code{font-size:10px}#dat-gui-save-locally{display:none}.dg{color:#eee;font:11px 'Lucida Grande', sans-serif;text-shadow:0 -1px 0 #111}.dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.dg.main::-webkit-scrollbar-corner{height:0;display:none}.dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.dg li:not(.folder){background:#1a1a1a;border-bottom:1px solid #2c2c2c}.dg li.save-row{line-height:25px;background:#dad5cb;border:0}.dg li.save-row select{margin-left:5px;width:108px}.dg li.save-row .button{margin-left:5px;margin-top:1px;border-radius:2px;font-size:9px;line-height:7px;padding:4px 4px 5px 4px;background:#c5bdad;color:#fff;text-shadow:0 1px 0 #b0a58f;box-shadow:0 -1px 0 #b0a58f;cursor:pointer}.dg li.save-row .button.gears{background:#c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;height:7px;width:8px}.dg li.save-row .button:hover{background-color:#bab19e;box-shadow:0 -1px 0 #b0a58f}.dg li.folder{border-bottom:0}.dg li.title{padding-left:16px;background:#000 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;cursor:pointer;border-bottom:1px solid rgba(255,255,255,0.2)}.dg .closed li.title{background-image:url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==)}.dg .cr.boolean{border-left:3px solid #806787}.dg .cr.function{border-left:3px solid #e61d5f}.dg .cr.number{border-left:3px solid #2fa1d6}.dg .cr.number input[type=text]{color:#2fa1d6}.dg .cr.string{border-left:3px solid #1ed36f}.dg .cr.string input[type=text]{color:#1ed36f}.dg .cr.function:hover,.dg .cr.boolean:hover{background:#111}.dg .c input[type=text]{background:#303030;outline:none}.dg .c input[type=text]:hover{background:#3c3c3c}.dg .c input[type=text]:focus{background:#494949;color:#fff}.dg .c .slider{background:#303030;cursor:ew-resize}.dg .c .slider-fg{background:#2fa1d6}.dg .c .slider:hover{background:#3c3c3c}.dg .c .slider:hover .slider-fg{background:#44abda}\n", +dat.controllers.factory=function(e,a,c,d,f,b,n){return function(h,j,m,l){var o=h[j];if(n.isArray(m)||n.isObject(m))return new e(h,j,m);if(n.isNumber(o))return n.isNumber(m)&&n.isNumber(l)?new c(h,j,m,l):new a(h,j,{min:m,max:l});if(n.isString(o))return new d(h,j);if(n.isFunction(o))return new f(h,j,"");if(n.isBoolean(o))return new b(h,j)}}(dat.controllers.OptionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.StringController=function(e,a,c){var d= +function(c,b){function e(){h.setValue(h.__input.value)}d.superclass.call(this,c,b);var h=this;this.__input=document.createElement("input");this.__input.setAttribute("type","text");a.bind(this.__input,"keyup",e);a.bind(this.__input,"change",e);a.bind(this.__input,"blur",function(){h.__onFinishChange&&h.__onFinishChange.call(h,h.getValue())});a.bind(this.__input,"keydown",function(a){a.keyCode===13&&this.blur()});this.updateDisplay();this.domElement.appendChild(this.__input)};d.superclass=e;c.extend(d.prototype, +e.prototype,{updateDisplay:function(){if(!a.isActive(this.__input))this.__input.value=this.getValue();return d.superclass.prototype.updateDisplay.call(this)}});return d}(dat.controllers.Controller,dat.dom.dom,dat.utils.common),dat.controllers.FunctionController,dat.controllers.BooleanController,dat.utils.common),dat.controllers.Controller,dat.controllers.BooleanController,dat.controllers.FunctionController,dat.controllers.NumberControllerBox,dat.controllers.NumberControllerSlider,dat.controllers.OptionController, +dat.controllers.ColorController=function(e,a,c,d,f){function b(a,b,c,d){a.style.background="";f.each(j,function(e){a.style.cssText+="background: "+e+"linear-gradient("+b+", "+c+" 0%, "+d+" 100%); "})}function n(a){a.style.background="";a.style.cssText+="background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);";a.style.cssText+="background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"; +a.style.cssText+="background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";a.style.cssText+="background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"}var h=function(e,l){function o(b){q(b);a.bind(window,"mousemove",q);a.bind(window, +"mouseup",j)}function j(){a.unbind(window,"mousemove",q);a.unbind(window,"mouseup",j)}function g(){var a=d(this.value);a!==false?(p.__color.__state=a,p.setValue(p.__color.toOriginal())):this.value=p.__color.toString()}function i(){a.unbind(window,"mousemove",s);a.unbind(window,"mouseup",i)}function q(b){b.preventDefault();var c=a.getWidth(p.__saturation_field),d=a.getOffset(p.__saturation_field),e=(b.clientX-d.left+document.body.scrollLeft)/c,b=1-(b.clientY-d.top+document.body.scrollTop)/c;b>1?b= +1:b<0&&(b=0);e>1?e=1:e<0&&(e=0);p.__color.v=b;p.__color.s=e;p.setValue(p.__color.toOriginal());return false}function s(b){b.preventDefault();var c=a.getHeight(p.__hue_field),d=a.getOffset(p.__hue_field),b=1-(b.clientY-d.top+document.body.scrollTop)/c;b>1?b=1:b<0&&(b=0);p.__color.h=b*360;p.setValue(p.__color.toOriginal());return false}h.superclass.call(this,e,l);this.__color=new c(this.getValue());this.__temp=new c(0);var p=this;this.domElement=document.createElement("div");a.makeSelectable(this.domElement, +false);this.__selector=document.createElement("div");this.__selector.className="selector";this.__saturation_field=document.createElement("div");this.__saturation_field.className="saturation-field";this.__field_knob=document.createElement("div");this.__field_knob.className="field-knob";this.__field_knob_border="2px solid ";this.__hue_knob=document.createElement("div");this.__hue_knob.className="hue-knob";this.__hue_field=document.createElement("div");this.__hue_field.className="hue-field";this.__input= +document.createElement("input");this.__input.type="text";this.__input_textShadow="0 1px 1px ";a.bind(this.__input,"keydown",function(a){a.keyCode===13&&g.call(this)});a.bind(this.__input,"blur",g);a.bind(this.__selector,"mousedown",function(){a.addClass(this,"drag").bind(window,"mouseup",function(){a.removeClass(p.__selector,"drag")})});var t=document.createElement("div");f.extend(this.__selector.style,{width:"122px",height:"102px",padding:"3px",backgroundColor:"#222",boxShadow:"0px 1px 3px rgba(0,0,0,0.3)"}); +f.extend(this.__field_knob.style,{position:"absolute",width:"12px",height:"12px",border:this.__field_knob_border+(this.__color.v<0.5?"#fff":"#000"),boxShadow:"0px 1px 3px rgba(0,0,0,0.5)",borderRadius:"12px",zIndex:1});f.extend(this.__hue_knob.style,{position:"absolute",width:"15px",height:"2px",borderRight:"4px solid #fff",zIndex:1});f.extend(this.__saturation_field.style,{width:"100px",height:"100px",border:"1px solid #555",marginRight:"3px",display:"inline-block",cursor:"pointer"});f.extend(t.style, +{width:"100%",height:"100%",background:"none"});b(t,"top","rgba(0,0,0,0)","#000");f.extend(this.__hue_field.style,{width:"15px",height:"100px",display:"inline-block",border:"1px solid #555",cursor:"ns-resize"});n(this.__hue_field);f.extend(this.__input.style,{outline:"none",textAlign:"center",color:"#fff",border:0,fontWeight:"bold",textShadow:this.__input_textShadow+"rgba(0,0,0,0.7)"});a.bind(this.__saturation_field,"mousedown",o);a.bind(this.__field_knob,"mousedown",o);a.bind(this.__hue_field,"mousedown", +function(b){s(b);a.bind(window,"mousemove",s);a.bind(window,"mouseup",i)});this.__saturation_field.appendChild(t);this.__selector.appendChild(this.__field_knob);this.__selector.appendChild(this.__saturation_field);this.__selector.appendChild(this.__hue_field);this.__hue_field.appendChild(this.__hue_knob);this.domElement.appendChild(this.__input);this.domElement.appendChild(this.__selector);this.updateDisplay()};h.superclass=e;f.extend(h.prototype,e.prototype,{updateDisplay:function(){var a=d(this.getValue()); +if(a!==false){var e=false;f.each(c.COMPONENTS,function(b){if(!f.isUndefined(a[b])&&!f.isUndefined(this.__color.__state[b])&&a[b]!==this.__color.__state[b])return e=true,{}},this);e&&f.extend(this.__color.__state,a)}f.extend(this.__temp.__state,this.__color.__state);this.__temp.a=1;var h=this.__color.v<0.5||this.__color.s>0.5?255:0,j=255-h;f.extend(this.__field_knob.style,{marginLeft:100*this.__color.s-7+"px",marginTop:100*(1-this.__color.v)-7+"px",backgroundColor:this.__temp.toString(),border:this.__field_knob_border+ +"rgb("+h+","+h+","+h+")"});this.__hue_knob.style.marginTop=(1-this.__color.h/360)*100+"px";this.__temp.s=1;this.__temp.v=1;b(this.__saturation_field,"left","#fff",this.__temp.toString());f.extend(this.__input.style,{backgroundColor:this.__input.value=this.__color.toString(),color:"rgb("+h+","+h+","+h+")",textShadow:this.__input_textShadow+"rgba("+j+","+j+","+j+",.7)"})}});var j=["-moz-","-o-","-webkit-","-ms-",""];return h}(dat.controllers.Controller,dat.dom.dom,dat.color.Color=function(e,a,c,d){function f(a, +b,c){Object.defineProperty(a,b,{get:function(){if(this.__state.space==="RGB")return this.__state[b];n(this,b,c);return this.__state[b]},set:function(a){if(this.__state.space!=="RGB")n(this,b,c),this.__state.space="RGB";this.__state[b]=a}})}function b(a,b){Object.defineProperty(a,b,{get:function(){if(this.__state.space==="HSV")return this.__state[b];h(this);return this.__state[b]},set:function(a){if(this.__state.space!=="HSV")h(this),this.__state.space="HSV";this.__state[b]=a}})}function n(b,c,e){if(b.__state.space=== +"HEX")b.__state[c]=a.component_from_hex(b.__state.hex,e);else if(b.__state.space==="HSV")d.extend(b.__state,a.hsv_to_rgb(b.__state.h,b.__state.s,b.__state.v));else throw"Corrupted color state";}function h(b){var c=a.rgb_to_hsv(b.r,b.g,b.b);d.extend(b.__state,{s:c.s,v:c.v});if(d.isNaN(c.h)){if(d.isUndefined(b.__state.h))b.__state.h=0}else b.__state.h=c.h}var j=function(){this.__state=e.apply(this,arguments);if(this.__state===false)throw"Failed to interpret color arguments";this.__state.a=this.__state.a|| +1};j.COMPONENTS="r,g,b,h,s,v,hex,a".split(",");d.extend(j.prototype,{toString:function(){return c(this)},toOriginal:function(){return this.__state.conversion.write(this)}});f(j.prototype,"r",2);f(j.prototype,"g",1);f(j.prototype,"b",0);b(j.prototype,"h");b(j.prototype,"s");b(j.prototype,"v");Object.defineProperty(j.prototype,"a",{get:function(){return this.__state.a},set:function(a){this.__state.a=a}});Object.defineProperty(j.prototype,"hex",{get:function(){if(!this.__state.space!=="HEX")this.__state.hex= +a.rgb_to_hex(this.r,this.g,this.b);return this.__state.hex},set:function(a){this.__state.space="HEX";this.__state.hex=a}});return j}(dat.color.interpret,dat.color.math=function(){var e;return{hsv_to_rgb:function(a,c,d){var e=a/60-Math.floor(a/60),b=d*(1-c),n=d*(1-e*c),c=d*(1-(1-e)*c),a=[[d,c,b],[n,d,b],[b,d,c],[b,n,d],[c,b,d],[d,b,n]][Math.floor(a/60)%6];return{r:a[0]*255,g:a[1]*255,b:a[2]*255}},rgb_to_hsv:function(a,c,d){var e=Math.min(a,c,d),b=Math.max(a,c,d),e=b-e;if(b==0)return{h:NaN,s:0,v:0}; +a=a==b?(c-d)/e:c==b?2+(d-a)/e:4+(a-c)/e;a/=6;a<0&&(a+=1);return{h:a*360,s:e/b,v:b/255}},rgb_to_hex:function(a,c,d){a=this.hex_with_component(0,2,a);a=this.hex_with_component(a,1,c);return a=this.hex_with_component(a,0,d)},component_from_hex:function(a,c){return a>>c*8&255},hex_with_component:function(a,c,d){return d<<(e=c*8)|a&~(255< this.fGrowDuration + this.fWaitDuration) { + this.fVX += this.fAX + fMaxAX * fnRnd2(); + this.fVY += this.fAY + fMaxAY * fnRnd2(); + this.fVZ += this.fAZ + fMaxAZ * fnRnd2(); + this.fX += this.fVX; + this.fY += this.fVY; + this.fZ += this.fVZ; + } + this.fRotX = fCosAngle * this.fX + fSinAngle * this.fZ; + this.fRotZ = -fSinAngle * this.fX + fCosAngle * this.fZ; + this.fRadiusCurrent = Math.max(0.01, window.iPerspective / (window.iPerspective - this.fRotZ)); + this.fProjX = this.fRotX * this.fRadiusCurrent + iProjSphereX; + this.fProjY = this.fY * this.fRadiusCurrent + iProjSphereY; + this.iFramesAlive += 1; + if (this.iFramesAlive < this.fGrowDuration) { + this.fAlpha = this.iFramesAlive * 1.0 / this.fGrowDuration; + } else if (this.iFramesAlive < this.fGrowDuration + this.fWaitDuration) { + this.fAlpha = 1.0; + } else if (this.iFramesAlive < this.fGrowDuration + this.fWaitDuration + this.fShrinkDuration) { + this.fAlpha = (this.fGrowDuration + this.fWaitDuration + this.fShrinkDuration - this.iFramesAlive) * 1.0 / this.fShrinkDuration; + } else { + this.bIsDead = true; + } + if (this.bIsDead === true) { + fnSwapList(this, oRender, oBuffer); + } + this.fAlpha *= fnMin(1.0, fnMax(0.5, this.fRotZ / iRadiusSphere)); + this.fAlpha = fnMin(1.0, fnMax(0.0, this.fAlpha)); + } + + }; + + // Current Position + Particle.prototype.fX = 0.0; + + Particle.prototype.fY = 0.0; + + Particle.prototype.fZ = 0.0; + + // Current Velocity + Particle.prototype.fVX = 0.0; + + Particle.prototype.fVY = 0.0; + + Particle.prototype.fVZ = 0.0; + + // Current Acceleration + Particle.prototype.fAX = 0.0; + + Particle.prototype.fAY = 0.0; + + Particle.prototype.fAZ = 0.0; + + // Projection Position + Particle.prototype.fProjX = 0.0; + + Particle.prototype.fProjY = 0.0; + + // Rotation + Particle.prototype.fRotX = 0.0; + + Particle.prototype.fRotZ = 0.0; + + // double linked list + Particle.prototype.pPrev = null; + + Particle.prototype.pNext = null; + + Particle.prototype.fAngle = 0.0; + + Particle.prototype.fForce = 0.0; + + Particle.prototype.fGrowDuration = 0.0; + + Particle.prototype.fWaitDuration = 0.0; + + Particle.prototype.fShrinkDuration = 0.0; + + Particle.prototype.fRadiusCurrent = 0.0; + + Particle.prototype.iFramesAlive = 0; + + Particle.prototype.bIsDead = false; + + return Particle; + + }).call(this); + fnRender = function() { + var iCount, p; + ctxRender.fillStyle = "#000"; + ctxRender.fillRect(0, 0, w, h); + p = oRender.pFirst; + iCount = 0; + while (p != null) { + ctxRender.fillStyle = "rgba(" + window.aColor.join(',') + ',' + p.fAlpha.toFixed(4) + ")"; + ctxRender.beginPath(); + ctxRender.arc(p.fProjX, p.fProjY, p.fRadiusCurrent, 0, 2 * fPI, false); + ctxRender.closePath(); + ctxRender.fill(); + p = p.pNext; + iCount += 1; + } + }; + fnNextFrame = function() { + var iAddParticle, iCount, p, pNext; + oStats.begin(); + fAngle = (fAngle + fVX) % (2.0 * fPI); + fSinAngle = fnSin(fAngle); + fCosAngle = fnCos(fAngle); + iAddParticle = 0; + iCount = 0; + while (iAddParticle++ < window.iNewParticlePerFrame) { + p = fnSwapList(oBuffer.pFirst, oBuffer, oRender); + p.fnInit(); + } + p = oRender.pFirst; + while (p != null) { + pNext = p.pNext; + p.fnUpdate(); + p = pNext; + iCount++; + } + fnRender(); + oStats.end(); + return fnRequestAnimationFrame(function() { + return fnNextFrame(); + }); + }; + fnNextFrame(); + /* + gui = new dat.GUI(); + gui.add(window, 'fGrowDuration').min(10).max(500).step(1); + gui.add(window, 'fWaitDuration').min(10).max(500).step(1); + gui.add(window, 'fShrinkDuration').min(10).max(500).step(1); + gui.add(window, 'iPerspective').min(150).max(1000).step(1); + gui.add(window, 'iNewParticlePerFrame').min(1).max(20).step(1); + gui.add(window, 'iFramesToRotate').min(50).max(2500).step(50).onChange(function() { + return fVX = (2.0 * fPI) / window.iFramesToRotate; + }); + gui.addColor(window, 'aColor').onChange(function() { + window.aColor[0] = ~~window.aColor[0]; + window.aColor[1] = ~~window.aColor[1]; + return window.aColor[2] = ~~window.aColor[2]; + }); + if (window.innerWidth < 1000) { + gui.close(); + window.iNewParticlePerFrame = 5; + } + */ + window.app = this; + }; + + fnAddEventListener(window, 'load', app); + +}).call(this); + +function livelyPropertyListener(name, val) +{ + switch(name) { + case "fGrowDuration": + window.fGrowDuration = val; + break; + case "fWaitDuration": + window.fWaitDuration = val; + break; + case "fShrinkDuration": + window.fShrinkDuration = val; + break; + case "iPerspective": + window.iPerspective = val; + break; + case "iNewParticlePerFrame": + window.iNewParticlePerFrame = val; + break; + case "iFramesToRotate": + window.iFramesToRotate = val; + fVX = (2.0 * fPI) / window.iFramesToRotate; + break; + case "aColor": + var tmpColor = hexToRgb(val); + window.aColor[0] = tmpColor.r; + window.aColor[1] = tmpColor.g; + window.aColor[2] = tmpColor.b; + break; + } +} + +function hexToRgb(hex) { + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; +} +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiPGFub255bW91cz4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7RUFBQTs7Ozs7Ozs7Ozs7Ozs7QUFBQSxNQUFBLEdBQUEsRUFBQSxrQkFBQSxFQUFBOztFQWNBLHVCQUFBLEdBQTBCLFFBQUEsQ0FBQyxVQUFELENBQUE7QUFDeEIsUUFBQTtJQUFBLFdBQUEsR0FDRSxNQUFNLENBQUMscUJBQVAsSUFDQSxNQUFNLENBQUMsMkJBRFAsSUFFQSxNQUFNLENBQUMsd0JBRlAsSUFHQSxNQUFNLENBQUMsc0JBSFAsSUFJQSxNQUFNLENBQUMsdUJBSlAsSUFLQSxRQUFBLENBQUMsVUFBRCxDQUFBO01BQ0UsTUFBTSxDQUFDLFVBQVAsQ0FBa0IsVUFBbEIsRUFBOEIsSUFBQSxHQUFPLEVBQXJDO0lBREY7SUFHRixXQUFBLENBQVksVUFBWjtFQVZ3QixFQWQxQjs7O0VBNEJBLGtCQUFBLEdBQXFCLFFBQUEsQ0FBQyxDQUFELEVBQUksTUFBSixFQUFZLEVBQVosQ0FBQTtJQUNuQixJQUFHLENBQUMsQ0FBQyxnQkFBTDtNQUNFLENBQUMsQ0FBQyxnQkFBRixDQUFtQixNQUFuQixFQUEyQixFQUEzQixFQUErQixLQUEvQixFQURGO0tBQUEsTUFBQTtNQUdFLENBQUUsQ0FBQSxJQUFBLEdBQU8sTUFBUCxDQUFGLEdBQW1CLEdBSHJCOztFQURtQjs7RUFPckIsR0FBQSxHQUFNLFFBQUEsQ0FBQSxDQUFBO0FBRUosUUFBQSxRQUFBLEVBQUEsU0FBQSxFQUFBLE1BQUEsRUFBQSxTQUFBLEVBQUEsTUFBQSxFQUFBLE1BQUEsRUFBQSxNQUFBLEVBQUEsR0FBQSxFQUFBLFNBQUEsRUFBQSxRQUFBLEVBQUEsUUFBQSxFQUFBLFFBQUEsRUFBQSxHQUFBLEVBQUEsTUFBQSxFQUFBLEtBQUEsRUFBQSxLQUFBLEVBQUEsS0FBQSxFQUFBLFdBQUEsRUFBQSxRQUFBLEVBQUEsS0FBQSxFQUFBLE1BQUEsRUFBQSxTQUFBLEVBQUEsS0FB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QTBDLENBQUMsR0FBM0MsQ0FBK0MsSUFBL0MsQ0FBb0QsQ0FBQyxJQUFyRCxDQUEwRCxFQUExRCxDQUE2RCxDQUFDLFFBQTlELENBQXVFLFFBQUEsQ0FBQSxDQUFBO2FBQ3JFLEdBQUEsR0FBTSxDQUFDLEdBQUEsR0FBTSxHQUFQLENBQUEsR0FBYyxNQUFNLENBQUM7SUFEMEMsQ0FBdkU7SUFHQSxHQUFHLENBQUMsUUFBSixDQUFhLE1BQWIsRUFBcUIsUUFBckIsQ0FBOEIsQ0FBQyxRQUEvQixDQUF3QyxRQUFBLENBQUEsQ0FBQTtNQUN0QyxNQUFNLENBQUMsTUFBTyxDQUFBLENBQUEsQ0FBZCxHQUFtQixDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU8sQ0FBQSxDQUFBO01BQ25DLE1BQU0sQ0FBQyxNQUFPLENBQUEsQ0FBQSxDQUFkLEdBQW1CLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTyxDQUFBLENBQUE7YUFDbkMsTUFBTSxDQUFDLE1BQU8sQ0FBQSxDQUFBLENBQWQsR0FBbUIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFPLENBQUEsQ0FBQTtJQUhHLENBQXhDO0lBS0EsSUFBRyxNQUFNLENBQUMsVUFBUCxHQUFvQixJQUF2QjtNQUNFLEdBQUcsQ0FBQyxLQUFKLENBQUE7TUFDQSxNQUFNLENBQUMsb0JBQVAsR0FBOEIsRUFGaEM7O0lBSUEsTUFBTSxDQUFDLEdBQVAsR0FBYTtFQTNPVDs7RUE4T04sa0JBQUEsQ0FBbUIsTUFBbkIsRUFBMkIsTUFBM0IsRUFBbUMsR0FBbkM7QUFqUkEiLCJzb3VyY2VzQ29udGVudCI6WyIjIEh1bmdhcmlhbiBub3RhdGlvblxuIyAoaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9IdW5nYXJpYW5fbm90YXRpb24pXG4jIG4gLSBIVE1MLU5vZGVcbiMgbyAtIG9iamVjdFxuIyBzIC0gc3RyaW5nXG4jIGkgLSBpbnRlZ2VyXG4jIGEgLSBhcnJheVxuIyBiIC0gYm9vbGVhblxuIyBmIC0gZmxvYXRcbiMgcCAtIFBhcnRpY2xlXG4jIGZuIC0gZnVuY3Rpb25cbiMgY3R4IC0gMkQgQ29udGV4dFxuXG4jIEdlbmVyYWwgRnVuY3Rpb25zXG5mblJlcXVlc3RBbmltYXRpb25GcmFtZSA9IChmbkNhbGxiYWNrKSAtPlxuICBmbkFuaW1GcmFtZSA9XG4gICAgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSBvclxuICAgIHdpbmRvdy53ZWJraXRSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgb3JcbiAgICB3aW5kb3cubW96UmVxdWVzdEFuaW1hdGlvbkZyYW1lIG9yXG4gICAgd2luZG93Lm9SZXF1ZXN0QW5pbWF0aW9uRnJhbWUgb3JcbiAgICB3aW5kb3cubXNSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgb3JcbiAgICAoZm5DYWxsYmFjaykgLT5cbiAgICAgIHdpbmRvdy5zZXRUaW1lT3V0KGZuQ2FsbGJhY2ssIDEwMDAgLyA2MClcbiAgICAgIHJldHVyblxuICBmbkFuaW1GcmFtZSBmbkNhbGxiYWNrXG4gIHJldHVyblxuXG4jIEFkZCBFdmVudCBMaXN0ZW5lclxuZm5BZGRFdmVudExpc3RlbmVyID0gKG8sIHNFdmVudCwgZm4pIC0+XG4gIGlmIG8uYWRkRXZlbnRMaXN0ZW5lclxuICAgIG8uYWRkRXZlbnRMaXN0ZW5lcihzRXZlbnQsIGZuLCBmYWxzZSlcbiAgZWxzZVxuICAgIG9bJ29uJyArIHNFdmVudF0gPSBmblxuICByZXR1cm5cblxuYXBwID0gKCkgLT5cblxuICBvU3RhdHMgPSBuZXcgU3RhdHMoKVxuICBvU3RhdHMuc2V0TW9kZSgwKVxuICBvU3RhdHMuZG9tRWxlbWVudC5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSdcbiAgb1N0YXRzLmRvbUVsZW1lbnQuc3R5bGUubGVmdCA9ICcwcHgnXG4gIG9TdGF0cy5kb21FbGVtZW50LnN0eWxlLnRvcCA9ICcwcHgnXG4gIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQob1N0YXRzLmRvbUVsZW1lbnQpXG5cbiAgIyBHZW5lcmFsIEVsZW1lbnRzXG4gIG9Eb2MgPSBkb2N1bWVudFxuICBuQm9keSA9IG9Eb2MuYm9keVxuICAjIFNob3J0Y3V0c1xuICBmUEkgPSBNYXRoLlBJXG4gIGZuTWF4ID0gTWF0aC5tYXhcbiAgZm5NaW4gPSBNYXRoLm1pblxuICBmblJuZCA9IE1hdGgucmFuZG9tXG4gIGZuUm5kMiA9ICgpIC0+IDIuMCAqIGZuUm5kKCkgLSAxLjBcbiAgZm5Db3MgPSBNYXRoLmNvc1xuICBmbkFDb3MgPSBNYXRoLmFjb3NcbiAgZm5TaW4gPSBNYXRoLnNpblxuICAjIFNwaGVyZSBTZXR0aW5nc1xuICBpUmFkaXVzU3BoZXJlID0gMTUwXG4gIGlQcm9qU3BoZXJlWCA9IDBcbiAgaVByb2pTcGhlcmVZID0gMFxuICAjIFBhcnRpY2xlIFNldHRpbmdzXG4gIGZNYXhBWCA9IDAuMVxuICBmTWF4QVkgPSAwLjFcbiAgZk1heEFaID0gMC4xXG4gIGZTdGFydFZYID0gMC4wMDFcbiAgZlN0YXJ0VlkgPSAwLjAwMVxuICBmU3RhcnRWWiA9IDAuMDAxXG4gIGZBbmdsZSA9IDAuMFxuICBmU2luQW5nbGUgPSAwLjBcbiAgZkNvc0FuZ2xlID0gMC4wXG5cbiAgd2luZG93LmlGcmFtZXNUb1JvdGF0ZSA9IDIwMDAuMFxuICB3aW5kb3cuaVBlcnNwZWN0aXZlID0gMjUwXG4gIHdpbmRvdy5pTmV3UGFydGljbGVQZXJGcmFtZSA9IDEwXG4gIHdpbmRvdy5mR3Jvd0R1cmF0aW9uID0gMjAwLjBcbiAgd2luZG93LmZXYWl0RHVyYXRpb24gPSA1MC4wXG4gIHdpbmRvdy5mU2hyaW5rRHVyYXRpb24gPSAyNTAuMFxuICB3aW5kb3cuYUNvbG9yID0gWzI1NSwgMTI4LCAxMjhdXG5cbiAgZlZYID0gKDIuMCAqIGZQSSkgLyB3aW5kb3cuaUZyYW1lc1RvUm90YXRlXG5cbiAgb1JhZEdyYWQgPSBudWxsXG4gIGN0eFJlbmRlciA9IG5DYW52YXNSZW5kZXIuZ2V0Q29udGV4dCAnMmQnXG5cblxuICBvUmVuZGVyID0ge3BGaXJzdDogbnVsbH1cbiAgb0J1ZmZlciA9IHtwRmlyc3Q6IG51bGx9XG4gIFxuICB3ID0gaCA9IDBcblxuICAjIGdldHMvc2V0cyBzaXplXG4gIGZuU2V0U2l6ZSA9ICgpIC0+XG4gICAgbkNhbnZhc1JlbmRlci53aWR0aCA9IHcgPSB3aW5kb3cuaW5uZXJXaWR0aFxuICAgIG5DYW52YXNSZW5kZXIuaGVpZ2h0ID0gaCA9IHdpbmRvdy5pbm5lckhlaWdodFxuICAgIGlQcm9qU3BoZXJlWCA9IHcgLyAyXG4gICAgaVByb2pTcGhlcmVZID0gaCAvIDJcbiAgICB7dzogdywgaDogaH1cblxuICBmblNldFNpemUoKVxuICBcbiAgIyB3aW5kb3cub25yZXNpemVcbiAgZm5BZGRFdmVudExpc3RlbmVyKHdpbmRvdywgJ3Jlc2l6ZScsIGZuU2V0U2l6ZSlcblxuICBmblN3YXBMaXN0ID0gKHAsIG9TcmMsIG9Ec3QpIC0+XG4gICAgaWYgcD9cbiAgICAgICMgcmVtb3ZlIHAgZnJvbSBvU3JjXG4gICAgICBpZiBvU3JjLnBGaXJzdCBpcyBwXG4gICAgICAgIG9TcmMucEZpcnN0ID0gcC5wTmV4dFxuICAgICAgICBwLnBOZXh0LnBQcmV2ID0gbnVsbCBpZiBwLnBOZXh0P1xuICAgICAgZWxzZVxuICAgICAgICBwLnBQcmV2LnBOZXh0ID0gcC5wTmV4dFxuICAgICAgICBwLnBOZXh0LnBQcmV2ID0gcC5wUHJldiBpZiBwLnBOZXh0P1xuICAgIGVsc2VcbiAgICAgICMgY3JlYXRlIG5ldyBwXG4gICAgICBwID0gbmV3IFBhcnRpY2xlKClcbiAgXG4gICAgcC5wTmV4dCA9IG9Ec3QucEZpcnN0XG4gICAgb0RzdC5wRmlyc3QucFByZXYgPSBwIGlmIG9Ec3QucEZpcnN0P1xuICAgIG9Ec3QucEZpcnN0ID0gcFxuICAgIHAucFByZXYgPSBudWxsXG4gICAgcFxuICBcbiAgIyBQYXJ0aWNsZVxuICBjbGFzcyBQYXJ0aWNsZVxuICAgICMgQ3VycmVudCBQb3NpdGlvblxuICAgIGZYOiAwLjBcbiAgICBmWTogMC4wXG4gICAgZlo6IDAuMFxuICAgICMgQ3VycmVudCBWZWxvY2l0eVxuICAgIGZWWDogMC4wXG4gICAgZlZZOiAwLjBcbiAgICBmVlo6IDAuMFxuICAgICMgQ3VycmVudCBBY2NlbGVyYXRpb25cbiAgICBmQVg6IDAuMFxuICAgIGZBWTogMC4wXG4gICAgZkFaOiAwLjBcbiAgICAjIFByb2plY3Rpb24gUG9zaXRpb25cbiAgICBmUHJvalg6IDAuMFxuICAgIGZQcm9qWTogMC4wXG4gICAgIyBSb3RhdGlvblxuICAgIGZSb3RYOiAwLjBcbiAgICBmUm90WjogMC4wXG4gICAgIyBkb3VibGUgbGlua2VkIGxpc3RcbiAgICBwUHJldjogbnVsbFxuICAgIHBOZXh0OiBudWxsXG4gICAgXG4gICAgZkFuZ2xlOiAwLjBcbiAgICBmRm9yY2U6IDAuMFxuXG4gICAgZkdyb3dEdXJhdGlvbjogMC4wXG4gICAgZldhaXREdXJhdGlvbjogMC4wXG4gICAgZlNocmlua0R1cmF0aW9uOiAwLjBcbiAgICBcbiAgICBmUmFkaXVzQ3VycmVudDogMC4wXG4gICAgXG4gICAgaUZyYW1lc0FsaXZlOiAwXG4gICAgYklzRGVhZDogZmFsc2VcbiAgICAgIFxuICAgIGZuSW5pdDogKCkgLT5cbiAgICAgIEBmQW5nbGUgPSBmblJuZCgpICogZlBJICogMlxuICAgICAgQGZGb3JjZSA9IGZuQUNvcyhmblJuZDIoKSlcbiAgICAgIEBmQWxwaGEgPSAwXG4gICAgICBAYklzRGVhZCA9IGZhbHNlO1xuICAgICAgQGlGcmFtZXNBbGl2ZSA9IDA7XG4gICAgICBAZlggPSBpUmFkaXVzU3BoZXJlICogZm5TaW4oQGZGb3JjZSkgKiBmbkNvcyhAZkFuZ2xlKVxuICAgICAgQGZZID0gaVJhZGl1c1NwaGVyZSAqIGZuU2luKEBmRm9yY2UpICogZm5TaW4oQGZBbmdsZSlcbiAgICAgIEBmWiA9IGlSYWRpdXNTcGhlcmUgKiBmbkNvcyhAZkZvcmNlKVxuICAgICAgQGZWWCA9IGZTdGFydFZYICogQGZYXG4gICAgICBAZlZZID0gZlN0YXJ0VlkgKiBAZllcbiAgICAgIEBmVlogPSBmU3RhcnRWWiAqIEBmWlxuICAgICAgQGZHcm93RHVyYXRpb24gPSB3aW5kb3cuZkdyb3dEdXJhdGlvbiArIGZuUm5kMigpICogKHdpbmRvdy5mR3Jvd0R1cmF0aW9uIC8gNC4wKVxuICAgICAgQGZXYWl0RHVyYXRpb24gPSB3aW5kb3cuZldhaXREdXJhdGlvbiArIGZuUm5kMigpICogKHdpbmRvdy5mV2FpdER1cmF0aW9uIC8gNC4wKVxuICAgICAgQGZTaHJpbmtEdXJhdGlvbiA9IHdpbmRvdy5mU2hyaW5rRHVyYXRpb24gKyBmblJuZDIoKSAqICh3aW5kb3cuZlNocmlua0R1cmF0aW9uIC8gNC4wKVxuICAgICAgQGZBWCA9IDAuMFxuICAgICAgQGZBWSA9IDAuMFxuICAgICAgQGZBWiA9IDAuMFxuICAgICAgcmV0dXJuXG4gIFxuICAgIGZuVXBkYXRlOiAoKSAtPlxuICAgICAgaWYgQGlGcmFtZXNBbGl2ZSA+IEBmR3Jvd0R1cmF0aW9uICsgQGZXYWl0RHVyYXRpb25cbiAgICAgICAgQGZWWCArPSBAZkFYICsgZk1heEFYICogZm5SbmQyKClcbiAgICAgICAgQGZWWSArPSBAZkFZICsgZk1heEFZICogZm5SbmQyKClcbiAgICAgICAgQGZWWiArPSBAZkFaICsgZk1heEFaICogZm5SbmQyKClcbiAgICAgICAgQGZYICs9IEBmVlhcbiAgICAgICAgQGZZICs9IEBmVllcbiAgICAgICAgQGZaICs9IEBmVlpcblxuICAgICAgQGZSb3RYID0gZkNvc0FuZ2xlICogQGZYICsgZlNpbkFuZ2xlICogQGZaXG4gICAgICBAZlJvdFogPSAtZlNpbkFuZ2xlICogQGZYICsgZkNvc0FuZ2xlICogQGZaXG4gICAgICBAZlJhZGl1c0N1cnJlbnQgPSBNYXRoLm1heCgwLjAxLCB3aW5kb3cuaVBlcnNwZWN0aXZlIC8gKHdpbmRvdy5pUGVyc3BlY3RpdmUgLSBAZlJvdFopKVxuICAgICAgQGZQcm9qWCA9IEBmUm90WCAqIEBmUmFkaXVzQ3VycmVudCArIGlQcm9qU3BoZXJlWCBcbiAgICAgIEBmUHJvalkgPSBAZlkgKiBAZlJhZGl1c0N1cnJlbnQgKyBpUHJvalNwaGVyZVkgXG5cbiAgICAgIEBpRnJhbWVzQWxpdmUgKz0gMVxuXG4gICAgICBpZiBAaUZyYW1lc0FsaXZlIDwgQGZHcm93RHVyYXRpb25cbiAgICAgICAgQGZBbHBoYSA9IEBpRnJhbWVzQWxpdmUgKiAxLjAgLyBAZkdyb3dEdXJhdGlvblxuICAgICAgZWxzZSBpZiBAaUZyYW1lc0FsaXZlIDwgQGZHcm93RHVyYXRpb24gKyBAZldhaXREdXJhdGlvblxuICAgICAgICBAZkFscGhhID0gMS4wXG4gICAgICBlbHNlIGlmIEBpRnJhbWVzQWxpdmUgPCBAZkdyb3dEdXJhdGlvbiArIEBmV2FpdER1cmF0aW9uICsgQGZTaHJpbmtEdXJhdGlvblxuICAgICAgICBAZkFscGhhID0gKEBmR3Jvd0R1cmF0aW9uICsgQGZXYWl0RHVyYXRpb24gKyBAZlNocmlua0R1cmF0aW9uIC0gQGlGcmFtZXNBbGl2ZSkgKiAxLjAgLyBAZlNocmlua0R1cmF0aW9uXG4gICAgICBlbHNlXG4gICAgICAgIEBiSXNEZWFkID0gdHJ1ZVxuXG4gICAgICBpZiBAYklzRGVhZCBpcyB0cnVlXG4gICAgICAgIGZuU3dhcExpc3QoQCwgb1JlbmRlciwgb0J1ZmZlcilcblxuICAgICAgQGZBbHBoYSAqPSBmbk1pbigxLjAsIGZuTWF4KDAuNSwgQGZSb3RaIC8gaVJhZGl1c1NwaGVyZSkpXG4gICAgICBAZkFscGhhID0gZm5NaW4oMS4wLCBmbk1heCgwLjAsIEBmQWxwaGEpKVxuICAgICAgcmV0dXJuXG4gICAgICBcbiAgZm5SZW5kZXIgPSAoKSAtPlxuICAgIGN0eFJlbmRlci5maWxsU3R5bGUgPSBcIiMwMDBcIlxuICAgIGN0eFJlbmRlci5maWxsUmVjdCgwLCAwLCB3LCBoKVxuXG4gICAgcCA9IG9SZW5kZXIucEZpcnN0XG4gICAgaUNvdW50ID0gMFxuICAgIHdoaWxlIHA/XG4gICAgICBjdHhSZW5kZXIuZmlsbFN0eWxlID0gXCJyZ2JhKFwiICsgd2luZG93LmFDb2xvci5qb2luKCcsJykgKyAnLCcgKyBwLmZBbHBoYS50b0ZpeGVkKDQpICsgXCIpXCJcbiAgICAgIGN0eFJlbmRlci5iZWdpblBhdGgoKVxuICAgICAgY3R4UmVuZGVyLmFyYyhwLmZQcm9qWCwgcC5mUHJvalksIHAuZlJhZGl1c0N1cnJlbnQsIDAsIDIgKiBmUEksIGZhbHNlKVxuICAgICAgY3R4UmVuZGVyLmNsb3NlUGF0aCgpXG4gICAgICBjdHhSZW5kZXIuZmlsbCgpXG4gICAgICBwID0gcC5wTmV4dFxuICAgICAgaUNvdW50ICs9IDFcbiAgICByZXR1cm5cbiAgXG4gIGZuTmV4dEZyYW1lID0gKCkgLT5cbiAgICBvU3RhdHMuYmVnaW4oKVxuICAgIGZBbmdsZSA9IChmQW5nbGUgKyBmVlgpICUgKDIuMCAqIGZQSSlcbiAgICBmU2luQW5nbGUgPSBmblNpbihmQW5nbGUpXG4gICAgZkNvc0FuZ2xlID0gZm5Db3MoZkFuZ2xlKVxuXG4gICAgaUFkZFBhcnRpY2xlID0gMFxuICAgIGlDb3VudCA9IDBcbiAgICB3aGlsZSBpQWRkUGFydGljbGUrKyA8IHdpbmRvdy5pTmV3UGFydGljbGVQZXJGcmFtZVxuICAgICAgcCA9IGZuU3dhcExpc3Qob0J1ZmZlci5wRmlyc3QsIG9CdWZmZXIsIG9SZW5kZXIpXG4gICAgICBwLmZuSW5pdCgpXG4gIFxuICAgIHAgPSBvUmVuZGVyLnBGaXJzdFxuICAgIHdoaWxlIHA/XG4gICAgICBwTmV4dCA9IHAucE5leHRcbiAgICAgIHAuZm5VcGRhdGUoKVxuICAgICAgcCA9IHBOZXh0XG4gICAgICBpQ291bnQrK1xuICAgIGZuUmVuZGVyKClcblxuICAgIG9TdGF0cy5lbmQoKVxuICAgIGZuUmVxdWVzdEFuaW1hdGlvbkZyYW1lICgpIC0+IGZuTmV4dEZyYW1lKCkgXG4gICAgXG4gIGZuTmV4dEZyYW1lKCkgIFxuXG4gIGd1aSA9IG5ldyBkYXQuR1VJKCk7XG4gIGd1aS5hZGQod2luZG93LCAnZkdyb3dEdXJhdGlvbicpLm1pbigxMCkubWF4KDUwMCkuc3RlcCgxKVxuICBndWkuYWRkKHdpbmRvdywgJ2ZXYWl0RHVyYXRpb24nKS5taW4oMTApLm1heCg1MDApLnN0ZXAoMSlcbiAgZ3VpLmFkZCh3aW5kb3csICdmU2hyaW5rRHVyYXRpb24nKS5taW4oMTApLm1heCg1MDApLnN0ZXAoMSlcbiAgZ3VpLmFkZCh3aW5kb3csICdpUGVyc3BlY3RpdmUnKS5taW4oMTUwKS5tYXgoMTAwMCkuc3RlcCgxKVxuICBndWkuYWRkKHdpbmRvdywgJ2lOZXdQYXJ0aWNsZVBlckZyYW1lJykubWluKDEpLm1heCgyMCkuc3RlcCgxKVxuICBndWkuYWRkKHdpbmRvdywgJ2lGcmFtZXNUb1JvdGF0ZScpLm1pbig1MCkubWF4KDI1MDApLnN0ZXAoNTApLm9uQ2hhbmdlKCgpIC0+XG4gICAgZlZYID0gKDIuMCAqIGZQSSkgLyB3aW5kb3cuaUZyYW1lc1RvUm90YXRlXG4gIClcbiAgZ3VpLmFkZENvbG9yKHdpbmRvdywgJ2FDb2xvcicpLm9uQ2hhbmdlKCgpIC0+XG4gICAgd2luZG93LmFDb2xvclswXSA9IH5+d2luZG93LmFDb2xvclswXVxuICAgIHdpbmRvdy5hQ29sb3JbMV0gPSB+fndpbmRvdy5hQ29sb3JbMV1cbiAgICB3aW5kb3cuYUNvbG9yWzJdID0gfn53aW5kb3cuYUNvbG9yWzJdXG4gIClcbiAgaWYgd2luZG93LmlubmVyV2lkdGggPCAxMDAwXG4gICAgZ3VpLmNsb3NlKClcbiAgICB3aW5kb3cuaU5ld1BhcnRpY2xlUGVyRnJhbWUgPSA1XG5cbiAgd2luZG93LmFwcCA9IEBcbiAgcmV0dXJuXG4gIFxuZm5BZGRFdmVudExpc3RlbmVyKHdpbmRvdywgJ2xvYWQnLCBhcHApIl19 +//# sourceURL=coffeescript \ No newline at end of file diff --git a/public/themes/dusty sphere/lively_p.gif b/public/themes/dusty sphere/lively_p.gif new file mode 100644 index 0000000..4673ef8 Binary files /dev/null and b/public/themes/dusty sphere/lively_p.gif differ diff --git a/public/themes/dusty sphere/lively_t.jpg b/public/themes/dusty sphere/lively_t.jpg new file mode 100644 index 0000000..096799d Binary files /dev/null and b/public/themes/dusty sphere/lively_t.jpg differ diff --git a/public/themes/electric fence/License.txt b/public/themes/electric fence/License.txt new file mode 100644 index 0000000..2ba746d --- /dev/null +++ b/public/themes/electric fence/License.txt @@ -0,0 +1,30 @@ +Electric Fence: https://www.shadertoy.com/view/4sVBWd +by MadEqua + +********************************************************************************************** + +https://github.com/patriciogonzalezvivo/glslCanvas +MIT License +The MIT License (MIT) + +Copyright (c) 2015 Patricio Gonzalez Vivo ( http://www.patriciogonzalezvivo.com ) + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +********************************************************************************************** \ No newline at end of file diff --git a/public/themes/electric fence/LivelyInfo.json b/public/themes/electric fence/LivelyInfo.json new file mode 100644 index 0000000..377d7c1 --- /dev/null +++ b/public/themes/electric fence/LivelyInfo.json @@ -0,0 +1,14 @@ +{ + "AppVersion": "0.8.5.0", + "Title": "Electric Fence [Customisable]", + "Thumbnail": "lively_t.jpg", + "Preview": "lively_p.gif", + "Desc": "Winner of the July 2018 ShaderToy compo from Graphics Programming Discord. Hexagons never disappoint.", + "Author": "MadEqua", + "License": null, + "Contact": "https://www.shadertoy.com/view/4sVBWd", + "Type": 1, + "FileName": "electric.html", + "Arguments": null, + "IsAbsolutePath": false +} \ No newline at end of file diff --git a/public/themes/electric fence/LivelyProperties.backup.json b/public/themes/electric fence/LivelyProperties.backup.json new file mode 100644 index 0000000..774f8ea --- /dev/null +++ b/public/themes/electric fence/LivelyProperties.backup.json @@ -0,0 +1,51 @@ +{ + "speed": { + "max": 50, + "min": 1, + "tick": 25, + "text": "Speed", + "type": "slider", + "value": 5 + }, + "scale": { + "max": 10, + "min": 1, + "tick": 25, + "text": "Scale", + "type": "slider", + "value": 1 + }, + "layers": { + "max": 10, + "min": 1, + "tick": 10, + "text": "Layers", + "type": "slider", + "value": 6 + }, + "color1": { + "text": "Color 1", + "type": "color", + "value": "#008040" + }, + "color2": { + "text": "Color 2", + "type": "color", + "value": "#800000" + }, + "color3": { + "text": "Color 3", + "type": "color", + "value": "#D0D000" + }, + "color4": { + "text": "Color 4", + "type": "color", + "value": "#0000FF" + }, + "fpsLock": { + "type": "checkbox", + "value": false, + "text": "30FPS Lock" + } +} \ No newline at end of file diff --git a/public/themes/electric fence/LivelyProperties.json b/public/themes/electric fence/LivelyProperties.json new file mode 100644 index 0000000..774f8ea --- /dev/null +++ b/public/themes/electric fence/LivelyProperties.json @@ -0,0 +1,51 @@ +{ + "speed": { + "max": 50, + "min": 1, + "tick": 25, + "text": "Speed", + "type": "slider", + "value": 5 + }, + "scale": { + "max": 10, + "min": 1, + "tick": 25, + "text": "Scale", + "type": "slider", + "value": 1 + }, + "layers": { + "max": 10, + "min": 1, + "tick": 10, + "text": "Layers", + "type": "slider", + "value": 6 + }, + "color1": { + "text": "Color 1", + "type": "color", + "value": "#008040" + }, + "color2": { + "text": "Color 2", + "type": "color", + "value": "#800000" + }, + "color3": { + "text": "Color 3", + "type": "color", + "value": "#D0D000" + }, + "color4": { + "text": "Color 4", + "type": "color", + "value": "#0000FF" + }, + "fpsLock": { + "type": "checkbox", + "value": false, + "text": "30FPS Lock" + } +} \ No newline at end of file diff --git a/public/themes/electric fence/electric.html b/public/themes/electric fence/electric.html new file mode 100644 index 0000000..0991b30 --- /dev/null +++ b/public/themes/electric fence/electric.html @@ -0,0 +1,70 @@ + + + + + + + \ No newline at end of file diff --git a/public/themes/electric fence/js/GlslCanvas.js b/public/themes/electric fence/js/GlslCanvas.js new file mode 100644 index 0000000..1baa021 --- /dev/null +++ b/public/themes/electric fence/js/GlslCanvas.js @@ -0,0 +1,2107 @@ +//fps loop +var queuedMilliseconds = 0; +var elapsedTime = 0; +var previousTime = 0; +var startTime = new Date(); +var endTime = 0; +var responseTime = -1; +function timeUpdate(){ + endTime = new Date(); + elapsedTime = endTime - startTime; //in ms + //elapsedTime = timeDiff;//Math.round(timeDiff); + startTime = endTime; +} + +//modification, blurry texture. +window.onload =()=>{ + let canvas = document.querySelector('.glslCanvas'); + canvas.setAttribute("width",window.innerWidth); + canvas.setAttribute("height",window.innerHeight); + window.onresize=()=>{ + canvas.setAttribute("width",window.innerWidth); + canvas.setAttribute("height",window.innerHeight); + } +} +//Basically uses the same code GlslCanvas uses to load it shaders +function reload(){ + var list = document.getElementsByClassName('glslCanvas'); + if (list.length > 0) { + window.glslCanvases = []; + for (var i = 0; i < list.length; i++) { + var sandbox = new GlslCanvas(list[i]); + if (sandbox.isValid) { + window.glslCanvases.push(sandbox); + } + } + } +} + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.GlslCanvas = factory()); +}(this, (function () { 'use strict'; + +var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + +function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; +} + +var win; + +if (typeof window !== "undefined") { + win = window; +} else if (typeof commonjsGlobal !== "undefined") { + win = commonjsGlobal; +} else if (typeof self !== "undefined"){ + win = self; +} else { + win = {}; +} + +var window_1 = win; + +var isFunction_1 = isFunction; + +var toString = Object.prototype.toString; + +function isFunction (fn) { + var string = toString.call(fn); + return string === '[object Function]' || + (typeof fn === 'function' && string !== '[object RegExp]') || + (typeof window !== 'undefined' && + // IE8 and below + (fn === window.setTimeout || + fn === window.alert || + fn === window.confirm || + fn === window.prompt)) +} + +var trim_1 = createCommonjsModule(function (module, exports) { +exports = module.exports = trim; + +function trim(str){ + return str.replace(/^\s*|\s*$/g, ''); +} + +exports.left = function(str){ + return str.replace(/^\s*/, ''); +}; + +exports.right = function(str){ + return str.replace(/\s*$/, ''); +}; +}); + +var forEach_1 = forEach; + +var toString$1 = Object.prototype.toString; +var hasOwnProperty = Object.prototype.hasOwnProperty; + +function forEach(list, iterator, context) { + if (!isFunction_1(iterator)) { + throw new TypeError('iterator must be a function') + } + + if (arguments.length < 3) { + context = this; + } + + if (toString$1.call(list) === '[object Array]') + forEachArray$1(list, iterator, context); + else if (typeof list === 'string') + forEachString(list, iterator, context); + else + forEachObject(list, iterator, context); +} + +function forEachArray$1(array, iterator, context) { + for (var i = 0, len = array.length; i < len; i++) { + if (hasOwnProperty.call(array, i)) { + iterator.call(context, array[i], i, array); + } + } +} + +function forEachString(string, iterator, context) { + for (var i = 0, len = string.length; i < len; i++) { + // no such thing as a sparse string. + iterator.call(context, string.charAt(i), i, string); + } +} + +function forEachObject(object, iterator, context) { + for (var k in object) { + if (hasOwnProperty.call(object, k)) { + iterator.call(context, object[k], k, object); + } + } +} + +var isArray = function(arg) { + return Object.prototype.toString.call(arg) === '[object Array]'; + }; + +var parseHeaders = function (headers) { + if (!headers) + return {} + + var result = {}; + + forEach_1( + trim_1(headers).split('\n') + , function (row) { + var index = row.indexOf(':') + , key = trim_1(row.slice(0, index)).toLowerCase() + , value = trim_1(row.slice(index + 1)); + + if (typeof(result[key]) === 'undefined') { + result[key] = value; + } else if (isArray(result[key])) { + result[key].push(value); + } else { + result[key] = [ result[key], value ]; + } + } + ); + + return result +}; + +var immutable = extend; + +var hasOwnProperty$1 = Object.prototype.hasOwnProperty; + +function extend() { + var target = {}; + + for (var i = 0; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (hasOwnProperty$1.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target +} + +"use strict"; + +var xhr = createXHR; +// Allow use of default import syntax in TypeScript +var default_1 = createXHR; +createXHR.XMLHttpRequest = window_1.XMLHttpRequest || noop; +createXHR.XDomainRequest = "withCredentials" in (new createXHR.XMLHttpRequest()) ? createXHR.XMLHttpRequest : window_1.XDomainRequest; + +forEachArray(["get", "put", "post", "patch", "head", "delete"], function(method) { + createXHR[method === "delete" ? "del" : method] = function(uri, options, callback) { + options = initParams(uri, options, callback); + options.method = method.toUpperCase(); + return _createXHR(options) + }; +}); + +function forEachArray(array, iterator) { + for (var i = 0; i < array.length; i++) { + iterator(array[i]); + } +} + +function isEmpty(obj){ + for(var i in obj){ + if(obj.hasOwnProperty(i)) return false + } + return true +} + +function initParams(uri, options, callback) { + var params = uri; + + if (isFunction_1(options)) { + callback = options; + if (typeof uri === "string") { + params = {uri:uri}; + } + } else { + params = immutable(options, {uri: uri}); + } + + params.callback = callback; + return params +} + +function createXHR(uri, options, callback) { + options = initParams(uri, options, callback); + return _createXHR(options) +} + +function _createXHR(options) { + if(typeof options.callback === "undefined"){ + throw new Error("callback argument missing") + } + + var called = false; + var callback = function cbOnce(err, response, body){ + if(!called){ + called = true; + options.callback(err, response, body); + } + }; + + function readystatechange() { + if (xhr.readyState === 4) { + setTimeout(loadFunc, 0); + } + } + + function getBody() { + // Chrome with requestType=blob throws errors arround when even testing access to responseText + var body = undefined; + + if (xhr.response) { + body = xhr.response; + } else { + body = xhr.responseText || getXml(xhr); + } + + if (isJson) { + try { + body = JSON.parse(body); + } catch (e) {} + } + + return body + } + + function errorFunc(evt) { + clearTimeout(timeoutTimer); + if(!(evt instanceof Error)){ + evt = new Error("" + (evt || "Unknown XMLHttpRequest Error") ); + } + evt.statusCode = 0; + return callback(evt, failureResponse) + } + + // will load the data & process the response in a special response object + function loadFunc() { + if (aborted) return + var status; + clearTimeout(timeoutTimer); + if(options.useXDR && xhr.status===undefined) { + //IE8 CORS GET successful response doesn't have a status field, but body is fine + status = 200; + } else { + status = (xhr.status === 1223 ? 204 : xhr.status); + } + var response = failureResponse; + var err = null; + + if (status !== 0){ + response = { + body: getBody(), + statusCode: status, + method: method, + headers: {}, + url: uri, + rawRequest: xhr + }; + if(xhr.getAllResponseHeaders){ //remember xhr can in fact be XDR for CORS in IE + response.headers = parseHeaders(xhr.getAllResponseHeaders()); + } + } else { + err = new Error("Internal XMLHttpRequest Error"); + } + return callback(err, response, response.body) + } + + var xhr = options.xhr || null; + + if (!xhr) { + if (options.cors || options.useXDR) { + xhr = new createXHR.XDomainRequest(); + }else{ + xhr = new createXHR.XMLHttpRequest(); + } + } + + var key; + var aborted; + var uri = xhr.url = options.uri || options.url; + var method = xhr.method = options.method || "GET"; + var body = options.body || options.data; + var headers = xhr.headers = options.headers || {}; + var sync = !!options.sync; + var isJson = false; + var timeoutTimer; + var failureResponse = { + body: undefined, + headers: {}, + statusCode: 0, + method: method, + url: uri, + rawRequest: xhr + }; + + if ("json" in options && options.json !== false) { + isJson = true; + headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json"); //Don't override existing accept header declared by user + if (method !== "GET" && method !== "HEAD") { + headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json"); //Don't override existing accept header declared by user + body = JSON.stringify(options.json === true ? body : options.json); + } + } + + xhr.onreadystatechange = readystatechange; + xhr.onload = loadFunc; + xhr.onerror = errorFunc; + // IE9 must have onprogress be set to a unique function. + xhr.onprogress = function () { + // IE must die + }; + xhr.onabort = function(){ + aborted = true; + }; + xhr.ontimeout = errorFunc; + xhr.open(method, uri, !sync, options.username, options.password); + //has to be after open + if(!sync) { + xhr.withCredentials = !!options.withCredentials; + } + // Cannot set timeout with sync request + // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly + // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent + if (!sync && options.timeout > 0 ) { + timeoutTimer = setTimeout(function(){ + if (aborted) return + aborted = true;//IE9 may still call readystatechange + xhr.abort("timeout"); + var e = new Error("XMLHttpRequest timeout"); + e.code = "ETIMEDOUT"; + errorFunc(e); + }, options.timeout ); + } + + if (xhr.setRequestHeader) { + for(key in headers){ + if(headers.hasOwnProperty(key)){ + xhr.setRequestHeader(key, headers[key]); + } + } + } else if (options.headers && !isEmpty(options.headers)) { + throw new Error("Headers cannot be set on an XDomainRequest object") + } + + if ("responseType" in options) { + xhr.responseType = options.responseType; + } + + if ("beforeSend" in options && + typeof options.beforeSend === "function" + ) { + options.beforeSend(xhr); + } + + // Microsoft Edge browser sends "undefined" when send is called with undefined value. + // XMLHttpRequest spec says to pass null as body to indicate no body + // See https://github.com/naugtur/xhr/issues/100. + xhr.send(body || null); + + return xhr + + +} + +function getXml(xhr) { + // xhr.responseXML will throw Exception "InvalidStateError" or "DOMException" + // See https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseXML. + try { + if (xhr.responseType === "document") { + return xhr.responseXML + } + var firefoxBugTakenEffect = xhr.responseXML && xhr.responseXML.documentElement.nodeName === "parsererror"; + if (xhr.responseType === "" && !firefoxBugTakenEffect) { + return xhr.responseXML + } + } catch (e) {} + + return null +} + +function noop() {} + +xhr.default = default_1; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { + return typeof obj; +} : function (obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; +}; + + + + + +var asyncGenerator = function () { + function AwaitValue(value) { + this.value = value; + } + + function AsyncGenerator(gen) { + var front, back; + + function send(key, arg) { + return new Promise(function (resolve, reject) { + var request = { + key: key, + arg: arg, + resolve: resolve, + reject: reject, + next: null + }; + + if (back) { + back = back.next = request; + } else { + front = back = request; + resume(key, arg); + } + }); + } + + function resume(key, arg) { + try { + var result = gen[key](arg); + var value = result.value; + + if (value instanceof AwaitValue) { + Promise.resolve(value.value).then(function (arg) { + resume("next", arg); + }, function (arg) { + resume("throw", arg); + }); + } else { + settle(result.done ? "return" : "normal", result.value); + } + } catch (err) { + settle("throw", err); + } + } + + function settle(type, value) { + switch (type) { + case "return": + front.resolve({ + value: value, + done: true + }); + break; + + case "throw": + front.reject(value); + break; + + default: + front.resolve({ + value: value, + done: false + }); + break; + } + + front = front.next; + + if (front) { + resume(front.key, front.arg); + } else { + back = null; + } + } + + this._invoke = send; + + if (typeof gen.return !== "function") { + this.return = undefined; + } + } + + if (typeof Symbol === "function" && Symbol.asyncIterator) { + AsyncGenerator.prototype[Symbol.asyncIterator] = function () { + return this; + }; + } + + AsyncGenerator.prototype.next = function (arg) { + return this._invoke("next", arg); + }; + + AsyncGenerator.prototype.throw = function (arg) { + return this._invoke("throw", arg); + }; + + AsyncGenerator.prototype.return = function (arg) { + return this._invoke("return", arg); + }; + + return { + wrap: function (fn) { + return function () { + return new AsyncGenerator(fn.apply(this, arguments)); + }; + }, + await: function (value) { + return new AwaitValue(value); + } + }; +}(); + + + + + +var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; + +var createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; +}(); + + + + + + + + + + + +var toConsumableArray = function (arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; + + return arr2; + } else { + return Array.from(arr); + } +}; + +var lastError = ''; + +/** + * Creates the HTLM for a failure message + * @param {string} canvasContainerId id of container of th + * canvas. + * @return {string} The html. + */ +function makeFailHTML(msg) { + return '\n\n
\n
\n
' + msg + '
\n
\n
\n'; +} + +/** + * Message for getting a webgl browser + * @type {string} + */ +var GET_A_WEBGL_BROWSER = '\n\tThis page requires a browser that supports WebGL.
\n\tClick here to upgrade your browser.\n'; + +/** + * Message for need better hardware + * @type {string} + */ +var OTHER_PROBLEM = '\n\tIt does not appear your computer can support WebGL.
\n\tClick here for more information.\n'; + +/** + * Code to return in `onError` callback when the browser doesn't support webgl + * @type {number} + */ +var ERROR_BROWSER_SUPPORT = 1; + +/** + * Code to return in `onError` callback there's any other problem related to webgl + * @type {number} + */ +var ERROR_OTHER = 2; + +/** + * Creates a webgl context. If creation fails it will + * change the contents of the container of the + * tag to an error message with the correct links for WebGL, + * unless `onError` option is defined to a callback, + * which allows for custom error handling.. + * @param {Element} canvas. The canvas element to create a + * context from. + * @param {WebGLContextCreationAttributes} optAttribs Any + * creation attributes you want to pass in. + * @return {WebGLRenderingContext} The created context. + */ +function setupWebGL(canvas, optAttribs, onError) { + function showLink(str) { + var container = canvas.parentNode; + if (container) { + container.innerHTML = makeFailHTML(str); + } + } + + function handleError(errorCode, msg) { + if (typeof onError === 'function') { + onError(errorCode); + } else { + showLink(msg); + } + } + + if (!window.WebGLRenderingContext) { + handleError(ERROR_BROWSER_SUPPORT, GET_A_WEBGL_BROWSER); + return null; + } + + var context = create3DContext(canvas, optAttribs); + if (!context) { + handleError(ERROR_OTHER, OTHER_PROBLEM); + } else { + context.getExtension('OES_standard_derivatives'); + } + return context; +} + +/** + * Creates a webgl context. + * @param {!Canvas} canvas The canvas tag to get context + * from. If one is not passed in one will be created. + * @return {!WebGLContext} The created context. + */ +function create3DContext(canvas, optAttribs) { + var names = ['webgl', 'experimental-webgl']; + var context = null; + for (var ii = 0; ii < names.length; ++ii) { + try { + context = canvas.getContext(names[ii], optAttribs); + } catch (e) { + if (context) { + break; + } + } + } + return context; +} + +/* + * Create a Vertex of a specific type (gl.VERTEX_SHADER/) + */ +function createShader(main, source, type, offset) { + var gl = main.gl; + + var shader = gl.createShader(type); + gl.shaderSource(shader, source); + gl.compileShader(shader); + + var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS); + + if (!compiled) { + // Something went wrong during compilation; get the error + lastError = gl.getShaderInfoLog(shader); + console.error('*** Error compiling shader ' + shader + ':' + lastError); + main.trigger('error', { + shader: shader, + source: source, + type: type, + error: lastError, + offset: offset || 0 + }); + gl.deleteShader(shader); + return null; + } + + return shader; +} + +/** + * Loads a shader. + * @param {!WebGLContext} gl The WebGLContext to use. + * @param {string} shaderSource The shader source. + * @param {number} shaderType The type of shader. + * @param {function(string): void) opt_errorCallback callback for errors. + * @return {!WebGLShader} The created shader. + */ +function createProgram(main, shaders, optAttribs, optLocations) { + var gl = main.gl; + + var program = gl.createProgram(); + for (var ii = 0; ii < shaders.length; ++ii) { + gl.attachShader(program, shaders[ii]); + } + if (optAttribs) { + for (var _ii = 0; _ii < optAttribs.length; ++_ii) { + gl.bindAttribLocation(program, optLocations ? optLocations[_ii] : _ii, optAttribs[_ii]); + } + } + gl.linkProgram(program); + + // Check the link status + var linked = gl.getProgramParameter(program, gl.LINK_STATUS); + if (!linked) { + // something went wrong with the link + lastError = gl.getProgramInfoLog(program); + console.log('Error in program linking:' + lastError); + gl.deleteProgram(program); + return null; + } + return program; +} + +// By Brett Camber on +// https://github.com/tangrams/tangram/blob/master/src/gl/glsl.js +function parseUniforms(uniforms) { + var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + var parsed = []; + + for (var name in uniforms) { + var uniform = uniforms[name]; + var u = void 0; + + if (prefix) { + name = prefix + '.' + name; + } + + // Single float + if (typeof uniform === 'number') { + parsed.push({ + type: 'float', + method: '1f', + name: name, + value: uniform + }); + } + // Array: vector, array of floats, array of textures, or array of structs + else if (Array.isArray(uniform)) { + // Numeric values + if (typeof uniform[0] === 'number') { + // float vectors (vec2, vec3, vec4) + if (uniform.length === 1) { + parsed.push({ + type: 'float', + method: '1f', + name: name, + value: uniform + }); + } + // float vectors (vec2, vec3, vec4) + else if (uniform.length >= 2 && uniform.length <= 4) { + parsed.push({ + type: 'vec' + uniform.length, + method: uniform.length + 'fv', + name: name, + value: uniform + }); + } + // float array + else if (uniform.length > 4) { + parsed.push({ + type: 'float[]', + method: '1fv', + name: name + '[0]', + value: uniform + }); + } + // TODO: assume matrix for (typeof == Float32Array && length == 16)? + } + // Array of textures + else if (typeof uniform[0] === 'string') { + parsed.push({ + type: 'sampler2D', + method: '1i', + name: name, + value: uniform + }); + } + // Array of arrays - but only arrays of vectors are allowed in this case + else if (Array.isArray(uniform[0]) && typeof uniform[0][0] === 'number') { + // float vectors (vec2, vec3, vec4) + if (uniform[0].length >= 2 && uniform[0].length <= 4) { + // Set each vector in the array + for (u = 0; u < uniform.length; u++) { + parsed.push({ + type: 'vec' + uniform[0].length, + method: uniform[u].length + 'fv', + name: name + '[' + u + ']', + value: uniform[u] + }); + } + } + // else error? + } + // Array of structures + else if (_typeof(uniform[0]) === 'object') { + for (u = 0; u < uniform.length; u++) { + // Set each struct in the array + parsed.push.apply(parsed, toConsumableArray(parseUniforms(uniform[u], name + '[' + u + ']'))); + } + } + } + // Boolean + else if (typeof uniform === 'boolean') { + parsed.push({ + type: 'bool', + method: '1i', + name: name, + value: uniform + }); + } + // Texture + else if (typeof uniform === 'string') { + parsed.push({ + type: 'sampler2D', + method: '1i', + name: name, + value: uniform + }); + } + // Structure + else if ((typeof uniform === 'undefined' ? 'undefined' : _typeof(uniform)) === 'object') { + // Set each field in the struct + parsed.push.apply(parsed, toConsumableArray(parseUniforms(uniform, name))); + } + // TODO: support other non-float types? (int, etc.) + } + return parsed; +} + +function isCanvasVisible(canvas) { + return canvas.getBoundingClientRect().top + canvas.height > 0 && canvas.getBoundingClientRect().top < (window.innerHeight || document.documentElement.clientHeight); +} + +function isPowerOf2(value) { + return (value & value - 1) === 0; +} + +function isSafari() { + return (/^((?!chrome|android).)*safari/i.test(navigator.userAgent) + ); +} + + + + + + + +function isDiff(a, b) { + if (a && b) { + return a.toString() !== b.toString(); + } + return false; +} + +function subscribeMixin$1(target) { + var listeners = new Set(); + + return Object.assign(target, { + on: function on(type, f) { + var listener = {}; + listener[type] = f; + listeners.add(listener); + }, + off: function off(type, f) { + if (f) { + var listener = {}; + listener[type] = f; + listeners.delete(listener); + } else { + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = listeners[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var item = _step.value; + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for (var _iterator2 = Object.keys(item)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var key = _step2.value; + + if (key === type) { + listeners.delete(item); + return; + } + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + } + }, + listSubscriptions: function listSubscriptions() { + var _iteratorNormalCompletion3 = true; + var _didIteratorError3 = false; + var _iteratorError3 = undefined; + + try { + for (var _iterator3 = listeners[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { + var item = _step3.value; + + console.log(item); + } + } catch (err) { + _didIteratorError3 = true; + _iteratorError3 = err; + } finally { + try { + if (!_iteratorNormalCompletion3 && _iterator3.return) { + _iterator3.return(); + } + } finally { + if (_didIteratorError3) { + throw _iteratorError3; + } + } + } + }, + subscribe: function subscribe(listener) { + listeners.add(listener); + }, + unsubscribe: function unsubscribe(listener) { + listeners.delete(listener); + }, + unsubscribeAll: function unsubscribeAll() { + listeners.clear(); + }, + trigger: function trigger(event) { + for (var _len = arguments.length, data = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + data[_key - 1] = arguments[_key]; + } + + var _iteratorNormalCompletion4 = true; + var _didIteratorError4 = false; + var _iteratorError4 = undefined; + + try { + for (var _iterator4 = listeners[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { + var listener = _step4.value; + + if (typeof listener[event] === 'function') { + listener[event].apply(listener, toConsumableArray(data)); + } + } + } catch (err) { + _didIteratorError4 = true; + _iteratorError4 = err; + } finally { + try { + if (!_iteratorNormalCompletion4 && _iterator4.return) { + _iterator4.return(); + } + } finally { + if (_didIteratorError4) { + throw _iteratorError4; + } + } + } + } + }); +} + +// Texture management +// GL texture wrapper object for keeping track of a global set of textures, keyed by a unique user-defined name + +var Texture = function () { + function Texture(gl, name) { + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + classCallCheck(this, Texture); + + subscribeMixin$1(this); + + this.gl = gl; + this.texture = gl.createTexture(); + if (this.texture) { + this.valid = true; + } + this.bind(); + + this.name = name; + this.source = null; + this.sourceType = null; + this.loading = null; // a Promise object to track the loading state of this texture + + // Default to a 1-pixel black texture so we can safely render while we wait for an image to load + // See: http://stackoverflow.com/questions/19722247/webgl-wait-for-texture-to-load + this.setData(1, 1, new Uint8Array([0, 0, 0, 255]), { filtering: 'linear' }); + this.setFiltering(options.filtering); + + this.load(options); + } + + // Destroy a single texture instance + + + createClass(Texture, [{ + key: 'destroy', + value: function destroy() { + if (!this.valid) { + return; + } + this.gl.deleteTexture(this.texture); + this.texture = null; + delete this.data; + this.data = null; + this.valid = false; + } + }, { + key: 'bind', + value: function bind(unit) { + if (!this.valid) { + return; + } + if (typeof unit === 'number') { + if (Texture.activeUnit !== unit) { + this.gl.activeTexture(this.gl.TEXTURE0 + unit); + Texture.activeUnit = unit; + } + } + if (Texture.activeTexture !== this.texture) { + this.gl.bindTexture(this.gl.TEXTURE_2D, this.texture); + Texture.activeTexture = this.texture; + } + } + }, { + key: 'load', + value: function load() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + this.loading = null; + + if (typeof options.url === 'string') { + if (this.url === undefined || options.url !== this.url) { + this.setUrl(options.url, options); + } + } else if (options.element) { + this.setElement(options.element, options); + } else if (options.data && options.width && options.height) { + this.setData(options.width, options.height, options.data, options); + } + } + + // Sets texture from an url + + }, { + key: 'setUrl', + value: function setUrl(url) { + var _this = this; + + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (!this.valid) { + return; + } + + this.url = url; // save URL reference (will be overwritten when element is loaded below) + this.source = this.url; + this.sourceType = 'url'; + + this.loading = new Promise(function (resolve, reject) { + var ext = url.split('.').pop().toLowerCase(); + var isVideo = ext === 'ogv' || ext === 'webm' || ext === 'mp4'; + + var element = undefined; + if (isVideo) { + element = document.createElement('video'); + element.autoplay = true; + options.filtering = 'nearest'; + // element.preload = 'auto'; + // element.style.display = 'none'; + // document.body.appendChild(element); + } else { + element = new Image(); + } + + element.onload = function () { + try { + _this.setElement(element, options); + } catch (e) { + console.log('Texture \'' + _this.name + '\': failed to load url: \'' + _this.source + '\'', e, options); + } + resolve(_this); + }; + element.onerror = function (e) { + // Warn and resolve on error + console.log('Texture \'' + _this.name + '\': failed to load url: \'' + _this.source + '\'', e, options); + resolve(_this); + }; + + // Safari has a bug loading data-URL elements with CORS enabled, so it must be disabled in that case + // https://bugs.webkit.org/show_bug.cgi?id=123978 + if (!(isSafari() && _this.source.slice(0, 5) === 'data:')) { + element.crossOrigin = 'anonymous'; + } + + element.src = _this.source; + if (isVideo) { + _this.setElement(element, options); + } + }); + return this.loading; + } + + // Sets texture to a raw image buffer + + }, { + key: 'setData', + value: function setData(width, height, data) { + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + this.width = width; + this.height = height; + + this.source = data; + this.sourceType = 'data'; + + this.update(options); + this.setFiltering(options); + + this.loading = Promise.resolve(this); + return this.loading; + } + + // Sets the texture to track a element (canvas/image) + + }, { + key: 'setElement', + value: function setElement(element, options) { + var _this2 = this; + + var el = element; + + // a string element is interpeted as a CSS selector + if (typeof element === 'string') { + element = document.querySelector(element); + } + + if (element instanceof HTMLCanvasElement || element instanceof HTMLImageElement || element instanceof HTMLVideoElement) { + this.source = element; + this.sourceType = 'element'; + + if (element instanceof HTMLVideoElement) { + element.addEventListener('canplaythrough', function () { + _this2.intervalID = setInterval(function () { + _this2.update(options); + }, 15); + }, true); + element.addEventListener('ended', function () { + element.currentTime = 0; + element.play(); + }, true); + } else { + this.update(options); + } + this.setFiltering(options); + } else { + var msg = 'the \'element\' parameter (`element: ' + JSON.stringify(el) + '`) must be a CSS '; + msg += 'selector string, or a , or