@idosgames/characters 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +38 -2
- package/dist/PartsManager-CAVBKvp6.d.ts +589 -0
- package/dist/PartsManager-Cn3MU-VS.d.cts +589 -0
- package/dist/chunk-64D567CX.js +1 -0
- package/dist/chunk-BU66AZ2Z.js +1 -0
- package/dist/chunk-CGF2TQVK.js +1 -0
- package/dist/chunk-OF4BH3JZ.js +2 -0
- package/dist/chunk-WKHHFTK2.js +1 -0
- package/dist/chunk-Z5I76WRJ.js +1 -0
- package/dist/contract-DhZuKNIf.d.cts +24 -0
- package/dist/contract-DhZuKNIf.d.ts +24 -0
- package/dist/gltf/index.cjs +1 -0
- package/dist/gltf/index.d.cts +150 -0
- package/dist/gltf/index.d.ts +150 -0
- package/dist/gltf/index.js +1 -0
- package/dist/image-D5NaQeFz.d.cts +8 -0
- package/dist/image-D5NaQeFz.d.ts +8 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +65 -0
- package/dist/index.d.ts +65 -0
- package/dist/index.js +1 -0
- package/dist/rig2d/editor/index.cjs +81 -0
- package/dist/rig2d/editor/index.d.cts +25 -0
- package/dist/rig2d/editor/index.d.ts +25 -0
- package/dist/rig2d/editor/index.js +81 -0
- package/dist/rig2d/index.cjs +17 -0
- package/dist/rig2d/index.d.cts +190 -0
- package/dist/rig2d/index.d.ts +190 -0
- package/dist/rig2d/index.js +17 -0
- package/dist/rig2d/phaser/index.cjs +2 -0
- package/dist/rig2d/phaser/index.d.cts +106 -0
- package/dist/rig2d/phaser/index.d.ts +106 -0
- package/dist/rig2d/phaser/index.js +1 -0
- package/dist/rig2d/three/index.cjs +2 -0
- package/dist/rig2d/three/index.d.cts +63 -0
- package/dist/rig2d/three/index.d.ts +63 -0
- package/dist/rig2d/three/index.js +1 -0
- package/dist/thumbnail-BhGEEXux.d.cts +49 -0
- package/dist/thumbnail-Bp-jK70T.d.ts +49 -0
- package/dist/voxel/index.cjs +54 -0
- package/dist/voxel/index.d.cts +972 -0
- package/dist/voxel/index.d.ts +972 -0
- package/dist/voxel/index.js +54 -0
- package/package.json +101 -4
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { V as Viseme } from './contract-DhZuKNIf.js';
|
|
2
|
+
export { a as ACTOR_POSES, b as ACTOR_SOCKETS, c as ActorKind, d as ActorPose, A as ActorSocket, e as EMOTIONS, E as Emotion, S as STYLE_FAMILIES, f as StyleFamily, g as VISEMES, i as isEmotion, h as isViseme } from './contract-DhZuKNIf.js';
|
|
3
|
+
export { R as RGBAImage } from './image-D5NaQeFz.js';
|
|
4
|
+
|
|
5
|
+
/** Слово реплики со временем от начала реплики, секунды. */
|
|
6
|
+
interface SpokenWord {
|
|
7
|
+
text: string;
|
|
8
|
+
start: number;
|
|
9
|
+
end: number;
|
|
10
|
+
}
|
|
11
|
+
/** Ключ формы рта: с `t` (секунды от начала реплики) до следующего ключа. */
|
|
12
|
+
interface VisemeKey {
|
|
13
|
+
t: number;
|
|
14
|
+
v: Viseme;
|
|
15
|
+
}
|
|
16
|
+
interface SpeechLayout {
|
|
17
|
+
words: SpokenWord[];
|
|
18
|
+
visemes: VisemeKey[];
|
|
19
|
+
}
|
|
20
|
+
/** Форма рта для буквы; null — буква не двигает губы заметно (рот чуть приоткрыт — «Э»). */
|
|
21
|
+
declare function visemeOfLetter(ch: string): Viseme | null;
|
|
22
|
+
/**
|
|
23
|
+
* Раскладка реплики на `duration` секунд. `words` — таймкоды слов выравнивания (если есть);
|
|
24
|
+
* их тексты должны идти в том же порядке, что слова `text`.
|
|
25
|
+
*/
|
|
26
|
+
declare function layoutSpeech(text: string, duration: number, words?: readonly SpokenWord[]): SpeechLayout;
|
|
27
|
+
/** Форма рта в момент `t` (секунды от начала реплики). */
|
|
28
|
+
declare function visemeAt(keys: readonly VisemeKey[], t: number): Viseme;
|
|
29
|
+
/** Слово под курсором `t`: индекс в `words` или -1 (пауза). */
|
|
30
|
+
declare function wordAt(words: readonly SpokenWord[], t: number): number;
|
|
31
|
+
|
|
32
|
+
type Lang = "en" | "ru";
|
|
33
|
+
/** Текущий язык текстов пакета. */
|
|
34
|
+
declare function lang(): Lang;
|
|
35
|
+
/** Сменить язык в памяти (игра при своём выборе языка, тесты). */
|
|
36
|
+
declare function setLang(l: Lang): void;
|
|
37
|
+
/** Текст на двух языках; строка — один текст для обоих (числа, эмодзи, имена). */
|
|
38
|
+
type Loc = string | {
|
|
39
|
+
en: string;
|
|
40
|
+
ru: string;
|
|
41
|
+
};
|
|
42
|
+
/** Текст на текущем языке; `{name}` в нём заменяются из vars. */
|
|
43
|
+
declare function tr(text: Loc, vars?: Record<string, string | number>): string;
|
|
44
|
+
|
|
45
|
+
/** Генератор случайных чисел [0, 1) по 32-битному сиду. */
|
|
46
|
+
declare function mulberry32(seed: number): () => number;
|
|
47
|
+
/** Хэш строки в 32-битный сид (FNV-1a). */
|
|
48
|
+
declare function hashString(str: string): number;
|
|
49
|
+
|
|
50
|
+
type JsonExtract = {
|
|
51
|
+
ok: true;
|
|
52
|
+
value: unknown;
|
|
53
|
+
} | {
|
|
54
|
+
ok: false;
|
|
55
|
+
error: string;
|
|
56
|
+
truncated: boolean;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Достаёт первый JSON-объект из текста модели: срезает ```json-обёртку и болтовню вокруг.
|
|
60
|
+
* Обрезанный ответ (модель упёрлась в лимит токенов — движок такой считает успехом и списывает)
|
|
61
|
+
* распознаётся по незакрытым скобкам: `truncated: true`.
|
|
62
|
+
*/
|
|
63
|
+
declare function extractJsonObject(text: string): JsonExtract;
|
|
64
|
+
|
|
65
|
+
export { type JsonExtract, type Lang, type Loc, type SpeechLayout, type SpokenWord, Viseme, type VisemeKey, extractJsonObject, hashString, lang, layoutSpeech, mulberry32, setLang, tr, visemeAt, visemeOfLetter, wordAt };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{e as ACTOR_POSES,f as ACTOR_SOCKETS,a as EMOTIONS,g as STYLE_FAMILIES,c as VISEMES,b as isEmotion,d as isViseme}from'./chunk-64D567CX.js';export{d as extractJsonObject,a as lang,b as setLang,c as tr}from'./chunk-WKHHFTK2.js';export{b as hashString,a as mulberry32}from'./chunk-CGF2TQVK.js';var k=new Set([..."a\u0430\u044F\xE4"]),E=new Set([..."eiy\u044D\u0435\u0438\u044B\u0439\u0451\xE9\xE8\xEA"]),W=new Set([..."ou\u043E\u0443\u044Ew\xF6\xFC"]),w=new Set([..."mbp\u043C\u0431\u043F"]),O=new Set([..."fv\u0444\u0432"]);function x(t){let e=t.toLowerCase();return k.has(e)?"A":E.has(e)?"E":W.has(e)?"O":w.has(e)?"MBP":O.has(e)?"FV":null}var g=t=>/\p{L}|\p{N}/u.test(t),A=t=>{let e=x(t);return e==="A"||e==="E"||e==="O"};function m(t){return g(t)?A(t)?1:.6:/[.!?…]/.test(t)?3:/[,;:—–-]/.test(t)?1.6:/\s/.test(t)?.35:0}function j(t,e,r){let o=Math.max(0,e),f=t.match(/\S+/g)??[];if(f.length===0||o===0)return {words:[],visemes:[{t:0,v:"rest"}]};let c=r&&r.length===f.length?r.map(n=>({...n})):K(t,o),s=[{t:0,v:"rest"}];for(let n of c){let i=[...n.text].filter(g),p=i.reduce((l,u)=>l+m(u),0)||1,d=n.start;for(let l of i){let u=x(l)??"E";s[s.length-1].v!==u&&s.push({t:a(d),v:u}),d+=(n.end-n.start)*m(l)/p;}s.push({t:a(n.end),v:"rest"});}return {words:c,visemes:M(s)}}function K(t,e){let r=[...t],o=r.reduce((n,i)=>n+m(i),0)||1,f=[],c=0,s=null;for(let n of r){let i=e*m(n)/o;/\s/.test(n)?(s&&f.push({text:s.text,start:a(s.start),end:a(c)}),s=null):s?s.text+=n:s={text:n,start:c},c+=i;}return s&&f.push({text:s.text,start:a(s.start),end:a(c)}),f.map(n=>{let i=/[^\p{L}\p{N}]+$/u.exec(n.text)?.[0].length??0;if(i===0)return n;let p=[...n.text],d=p.reduce((u,h)=>u+m(h),0)||1,l=p.slice(p.length-i).reduce((u,h)=>u+m(h),0);return {...n,end:a(n.end-(n.end-n.start)*l/d)}})}function C(t,e){let r="rest";for(let o of t){if(o.t>e)break;r=o.v;}return r}function F(t,e){for(let r=0;r<t.length;r++){let o=t[r];if(e>=o.start&&e<o.end)return r}return -1}var a=t=>Math.round(t*1e3)/1e3;function M(t){let e=[];for(let r of t){let o=e[e.length-1];o&&o.t===r.t?e[e.length-1]=r:(!o||o.v!==r.v)&&e.push(r);}return e}export{j as layoutSpeech,C as visemeAt,x as visemeOfLetter,F as wordAt};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
'use strict';var react=require('react'),_=require('phaser'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var ___default=/*#__PURE__*/_interopDefault(_);var U=Math.PI/180,vt=1e-5;function Et(a,t){return a.type==="ik"?new J(a,t):new wt(a,t)}var kt=a=>a>180?a-360:a<=-180?a+360:a,J=class{constructor(t,e){this.data=t;this.bones=t.bones.map(n=>e.bones[n.index]),this.target=e.bones[t.target.index],this.mix=t.mix,this.bendDirection=t.bendDirection;}data;mix;bendDirection;bones;target;setupPose(){this.mix=this.data.mix,this.bendDirection=this.data.bendDirection;}sort(t){t.sortBone(this.target);let e=this.bones[0];t.sortBone(e),t.pushConstraint(this),e.sorted=false,t.sortReset(e.children);}update(t){if(this.mix===0)return;let e=this.target.applied;this.bones.length===1?Xt(t,this.bones[0].applied,e.worldX,e.worldY,this.mix):Qt(t,this.bones[0].applied,this.bones[1].applied,e.worldX,e.worldY,this.bendDirection,this.mix);}};function Xt(a,t,e,n,o){let r=t.bone.parent;if(!r)return;t.modifyLocal(a);let s=r.applied,i=s.a,l=s.b,c=s.c,h=s.d,d=-t.shearX-t.rotation,f=i*h-l*c,u=e-s.worldX,m=n-s.worldY,x=(u*h-m*l)/f-t.x,b=(m*i-u*c)/f-t.y;d+=Math.atan2(b,x)/U,t.scaleX<0&&(d+=180),t.rotation+=kt(d)*o;}function Qt(a,t,e,n,o,r,s){t.modifyLocal(a),e.modifyLocal(a);let i=t.x,l=t.y,c=t.scaleX,h=t.scaleY,d=e.scaleX,f,u,m;c<0?(c=-c,f=180,m=-1):(f=0,m=1),h<0&&(h=-h,m=-m),d<0?(d=-d,u=180):u=0;let x=Math.abs(c-h)<=vt,b,p;x?(b=t.a*e.x+t.b*e.y+t.worldX,p=t.c*e.x+t.d*e.y+t.worldY):(e.y=0,b=t.a*e.x+t.worldX,p=t.c*e.x+t.worldY);let M=t.bone.parent;if(!M)return;let S=M.applied,k=S.a,A=S.b,Y=S.c,X=S.d,I=k*X-A*Y,g=b-S.worldX,y=p-S.worldY;I=Math.abs(I)<=vt?0:1/I;let w=(g*X-y*A)*I-i,C=(y*k-g*Y)*I-l,v=Math.sqrt(w*w+C*C),P=e.bone.data.length*d;if(v<vt){Xt(a,t,n,o,s),e.rotation=0;return}g=n-S.worldX,y=o-S.worldY;let D=(g*X-y*A)*I-i,L=(y*k-g*Y)*I-l,ot=D*D+L*L,N=0,H=0;if(x){P*=c;let E=(ot-v*v-P*P)/(2*v*P);E<-1?(E=-1,H=Math.PI*r):E>1?(E=1,H=0):H=Math.acos(E)*r;let V=v+P*E,F=P*Math.sin(H);N=Math.atan2(L*V-D*F,D*V+L*F);}else {let E=c*P,V=h*P,F=E*E,Q=V*V,xt=Math.atan2(L,D),R=Q*v*v+F*ot-F*Q,rt=-2*Q*v,Dt=Q-F,Yt=rt*rt-4*Dt*R,$t=false;if(Yt>=0){let B=Math.sqrt(Yt);rt<0&&(B=-B),B=-(rt+B)*.5;let W=B/Dt,z=R/B,q=Math.abs(W)<Math.abs(z)?W:z,Z=ot-q*q;if(Z>=0){let G=Math.sqrt(Z)*r;N=xt-Math.atan2(G,q),H=Math.atan2(G/h,(q-v)/c),$t=true;}}if(!$t){let B=Math.PI,W=v-E,z=W*W,q=0,Z=0,G=v+E,yt=G*G,Lt=0;if(R=-E*v/(F-Q),R>=-1&&R<=1){R=Math.acos(R);let st=E*Math.cos(R)+v,it=V*Math.sin(R),at=st*st+it*it;at<z&&(B=R,z=at,W=st,q=it),at>yt&&(Z=R,yt=at,G=st,Lt=it);}ot<=(z+yt)*.5?(N=xt-Math.atan2(q*r,W),H=B*r):(N=xt-Math.atan2(Lt*r,G),H=Z*r);}}let It=Math.atan2(e.y,e.x)*m;N=kt((N-It)/U+f-t.rotation),H=kt(((H+It)/U-e.shearX)*m+u-e.rotation),t.rotation+=N*s,e.rotation+=H*s;}var wt=class{constructor(t,e){this.data=t;this.source=e.bones[t.source.index],this.bones=t.bones.map(n=>e.bones[n.index]),this.mix={...t.mix};}data;mix;source;bones;setupPose(){Object.assign(this.mix,this.data.mix);}sort(t){t.sortBone(this.source);for(let e of this.bones)t.sortBone(e);t.pushConstraint(this);for(let e of this.bones)t.sortReset(e.children);for(let e of this.bones)e.sorted=true;}update(t){let e=this.mix;if(!e.rotate&&!e.x&&!e.y&&!e.scaleX&&!e.scaleY&&!e.shearY)return;let n=this.source.applied,o=this.data.offsets;for(let r of this.bones){let s=r.applied;s.modifyWorld(t);for(let i of this.data.properties){let l=Zt(t,n,i.prop,o)-i.offset;for(let c of i.to){let h=e[c.prop];h!==0&&te(t,s,c.prop,c.offset+l*c.scale,h);}}}}};function Zt(a,t,e,n){let o=a.scaleX,r=a.scaleY;switch(e){case "rotate":{let s=(t.a*t.d-t.b*t.c)*o*r>0?1:-1,i=Math.atan2(t.c/r,t.a/o)/U+s*n.rotate;return i<0&&(i+=360),i}case "x":return (n.x*t.a+n.y*t.b+t.worldX)/o;case "y":return (n.x*t.c+n.y*t.d+t.worldY)/r;case "scaleX":return Math.hypot(t.a/o,t.c/r)+n.scaleX;case "scaleY":return Math.hypot(t.b/o,t.d/r)+n.scaleY;case "shearY":return (Math.atan2(t.d/r,t.b/o)-Math.atan2(t.c/r,t.a/o))/U-90+n.shearY}}function te(a,t,e,n,o){let r=a.scaleX,s=a.scaleY;switch(e){case "rotate":{let i=t.a/r,l=t.b/r,c=t.c/s,h=t.d/s,d=n*U-Math.atan2(c,i);d>Math.PI?d-=2*Math.PI:d<-Math.PI&&(d+=2*Math.PI),d*=o;let f=Math.cos(d),u=Math.sin(d);t.a=(f*i-u*c)*r,t.b=(f*l-u*h)*r,t.c=(u*i+f*c)*s,t.d=(u*l+f*h)*s;return}case "x":t.worldX+=(n-t.worldX/r)*o*r;return;case "y":t.worldY+=(n-t.worldY/s)*o*s;return;case "scaleX":{let i=Math.hypot(t.a/r,t.c/s);i!==0&&(i=1+(n-i)*o/i,t.a*=i,t.c*=i);return}case "scaleY":{let i=Math.hypot(t.b/r,t.d/s);i!==0&&(i=1+(n-i)*o/i,t.b*=i,t.d*=i);return}case "shearY":{let i=t.b/r,l=t.d/s,c=Math.atan2(l,i),h=(n+90)*U;h-=c-Math.atan2(t.c/s,t.a/r),h>Math.PI?h-=2*Math.PI:h<-Math.PI&&(h+=2*Math.PI),h=c+h*o;let d=Math.hypot(i,l);t.b=Math.cos(h)*d*r,t.d=Math.sin(h)*d*s;return}}}function Rt(a){let t=/^#?([0-9a-f]{6})$/i.exec(a.trim());return t?parseInt(t[1],16):16777215}var Ht=new WeakMap;function lt(a){let t=Ht.get(a);if(t)return t;t=new Map;for(let e of a.skins.values())for(let n of e.attachments.values())for(let o of n.values())t.has(o.path)||t.set(o.path,{w:o.width,h:o.height});return Ht.set(a,t),t}function ct(a,t){let e=a.skins.get(t);if(!e)return [];let n=new Set;for(let o of e.attachments.values())for(let r of o.values())n.add(r.path);return [...n]}var j=class{constructor(t,e=()=>true){this.rig=t;this.drawable=e;let n=(o,r)=>t.colorTargets.find(s=>(s.into??"tint")===r&&s.slotPrefixes.some(i=>o.startsWith(i)))?.id??null;this.slotTarget=t.data.slots.map(o=>n(o.name,"tint")),this.slotArt=t.data.slots.map(o=>n(o.name,"art")),this.rebuildLists(),this.init();}rig;drawable;chosen=new Map;hidden=new Map;colors=new Map;lists=new Map;listeners=new Set;slotTarget;slotArt;face=null;emotionFace=null;speech="rest";setDrawable(t){let e=new Set(this.rig.partTypes.filter(n=>!this.count(n.id)).map(n=>n.id));this.drawable=t,this.rebuildLists();for(let n of this.rig.partTypes){if(n.auto)continue;let o=this.chosen.get(n.id);(o&&!this.lists.get(n.id).includes(o)||!o&&e.has(n.id))&&this.chosen.set(n.id,this.first(n));}this.emit({kind:"part",type:"*",skin:null});}on(t){return this.listeners.add(t),()=>this.listeners.delete(t)}emit(t){for(let e of [...this.listeners])e(t);}typeDef(t){return this.rig.partTypes.find(e=>e.id===t)}list(t){return this.lists.get(t)??[]}count(t){return this.list(t).length}part(t){return this.chosen.get(t)??null}index(t){let e=this.part(t);return e?this.list(t).indexOf(e):-1}isHidden(t){return this.hidden.get(t)??false}isWorn(t){return this.part(t)!==null&&!this.isHidden(t)}color(t){return this.colors.get(t)??null}wornSkins(){let t=new Map;for(let c of this.rig.partTypes)t.set(c.id,!c.auto&&this.isWorn(c.id)?this.part(c.id):null);let e={worn:c=>t.get(c)??null,setWorn:(c,h)=>t.set(c,h),exists:c=>this.rig.data.skins.has(c)&&this.drawable(c)};for(let c of this.rig.rules)c.apply(e);let n=this.rig.expressions,o=this.face??this.emotionFace,r=o?n?.faces[o]:void 0;for(let[c,h]of Object.entries(r??{}))t.get(c)&&e.exists(h)&&t.set(c,h);let s=this.speech!=="rest"?n?.speech:void 0,i=s?.visemes[this.speech];s&&i&&t.get(s.type)&&e.exists(i)&&t.set(s.type,i);let l=[];for(let c of this.rig.partTypes){let h=t.get(c.id);h&&l.push(h);}return l}slotColor(t){let e=this.slotTarget[t];return e?this.color(e):null}artColor(t){let e=this.slotArt[t];return e?this.color(e):null}expression(){return this.face}equip(t,e){let n=this.lists.get(t);if(!n)return;let o;if(e===null||e===-1)o=null;else if(typeof e=="number")o=n[Math.max(0,Math.min(n.length-1,e))]??null;else if(n.includes(e))o=e;else return;o===null&&!this.typeDef(t)?.canHide||(this.chosen.set(t,o),this.emit({kind:"part",type:t,skin:o}));}unequip(t){this.equip(t,null);}setHidden(t,e){this.typeDef(t)?.canHide&&(this.hidden.set(t,e),this.emit({kind:"hidden",type:t,hidden:e}));}next(t){let e=this.count(t);if(!e)return;let n=this.index(t);this.typeDef(t)?.canHide?this.equip(t,n>=e-1?-1:n+1):this.equip(t,(n+1)%e);}prev(t){let e=this.count(t);if(!e)return;let n=this.index(t);this.typeDef(t)?.canHide?this.equip(t,n<=-1?e-1:n-1):this.equip(t,(n-1+e)%e);}setColor(t,e){this.colors.set(t,e),this.emit({kind:"color",target:t,color:e});}setExpression(t){let e=t&&this.rig.expressions?.faces[t]?t:null;e!==this.face&&(this.face=e,this.emit({kind:"expression",name:e}));}setEmotion(t){let e=this.rig.expressions?.emotions?.[t]??null,n=e&&this.rig.expressions?.faces[e]?e:null;n!==this.emotionFace&&(this.emotionFace=n,this.emit({kind:"expression",name:this.face??n}));}setSpeech(t){t!==this.speech&&(this.speech=t,this.emit({kind:"speech",viseme:t}));}randomize(t=Math.random){for(let e of this.rig.partTypes){if(e.auto)continue;let n=this.count(e.id);n&&this.equip(e.id,e.canHide&&t()<.3?-1:Math.floor(t()*n));}}reset(){this.init();for(let t of this.rig.partTypes)this.emit({kind:"part",type:t.id,skin:this.part(t.id)});}toLook(){let t={};for(let n of this.rig.partTypes)n.auto||(t[n.id]=this.isWorn(n.id)?this.part(n.id):null);let e={};for(let[n,o]of this.colors)o&&(e[n]=o);return {v:1,parts:t,colors:e}}applyLook(t){for(let[e,n]of Object.entries(t.parts??{}))n===void 0||this.typeDef(e)?.auto||(this.equip(e,n),n!==null&&this.part(e)===n&&this.hidden.set(e,false));for(let[e,n]of Object.entries(t.colors??{}))n&&this.setColor(e,n);}rebuildLists(){for(let t of this.rig.partTypes)this.lists.set(t.id,this.rig.data.skinOrder.filter(e=>e.startsWith(t.skinPrefix)&&this.drawable(e)));}first(t){return this.lists.get(t.id)?.[0]??null}init(){this.chosen.clear(),this.hidden.clear(),this.colors.clear();for(let t of this.rig.partTypes)this.chosen.set(t.id,t.auto?null:this.first(t));}};function ht(a,t,e=1,n={}){let o=Math.max(1,Math.ceil(t.w*e)),r=Math.max(1,Math.ceil(t.h*e)),s=n.paint??a.paint,i=n.light?ee(t,n.light):"";return `<svg xmlns="http://www.w3.org/2000/svg" width="${o}" height="${r}" viewBox="0 0 ${t.w} ${t.h}"${s?` color="${s}"`:""}>${i}<g stroke-linejoin="round" stroke-linecap="round"${i?' filter="url(#cel)"':""}>${a.svg}</g></svg>`}var tt={depth:.18,min:2.6,max:11,dark:.3,shine:.36};function ee(a,t){let e=Math.max(tt.min,Math.min(tt.max,Math.min(a.w,a.h)*tt.depth)),n=o=>+o.toFixed(2);return `<defs><filter id="cel" filterUnits="userSpaceOnUse" x="0" y="0" width="${a.w}" height="${a.h}" color-interpolation-filters="sRGB"><feMorphology in="SourceAlpha" operator="erode" radius="${n(3.6*.7)}" result="body"/><feOffset in="body" dx="${n(t.x*e)}" dy="${n(t.y*e)}" result="moved"/><feComposite in="body" in2="moved" operator="out" result="far"/><feFlood flood-color="#000000" flood-opacity="${tt.dark}"/><feComposite in2="far" operator="in" result="dark"/><feMorphology in="SourceAlpha" operator="erode" radius="${n(3.6*1.05)}" result="inner"/><feOffset in="inner" dx="${n(-t.x*e*.42)}" dy="${n(-t.y*e*.42)}" result="back"/><feComposite in="inner" in2="back" operator="out" result="near"/><feFlood flood-color="#ffffff" flood-opacity="${tt.shine}"/><feComposite in2="near" operator="in" result="shine"/><feMerge><feMergeNode in="SourceGraphic"/><feMergeNode in="dark"/><feMergeNode in="shine"/></feMerge></filter></defs>`}var Bt=Math.PI/180,ne=new Float32Array([0,1,0,0,1,0,1,1]),oe=new Uint16Array([0,1,2,2,3,0]),Ot=new WeakMap;function re(a){let t=Ot.get(a);if(t)return t;let e=-a.width/2*a.scaleX,n=-a.height/2*a.scaleY,o=a.width/2*a.scaleX,r=a.height/2*a.scaleY,s=Math.cos(a.rotation*Bt),i=Math.sin(a.rotation*Bt),l=(c,h)=>[c*s-h*i+a.x,c*i+h*s+a.y];return t=Float32Array.from([...l(e,n),...l(e,r),...l(o,r),...l(o,n)]),Ot.set(a,t),t}function K(a,t,e,n){if(e.type==="region"){let o=n&&n.length===8?n:new Float32Array(8),r=re(e),s=t.bone.applied;for(let i=0;i<8;i+=2){let l=r[i],c=r[i+1];o[i]=l*s.a+c*s.b+s.worldX,o[i+1]=l*s.c+c*s.d+s.worldY;}return {positions:o,uvs:ne,triangles:oe}}return se(a,t,e,n)}function se(a,t,e,n){let o=e.vertexCount*2,r=n&&n.length===o?n:new Float32Array(o),s=e.vertices;if(e.weighted){let i=0;for(let l=0;l<o;l+=2){let c=s[i++],h=0,d=0;for(let f=0;f<c;f++,i+=4){let u=a.bones[s[i]].applied,m=s[i+1],x=s[i+2],b=s[i+3];h+=(m*u.a+x*u.b+u.worldX)*b,d+=(m*u.c+x*u.d+u.worldY)*b;}r[l]=h,r[l+1]=d;}}else {let i=t.bone.applied;for(let l=0;l<o;l+=2){let c=s[l],h=s[l+1];r[l]=c*i.a+h*i.b+i.worldX,r[l+1]=c*i.c+h*i.d+i.worldY;}}return {positions:r,uvs:e.uvs,triangles:e.triangles}}var et=Math.PI/180,Mt=1e-5,dt=class{constructor(t){this.bone=t;}bone;x=0;y=0;rotation=0;scaleX=1;scaleY=1;shearX=0;shearY=0;a=1;b=0;c=0;d=1;worldX=0;worldY=0;world=0;local=0;copyLocal(t){this.x=t.x,this.y=t.y,this.rotation=t.rotation,this.scaleX=t.scaleX,this.scaleY=t.scaleY,this.shearX=t.shearX,this.shearY=t.shearY;}update(t){this.world!==t.updateId&&this.updateWorldTransform(t);}updateWorldTransform(t){this.local===t.updateId?this.updateLocalTransform(t):this.world=t.updateId;let e=(this.rotation+this.shearX)*et,n=(this.rotation+90+this.shearY)*et,o=Math.cos(e)*this.scaleX,r=Math.cos(n)*this.scaleY,s=Math.sin(e)*this.scaleX,i=Math.sin(n)*this.scaleY,l=this.bone.parent;if(!l){let h=t.scaleX,d=t.scaleY;this.a=o*h,this.b=r*h,this.c=s*d,this.d=i*d,this.worldX=this.x*h+t.x,this.worldY=this.y*d+t.y;return}let c=l.applied;this.worldX=c.a*this.x+c.b*this.y+c.worldX,this.worldY=c.c*this.x+c.d*this.y+c.worldY,this.a=c.a*o+c.b*s,this.b=c.a*r+c.b*i,this.c=c.c*o+c.d*s,this.d=c.c*r+c.d*i;}updateLocalTransform(t){this.local=0,this.world=t.updateId;let e=this.bone.parent;if(!e){this.x=(this.worldX-t.x)/t.scaleX,this.y=(this.worldY-t.y)/t.scaleY,this.set5(this.a/t.scaleX,this.b/t.scaleX,this.c/t.scaleY,this.d/t.scaleY);return}let n=e.applied,o=1/(n.a*n.d-n.b*n.c),r=n.d*o,s=n.b*o,i=n.c*o,l=n.a*o,c=this.worldX-n.worldX,h=this.worldY-n.worldY;this.x=c*r-h*s,this.y=h*l-c*i,this.set5(r*this.a-s*this.c,r*this.b-s*this.d,l*this.c-i*this.a,l*this.d-i*this.b);}set5(t,e,n,o){this.shearX=0;let r=t*t+n*n,s=e*e+o*o;if(r>Mt){let i=Math.atan2(n,t)/et;this.rotation=i,this.scaleX=Math.sqrt(r),this.scaleY=Math.sqrt(s),s>Mt?(this.shearY=Math.atan2(o,e)/et,t*o-e*n<0?(this.scaleY=-this.scaleY,this.shearY+=90-i):this.shearY-=90+i,this.shearY>180?this.shearY-=360:this.shearY<=-180&&(this.shearY+=360)):this.shearY=0;}else this.scaleX=0,this.scaleY=Math.sqrt(s),this.shearY=0,this.rotation=s>Mt?Math.atan2(o,e)/et-90:0;}modifyLocal(t){this.local===t.updateId&&this.updateLocalTransform(t),this.world=0,this.resetWorld(t);}modifyWorld(t){this.local=t.updateId,this.world=t.updateId,this.resetWorld(t);}resetWorld(t){for(let e of this.bone.children){let n=e.applied;n.world===t.updateId&&(n.local===t.updateId&&n.updateLocalTransform(t),n.world=0,n.resetWorld(t));}}},pt=class{constructor(t){this.data=t;this.pose=new dt(this),this.applied=new dt(this),this.setupPose();}data;pose;applied;parent=null;children=[];sorted=false;setupPose(){let t=this.data,e=this.pose;e.x=t.x,e.y=t.y,e.rotation=t.rotation,e.scaleX=t.scaleX,e.scaleY=t.scaleY,e.shearX=0,e.shearY=0;}},St=class{constructor(t,e){this.data=t;this.bone=e;this.color={...t.color},this.attachmentKey=t.attachment;}data;bone;color;attachmentKey;attachment=null},O=class{constructor(t){this.data=t;this.bones=t.bones.map(e=>new pt(e));for(let e of this.bones)e.data.parent&&(e.parent=this.bones[e.data.parent.index],e.parent.children.push(e));this.slots=t.slots.map(e=>new St(e,this.bones[e.bone.index])),this.constraints=t.constraints.map(e=>Et(e,this)),this.updateCache();}data;bones;slots;constraints;skins=[];scaleX=1;scaleY=1;x=0;y=0;updateId=0;cache=[];bone(t){return this.bones[this.data.bone(t).index]}slot(t){return this.slots[this.data.slot(t).index]}setSkins(t){this.skins=[...t],this.resolveAttachments();}getAttachment(t,e){for(let n=this.skins.length-1;n>=0;n--){let o=this.skins[n].attachments.get(t)?.get(e);if(o)return o}return null}resolveAttachments(){for(let t of this.slots)t.attachment=t.attachmentKey?this.getAttachment(t.data.index,t.attachmentKey):null;}setupPose(){for(let t of this.bones)t.setupPose();for(let t of this.constraints)t.setupPose();for(let t of this.slots)Object.assign(t.color,t.data.color),t.attachmentKey=t.data.attachment;}updateWorldTransform(){this.updateId++;for(let t of this.bones)t.applied.copyLocal(t.pose),t.applied.world=0,t.applied.local=0;for(let t of this.cache)t instanceof pt?t.applied.update(this):t.update(this);}updateCache(){this.cache=[];for(let t of this.bones)t.sorted=false;for(let t of this.constraints)t.sort(this);for(let t of this.bones)this.sortBone(t);}sortBone(t){t.sorted||(t.parent&&this.sortBone(t.parent),t.sorted=true,this.cache.push(t));}sortReset(t){for(let e of t)e.sorted&&this.sortReset(e.children),e.sorted=false;}pushConstraint(t){this.cache.push(t);}};var Nt=new WeakMap;function ut(a,t){let e=Nt.get(a);if(e)return e;e=new Map;let n=new O(a);n.setupPose(),n.updateWorldTransform();let[o,r]=t.light;for(let s of a.skins.values())for(let[i,l]of s.attachments)for(let c of l.values()){if(e.has(c.path)||t.skip?.some(b=>c.path.startsWith(b)))continue;let h=K(n,n.slots[i],c,null),d=ie(h.positions,h.uvs,c.width,c.height);if(!d)continue;let f=d.a*d.d-d.b*d.c;if(Math.abs(f)<1e-9)continue;let u=(d.d*o-d.b*r)/f,m=(-d.c*o+d.a*r)/f,x=Math.hypot(u,m)||1;e.set(c.path,{x:u/x,y:m/x});}return Nt.set(a,e),e}function ie(a,t,e,n){let o=t.length/2;if(o<3)return null;let r=0,s=0,i=0,l=0;for(let p=0;p<o;p++)r+=t[p*2]*e,s+=t[p*2+1]*n,i+=a[p*2],l+=a[p*2+1];r/=o,s/=o,i/=o,l/=o;let c=0,h=0,d=0,f=0,u=0,m=0,x=0;for(let p=0;p<o;p++){let M=t[p*2]*e-r,S=t[p*2+1]*n-s,k=a[p*2]-i,A=a[p*2+1]-l;c+=M*M,h+=M*S,d+=S*S,f+=k*M,u+=k*S,m+=A*M,x+=A*S;}let b=c*d-h*h;return Math.abs(b)<1e-9?null:{a:(f*d-u*h)/b,b:(u*c-f*h)/b,c:(m*d-x*h)/b,d:(x*c-m*h)/b}}function Ft(a,t,e=2){let n=lt(a.data),o=a.shading?ut(a.data,a.shading):new Map,r=new Map;return {image(s,i){let l=t.get(s),c=l?.paint?i??null:null,h=c?`${s}${c}`:s,d=r.get(h);if(d)return d;let f=n.get(s);return d=l&&f?new Promise(u=>{let m=new Image;m.onload=()=>u(m),m.onerror=()=>u(null),m.src=`data:image/svg+xml;charset=utf-8,${encodeURIComponent(ht(l,f,e,{paint:c,light:o.get(s)??null}))}`;}):Promise.resolve(null),r.set(h,d),d}}}function Wt(a,t){let e=new Map,n=new O(a.data),o=(s,i,l)=>{let[c,h,d]=l.tint;if(!l.fill&&c===1&&h===1&&d===1)return i;let f=`${s}|${l.fill??`${c.toFixed(3)},${h.toFixed(3)},${d.toFixed(3)}`}`,u=e.get(f);if(u)return u;u=document.createElement("canvas"),u.width=i.width,u.height=i.height;let m=u.getContext("2d");return m.drawImage(i,0,0),m.globalCompositeOperation=l.fill?"source-in":"multiply",m.fillStyle=l.fill??`rgb(${c*255}, ${h*255}, ${d*255})`,m.fillRect(0,0,u.width,u.height),l.fill||(m.globalCompositeOperation="destination-in",m.drawImage(i,0,0)),e.set(f,u),u},r=(s,i,l,c,h,d)=>{let f=n;f.setSkins(s.flatMap(x=>a.data.skins.get(x)?[a.data.skins.get(x)]:[])),f.setupPose(),a.data.animations.get(d.animation)?.apply(f,d.time),f.resolveAttachments(),f.updateWorldTransform();let u=i?new Set(i):null,m=[];return f.slots.forEach((x,b)=>{let p=x.attachment;if(!p||u&&!u.has(x.data.name))return;let M=l?.(b)??null,S=M?ce(M):[x.color.r,x.color.g,x.color.b],k=x.color.a*p.color.a;if(k<=0)return;let A=K(f,x,p,null);m.push({path:p.path,paint:c?.(b)??null,positions:Float32Array.from(A.positions),uvs:A.uvs,triangles:A.triangles,tint:[S[0]*p.color.r,S[1]*p.color.g,S[2]*p.color.b],alpha:k,fill:h});}),m};return {async draw(s,i){let l=i.pose??{animation:a.defaultAnimation,time:0},c=i.backdrop?r(i.backdrop.skins,i.backdrop.slots,void 0,void 0,i.backdrop.color,l):[],h=r(i.skins,i.slots,i.slotColor,i.artColor,null,l),d=[...c,...h],f=await Promise.all(d.map(k=>t.image(k.path,k.paint))),u=i.frame==="content"||!c.length?h:c,m=ae(u.length?u:d),x=s.getContext("2d");if(x.setTransform(1,0,0,1,0,0),x.clearRect(0,0,s.width,s.height),!m)return;let b=(i.padding??.08)*Math.min(s.width,s.height),p=Math.min((s.width-b*2)/Math.max(1,m.w),(s.height-b*2)/Math.max(1,m.h)),M=s.width/2-(m.x+m.w/2)*p,S=s.height/2+(m.y+m.h/2)*p;d.forEach((k,A)=>{let Y=f[A];if(!Y)return;let X=o(k.paint?`${k.path}${k.paint}`:k.path,Y,k);x.globalAlpha=k.alpha;let I=k.triangles,g=v=>M+k.positions[v*2]*p,y=v=>S-k.positions[v*2+1]*p,w=v=>k.uvs[v*2]*Y.width,C=v=>k.uvs[v*2+1]*Y.height;for(let v=0;v<I.length;v+=3){let P=I[v],D=I[v+1],L=I[v+2];le(x,X,g(P),y(P),g(D),y(D),g(L),y(L),w(P),C(P),w(D),C(D),w(L),C(L));}}),x.globalAlpha=1;}}}function ae(a){let t=1/0,e=1/0,n=-1/0,o=-1/0;for(let r of a)for(let s=0;s<r.positions.length;s+=2)t=Math.min(t,r.positions[s]),n=Math.max(n,r.positions[s]),e=Math.min(e,r.positions[s+1]),o=Math.max(o,r.positions[s+1]);return t===1/0?null:{x:t,y:e,w:n-t,h:o-e}}function le(a,t,e,n,o,r,s,i,l,c,h,d,f,u){let m=h-l,x=d-c,b=f-l,p=u-c,M=m*p-b*x;if(Math.abs(M)<1e-9)return;let S=o-e,k=r-n,A=s-e,Y=i-n,X=(S*p-A*x)/M,I=(k*p-Y*x)/M,g=(A*m-S*b)/M,y=(Y*m-k*b)/M,w=(e+o+s)/3,C=(n+r+i)/3,v=(P,D)=>{let L=Math.hypot(P-w,D-C)||1;return [P+(P-w)/L*.6,D+(D-C)/L*.6]};a.save(),a.beginPath(),a.moveTo(...v(e,n)),a.lineTo(...v(o,r)),a.lineTo(...v(s,i)),a.closePath(),a.clip(),a.transform(X,I,g,y,e-X*l-g*c,n-I*l-y*c),a.drawImage(t,0,0),a.restore();}function ce(a){let t=parseInt(a.replace("#",""),16);return [(t>>16&255)/255,(t>>8&255)/255,(t&255)/255]}var qt=new WeakMap;function he(a,t,e){return `chr:${a}@${t}${e||""}`}function Gt(a,t,e,n,o,r,s={}){let i=e.paint?s.paint??null:null,l=he(t,o,i);if(a.exists(l))return l;let c=qt.get(a);c||qt.set(a,c=new Map);let h=c.get(l);if(h)return h.push(r),null;let d=[r];c.set(l,d);let f=new Image,u=()=>{c.delete(l);for(let m of d)m();};return f.onload=()=>{a.exists(l)||a.addImage(l,f),u();},f.onerror=()=>{console.warn(`[character] art ${t} did not render`),u();},f.src="data:image/svg+xml;charset=utf-8,"+encodeURIComponent(ht(e,n,o,{paint:i,light:s.light??null})),null}function Ut(a,t,e=2){return {has:n=>t.has(n),texture(n,o,r,s){let i=t.get(n);return i?Gt(a,n,i,o,e,r,s):null}}}var mt=class{constructor(t,e,n=.2){this.skeleton=t;this.data=e;this.defaultMix=n;this.snapshot=new Float32Array(t.bones.length*5),this.slotSnapshot=new Float32Array(t.slots.length*4),this.ikSnapshot=new Float32Array(t.constraints.length);}skeleton;data;defaultMix;track=null;previous=null;mixTime=0;mixDuration=0;listeners=new Map;snapshot;slotSnapshot;ikSnapshot;blink=null;setBlink(t){let e=t?this.data.animations.get(t.animation):void 0;if(!t||!e){this.blink=null;return}let n={bones:new Set(t.bones.map(o=>this.data.bone(o).index)),slots:new Set(t.slots.map(o=>this.data.slot(o).index))};this.blink={source:e,filter:n,options:t,wait:this.nextBlink(t),at:-1};}blinkNow(){this.blink&&(this.blink.at=0);}blinking(){return (this.blink?.at??-1)>=0}setRandom(t){this.random=t;}random=Math.random;nextBlink(t){return t.every[0]+this.random()*(t.every[1]-t.every[0])}names(){return [...this.data.animations.keys()]}has(t){return this.data.animations.has(t)}play(t,e={}){let n=this.data.animations.get(t);if(!n)return false;let o=e.mix??this.defaultMix;return this.previous=this.track&&o>0?this.track:null,this.mixTime=0,this.mixDuration=this.previous?o:0,this.track={animation:n,time:Math.max(0,e.from??0),speed:e.speed??1,loop:e.loop??true,done:false},true}current(){return this.track?.animation.name??null}time(){return this.track?this.local(this.track):0}duration(){return this.track?.animation.duration??0}finished(){return this.track?.done??false}setSpeed(t){this.track&&(this.track.speed=t);}on(t,e){let n=this.listeners.get(t)??new Set;return n.add(e),this.listeners.set(t,n),()=>n.delete(e)}update(t){let e=[],n=this.track;if(n&&!n.done){let o=n.time;n.time+=Math.max(0,t)*n.speed,this.collect(n,o,n.time,e),!n.loop&&n.time>=n.animation.duration&&(n.time=n.animation.duration,n.done=true,e.push({name:"end",animation:n.animation.name}));}if(this.previous){let o=this.previous;o.time+=Math.max(0,t)*o.speed,this.mixTime+=Math.max(0,t),this.mixTime>=this.mixDuration&&(this.previous=null);}this.advanceBlink(Math.max(0,t)),this.pose();for(let o of e){for(let r of this.listeners.get(o.name)??[])r(o);for(let r of this.listeners.get("*")??[])r(o);}}pose(){let t=this.skeleton,e=this.previous;e&&this.mixDuration>0&&(t.setupPose(),e.animation.apply(t,this.local(e)),this.save()),t.setupPose(),this.track&&this.track.animation.apply(t,this.local(this.track)),e&&this.mixDuration>0&&this.blendFromSaved(Math.min(1,this.mixTime/this.mixDuration));let n=this.blink;n&&n.at>=0&&n.source.applyOnly(t,n.options.from+n.at,n.filter),t.resolveAttachments();}advanceBlink(t){let e=this.blink;if(e){if(this.track?.animation.touches(e.filter)){e.at=-1;return}if(e.at>=0){e.at+=t,e.at>=e.options.to-e.options.from&&(e.at=-1,e.wait=this.nextBlink(e.options));return}e.wait-=t,e.wait<=0&&(e.at=0);}}local(t){let e=t.animation.duration;return e<=0?0:t.loop?t.time%e:Math.min(t.time,e)}collect(t,e,n,o){let r=t.animation.duration;if(r<=0||n<=e)return;let s=Math.floor(e/r),i=t.loop?Math.floor(n/r):0;for(let l=s;l<=i;l++)for(let c of t.animation.events){let h=l*r+c.time;h>=e&&(h<n||!t.loop&&h<=n)&&o.push({name:c.name,animation:t.animation.name});}}save(){let t=this.skeleton;t.bones.forEach((e,n)=>{let o=e.pose;this.snapshot.set([o.x,o.y,o.rotation,o.scaleX,o.scaleY],n*5);}),t.slots.forEach((e,n)=>this.slotSnapshot.set([e.color.r,e.color.g,e.color.b,e.color.a],n*4)),t.constraints.forEach((e,n)=>{e instanceof J&&(this.ikSnapshot[n]=e.mix);});}blendFromSaved(t){let e=this.skeleton,n=(o,r)=>o+(r-o)*t;e.bones.forEach((o,r)=>{let s=this.snapshot,i=o.pose,l=r*5;i.x=n(s[l],i.x),i.y=n(s[l+1],i.y);let c=i.rotation-s[l+2];c-=Math.round(c/360)*360,i.rotation=s[l+2]+c*t,i.scaleX=n(s[l+3],i.scaleX),i.scaleY=n(s[l+4],i.scaleY);}),e.slots.forEach((o,r)=>{let s=this.slotSnapshot;o.color.r=n(s[r*4],o.color.r),o.color.g=n(s[r*4+1],o.color.g),o.color.b=n(s[r*4+2],o.color.b),o.color.a=n(s[r*4+3],o.color.a);}),e.constraints.forEach((o,r)=>{o instanceof J&&(o.mix=n(this.ikSnapshot[r],o.mix));});}};var ft=class{constructor(t,e){this.scene=t;let n=this.rig=e.rig;this.art=e.art,this.skeleton=new O(n.data),this.sizes=lt(n.data),this.lights=n.shading?ut(n.data,n.shading):new Map,this.parts=new j(n,o=>this.drawsSkin(o)),e.look&&this.parts.applyLook(e.look),this.offs.push(this.parts.on(()=>this.skinsDirty=true)),this.animator=new mt(this.skeleton,n.data,n.mix),this.animator.setBlink(n.blink??null),this.play(e.animation??n.defaultAnimation,{mix:0}),this.root=t.add.container(e.x??0,e.y??0);for(let o=0;o<this.skeleton.slots.length;o++){let r=new ___default.default.GameObjects.Mesh2D(t,0,0,"__DEFAULT",[],[],true);r.setRenderAsTriangles(true),r.setVisible(false),this.root.add(r),this.slots.push({mesh:r,positions:null,vertices:[],indices:[],path:null,key:null,paint:null,waiting:false});}if(this.setScale(e.scale??1),e.autoUpdate!==false){let o=(r,s)=>this.update(s/1e3);t.events.on(___default.default.Scenes.Events.UPDATE,o),this.offs.push(()=>t.events.off(___default.default.Scenes.Events.UPDATE,o));}this.root.once(___default.default.GameObjects.Events.DESTROY,()=>{for(let o of this.offs.splice(0))o();}),this.update(0);}scene;root;skeleton;animator;parts;slots=[];sizes;lights;skinsDirty=true;overlay=null;flashUntil=0;flashColor=16777215;facing=1;size=1;offs=[];asked=null;rig;art;play(t,e){return this.asked={name:t,...e?{options:e}:{}},this.animator.play(this.stanceOf(t),e)}animation(){return this.asked?.name??null}stanceOf(t){let e=this.parts;return this.rig.stance?.(t,n=>e.isWorn(n)?e.part(n):null)??t}on(t,e){let n=this.animator.on(t,e);return this.offs.push(n),n}setLook(t){this.parts.applyLook(t);}setArt(t){this.art=t;for(let e of this.slots)e.key=e.path=null,e.waiting=false;this.parts.setDrawable(e=>this.drawsSkin(e));}setPosition(t,e){return this.root.setPosition(t,e),this}setScale(t){return this.size=t,this.root.setScale(t*this.facing,t),this}setFacing(t){return this.facing=t,this.setScale(this.size)}setDepth(t){return this.root.setDepth(t),this}setVisible(t){return this.root.setVisible(t),this}setAlpha(t){return this.root.setAlpha(t),this}setOverlay(t){return this.overlay=t,this}flash(t=16777215,e=90){this.flashColor=t,this.flashUntil=this.scene.time.now+e;}worldPoint(t){let e=this.rig.anchors[t]??t,n=this.skeleton.bone(e).applied,o=this.root.getWorldTransformMatrix();return {x:o.tx+o.a*n.worldX+o.c*-n.worldY,y:o.ty+o.b*n.worldX+o.d*-n.worldY}}get displayHeight(){return this.rig.data.height*this.size}destroy(){this.root.destroy();}update(t){let e=this.skeleton,n=this.rig.expressions;if(n&&this.parts.setExpression(n.byAnimation[this.animator.current()??""]??null),this.skinsDirty){this.skinsDirty=false,e.setSkins(this.parts.wornSkins().flatMap(s=>{let i=this.rig.data.skins.get(s);return i?[i]:[]}));let r=this.asked;r&&this.stanceOf(r.name)!==this.animator.current()&&this.animator.play(this.stanceOf(r.name),{...r.options,mix:.15});}this.animator.update(t),e.slots.forEach((r,s)=>{let i=this.parts.slotColor(s);if(!i)return;let l=Rt(i);r.color.r=(l>>16&255)/255,r.color.g=(l>>8&255)/255,r.color.b=(l&255)/255,r.color.a=1;}),e.updateWorldTransform();let o=this.flashUntil>this.scene.time.now;e.slots.forEach((r,s)=>this.drawSlot(s,o));}drawSlot(t,e){let n=this.slots[t],o=this.skeleton.slots[t],r=o.attachment,s=n.mesh;if(!r||o.color.a<=0){s.setVisible(false);return}let i=this.parts.artColor(t);if((n.path!==r.path||n.paint!==i)&&(n.path=r.path,n.paint=i,n.key=null,n.waiting=false),!n.key&&!n.waiting){let b=this.sizes.get(r.path)??{w:r.width,h:r.height},p=r.path,M=this.art.texture(p,b,()=>{n.path===p&&(n.waiting=false);},{paint:i,light:this.lights.get(p)??null});M?(n.key=M,s.setTexture(M)):n.waiting=true;}if(!n.key){s.setVisible(false);return}let l=K(this.skeleton,o,r,n.positions);n.positions=l.positions;let c=l.uvs.length/2,h=n.vertices;h.length=c*4;for(let b=0;b<c;b++)h[b*4]=l.positions[b*2],h[b*4+1]=-l.positions[b*2+1],h[b*4+2]=l.uvs[b*2],h[b*4+3]=l.uvs[b*2+1];let d=l.triangles,f=n.indices;if(f.length!==d.length/3*4){f.length=0;for(let b=0;b<d.length;b+=3)f.push(d[b],d[b+1],d[b+2],0);}else for(let b=0,p=0;b<d.length;b+=3,p+=4)f[p]=d[b],f[p+1]=d[b+1],f[p+2]=d[b+2];s.vertices=h,s.indices=f;let u=o.color,m=r.color,x=Math.round(u.r*m.r*255)<<16|Math.round(u.g*m.g*255)<<8|Math.round(u.b*m.b*255);this.overlay!==null&&(x=de(x,this.overlay)),e?s.setTint(this.flashColor).setTintMode(___default.default.TintModes.FILL):s.setTint(x).setTintMode(___default.default.TintModes.MULTIPLY),s.setAlpha(u.a*m.a),s.setVisible(true);}drawsSkin(t){return ct(this.rig.data,t).every(e=>this.art.has(e))}};function de(a,t){let e=n=>Math.round((a>>n&255)*(t>>n&255)/255)<<n;return e(16)|e(8)|e(0)}function Vt(a,t){return new Promise(e=>{let{width:n,height:o}=t;class r extends ___default.default.Scene{create(){let l=t.scale??1,c=Ut(this.textures,t.catalog,Math.max(2,Math.ceil(l*1.5))),h=new ft(this,{rig:t.rig,art:c,...t.look?{look:t.look}:{},x:n/2,y:Math.round(o*.88),scale:l});e({view:h,game:s,vector:c,destroy:()=>s.destroy(true)});}}let s=new ___default.default.Game({type:___default.default.WEBGL,parent:a,width:n,height:o,transparent:!t.background,...t.background?{backgroundColor:t.background}:{},scene:r,banner:false,audio:{noAudio:true}});})}function me(a){let t=parseInt(a.replace("#",""),16),e=(t>>16&255)/255,n=(t>>8&255)/255,o=(t&255)/255,r=Math.max(e,n,o),s=r-Math.min(e,n,o),i=0;return s&&(r===e?i=(n-o)/s%6:r===n?i=(o-e)/s+2:i=(e-n)/s+4,i=(i*60+360)%360),{h:i,s:r?s/r:0,v:r}}function Jt({h:a,s:t,v:e}){let n=o=>{let r=(o+a/60)%6;return Math.round((e-e*t*Math.max(0,Math.min(r,4-r,1)))*255)};return `#${(n(5)<<16|n(3)<<8|n(1)).toString(16).padStart(6,"0")}`}function jt(a){let t=me(a.value),[e,n]=react.useState(t.h);react.useEffect(()=>{t.s>.02&&t.v>.02&&n(t.h);},[t.h,t.s,t.v]);let o=react.useRef(null),r=react.useRef(null),s=(i,l)=>c=>{let h=i.current;if(!h)return;let d=u=>{let m=h.getBoundingClientRect();l(Math.max(0,Math.min(1,(u.clientX-m.left)/m.width)),Math.max(0,Math.min(1,(u.clientY-m.top)/m.height)));};d(c);let f=()=>{window.removeEventListener("pointermove",d),window.removeEventListener("pointerup",f);};window.addEventListener("pointermove",d),window.addEventListener("pointerup",f);};return jsxRuntime.jsxs("div",{className:"ce-picker",children:[jsxRuntime.jsx("div",{ref:o,className:"ce-sv",style:{background:`linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, hsl(${e} 100% 50%))`},onPointerDown:s(o,(i,l)=>a.onChange(Jt({h:e,s:i,v:1-l}))),children:jsxRuntime.jsx("span",{className:"ce-knob",style:{left:`${t.s*100}%`,top:`${(1-t.v)*100}%`}})}),jsxRuntime.jsx("div",{ref:r,className:"ce-hue",onPointerDown:s(r,i=>{n(i*359.9),a.onChange(Jt({h:i*359.9,s:Math.max(t.s,.05),v:Math.max(t.v,.05)}));}),children:jsxRuntime.jsx("span",{className:"ce-knob",style:{left:`${e/360*100}%`,top:"50%"}})})]})}var Kt=`
|
|
2
|
+
.ce-root { display: flex; gap: 0; align-items: stretch; font-family: "Trebuchet MS", "Segoe UI", sans-serif;
|
|
3
|
+
color: #fff; background: #1f2a22; border-radius: 14px; overflow: hidden; min-height: 600px; user-select: none; }
|
|
4
|
+
.ce-title { font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; text-align: center;
|
|
5
|
+
font-size: 14px; margin: 14px 0 10px; text-shadow: 0 2px 0 #0006; }
|
|
6
|
+
.ce-presets { width: 200px; background: #3a3d45; padding: 0 10px 12px; flex: none; }
|
|
7
|
+
.ce-preset-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
|
|
8
|
+
.ce-preset { background: transparent; border: 2px solid transparent; border-radius: 8px; padding: 0;
|
|
9
|
+
cursor: pointer; aspect-ratio: 3 / 4; }
|
|
10
|
+
.ce-preset:hover { background: #ffffff12; }
|
|
11
|
+
.ce-preset.ce-on { border-color: #fff; background: #ffffff1a; }
|
|
12
|
+
.ce-preset canvas { width: 100%; height: 100%; display: block; }
|
|
13
|
+
.ce-scene { position: relative; flex: 1; min-width: 360px; display: flex; flex-direction: column;
|
|
14
|
+
align-items: center; justify-content: flex-end;
|
|
15
|
+
background: radial-gradient(ellipse 34% 9% at 50% 84%, #6d4a35 0 70%, transparent 72%),
|
|
16
|
+
radial-gradient(ellipse 60% 30% at 50% 82%, #7a5a40 0 40%, transparent 70%),
|
|
17
|
+
linear-gradient(#3f6e45, #4f7f4c 55%, #446f43); }
|
|
18
|
+
.ce-stage { flex: none; max-width: 100%; }
|
|
19
|
+
.ce-stage canvas { width: 100% !important; height: auto !important; display: block; }
|
|
20
|
+
.ce-actions { display: flex; gap: 14px; margin: 6px 0 22px; }
|
|
21
|
+
.ce-big { font: inherit; font-weight: 800; font-size: 17px; letter-spacing: 0.05em; text-transform: uppercase;
|
|
22
|
+
color: #fff; border: 3px solid #1d1d2a; border-radius: 6px; padding: 12px 22px; cursor: pointer;
|
|
23
|
+
box-shadow: inset 0 -5px 0 #0003; text-shadow: 0 2px 0 #0007; }
|
|
24
|
+
.ce-big:active { transform: translateY(2px); box-shadow: inset 0 -2px 0 #0003; }
|
|
25
|
+
.ce-random { background: #5b55d9; }
|
|
26
|
+
.ce-reset { background: #f28a3a; }
|
|
27
|
+
.ce-options { width: 290px; background: #2d2f37; flex: none; display: flex; flex-direction: column; }
|
|
28
|
+
.ce-options-head { display: flex; align-items: center; justify-content: center; position: relative;
|
|
29
|
+
min-height: 46px; }
|
|
30
|
+
.ce-close { position: absolute; right: 10px; top: 9px; width: 28px; height: 28px; border-radius: 6px;
|
|
31
|
+
border: 2px solid #1d1d2a; background: #e2433f; color: #fff; font-weight: 800; cursor: pointer; }
|
|
32
|
+
.ce-option-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; padding: 10px; overflow-y: auto;
|
|
33
|
+
flex: 1; align-content: start; }
|
|
34
|
+
.ce-option { background: #3a3d48; border: 2px solid transparent; border-radius: 6px; aspect-ratio: 1; padding: 0;
|
|
35
|
+
cursor: pointer; position: relative; }
|
|
36
|
+
.ce-option:hover { background: #474b58; }
|
|
37
|
+
.ce-option.ce-on { background: #56607c; border-color: #dfe6ff; }
|
|
38
|
+
.ce-option canvas { width: 100%; height: 100%; display: block; }
|
|
39
|
+
.ce-none { position: absolute; inset: 22%; border: 3px solid #8a8fa0; border-radius: 50%; }
|
|
40
|
+
.ce-none::after { content: ""; position: absolute; left: 50%; top: -10%; bottom: -10%; width: 3px;
|
|
41
|
+
background: #8a8fa0; transform: rotate(45deg); }
|
|
42
|
+
.ce-picker { padding: 4px 18px 12px; }
|
|
43
|
+
.ce-sv { position: relative; height: 130px; border-radius: 4px; border: 2px solid #1d1d2a; cursor: crosshair;
|
|
44
|
+
touch-action: none; }
|
|
45
|
+
.ce-hue { position: relative; height: 12px; margin-top: 12px; border-radius: 6px; cursor: pointer; touch-action: none;
|
|
46
|
+
background: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00); }
|
|
47
|
+
.ce-knob { position: absolute; width: 12px; height: 12px; margin: -6px 0 0 -6px; border-radius: 50%;
|
|
48
|
+
border: 2px solid #fff; box-shadow: 0 0 0 1px #0008; pointer-events: none; }
|
|
49
|
+
.ce-sv .ce-knob { margin: -6px 0 0 -6px; }
|
|
50
|
+
.ce-paint-reset { font: inherit; font-size: 11px; margin-top: 8px; background: none; color: #c8cbe0;
|
|
51
|
+
border: 1px solid #555a6c; border-radius: 4px; padding: 2px 8px; cursor: pointer; }
|
|
52
|
+
.ce-parts { width: 300px; background: #6b4532; padding: 0 12px 12px; flex: none; display: flex; flex-direction: column; }
|
|
53
|
+
.ce-tile-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 7px; }
|
|
54
|
+
.ce-tile { position: relative; aspect-ratio: 1.1; background: #8a5a3e; border: 3px solid #4a2c20; border-radius: 4px;
|
|
55
|
+
padding: 0; cursor: pointer; }
|
|
56
|
+
.ce-tile.ce-worn { background: #2f73b5; }
|
|
57
|
+
.ce-tile.ce-open { border-color: #fff; }
|
|
58
|
+
.ce-tile canvas { width: 100%; height: 100%; display: block; }
|
|
59
|
+
.ce-tile.ce-hidden canvas { opacity: 0.35; }
|
|
60
|
+
.ce-eye { position: absolute; right: 3px; top: 3px; width: 20px; height: 20px; border-radius: 50%; border: none;
|
|
61
|
+
background: #fff; color: #2b2b38; font-size: 11px; line-height: 20px; padding: 0; cursor: pointer; }
|
|
62
|
+
.ce-eye.ce-off { background: #9a9aa8; }
|
|
63
|
+
.ce-anim { margin-top: auto; padding-top: 14px; }
|
|
64
|
+
.ce-anim-row { display: flex; align-items: stretch; gap: 0; }
|
|
65
|
+
.ce-arrow { width: 38px; border: 3px solid #1d1d2a; background: #f0a03a; color: #1d1d2a; font-weight: 900;
|
|
66
|
+
font-size: 16px; cursor: pointer; border-radius: 4px; }
|
|
67
|
+
.ce-anim-name { flex: 1; background: #111; display: flex; align-items: center; justify-content: center;
|
|
68
|
+
font-weight: 800; letter-spacing: 0.05em; text-transform: uppercase; font-size: 13px; min-height: 36px; }
|
|
69
|
+
@media (max-width: 1200px) {
|
|
70
|
+
.ce-root { flex-wrap: wrap; }
|
|
71
|
+
.ce-presets { width: 100%; }
|
|
72
|
+
.ce-preset-grid { grid-template-columns: repeat(8, 1fr); }
|
|
73
|
+
.ce-preset { aspect-ratio: 1; }
|
|
74
|
+
.ce-scene { min-width: 300px; }
|
|
75
|
+
.ce-options { width: 240px; }
|
|
76
|
+
.ce-parts { width: 260px; }
|
|
77
|
+
}
|
|
78
|
+
@media (max-width: 760px) {
|
|
79
|
+
.ce-scene, .ce-options, .ce-parts { width: 100%; min-width: 100%; }
|
|
80
|
+
}
|
|
81
|
+
`;var bt={width:460,height:500},be="#26334a";function xe(a){let{rig:t,catalog:e,presets:n=[]}=a,o=react.useRef(null),[r,s]=react.useState(null),[,i]=react.useReducer(g=>g+1,0),[l,c]=react.useState(null),[h,d]=react.useState(a.look?null:n[0]?.id??null),f=react.useMemo(()=>Ft(t,e,2),[t,e]),u=react.useMemo(()=>Wt(t,a.pictures??f),[t,a.pictures,f]),m=react.useRef(a.onChange);m.current=a.onChange;let x=react.useRef(a.onStage);x.current=a.onStage;let b=react.useRef(a.look??n[0]?.look);react.useEffect(()=>{if(!o.current)return;let g=true,y=null;return Vt(o.current,{rig:t,catalog:e,...bt,scale:a.scale??1.6,...b.current?{look:b.current}:{}}).then(w=>{if(!g)return w.destroy();y=w,w.view.parts.on(()=>{i(),m.current?.(w.view.parts.toLook());}),w.view.on("*",()=>i()),s(w),x.current?.(w);}),()=>{g=false,y?.destroy();}},[t,e,a.scale]);let p=r?.view.parts,M=t.editor?.groups??[{id:"parts",label:"Parts",types:t.partTypes.filter(g=>!g.auto).map(g=>g.id)}],S=p?JSON.stringify(p.toLook().colors):"",k=(g,y)=>{let w=M.find(C=>C.types.includes(g))?.thumbnail;return {skins:[y],...p?{slotColor:C=>p.slotColor(C),artColor:C=>p.artColor(C)}:{},...w?.slots?{slots:w.slots}:{},...w?.backdrop?{backdrop:{skins:[w.backdrop.skin],slots:w.backdrop.slots,color:be}}:{},frame:w?.backdrop?"backdrop":"content"}},A=g=>{p&&(p.reset(),p.applyLook(g.look),d(g.id));},Y=(r?.view.animator.names()??[]).filter(g=>!g.includes("@")&&g!==t.blink?.animation),X=r?.view.animation()??"",I=g=>{if(!r||!Y.length)return;let y=(Y.indexOf(X)+g+Y.length)%Y.length;r.view.play(Y[y],{loop:true}),i();};return jsxRuntime.jsxs("div",{className:"ce-root",children:[jsxRuntime.jsx("style",{children:Kt}),n.length>0&&jsxRuntime.jsxs("div",{className:"ce-presets",children:[jsxRuntime.jsx("div",{className:"ce-title",children:"Preset"}),jsxRuntime.jsx("div",{className:"ce-preset-grid",children:n.map(g=>jsxRuntime.jsx("button",{className:`ce-preset${g.id===h?" ce-on":""}`,onClick:()=>A(g),"aria-label":g.label,children:jsxRuntime.jsx(ve,{rig:t,catalog:e,thumbs:u,preset:g})},g.id))})]}),jsxRuntime.jsxs("div",{className:"ce-scene",children:[jsxRuntime.jsx("div",{ref:o,className:"ce-stage",style:{width:bt.width,aspectRatio:`${bt.width} / ${bt.height}`}}),jsxRuntime.jsxs("div",{className:"ce-actions",children:[jsxRuntime.jsx("button",{className:"ce-big ce-random",onClick:()=>{p?.randomize(),d(null);},children:"Random parts"}),jsxRuntime.jsx("button",{className:"ce-big ce-reset",onClick:()=>{let g=n.find(y=>y.id===h)??n[0];g?A(g):p?.reset();},children:"Reset"})]})]}),p&&l&&jsxRuntime.jsxs("div",{className:"ce-options",children:[jsxRuntime.jsxs("div",{className:"ce-options-head",children:[jsxRuntime.jsxs("div",{className:"ce-title",children:[p.typeDef(l)?.label??l," ",ye(p.isWorn(l)?p.part(l):null)]}),jsxRuntime.jsx("button",{className:"ce-close",onClick:()=>c(null),"aria-label":"Close",children:"\xD7"})]}),(()=>{let g=p.typeDef(l)?.colorTarget;return g?jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx(jt,{value:p.color(g)??"#ffffff",onChange:y=>p.setColor(g,y)}),jsxRuntime.jsx("div",{style:{padding:"0 18px"},children:jsxRuntime.jsx("button",{className:"ce-paint-reset",onClick:()=>p.setColor(g,null),children:"Original colour"})})]}):null})(),jsxRuntime.jsxs("div",{className:"ce-option-grid",children:[p.typeDef(l)?.canHide&&jsxRuntime.jsx("button",{className:`ce-option${p.isWorn(l)?"":" ce-on"}`,onClick:()=>p.equip(l,null),"aria-label":"None",children:jsxRuntime.jsx("span",{className:"ce-none"})}),p.list(l).map(g=>jsxRuntime.jsx("button",{className:`ce-option${p.isWorn(l)&&p.part(l)===g?" ce-on":""}`,onClick:()=>{p.equip(l,g),p.setHidden(l,false),d(null);},"aria-label":g,children:jsxRuntime.jsx(At,{thumbs:u,request:k(l,g),refresh:S})},g))]})]}),p&&jsxRuntime.jsxs("div",{className:"ce-parts",children:[M.map(g=>jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("div",{className:"ce-title",children:g.label}),jsxRuntime.jsx("div",{className:"ce-tile-grid",children:g.types.map(y=>{let w=p.typeDef(y),C=p.part(y),v=p.isWorn(y),P=p.isHidden(y);return jsxRuntime.jsxs("div",{role:"button",tabIndex:0,className:`ce-tile${v?" ce-worn":""}${l===y?" ce-open":""}${P?" ce-hidden":""}`,onClick:()=>c(l===y?null:y),onKeyDown:D=>D.key==="Enter"&&c(l===y?null:y),"aria-label":w?.label??y,children:[C&&jsxRuntime.jsx(At,{thumbs:u,request:k(y,C),refresh:S}),w?.canHide&&C&&jsxRuntime.jsx("button",{className:`ce-eye${P?" ce-off":""}`,onClick:D=>{D.stopPropagation(),p.setHidden(y,!P);},"aria-label":P?"Show":"Hide",children:P?"\u2715":"\u25CF"})]},y)})})]},g.id)),jsxRuntime.jsxs("div",{className:"ce-anim",children:[jsxRuntime.jsx("div",{className:"ce-title",children:"Animation"}),jsxRuntime.jsxs("div",{className:"ce-anim-row",children:[jsxRuntime.jsx("button",{className:"ce-arrow",onClick:()=>I(-1),"aria-label":"Previous animation",children:"\u25C0"}),jsxRuntime.jsx("div",{className:"ce-anim-name",children:X.replace(/_/g," ").replace(/(\d+)$/," $1")}),jsxRuntime.jsx("button",{className:"ce-arrow",onClick:()=>I(1),"aria-label":"Next animation",children:"\u25B6"})]})]})]})]})}function ye(a){let t=a?/(\d+)$/.exec(a):null;return t?t[1]:""}function At(a){let t=react.useRef(null),{thumbs:e,request:n}=a,o=JSON.stringify([n.skins,n.slots,n.backdrop,n.frame,a.refresh]);return react.useEffect(()=>{let r=t.current;if(!r)return;let s=Math.min(2,window.devicePixelRatio||1),i=r.getBoundingClientRect();r.width=Math.max(32,Math.round(i.width*s)),r.height=Math.max(32,Math.round(i.height*s)),e.draw(r,n);},[e,o]),jsxRuntime.jsx("canvas",{ref:t})}function ve(a){let{rig:t,catalog:e,preset:n}=a,o=react.useMemo(()=>{let r=new j(t,s=>ct(t.data,s).every(i=>e.has(i)));return r.applyLook(n.look),{skins:r.wornSkins(),slotColor:s=>r.slotColor(s),artColor:s=>r.artColor(s),frame:"content",padding:.05}},[t,e,n]);return jsxRuntime.jsx(At,{thumbs:a.thumbs,request:o,refresh:n.id})}exports.CharacterEditor=xe;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { R as RigDef, A as ArtCatalog, C as CharacterLook } from '../../PartsManager-Cn3MU-VS.cjs';
|
|
3
|
+
import { L as LookPreset, P as PictureArt } from '../../thumbnail-BhGEEXux.cjs';
|
|
4
|
+
import { CharacterStage } from '../phaser/index.cjs';
|
|
5
|
+
import '../../contract-DhZuKNIf.cjs';
|
|
6
|
+
import 'phaser';
|
|
7
|
+
|
|
8
|
+
interface CharacterEditorProps {
|
|
9
|
+
rig: RigDef;
|
|
10
|
+
catalog: ArtCatalog;
|
|
11
|
+
presets?: readonly LookPreset[];
|
|
12
|
+
/** The look to start with; omitted — the first preset. */
|
|
13
|
+
look?: CharacterLook;
|
|
14
|
+
/** Every change of what is worn or its colours. */
|
|
15
|
+
onChange?: (look: CharacterLook) => void;
|
|
16
|
+
/** The live stage once it exists (a page that swaps the art, plays from code). */
|
|
17
|
+
onStage?: (stage: CharacterStage) => void;
|
|
18
|
+
/** The character's scale on the scene (default 1.6). */
|
|
19
|
+
scale?: number;
|
|
20
|
+
/** Where the tiles' pictures come from (default our vector art) — swapped with the stage's art. */
|
|
21
|
+
pictures?: PictureArt;
|
|
22
|
+
}
|
|
23
|
+
declare function CharacterEditor(props: CharacterEditorProps): react.JSX.Element;
|
|
24
|
+
|
|
25
|
+
export { CharacterEditor, type CharacterEditorProps };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { R as RigDef, A as ArtCatalog, C as CharacterLook } from '../../PartsManager-CAVBKvp6.js';
|
|
3
|
+
import { L as LookPreset, P as PictureArt } from '../../thumbnail-Bp-jK70T.js';
|
|
4
|
+
import { CharacterStage } from '../phaser/index.js';
|
|
5
|
+
import '../../contract-DhZuKNIf.js';
|
|
6
|
+
import 'phaser';
|
|
7
|
+
|
|
8
|
+
interface CharacterEditorProps {
|
|
9
|
+
rig: RigDef;
|
|
10
|
+
catalog: ArtCatalog;
|
|
11
|
+
presets?: readonly LookPreset[];
|
|
12
|
+
/** The look to start with; omitted — the first preset. */
|
|
13
|
+
look?: CharacterLook;
|
|
14
|
+
/** Every change of what is worn or its colours. */
|
|
15
|
+
onChange?: (look: CharacterLook) => void;
|
|
16
|
+
/** The live stage once it exists (a page that swaps the art, plays from code). */
|
|
17
|
+
onStage?: (stage: CharacterStage) => void;
|
|
18
|
+
/** The character's scale on the scene (default 1.6). */
|
|
19
|
+
scale?: number;
|
|
20
|
+
/** Where the tiles' pictures come from (default our vector art) — swapped with the stage's art. */
|
|
21
|
+
pictures?: PictureArt;
|
|
22
|
+
}
|
|
23
|
+
declare function CharacterEditor(props: CharacterEditorProps): react.JSX.Element;
|
|
24
|
+
|
|
25
|
+
export { CharacterEditor, type CharacterEditorProps };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import {a,b}from'../../chunk-Z5I76WRJ.js';import {c}from'../../chunk-BU66AZ2Z.js';import {C,t}from'../../chunk-OF4BH3JZ.js';import {useRef,useState,useReducer,useMemo,useEffect}from'react';import {jsxs,jsx}from'react/jsx-runtime';function V(a){let t=parseInt(a.replace("#",""),16),s=(t>>16&255)/255,r=(t>>8&255)/255,u=(t&255)/255,n=Math.max(s,r,u),p=n-Math.min(s,r,u),l=0;return p&&(n===s?l=(r-u)/p%6:n===r?l=(u-s)/p+2:l=(s-r)/p+4,l=(l*60+360)%360),{h:l,s:n?p/n:0,v:n}}function B({h:a,s:t,v:s}){let r=u=>{let n=(u+a/60)%6;return Math.round((s-s*t*Math.max(0,Math.min(n,4-n,1)))*255)};return `#${(r(5)<<16|r(3)<<8|r(1)).toString(16).padStart(6,"0")}`}function J(a){let t=V(a.value),[s,r]=useState(t.h);useEffect(()=>{t.s>.02&&t.v>.02&&r(t.h);},[t.h,t.s,t.v]);let u=useRef(null),n=useRef(null),p=(l,d)=>v=>{let k=l.current;if(!k)return;let h=x=>{let b=k.getBoundingClientRect();d(Math.max(0,Math.min(1,(x.clientX-b.left)/b.width)),Math.max(0,Math.min(1,(x.clientY-b.top)/b.height)));};h(v);let w=()=>{window.removeEventListener("pointermove",h),window.removeEventListener("pointerup",w);};window.addEventListener("pointermove",h),window.addEventListener("pointerup",w);};return jsxs("div",{className:"ce-picker",children:[jsx("div",{ref:u,className:"ce-sv",style:{background:`linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, hsl(${s} 100% 50%))`},onPointerDown:p(u,(l,d)=>a.onChange(B({h:s,s:l,v:1-d}))),children:jsx("span",{className:"ce-knob",style:{left:`${t.s*100}%`,top:`${(1-t.v)*100}%`}})}),jsx("div",{ref:n,className:"ce-hue",onPointerDown:p(n,l=>{r(l*359.9),a.onChange(B({h:l*359.9,s:Math.max(t.s,.05),v:Math.max(t.v,.05)}));}),children:jsx("span",{className:"ce-knob",style:{left:`${s/360*100}%`,top:"50%"}})})]})}var U=`
|
|
2
|
+
.ce-root { display: flex; gap: 0; align-items: stretch; font-family: "Trebuchet MS", "Segoe UI", sans-serif;
|
|
3
|
+
color: #fff; background: #1f2a22; border-radius: 14px; overflow: hidden; min-height: 600px; user-select: none; }
|
|
4
|
+
.ce-title { font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; text-align: center;
|
|
5
|
+
font-size: 14px; margin: 14px 0 10px; text-shadow: 0 2px 0 #0006; }
|
|
6
|
+
.ce-presets { width: 200px; background: #3a3d45; padding: 0 10px 12px; flex: none; }
|
|
7
|
+
.ce-preset-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
|
|
8
|
+
.ce-preset { background: transparent; border: 2px solid transparent; border-radius: 8px; padding: 0;
|
|
9
|
+
cursor: pointer; aspect-ratio: 3 / 4; }
|
|
10
|
+
.ce-preset:hover { background: #ffffff12; }
|
|
11
|
+
.ce-preset.ce-on { border-color: #fff; background: #ffffff1a; }
|
|
12
|
+
.ce-preset canvas { width: 100%; height: 100%; display: block; }
|
|
13
|
+
.ce-scene { position: relative; flex: 1; min-width: 360px; display: flex; flex-direction: column;
|
|
14
|
+
align-items: center; justify-content: flex-end;
|
|
15
|
+
background: radial-gradient(ellipse 34% 9% at 50% 84%, #6d4a35 0 70%, transparent 72%),
|
|
16
|
+
radial-gradient(ellipse 60% 30% at 50% 82%, #7a5a40 0 40%, transparent 70%),
|
|
17
|
+
linear-gradient(#3f6e45, #4f7f4c 55%, #446f43); }
|
|
18
|
+
.ce-stage { flex: none; max-width: 100%; }
|
|
19
|
+
.ce-stage canvas { width: 100% !important; height: auto !important; display: block; }
|
|
20
|
+
.ce-actions { display: flex; gap: 14px; margin: 6px 0 22px; }
|
|
21
|
+
.ce-big { font: inherit; font-weight: 800; font-size: 17px; letter-spacing: 0.05em; text-transform: uppercase;
|
|
22
|
+
color: #fff; border: 3px solid #1d1d2a; border-radius: 6px; padding: 12px 22px; cursor: pointer;
|
|
23
|
+
box-shadow: inset 0 -5px 0 #0003; text-shadow: 0 2px 0 #0007; }
|
|
24
|
+
.ce-big:active { transform: translateY(2px); box-shadow: inset 0 -2px 0 #0003; }
|
|
25
|
+
.ce-random { background: #5b55d9; }
|
|
26
|
+
.ce-reset { background: #f28a3a; }
|
|
27
|
+
.ce-options { width: 290px; background: #2d2f37; flex: none; display: flex; flex-direction: column; }
|
|
28
|
+
.ce-options-head { display: flex; align-items: center; justify-content: center; position: relative;
|
|
29
|
+
min-height: 46px; }
|
|
30
|
+
.ce-close { position: absolute; right: 10px; top: 9px; width: 28px; height: 28px; border-radius: 6px;
|
|
31
|
+
border: 2px solid #1d1d2a; background: #e2433f; color: #fff; font-weight: 800; cursor: pointer; }
|
|
32
|
+
.ce-option-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; padding: 10px; overflow-y: auto;
|
|
33
|
+
flex: 1; align-content: start; }
|
|
34
|
+
.ce-option { background: #3a3d48; border: 2px solid transparent; border-radius: 6px; aspect-ratio: 1; padding: 0;
|
|
35
|
+
cursor: pointer; position: relative; }
|
|
36
|
+
.ce-option:hover { background: #474b58; }
|
|
37
|
+
.ce-option.ce-on { background: #56607c; border-color: #dfe6ff; }
|
|
38
|
+
.ce-option canvas { width: 100%; height: 100%; display: block; }
|
|
39
|
+
.ce-none { position: absolute; inset: 22%; border: 3px solid #8a8fa0; border-radius: 50%; }
|
|
40
|
+
.ce-none::after { content: ""; position: absolute; left: 50%; top: -10%; bottom: -10%; width: 3px;
|
|
41
|
+
background: #8a8fa0; transform: rotate(45deg); }
|
|
42
|
+
.ce-picker { padding: 4px 18px 12px; }
|
|
43
|
+
.ce-sv { position: relative; height: 130px; border-radius: 4px; border: 2px solid #1d1d2a; cursor: crosshair;
|
|
44
|
+
touch-action: none; }
|
|
45
|
+
.ce-hue { position: relative; height: 12px; margin-top: 12px; border-radius: 6px; cursor: pointer; touch-action: none;
|
|
46
|
+
background: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00); }
|
|
47
|
+
.ce-knob { position: absolute; width: 12px; height: 12px; margin: -6px 0 0 -6px; border-radius: 50%;
|
|
48
|
+
border: 2px solid #fff; box-shadow: 0 0 0 1px #0008; pointer-events: none; }
|
|
49
|
+
.ce-sv .ce-knob { margin: -6px 0 0 -6px; }
|
|
50
|
+
.ce-paint-reset { font: inherit; font-size: 11px; margin-top: 8px; background: none; color: #c8cbe0;
|
|
51
|
+
border: 1px solid #555a6c; border-radius: 4px; padding: 2px 8px; cursor: pointer; }
|
|
52
|
+
.ce-parts { width: 300px; background: #6b4532; padding: 0 12px 12px; flex: none; display: flex; flex-direction: column; }
|
|
53
|
+
.ce-tile-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 7px; }
|
|
54
|
+
.ce-tile { position: relative; aspect-ratio: 1.1; background: #8a5a3e; border: 3px solid #4a2c20; border-radius: 4px;
|
|
55
|
+
padding: 0; cursor: pointer; }
|
|
56
|
+
.ce-tile.ce-worn { background: #2f73b5; }
|
|
57
|
+
.ce-tile.ce-open { border-color: #fff; }
|
|
58
|
+
.ce-tile canvas { width: 100%; height: 100%; display: block; }
|
|
59
|
+
.ce-tile.ce-hidden canvas { opacity: 0.35; }
|
|
60
|
+
.ce-eye { position: absolute; right: 3px; top: 3px; width: 20px; height: 20px; border-radius: 50%; border: none;
|
|
61
|
+
background: #fff; color: #2b2b38; font-size: 11px; line-height: 20px; padding: 0; cursor: pointer; }
|
|
62
|
+
.ce-eye.ce-off { background: #9a9aa8; }
|
|
63
|
+
.ce-anim { margin-top: auto; padding-top: 14px; }
|
|
64
|
+
.ce-anim-row { display: flex; align-items: stretch; gap: 0; }
|
|
65
|
+
.ce-arrow { width: 38px; border: 3px solid #1d1d2a; background: #f0a03a; color: #1d1d2a; font-weight: 900;
|
|
66
|
+
font-size: 16px; cursor: pointer; border-radius: 4px; }
|
|
67
|
+
.ce-anim-name { flex: 1; background: #111; display: flex; align-items: center; justify-content: center;
|
|
68
|
+
font-weight: 800; letter-spacing: 0.05em; text-transform: uppercase; font-size: 13px; min-height: 36px; }
|
|
69
|
+
@media (max-width: 1200px) {
|
|
70
|
+
.ce-root { flex-wrap: wrap; }
|
|
71
|
+
.ce-presets { width: 100%; }
|
|
72
|
+
.ce-preset-grid { grid-template-columns: repeat(8, 1fr); }
|
|
73
|
+
.ce-preset { aspect-ratio: 1; }
|
|
74
|
+
.ce-scene { min-width: 300px; }
|
|
75
|
+
.ce-options { width: 240px; }
|
|
76
|
+
.ce-parts { width: 260px; }
|
|
77
|
+
}
|
|
78
|
+
@media (max-width: 760px) {
|
|
79
|
+
.ce-scene, .ce-options, .ce-parts { width: 100%; min-width: 100%; }
|
|
80
|
+
}
|
|
81
|
+
`;var E={width:460,height:500},te="#26334a";function oe(a$1){let{rig:t,catalog:s,presets:r=[]}=a$1,u=useRef(null),[n,p]=useState(null),[,l]=useReducer(e=>e+1,0),[d,v]=useState(null),[k,h]=useState(a$1.look?null:r[0]?.id??null),w=useMemo(()=>a(t,s,2),[t,s]),x=useMemo(()=>b(t,a$1.pictures??w),[t,a$1.pictures,w]),b$1=useRef(a$1.onChange);b$1.current=a$1.onChange;let L=useRef(a$1.onStage);L.current=a$1.onStage;let R=useRef(a$1.look??r[0]?.look);useEffect(()=>{if(!u.current)return;let e=true,c$1=null;return c(u.current,{rig:t,catalog:s,...E,scale:a$1.scale??1.6,...R.current?{look:R.current}:{}}).then(f=>{if(!e)return f.destroy();c$1=f,f.view.parts.on(()=>{l(),b$1.current?.(f.view.parts.toLook());}),f.view.on("*",()=>l()),p(f),L.current?.(f);}),()=>{e=false,c$1?.destroy();}},[t,s,a$1.scale]);let o=n?.view.parts,$=t.editor?.groups??[{id:"parts",label:"Parts",types:t.partTypes.filter(e=>!e.auto).map(e=>e.id)}],D=o?JSON.stringify(o.toLook().colors):"",q=(e,c)=>{let f=$.find(g=>g.types.includes(e))?.thumbnail;return {skins:[c],...o?{slotColor:g=>o.slotColor(g),artColor:g=>o.artColor(g)}:{},...f?.slots?{slots:f.slots}:{},...f?.backdrop?{backdrop:{skins:[f.backdrop.skin],slots:f.backdrop.slots,color:te}}:{},frame:f?.backdrop?"backdrop":"content"}},I=e=>{o&&(o.reset(),o.applyLook(e.look),h(e.id));},y=(n?.view.animator.names()??[]).filter(e=>!e.includes("@")&&e!==t.blink?.animation),O=n?.view.animation()??"",A=e=>{if(!n||!y.length)return;let c=(y.indexOf(O)+e+y.length)%y.length;n.view.play(y[c],{loop:true}),l();};return jsxs("div",{className:"ce-root",children:[jsx("style",{children:U}),r.length>0&&jsxs("div",{className:"ce-presets",children:[jsx("div",{className:"ce-title",children:"Preset"}),jsx("div",{className:"ce-preset-grid",children:r.map(e=>jsx("button",{className:`ce-preset${e.id===k?" ce-on":""}`,onClick:()=>I(e),"aria-label":e.label,children:jsx(ne,{rig:t,catalog:s,thumbs:x,preset:e})},e.id))})]}),jsxs("div",{className:"ce-scene",children:[jsx("div",{ref:u,className:"ce-stage",style:{width:E.width,aspectRatio:`${E.width} / ${E.height}`}}),jsxs("div",{className:"ce-actions",children:[jsx("button",{className:"ce-big ce-random",onClick:()=>{o?.randomize(),h(null);},children:"Random parts"}),jsx("button",{className:"ce-big ce-reset",onClick:()=>{let e=r.find(c=>c.id===k)??r[0];e?I(e):o?.reset();},children:"Reset"})]})]}),o&&d&&jsxs("div",{className:"ce-options",children:[jsxs("div",{className:"ce-options-head",children:[jsxs("div",{className:"ce-title",children:[o.typeDef(d)?.label??d," ",re(o.isWorn(d)?o.part(d):null)]}),jsx("button",{className:"ce-close",onClick:()=>v(null),"aria-label":"Close",children:"\xD7"})]}),(()=>{let e=o.typeDef(d)?.colorTarget;return e?jsxs("div",{children:[jsx(J,{value:o.color(e)??"#ffffff",onChange:c=>o.setColor(e,c)}),jsx("div",{style:{padding:"0 18px"},children:jsx("button",{className:"ce-paint-reset",onClick:()=>o.setColor(e,null),children:"Original colour"})})]}):null})(),jsxs("div",{className:"ce-option-grid",children:[o.typeDef(d)?.canHide&&jsx("button",{className:`ce-option${o.isWorn(d)?"":" ce-on"}`,onClick:()=>o.equip(d,null),"aria-label":"None",children:jsx("span",{className:"ce-none"})}),o.list(d).map(e=>jsx("button",{className:`ce-option${o.isWorn(d)&&o.part(d)===e?" ce-on":""}`,onClick:()=>{o.equip(d,e),o.setHidden(d,false),h(null);},"aria-label":e,children:jsx(M,{thumbs:x,request:q(d,e),refresh:D})},e))]})]}),o&&jsxs("div",{className:"ce-parts",children:[$.map(e=>jsxs("div",{children:[jsx("div",{className:"ce-title",children:e.label}),jsx("div",{className:"ce-tile-grid",children:e.types.map(c=>{let f=o.typeDef(c),g=o.part(c),K=o.isWorn(c),C=o.isHidden(c);return jsxs("div",{role:"button",tabIndex:0,className:`ce-tile${K?" ce-worn":""}${d===c?" ce-open":""}${C?" ce-hidden":""}`,onClick:()=>v(d===c?null:c),onKeyDown:S=>S.key==="Enter"&&v(d===c?null:c),"aria-label":f?.label??c,children:[g&&jsx(M,{thumbs:x,request:q(c,g),refresh:D}),f?.canHide&&g&&jsx("button",{className:`ce-eye${C?" ce-off":""}`,onClick:S=>{S.stopPropagation(),o.setHidden(c,!C);},"aria-label":C?"Show":"Hide",children:C?"\u2715":"\u25CF"})]},c)})})]},e.id)),jsxs("div",{className:"ce-anim",children:[jsx("div",{className:"ce-title",children:"Animation"}),jsxs("div",{className:"ce-anim-row",children:[jsx("button",{className:"ce-arrow",onClick:()=>A(-1),"aria-label":"Previous animation",children:"\u25C0"}),jsx("div",{className:"ce-anim-name",children:O.replace(/_/g," ").replace(/(\d+)$/," $1")}),jsx("button",{className:"ce-arrow",onClick:()=>A(1),"aria-label":"Next animation",children:"\u25B6"})]})]})]})]})}function re(a){let t=a?/(\d+)$/.exec(a):null;return t?t[1]:""}function M(a){let t=useRef(null),{thumbs:s,request:r}=a,u=JSON.stringify([r.skins,r.slots,r.backdrop,r.frame,a.refresh]);return useEffect(()=>{let n=t.current;if(!n)return;let p=Math.min(2,window.devicePixelRatio||1),l=n.getBoundingClientRect();n.width=Math.max(32,Math.round(l.width*p)),n.height=Math.max(32,Math.round(l.height*p)),s.draw(n,r);},[s,u]),jsx("canvas",{ref:t})}function ne(a){let{rig:t$1,catalog:s,preset:r}=a,u=useMemo(()=>{let n=new C(t$1,p=>t(t$1.data,p).every(l=>s.has(l)));return n.applyLook(r.look),{skins:n.wornSkins(),slotColor:p=>n.slotColor(p),artColor:p=>n.artColor(p),frame:"content",padding:.05}},[t$1,s,r]);return jsx(M,{thumbs:a.thumbs,request:u,refresh:r.id})}export{oe as CharacterEditor};
|