@rosalana/sandbox 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/globals.d.ts +0 -5
- package/dist/index.cjs.js +21 -21
- package/dist/index.es.js +326 -319
- package/dist/tools/compilable.d.ts +2 -1
- package/dist/tools/web_gl.d.ts +6 -0
- package/package.json +1 -1
package/dist/globals.d.ts
CHANGED
|
@@ -5,11 +5,6 @@ import ModuleRegistry from "./tools/module_registry";
|
|
|
5
5
|
* This registry will grow when more modules are defined
|
|
6
6
|
*/
|
|
7
7
|
export declare const modules: ModuleRegistry;
|
|
8
|
-
/**
|
|
9
|
-
* A global registry of modules that are currently in use by the webGL context.
|
|
10
|
-
* This is flushed on every shader switch.
|
|
11
|
-
*/
|
|
12
|
-
export declare const runtime_modules: ModuleRegistry;
|
|
13
8
|
/**
|
|
14
9
|
* Global uniforms that are automatically provided by Sandbox.
|
|
15
10
|
* These uniforms will NOT be renamed during preprocessing.
|
package/dist/index.cjs.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var ne=Object.defineProperty;var ie=(u,e,t)=>e in u?ne(u,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):u[e]=t;var a=(u,e,t)=>ie(u,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class y{constructor(e,t,n,i){this.target=e,this.type=t,this.listener=n,this.options=i,this.target.addEventListener(this.type,this.listener,this.options)}remove(){this.target.removeEventListener(this.type,this.listener,this.options)}static on(e,t,n,i){return e.addEventListener(t,n,i),()=>e.removeEventListener(t,n,i)}}class h extends Error{constructor(t,n){super(t);a(this,"name","SandboxError");this.code=n}}class O extends h{constructor(){super("WebGL is not supported in this browser.","CONTEXT_ERROR")}}class re extends h{constructor(){super("Failed to create WebGL context. The GPU may be unavailable.","CONTEXT_ERROR")}}class V extends h{constructor(e,t){super(`Vertex and fragment shader WebGL versions do not match (${e} vs ${t})`,"VALIDATION_ERROR"),this.vertexVersion=e,this.fragmentVersion=t}}class w extends h{constructor(t,n,i){const r=w.parseErrorLines(i),s=r.length>0?` at line(s): ${r.join(", ")}`:"";super(`${t} shader compilation failed${s}
|
|
2
2
|
|
|
3
|
-
${i}`,"SHADER_ERROR");
|
|
3
|
+
${i}`,"SHADER_ERROR");a(this,"lines");this.shaderType=t,this.source=n,this.infoLog=i,this.lines=r}static parseErrorLines(t){const n=[/ERROR:\s*\d*:(\d+)/g,/(\d+):(\d+)\(\d+\):/g,/^(\d+):/gm],i=new Set;for(const r of n){let s;for(;(s=r.exec(t))!==null;){const o=parseInt(s[1],10);o>0&&i.add(o)}}return[...i].sort((r,s)=>r-s)}}class A extends h{constructor(e,t,n,i){super(`The shader ${e} "${t}" has type "${i}" but expected "${n}"`,"SHADER_ERROR"),this.requirement=e,this.name=t,this.expectedType=n,this.actualType=i}}class I extends h{constructor(){super("Shader source does not contain any function.","SHADER_ERROR")}}class P extends h{constructor(e,t){super(`Syntax error in shader import statement at line ${e}: ${t}`,"SHADER_ERROR"),this.line=e,this.details=t}}class $ extends h{constructor(e,t){super(`Duplicate import name "${e}" found at line ${t}. Each import must have a unique name.`,"SHADER_ERROR"),this.name=e,this.line=t}}class D extends h{constructor(e){super(`Can not find module '${e}'. Check if it is defined before usage or if the name is correct.`,"MODULE_ERROR"),this.moduleName=e}}class B extends h{constructor(e,t){super(`Method '${t}' not found in shader module '${e}'. Check if the method is defined in the module source code or if the name is correct.`,"MODULE_ERROR"),this.moduleName=e,this.methodName=t}}class N extends h{constructor(e){super(`Importing 'main' function from module '${e}' is forbidden.`,"MODULE_ERROR"),this.moduleName=e}}class G extends h{constructor(e){super(`Name 'default' is reserved and cannot be used as a function name in module '${e}'.`,"MODULE_ERROR"),this.moduleName=e}}class W extends h{constructor(e){super(`Module name '${e}' is not allowed. Module names cannot be 'sandbox' or start with 'sandbox/'.`,"MODULE_ERROR"),this.moduleName=e}}class z extends h{constructor(e){super(`Module '${e}' is already defined. Overwriting existing modules is not allowed.`,"MODULE_ERROR"),this.moduleName=e}}class H extends h{constructor(e,t,n){super(`Uniform '${n}' mentioned for function '${t}' of module '${e}' was not found among the module's declared uniforms. Check if the uniform is declared in the module source code or if the name is correct.`,"MODULE_ERROR"),this.moduleName=e,this.functionName=t,this.uniformName=n}}class q extends h{constructor(e,t){super(`Uniform '${t}' mentioned for function '${e}' was not imported from any module. Check if the function is imported from the correct module and if the uniform is declared in that module's source code with the correct name.`,"MODULE_ERROR"),this.functionName=e,this.uniformName=t}}class j extends h{constructor(e,t){super(`Mention '${e}' called in function '${t}' could not be replaced with the corresponding uniform reference. There might be an issue with the compilation process because the referenced uniform was not found among the shader requirements. Try use a different name for uniforms you want to mention in functions or check if the uniform is properly declared and mentioned in the module source code.`,"MODULE_ERROR"),this.mentionName=e,this.calledInFunction=t}}class _ extends h{constructor(e){super(`Shader program linking failed
|
|
4
4
|
|
|
5
|
-
${e}`,"PROGRAM_ERROR"),this.infoLog=e}}class
|
|
6
|
-
`)[f-1].trim();throw new
|
|
7
|
-
`){s=!1;continue}if(!r&&!s&&f==="/"&&c==="*"){
|
|
5
|
+
${e}`,"PROGRAM_ERROR"),this.infoLog=e}}class se extends h{constructor(t){super(`Failed to create WebGL texture for "${t}".`,"TEXTURE_ERROR");a(this,"name","SandboxTextureCreationError");this.textureName=t}}class oe extends h{constructor(t,n){super(`Cannot bind texture "${t}": all ${n} texture units are in use.`,"TEXTURE_ERROR");a(this,"name","SandboxTextureUnitLimitError");this.textureName=t,this.maxUnits=n}}class X extends h{constructor(e){super(`Error in onLoad callback: ${e}`,"UNKNOWN_ERROR")}}class Y extends h{constructor(e,t){super(`Error in onBefore/onAfter hook callback with ID ${e}: ${t}`,"UNKNOWN_ERROR")}}class ae{constructor(){a(this,"time",0);a(this,"delta",0);a(this,"frame",0);a(this,"running",!1);a(this,"fps",0);a(this,"startTime",0);a(this,"lastTime",0);a(this,"rafId",null);a(this,"callback",null);a(this,"maxFps",0);this.loop=this.loop.bind(this)}start(e){if(this.running)return this;this.callback=e,this.running=!0;const t=performance.now();return this.frame===0?this.startTime=t:this.startTime=t-this.time*1e3,this.lastTime=t,this.rafId=requestAnimationFrame(this.loop),this}stop(){return this.running?(this.running=!1,this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null),this):this}reset(){return this.stop(),this.time=0,this.delta=0,this.frame=0,this.fps=0,this}getState(){return{time:this.time,delta:this.delta,frame:this.frame,running:this.running,fps:Math.round(this.fps)}}tick(e=0){return this.delta=e,this.time+=e,this.frame++,this.callback&&this.callback(this.getState()),this}setTime(e){return this.time=e,this}destroy(){this.reset(),this.callback=null}setMaxFps(e){return this.maxFps=e,this}loop(e){if(!this.running)return;if(this.maxFps>0){const n=1e3/this.maxFps;if(e-this.lastTime<n){this.rafId=requestAnimationFrame(this.loop);return}}this.delta=(e-this.lastTime)/1e3,this.lastTime=e;const t=this.delta>0?1/this.delta:0;this.fps=this.fps*.95+t*.05,this.time=(e-this.startTime)/1e3,this.frame++,this.callback&&this.callback(this.getState()),this.rafId=requestAnimationFrame(this.loop)}}class M{constructor(e){a(this,"gl");a(this,"vao",null);a(this,"vbo",null);a(this,"ibo",null);a(this,"vertexCount",0);a(this,"indexCount",0);a(this,"useIndices",!1);a(this,"vaoExt",null);a(this,"isWebGL2");this.gl=e,this.isWebGL2=e instanceof WebGL2RenderingContext,this.isWebGL2||(this.vaoExt=e.getExtension("OES_vertex_array_object"))}static fullscreenQuad(e){const t=new M(e),n=new Float32Array([-1,-1,0,0,1,-1,1,0,-1,1,0,1,1,1,1,1]),i=new Uint16Array([0,1,2,2,1,3]);return t.setup(n,i),t}setup(e,t){const n=this.gl;return this.createVAO(),this.bindVAO(),this.vbo=n.createBuffer(),n.bindBuffer(n.ARRAY_BUFFER,this.vbo),n.bufferData(n.ARRAY_BUFFER,e,n.STATIC_DRAW),this.vertexCount=e.length/4,t&&(this.ibo=n.createBuffer(),n.bindBuffer(n.ELEMENT_ARRAY_BUFFER,this.ibo),n.bufferData(n.ELEMENT_ARRAY_BUFFER,t,n.STATIC_DRAW),this.indexCount=t.length,this.useIndices=!0),this.unbindVAO(),this}linkAttributes(e){const t=this.gl;this.bindVAO(),t.bindBuffer(t.ARRAY_BUFFER,this.vbo);const n=4*Float32Array.BYTES_PER_ELEMENT,i=this.getPositionLocation(e);i>=0&&(t.enableVertexAttribArray(i),t.vertexAttribPointer(i,2,t.FLOAT,!1,n,0));const r=this.getTexcoordLocation(e);return r>=0&&(t.enableVertexAttribArray(r),t.vertexAttribPointer(r,2,t.FLOAT,!1,n,2*Float32Array.BYTES_PER_ELEMENT)),this.useIndices&&t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,this.ibo),this.unbindVAO(),this}bind(){return this.bindVAO(),this}unbind(){return this.unbindVAO(),this}draw(){const e=this.gl;return this.bindVAO(),this.useIndices?e.drawElements(e.TRIANGLES,this.indexCount,e.UNSIGNED_SHORT,0):e.drawArrays(e.TRIANGLE_STRIP,0,this.vertexCount),this}destroy(){const e=this.gl;this.deleteVAO(),this.vbo&&(e.deleteBuffer(this.vbo),this.vbo=null),this.ibo&&(e.deleteBuffer(this.ibo),this.ibo=null)}getPositionLocation(e){let t=e.getAttribLocation("a_position");return t>=0||(t=e.getAttribLocation("aPosition"),t>=0)||(t=e.getAttribLocation("position"),t>=0)?t:-1}getTexcoordLocation(e){let t=e.getAttribLocation("a_texcoord");return t>=0||(t=e.getAttribLocation("aTexCoord"),t>=0)||(t=e.getAttribLocation("texcoord"),t>=0)||(t=e.getAttribLocation("a_uv"),t>=0)?t:-1}createVAO(){this.isWebGL2?this.vao=this.gl.createVertexArray():this.vaoExt&&(this.vao=this.vaoExt.createVertexArrayOES())}bindVAO(){this.vao&&(this.isWebGL2?this.gl.bindVertexArray(this.vao):this.vaoExt&&this.vaoExt.bindVertexArrayOES(this.vao))}unbindVAO(){this.isWebGL2?this.gl.bindVertexArray(null):this.vaoExt&&this.vaoExt.bindVertexArrayOES(null)}deleteVAO(){this.vao&&(this.isWebGL2?this.gl.deleteVertexArray(this.vao):this.vaoExt&&this.vaoExt.deleteVertexArrayOES(this.vao),this.vao=null)}}class le{constructor(e){a(this,"gl");a(this,"program",null);a(this,"vertexShader",null);a(this,"fragmentShader",null);this.gl=e}compile(e,t){return this.destroy(),this.vertexShader=this.compileShader("vertex",e),this.fragmentShader=this.compileShader("fragment",t),this.linkProgram(),this}use(){return this.program&&this.gl.useProgram(this.program),this}getProgram(){return this.program}getAttribLocation(e){return this.program?this.gl.getAttribLocation(this.program,e):-1}getUniformLocation(e){return this.program?this.gl.getUniformLocation(this.program,e):null}destroy(){const e=this.gl;this.program&&(this.vertexShader&&e.detachShader(this.program,this.vertexShader),this.fragmentShader&&e.detachShader(this.program,this.fragmentShader),e.deleteProgram(this.program),this.program=null),this.vertexShader&&(e.deleteShader(this.vertexShader),this.vertexShader=null),this.fragmentShader&&(e.deleteShader(this.fragmentShader),this.fragmentShader=null)}compileShader(e,t){const n=this.gl,i=e==="vertex"?n.VERTEX_SHADER:n.FRAGMENT_SHADER,r=n.createShader(i);if(!r)throw new w(e,t,"Failed to create shader object");if(n.shaderSource(r,t),n.compileShader(r),!n.getShaderParameter(r,n.COMPILE_STATUS)){const o=n.getShaderInfoLog(r)||"Unknown error";throw n.deleteShader(r),new w(e,t,o)}return r}linkProgram(){const e=this.gl;if(!this.vertexShader||!this.fragmentShader)throw new _("Shaders not compiled");const t=e.createProgram();if(!t)throw new _("Failed to create program object");if(e.attachShader(t,this.vertexShader),e.attachShader(t,this.fragmentShader),e.linkProgram(t),!e.getProgramParameter(t,e.LINK_STATUS)){const i=e.getProgramInfoLog(t)||"Unknown error";throw e.deleteProgram(t),new _(i)}this.program=t}}class k{constructor(e,t){a(this,"name");a(this,"method");a(this,"isArray");a(this,"isMatrix");a(this,"location",null);a(this,"locationResolved",!1);a(this,"value");this.name=e,this.value=t;const n=k.inferMethodInfo(t);this.method=n.method,this.isArray=n.isArray,this.isMatrix=n.isMatrix}static inferMethodInfo(e){if(typeof e=="boolean")return{method:"uniform1i",isArray:!1,isMatrix:!1};if(typeof e=="number")return{method:"uniform1f",isArray:!1,isMatrix:!1};if(!Array.isArray(e))return{method:"uniform1f",isArray:!1,isMatrix:!1};const t=e.length,n=e[0];if(Array.isArray(n))switch(n.length){case 2:return{method:"uniform2fv",isArray:!0,isMatrix:!1};case 3:return{method:"uniform3fv",isArray:!0,isMatrix:!1};case 4:return{method:"uniform4fv",isArray:!0,isMatrix:!1};default:return{method:"uniform1fv",isArray:!0,isMatrix:!1}}switch(t){case 2:return{method:"uniform2fv",isArray:!1,isMatrix:!1};case 3:return{method:"uniform3fv",isArray:!1,isMatrix:!1};case 4:return{method:"uniform4fv",isArray:!1,isMatrix:!1};case 9:return{method:"uniformMatrix3fv",isArray:!1,isMatrix:!0};case 16:return{method:"uniformMatrix4fv",isArray:!1,isMatrix:!0};default:return{method:"uniform1fv",isArray:!0,isMatrix:!1}}}resolveLocation(e,t){return this.locationResolved||(this.location=e.getUniformLocation(t,this.name),this.locationResolved=!0),this.location}invalidateLocation(){this.location=null,this.locationResolved=!1}setValue(e){this.value=e}getValue(){return this.value}upload(e,t){const n=this.resolveLocation(e,t);if(n===null)return;const i=this.value;let r;switch(typeof i=="boolean"?r=i?1:0:typeof i=="number"?r=i:this.isArray&&Array.isArray(i[0])?r=new Float32Array(i.flat()):r=new Float32Array(i),this.method){case"uniform1f":e.uniform1f(n,r);break;case"uniform1i":e.uniform1i(n,r);break;case"uniform1fv":e.uniform1fv(n,r);break;case"uniform2fv":e.uniform2fv(n,r);break;case"uniform3fv":e.uniform3fv(n,r);break;case"uniform4fv":e.uniform4fv(n,r);break;case"uniformMatrix2fv":e.uniformMatrix2fv(n,!1,r);break;case"uniformMatrix3fv":e.uniformMatrix3fv(n,!1,r);break;case"uniformMatrix4fv":e.uniformMatrix4fv(n,!1,r);break}}}class E{constructor(e){a(this,"parsed",null);this.source=e}parse(){if(this.parsed)return this.parsed;const e=this.detectVersion(),t=this.detectImports(),n=this.detectUniforms(),i=this.detectFunctions(n);return this.parsed={version:e,imports:t,uniforms:n,functions:i}}isParsed(){return this.parsed!==null}setSource(e){this.source=e,this.parsed=null}version(){return this.detectVersion()}detectVersion(){return/^\s*#version\s+300\s+es/m.test(this.source)?2:1}detectImports(){const e=/^[ \t]*#import\s+(\w+)(?:\s+as\s+(\w+))?\s+from\s+["'](.+)["']/gm,t=/^[ \t]*[^\w\s]?import\b/gm,n=[],i=new Set;let r,s=1,o=0;for(;(r=e.exec(this.source))!==null;){s+=(this.source.substring(o,r.index).match(/\n/g)||[]).length,o=r.index,i.add(s);const f=r[1],c=r[2]||r[1],m=r[3];if(n.some(d=>d.alias===c))throw new $(c,s);n.push({name:f,alias:c,module:m,line:s})}let l;for(;(l=t.exec(this.source))!==null;){const f=(this.source.substring(0,l.index).match(/\n/g)||[]).length+1;if(i.has(f))continue;const c=this.source.split(`
|
|
6
|
+
`)[f-1].trim();throw new P(f,this.diagnoseImport(c))}return n}diagnoseImport(e){const t=e.match(/^([^\w\s])import\b/);if(t&&t[1]!=="#")return`Invalid prefix '${t[1]}'. Expected: #import <function> from '<module>'`;if(/^import\b/.test(e))return"Missing '#' prefix. Expected: #import <function> from '<module>'";if(/^#import\s+from\b/.test(e))return"Missing function name. Expected: #import <function> from '<module>'";if(/^#import\s+\w+\s*$/.test(e))return`Missing 'from' clause. Expected: #import ${e.split(/\s+/)[1]} from '<module>'`;if(/^#import\s+\w+\s+as\s*$/.test(e)||/^#import\s+\w+\s+as\s+from\b/.test(e))return`Missing alias name after 'as'. Expected: #import ${e.split(/\s+/)[1]} as <alias> from '<module>'`;if(/^#import\s+\w+\s+as\s+\w+\s*$/.test(e)){const n=e.split(/\s+/);return`Missing 'from' clause. Expected: #import ${n[1]} as ${n[3]} from '<module>'`}if(/^#import\s+\w+(?:\s+as\s+\w+)?\s+from\s+\w+/.test(e)){const n=e.match(/from\s+(\S+)/);return`Module name must be quoted. Expected: from '${n==null?void 0:n[1]}'`}return"Invalid syntax. Expected: #import <function> from '<module>'"}detectUniforms(){const e=/^[ \t]*uniform\s+(?:(?:highp|mediump|lowp)\s+)?(\w+)\s+(\w+)(?:\[(\d+)\])?\s*;/gm,t=[];let n,i=1,r=0;for(;(n=e.exec(this.source))!==null;){i+=(this.source.substring(r,n.index).match(/\n/g)||[]).length,r=n.index;const s=n[1],o=n[2],l=n[3]?parseInt(n[3],10):void 0;t.push({name:o,type:s,line:i,arrayNum:l})}return t}detectFunctions(e){const t=[],n="void|float|int|uint|bool|vec[234]|ivec[234]|uvec[234]|bvec[234]|mat[234](?:x[234])?|sampler2D|samplerCube|sampler3D|sampler2DArray",i=new RegExp(`^[ \\t]*(${n})\\s+(\\w+)\\s*\\(([^)]*)\\)\\s*\\{`,"gm");let r;for(;(r=i.exec(this.source))!==null;){const s=r[1],o=r[2],l=r[3].trim(),f=r.index,c=(this.source.substring(0,f).match(/\n/g)||[]).length+1,m=this.source.indexOf("{",f),d=this.findClosingBrace(this.source,m);if(d===-1)continue;const v=this.source.slice(m,d+1),J=this.parseParams(l),Z=this.findFunctionCalls(v),ee=this.findUniformCalls(v,e),te=this.findMentionCalls(v);t.push({name:o,type:s,params:J,body:v,dependencies:[...Z,...ee,...te],line:c})}return t}parseParams(e){if(!e.trim())return[];const t=[],n=e.split(",");for(const i of n){const r=i.trim();if(!r)continue;const o=r.replace(/\b(in|out|inout|const|highp|mediump|lowp)\b\s*/g,"").trim().match(/^(\w+)\s+(\w+)(?:\[\d*\])?$/);o&&t.push({type:o[1],name:o[2]})}return t}findClosingBrace(e,t){let n=0,i=!1,r=!1,s=!1,o=!1;for(let l=t;l<e.length;l++){const f=e[l],c=e[l+1],m=e[l-1];if(!r&&!o&&f==="/"&&c==="/"){s=!0;continue}if(s&&f===`
|
|
7
|
+
`){s=!1;continue}if(!r&&!s&&f==="/"&&c==="*"){o=!0,l++;continue}if(o&&f==="*"&&c==="/"){o=!1,l++;continue}if(!(s||o)){if(f==='"'&&m!=="\\"){r=!r;continue}if(!r){if(f==="{")n++,i=!0;else if(f==="}"&&(n--,i&&n===0))return l}}}return-1}findFunctionCalls(e){const t=[],n=new Set(["if","else","for","while","do","switch","case","return","break","continue","discard"]),i=/\b([a-zA-Z_]\w*)\s*\(/g;let r;for(;(r=i.exec(e))!==null;){const s=r[1];n.has(s)||t.push({name:s,type:"function",index:r.index})}return t}findUniformCalls(e,t){const n=[];for(const i of t){const r=new RegExp(`\\b${i.name}\\b`,"g");let s;for(;(s=r.exec(e))!==null;)n.push({name:i.name,type:"uniform",index:s.index})}return n}findMentionCalls(e){const t=[],n=/@(\w+)\.([a-zA-Z_]\w*)/g;let i;for(;(i=n.exec(e))!==null;){const r=i[1],s=i[2];t.push({name:`${r}.${s}`,type:"mention",index:i.index})}return t}}class K{constructor(e){a(this,"isCompiled",!1);a(this,"original");a(this,"compiled");a(this,"requirements",{uniforms:new Map,functions:new Map});this.original=new E(e),this.compiled=new E(e)}version(){return this.original.version()}source(){return this.original.source}recompile(){return this.isCompiled=!1,this.compile()}compile(e){return this.isCompiled?this.compiled.source:(this.original.parse().imports.length>0&&this.processImports(e),this.compiled.setSource(this.build()),this.isCompiled=!0,this.compiled.source)}processImports(e){const t=this.original.parse(),n=t.functions.flatMap(i=>i.dependencies.filter(r=>r.type==="mention").map(r=>({name:r.name.split(".")[0],uniform:r.name.split(".")[1]})));for(const i of t.imports){const r=b.resolve(i.module),s=r.extract(i.name);let o=n.filter(f=>f.name===s.function.name);if(o.length>0){const f=r.getDefinition().uniforms;if(o=o.filter(c=>{const m=f.find(d=>d.name===`u_${c.uniform}`||d.name===c.uniform);if(m){s.dependencies.uniforms.some(v=>v.name===m.name)||s.dependencies.uniforms.push(m);const d=n.indexOf(c);return d>-1&&n.splice(d,1),!1}return!0}),o.length>0)throw new H(i.module,s.function.name,o[0].uniform)}const l=r.copy();this.processExtraction(s,i.alias,l.options),e==null||e.merge(i.module,l)}if(n.length>0)throw new q(n[0].name,n[0].uniform)}processExtraction(e,t,n={}){const i=e.function,r=Math.random().toString(36).substring(2,8),s=`${t}_${r}`;for(let l=e.dependencies.functions.length-1;l>=0;l--){const f=e.dependencies.functions[l],c=this.rewriteFunction(f,t,{uniforms:e.dependencies.uniforms,functions:e.dependencies.functions,unique:s});this.requirements.functions.set(c.name,c)}const o=this.rewriteFunction(i,t,{uniforms:e.dependencies.uniforms,functions:e.dependencies.functions,rename:!0,unique:s});this.requirements.functions.set(o.name,o);for(const l of e.dependencies.uniforms){if(R.has(l.name))continue;const f={...l,name:`${s}_${l.name}${l.arrayNum?`[${l.arrayNum}]`:""}`};if(n[i.name]){const c=Object.entries(n[i.name]).find(([m,d])=>d.uniform===l.name);c&&(c[1].uniform=`${s}_${l.name}`)}this.requirements.uniforms.set(f.name,f)}n[i.name]&&t!==i.name&&(n[t]=n[i.name],delete n[i.name])}rewriteFunction(e,t,n={rename:!1,uniforms:[],functions:[],unique:""}){const i=new Set(n.uniforms.map(c=>c.name)),r=new Set(n.functions.map(c=>c.name)),s=[],o=n.unique?n.unique:t;for(const c of e.dependencies)if(c.index!==void 0)if(c.type==="uniform"&&i.has(c.name)){if(R.has(c.name))continue;s.push({index:c.index,oldText:c.name,newText:`${o}_${c.name}`})}else c.type==="function"&&r.has(c.name)&&s.push({index:c.index,oldText:c.name,newText:`${o}_${c.name}`});const l=this.applyRewrites(e.body,s),f=n.rename?t:`${o}_${e.name}`;return{...e,name:f,body:l}}applyRewrites(e,t){const n=[...t].sort((r,s)=>s.index-r.index);let i=e;for(const r of n)i=i.slice(0,r.index)+r.newText+i.slice(r.index+r.oldText.length);return i}build(){const e=this.original.parse();let t=this.original.source;t=this.removeImportLines(t,e);const n=this.findInsertionPointForUniforms(t),i=this.generateUniformsCode();i&&(t=t.slice(0,n)+i+`
|
|
8
8
|
`+t.slice(n));const r=this.findInsertionPointForFunctions(t),s=this.generateFunctionCode();return s&&(t=t.slice(0,r)+s+t.slice(r)),t=t.replace(/\n{3,}/g,`
|
|
9
9
|
|
|
10
|
-
`),t=this.replaceMentions(t,e),t}replaceMentions(e,t){let n=e;const i=t.functions.filter(r=>r.dependencies.some(s=>s.type==="mention"));for(const r of i){const s=r.dependencies.filter(
|
|
11
|
-
`),i=new Set(t.imports.map(r=>r.line));return n.filter((r,s)=>{const
|
|
12
|
-
`)}findInsertionPointForUniforms(e){const t=new
|
|
13
|
-
`);let r=0;if(n&&n.line)r=n.line;else for(let
|
|
14
|
-
`);let r=0;if(n&&n.line)r=n.line-2;else throw new
|
|
10
|
+
`),t=this.replaceMentions(t,e),t}replaceMentions(e,t){let n=e;const i=t.functions.filter(r=>r.dependencies.some(s=>s.type==="mention"));for(const r of i){const s=r.dependencies.filter(o=>o.type==="mention");for(const o of s){const l=o.name.split("."),f=new RegExp(`\\b${l[0]}_(\\w+)_${l[1]}\\b`,"g"),c=this.requirements.uniforms.keys().find(d=>{var v;return((v=d.match(f))==null?void 0:v[0])===d});if(!c)throw new j(o.name,r.name);const m=new RegExp(`@\\b${o.name}\\b`,"g");n=n.replace(m,c)}}return n}removeImportLines(e,t){const n=e.split(`
|
|
11
|
+
`),i=new Set(t.imports.map(r=>r.line));return n.filter((r,s)=>{const o=i.has(s+1);if(!o&&r.trim()===""&&s>0){const l=s-1;if(i.has(l+1))return!1}return!o}).join(`
|
|
12
|
+
`)}findInsertionPointForUniforms(e){const t=new E(e).parse(),n=t.uniforms.find(o=>o.line===Math.max(...t.uniforms.map(l=>l.line??0))),i=e.split(`
|
|
13
|
+
`);let r=0;if(n&&n.line)r=n.line;else for(let o=0;o<i.length;o++){const l=i[o].trim();if(l.startsWith("#version")){r=o+1;continue}if(l.startsWith("precision ")){r=o+1;continue}if(l===""||l.startsWith("//")){r===o&&(r=o+1);continue}break}let s=0;for(let o=0;o<r;o++)s+=i[o].length+1;return s}findInsertionPointForFunctions(e){const t=new E(e).parse(),n=t.functions.find(o=>o.line===Math.min(...t.functions.map(l=>l.line??1/0))),i=e.split(`
|
|
14
|
+
`);let r=0;if(n&&n.line)r=n.line-2;else throw new I;let s=0;for(let o=0;o<r;o++)s+=i[o].length+1;return s}generateUniformsCode(){const e=[];if(this.requirements.uniforms.size>0)for(const t of this.checkUniformsPresence())e.push(`uniform ${t.type} ${t.name};`);return e.length===0?"":e.join(`
|
|
15
15
|
`)+`
|
|
16
16
|
`}generateFunctionCode(){const e=[];if(this.requirements.functions.size>0)for(const t of this.checkFunctionsPresence()){const n=t.params.map(i=>`${i.type} ${i.name}`).join(", ");e.push(`
|
|
17
17
|
${t.type} ${t.name}(${n}) ${t.body}`)}return e.length===0?"":e.join(`
|
|
18
18
|
`)+`
|
|
19
|
-
`}checkUniformsPresence(){const e=this.original.parse(),t=[],n=this.requirements.uniforms;for(const[i,r]of n){const s=e.uniforms.find(
|
|
19
|
+
`}checkUniformsPresence(){const e=this.original.parse(),t=[],n=this.requirements.uniforms;for(const[i,r]of n){const s=e.uniforms.find(o=>o.name===i);if(!s){t.push(r);continue}if(s.type!==r.type)throw new A("uniform",i,r.type,s.type)}return t}checkFunctionsPresence(){const e=this.original.parse(),t=[],n=this.requirements.functions;for(const[i,r]of n){const s=e.functions.find(o=>o.name===i);if(!s){t.push(r);continue}if(s.type!==r.type)throw new A("function",i,r.type,s.type)}return t}}class g extends K{constructor(t,n,i={}){super(n);a(this,"name");a(this,"options",{});this.name=t,this.options=this.resolveOptions(i)}resolveOptions(t){if(!(t!=null&&t.default))return t||{};const n=this.original.parse(),i=t.default;for(const r of n.functions)if(!(r.name==="main"||r.name==="default"))if(t[r.name]){const s=t[r.name];for(const o in i)o in s||(s[o]=i[o])}else t[r.name]={...i};return delete t.default,t||{}}static define(t){const{name:n,source:i,options:r}=t;if(n==="sandbox"||n.startsWith("sandbox/"))throw new W(n);const s=new g(n,i,r);if(b.has(n))throw new z(n);return b.register(n,s),s}static resolve(t){return b.resolve(t)}copy(t="original"){return new g(this.name,this[t].source,JSON.parse(JSON.stringify(this.options)))}merge(t){this.options=this.options||{};const n=this.getDefinition().uniforms.map(i=>i.name);for(const[i,r]of Object.entries(t.options??{}))if(!this.options[i])this.options[i]=r;else for(const[s,o]of Object.entries(r))n.includes(o.uniform)||(this.options[i][s]=o)}getDefinition(){return this.compile(),{name:this.name,methods:this.compiled.parse().functions.map(t=>t.name).filter(t=>t!=="main"&&t!=="default"),uniforms:this.compiled.parse().uniforms.map(t=>({name:t.name,type:t.type})),options:this.options}}extract(t){if(this.compile(),t==="main")throw new N(this.name);if(t==="default")throw new G(this.name);const n=this.compiled.parse(),i=n.functions.find(o=>o.name===t);if(!i)throw new B(this.name,t);const r=new Map,s=new Map;return this.collectDependencies({current:i,scope:{functions:n.functions,uniforms:n.uniforms},collected:{functions:r,uniforms:s},visited:new Set([t])}),{function:i,dependencies:{functions:Array.from(r.values()),uniforms:Array.from(s.values())}}}collectDependencies(t){for(const n of t.current.dependencies)if(n.type==="function"){if(t.visited.has(n.name))continue;const i=t.scope.functions.find(r=>r.name===n.name);i&&(t.visited.add(n.name),t.collected.functions.set(n.name,i),this.collectDependencies({current:i,scope:{functions:t.scope.functions,uniforms:t.scope.uniforms},collected:{functions:t.collected.functions,uniforms:t.collected.uniforms},visited:t.visited}))}else if(n.type==="uniform"){const i=t.scope.uniforms.find(r=>r.name===n.name);i&&!t.collected.uniforms.has(n.name)&&t.collected.uniforms.set(n.name,i)}}}class Q{constructor(e=[]){a(this,"modules",new Map);e.forEach(t=>{this.register(t.name,t)})}compile(){this.modules.forEach(e=>{e.compile()})}available(){return Array.from(this.modules.values()).map(e=>e.getDefinition())}defaults(){const e={};return this.modules.forEach(t=>{const n=t.getDefinition();if(n.options)for(const i in n.options){const r=n.options[i];for(const s in r){const o=r[s];o.default!==void 0&&!n.uniforms.map(l=>l.name).includes(o.uniform)&&(e[o.uniform]=o.default)}}}),e}resolveOptions(e){for(const t of this.modules.values())if(t.options&&t.options[e])return t.options[e];return null}register(e,t){this.modules.set(e,t)}merge(e,t){if(!this.modules.has(e))return this.register(e,t);const n=this.modules.get(e);n.merge(t),this.modules.set(e,n)}resolve(e){const t=this.modules.get(e);if(!t)throw new D(e);return t}has(e){return this.modules.has(e)}isEmpty(){return this.modules.size===0}remove(e){this.modules.delete(e)}load(e){e.forEach(t=>{this.register(t.name,t)})}clear(){this.modules.clear()}}const ce=`// ─── Constants ──────────────────────────────────────────────
|
|
20
20
|
|
|
21
21
|
const float PI = 3.14159265359;
|
|
22
22
|
const float TAU = 6.28318530718;
|
|
@@ -225,7 +225,7 @@ vec2 voronoi(vec2 p) {
|
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
void main() {}
|
|
228
|
-
`,
|
|
228
|
+
`,ue=`/**
|
|
229
229
|
* Hex integer to RGB.
|
|
230
230
|
* Usage: hex(0xFF6600) → orange
|
|
231
231
|
*/
|
|
@@ -324,7 +324,7 @@ vec3 iridescent(vec2 uv, float time, float speed) {
|
|
|
324
324
|
}
|
|
325
325
|
|
|
326
326
|
void main() {}
|
|
327
|
-
`,
|
|
327
|
+
`,fe=`// ─── Time Shapers ──────────────────────────────────────────
|
|
328
328
|
// Convert raw time (u_time) to normalized 0–1 range.
|
|
329
329
|
// Output feeds directly into easing functions.
|
|
330
330
|
|
|
@@ -446,7 +446,7 @@ float teleport(float t) {
|
|
|
446
446
|
}
|
|
447
447
|
|
|
448
448
|
void main() {}
|
|
449
|
-
`,
|
|
449
|
+
`,he=`#import hash from 'sandbox'
|
|
450
450
|
#import noise from 'sandbox'
|
|
451
451
|
#import fbm from 'sandbox'
|
|
452
452
|
#import voronoi from 'sandbox'
|
|
@@ -641,7 +641,7 @@ vec2 cells(vec2 uv, float intensity) {
|
|
|
641
641
|
}
|
|
642
642
|
|
|
643
643
|
void main() {}
|
|
644
|
-
`,
|
|
644
|
+
`,de=`#import hash from 'sandbox'
|
|
645
645
|
|
|
646
646
|
uniform float u_intensity;
|
|
647
647
|
|
|
@@ -828,7 +828,7 @@ vec3 arcade(vec3 color, vec2 uv, float intensity) {
|
|
|
828
828
|
}
|
|
829
829
|
|
|
830
830
|
void main() {}
|
|
831
|
-
`,w=new J([new v("sandbox",ue),new v("sandbox/colors",fe),new v("sandbox/time",he),new v("sandbox/effects",de,{default:{intensity:{uniform:"u_intensity",default:1}},pixelate:{intensity:{uniform:"u_intensity",default:20}},twist:{intensity:{uniform:"u_intensity",default:1}},ripple:{intensity:{uniform:"u_intensity",default:1}},fisheye:{intensity:{uniform:"u_intensity",default:1}},wobble:{intensity:{uniform:"u_intensity",default:1}},organic:{intensity:{uniform:"u_intensity",default:3}},glitch:{intensity:{uniform:"u_intensity",default:1}},mirror:{intensity:{uniform:"u_intensity",default:0}},kaleidoscope:{intensity:{uniform:"u_intensity",default:6}},zoom:{intensity:{uniform:"u_intensity",default:1}},warp:{intensity:{uniform:"u_intensity",default:1}},displace:{intensity:{uniform:"u_intensity",default:1}},shatter:{intensity:{uniform:"u_intensity",default:10}},cells:{intensity:{uniform:"u_intensity",default:8}},glass:{intensity:{uniform:"u_intensity",default:1}}}),new v("sandbox/filters",me,{default:{intensity:{uniform:"u_intensity",default:1}},posterize:{intensity:{uniform:"u_intensity",default:8}},threshold:{intensity:{uniform:"u_intensity",default:.5}},grain:{intensity:{uniform:"u_intensity",default:.1}},vignette:{intensity:{uniform:"u_intensity",default:1.4}},glow:{intensity:{uniform:"u_intensity",default:.5}},gamma:{intensity:{uniform:"u_intensity",default:2.2}},dither:{intensity:{uniform:"u_intensity",default:4}},highlights:{intensity:{uniform:"u_intensity",default:.5}}})]),y=new J,S=new Map([["u_resolution","vec2"],["u_time","float"],["u_delta","float"],["u_mouse","vec2"],["u_frame","int"]]);class pe{constructor(e){o(this,"gl");o(this,"program",null);o(this,"uniforms",new Map);this.gl=e}attachProgram(e){this.program=e;for(const t of this.uniforms.values())t.invalidateLocation();return this}set(e,t){const n=this.uniforms.get(e);return n?n.setValue(t):this.uniforms.set(e,new T(e,t)),this}setMany(e){for(const[t,n]of Object.entries(e))this.set(t,n);return this}get(e){var t;return(t=this.uniforms.get(e))==null?void 0:t.getValue()}has(e){return this.uniforms.has(e)}delete(e){return this.uniforms.delete(e)}uploadAll(){if(!this.program)return this;for(const e of this.uniforms.values())e.upload(this.gl,this.program);return this}uploadBuiltIns(e,t,n){if(this.set("u_resolution",t),this.set("u_time",e.time),this.set("u_delta",e.delta),this.set("u_mouse",n),this.set("u_frame",e.frame),!this.program)return this;for(const i of S.keys()){const r=this.uniforms.get(i);r&&r.upload(this.gl,this.program)}return this}clear(){this.uniforms.clear()}destroy(){this.uniforms.clear(),this.program=null}keys(){return this.uniforms.keys()}get size(){return this.uniforms.size}}class x{constructor(e,t,n,i){o(this,"name");o(this,"gl");o(this,"texture",null);o(this,"location",null);o(this,"locationResolved",!1);o(this,"source");o(this,"options");o(this,"dynamicOverride");o(this,"needsUpload",!0);o(this,"needsReupload",!1);this.gl=e,this.name=t,this.source=n,this.dynamicOverride=i==null?void 0:i.dynamic,this.options=x.resolveOptions(n,i),this.needsReupload=this.options.dynamic}setSource(e){this.source=e,this.needsUpload=!0,this.needsReupload=this.dynamicOverride??x.isDynamicSource(e)}resolveLocation(e,t){return this.locationResolved||(this.location=e.getUniformLocation(t,this.name),this.locationResolved=!0),this.location}invalidateLocation(){this.location=null,this.locationResolved=!1}upload(e,t){const n=this.gl,i=this.resolveLocation(n,e);if(i!==null){if(!this.texture){if(this.texture=n.createTexture(),!this.texture)return;this.needsUpload=!0}n.activeTexture(n.TEXTURE0+t),n.bindTexture(n.TEXTURE_2D,this.texture),(this.needsUpload||this.needsReupload)&&(this.uploadPixels(),this.needsUpload=!1),n.uniform1i(i,t)}}destroy(){this.texture&&(this.gl.deleteTexture(this.texture),this.texture=null),this.location=null,this.locationResolved=!1}uploadPixels(){const e=this.gl;e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,this.options.flipY),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,this.source),this.applyParameters()}applyParameters(){const e=this.gl;e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,x.resolveWrap(e,this.options.wrapS)),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,x.resolveWrap(e,this.options.wrapT)),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,this.options.minFilter==="nearest"?e.NEAREST:e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,this.options.magFilter==="nearest"?e.NEAREST:e.LINEAR)}static resolveWrap(e,t){switch(t){case"repeat":return e.REPEAT;case"mirror":return e.MIRRORED_REPEAT;case"clamp":default:return e.CLAMP_TO_EDGE}}static resolveOptions(e,t){const n=(t==null?void 0:t.wrap)??"clamp";return{wrap:n,wrapS:(t==null?void 0:t.wrapS)??n,wrapT:(t==null?void 0:t.wrapT)??n,minFilter:(t==null?void 0:t.minFilter)??"linear",magFilter:(t==null?void 0:t.magFilter)??"linear",flipY:(t==null?void 0:t.flipY)??!0,dynamic:(t==null?void 0:t.dynamic)??x.isDynamicSource(e)}}static isDynamicSource(e){return e instanceof HTMLVideoElement}}class ve{constructor(e){o(this,"gl");o(this,"program",null);o(this,"textures",new Map);this.gl=e}attachProgram(e){this.program=e;for(const t of this.textures.values())t.invalidateLocation();return this}set(e,t,n){const i=this.textures.get(e);return i?i.setSource(t):this.textures.set(e,new x(this.gl,e,t,n)),this}get(e){return this.textures.get(e)}has(e){return this.textures.has(e)}delete(e){const t=this.textures.get(e);return t?(t.destroy(),this.textures.delete(e)):!1}uploadAll(){if(!this.program)return this;let e=0;for(const t of this.textures.values())t.upload(this.program,e),e++;return this}get size(){return this.textures.size}destroy(){for(const e of this.textures.values())e.destroy();this.textures.clear(),this.program=null}}class C{constructor(){o(this,"hooks",new Map)}id(){return Math.random().toString(36).substring(2,10)}add(e){const t=this.id();return this.hooks.set(t,e),()=>this.remove(t)}remove(e){this.hooks.delete(e)}run(e){for(const[t,n]of this.hooks)try{n(e)===!1&&this.remove(t)}catch(i){throw new K(t,i instanceof Error?i.message:String(i))}}destroy(){this.hooks.clear()}}class L{constructor(e,t){o(this,"canvas");o(this,"gl");o(this,"options");o(this,"onBeforeHooks",new C);o(this,"onAfterHooks",new C);o(this,"_program");o(this,"_geometry");o(this,"_uniforms");o(this,"_textures");o(this,"_clock");o(this,"_resolution",[1,1]);o(this,"_mouse",[0,0]);o(this,"_version",1);o(this,"playing",!1);this.canvas=e,this.options=t,this.gl=this.initContext(),this.enableExtensions(),this._program=new ce(this.gl),this._geometry=k.fullscreenQuad(this.gl),this._uniforms=new pe(this.gl),this._textures=new ve(this.gl),this._clock=new le,this.options.fps&&this._clock.setMaxFps(this.options.fps),this.options.onBeforeRender&&this.onBeforeHooks.add(this.options.onBeforeRender),this.options.onAfterRender&&this.onAfterHooks.add(this.options.onAfterRender),this.onRender=this.onRender.bind(this)}static setup(e,t){const n=new L(e,t);return t.vertex&&t.fragment&&n.shader(t.vertex,t.fragment),t.uniforms&&n._uniforms.setMany(t.uniforms),t.textures&&n.texturesFromSchema(t.textures),y.isEmpty()||n._uniforms.setMany(y.defaults()),n}initContext(){const e={antialias:this.options.antialias,preserveDrawingBuffer:this.options.preserveDrawingBuffer,alpha:!0,depth:!1,stencil:!1},t=this.canvas.getContext("webgl2",e);if(t)return this._version=2,t;const n=this.canvas.getContext("webgl",e);if(n)return this._version=1,n;const i=new V;throw this.options.onError(i),i}enableExtensions(){this.gl.getExtension("OES_standard_derivatives"),this.gl.getExtension("OES_texture_float"),this.gl.getExtension("OES_texture_float_linear"),this._version===1&&this.gl.getExtension("OES_vertex_array_object")}viewport(e,t,n,i){return this.canvas.width=n,this.canvas.height=i,this.gl.viewport(e,t,n,i),this._resolution=[n,i],this}clock(e){return this._clock.setTime(e),this}mouse(e,t){return this._mouse=[e,t],this}uniform(e,t){return this._uniforms.set(e,t),this}uniforms(e){return this._uniforms.setMany(e),this}getUniform(e){return this._uniforms.get(e)}texture(e,t,n){return this._textures.set(e,t,n),this}texturesFromSchema(e){for(const[t,n]of Object.entries(e))if(n instanceof HTMLImageElement||n instanceof HTMLCanvasElement||n instanceof HTMLVideoElement||n instanceof ImageBitmap||n instanceof ImageData||n instanceof OffscreenCanvas)this._textures.set(t,n);else{const{source:i,...r}=n;this._textures.set(t,i,r)}return this}removeTexture(e){return this._textures.delete(e),this}shader(e,t){try{if(y.clear(),e.version()!==t.version())throw new I(e.version(),t.version());this._program.compile(e.source(),t.compile()),this._version=t.version(),this._geometry.linkAttributes(this._program);const n=this._program.getProgram();n&&(this._uniforms.attachProgram(n),this._textures.attachProgram(n));try{this.options.onLoad()}catch(i){throw new Y(i instanceof Error?i.message:String(i))}}catch(n){n instanceof h&&this.options.onError(n)}return this}play(){return this.playing?this:(this.playing=!0,this._clock.start(this.onRender),this)}pause(){if(!this.playing)return this;const e=this._clock.getState();try{this.onBeforeHooks.run(e)}catch(t){t instanceof h&&this.options.onError(t)}this.playing=!1,this._clock.stop();try{this.onAfterHooks.run(e)}catch(t){t instanceof h&&this.options.onError(t)}return this}render(){return this.onRender(this._clock.getState()),this}getContext(){return this.gl}getVersion(){return this._version}getClock(){return this._clock}destroy(){this.pause(),this._clock.destroy(),this._geometry.destroy(),this._program.destroy(),this._uniforms.destroy(),this._textures.destroy(),this.onAfterHooks.destroy(),this.onBeforeHooks.destroy(),y.clear()}onRender(e){const t=this.gl;try{this.onBeforeHooks.run(e)}catch(n){n instanceof h&&this.options.onError(n)}t.clearColor(0,0,0,0),t.clear(t.COLOR_BUFFER_BIT),this._program.use(),this._uniforms.uploadBuiltIns(e,this._resolution,this._mouse),this._uniforms.uploadAll(),this._textures.uploadAll(),this._geometry.bind(),this._geometry.draw();try{this.onAfterHooks.run(e)}catch(n){n instanceof h&&this.options.onError(n)}}}class m extends Q{constructor(e){super(e),S.forEach((t,n)=>{this.requirements.uniforms.set(n,{name:n,type:t,line:0})})}}const A=`#ifdef GL_ES
|
|
831
|
+
`,b=new Q([new g("sandbox",ce),new g("sandbox/colors",ue),new g("sandbox/time",fe),new g("sandbox/effects",he,{default:{intensity:{uniform:"u_intensity",default:1}},pixelate:{intensity:{uniform:"u_intensity",default:20}},twist:{intensity:{uniform:"u_intensity",default:1}},ripple:{intensity:{uniform:"u_intensity",default:1}},fisheye:{intensity:{uniform:"u_intensity",default:1}},wobble:{intensity:{uniform:"u_intensity",default:1}},organic:{intensity:{uniform:"u_intensity",default:3}},glitch:{intensity:{uniform:"u_intensity",default:1}},mirror:{intensity:{uniform:"u_intensity",default:0}},kaleidoscope:{intensity:{uniform:"u_intensity",default:6}},zoom:{intensity:{uniform:"u_intensity",default:1}},warp:{intensity:{uniform:"u_intensity",default:1}},displace:{intensity:{uniform:"u_intensity",default:1}},shatter:{intensity:{uniform:"u_intensity",default:10}},cells:{intensity:{uniform:"u_intensity",default:8}},glass:{intensity:{uniform:"u_intensity",default:1}}}),new g("sandbox/filters",de,{default:{intensity:{uniform:"u_intensity",default:1}},posterize:{intensity:{uniform:"u_intensity",default:8}},threshold:{intensity:{uniform:"u_intensity",default:.5}},grain:{intensity:{uniform:"u_intensity",default:.1}},vignette:{intensity:{uniform:"u_intensity",default:1.4}},glow:{intensity:{uniform:"u_intensity",default:.5}},gamma:{intensity:{uniform:"u_intensity",default:2.2}},dither:{intensity:{uniform:"u_intensity",default:4}},highlights:{intensity:{uniform:"u_intensity",default:.5}}})]),R=new Map([["u_resolution","vec2"],["u_time","float"],["u_delta","float"],["u_mouse","vec2"],["u_frame","int"]]);class me{constructor(e){a(this,"gl");a(this,"program",null);a(this,"uniforms",new Map);this.gl=e}attachProgram(e){this.program=e;for(const t of this.uniforms.values())t.invalidateLocation();return this}set(e,t){const n=this.uniforms.get(e);return n?n.setValue(t):this.uniforms.set(e,new k(e,t)),this}setMany(e){for(const[t,n]of Object.entries(e))this.set(t,n);return this}get(e){var t;return(t=this.uniforms.get(e))==null?void 0:t.getValue()}has(e){return this.uniforms.has(e)}delete(e){return this.uniforms.delete(e)}uploadAll(){if(!this.program)return this;for(const e of this.uniforms.values())e.upload(this.gl,this.program);return this}uploadBuiltIns(e,t,n){if(this.set("u_resolution",t),this.set("u_time",e.time),this.set("u_delta",e.delta),this.set("u_mouse",n),this.set("u_frame",e.frame),!this.program)return this;for(const i of R.keys()){const r=this.uniforms.get(i);r&&r.upload(this.gl,this.program)}return this}clear(){this.uniforms.clear()}destroy(){this.uniforms.clear(),this.program=null}keys(){return this.uniforms.keys()}get size(){return this.uniforms.size}}class x{constructor(e,t,n,i){a(this,"name");a(this,"gl");a(this,"texture",null);a(this,"location",null);a(this,"locationResolved",!1);a(this,"source");a(this,"options");a(this,"dynamicOverride");a(this,"needsUpload",!0);a(this,"needsReupload",!1);this.gl=e,this.name=t,this.source=n,this.dynamicOverride=i==null?void 0:i.dynamic,this.options=x.resolveOptions(n,i),this.needsReupload=this.options.dynamic}setSource(e){this.source=e,this.needsUpload=!0,this.needsReupload=this.dynamicOverride??x.isDynamicSource(e)}resolveLocation(e,t){return this.locationResolved||(this.location=e.getUniformLocation(t,this.name),this.locationResolved=!0),this.location}invalidateLocation(){this.location=null,this.locationResolved=!1}upload(e,t){const n=this.gl,i=this.resolveLocation(n,e);if(i!==null){if(!this.texture){if(this.texture=n.createTexture(),!this.texture)return;this.needsUpload=!0}n.activeTexture(n.TEXTURE0+t),n.bindTexture(n.TEXTURE_2D,this.texture),(this.needsUpload||this.needsReupload)&&(this.uploadPixels(),this.needsUpload=!1),n.uniform1i(i,t)}}destroy(){this.texture&&(this.gl.deleteTexture(this.texture),this.texture=null),this.location=null,this.locationResolved=!1}uploadPixels(){const e=this.gl;e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,this.options.flipY),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,this.source),this.applyParameters()}applyParameters(){const e=this.gl;e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,x.resolveWrap(e,this.options.wrapS)),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,x.resolveWrap(e,this.options.wrapT)),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,this.options.minFilter==="nearest"?e.NEAREST:e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,this.options.magFilter==="nearest"?e.NEAREST:e.LINEAR)}static resolveWrap(e,t){switch(t){case"repeat":return e.REPEAT;case"mirror":return e.MIRRORED_REPEAT;case"clamp":default:return e.CLAMP_TO_EDGE}}static resolveOptions(e,t){const n=(t==null?void 0:t.wrap)??"clamp";return{wrap:n,wrapS:(t==null?void 0:t.wrapS)??n,wrapT:(t==null?void 0:t.wrapT)??n,minFilter:(t==null?void 0:t.minFilter)??"linear",magFilter:(t==null?void 0:t.magFilter)??"linear",flipY:(t==null?void 0:t.flipY)??!0,dynamic:(t==null?void 0:t.dynamic)??x.isDynamicSource(e)}}static isDynamicSource(e){return e instanceof HTMLVideoElement}}class pe{constructor(e){a(this,"gl");a(this,"program",null);a(this,"textures",new Map);this.gl=e}attachProgram(e){this.program=e;for(const t of this.textures.values())t.invalidateLocation();return this}set(e,t,n){const i=this.textures.get(e);return i?i.setSource(t):this.textures.set(e,new x(this.gl,e,t,n)),this}get(e){return this.textures.get(e)}has(e){return this.textures.has(e)}delete(e){const t=this.textures.get(e);return t?(t.destroy(),this.textures.delete(e)):!1}uploadAll(){if(!this.program)return this;let e=0;for(const t of this.textures.values())t.upload(this.program,e),e++;return this}get size(){return this.textures.size}destroy(){for(const e of this.textures.values())e.destroy();this.textures.clear(),this.program=null}}class L{constructor(){a(this,"hooks",new Map)}id(){return Math.random().toString(36).substring(2,10)}add(e){const t=this.id();return this.hooks.set(t,e),()=>this.remove(t)}remove(e){this.hooks.delete(e)}run(e){for(const[t,n]of this.hooks)try{n(e)===!1&&this.remove(t)}catch(i){throw new Y(t,i instanceof Error?i.message:String(i))}}destroy(){this.hooks.clear()}}class T{constructor(e,t){a(this,"canvas");a(this,"gl");a(this,"options");a(this,"onBeforeHooks",new L);a(this,"onAfterHooks",new L);a(this,"_program");a(this,"_geometry");a(this,"_uniforms");a(this,"_textures");a(this,"_clock");a(this,"_resolution",[1,1]);a(this,"_mouse",[0,0]);a(this,"_version",1);a(this,"_runtimeModules",new Q);a(this,"playing",!1);this.canvas=e,this.options=t,this.gl=this.initContext(),this.enableExtensions(),this._program=new le(this.gl),this._geometry=M.fullscreenQuad(this.gl),this._uniforms=new me(this.gl),this._textures=new pe(this.gl),this._clock=new ae,this.options.fps&&this._clock.setMaxFps(this.options.fps),this.options.onBeforeRender&&this.onBeforeHooks.add(this.options.onBeforeRender),this.options.onAfterRender&&this.onAfterHooks.add(this.options.onAfterRender),this.onRender=this.onRender.bind(this)}static setup(e,t){const n=new T(e,t);return t.vertex&&t.fragment&&n.shader(t.vertex,t.fragment),t.uniforms&&n._uniforms.setMany(t.uniforms),t.textures&&n.texturesFromSchema(t.textures),n._runtimeModules.isEmpty()||n._uniforms.setMany(n._runtimeModules.defaults()),n}initContext(){const e={antialias:this.options.antialias,preserveDrawingBuffer:this.options.preserveDrawingBuffer,alpha:!0,depth:!1,stencil:!1},t=this.canvas.getContext("webgl2",e);if(t)return this._version=2,t;const n=this.canvas.getContext("webgl",e);if(n)return this._version=1,n;const i=new O;throw this.options.onError(i),i}enableExtensions(){this.gl.getExtension("OES_standard_derivatives"),this.gl.getExtension("OES_texture_float"),this.gl.getExtension("OES_texture_float_linear"),this._version===1&&this.gl.getExtension("OES_vertex_array_object")}viewport(e,t,n,i){return this.canvas.width=n,this.canvas.height=i,this.gl.viewport(e,t,n,i),this._resolution=[n,i],this}clock(e){return this._clock.setTime(e),this}mouse(e,t){return this._mouse=[e,t],this}uniform(e,t){return this._uniforms.set(e,t),this}uniforms(e){return this._uniforms.setMany(e),this}getUniform(e){return this._uniforms.get(e)}texture(e,t,n){return this._textures.set(e,t,n),this}texturesFromSchema(e){for(const[t,n]of Object.entries(e))if(n instanceof HTMLImageElement||n instanceof HTMLCanvasElement||n instanceof HTMLVideoElement||n instanceof ImageBitmap||n instanceof ImageData||n instanceof OffscreenCanvas)this._textures.set(t,n);else{const{source:i,...r}=n;this._textures.set(t,i,r)}return this}removeTexture(e){return this._textures.delete(e),this}shader(e,t){try{if(this._runtimeModules.clear(),e.version()!==t.version())throw new V(e.version(),t.version());this._program.compile(e.source(),t.compile(this._runtimeModules)),this._version=t.version(),this._geometry.linkAttributes(this._program);const n=this._program.getProgram();n&&(this._uniforms.attachProgram(n),this._textures.attachProgram(n));try{this.options.onLoad()}catch(i){throw new X(i instanceof Error?i.message:String(i))}}catch(n){n instanceof h&&this.options.onError(n)}return this}play(){return this.playing?this:(this.playing=!0,this._clock.start(this.onRender),this)}pause(){if(!this.playing)return this;const e=this._clock.getState();try{this.onBeforeHooks.run(e)}catch(t){t instanceof h&&this.options.onError(t)}this.playing=!1,this._clock.stop();try{this.onAfterHooks.run(e)}catch(t){t instanceof h&&this.options.onError(t)}return this}render(){return this.onRender(this._clock.getState()),this}getContext(){return this.gl}getUsingModules(){return this._runtimeModules}getVersion(){return this._version}getClock(){return this._clock}destroy(){this.pause(),this._clock.destroy(),this._geometry.destroy(),this._program.destroy(),this._uniforms.destroy(),this._textures.destroy(),this.onAfterHooks.destroy(),this.onBeforeHooks.destroy(),this._runtimeModules.clear()}onRender(e){const t=this.gl;try{this.onBeforeHooks.run(e)}catch(n){n instanceof h&&this.options.onError(n)}t.clearColor(0,0,0,0),t.clear(t.COLOR_BUFFER_BIT),this._program.use(),this._uniforms.uploadBuiltIns(e,this._resolution,this._mouse),this._uniforms.uploadAll(),this._textures.uploadAll(),this._geometry.bind(),this._geometry.draw();try{this.onAfterHooks.run(e)}catch(n){n instanceof h&&this.options.onError(n)}}}class p extends K{constructor(e){super(e),R.forEach((t,n)=>{this.requirements.uniforms.set(n,{name:n,type:t,line:0})})}}const S=`#ifdef GL_ES
|
|
832
832
|
precision mediump float;
|
|
833
833
|
#endif
|
|
834
834
|
|
|
@@ -841,7 +841,7 @@ void main() {
|
|
|
841
841
|
v_texcoord = a_texcoord;
|
|
842
842
|
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
843
843
|
}
|
|
844
|
-
`,
|
|
844
|
+
`,C=`#ifdef GL_ES
|
|
845
845
|
precision mediump float;
|
|
846
846
|
#endif
|
|
847
847
|
|
|
@@ -855,7 +855,7 @@ void main() {
|
|
|
855
855
|
vec3 color = vec3(uv.x, uv.y, 0.5 + 0.5 * sin(u_time));
|
|
856
856
|
gl_FragColor = vec4(color, 1.0);
|
|
857
857
|
}
|
|
858
|
-
`,
|
|
858
|
+
`,F=`#version 300 es
|
|
859
859
|
|
|
860
860
|
in vec2 a_position;
|
|
861
861
|
in vec2 a_texcoord;
|
|
@@ -865,7 +865,7 @@ out vec2 v_texcoord;
|
|
|
865
865
|
void main() {
|
|
866
866
|
v_texcoord = a_texcoord;
|
|
867
867
|
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
868
|
-
}`,
|
|
868
|
+
}`,ve=`#version 300 es
|
|
869
869
|
precision highp float;
|
|
870
870
|
|
|
871
871
|
uniform vec2 u_resolution;
|
|
@@ -879,5 +879,5 @@ void main() {
|
|
|
879
879
|
vec2 uv = gl_FragCoord.xy / u_resolution;
|
|
880
880
|
vec3 color = vec3(uv.x, uv.y, 0.5 + 0.5 * sin(u_time));
|
|
881
881
|
fragColor = vec4(color, 1.0);
|
|
882
|
-
}`;class U{constructor(e,t){
|
|
883
|
-
You can handle errors programmatically by providing an onError callback to suppress this log and implement custom fallback behavior.`)},onLoad:()=>{},onBeforeRender:null,onAfterRender:null,uniforms:{},modules:{},textures:{}};if(e!=null&&e.vertex&&(this.usingCustomVertex=!0),e!=null&&e.vertex&&!(e!=null&&e.fragment)){t.vertex=new
|
|
882
|
+
}`;class U{constructor(e,t){a(this,"listeners",[]);a(this,"canvasEl");a(this,"options");a(this,"engine");a(this,"usingCustomVertex",!1);if(this.canvasEl=e,this.options=this.resolveOptions(t),this.engine=T.setup(this.canvasEl,this.options),this.setupListeners(),this.setViewport(),this.options.modules)for(const[n,i]of Object.entries(this.options.modules))this.module(n,i);this.options.autoplay&&this.play()}static create(e,t){return new U(e,t)}static defineModule(e,t,n={}){g.define({name:e,source:t,options:n})}static availableModules(){return b.available()}static compile(e){return new p(e).compile()}resolveOptions(e){const t={vertex:new p(S),fragment:new p(C),autoplay:!0,pauseWhenHidden:!0,dpr:"auto",fps:0,preserveDrawingBuffer:!1,antialias:!0,onError:s=>{console.error("Oops!",s,`
|
|
883
|
+
You can handle errors programmatically by providing an onError callback to suppress this log and implement custom fallback behavior.`)},onLoad:()=>{},onBeforeRender:null,onAfterRender:null,uniforms:{},modules:{},textures:{}};if(e!=null&&e.vertex&&(this.usingCustomVertex=!0),e!=null&&e.vertex&&!(e!=null&&e.fragment)){t.vertex=new p(e.vertex);const s=t.vertex.version();t.fragment=new p(s===2?ve:C)}if(e!=null&&e.fragment&&!(e!=null&&e.vertex)){t.fragment=new p(e.fragment);const s=t.fragment.version();t.vertex=new p(s===2?F:S)}e!=null&&e.vertex&&(e!=null&&e.fragment)&&(t.vertex=new p(e.vertex),t.fragment=new p(e.fragment));const{vertex:n,fragment:i,...r}=e||{};return{...t,...r}}setupListeners(){this.listeners.push(y.on(window,"resize",()=>{this.setViewport()}),y.on(this.canvasEl,"resize",()=>{this.setViewport()}),(()=>{let e=!1;return y.on(document,"scroll",t=>{this.options.pauseWhenHidden&&(this.isInViewport()?e&&!this.isPlaying()&&(this.play(),e=!1):this.isPlaying()&&(this.pause(),e=!0))})})(),y.on(document,"mousemove",e=>{this.setMouse(e.clientX||e.pageX,e.clientY||e.pageY)}),y.on(document,"touchmove",e=>{e.touches.length>0&&this.setMouse(e.touches[0].clientX,e.touches[0].clientY)}))}destroyListeners(){this.listeners.forEach(e=>e()),this.listeners=[]}setViewport(){const e=this.options.dpr==="auto"?Math.min(2,window.devicePixelRatio||1):this.options.dpr,t=this.canvasEl.clientWidth||this.canvasEl.width||1,n=this.canvasEl.clientHeight||this.canvasEl.height||1;this.engine.viewport(0,0,Math.max(1,Math.floor(t*e)),Math.max(1,Math.floor(n*e)))}isInViewport(){const e=this.canvasEl.getBoundingClientRect();return e.bottom>=0&&e.right>=0&&e.top<=(window.innerHeight||document.documentElement.clientHeight)&&e.left<=(window.innerWidth||document.documentElement.clientWidth)}setMouse(e,t){const n=this.canvasEl.getBoundingClientRect();e>=n.left&&e<=n.right&&t>=n.top&&t<=n.bottom&&this.engine.mouse(e-n.left,t-n.top)}setUniform(e,t){return this.engine.uniform(e,t),this}setUniforms(e){return this.engine.uniforms(e),this}getUniform(e){return this.engine.getUniform(e)}setTexture(e,t,n){return this.engine.texture(e,t,n),this}setTextures(e){return this.engine.texturesFromSchema(e),this}removeTexture(e){return this.engine.removeTexture(e),this}setShader(e,t){return this.options.vertex=new p(e),this.options.fragment=new p(t),this.usingCustomVertex=!0,this.engine.shader(this.options.vertex,this.options.fragment),this}setFragment(e){const t=new p(e),n=t.version(),i=this.options.vertex.version();return this.options.fragment=t,n!==i&&(this.usingCustomVertex||(this.options.vertex=new p(n===2?F:S))),this.engine.shader(this.options.vertex,this.options.fragment),this}getFragment(){return this.options.fragment.source()}getVertex(){return this.options.vertex.source()}setFps(e){return this.engine.getClock().setMaxFps(e),this}hook(e,t="before"){return t==="before"?this.engine.onBeforeHooks.add(e):this.engine.onAfterHooks.add(e)}module(e,t){const i=this.engine.getUsingModules().resolveOptions(e);if(!i)return console.warn(`Sandbox: Counld not find options for '${e}' function. Make sure you used the correct imported name and the module is currently in use by the shader.`),this;for(const[r,s]of Object.entries(t)){const o=i[r];if(!o){console.warn(`Sandbox: Option '${r}' not found for function '${e}'. Make sure to check available options with Sandbox.availableModules() and provide the correct option name.`);continue}this.setUniform(o.uniform,s)}return this}play(){return this.engine.play(),this}playAt(e){return this.engine.clock(e),this.engine.play(),this}pause(){return this.engine.pause(),this}pauseAt(e){const t=this.hook(n=>{n.time>=e&&(t(),this.pause())},"after");return this}toggle(){return this.engine.playing?this.pause():this.play(),this}time(e){return this.engine.clock(e),this}render(){return this.engine.render(),this}renderAt(e){return this.engine.clock(e),this.engine.render(),this}isPlaying(){return this.engine.playing}get version(){return this.engine.getVersion()}get canvas(){return this.canvasEl}exportAsURL(e="image/png",t){return this.canvas.toDataURL(e,t)}exportAsBlob(e="image/png",t){return new Promise((n,i)=>{this.canvas.toBlob(r=>{r?n(r):i(new Error("Failed to create blob from canvas."))},e,t)})}exportAsImage(e="image/png",t){const n=new Image;return n.src=this.exportAsURL(e,t),n}stream(e){return this.canvasEl.captureStream(e)}destroy(){this.destroyListeners(),this.engine.destroy()}}exports.Sandbox=U;exports.SandboxAttemptedToImportDefaultFunctionError=G;exports.SandboxAttemptedToImportMainFunctionError=N;exports.SandboxContextCreationError=re;exports.SandboxError=h;exports.SandboxForbiddenModuleNameError=W;exports.SandboxGLSLShaderCompilationError=w;exports.SandboxMentionCouldNotBeReplacedError=j;exports.SandboxMentionFunctionNotFoundError=q;exports.SandboxMentionUniformNotFoundError=H;exports.SandboxModuleMethodNotFoundError=B;exports.SandboxModuleNotFoundError=D;exports.SandboxOnHookCallbackError=Y;exports.SandboxOnLoadCallbackError=X;exports.SandboxOverwriteModuleError=z;exports.SandboxProgramError=_;exports.SandboxShaderDuplicateImportNameError=$;exports.SandboxShaderImportSyntaxError=P;exports.SandboxShaderRequirementMismatchError=A;exports.SandboxShaderVersionMismatchError=V;exports.SandboxShaderWithoutFunctionError=I;exports.SandboxTextureCreationError=se;exports.SandboxTextureUnitLimitError=oe;exports.SandboxWebGLNotSupportedError=O;
|