wobnimo 0.1.4 → 0.2.0
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/AGENTS.md +18 -4
- package/README.md +38 -7
- package/dist/characters/bao.d.ts +6 -0
- package/dist/characters/bao.js +1 -0
- package/dist/characters/berry.d.ts +6 -0
- package/dist/characters/berry.js +1 -0
- package/dist/characters/boo.js +1 -1
- package/dist/characters/bumble.d.ts +6 -0
- package/dist/characters/bumble.js +1 -0
- package/dist/characters/cacti.d.ts +6 -0
- package/dist/characters/cacti.js +1 -0
- package/dist/characters/cap.d.ts +6 -0
- package/dist/characters/cap.js +1 -0
- package/dist/characters/drift.d.ts +6 -0
- package/dist/characters/drift.js +1 -0
- package/dist/characters/ember.d.ts +6 -0
- package/dist/characters/ember.js +1 -0
- package/dist/characters/hop.d.ts +6 -0
- package/dist/characters/hop.js +1 -0
- package/dist/characters/index.d.ts +11 -1
- package/dist/characters/index.js +11 -11
- package/dist/characters/inky.js +1 -1
- package/dist/characters/latte.d.ts +6 -0
- package/dist/characters/latte.js +1 -0
- package/dist/characters/microduck.js +1 -1
- package/dist/characters/miso.js +1 -1
- package/dist/characters/mochi.js +1 -1
- package/dist/characters/pebble.js +1 -1
- package/dist/characters/pip.js +1 -1
- package/dist/characters/rex.js +1 -1
- package/dist/characters/swirl.d.ts +6 -0
- package/dist/characters/swirl.js +1 -0
- package/dist/characters/tad.js +1 -1
- package/dist/characters/volt.js +1 -1
- package/dist/cli.js +1888 -0
- package/dist/element.d.ts +1 -1
- package/dist/element.js +9 -9
- package/dist/index-Cm5wWKoT.d.ts +12 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +6 -6
- package/dist/react.js +16 -16
- package/dist/wobnimo.js +12 -12
- package/package.json +14 -4
- package/skill/SKILL.md +719 -0
- package/skill/examples/bao.ts +73 -0
- package/skill/examples/berry.ts +97 -0
- package/skill/examples/boo.ts +87 -0
- package/skill/examples/bumble.ts +70 -0
- package/skill/examples/cacti.ts +79 -0
- package/skill/examples/cap.ts +59 -0
- package/skill/examples/drift.ts +74 -0
- package/skill/examples/ember.ts +78 -0
- package/skill/examples/hop.ts +66 -0
- package/skill/examples/inky.ts +168 -0
- package/skill/examples/latte.ts +73 -0
- package/skill/examples/microduck.ts +222 -0
- package/skill/examples/miso.ts +182 -0
- package/skill/examples/mochi.ts +78 -0
- package/skill/examples/pebble.ts +174 -0
- package/skill/examples/pip.ts +170 -0
- package/skill/examples/rex.ts +193 -0
- package/skill/examples/swirl.ts +69 -0
- package/skill/examples/tad.ts +117 -0
- package/skill/examples/volt.ts +214 -0
- package/skill/reference/recipes.md +551 -0
- package/skill/reference/spec.md +258 -0
- package/skill/templates/starter.ts +73 -0
- package/dist/index-DRDEWSGV.d.ts +0 -8
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { C as CharacterSpec } from './types-PAZ6PnKv.js';
|
|
2
|
+
|
|
3
|
+
/** The original ten, hand-built body plans, each chosen to stress the engine somewhere new. */
|
|
4
|
+
declare const originals: CharacterSpec[];
|
|
5
|
+
/** Ten more, each written as a spec from nothing but one sentence: the "describe it" cast. */
|
|
6
|
+
declare const described: CharacterSpec[];
|
|
7
|
+
/** The whole cast. */
|
|
8
|
+
declare const characters: CharacterSpec[];
|
|
9
|
+
/** Registers <wobnimo-mascot> with the whole cast: `<wobnimo-mascot character="pip">`. */
|
|
10
|
+
declare function defineWobnimoElement(tag?: string): void;
|
|
11
|
+
|
|
12
|
+
export { described as a, characters as c, defineWobnimoElement as d, originals as o };
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,10 @@ interface SnapshotOptions {
|
|
|
15
15
|
floor?: number;
|
|
16
16
|
palette?: Palette;
|
|
17
17
|
seed?: number;
|
|
18
|
+
/** Turns the character about its vertical axis, in radians: π/2 shows its left side, π its back. */
|
|
19
|
+
turn?: number;
|
|
20
|
+
/** How long the state has been held when the picture is taken, in seconds. Default 1.5. */
|
|
21
|
+
settle?: number;
|
|
18
22
|
}
|
|
19
23
|
/** Draws the character once onto a new canvas, resolving when the frame is there. */
|
|
20
24
|
declare function snapshot(spec: CharacterSpec, options?: SnapshotOptions): Promise<HTMLCanvasElement>;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
var C=()=>Y(new Float32Array(16));function Y(t){return t.fill(0),t[0]=t[5]=t[10]=t[15]=1,t}function _(t,e,o){let r=new Float32Array(16);for(let a=0;a<4;a++)for(let s=0;s<4;s++)r[a*4+s]=e[s]*o[a*4]+e[4+s]*o[a*4+1]+e[8+s]*o[a*4+2]+e[12+s]*o[a*4+3];return t.set(r),t}function ie(t,e,o,r){return Y(t),t[12]=e,t[13]=o,t[14]=r,t}function Ve(t,e,o,r){return Y(t),t[0]=e,t[5]=o,t[10]=r,t}function Z(t,e,o,r){let a=Math.cos(e),s=Math.sin(e),i=Math.cos(o),n=Math.sin(o),l=Math.cos(r),h=Math.sin(r);return Y(t),t[0]=l*i,t[1]=h*i,t[2]=-n,t[4]=l*n*s-h*a,t[5]=h*n*s+l*a,t[6]=i*s,t[8]=l*n*a+h*s,t[9]=h*n*a-l*s,t[10]=i*a,t}function ne(t,e,o){let[r,a,s]=e,i=Math.cos(o),n=Math.sin(o),l=1-i;return Y(t),t[0]=l*r*r+i,t[1]=l*r*a+n*s,t[2]=l*r*s-n*a,t[4]=l*r*a-n*s,t[5]=l*a*a+i,t[6]=l*a*s+n*r,t[8]=l*r*s+n*a,t[9]=l*a*s-n*r,t[10]=l*s*s+i,t}function be(t,e){let[o,r,a,s,i,n,l,h,f,c,m,d,u,y,w,x]=e,E=o*n-r*i,A=o*l-a*i,S=o*h-s*i,V=r*l-a*n,q=r*h-s*n,T=a*h-s*l,v=f*y-c*u,j=f*w-m*u,N=f*x-d*u,P=c*w-m*y,I=c*x-d*y,B=m*x-d*w,D=E*B-A*I+S*P+V*N-q*j+T*v;if(!D)return Y(t);let b=1/D;return t[0]=(n*B-l*I+h*P)*b,t[1]=(a*I-r*B-s*P)*b,t[2]=(y*T-w*q+x*V)*b,t[3]=(m*q-c*T-d*V)*b,t[4]=(l*N-i*B-h*j)*b,t[5]=(o*B-a*N+s*j)*b,t[6]=(w*S-u*T-x*A)*b,t[7]=(f*T-m*S+d*A)*b,t[8]=(i*I-n*N+h*v)*b,t[9]=(r*N-o*I-s*v)*b,t[10]=(u*q-y*S+x*E)*b,t[11]=(c*S-f*q-d*E)*b,t[12]=(n*j-i*P-l*v)*b,t[13]=(o*P-r*j+a*v)*b,t[14]=(y*A-u*V-w*E)*b,t[15]=(f*V-c*A+m*E)*b,t}function ye(t,e){let[o,r,a]=e;return [t[0]*o+t[4]*r+t[8]*a+t[12],t[1]*o+t[5]*r+t[9]*a+t[13],t[2]*o+t[6]*r+t[10]*a+t[14]]}function we(t,e){let[o,r,a]=e;return [t[0]*o+t[4]*r+t[8]*a,t[1]*o+t[5]*r+t[9]*a,t[2]*o+t[6]*r+t[10]*a]}var $=(t,e,o)=>Math.min(o,Math.max(e,t)),re=(t,e,o)=>t+(e-t)*o,ke=(t,e,o)=>{let r=$((o-t)/(e-t),0,1);return r*r*(3-2*r)},je=t=>t<.5?4*t*t*t:1-Math.pow(-2*t+2,3)/2;function Q(t){let e=Math.floor(t*4294967295)>>>0||1;return ()=>{e=e+1831565813>>>0;let o=e;return o=Math.imul(o^o>>>15,o|1),o^=o+Math.imul(o^o>>>7,o|61),((o^o>>>14)>>>0)/4294967296}}var k=class{constructor(e=0){this.x=e;}x;v=0;step(e,o,r,a){let s=r*Math.PI*2;return this.v+=(s*s*(e-this.x)-2*a*s*this.v)*o,this.x+=this.v*o,this.x}};var mt=[{round:0,open:1,weight:.34},{round:.08,open:.55,weight:.26},{round:.7,open:.85,weight:.24},{round:1,open:.5,weight:.16}],le=class{constructor(e){this.random=e;this.silence=.15+e()*.3;}random;open=0;round=0;age=0;length=0;stress=0;silence=0;syllablesLeft=0;wordsLeft=0;reset(){this.age=this.length=this.open=0,this.syllablesLeft=this.wordsLeft=0,this.silence=.12;}update(e){if(this.silence>0){this.silence-=e,this.open=0;return}this.age+=e,this.age>=this.length&&this.next();let o=$(this.age/this.length,0,1);this.open=this.stress*Math.pow(Math.sin(Math.PI*o),.55);}next(){let e=this.random;this.age=0;let o=this.syllablesLeft===0;o&&(this.wordsLeft===0?(this.wordsLeft=3+Math.floor(e()*5),this.silence=this.length>0?.45+e()*.7:0):this.silence=.04+e()*.09,this.wordsLeft--,this.syllablesLeft=1+Math.floor(Math.pow(e(),1.6)*3)),this.syllablesLeft--;let r=o&&e()<.6,a=dt(mt,e());this.length=.12+e()*.13,this.stress=a.open*(r?.85+e()*.15:.5+e()*.35),this.round=a.round;}};function dt(t,e){for(let o of t){if(e<o.weight)return o;e-=o.weight;}return t[0]}var L=["idle","thinking","listening","speaking","sleeping","working","error","surprised","celebrating","sad"],z=[...L,"happy"],ae=Object.fromEntries(z.map((t,e)=>[t,e])),Se={idle:{lid:.06,squint:0,smile:.35,tilt:0,energy:1,flap:.05,glow:[.45,.7,1],exposure:1,wide:0,asym:0},thinking:{lid:.4,squint:0,smile:-0.15,tilt:.22,energy:.6,flap:0,glow:[1,.55,.12],exposure:1,wide:0,asym:0},listening:{lid:0,squint:0,smile:.2,tilt:-0.08,energy:.8,flap:.05,glow:[.25,1,.5],exposure:1,wide:.15,asym:0},speaking:{lid:.04,squint:.1,smile:.45,tilt:0,energy:1.2,flap:.1,glow:[.35,.82,1],exposure:1,wide:0,asym:0},sleeping:{lid:1,squint:0,smile:0,tilt:0,energy:.35,flap:0,glow:[.08,.09,.18],exposure:.84,wide:0,asym:0},working:{lid:.3,squint:.2,smile:.05,tilt:0,energy:1.3,flap:.18,glow:[.6,.45,1],exposure:1,wide:0,asym:0},error:{lid:.12,squint:.15,smile:-0.45,tilt:.1,energy:.9,flap:.25,glow:[1,.16,.12],exposure:.97,wide:.2,asym:1},surprised:{lid:0,squint:0,smile:0,tilt:0,energy:1,flap:.55,glow:[.95,.95,1],exposure:1.04,wide:1,asym:0},celebrating:{lid:0,squint:1,smile:1,tilt:0,energy:1.8,flap:.9,glow:[1,.72,.2],exposure:1.08,wide:0,asym:0},sad:{lid:.42,squint:0,smile:-0.85,tilt:-0.32,energy:.35,flap:-0.12,glow:[.22,.32,.7],exposure:.9,wide:0,asym:0},happy:{lid:0,squint:1,smile:1,tilt:0,energy:1.6,flap:.3,glow:[1,.42,.72],exposure:1.05,wide:0,asym:0}};var ut={float:0,hop:.16,squash:1,snap:1,look:1,snapLook:0,talkSquash:0},ce=.11,vt=1.8,H=class{temperament;state="idle";pointer=null;shown="idle";previous="idle";switched=10;time=0;since=0;random;yaw=new k;pitch=new k;roll=new k;squash=new k;hover;face={lid:new k,squint:new k,smile:new k(.3),tilt:new k,talk:new k,round:new k,gazeX:new k,gazeY:new k,flap:new k,energy:new k(1),exposure:new k(1),wide:new k,asym:new k};weights;glow=[...Se.idle.glow];jump=null;look={yaw:0,pitch:0,x:0,y:0};saccade={x:0,y:0,next:0};nextLook=.6;nextBlink;blinkAge=-1;nextHop;nextSide=4;side=1;nextNod=2.5;shake={start:-10,amount:0,next:0};sigh={start:-10,next:0};reactUntil=-1;speech;lastTalk=0;syllableArmed=true;matrices={a:C(),b:C()};pose;constructor(e={},o=.5){this.temperament={...ut,...e},this.random=Q(o),this.speech=new le(this.random),this.nextBlink=1+this.random()*3,this.nextHop=6+this.random()*6,this.hover=new k(this.temperament.float),this.weights=Object.fromEntries(z.map(r=>[r,new k(r==="idle"?1:0)])),this.pose={root:C(),minScale:1,lift:0,channels:{yaw:0,pitch:0,roll:0,flap:0,talk:0,energy:1},weights:Object.fromEntries(z.map(r=>[r,r==="idle"?1:0])),expression:"idle",faceA:[0,0,0,0],faceB:[0,0,0,0],faceC:[0,0,1,0],faceD:[0,0,0,0],glow:this.glow,exposure:1,events:[]};}setState(e){e!==this.state&&(this.state=e,this.since=0,e==="speaking"&&this.speech.reset(),this.nextLook=0);}poke(){this.hop(this.temperament.hop*1.5,this.random()<.5?1:-1),this.reactUntil=this.time+vt;}update(e){if(!(e>0))return;let o=Math.max(1,Math.ceil(e/(1/120)));for(let r=0;r<o;r++)this.step(e/o);}enter(e,o){let r=this.temperament;e==="surprised"?(this.hop(r.hop*.6,0),this.pitch.v+=1.2,this.startShake(o,.35,1/0)):e==="error"?(this.side=this.random()<.5?1:-1,this.squash.v-=2.5,this.startShake(o,1,o+2+this.random())):e==="celebrating"?this.nextHop=o:e==="sad"&&(this.sigh.next=o+1.2);}startShake(e,o,r){this.shake.start=e,this.shake.amount=o,this.shake.next=r;}hop(e,o){if(this.jump)return;let r=this.temperament.float>0;this.jump={age:r?ce:0,height:e,spin:o,lean:(this.random()-.5)*.3,air:.42+e*.45+(r?.25:0),landed:false};}step(e){this.time+=e,this.since+=e,this.switched+=e;let o=this.time,r=this.random,a=this.temperament,s=this.pose.events,i=o<this.reactUntil?"happy":this.state;i!==this.shown&&(this.previous=this.shown,this.shown=i,this.switched=0,s.push(`enter:${i}`),this.enter(i,o));let n=Se[i];o>this.nextLook&&(this.look.yaw=(r()-.5)*.75,this.look.pitch=(r()-.5)*.24,this.look.x=$(this.look.yaw*2.2,-1,1),this.look.y=r()<.3?.6:r()<.2?-0.6:0,this.nextLook=o+re(1.4+r()*2.6,.45+r()*1.1,a.snapLook)),o>this.saccade.next&&(this.saccade.x=(r()-.5)*.22,this.saccade.y=(r()-.5)*.14,this.saccade.next=o+.25+r()*.7);let l=0,h=0,f=0,c=Math.sin(o*1.9)*.008,m=0,d=0,u=0,y=0,w=n.flap,x=1.3,E=.62,A=a.float,S=this.pointer,V=S&&(i==="idle"||i==="listening"||i==="speaking"||i==="surprised");switch(i){case "idle":l=this.look.yaw,h=this.look.pitch,f=-this.look.yaw*.16,m=this.look.x,d=this.look.y,o>this.nextHop&&(this.hop(a.hop*(.9+r()*.4),r()<.35?r()<.5?1:-1:0),this.nextHop=o+7+r()*7);break;case "thinking":{o>this.nextSide&&(this.side=-this.side,this.nextSide=o+3+r()*2);let g=this.side;l=.24*g+Math.sin(o*.9)*.05,h=.17+Math.sin(o*1.3)*.03,f=-0.13*g,m=.7*g,d=.8,x=.9;break}case "listening":l=-0.14,h=.02,f=.17,m=-0.2,o>this.nextNod&&(this.pitch.v-=.9,this.nextNod=o+2+r()*2.5);break;case "speaking":{l=Math.sin(o*.7)*.12,f=Math.sin(o*.9)*.05,this.speech.update(e),u=this.speech.open,y=this.speech.round,h=.04+u*.07,c+=u*.014,w+=Math.sin(o*2.6)*.1,x=1.8;break}case "sleeping":h=-0.3,f=.13,l=.06,c=Math.sin(o*1.15)*.016,u=.12+.1*Math.sin(o*1.15),y=.7,A*=.65,x=.55,E=.9,o>this.nextNod&&(this.pitch.v-=.5,this.nextNod=o+5+r()*4);break;case "working":l=Math.sin(o*.8)*.07,h=-0.13+Math.abs(Math.sin(o*5.2))*.03,f=Math.sin(o*.6)*.04,m=Math.sin(o*1.6)*.45,d=-0.55,w+=Math.sin(o*11)*.06,x=1.6;break;case "error":{o>this.shake.next&&this.startShake(o,.55,2.4+r()*1.4);let g=this.side;f=.16*g,l=-0.1*g,h=.05,m=.45*g,d=.3,u=.16,x=1.5;break}case "surprised":h=.1,u=.42,y=1,x=2.2,E=.5;break;case "celebrating":l=Math.sin(o*3.1)*.22,f=Math.sin(o*6.2)*.1,h=.14,u=.6+.12*Math.sin(o*7),y=.05,w+=Math.sin(o*9)*.25,x=2,o>this.nextHop&&(this.hop(a.hop*1.25,r()<.3?r()<.5?1:-1:0),this.nextHop=o+.85+r()*.4);break;case "sad":{o>this.sigh.next&&(this.sigh.start=o,this.sigh.next=o+4+r()*2.5);let g=Math.sin($((o-this.sigh.start)/1.7,0,1)*Math.PI);h=-0.24+g*.1,l=Math.sin(o*.3)*.1,f=.08,m=-0.15,d=-0.65+g*.3,c+=g*.018,A*=.7,x=.7,E=.85;break}case "happy":l=Math.sin(o*2.2)*.18,f=Math.sin(o*4.4)*.12,h=.12,u=.5+.15*Math.sin(o*8),y=.2,o>this.nextHop&&(this.hop(a.hop*1.05,0),this.nextHop=o+1.05+r()*.4);break}V&&S&&(l=$(S.x,-1,1)*.55,h=$(-S.y,-1,1)*.32+(i==="speaking"?u*.07:0),f=-l*.12+(i==="listening"?.12:0),m=$(S.x*2,-1,1),d=$(-S.y*1.5,-1,1)),i!=="sleeping"&&(m+=this.saccade.x,d+=this.saccade.y),a.float>0&&(c+=Math.sin(o*1.5)*.035);let q=re(x,x*3.2,a.snapLook)*a.snap,T=re(E,.95,a.snapLook);this.yaw.step(l*a.look,e,q,T),this.pitch.step(h*a.look,e,q,T),this.roll.step(f,e,x*a.snap,E),this.hover.step(A,e,.6,.8);let v=this.face;v.lid.step(n.lid,e,2.2,.9),v.squint.step(n.squint,e,3,.8),v.smile.step(n.smile,e,2.4,.75),v.tilt.step(n.tilt*this.side,e,1.6,.8),v.talk.step(u,e,14,.8),v.round.step(y,e,6,.8),v.gazeX.step(m,e,7,.85),v.gazeY.step(d,e,7,.85),v.flap.step(w,e,2.4*a.snap,.5),v.energy.step(n.energy,e,.8,1),v.exposure.step(n.exposure,e,.4,1),v.wide.step(n.wide,e,5,.6),v.asym.step(n.asym*this.side,e,3,.8);for(let g of z)this.weights[g].step(g===i?1:0,e,1.6*a.snap,.95);let j=1-Math.exp(-e*4),N=i==="thinking"?.55+.45*Math.sin(o*4.2):i==="speaking"?.6+.6*v.talk.x:i==="working"?.75+.25*Math.sin(o*7):i==="error"?Math.sin(o*7)>0?1.1:.45:1;for(let g=0;g<3;g++)this.glow[g]=re(this.glow[g],n.glow[g]*N,j);this.syllableArmed&&v.talk.x>.55&&this.lastTalk<=.55&&i==="speaking"&&(s.push("syllable"),this.syllableArmed=false),v.talk.x<.35&&(this.syllableArmed=true),this.lastTalk=v.talk.x;let P=0,I=0,B=0,D=0,b=this.jump;if(b)if(b.age+=e,b.age<ce)D=.14;else {let g=(b.age-ce)/b.air;g<1?(g<.06&&this.squash.x>.05&&(this.squash.v=-2.6),P=4*b.height*g*(1-g),I=b.spin*Math.PI*2*je($(g*1.08,0,1)),B=b.lean*Math.sin(g*Math.PI),D=g<.5?-0.05:0):b.landed?b.age-ce-b.air>.35&&(this.jump=null):(b.landed=true,a.float===0&&(this.squash.v+=3.2,s.push("land")));}a.float>0&&(D*=.3),this.squash.step(D,e,3.2,.32),o>this.nextBlink&&(this.blinkAge=0,this.nextBlink=o+2.2+r()*3.5,r()<.2&&(this.nextBlink=o+.35));let qe=0;this.blinkAge>=0&&(this.blinkAge+=e,qe=Math.sin($(this.blinkAge/.17,0,1)*Math.PI),this.blinkAge>.17&&(this.blinkAge=-1));let ge=i==="sleeping",Te=Math.sin(o*(ge?1.15:2.1))*(ge?.024:.01),Pe=this.squash.x*a.squash+v.talk.x*.05*a.talkSquash,xe=1+Pe*.55-Te*.5,Ie=1-Pe+Te,Be=P+c+this.hover.x,{a:ht,b:ft}=this.matrices,oe=this.pose.root;ie(oe,0,Be,0),_(oe,oe,Z(ht,0,I,B)),_(oe,oe,Ve(ft,xe,Ie,xe));let R=this.pose;R.minScale=Math.min(xe,Ie),R.lift=Be,R.expression=i;let W=R.channels,Le=this.shake.amount*Math.max(0,1-(o-this.shake.start)/.6);W.yaw=this.yaw.x+Math.sin(o*31)*.06*Le,W.pitch=this.pitch.x,W.roll=this.roll.x+Math.sin(o*38)*.07*Le,W.flap=v.flap.x,W.talk=v.talk.x,W.energy=v.energy.x;let Oe=0;for(let g of z)Oe+=Math.max(0,this.weights[g].x);for(let g of z)R.weights[g]=Math.max(0,this.weights[g].x)/(Oe||1);R.faceA=[ge?0:qe,v.lid.x,v.squint.x,v.smile.x],R.faceB=[v.talk.x,v.gazeX.x,v.gazeY.x,v.tilt.x],R.faceC=[ae[this.shown],ae[this.previous],$(this.switched/.35,0,1),this.switched<.3?1-this.switched/.3:0],R.faceD=[this.since,v.round.x,v.wide.x,v.asym.x],R.exposure=v.exposure.x;}};var J=32,gt={z:0,bubble:1,sparkle:2,heart:3,note:4,arc:5,puff:6,ring:7,drop:8,spark:9,mote:10,feather:11,dot:12,exclaim:13,warning:14,confetti:15,cloud:16,star:17,gear:18},Me={sleeping:[{glyph:"z",anchor:"top",rate:.55,offset:[.12,.04,.05],spread:.02,velocity:[.07,.13,0],jitter:.015,wobble:.05,life:[3,3.6],size:[.045,.12],rotation:-0.2,spin:.12,color:"#7f88ad"}],thinking:[{glyph:"dot",anchor:"top",rate:1.1,offset:[.16,.02,.06],spread:.01,velocity:[.05,.11,0],jitter:.01,wobble:.02,life:[1.5,1.8],size:[.012,.04],color:"#a3abc9"}],listening:[{glyph:"arc",anchor:"ear",rate:1.5,offset:[-0.4,0,.04],velocity:[.3,0,0],life:[1.05,1.2],size:[.1,.05],rotation:0,color:"#5cc489"}],syllable:[{glyph:"arc",anchor:"mouth",rate:2,offset:[.1,0,.06],mirror:true,velocity:[.24,.02,.04],jitter:.02,life:[.55,.7],size:[.03,.085],rotation:0,color:"#6aaee6"}],"enter:happy":[{glyph:"sparkle",anchor:"top",rate:7,spread:.22,velocity:[0,.3,.05],jitter:.4,gravity:.5,drag:1.5,life:[.7,1.1],size:[.06,0],spin:2.4,color:"#ffc94d"},{glyph:"heart",anchor:"top",rate:2,spread:.12,velocity:[0,.32,.05],jitter:.15,wobble:.06,life:[1,1.3],size:[.045,.08],color:"#ff6b8f"}],happy:[{glyph:"sparkle",anchor:"top",rate:2.5,spread:.35,velocity:[0,.14,0],jitter:.1,life:[.6,.9],size:[.045,0],spin:1.6,color:"#ffd166"}],working:[{glyph:"gear",anchor:"top",rate:.7,offset:[.12,.02,.05],spread:.03,velocity:[.05,.1,0],jitter:.02,wobble:.02,life:[2,2.4],size:[.035,.065],spin:2.2,color:"#a99cf0"},{glyph:"dot",anchor:"top",rate:2.2,offset:[-0.16,.06,.05],spread:.02,velocity:[-0.06,.14,0],jitter:.03,life:[.8,1.1],size:[.015,.006],color:"#c7bfff",glow:true}],"enter:error":[{glyph:"warning",anchor:"top",rate:1,offset:[.02,.12,.08],velocity:[0,.16,0],drag:2.2,life:[1.5,1.5],size:[.12,.1],color:"#ff4d3d"},{glyph:"spark",anchor:"top",rate:6,offset:[0,0,.05],velocity:[0,.4,0],jitter:1.3,gravity:1.6,life:[.25,.4],size:[.035,.015],color:"#ffd166",glow:true,align:true}],error:[{glyph:"puff",anchor:"top",rate:2.2,offset:[.02,.02,0],spread:.04,velocity:[0,.16,0],jitter:.05,wobble:.04,drag:.4,life:[1.3,1.7],size:[.04,.13],color:"#8b8fa3"}],"enter:surprised":[{glyph:"exclaim",anchor:"top",rate:1,offset:[.04,.14,.06],velocity:[0,.3,0],drag:3.5,life:[1.1,1.1],size:[.11,.08],rotation:-0.15,color:"#ffcc33"},{glyph:"spark",anchor:"top",rate:8,offset:[0,.02,.04],spread:.04,velocity:[0,.5,0],jitter:1.1,drag:4,life:[.3,.42],size:[.05,.02],color:"#ffe08a",align:true}],celebrating:[{glyph:"confetti",anchor:"top",rate:2.6,spread:.25,velocity:[0,.7,.05],jitter:.7,gravity:.9,drag:1.4,wobble:.06,life:[1.6,2.2],size:[.03,.026],spin:7,color:"#ff5d8f"},{glyph:"confetti",anchor:"top",rate:2.6,spread:.25,velocity:[0,.7,.05],jitter:.7,gravity:.9,drag:1.4,wobble:.06,life:[1.6,2.2],size:[.03,.026],spin:-6,color:"#ffc933"},{glyph:"confetti",anchor:"top",rate:2.6,spread:.25,velocity:[0,.7,.05],jitter:.7,gravity:.9,drag:1.4,wobble:.06,life:[1.6,2.2],size:[.03,.026],spin:8,color:"#4dc3ff"},{glyph:"confetti",anchor:"top",rate:2.6,spread:.25,velocity:[0,.7,.05],jitter:.7,gravity:.9,drag:1.4,wobble:.06,life:[1.6,2.2],size:[.03,.026],spin:-7,color:"#5ee08f"}],"enter:celebrating":[{glyph:"star",anchor:"top",rate:6,spread:.1,velocity:[0,.55,.05],jitter:.9,gravity:.6,drag:1.6,life:[.8,1.2],size:[.06,.02],spin:2,color:"#ffd23f"}],sad:[{glyph:"cloud",anchor:"top",rate:.42,offset:[-0.12,.22,.02],velocity:[0,0,0],wobble:.015,life:[2.6,2.6],size:[.15,.15],color:"#9aa3bd"},{glyph:"drop",anchor:"top",rate:4,offset:[-0.12,.16,.03],spread:.08,velocity:[0,-0.25,0],gravity:1.2,life:[.45,.6],size:[.018,.014],color:"#6aa8ff",align:true}],land:[{glyph:"puff",anchor:"feet",rate:7,spread:.1,velocity:[0,.05,0],jitter:.32,drag:3.5,life:[.45,.7],size:[.05,.12],color:"#c4cad9"}]};function xt(t){let e=parseInt(t.replace("#",""),16);return [(e>>16&255)/255,(e>>8&255)/255,(e&255)/255]}function Ne(t,e){return t==="drop"?Math.atan2(e[0],-e[1]):Math.atan2(e[1],e[0])}var G=class{constructor(e,o){this.character=e;this.random=o;let r=e.spec.fx??{},a=new Set([...Object.keys(Me),...Object.keys(r)].filter(s=>s!=="replace"));for(let s of a){let i=r[s]??[],n=r.replace?.includes(s)?i:[...Me[s]??[],...i];this.emitters[s]=n.filter(l=>e.anchors[l.anchor]);}}character;random;a=new Float32Array(J*4);b=new Float32Array(J*4);c=new Float32Array(J*4);count=0;emitters={};carry=new Map;particles=[];update(e,o,r){for(let s of this.emitters[o.expression]??[])this.emitContinuous(s,e*o.weights[o.expression],r);for(let s of this.emitters.ambient??[])this.emitContinuous(s,e,r);for(let s of o.events)for(let i of this.emitters[s]??[])this.burst(i,i.rate,r);let a=[];for(let s of this.particles){if(s.age+=e,s.age>=s.life)continue;let i=s.spec;s.vel[1]-=(i.gravity??0)*e;let n=Math.max(0,1-(i.drag??0)*e);for(let l=0;l<3;l++)s.vel[l]*=n,s.pos[l]+=s.vel[l]*e;i.wobble&&(s.pos[0]+=Math.cos(s.age*3.1+s.seed*6.28)*i.wobble*e*3),s.rot=i.align?Ne(i.glyph,s.vel):s.rot+(i.spin??0)*e,a.push(s);}this.particles=a.slice(-J),this.pack();}emitContinuous(e,o,r){let a=(this.carry.get(e)??this.random())+e.rate*o,s=Math.floor(a);this.carry.set(e,a-s),s>0&&this.burst(e,s,r);}burst(e,o,r){let a=this.character.anchors[e.anchor],s=this.random;for(let i=0;i<o;i++){let n=e.mirror&&i%2===1?-1:1,l=e.offset??[0,0,0],h=e.spread??0,f=[a.at[0]+l[0]*n+(s()-.5)*2*h,a.at[1]+l[1]+(s()-.5)*2*h,a.at[2]+l[2]+(s()-.5)*2*h],c=e.jitter??0,m=[e.velocity[0]*n+(s()-.5)*2*c,e.velocity[1]+(s()-.5)*c,e.velocity[2]+(s()-.5)*2*c];this.particles.push({pos:r.point(a.bone,f),vel:m,age:0,life:e.life[0]+(e.life[1]-e.life[0])*s(),size:e.size,rot:e.align?Ne(e.glyph,m):n<0?Math.PI-(e.rotation??0):(e.rotation??0)+(e.spin?s():0),spec:e,color:xt(e.color),seed:s()});}}pack(){this.count=this.particles.length,this.particles.forEach((e,o)=>{let r=e.age/e.life,a=1-(1-r)*(1-r),s=ke(0,.12,r)*(1-ke(.62,1,r)),i=o*4;this.a.set([e.pos[0],e.pos[1],e.pos[2],e.size[0]+(e.size[1]-e.size[0])*a],i),this.b.set([gt[e.spec.glyph],s,e.rot,e.spec.glow?1:0],i),this.c.set([e.color[0],e.color[1],e.color[2],e.seed],i);});}};function O(t){let e=parseInt(t.replace("#",""),16),o=r=>Math.pow(r/255,2.2);return [o(e>>16&255),o(e>>8&255),o(e&255)]}function De(t){return `#${t.map(e=>Math.round(Math.pow(Math.min(Math.max(e,0),1),1/2.2)*255).toString(16).padStart(2,"0")).join("")}`}var p=t=>{let e=Number(t.toFixed(5)).toString();return e.includes(".")||e.includes("e")?e:`${e}.0`},U=t=>`vec2(${p(t[0])}, ${p(t[1])})`,M=t=>`vec3(${p(t[0])}, ${p(t[1])}, ${p(t[2])})`;function _e(t){let e=Z(C(),t[0],t[1],t[2]);return `mat3(${[0,1,2].map(r=>[e[r],e[4+r],e[8+r]]).flat().map(p).join(", ")})`}function Ge(t){let e=["vec2 map(vec3 p) {"," vec2 r = vec2(1e9, 0.0);"," vec3 l;"],o=new Set,r=a=>(o.has(a)||(o.add(a),e.push(` vec3 b${a} = (uBones[${a}] * vec4(p, 1.0)).xyz;`)),`b${a}`);return t.spec.parts.forEach((a,s)=>{let i=r(t.boneIndex(a.bone,`parts[${s}]`)),n=a.at??[0,0,0],l=a.rot?`${_e(a.rot)} * (${i} - ${M(n)})`:`${i} - ${M(n)}`;e.push(` l = ${l};`);let h=p(t.materialId(a.material,`parts[${s}]`));if(a.shape==="hem"){e.push(` r.x = smax(r.x, ${p(a.y)} + ${p(a.amplitude)} * sin(atan(l.z, l.x) * ${p(a.waves)} + uTime * ${p(a.speed)}) - l.y, ${p(a.blend)});`);return}let f=a.clip?`max(${He(a)}, dot(l, ${M(bt(a.clip.normal))}) - ${p(a.clip.offset??0)})`:He(a),c=p(a.blend??0);e.push(a.op==="sub"?` opSub(r, ${f}, ${c});`:` opAdd(r, ${f}, ${h}, ${c});`);}),e.push(...yt(t,r)),e.push(" r.x *= uScaleFix;"," return r;","}"),e.join(`
|
|
2
|
-
`)}function bt(t){let e=Math.hypot(...t)||1;return [t[0]/e,t[1]/e,t[2]/e]}function He(t){switch(t.shape){case "sphere":return `sdSphere(l, ${p(t.radius)})`;case "ellipsoid":return `sdEllipsoid(l, ${
|
|
1
|
+
var C=()=>Z(new Float32Array(16));function Z(t){return t.fill(0),t[0]=t[5]=t[10]=t[15]=1,t}function F(t,e,o){let r=new Float32Array(16);for(let a=0;a<4;a++)for(let s=0;s<4;s++)r[a*4+s]=e[s]*o[a*4]+e[4+s]*o[a*4+1]+e[8+s]*o[a*4+2]+e[12+s]*o[a*4+3];return t.set(r),t}function ie(t,e,o,r){return Z(t),t[12]=e,t[13]=o,t[14]=r,t}function Ve(t,e,o,r){return Z(t),t[0]=e,t[5]=o,t[10]=r,t}function O(t,e,o,r){let a=Math.cos(e),s=Math.sin(e),i=Math.cos(o),n=Math.sin(o),l=Math.cos(r),h=Math.sin(r);return Z(t),t[0]=l*i,t[1]=h*i,t[2]=-n,t[4]=l*n*s-h*a,t[5]=h*n*s+l*a,t[6]=i*s,t[8]=l*n*a+h*s,t[9]=h*n*a-l*s,t[10]=i*a,t}function ne(t,e,o){let[r,a,s]=e,i=Math.cos(o),n=Math.sin(o),l=1-i;return Z(t),t[0]=l*r*r+i,t[1]=l*r*a+n*s,t[2]=l*r*s-n*a,t[4]=l*r*a-n*s,t[5]=l*a*a+i,t[6]=l*a*s+n*r,t[8]=l*r*s+n*a,t[9]=l*a*s-n*r,t[10]=l*s*s+i,t}function be(t,e){let[o,r,a,s,i,n,l,h,f,c,m,d,u,y,w,x]=e,E=o*n-r*i,A=o*l-a*i,M=o*h-s*i,N=r*l-a*n,T=r*h-s*n,P=a*h-s*l,v=f*y-c*u,D=f*w-m*u,_=f*x-d*u,I=c*w-m*y,B=c*x-d*y,L=m*x-d*w,H=E*L-A*B+M*I+N*_-T*D+P*v;if(!H)return Z(t);let b=1/H;return t[0]=(n*L-l*B+h*I)*b,t[1]=(a*B-r*L-s*I)*b,t[2]=(y*P-w*T+x*N)*b,t[3]=(m*T-c*P-d*N)*b,t[4]=(l*_-i*L-h*D)*b,t[5]=(o*L-a*_+s*D)*b,t[6]=(w*M-u*P-x*A)*b,t[7]=(f*P-m*M+d*A)*b,t[8]=(i*B-n*_+h*v)*b,t[9]=(r*_-o*B-s*v)*b,t[10]=(u*T-y*M+x*E)*b,t[11]=(c*M-f*T-d*E)*b,t[12]=(n*D-i*I-l*v)*b,t[13]=(o*I-r*D+a*v)*b,t[14]=(y*A-u*N-w*E)*b,t[15]=(f*N-c*A+m*E)*b,t}function ye(t,e){let[o,r,a]=e;return [t[0]*o+t[4]*r+t[8]*a+t[12],t[1]*o+t[5]*r+t[9]*a+t[13],t[2]*o+t[6]*r+t[10]*a+t[14]]}function we(t,e){let[o,r,a]=e;return [t[0]*o+t[4]*r+t[8]*a,t[1]*o+t[5]*r+t[9]*a,t[2]*o+t[6]*r+t[10]*a]}var $=(t,e,o)=>Math.min(o,Math.max(e,t)),re=(t,e,o)=>t+(e-t)*o,ke=(t,e,o)=>{let r=$((o-t)/(e-t),0,1);return r*r*(3-2*r)},je=t=>t<.5?4*t*t*t:1-Math.pow(-2*t+2,3)/2;function Q(t){let e=Math.floor(t*4294967295)>>>0||1;return ()=>{e=e+1831565813>>>0;let o=e;return o=Math.imul(o^o>>>15,o|1),o^=o+Math.imul(o^o>>>7,o|61),((o^o>>>14)>>>0)/4294967296}}var k=class{constructor(e=0){this.x=e;}x;v=0;step(e,o,r,a){let s=r*Math.PI*2;return this.v+=(s*s*(e-this.x)-2*a*s*this.v)*o,this.x+=this.v*o,this.x}};var mt=[{round:0,open:1,weight:.34},{round:.08,open:.55,weight:.26},{round:.7,open:.85,weight:.24},{round:1,open:.5,weight:.16}],le=class{constructor(e){this.random=e;this.silence=.15+e()*.3;}random;open=0;round=0;age=0;length=0;stress=0;silence=0;syllablesLeft=0;wordsLeft=0;reset(){this.age=this.length=this.open=0,this.syllablesLeft=this.wordsLeft=0,this.silence=.12;}update(e){if(this.silence>0){this.silence-=e,this.open=0;return}this.age+=e,this.age>=this.length&&this.next();let o=$(this.age/this.length,0,1);this.open=this.stress*Math.pow(Math.sin(Math.PI*o),.55);}next(){let e=this.random;this.age=0;let o=this.syllablesLeft===0;o&&(this.wordsLeft===0?(this.wordsLeft=3+Math.floor(e()*5),this.silence=this.length>0?.45+e()*.7:0):this.silence=.04+e()*.09,this.wordsLeft--,this.syllablesLeft=1+Math.floor(Math.pow(e(),1.6)*3)),this.syllablesLeft--;let r=o&&e()<.6,a=dt(mt,e());this.length=.12+e()*.13,this.stress=a.open*(r?.85+e()*.15:.5+e()*.35),this.round=a.round;}};function dt(t,e){for(let o of t){if(e<o.weight)return o;e-=o.weight;}return t[0]}var V=["idle","thinking","listening","speaking","sleeping","working","error","surprised","celebrating","sad"],z=[...V,"happy"],ae=Object.fromEntries(z.map((t,e)=>[t,e])),Me={idle:{lid:.06,squint:0,smile:.35,tilt:0,energy:1,flap:.05,glow:[.45,.7,1],exposure:1,wide:0,asym:0},thinking:{lid:.4,squint:0,smile:-0.15,tilt:.22,energy:.6,flap:0,glow:[1,.55,.12],exposure:1,wide:0,asym:0},listening:{lid:0,squint:0,smile:.2,tilt:-0.08,energy:.8,flap:.05,glow:[.25,1,.5],exposure:1,wide:.15,asym:0},speaking:{lid:.04,squint:.1,smile:.45,tilt:0,energy:1.2,flap:.1,glow:[.35,.82,1],exposure:1,wide:0,asym:0},sleeping:{lid:1,squint:0,smile:0,tilt:0,energy:.35,flap:0,glow:[.08,.09,.18],exposure:.84,wide:0,asym:0},working:{lid:.3,squint:.2,smile:.05,tilt:0,energy:1.3,flap:.18,glow:[.6,.45,1],exposure:1,wide:0,asym:0},error:{lid:.12,squint:.15,smile:-0.45,tilt:.1,energy:.9,flap:.25,glow:[1,.16,.12],exposure:.97,wide:.2,asym:1},surprised:{lid:0,squint:0,smile:0,tilt:0,energy:1,flap:.55,glow:[.95,.95,1],exposure:1.04,wide:1,asym:0},celebrating:{lid:0,squint:1,smile:1,tilt:0,energy:1.8,flap:.9,glow:[1,.72,.2],exposure:1.08,wide:0,asym:0},sad:{lid:.42,squint:0,smile:-0.85,tilt:-0.32,energy:.35,flap:-0.12,glow:[.22,.32,.7],exposure:.9,wide:0,asym:0},happy:{lid:0,squint:1,smile:1,tilt:0,energy:1.6,flap:.3,glow:[1,.42,.72],exposure:1.05,wide:0,asym:0}};var ut={float:0,hop:.16,squash:1,snap:1,look:1,snapLook:0,talkSquash:0},ce=.11,vt=1.8,G=class{temperament;state="idle";pointer=null;shown="idle";previous="idle";switched=10;time=0;since=0;random;yaw=new k;pitch=new k;roll=new k;squash=new k;hover;face={lid:new k,squint:new k,smile:new k(.3),tilt:new k,talk:new k,round:new k,gazeX:new k,gazeY:new k,flap:new k,energy:new k(1),exposure:new k(1),wide:new k,asym:new k};weights;glow=[...Me.idle.glow];jump=null;look={yaw:0,pitch:0,x:0,y:0};saccade={x:0,y:0,next:0};nextLook=.6;nextBlink;blinkAge=-1;nextHop;nextSide=4;side=1;nextNod=2.5;shake={start:-10,amount:0,next:0};sigh={start:-10,next:0};reactUntil=-1;speech;lastTalk=0;syllableArmed=true;matrices={a:C(),b:C()};pose;constructor(e={},o=.5){this.temperament={...ut,...e},this.random=Q(o),this.speech=new le(this.random),this.nextBlink=1+this.random()*3,this.nextHop=6+this.random()*6,this.hover=new k(this.temperament.float),this.weights=Object.fromEntries(z.map(r=>[r,new k(r==="idle"?1:0)])),this.pose={root:C(),minScale:1,lift:0,channels:{yaw:0,pitch:0,roll:0,flap:0,talk:0,energy:1},weights:Object.fromEntries(z.map(r=>[r,r==="idle"?1:0])),expression:"idle",faceA:[0,0,0,0],faceB:[0,0,0,0],faceC:[0,0,1,0],faceD:[0,0,0,0],glow:this.glow,exposure:1,events:[]};}setState(e){e!==this.state&&(this.state=e,this.since=0,e==="speaking"&&this.speech.reset(),this.nextLook=0);}poke(){this.hop(this.temperament.hop*1.5,this.random()<.5?1:-1),this.reactUntil=this.time+vt;}update(e){if(!(e>0))return;let o=Math.max(1,Math.ceil(e/(1/120)));for(let r=0;r<o;r++)this.step(e/o);}enter(e,o){let r=this.temperament;e==="surprised"?(this.hop(r.hop*.6,0),this.pitch.v+=1.2,this.startShake(o,.35,1/0)):e==="error"?(this.side=this.random()<.5?1:-1,this.squash.v-=2.5,this.startShake(o,1,o+2+this.random())):e==="celebrating"?this.nextHop=o:e==="sad"&&(this.sigh.next=o+1.2);}startShake(e,o,r){this.shake.start=e,this.shake.amount=o,this.shake.next=r;}hop(e,o){if(this.jump)return;let r=this.temperament.float>0;this.jump={age:r?ce:0,height:e,spin:o,lean:(this.random()-.5)*.3,air:.42+e*.45+(r?.25:0),landed:false};}step(e){this.time+=e,this.since+=e,this.switched+=e;let o=this.time,r=this.random,a=this.temperament,s=this.pose.events,i=o<this.reactUntil?"happy":this.state;i!==this.shown&&(this.previous=this.shown,this.shown=i,this.switched=0,s.push(`enter:${i}`),this.enter(i,o));let n=Me[i];o>this.nextLook&&(this.look.yaw=(r()-.5)*.75,this.look.pitch=(r()-.5)*.24,this.look.x=$(this.look.yaw*2.2,-1,1),this.look.y=r()<.3?.6:r()<.2?-0.6:0,this.nextLook=o+re(1.4+r()*2.6,.45+r()*1.1,a.snapLook)),o>this.saccade.next&&(this.saccade.x=(r()-.5)*.22,this.saccade.y=(r()-.5)*.14,this.saccade.next=o+.25+r()*.7);let l=0,h=0,f=0,c=Math.sin(o*1.9)*.008,m=0,d=0,u=0,y=0,w=n.flap,x=1.3,E=.62,A=a.float,M=this.pointer,N=M&&(i==="idle"||i==="listening"||i==="speaking"||i==="surprised");switch(i){case "idle":l=this.look.yaw,h=this.look.pitch,f=-this.look.yaw*.16,m=this.look.x,d=this.look.y,o>this.nextHop&&(this.hop(a.hop*(.9+r()*.4),r()<.35?r()<.5?1:-1:0),this.nextHop=o+7+r()*7);break;case "thinking":{o>this.nextSide&&(this.side=-this.side,this.nextSide=o+3+r()*2);let g=this.side;l=.24*g+Math.sin(o*.9)*.05,h=.17+Math.sin(o*1.3)*.03,f=-0.13*g,m=.7*g,d=.8,x=.9;break}case "listening":l=-0.14,h=.02,f=.17,m=-0.2,o>this.nextNod&&(this.pitch.v-=.9,this.nextNod=o+2+r()*2.5);break;case "speaking":{l=Math.sin(o*.7)*.12,f=Math.sin(o*.9)*.05,this.speech.update(e),u=this.speech.open,y=this.speech.round,h=.04+u*.07,c+=u*.014,w+=Math.sin(o*2.6)*.1,x=1.8;break}case "sleeping":h=-0.3,f=.13,l=.06,c=Math.sin(o*1.15)*.016,u=.12+.1*Math.sin(o*1.15),y=.7,A*=.65,x=.55,E=.9,o>this.nextNod&&(this.pitch.v-=.5,this.nextNod=o+5+r()*4);break;case "working":l=Math.sin(o*.8)*.07,h=-0.13+Math.abs(Math.sin(o*5.2))*.03,f=Math.sin(o*.6)*.04,m=Math.sin(o*1.6)*.45,d=-0.55,w+=Math.sin(o*11)*.06,x=1.6;break;case "error":{o>this.shake.next&&this.startShake(o,.55,2.4+r()*1.4);let g=this.side;f=.16*g,l=-0.1*g,h=.05,m=.45*g,d=.3,u=.16,x=1.5;break}case "surprised":h=.1,u=.42,y=1,x=2.2,E=.5;break;case "celebrating":l=Math.sin(o*3.1)*.22,f=Math.sin(o*6.2)*.1,h=.14,u=.6+.12*Math.sin(o*7),y=.05,w+=Math.sin(o*9)*.25,x=2,o>this.nextHop&&(this.hop(a.hop*1.25,r()<.3?r()<.5?1:-1:0),this.nextHop=o+.85+r()*.4);break;case "sad":{o>this.sigh.next&&(this.sigh.start=o,this.sigh.next=o+4+r()*2.5);let g=Math.sin($((o-this.sigh.start)/1.7,0,1)*Math.PI);h=-0.24+g*.1,l=Math.sin(o*.3)*.1,f=.08,m=-0.15,d=-0.65+g*.3,c+=g*.018,A*=.7,x=.7,E=.85;break}case "happy":l=Math.sin(o*2.2)*.18,f=Math.sin(o*4.4)*.12,h=.12,u=.5+.15*Math.sin(o*8),y=.2,o>this.nextHop&&(this.hop(a.hop*1.05,0),this.nextHop=o+1.05+r()*.4);break}N&&M&&(l=$(M.x,-1,1)*.55,h=$(-M.y,-1,1)*.32+(i==="speaking"?u*.07:0),f=-l*.12+(i==="listening"?.12:0),m=$(M.x*2,-1,1),d=$(-M.y*1.5,-1,1)),i!=="sleeping"&&(m+=this.saccade.x,d+=this.saccade.y),a.float>0&&(c+=Math.sin(o*1.5)*.035);let T=re(x,x*3.2,a.snapLook)*a.snap,P=re(E,.95,a.snapLook);this.yaw.step(l*a.look,e,T,P),this.pitch.step(h*a.look,e,T,P),this.roll.step(f,e,x*a.snap,E),this.hover.step(A,e,.6,.8);let v=this.face;v.lid.step(n.lid,e,2.2,.9),v.squint.step(n.squint,e,3,.8),v.smile.step(n.smile,e,2.4,.75),v.tilt.step(n.tilt*this.side,e,1.6,.8),v.talk.step(u,e,14,.8),v.round.step(y,e,6,.8),v.gazeX.step(m,e,7,.85),v.gazeY.step(d,e,7,.85),v.flap.step(w,e,2.4*a.snap,.5),v.energy.step(n.energy,e,.8,1),v.exposure.step(n.exposure,e,.4,1),v.wide.step(n.wide,e,5,.6),v.asym.step(n.asym*this.side,e,3,.8);for(let g of z)this.weights[g].step(g===i?1:0,e,1.6*a.snap,.95);let D=1-Math.exp(-e*4),_=i==="thinking"?.55+.45*Math.sin(o*4.2):i==="speaking"?.6+.6*v.talk.x:i==="working"?.75+.25*Math.sin(o*7):i==="error"?Math.sin(o*7)>0?1.1:.45:1;for(let g=0;g<3;g++)this.glow[g]=re(this.glow[g],n.glow[g]*_,D);this.syllableArmed&&v.talk.x>.55&&this.lastTalk<=.55&&i==="speaking"&&(s.push("syllable"),this.syllableArmed=false),v.talk.x<.35&&(this.syllableArmed=true),this.lastTalk=v.talk.x;let I=0,B=0,L=0,H=0,b=this.jump;if(b)if(b.age+=e,b.age<ce)H=.14;else {let g=(b.age-ce)/b.air;g<1?(g<.06&&this.squash.x>.05&&(this.squash.v=-2.6),I=4*b.height*g*(1-g),B=b.spin*Math.PI*2*je($(g*1.08,0,1)),L=b.lean*Math.sin(g*Math.PI),H=g<.5?-0.05:0):b.landed?b.age-ce-b.air>.35&&(this.jump=null):(b.landed=true,a.float===0&&(this.squash.v+=3.2,s.push("land")));}a.float>0&&(H*=.3),this.squash.step(H,e,3.2,.32),o>this.nextBlink&&(this.blinkAge=0,this.nextBlink=o+2.2+r()*3.5,r()<.2&&(this.nextBlink=o+.35));let qe=0;this.blinkAge>=0&&(this.blinkAge+=e,qe=Math.sin($(this.blinkAge/.17,0,1)*Math.PI),this.blinkAge>.17&&(this.blinkAge=-1));let ge=i==="sleeping",Te=Math.sin(o*(ge?1.15:2.1))*(ge?.024:.01),Pe=this.squash.x*a.squash+v.talk.x*.05*a.talkSquash,xe=1+Pe*.55-Te*.5,Ie=1-Pe+Te,Be=I+c+this.hover.x,{a:ht,b:ft}=this.matrices,oe=this.pose.root;ie(oe,0,Be,0),F(oe,oe,O(ht,0,B,L)),F(oe,oe,Ve(ft,xe,Ie,xe));let R=this.pose;R.minScale=Math.min(xe,Ie),R.lift=Be,R.expression=i;let Y=R.channels,Le=this.shake.amount*Math.max(0,1-(o-this.shake.start)/.6);Y.yaw=this.yaw.x+Math.sin(o*31)*.06*Le,Y.pitch=this.pitch.x,Y.roll=this.roll.x+Math.sin(o*38)*.07*Le,Y.flap=v.flap.x,Y.talk=v.talk.x,Y.energy=v.energy.x;let Oe=0;for(let g of z)Oe+=Math.max(0,this.weights[g].x);for(let g of z)R.weights[g]=Math.max(0,this.weights[g].x)/(Oe||1);R.faceA=[ge?0:qe,v.lid.x,v.squint.x,v.smile.x],R.faceB=[v.talk.x,v.gazeX.x,v.gazeY.x,v.tilt.x],R.faceC=[ae[this.shown],ae[this.previous],$(this.switched/.35,0,1),this.switched<.3?1-this.switched/.3:0],R.faceD=[this.since,v.round.x,v.wide.x,v.asym.x],R.exposure=v.exposure.x;}};var J=32,gt={z:0,bubble:1,sparkle:2,heart:3,note:4,arc:5,puff:6,ring:7,drop:8,spark:9,mote:10,feather:11,dot:12,exclaim:13,warning:14,confetti:15,cloud:16,star:17,gear:18},Se={sleeping:[{glyph:"z",anchor:"top",rate:.55,offset:[.12,.04,.05],spread:.02,velocity:[.07,.13,0],jitter:.015,wobble:.05,life:[3,3.6],size:[.045,.12],rotation:-0.2,spin:.12,color:"#7f88ad"}],thinking:[{glyph:"dot",anchor:"top",rate:1.1,offset:[.16,.02,.06],spread:.01,velocity:[.05,.11,0],jitter:.01,wobble:.02,life:[1.5,1.8],size:[.012,.04],color:"#a3abc9"}],listening:[{glyph:"arc",anchor:"ear",rate:1.5,offset:[-0.4,0,.04],velocity:[.3,0,0],life:[1.05,1.2],size:[.1,.05],rotation:0,color:"#5cc489"}],syllable:[{glyph:"arc",anchor:"mouth",rate:2,offset:[.1,0,.06],mirror:true,velocity:[.24,.02,.04],jitter:.02,life:[.55,.7],size:[.03,.085],rotation:0,color:"#6aaee6"}],"enter:happy":[{glyph:"sparkle",anchor:"top",rate:7,spread:.22,velocity:[0,.3,.05],jitter:.4,gravity:.5,drag:1.5,life:[.7,1.1],size:[.06,0],spin:2.4,color:"#ffc94d"},{glyph:"heart",anchor:"top",rate:2,spread:.12,velocity:[0,.32,.05],jitter:.15,wobble:.06,life:[1,1.3],size:[.045,.08],color:"#ff6b8f"}],happy:[{glyph:"sparkle",anchor:"top",rate:2.5,spread:.35,velocity:[0,.14,0],jitter:.1,life:[.6,.9],size:[.045,0],spin:1.6,color:"#ffd166"}],working:[{glyph:"gear",anchor:"top",rate:.7,offset:[.12,.02,.05],spread:.03,velocity:[.05,.1,0],jitter:.02,wobble:.02,life:[2,2.4],size:[.035,.065],spin:2.2,color:"#a99cf0"},{glyph:"dot",anchor:"top",rate:2.2,offset:[-0.16,.06,.05],spread:.02,velocity:[-0.06,.14,0],jitter:.03,life:[.8,1.1],size:[.015,.006],color:"#c7bfff",glow:true}],"enter:error":[{glyph:"warning",anchor:"top",rate:1,offset:[.02,.12,.08],velocity:[0,.16,0],drag:2.2,life:[1.5,1.5],size:[.12,.1],color:"#ff4d3d"},{glyph:"spark",anchor:"top",rate:6,offset:[0,0,.05],velocity:[0,.4,0],jitter:1.3,gravity:1.6,life:[.25,.4],size:[.035,.015],color:"#ffd166",glow:true,align:true}],error:[{glyph:"puff",anchor:"top",rate:2.2,offset:[.02,.02,0],spread:.04,velocity:[0,.16,0],jitter:.05,wobble:.04,drag:.4,life:[1.3,1.7],size:[.04,.13],color:"#8b8fa3"}],"enter:surprised":[{glyph:"exclaim",anchor:"top",rate:1,offset:[.04,.14,.06],velocity:[0,.3,0],drag:3.5,life:[1.1,1.1],size:[.11,.08],rotation:-0.15,color:"#ffcc33"},{glyph:"spark",anchor:"top",rate:8,offset:[0,.02,.04],spread:.04,velocity:[0,.5,0],jitter:1.1,drag:4,life:[.3,.42],size:[.05,.02],color:"#ffe08a",align:true}],celebrating:[{glyph:"confetti",anchor:"top",rate:2.6,spread:.25,velocity:[0,.7,.05],jitter:.7,gravity:.9,drag:1.4,wobble:.06,life:[1.6,2.2],size:[.03,.026],spin:7,color:"#ff5d8f"},{glyph:"confetti",anchor:"top",rate:2.6,spread:.25,velocity:[0,.7,.05],jitter:.7,gravity:.9,drag:1.4,wobble:.06,life:[1.6,2.2],size:[.03,.026],spin:-6,color:"#ffc933"},{glyph:"confetti",anchor:"top",rate:2.6,spread:.25,velocity:[0,.7,.05],jitter:.7,gravity:.9,drag:1.4,wobble:.06,life:[1.6,2.2],size:[.03,.026],spin:8,color:"#4dc3ff"},{glyph:"confetti",anchor:"top",rate:2.6,spread:.25,velocity:[0,.7,.05],jitter:.7,gravity:.9,drag:1.4,wobble:.06,life:[1.6,2.2],size:[.03,.026],spin:-7,color:"#5ee08f"}],"enter:celebrating":[{glyph:"star",anchor:"top",rate:6,spread:.1,velocity:[0,.55,.05],jitter:.9,gravity:.6,drag:1.6,life:[.8,1.2],size:[.06,.02],spin:2,color:"#ffd23f"}],sad:[{glyph:"cloud",anchor:"top",rate:.42,offset:[-0.12,.22,.02],velocity:[0,0,0],wobble:.015,life:[2.6,2.6],size:[.15,.15],color:"#9aa3bd"},{glyph:"drop",anchor:"top",rate:4,offset:[-0.12,.16,.03],spread:.08,velocity:[0,-0.25,0],gravity:1.2,life:[.45,.6],size:[.018,.014],color:"#6aa8ff",align:true}],land:[{glyph:"puff",anchor:"feet",rate:7,spread:.1,velocity:[0,.05,0],jitter:.32,drag:3.5,life:[.45,.7],size:[.05,.12],color:"#c4cad9"}]};function xt(t){let e=parseInt(t.replace("#",""),16);return [(e>>16&255)/255,(e>>8&255)/255,(e&255)/255]}function Ne(t,e){return t==="drop"?Math.atan2(e[0],-e[1]):Math.atan2(e[1],e[0])}var U=class{constructor(e,o){this.character=e;this.random=o;let r=e.spec.fx??{},a=new Set([...Object.keys(Se),...Object.keys(r)].filter(s=>s!=="replace"));for(let s of a){let i=r[s]??[],n=r.replace?.includes(s)?i:[...Se[s]??[],...i];this.emitters[s]=n.filter(l=>e.anchors[l.anchor]);}}character;random;a=new Float32Array(J*4);b=new Float32Array(J*4);c=new Float32Array(J*4);count=0;emitters={};carry=new Map;particles=[];update(e,o,r){for(let s of this.emitters[o.expression]??[])this.emitContinuous(s,e*o.weights[o.expression],r);for(let s of this.emitters.ambient??[])this.emitContinuous(s,e,r);for(let s of o.events)for(let i of this.emitters[s]??[])this.burst(i,i.rate,r);let a=[];for(let s of this.particles){if(s.age+=e,s.age>=s.life)continue;let i=s.spec;s.vel[1]-=(i.gravity??0)*e;let n=Math.max(0,1-(i.drag??0)*e);for(let l=0;l<3;l++)s.vel[l]*=n,s.pos[l]+=s.vel[l]*e;i.wobble&&(s.pos[0]+=Math.cos(s.age*3.1+s.seed*6.28)*i.wobble*e*3),s.rot=i.align?Ne(i.glyph,s.vel):s.rot+(i.spin??0)*e,a.push(s);}this.particles=a.slice(-J),this.pack();}emitContinuous(e,o,r){let a=(this.carry.get(e)??this.random())+e.rate*o,s=Math.floor(a);this.carry.set(e,a-s),s>0&&this.burst(e,s,r);}burst(e,o,r){let a=this.character.anchors[e.anchor],s=this.random;for(let i=0;i<o;i++){let n=e.mirror&&i%2===1?-1:1,l=e.offset??[0,0,0],h=e.spread??0,f=[a.at[0]+l[0]*n+(s()-.5)*2*h,a.at[1]+l[1]+(s()-.5)*2*h,a.at[2]+l[2]+(s()-.5)*2*h],c=e.jitter??0,m=[e.velocity[0]*n+(s()-.5)*2*c,e.velocity[1]+(s()-.5)*c,e.velocity[2]+(s()-.5)*2*c];this.particles.push({pos:r.point(a.bone,f),vel:m,age:0,life:e.life[0]+(e.life[1]-e.life[0])*s(),size:e.size,rot:e.align?Ne(e.glyph,m):n<0?Math.PI-(e.rotation??0):(e.rotation??0)+(e.spin?s():0),spec:e,color:xt(e.color),seed:s()});}}pack(){this.count=this.particles.length,this.particles.forEach((e,o)=>{let r=e.age/e.life,a=1-(1-r)*(1-r),s=ke(0,.12,r)*(1-ke(.62,1,r)),i=o*4;this.a.set([e.pos[0],e.pos[1],e.pos[2],e.size[0]+(e.size[1]-e.size[0])*a],i),this.b.set([gt[e.spec.glyph],s,e.rot,e.spec.glow?1:0],i),this.c.set([e.color[0],e.color[1],e.color[2],e.seed],i);});}};function j(t){let e=parseInt(t.replace("#",""),16),o=r=>Math.pow(r/255,2.2);return [o(e>>16&255),o(e>>8&255),o(e&255)]}function De(t){return `#${t.map(e=>Math.round(Math.pow(Math.min(Math.max(e,0),1),1/2.2)*255).toString(16).padStart(2,"0")).join("")}`}var p=t=>{let e=Number(t.toFixed(5)).toString();return e.includes(".")||e.includes("e")?e:`${e}.0`},X=t=>`vec2(${p(t[0])}, ${p(t[1])})`,S=t=>`vec3(${p(t[0])}, ${p(t[1])}, ${p(t[2])})`;function _e(t){let e=O(C(),t[0],t[1],t[2]);return `mat3(${[0,1,2].map(r=>[e[r],e[4+r],e[8+r]]).flat().map(p).join(", ")})`}function Ge(t){let e=["vec2 map(vec3 p) {"," vec2 r = vec2(1e9, 0.0);"," vec3 l;"],o=new Set,r=a=>(o.has(a)||(o.add(a),e.push(` vec3 b${a} = (uBones[${a}] * vec4(p, 1.0)).xyz;`)),`b${a}`);return t.spec.parts.forEach((a,s)=>{let i=r(t.boneIndex(a.bone,`parts[${s}]`)),n=a.at??[0,0,0],l=a.rot?`${_e(a.rot)} * (${i} - ${S(n)})`:`${i} - ${S(n)}`;e.push(` l = ${l};`);let h=p(t.materialId(a.material,`parts[${s}]`));if(a.shape==="hem"){e.push(` r.x = smax(r.x, ${p(a.y)} + ${p(a.amplitude)} * sin(atan(l.z, l.x) * ${p(a.waves)} + uTime * ${p(a.speed)}) - l.y, ${p(a.blend)});`);return}let f=a.clip?`max(${He(a)}, dot(l, ${S(bt(a.clip.normal))}) - ${p(a.clip.offset??0)})`:He(a),c=p(a.blend??0);e.push(a.op==="sub"?` opSub(r, ${f}, ${c});`:` opAdd(r, ${f}, ${h}, ${c});`);}),e.push(...yt(t,r)),e.push(" r.x *= uScaleFix;"," return r;","}"),e.join(`
|
|
2
|
+
`)}function bt(t){let e=Math.hypot(...t)||1;return [t[0]/e,t[1]/e,t[2]/e]}function He(t){switch(t.shape){case "sphere":return `sdSphere(l, ${p(t.radius)})`;case "ellipsoid":return `sdEllipsoid(l, ${S(t.radii)})`;case "roundBox":return `sdRoundBox(l, ${S(t.half)}, ${p(t.round)})`;case "capsule":return `sdCapsule(l, ${S(t.from)}, ${S(t.to)}, ${p(t.radius)})`;case "roundCone":return `sdRoundCone(l, ${S(t.from)}, ${S(t.to)}, ${p(t.r1)}, ${p(t.r2)})`;case "cylinder":return `sdCylinder(l, ${p(t.radius)}, ${p(t.half)}, ${p(t.round)})`;case "frame":return `sdFrame(l, ${X(t.half)}, ${p(t.corner)}, ${p(t.width)}, ${p(t.depth)})`;case "plate":return `sdPlate(l, ${X(t.half)}, ${p(t.corner)}, ${p(t.depth)})`;case "hem":throw new Error("unreachable")}}function yt(t,e){let o=t.spec.eyes;if(!o)return [];let r=e(t.boneIndex(o.bone,"eyes")),a=[];if(o.kind==="ball"){let s=p(t.materialId(o.lid,"eyes.lid")),i=o.radius;o.at.forEach((n,l)=>{let h=l===0?"-1.0":"1.0";a.push(` l = ${r} - ${S(n)};`,` opAdd(r, length(l) - ${p(i)}, ${p(t.eyeIds[l])}, 0.0);`," {",` float tilt = uFaceB.w * ${h};`," vec3 q = vec3(mat2(cos(tilt), sin(tilt), -sin(tilt), cos(tilt)) * l.xy, l.z);",` float shell = length(q) - ${p(i*1.1)};`,` float lid = clamp(uFaceA.y + uFaceD.w * ${h} * 0.38 - uFaceD.z * 0.1, 0.0, 1.0);`,` float top = mix(${p(i*1.18)}, ${p(-i*.14)}, max(uFaceA.x, lid));`,` float bottom = mix(${p(-i*1.18)}, ${p(-i*.02)}, uFaceA.z * 0.85);`,` opAdd(r, min(max(shell, top - q.y), max(shell, q.y - bottom)), ${s}, 0.0);`," }");});}else {let s=p(t.materialId(o.material,"eyes.material")),[i,n,l]=o.radii;a.push(" float grow = 1.0 + 0.2 * uFaceD.z;"),o.at.forEach((h,f)=>{let c=f===0?"-1.0":"1.0";a.push(` float open${f} = max(0.12, (1.0 - max(uFaceA.x, clamp(uFaceA.y + uFaceD.w * ${c} * 0.45, 0.0, 1.0))) * (1.0 - 0.6 * uFaceA.z));`,` l = ${r} - ${S(h)} - vec3(uFaceB.y * ${p(i*.45)}, uFaceB.z * ${p(n*.3)}, 0.0);`,` opAdd(r, sdEllipsoid(l, vec3(${p(i)} * grow, ${p(n)} * grow * open${f}, ${p(l)})), ${s}, 0.0);`);});}return a}var q=t=>S(j(t));function wt(t,e){let o=t.glows?`uGlow * ${p(t.emitStrength??1)}`:t.emit?`${q(t.emit)} * ${p(t.emitStrength??1)}`:"vec3(0.0)";return `Material(uAlbedo[${e}], ${p(t.f0??.04)}, ${p(t.spec??.5)}, ${p(t.shininess??40)}, ${p(t.metal??0)}, ${p(t.rim??.5)}, ${p(t.sheen??0)}, ${p(t.sss??0)}, ${t.sssColor?q(t.sssColor):"vec3(0.0)"}, ${o}, ${p(t.gloss??.3)})`}var Ue=t=>t.map(e=>`k == ${e}`).join(" || ");function Xe(t){let e=["Material getMaterial(float id, vec3 p, vec3 n) {"," int k = int(id + 0.5);"," Material m = material(vec3(0.5));"];return t.materials.forEach(({id:o,spec:r},a)=>e.push(` ${a?"else ":""}if (k == ${o}) m = ${wt(r,a)};`)),t.spec.paints?.forEach((o,r)=>{let a=t.boneIndex(o.bone,`paints[${r}]`),s=o.on.map(l=>t.materialId(l,`paints[${r}]`)),i=p(o.soft??.15),n=o.kind==="sphere"?`(length(q) - ${p(o.radius??.1)}) / ${p(o.radius??.1)}`:`q.z > 0.0 ? length(q.xy / ${X(o.radii??[.1,.1])}) - 1.0 : 1.0`;e.push(` if (${Ue(s)}) {`,` vec3 q = (uBones[${a}] * vec4(p, 1.0)).xyz - ${S(o.at)};`,` float e = ${n};`,` m.albedo = mix(m.albedo, ${q(o.color)}, (1.0 - smoothstep(-${i}, ${i}, e)) * ${p(o.opacity??1)});`," }");}),e.push(...Mt(t),...St(t)," return m;","}"),e.join(`
|
|
3
3
|
`)}function Ke(t){let e=["void surface(float id, vec3 p, inout vec3 n, inout Material m) {"," int k = int(id + 0.5);"];for(let{id:o,spec:r,name:a}of t.materials){let s=r.surface;if(!s)continue;let i=t.boneIndex(s.bone??"root",`materials.${a}.surface`),n=p(s.strength??.5);e.push(` if (k == ${o}) {`,` vec3 q = (uBones[${i}] * vec4(p, 1.0)).xyz * ${p(s.scale)};`,` float detail = ${n} * (1.0 - smoothstep(0.25, 0.9, gPixel * ${p(s.scale)}));`,...kt(s.kind,s.color)," }");}return e.push("}"),e.join(`
|
|
4
|
-
`)}function kt(t,e){let o=r=>[` vec3 g = vec3(noise3(${r}), noise3(${r} + 17.3), noise3(${r} + 41.7)) - 0.5;`," g -= n * dot(g, n);"];switch(t){case "fur":return [...o("q")," n = normalize(n + g * 0.5 * detail);"," float clump = noise3(q * 0.23);"," m.albedo *= mix(1.0, 0.9 + 0.2 * clump, detail);"];case "scales":return [" float c = noise3(q);"," float e = 0.12;"," vec3 grad = vec3(noise3(q + vec3(e, 0, 0)), noise3(q + vec3(0, e, 0)), noise3(q + vec3(0, 0, e))) - c;"," grad -= n * dot(grad, n);"," n = normalize(n - grad * 2.2 * detail);"," float seam = 1.0 - smoothstep(0.03, 0.13, abs(c - 0.5));",` m.albedo = mix(m.albedo, ${e?
|
|
4
|
+
`)}function kt(t,e){let o=r=>[` vec3 g = vec3(noise3(${r}), noise3(${r} + 17.3), noise3(${r} + 41.7)) - 0.5;`," g -= n * dot(g, n);"];switch(t){case "fur":return [...o("q")," n = normalize(n + g * 0.5 * detail);"," float clump = noise3(q * 0.23);"," m.albedo *= mix(1.0, 0.9 + 0.2 * clump, detail);"];case "scales":return [" float c = noise3(q);"," float e = 0.12;"," vec3 grad = vec3(noise3(q + vec3(e, 0, 0)), noise3(q + vec3(0, e, 0)), noise3(q + vec3(0, 0, e))) - c;"," grad -= n * dot(grad, n);"," n = normalize(n - grad * 2.2 * detail);"," float seam = 1.0 - smoothstep(0.03, 0.13, abs(c - 0.5));",` m.albedo = mix(m.albedo, ${e?q(e):"m.albedo * 0.55"}, seam * 0.7 * detail);`," m.albedo *= 0.9 + 0.2 * noise3(q * 0.31) * detail;"];case "speckle":return [" float spot = smoothstep(0.66, 0.7, noise3(q)) * (0.6 + 0.4 * noise3(q * 0.37));",` m.albedo = mix(m.albedo, ${e?q(e):"m.albedo * 0.6"}, spot * detail);`];case "ripple":return [...o("q")," n = normalize(n + g * 0.35 * detail);"]}}function Mt(t){let e=t.spec.eyes;if(e?.kind!=="ball")return [];let o=t.boneIndex(e.bone,"eyes"),r=[];return e.at.forEach((a,s)=>{r.push(` if (k == ${t.eyeIds[s]}) {`,` vec3 q = normalize((uBones[${o}] * vec4(p, 1.0)).xyz - ${S(a)});`," vec3 g = normalize(vec3(uFaceB.y * 0.5, uFaceB.z * 0.38, 1.0));"," vec3 right = normalize(cross(vec3(0.0, 1.0, 0.0), g));"," vec3 up = cross(g, right);"," vec2 s = vec2(dot(q, right), dot(q, up));"," float front = step(0.0, dot(q, g));",` float aa = gPixel / ${p(e.radius)} + 0.02;`," float rr = length(s);",` float iris = front - front * smoothstep(${p(e.irisSize)} - aa, ${p(e.irisSize)} + aa, rr);`,` float ps = ${p(e.pupilSize)} * (1.0 - 0.4 * uFaceD.z);`,` float pupil = front - front * smoothstep(ps - aa, ps + aa, length(s / vec2(${p(e.pupilAspect??1)}, 1.0)));`,` vec3 irisCol = ${q(e.iris)} * (0.55 + 0.9 * smoothstep(${p(e.irisSize)}, 0.0, rr)) * (0.7 + 0.3 * hash12(floor(vec2(atan(s.y, s.x) * 9.0, rr * 30.0))));`," vec3 albedo = mix(vec3(0.82, 0.8, 0.78), irisCol, iris);"," albedo = mix(albedo, vec3(0.004), pupil);"," m = Material(albedo, 0.06, 2.4, 600.0, 0.0, 0.15, 0.0, 0.0, vec3(0.0), vec3(0.0), 1.0);"," }");}),r}function St(t){let e=t.spec.face;if(!e)return [];if(e.kind==="screen"){let s=t.boneIndex(e.bone,"face");return [` if (k == ${t.materialId(e.material,"face.material")}) {`,` vec2 q = (uBones[${s}] * vec4(p, 1.0)).xy - ${X(e.center)};`,` m.emit += screenLight(q, ${q(e.color)}, ${p(e.cell)}, ${X(e.half)}, ${p(e.corner)});`," }"]}let o=t.boneIndex(e.bone,"face"),r=e.on.map(s=>t.materialId(s,"face.on")),a=e.width;return [` if (${Ue(r)}) {`,` vec3 q = (uBones[${o}] * vec4(p, 1.0)).xyz - ${S(e.at)};`," if (q.z > -0.02) {",` vec3 mo = mouth(q.xy, ${p(a)}, uFaceB.x * ${p(a*1.1)}, uFaceD.y, uFaceA.w, uFaceD.w, ${p(a*.12)}, gPixel * 0.8);`," float a = mo.x;",` vec3 inner = ${q(e.color)} * (1.25 - 0.5 * mo.z);`,` m.albedo = mix(m.albedo, mix(inner, ${q(e.tongue)}, mo.y), a);`," m.spec *= 1.0 - 0.6 * a; m.sss *= 1.0 - a; m.sheen *= 1.0 - a; m.emit *= 1.0 - a;"," }"," }"]}var We=`
|
|
5
5
|
const vec3 KEY = vec3(-0.4485, 0.6997, 0.5562);
|
|
6
6
|
const vec3 FILL = vec3(0.8521, -0.1504, 0.5013);
|
|
7
7
|
const vec3 BACK = vec3(0.5529, 0.5529, -0.6233);
|
|
@@ -687,6 +687,6 @@ void main() {
|
|
|
687
687
|
}`,Et=()=>z.map(t=>`#define E_${t.toUpperCase()} ${p(ae[t])}`).join(`
|
|
688
688
|
`)+`
|
|
689
689
|
`;function Ee(t){let e=tt(t),o=["#version 300 es","precision highp float;","precision highp int;",ot(e.bones.length,e.materials.length),"out vec4 fragColor;","float gPixel = 0.001;","#define ZERO (min(int(uTime), 0))",Je,Ge(e),We,t.face?.kind==="screen"?Et()+et:"",t.face?.kind==="mouth"?Ze:"",Xe(e),Ke(e),Qe,Ye].join(`
|
|
690
|
-
`);return {spec:t,bones:e.bones,acting:e.acting,anchors:e.anchors,fragment:o,materials:e.materials.map(r=>r.name),albedo:new Float32Array(e.materials.flatMap(r=>
|
|
691
|
-
`).length}}}var $e=(t,e)=>[t[0]+e[0],t[1]+e[1],t[2]+e[2]],Ce=(t,e)=>[t[0]-e[0],t[1]-e[1],t[2]-e[2]],fe=(t,e)=>[t[0]*e,t[1]*e,t[2]*e],at=(t,e)=>t[0]*e[0]+t[1]*e[1]+t[2]*e[2],st=(t,e)=>[t[1]*e[2]-t[2]*e[1],t[2]*e[0]-t[0]*e[2],t[0]*e[1]-t[1]*e[0]],Ae=t=>Math.hypot(t[0],t[1],t[2]);function se(t){let e=Ae(t)||1;return [t[0]/e,t[1]/e,t[2]/e]}var it=["rx","ry","rz"];function $t(t,e){if(typeof t=="number")return t;let[o,r=0,a=0,s=0]=t;return o+r*Math.sin(e*a*Math.PI*2+s)}var
|
|
692
|
-
${l}`)}s.deleteShader(r),s.deleteShader(a);let i=Object.fromEntries(Object.keys(he).map(l=>[l,s.getUniformLocation(o,he[l].includes("[")?`${l}[0]`:l)])),n={program:o,uniforms:i,character:e};return this.programs.set(e,n),n}};var nt=.2,Rt=.1,K=class{constructor(e){this.canvas=e;let o=e.getContext("2d");if(!o)throw new Error("Canvas 2D is not available");this.target=o;}canvas;gpu=de.shared();target;character=null;load(e){this.character=e,this.gpu.program(e);}render(e){let o=this.character&&this.gpu.program(this.character);if(!o)return false;let{gpu:r}=this,{gl:a}=r,{width:s,height:i}=e;(this.canvas.width!==s||this.canvas.height!==i)&&(this.canvas.width=s,this.canvas.height=i),r.reserve(s,i),a.viewport(0,0,s,i),a.scissor(0,0,s,i),a.clear(a.COLOR_BUFFER_BIT),a.useProgram(o.program);let n=o.uniforms,{spec:l}=o.character,h=e.pose,f=h.lift;return a.uniform2f(n.uResolution,e.width,e.height),a.uniform1f(n.uTime,e.time),a.uniform4f(n.uCamera,l.frame.target,l.frame.radius*e.framing/nt,nt,Rt),a.uniform4f(n.uBound,0,l.bound.y+f,0,l.bound.radius),a.uniformMatrix4fv(n.uBones,false,e.bones),a.uniform1f(n.uScaleFix,h.minScale),a.uniform4fv(n.uFaceA,h.faceA),a.uniform4fv(n.uFaceB,h.faceB),a.uniform4fv(n.uFaceC,h.faceC),a.uniform4fv(n.uFaceD,h.faceD),a.uniform3fv(n.uGlow,h.glow),a.uniform3fv(n.uShadow,e.shadow),a.uniform1f(n.uFloor,e.floor),a.uniform1f(n.uLift,f),a.uniform1f(n.uExposure,e.exposure*h.exposure),a.uniform3fv(n.uAlbedo,e.albedo),a.uniform1f(n.uGlowPool,l.glowPool??0),a.uniform4fv(n.uFxA,e.fx.a),a.uniform4fv(n.uFxB,e.fx.b),a.uniform4fv(n.uFxC,e.fx.c),a.uniform1i(n.uFxCount,e.fx.count),a.drawArrays(a.TRIANGLES,0,3),this.target.globalCompositeOperation="copy",this.target.drawImage(r.canvas,0,r.canvas.height-i,s,i,0,0,s,i),true}dispose(){this.character=null;}};var zt=/^#[0-9a-f]{6}$/i;function Ft(t,e,o,r){if(!e.includes(o))throw new Error(`${t}: palette names material "${o}". Materials are: ${e.join(", ")}.`);if(!zt.test(r))throw new Error(`${t}: palette colour for "${o}" must look like #rrggbb, got "${r}".`)}function lt(t,e){let o=Object.keys(t.materials),r=new Map;for(let[a,s]of Object.entries(e))Ft(t.id,o,a,s),r.set(a,O(s));for(let[a,s]of Object.entries(t.materials)){let i=s.shadeOf;if(!i||r.has(a)||!(i in e))continue;let n=O(t.materials[i].color),l=O(s.color),h=r.get(i);r.set(a,[0,1,2].map(f=>Math.min(1,n[f]>.001?h[f]*l[f]/n[f]:l[f])));}return r}function ct(t,e){let o={...t.materials};for(let[r,a]of lt(t,e))o[r]={...o[r],color:r in e?e[r]:De(a)};return {...t,materials:o}}function ee(t,e){let o=t.albedo.slice();if(!e)return o;for(let[r,a]of lt(t.spec,e))o.set(a,t.materials.indexOf(r)*3);return o}function qt(t,e){let{palette:o,...r}=e,a={...t,...r,motion:{...t.motion,...r.motion}};return o?ct(a,o):a}var Tt=t=>t;var Re=class{members=new Set;frame=0;last=0;time=0;quality=1;slow=0;fast=0;add(e){this.members.add(e),this.start();}delete(e){this.members.delete(e),this.members.size||this.stop();}start(){this.frame||typeof requestAnimationFrame>"u"||(this.last=performance.now(),this.frame=requestAnimationFrame(this.loop));}stop(){cancelAnimationFrame(this.frame),this.frame=0;}loop=e=>{this.frame=requestAnimationFrame(this.loop);let o=Math.max(0,e-this.last),r=Math.min(o/1e3,1/20);this.adapt(o),this.last=e,this.time+=r;for(let a of this.members)a.active&&a.tick(r,this.time,this.quality);};adapt(e){e>22&&e<200?this.slow++:this.slow=Math.max(0,this.slow-1),e<17.5?this.fast++:this.fast=0,this.slow>20?(this.quality=Math.max(.55,this.quality*.85),this.slow=0):this.fast>120&&this.quality<1&&(this.quality=Math.min(1,this.quality*1.08),this.fast=0);}},ze=new Re;var pt=new WeakMap;function ue(t){let e=pt.get(t);return e||pt.set(t,e=Ee(t)),e}var te=class{constructor(e,o,r={}){this.canvas=e;if(this.seed=r.seed??Math.random(),this.palette=r.palette,this.options={interactive:r.interactive??true,effects:r.effects??true,speed:r.speed??1,maxPixelRatio:r.maxPixelRatio??2,shadow:r.shadow??[.05,.06,.12],floor:r.floor??1,exposure:r.exposure??1,framing:r.framing??1,respectReducedMotion:r.respectReducedMotion??true},this.renderer=new K(e),this.load(o,r.state??"idle"),e.setAttribute("role","img"),this.reducedMotion=typeof matchMedia=="function"?matchMedia("(prefers-reduced-motion: reduce)"):null,typeof IntersectionObserver<"u"){let a=new IntersectionObserver(([s])=>this.visible=s.isIntersecting);a.observe(e),this.cleanup.push(()=>a.disconnect());}this.options.interactive&&this.listen(),ze.add(this);}canvas;character;brain;rig;fx;renderer;options;seed;palette;albedo;visible=true;paused=false;time=0;reducedMotion;stillFrames=0;drawn=false;listeners={poke:new Set,state:new Set,ready:new Set};cleanup=[];source;get state(){return this.brain.state}get spec(){return this.source}get stats(){return this.character.stats}setState(e){if(!L.includes(e))throw new Error(`Unknown state "${e}". Expected one of ${L.join(", ")}.`);e!==this.brain.state&&(this.brain.setState(e),this.stillFrames=0,this.label(),this.emit("state",e));}setSpec(e,o){this.palette=o,this.load(e,this.brain.state);}setPalette(e){this.albedo=ee(this.character,e),this.palette=e,this.stillFrames=0;}setSpeed(e){this.options.speed=Math.max(0,e);}setEffects(e){this.options.effects=e;}poke(){this.brain.poke(),this.stillFrames=0,this.emit("poke",void 0);}pause(){this.paused=true;}play(){this.paused=false;}on(e,o){return this.listeners[e].add(o),()=>this.listeners[e].delete(o)}get active(){return !this.visible||this.paused?false:!this.still||this.stillFrames<2}tick(e,o,r){let a=this.still,s=e*this.options.speed;if(a)for(let f=0;f<90;f++)this.brain.update(1/60);else this.brain.update(s),this.time+=s;let i=a?0:this.time,n=this.brain.pose;this.rig.update(n.root,n.channels,n.weights,i,a?0:s),!a&&this.options.effects?this.fx.update(s,n,this.rig):this.fx.count=0,n.events.length=0;let l=Math.min(devicePixelRatio||1,this.options.maxPixelRatio)*r,h=this.renderer.render({pose:n,bones:this.rig.inverse,fx:this.fx,albedo:this.albedo,time:i,width:Math.max(1,Math.round(this.canvas.clientWidth*l)),height:Math.max(1,Math.round(this.canvas.clientHeight*l)),shadow:this.options.shadow,floor:this.options.floor,exposure:this.options.exposure,framing:this.options.framing});h&&a&&this.stillFrames++,h&&!this.drawn&&(this.drawn=true,this.emit("ready",void 0));}get ready(){return this.drawn}dispose(){ze.delete(this),this.cleanup.forEach(e=>e()),this.listeners.poke.clear(),this.listeners.state.clear(),this.listeners.ready.clear(),this.renderer.dispose();}load(e,o){this.source=e,this.character=ue(e),this.albedo=ee(this.character,this.palette),this.renderer.load(this.character),this.brain=new H(e.motion,this.seed),this.brain.setState(o),this.rig=new X(this.character.bones,this.character.acting),this.fx=new G(this.character,Q(this.seed+.37)),this.stillFrames=0,this.label();}get still(){return this.options.respectReducedMotion&&(this.reducedMotion?.matches??false)}emit(e,o){for(let r of this.listeners[e])r(o);}label(){this.canvas.hasAttribute("data-own-label")||this.canvas.setAttribute("aria-label",`${this.source.name}, ${this.brain.state}`);}listen(){let e=a=>{let s=this.canvas.getBoundingClientRect(),i=Math.max(s.width,1),n=(a.clientX-(s.left+s.width/2))/(i*1.1),l=(a.clientY-(s.top+s.height*.45))/(i*1.1);this.brain.pointer=Math.hypot(n,l)<3?{x:n,y:l}:null;},o=()=>this.brain.pointer=null,r=()=>this.poke();window.addEventListener("pointermove",e,{passive:true}),document.addEventListener("pointerleave",o),this.canvas.addEventListener("click",r),this.cleanup.push(()=>{window.removeEventListener("pointermove",e),document.removeEventListener("pointerleave",o),this.canvas.removeEventListener("click",r);});}};function Pt(t,e,o={}){let r=document.createElement("canvas");r.style.cssText="display:block;width:100%;height:100%;touch-action:manipulation",t.append(r);let a=new te(r,e,o),s=a.dispose.bind(a);return a.dispose=()=>{s(),r.remove();},a}var It=()=>new Promise(t=>requestAnimationFrame(t));async function Bt(t,e={}){let o=e.pixelRatio??Math.min(devicePixelRatio||1,2),r=Math.max(1,Math.round((e.size??256)*o)),a=document.createElement("canvas"),s=ue(t),i=new K(a);i.load(s);let n=new H(t.motion,e.seed??.5);n.setState(e.state??"idle");for(let m=0;m<90;m++)n.update(1/60);let l=n.pose,h=new X(s.bones,s.acting);h.update(l.root,l.channels,l.weights,0,0);let f=new G(s,Q(0));f.count=0;let c={pose:l,bones:h.inverse,fx:f,albedo:ee(s,e.palette),time:0,width:r,height:r,shadow:[.05,.06,.12],floor:e.floor??1,exposure:1,framing:e.framing??1};for(;!i.render(c);)await It();return i.dispose(),a}var Lt={submitted:"thinking",streaming:"speaking",error:"error",idle:"idle"};function ve(t,e,o=1400){if(e==="ready"){t.state==="speaking"||t.state==="thinking"?(t.setState("celebrating"),setTimeout(()=>t.state==="celebrating"&&t.setState("idle"),o)):t.setState("idle");return}t.setState(Lt[e]??"idle");}var Ot=["character","state","status","seed","speed","palette","interactive","effects","framing","floor"];function Fe(t){if(!t)return;let e=t.split(";").map(o=>o.split(":").map(r=>r.trim())).filter(([o,r])=>o&&r);return e.length?Object.fromEntries(e):void 0}function Vt(t,e="wobnimo-mascot"){if(typeof customElements>"u"||customElements.get(e))return;let o=new Map(t.map(a=>[a.id,a]));class r extends HTMLElement{static observedAttributes=Ot;instance=null;custom=null;canvas;constructor(){super();let s=this.attachShadow({mode:"open"});s.innerHTML="<style>:host{display:inline-block;width:160px;height:160px;position:relative}canvas{display:block;width:100%;height:100%;touch-action:manipulation}</style>",this.canvas=document.createElement("canvas"),s.append(this.canvas);}get mascot(){return this.instance}get state(){return this.getAttribute("state")??"idle"}set state(s){this.setAttribute("state",s);}get spec(){return this.custom??o.get(this.getAttribute("character")??"")??null}set spec(s){this.custom=s,this.rebuild();}connectedCallback(){this.rebuild();}disconnectedCallback(){this.instance?.dispose(),this.instance=null;}attributeChangedCallback(s,i,n){if(i===n||!this.isConnected)return;let l=this.instance;s==="status"&&l&&n?ve(l,n):s==="state"&&l&&L.includes(n)?l.setState(n):s==="speed"&&l?l.setSpeed(Number(n??1)):s==="effects"&&l?l.setEffects(n!=="false"):s==="palette"&&l?l.setPalette(Fe(n)):s==="character"&&l&&this.spec?l.setSpec(this.spec,Fe(this.getAttribute("palette"))):this.rebuild();}rebuild(){if(!this.isConnected)return;this.instance?.dispose(),this.instance=null;let s=this.spec;if(!s){console.warn(`<${e}>: unknown character "${this.getAttribute("character")}". Registered: ${[...o.keys()].join(", ")}.`);return}let i=this.getAttribute("seed"),n=new te(this.canvas,s,{state:L.includes(this.state)?this.state:"idle",seed:i===null?void 0:Number(i),speed:Number(this.getAttribute("speed")??1),palette:Fe(this.getAttribute("palette")),interactive:this.getAttribute("interactive")!=="false",effects:this.getAttribute("effects")!=="false",framing:Number(this.getAttribute("framing")??1),floor:Number(this.getAttribute("floor")??1)});n.on("poke",()=>this.dispatchEvent(new CustomEvent("poke",{bubbles:true,composed:true}))),n.on("state",h=>this.dispatchEvent(new CustomEvent("statechange",{detail:h,bubbles:true,composed:true}))),n.on("ready",()=>this.dispatchEvent(new CustomEvent("ready",{bubbles:true,composed:true}))),this.instance=n;let l=this.getAttribute("status");l&&ve(n,l);}}customElements.define(e,r);}export{H as Brain,Me as DEFAULT_FX,z as EXPRESSIONS,G as Fx,te as Mascot,X as Rig,L as STATES,pe as SpecError,K as WebGL2Renderer,ee as albedo,Ee as compile,ue as compileCached,Tt as defineCharacter,Vt as defineMascotElement,ve as driveFromStatus,Pt as mount,ct as recolor,Bt as snapshot,qt as variant};
|
|
690
|
+
`);return {spec:t,bones:e.bones,acting:e.acting,anchors:e.anchors,fragment:o,materials:e.materials.map(r=>r.name),albedo:new Float32Array(e.materials.flatMap(r=>j(r.spec.color))),stats:{parts:t.parts.length+(t.eyes?2:0),bones:e.bones.length,materials:e.materials.length,shaderLines:o.split(`
|
|
691
|
+
`).length}}}var $e=(t,e)=>[t[0]+e[0],t[1]+e[1],t[2]+e[2]],Ce=(t,e)=>[t[0]-e[0],t[1]-e[1],t[2]-e[2]],fe=(t,e)=>[t[0]*e,t[1]*e,t[2]*e],at=(t,e)=>t[0]*e[0]+t[1]*e[1]+t[2]*e[2],st=(t,e)=>[t[1]*e[2]-t[2]*e[1],t[2]*e[0]-t[0]*e[2],t[0]*e[1]-t[1]*e[0]],Ae=t=>Math.hypot(t[0],t[1],t[2]);function se(t){let e=Ae(t)||1;return [t[0]/e,t[1]/e,t[2]/e]}var it=["rx","ry","rz"];function $t(t,e){if(typeof t=="number")return t;let[o,r=0,a=0,s=0]=t;return o+r*Math.sin(e*a*Math.PI*2+s)}var K=class{constructor(e,o=e.map(()=>[])){this.bones=e;this.acting=o;this.world=e.map(()=>C()),this.inverse=new Float32Array(e.length*16),this.tips=e.map(()=>null),this.spun=e.map(()=>({rx:0,ry:0,rz:0}));}bones;acting;world;inverse;tips;spun;scratch={t:C(),r:C(),j:C(),inv:C()};point(e,o){return ye(this.world[e],o)}update(e,o,r,a,s){let{t:i,r:n,j:l,inv:h}=this.scratch;this.world[0].set(e);for(let f=1;f<this.bones.length;f++){let c=this.bones[f],m={rx:c.rest?.rx??0,ry:c.rest?.ry??0,rz:c.rest?.rz??0};for(let u of it){for(let[w,x]of c.drive?.[u]??[])m[u]+=o[w]*x;let y=c.wave?.[u];y&&(m[u]+=y[0]*o.energy*Math.sin(a*y[1]*Math.PI*2+y[2]));}for(let[u,y,w]of this.acting[f]){let x=r[u];x<.001&&!(Array.isArray(w)&&w[4])||(m[y]+=x*$t(w,a),Array.isArray(w)&&w[4]&&(this.spun[f][y]+=x*w[4]*s));}for(let u of it)m[u]+=this.spun[f][u];let d=this.world[f];F(d,this.world[c.parentIndex],ie(i,...c.pivot)),F(d,d,O(n,m.rx,m.ry,m.rz)),c.jiggle&&F(d,d,this.jiggle(f,d,s,l,h));}for(let f=0;f<this.bones.length;f++)this.inverse.set(be(h,this.world[f]),f*16);}jiggle(e,o,r,a,s){let{axis:i,length:n,freq:l,damping:h,maxAngle:f=.9}=this.bones[e].jiggle,c=ye(o,[0,0,0]),m=$e(c,fe(se(we(o,i)),n)),d=this.tips[e];if((!d||!(r>0))&&(d=this.tips[e]=d??{x:m,v:[0,0,0]},!(r>0)))return ne(a,[0,1,0],0);let u=l*Math.PI*2;for(let M=0;M<3;M++)d.v[M]+=(u*u*(m[M]-d.x[M])-2*h*u*d.v[M])*r,d.x[M]+=d.v[M]*r;d.x=$e(c,fe(se(Ce(d.x,c)),n)),be(s,o);let y=se(we(s,Ce(d.x,c))),w=se(i),x=st(w,y),E=Ae(x);if(E<1e-6)return ne(a,[0,1,0],0);let A=$(Math.atan2(E,at(w,y)),0,f);return ne(a,fe(x,1/E),A)}};var Ct=48,me=128,At=null,de=class t{static shared(){return At??=new t}canvas=document.createElement("canvas");gl;programs=new Map;parallel;lastSyncBuild=-1/0;constructor(){let e=this.canvas.getContext("webgl2",{alpha:true,premultipliedAlpha:true,antialias:false,depth:false,stencil:false,powerPreference:"high-performance"});if(!e)throw new Error("WebGL2 is not available");this.gl=e,this.parallel=e.getExtension("KHR_parallel_shader_compile"),e.enable(e.SCISSOR_TEST),e.clearColor(0,0,0,0),this.canvas.addEventListener("webglcontextlost",o=>o.preventDefault()),this.canvas.addEventListener("webglcontextrestored",()=>{this.programs.clear(),e.enable(e.SCISSOR_TEST),e.clearColor(0,0,0,0);});}program(e){let o=this.programs.get(e);if(o==="failed")return null;if(o&&"program"in o)return o;if(!o){if(!this.parallel){let a=performance.now();if(a-this.lastSyncBuild<Ct)return null;this.lastSyncBuild=a;}let r=this.start(e);return this.programs.set(e,r),this.parallel?null:this.finish(e,r)}return this.parallel&&!this.gl.getProgramParameter(o.building,this.parallel.COMPLETION_STATUS_KHR)?null:this.finish(e,o)}reserve(e,o){let r=Math.ceil(e/me)*me,a=Math.ceil(o/me)*me;r>this.canvas.width&&(this.canvas.width=r),a>this.canvas.height&&(this.canvas.height=a);}start(e){let{gl:o}=this,r=(n,l)=>{let h=o.createShader(n);return o.shaderSource(h,l),o.compileShader(h),h},a=r(o.VERTEX_SHADER,rt),s=r(o.FRAGMENT_SHADER,e.fragment),i=o.createProgram();return o.attachShader(i,a),o.attachShader(i,s),o.linkProgram(i),{building:i,vertex:a,fragment:s}}finish(e,{building:o,vertex:r,fragment:a}){let{gl:s}=this;if(!s.getProgramParameter(o,s.LINK_STATUS)){let l=s.getShaderInfoLog(a)||s.getProgramInfoLog(o);throw this.programs.set(e,"failed"),new Error(`${e.spec.id}: shader failed to build
|
|
692
|
+
${l}`)}s.deleteShader(r),s.deleteShader(a);let i=Object.fromEntries(Object.keys(he).map(l=>[l,s.getUniformLocation(o,he[l].includes("[")?`${l}[0]`:l)])),n={program:o,uniforms:i,character:e};return this.programs.set(e,n),n}};var nt=.2,Rt=.1,W=class{constructor(e){this.canvas=e;let o=e.getContext("2d");if(!o)throw new Error("Canvas 2D is not available");this.target=o;}canvas;gpu=de.shared();target;character=null;load(e){this.character=e,this.gpu.program(e);}render(e){let o=this.character&&this.gpu.program(this.character);if(!o)return false;let{gpu:r}=this,{gl:a}=r,{width:s,height:i}=e;(this.canvas.width!==s||this.canvas.height!==i)&&(this.canvas.width=s,this.canvas.height=i),r.reserve(s,i),a.viewport(0,0,s,i),a.scissor(0,0,s,i),a.clear(a.COLOR_BUFFER_BIT),a.useProgram(o.program);let n=o.uniforms,{spec:l}=o.character,h=e.pose,f=h.lift;return a.uniform2f(n.uResolution,e.width,e.height),a.uniform1f(n.uTime,e.time),a.uniform4f(n.uCamera,l.frame.target,l.frame.radius*e.framing/nt,nt,Rt),a.uniform4f(n.uBound,0,l.bound.y+f,0,l.bound.radius),a.uniformMatrix4fv(n.uBones,false,e.bones),a.uniform1f(n.uScaleFix,h.minScale),a.uniform4fv(n.uFaceA,h.faceA),a.uniform4fv(n.uFaceB,h.faceB),a.uniform4fv(n.uFaceC,h.faceC),a.uniform4fv(n.uFaceD,h.faceD),a.uniform3fv(n.uGlow,h.glow),a.uniform3fv(n.uShadow,e.shadow),a.uniform1f(n.uFloor,e.floor),a.uniform1f(n.uLift,f),a.uniform1f(n.uExposure,e.exposure*h.exposure),a.uniform3fv(n.uAlbedo,e.albedo),a.uniform1f(n.uGlowPool,l.glowPool??0),a.uniform4fv(n.uFxA,e.fx.a),a.uniform4fv(n.uFxB,e.fx.b),a.uniform4fv(n.uFxC,e.fx.c),a.uniform1i(n.uFxCount,e.fx.count),a.drawArrays(a.TRIANGLES,0,3),this.target.globalCompositeOperation="copy",this.target.drawImage(r.canvas,0,r.canvas.height-i,s,i,0,0,s,i),true}dispose(){this.character=null;}};var zt=/^#[0-9a-f]{6}$/i;function Ft(t,e,o,r){if(!e.includes(o))throw new Error(`${t}: palette names material "${o}". Materials are: ${e.join(", ")}.`);if(!zt.test(r))throw new Error(`${t}: palette colour for "${o}" must look like #rrggbb, got "${r}".`)}function lt(t,e){let o=Object.keys(t.materials),r=new Map;for(let[a,s]of Object.entries(e))Ft(t.id,o,a,s),r.set(a,j(s));for(let[a,s]of Object.entries(t.materials)){let i=s.shadeOf;if(!i||r.has(a)||!(i in e))continue;let n=j(t.materials[i].color),l=j(s.color),h=r.get(i);r.set(a,[0,1,2].map(f=>Math.min(1,n[f]>.001?h[f]*l[f]/n[f]:l[f])));}return r}function ct(t,e){let o={...t.materials};for(let[r,a]of lt(t,e))o[r]={...o[r],color:r in e?e[r]:De(a)};return {...t,materials:o}}function ee(t,e){let o=t.albedo.slice();if(!e)return o;for(let[r,a]of lt(t.spec,e))o.set(a,t.materials.indexOf(r)*3);return o}function qt(t,e){let{palette:o,...r}=e,a={...t,...r,motion:{...t.motion,...r.motion}};return o?ct(a,o):a}var Tt=t=>t;var Re=class{members=new Set;frame=0;last=0;time=0;quality=1;slow=0;fast=0;add(e){this.members.add(e),this.start();}delete(e){this.members.delete(e),this.members.size||this.stop();}start(){this.frame||typeof requestAnimationFrame>"u"||(this.last=performance.now(),this.frame=requestAnimationFrame(this.loop));}stop(){cancelAnimationFrame(this.frame),this.frame=0;}loop=e=>{this.frame=requestAnimationFrame(this.loop);let o=Math.max(0,e-this.last),r=Math.min(o/1e3,1/20);this.adapt(o),this.last=e,this.time+=r;for(let a of this.members)a.active&&a.tick(r,this.time,this.quality);};adapt(e){e>22&&e<200?this.slow++:this.slow=Math.max(0,this.slow-1),e<17.5?this.fast++:this.fast=0,this.slow>20?(this.quality=Math.max(.55,this.quality*.85),this.slow=0):this.fast>120&&this.quality<1&&(this.quality=Math.min(1,this.quality*1.08),this.fast=0);}},ze=new Re;var pt=new WeakMap;function ue(t){let e=pt.get(t);return e||pt.set(t,e=Ee(t)),e}var te=class{constructor(e,o,r={}){this.canvas=e;if(this.seed=r.seed??Math.random(),this.palette=r.palette,this.options={interactive:r.interactive??true,effects:r.effects??true,speed:r.speed??1,maxPixelRatio:r.maxPixelRatio??2,shadow:r.shadow??[.05,.06,.12],floor:r.floor??1,exposure:r.exposure??1,framing:r.framing??1,respectReducedMotion:r.respectReducedMotion??true},this.renderer=new W(e),this.load(o,r.state??"idle"),e.setAttribute("role","img"),this.reducedMotion=typeof matchMedia=="function"?matchMedia("(prefers-reduced-motion: reduce)"):null,typeof IntersectionObserver<"u"){let a=new IntersectionObserver(([s])=>this.visible=s.isIntersecting);a.observe(e),this.cleanup.push(()=>a.disconnect());}this.options.interactive&&this.listen(),ze.add(this);}canvas;character;brain;rig;fx;renderer;options;seed;palette;albedo;visible=true;paused=false;time=0;reducedMotion;stillFrames=0;drawn=false;listeners={poke:new Set,state:new Set,ready:new Set};cleanup=[];source;get state(){return this.brain.state}get spec(){return this.source}get stats(){return this.character.stats}setState(e){if(!V.includes(e))throw new Error(`Unknown state "${e}". Expected one of ${V.join(", ")}.`);e!==this.brain.state&&(this.brain.setState(e),this.stillFrames=0,this.label(),this.emit("state",e));}setSpec(e,o){this.palette=o,this.load(e,this.brain.state);}setPalette(e){this.albedo=ee(this.character,e),this.palette=e,this.stillFrames=0;}setSpeed(e){this.options.speed=Math.max(0,e);}setEffects(e){this.options.effects=e;}poke(){this.brain.poke(),this.stillFrames=0,this.emit("poke",void 0);}pause(){this.paused=true;}play(){this.paused=false;}on(e,o){return this.listeners[e].add(o),()=>this.listeners[e].delete(o)}get active(){return !this.visible||this.paused?false:!this.still||this.stillFrames<2}tick(e,o,r){let a=this.still,s=e*this.options.speed;if(a)for(let f=0;f<90;f++)this.brain.update(1/60);else this.brain.update(s),this.time+=s;let i=a?0:this.time,n=this.brain.pose;this.rig.update(n.root,n.channels,n.weights,i,a?0:s),!a&&this.options.effects?this.fx.update(s,n,this.rig):this.fx.count=0,n.events.length=0;let l=Math.min(devicePixelRatio||1,this.options.maxPixelRatio)*r,h=this.renderer.render({pose:n,bones:this.rig.inverse,fx:this.fx,albedo:this.albedo,time:i,width:Math.max(1,Math.round(this.canvas.clientWidth*l)),height:Math.max(1,Math.round(this.canvas.clientHeight*l)),shadow:this.options.shadow,floor:this.options.floor,exposure:this.options.exposure,framing:this.options.framing});h&&a&&this.stillFrames++,h&&!this.drawn&&(this.drawn=true,this.emit("ready",void 0));}get ready(){return this.drawn}dispose(){ze.delete(this),this.cleanup.forEach(e=>e()),this.listeners.poke.clear(),this.listeners.state.clear(),this.listeners.ready.clear(),this.renderer.dispose();}load(e,o){this.source=e,this.character=ue(e),this.albedo=ee(this.character,this.palette),this.renderer.load(this.character),this.brain=new G(e.motion,this.seed),this.brain.setState(o),this.rig=new K(this.character.bones,this.character.acting),this.fx=new U(this.character,Q(this.seed+.37)),this.stillFrames=0,this.label();}get still(){return this.options.respectReducedMotion&&(this.reducedMotion?.matches??false)}emit(e,o){for(let r of this.listeners[e])r(o);}label(){this.canvas.hasAttribute("data-own-label")||this.canvas.setAttribute("aria-label",`${this.source.name}, ${this.brain.state}`);}listen(){let e=a=>{let s=this.canvas.getBoundingClientRect(),i=Math.max(s.width,1),n=(a.clientX-(s.left+s.width/2))/(i*1.1),l=(a.clientY-(s.top+s.height*.45))/(i*1.1);this.brain.pointer=Math.hypot(n,l)<3?{x:n,y:l}:null;},o=()=>this.brain.pointer=null,r=()=>this.poke();window.addEventListener("pointermove",e,{passive:true}),document.addEventListener("pointerleave",o),this.canvas.addEventListener("click",r),this.cleanup.push(()=>{window.removeEventListener("pointermove",e),document.removeEventListener("pointerleave",o),this.canvas.removeEventListener("click",r);});}};function Pt(t,e,o={}){let r=document.createElement("canvas");r.style.cssText="display:block;width:100%;height:100%;touch-action:manipulation",t.append(r);let a=new te(r,e,o),s=a.dispose.bind(a);return a.dispose=()=>{s(),r.remove();},a}var It=()=>new Promise(t=>requestAnimationFrame(t));async function Bt(t,e={}){let o=e.pixelRatio??Math.min(devicePixelRatio||1,2),r=Math.max(1,Math.round((e.size??256)*o)),a=document.createElement("canvas"),s=ue(t),i=new W(a);i.load(s);let n=new G(t.motion,e.seed??.5);n.setState(e.state??"idle");for(let m=0,d=Math.round((e.settle??1.5)*60);m<d;m++)n.update(1/60);let l=n.pose;e.turn&&F(l.root,O(C(),0,e.turn,0),l.root);let h=new K(s.bones,s.acting);h.update(l.root,l.channels,l.weights,0,0);let f=new U(s,Q(0));f.count=0;let c={pose:l,bones:h.inverse,fx:f,albedo:ee(s,e.palette),time:0,width:r,height:r,shadow:[.05,.06,.12],floor:e.floor??1,exposure:1,framing:e.framing??1};for(;!i.render(c);)await It();return i.dispose(),a}var Lt={submitted:"thinking",streaming:"speaking",error:"error",idle:"idle"};function ve(t,e,o=1400){if(e==="ready"){t.state==="speaking"||t.state==="thinking"?(t.setState("celebrating"),setTimeout(()=>t.state==="celebrating"&&t.setState("idle"),o)):t.setState("idle");return}t.setState(Lt[e]??"idle");}var Ot=["character","state","status","seed","speed","palette","interactive","effects","framing","floor"];function Fe(t){if(!t)return;let e=t.split(";").map(o=>o.split(":").map(r=>r.trim())).filter(([o,r])=>o&&r);return e.length?Object.fromEntries(e):void 0}function Vt(t,e="wobnimo-mascot"){if(typeof customElements>"u"||customElements.get(e))return;let o=new Map(t.map(a=>[a.id,a]));class r extends HTMLElement{static observedAttributes=Ot;instance=null;custom=null;canvas;constructor(){super();let s=this.attachShadow({mode:"open"});s.innerHTML="<style>:host{display:inline-block;width:160px;height:160px;position:relative}canvas{display:block;width:100%;height:100%;touch-action:manipulation}</style>",this.canvas=document.createElement("canvas"),s.append(this.canvas);}get mascot(){return this.instance}get state(){return this.getAttribute("state")??"idle"}set state(s){this.setAttribute("state",s);}get spec(){return this.custom??o.get(this.getAttribute("character")??"")??null}set spec(s){this.custom=s,this.rebuild();}connectedCallback(){this.rebuild();}disconnectedCallback(){this.instance?.dispose(),this.instance=null;}attributeChangedCallback(s,i,n){if(i===n||!this.isConnected)return;let l=this.instance;s==="status"&&l&&n?ve(l,n):s==="state"&&l&&V.includes(n)?l.setState(n):s==="speed"&&l?l.setSpeed(Number(n??1)):s==="effects"&&l?l.setEffects(n!=="false"):s==="palette"&&l?l.setPalette(Fe(n)):s==="character"&&l&&this.spec?l.setSpec(this.spec,Fe(this.getAttribute("palette"))):this.rebuild();}rebuild(){if(!this.isConnected)return;this.instance?.dispose(),this.instance=null;let s=this.spec;if(!s){console.warn(`<${e}>: unknown character "${this.getAttribute("character")}". Registered: ${[...o.keys()].join(", ")}.`);return}let i=this.getAttribute("seed"),n=new te(this.canvas,s,{state:V.includes(this.state)?this.state:"idle",seed:i===null?void 0:Number(i),speed:Number(this.getAttribute("speed")??1),palette:Fe(this.getAttribute("palette")),interactive:this.getAttribute("interactive")!=="false",effects:this.getAttribute("effects")!=="false",framing:Number(this.getAttribute("framing")??1),floor:Number(this.getAttribute("floor")??1)});n.on("poke",()=>this.dispatchEvent(new CustomEvent("poke",{bubbles:true,composed:true}))),n.on("state",h=>this.dispatchEvent(new CustomEvent("statechange",{detail:h,bubbles:true,composed:true}))),n.on("ready",()=>this.dispatchEvent(new CustomEvent("ready",{bubbles:true,composed:true}))),this.instance=n;let l=this.getAttribute("status");l&&ve(n,l);}}customElements.define(e,r);}export{G as Brain,Se as DEFAULT_FX,z as EXPRESSIONS,U as Fx,te as Mascot,K as Rig,V as STATES,pe as SpecError,W as WebGL2Renderer,ee as albedo,Ee as compile,ue as compileCached,Tt as defineCharacter,Vt as defineMascotElement,ve as driveFromStatus,Pt as mount,ct as recolor,Bt as snapshot,qt as variant};
|