UNPKG

@genart-api/core

Version:

Platform-independent extensible API for browser-based generative art

2 lines (1 loc) 17 kB
"use strict";(()=>{var vt=Object.defineProperty;var B=(e,t)=>{for(var r in t)vt(e,r,{get:t[r],enumerable:!0})};var q={};B(q,{clamp:()=>_,clamp01:()=>R,div:()=>F,easeInOut5:()=>W,fit:()=>K,mix:()=>T,norm:()=>M,parseNum:()=>G,round:()=>I,smoothstep:()=>jt,smoothstep01:()=>v});var G=(e,t=0)=>{let r=e?parseFloat(e):Number.NaN;return isNaN(r)?t:r},T=(e,t,r)=>e+(t-e)*r,K=(e,t,r,a,n)=>a+(n-a)*M(e,t,r),_=(e,t,r)=>e<t?t:e>r?r:e,R=e=>e<0?0:e>1?1:e,I=(e,t)=>Math.round(F(e,t))*t,M=(e,t,r)=>F(e-t,r-t),F=(e,t)=>t!=0?e/t:0,jt=(e,t,r)=>v(R(F(r-e,t-e))),v=e=>e*e*(3-2*e),zt=e=>{let t=2**(e-1);return r=>r<.5?t*r**e:1-(-2*r+2)**e/2},W=zt(5);var tt={};B(tt,{PARAM_DEFAULTS:()=>gt,bigint:()=>Gt,binary:()=>Kt,choice:()=>Z,color:()=>Wt,date:()=>qt,datetime:()=>Xt,image:()=>Ht,numlist:()=>Q,ramp:()=>Yt,range:()=>Jt,strlist:()=>Zt,text:()=>Qt,time:()=>te,toggle:()=>ee,vector:()=>re,weighted:()=>ae,xy:()=>ne});var O={};B(O,{ensure:()=>y,equiv:()=>J,equivArrayLike:()=>ft,equivObject:()=>dt,formatValuePrec:()=>Ot,hashBytes:()=>ct,hashString:()=>Ct,isBigInt:()=>E,isFunction:()=>S,isInRange:()=>c,isNumber:()=>u,isNumericArray:()=>h,isPrim:()=>X,isString:()=>p,isStringArray:()=>H,isTypedArray:()=>N,parseBigInt:()=>D,parseBigInt128:()=>pt,parseUUID:()=>Ut,stringifyBigInt:()=>Et,stringifyJSON:()=>Dt,u16:()=>V,u24:()=>Y,u32:()=>Vt,u8:()=>z,valuePrec:()=>lt});var j=0xfffffffffn,A=Math.imul,mt=Object.getPrototypeOf({}),y=(e,t)=>{if(!e)throw new Error(t);return e},E=e=>typeof e=="bigint",u=e=>typeof e=="number"&&!isNaN(e),p=e=>typeof e=="string",X=e=>{let t=typeof e;return t==="bigint"||t==="boolean"||t==="number"||t==="string"||t==="symbol"},S=e=>typeof e=="function",h=e=>N(e)||Array.isArray(e)&&e.every(u),H=e=>Array.isArray(e)&&e.every(p),N=e=>!!e&&(e instanceof Float32Array||e instanceof Float64Array||e instanceof Uint32Array||e instanceof Int32Array||e instanceof Uint8Array||e instanceof Int8Array||e instanceof Uint16Array||e instanceof Int16Array||e instanceof Uint8ClampedArray),c=(e,t,r)=>e>=t&&e<=r,z=e=>(e&=255,(e<16?"0":"")+e.toString(16)),V=e=>z(e>>>8)+z(e),Y=e=>V(e>>>8)+z(e&255),Vt=e=>V(e>>>16)+V(e),Et=(e,t=10)=>{let r={10:"",2:"0b",8:"0o",16:"0x"}[t];return e<0n?"-"+r+(-e).toString(t):r+e.toString(t)},D=e=>/^-0[box]/.test(e)?-BigInt(e.substring(1)):BigInt(e),pt=e=>new Uint32Array([Number(e>>96n&j),Number(e>>64n&j),Number(e>>32n&j),Number(e&j)]),Dt=e=>JSON.stringify(e,(t,r)=>E(r)?r.toString():N(r)?[...r]:r,4),lt=e=>{let t=e.toString(),r=t.indexOf(".");return r>0?t.length-r-1:0},Ot=e=>{let t=lt(e);return r=>r.toFixed(t)},J=(e,t)=>{let r;return e===t?!0:e==null?t==null:t==null?e==null:X(e)||X(t)||S(e)||S(t)?e===t||e!==e&&t!==t:e.length!=null&&t.length!=null?ft(e,t):(r=Object.getPrototypeOf(e),(r==null||r===mt)&&(r=Object.getPrototypeOf(t),r==null||r===mt)?dt(e,t):e instanceof Date&&t instanceof Date?e.getTime()===t.getTime():e instanceof RegExp&&t instanceof RegExp?e.toString()===t.toString():e===t)},dt=(e,t)=>{if(Object.keys(e).length!==Object.keys(t).length)return!1;for(let r in e)if(!(t.hasOwnProperty(r)&&J(e[r],t[r])))return!1;return!0},ft=(e,t)=>{if(e.length!==t.length)return!1;let r=e.length;for(;r-- >0&&J(e[r],t[r]););return r<0},Ut=e=>pt(BigInt("0x"+e.replace(/-/g,"").substring(0,32))),ct=(e,t=0)=>{let r=o=>e[o+3]<<24|e[o+2]<<16|e[o+1]<<8|e[o],a=(o,l)=>o<<l|o>>>32-l,n=(o,l)=>{let P=l+1&3;x[l]=A(a(x[l]^A(a(A(r(o),g[l]),15+l),g[P]),19-(l<<1))+x[P],5)+d[l]},i=o=>{let l=o[0]+=o[1]+o[2]+o[3];return o[1]+=l,o[2]+=l,o[3]+=l,o},s=o=>(o^=o>>>16,o=A(o,2246822507),o^=o>>>13,o=A(o,3266489909),o^=o>>>16),m=e.length,d=new Uint32Array([1444728091,197830471,2530024501,850148119]),g=new Uint32Array([597399067,2869860233,951274213,2716044179]),x=g.map(o=>o^t),b=0;for(let o=m&-16;b<o;b+=16)n(b,0),n(b+4,1),n(b+8,2),n(b+12,3);d.fill(0);for(let o=m&15;o>0;o--){let l=o-1;if((o&3)===1){let P=o>>2;d[P]=a(A(d[P]^e[b+l],g[P]),15+P),x[P]^=A(d[P],g[P+1&3])}else d[l>>2]^=e[b+l]<<(l<<3)}return i(i(x.map(o=>o^m)).map(s))},Ct=(e,t)=>ct(new TextEncoder().encode(e),t);var kt=/^\d{4}-\d{2}-\d{2}$/,U={validate:(e,t)=>t instanceof Date||u(t)||p(t)&&kt.test(t),coerce:(e,t)=>u(t)?new Date(t):p(t)?new Date(Date.parse(t)):t};var $t=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?(Z|[-+]\d{2}:\d{2})$/,C={validate:(e,t)=>t instanceof Date||u(t)||p(t)&&$t.test(t),coerce:(e,t)=>u(t)?new Date(t):p(t)?new Date(Date.parse(t)):t};var L={validate:(e,t)=>h(t)&&t.length===3&&c(t[0],0,23)&&c(t[1],0,59)&&c(t[2],0,59)||p(t)&&/^([01]\d|2[0-3]):[0-5]\d:[0-5]\d$/.test(t),coerce:(e,t)=>p(t)?t.split(":").map(G):t,randomize:(e,t)=>[t()*24|0,t()*60|0,t()*60|0]};var k={validate:(e,t)=>{let{min:r,max:a,size:n}=e;return h(t)&&t.length===n&&t.every((i,s)=>c(i,r[s],a[s]))},coerce:(e,t)=>{let{min:r,max:a,step:n}=e;return t.map((i,s)=>_(I(i,n[s]),r[s],a[s]))},randomize:(e,t)=>{let{min:r,max:a,size:n,step:i}=e;return new Array(n).fill(0).map((s,m)=>_(I(T(r[m],a[m],t()),i[m]),r[m],a[m]))}};var gt={desc:"TODO description",edit:"protected",group:"main",order:0,randomize:!0,state:"void",update:"event",widget:"default"},f=(e,t,r=!0)=>(y(t.name,"missing param `name`"),{...gt,type:e,randomize:r,...t}),ut=(e,t)=>t!=null?y(e.validate(null,t),`invalid default value: ${t}`)&&e.coerce(null,t):t,Pt=(e,t=10)=>{let r=0,a=e.maxLength||t;return e.minLength&&(r=e.minLength,e.maxLength||(a=Math.max(r,t))),y(r<=a,"invalid list length constraint"),[r,a]},Gt=e=>f("bigint",{min:0n,max:0xffffffffffffffffn,...e}),Kt=e=>f("binary",{minLength:0,maxLength:1024,...e},!1),Z=e=>f("choice",e),Wt=e=>f("color",e),qt=e=>f("date",{...e,default:ut(U,e.default)},!1),Xt=e=>f("datetime",{...e,default:ut(C,e.default)},!1),Ht=e=>f("image",{default:e.default||new(e.format==="gray"?Uint8Array:Uint32Array)(e.width*e.height),...e},!1),Q=e=>{let[t,r]=Pt(e,10);return f("numlist",{default:e.default||new Array(t).fill(0),minLength:t,maxLength:r,...e},!1)},Yt=e=>f("ramp",{...e,stops:e.stops?e.stops.flat():[0,0,1,1],mode:e.mode||"linear",default:0},!1),Jt=e=>f("range",{min:0,max:100,step:1,...e}),Zt=e=>{let[t,r]=Pt(e,10);return f("strlist",{default:e.default||new Array(t).fill(""),minLength:t,maxLength:r,...e},!1)},Qt=e=>f("text",{minLength:0,maxLength:32,multiline:!1,...e},!1),te=e=>f("time",{...e,default:e.default!=null?y(L.validate(null,e.default),"")&&L.coerce(null,e.default):e.default}),ee=e=>f("toggle",e),re=e=>{e.labels?y(e.labels.length>=e.size,`expected ${e.size} labels`):y(e.size<=4,"missing vector labels");let t=(a,n,i=0)=>Array.isArray(n)?(y(n.length===a,"wrong vector size"),n):new Array(a).fill(u(n)?n:i),r={min:t(e.size,e.min,0),max:t(e.size,e.max,1),step:t(e.size,e.step,.01)};return f("vector",{...e,...r,default:e.default?y(e.default.length==e.size,`wrong vector size, expected ${e.size} values`)&&k.coerce(r,e.default):e.default,labels:e.labels||["X","Y","Z","W"].slice(0,e.size)})},ae=e=>f("weighted",{...e,options:e.options.sort((t,r)=>r[0]-t[0]),total:e.options.reduce((t,r)=>t+r[0],0)}),ne=e=>f("xy",e);var at={};B(at,{SFC32:()=>et,randomBigInt:()=>rt});var yt=4294967296,et=class e{constructor(t){this.seed=t;this.buf=new Uint32Array(4),this.buf.set(t),this.#t=()=>{let r=this.buf,a=(r[0]+r[1]>>>0)+r[3]>>>0;return r[3]=r[3]+1>>>0,r[0]=r[1]^r[1]>>>9,r[1]=r[2]+(r[2]<<3)>>>0,r[2]=(r[2]<<21|r[2]>>>11)+a>>>0,a/yt}}buf;#t;get rnd(){return this.#t}reset(){this.buf.set(this.seed)}copy(){return new e(this.buf.slice())}},rt=(e,t=Math.random)=>{S(t)||(t=t.rnd.bind(t));let r=0n;for(let a=Math.log2(Number(e))+31>>5;a-- >0;)r=r<<32n|BigInt(t()*yt>>>0);return r%e};var ht={validate:(e,t)=>{let{min:r,max:a}=e;if(p(t)){if(!/^-?([0-9]+|0x[0-9a-f]+|0b[01]+|0o[0-7]+)$/.test(t))return!1;t=D(t)}else if(u(t)||E(t))t=BigInt(t);else return!1;return t>=r&&t<=a},coerce:(e,t)=>p(t)?D(t):BigInt(t),randomize:(e,t)=>{let{min:r,max:a}=e;return r+rt(a-r,t)}};var xt={validate:(e,t)=>{let{minLength:r,maxLength:a}=e;return t instanceof Uint8Array&&t.length>=r&&t.length<=a}};var bt={validate:(e,t)=>!!e.options.find(r=>(p(r)?r:r[0])===t),randomize:(e,t)=>{let r=e.options,a=r[t()*r.length|0];return p(a)?a:a[0]}};var Tt={validate:(e,t)=>p(t)&&/^#?[0-9a-f]{6,8}$/i.test(t),coerce:(e,t)=>(t[0]!=="#"?"#"+t:t).substring(0,7),randomize:(e,t)=>"#"+Y(t()*16777216|0)};var _t={validate:(e,t)=>{let{width:r,height:a,format:n}=e;return N(t)&&t.length==r*a&&(n==="gray"?t instanceof Uint8Array||t instanceof Uint8ClampedArray:t instanceof Uint32Array)}};var It={validate:(e,t)=>{let{minLength:r,maxLength:a}=e;return h(t)&&c(t.length,r,a)}};var At={validate:()=>!1,read:(e,t)=>{let{stops:r,mode:a}=e,n=r.length,i=n;for(;(i-=2)>=0&&!(t>=r[i]););n-=2;let s=r[i],m=r[i+1],d=r[i+2],g=r[i+3];return i<0?r[1]:i>=n?r[n+1]:{exp:()=>T(m,g,W(M(t,s,d))),linear:()=>K(t,s,d,m,g),smooth:()=>T(m,g,v(M(t,s,d)))}[a||"linear"]()},params:{stops:Q({name:"Ramp stops",desc:"Control points",minLength:4,maxLength:1/0,default:[]}),mode:Z({name:"Ramp mode",desc:"Interpolation method",options:["linear","smooth","exp"]})}};var wt={validate:(e,t)=>{let{min:r,max:a}=e;return u(t)&&c(t,r,a)},coerce:(e,t)=>{let r=e;return _(I(t??r.default,r.step||1),r.min,r.max)},randomize:(e,t)=>{let{min:r,max:a,step:n}=e;return _(I(T(r,a,t()),n||1),r,a)}};var Rt={validate:(e,t)=>{let{minLength:r,maxLength:a,match:n}=e;if(!(H(t)&&c(t.length,r,a)))return!1;if(n){let i=p(n)?new RegExp(n):n;return t.every(s=>i.test(s))}return!0}};var Mt={validate:(e,t)=>{if(!p(t))return!1;let{minLength:r,maxLength:a,match:n}=e;return n&&!(p(n)?new RegExp(n):n).test(t)?!1:c(t.length,r,a)}};var St={validate:(e,t)=>p(t)?/^(true|false|0|1)$/.test(t):t===1||t===0||typeof t=="boolean",coerce:(e,t)=>t==="true"||t==="1"?!0:t==="false"||t==="0"?!1:!!t,randomize:(e,t)=>t()<.5};var Nt={validate:(e,t)=>!!e.options.find(r=>r[1]===t),randomize:(e,t)=>{let{options:r,total:a,default:n}=e,i=t()*a;for(let s=0,m=r.length;s<m;s++)if(a-=r[s][0],a<=i)return r[s][1];return n}};var Lt={validate:(e,t)=>h(t)&&t.length==2,coerce:(e,t)=>[R(t[0]),R(t[1])],randomize:(e,t)=>[t(),t()]};var Bt=(e=250,t=60,r=0)=>{let a=r,n=1e3/t,i=!1;return{start(){a=r-1,i=!0},stop(){i=!1},next(s){setTimeout(()=>{a++,i&&s(a*n,a)},e)},now:()=>[a*n,a]}};var nt=(e=0,t=0)=>{let r=performance.now(),a=t,n=e,i=!0,s=!1;return{start(){s=i=!0},stop(){s=!1},next(m){requestAnimationFrame(d=>{s&&(i?(r=d,a=t,i=!1):a++,n=e+d-r,m(n,a))})},now:()=>[n,a]}};var{ensure:w,isFunction:ie}=O,$=typeof window<"u",st=class{_opts={id:Math.floor(Math.random()*1e12).toString(36),allowExternalConfig:!1,notifyFrameUpdate:!1};_adapter;_time=nt();_prng;_update;_state="init";_traits;_params;_paramTypes={bigint:ht,binary:xt,choice:bt,color:Tt,date:U,datetime:C,image:_t,numlist:It,ramp:At,range:wt,strlist:Rt,text:Mt,time:L,toggle:St,vector:k,weighted:Nt,xy:Lt};math=q;params=tt;prng=at;utils=O;time={offline:Bt,raf:nt};constructor(){$&&window.addEventListener("message",t=>{let r=t.data;if(!(!this.isRecipient(t)||r?.__self))switch(r.type){case"genart:get-info":this.notifyInfo();break;case"genart:randomize-param":this.randomizeParamValue(r.paramID,r.key);break;case"genart:resume":this.start(!0);break;case"genart:configure":{if(!this._opts.allowExternalConfig)return;let a=r.opts;delete a.id,delete a.allowExternalConfig,this.configure(a);break}case"genart:set-param-value":this.setParamValue(r.paramID,r.value,r.key);break;case"genart:start":this.start();break;case"genart:stop":this.stop();break}})}get version(){return"0.33.0"}get id(){return this._opts.id}get mode(){return this._adapter?.mode||"play"}get collector(){return this._adapter?.collector}get iteration(){return this._adapter?.iteration}get screen(){return this._adapter?.screen||($?{width:window.innerWidth,height:window.innerHeight,dpr:window.devicePixelRatio||1}:{width:640,height:640,dpr:1})}get random(){return this._prng?this._prng:this._prng=Ft(this._adapter).prng}get seed(){return Ft(this._adapter).seed}get state(){return this._state}get paramSpecs(){return this._params}get adapter(){return this._adapter}get timeProvider(){return this._time}registerParamType(t,r){it(t),this._paramTypes[t]&&console.warn("overriding impl for param type:",t),this._paramTypes[t]=r}paramType(t){return it(t),this._paramTypes[t]}async setParams(t){try{this._adapter?.augmentParams&&(t=this._adapter.augmentParams(t)),this._params={};for(let r in t){ot(r);let a={...t.PARAM_DEFAULTS,...t[r]},n=this.ensureParamImpl(a.type);if(a.default==null)if(n.randomize)a.default=n.randomize(a,this.random.rnd),a.state="random";else if(n.read)a.state="dynamic";else throw new Error(`missing default value for param: ${r}`);else{if(!(n.read||n.validate(a,a.default)))throw new Error(`invalid default value for param: ${r} (${a.default})`);a.state="default"}this._params[r]=a}return this._adapter&&(this._adapter.initParams&&await this._adapter.initParams(this._params),await this.updateParams()),this.notifySetParams(),this.getParamValue.bind(this)}catch(r){throw this.setState("error",r.message),r}}setTraits(t){this._traits=t,this.emit({type:"genart:traits",traits:t})}setAdapter(t){this._adapter=t,this.notifyReady()}waitForAdapter(){return this.waitFor("_adapter")}setTimeProvider(t){this._time.stop(),this._time=t,["play","stop"].includes(this._state)?t.start():this.notifyReady()}waitForTimeProvider(){return this.waitFor("_time")}setUpdate(t){this._update=t,this.notifyReady()}async updateParams(t="none"){if(this._adapter)for(let r in this._params){let a=this._params[r],n=await this._adapter.updateParam(r,a);if(!n)continue;let{value:i,update:s}=n;if(s)for(let m in s)this.setParamValue(r,s[m],m,"none");this.setParamValue(r,i,void 0,i!=null||s?t:"none")}}setParamValue(t,r,a,n="all"){let{spec:i,impl:s}=this.ensureParam(t);if(r!=null){let m=i;if(a){let{spec:d,impl:g}=this.ensureNestedParam(i,a);m=d,s=g}if(!s.validate(m,r)){this.paramError(t);return}i[a||"value"]=s.coerce?s.coerce(m,r):r,a||(i.state="custom")}this.emit({type:"genart:param-change",__self:!0,param:this.asNestedParam(i),paramID:t,key:a},n)}randomizeParamValue(t,r,a=Math.random,n="all"){let{spec:i,impl:{randomize:s}}=this.ensureParam(t),m=s&&i.randomize!==!1;if(r){let{spec:d,impl:g}=this.ensureNestedParam(i,r),x=g.randomize&&d.randomize!==!1;x&&this.setParamValue(t,g.randomize(d,a),r,x||!m?n:"none")}m&&this.setParamValue(t,s(i,a),void 0,n)}getParamValue(t,r){return this.paramValueGetter(t)(r)}paramValueGetter(t){let{spec:r,impl:{randomize:a,read:n}}=this.ensureParam(t);return(i=0)=>{if(ie(i)){if(a)return a(r,i);i=0}return n?n(r,i):r.value??r.default}}paramError(t){this.emit({type:"genart:param-error",paramID:t})}configure(t){Object.assign(this._opts,t),this.notifyInfo()}on(t,r){w($,"current env has no messaging support"),window.addEventListener("message",a=>{this.isRecipient(a)&&a.data?.type===t&&r(a.data)})}emit(t,r="all"){if(!$||r==="none")return;t.apiID=this.id;let a=r==="all";(a||r==="self")&&window.postMessage(t,"*"),(a&&parent!==window||r==="parent")&&parent.postMessage(t,"*")}start(t=!1){let r=this._state;if(r=="play")return;if(r!=="ready"&&r!=="stop")throw new Error(`can't start in state: ${r}`);this.setState("play");let a={type:"genart:frame",__self:!0,apiID:this.id,time:0,frame:0},n=(i,s)=>{this._state=="play"&&(this._update.call(null,i,s)?this._time.next(n):this.stop(),this._opts.notifyFrameUpdate&&(a.time=i,a.frame=s,this.emit(a)))};t||this._time.start(),this._time.next(n),this.emit({type:`genart:${t?"resume":"start"}`,__self:!0})}stop(){this._state==="play"&&(this.setState("stop"),this.emit({type:"genart:stop",__self:!0}))}capture(t){this._adapter?.capture(t),this.emit({type:"genart:capture",__self:!0},"parent")}setState(t,r){this._state=t,this.emit({type:"genart:state-change",__self:!0,state:t,info:r})}ensureParam(t){ot(t);let r=w(w(this._params,"no params defined")[t],`unknown param: ${t}`);return{spec:r,impl:this.ensureParamImpl(r.type)}}ensureParamImpl(t){return it(t),w(this._paramTypes[t],`unknown param type: ${t}`)}ensureNestedParam(t,r){let a=w(this.ensureParamImpl(t.type).params?.[r],`param type '${t.type}' has no nested: ${r}`);return{spec:a,impl:this.ensureParamImpl(a.type)}}async waitFor(t){for(;!this[t];)await new Promise(r=>setTimeout(r,0));return this[t]}notifySetParams(){this._params&&Object.keys(this._params).length&&this.emit({type:"genart:params",__self:!0,params:this.asNestedParams({},this._params)})}notifyReady(){this._state==="init"&&this._adapter&&this._time&&this._update&&this.setState("ready")}notifyInfo(){let[t,r]=this._time.now(),{id:a,collector:n,iteration:i}=this._adapter??{};this.emit({type:"genart:info",opts:this._opts,state:this._state,version:this.version,seed:this.seed,adapter:a,collector:n,iteration:i,time:t,frame:r})}isRecipient({data:t}){return t!=null&&typeof t=="object"&&(t.apiID===this.id||t.apiID==="*")}asNestedParams(t,r){for(let a in r)t[a]=this.asNestedParam(r[a]);return t}asNestedParam(t){let r={...t},a=this._paramTypes[t.type];return a.params&&(r.__params=this.asNestedParams({},a.params)),r}},ot=(e,t="ID")=>w(!(e==="__proto__"||e==="prototype"||e==="constructor"),`illegal param ${t}: ${e}`),it=e=>ot(e,"type"),Ft=e=>w(e,"missing platform adapter");globalThis.$genart=new st;})();