solfaces 2.2.0 → 2.3.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/README.md +45 -19
- package/SKILL.md +2 -3
- package/dist/agent/index.cjs +13 -14
- package/dist/agent/index.js +3 -4
- package/dist/agent/mcp-server.cjs +326 -333
- package/dist/{chunk-5DT27HMT.js → chunk-2KW35VRI.js} +3 -3
- package/dist/{chunk-5DT27HMT.js.map → chunk-2KW35VRI.js.map} +1 -1
- package/dist/{chunk-PVJR3SFG.cjs → chunk-BI3GHRKQ.cjs} +14 -15
- package/dist/chunk-BI3GHRKQ.cjs.map +1 -0
- package/dist/{chunk-DRUSCLEF.js → chunk-MYUSB4LA.js} +28 -8
- package/dist/chunk-MYUSB4LA.js.map +1 -0
- package/dist/{chunk-3CE7Q44S.js → chunk-N5GDLCCL.js} +324 -110
- package/dist/chunk-N5GDLCCL.js.map +1 -0
- package/dist/{chunk-74CSG63X.js → chunk-O2IIBSQH.js} +6 -7
- package/dist/chunk-O2IIBSQH.js.map +1 -0
- package/dist/{chunk-6QRDULAO.cjs → chunk-PCSRDAWQ.cjs} +28 -7
- package/dist/chunk-PCSRDAWQ.cjs.map +1 -0
- package/dist/{chunk-WIXGHS77.cjs → chunk-T7HEUW2O.cjs} +6 -6
- package/dist/{chunk-WIXGHS77.cjs.map → chunk-T7HEUW2O.cjs.map} +1 -1
- package/dist/{chunk-F54WHRCE.cjs → chunk-W2U6ITMR.cjs} +328 -110
- package/dist/chunk-W2U6ITMR.cjs.map +1 -0
- package/dist/core/index.cjs +43 -44
- package/dist/core/index.d.cts +39 -5
- package/dist/core/index.d.ts +39 -5
- package/dist/core/index.js +2 -3
- package/dist/index.cjs +53 -50
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -5
- package/dist/react/index.cjs +107 -120
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +23 -1
- package/dist/react/index.d.ts +23 -1
- package/dist/react/index.js +95 -108
- package/dist/react/index.js.map +1 -1
- package/dist/solfaces.cdn.global.js +2 -2
- package/dist/solfaces.cdn.global.js.map +1 -1
- package/dist/themes/index.cjs +18 -14
- package/dist/themes/index.d.cts +30 -4
- package/dist/themes/index.d.ts +30 -4
- package/dist/themes/index.js +1 -1
- package/dist/traits-D4tbtZIr.d.cts +259 -0
- package/dist/traits-D4tbtZIr.d.ts +259 -0
- package/dist/vanilla/index.cjs +6 -7
- package/dist/vanilla/index.cjs.map +1 -1
- package/dist/vanilla/index.d.cts +1 -1
- package/dist/vanilla/index.d.ts +1 -1
- package/dist/vanilla/index.js +2 -3
- package/dist/vanilla/index.js.map +1 -1
- package/package.json +4 -1
- package/python/solfaces.py +103 -119
- package/reference/integrations.md +1 -1
- package/dist/chunk-3CE7Q44S.js.map +0 -1
- package/dist/chunk-6QRDULAO.cjs.map +0 -1
- package/dist/chunk-74CSG63X.js.map +0 -1
- package/dist/chunk-CKHLRORB.js +0 -239
- package/dist/chunk-CKHLRORB.js.map +0 -1
- package/dist/chunk-DRUSCLEF.js.map +0 -1
- package/dist/chunk-F54WHRCE.cjs.map +0 -1
- package/dist/chunk-PVJR3SFG.cjs.map +0 -1
- package/dist/chunk-TYTBYDQU.cjs +0 -244
- package/dist/chunk-TYTBYDQU.cjs.map +0 -1
- package/dist/traits-sfe7rM9C.d.cts +0 -106
- package/dist/traits-sfe7rM9C.d.ts +0 -106
|
@@ -16,7 +16,10 @@ var EYE_COLORS = [
|
|
|
16
16
|
"#3868A8",
|
|
17
17
|
"#38784C",
|
|
18
18
|
"#808838",
|
|
19
|
-
"#586878"
|
|
19
|
+
"#586878",
|
|
20
|
+
"#A06830",
|
|
21
|
+
"#685898",
|
|
22
|
+
"#889898"
|
|
20
23
|
];
|
|
21
24
|
var HAIR_COLORS = [
|
|
22
25
|
"#1A1A24",
|
|
@@ -40,7 +43,9 @@ var BG_COLORS = [
|
|
|
40
43
|
"#7f8bbd",
|
|
41
44
|
"#8869ab",
|
|
42
45
|
"#b785b3",
|
|
43
|
-
"#ab6984"
|
|
46
|
+
"#ab6984",
|
|
47
|
+
"#a07ab5",
|
|
48
|
+
"#74b5a0"
|
|
44
49
|
];
|
|
45
50
|
function djb2(str) {
|
|
46
51
|
let hash = 5381;
|
|
@@ -64,22 +69,20 @@ function generateTraits(walletAddress, overrides) {
|
|
|
64
69
|
const traits = {
|
|
65
70
|
faceShape: Math.floor(rand() * 4),
|
|
66
71
|
skinColor: Math.floor(rand() * 10),
|
|
67
|
-
eyeStyle: Math.floor(rand() *
|
|
68
|
-
eyeColor: Math.floor(rand() *
|
|
69
|
-
eyebrows: Math.floor(rand() *
|
|
70
|
-
nose: Math.floor(rand() *
|
|
72
|
+
eyeStyle: Math.floor(rand() * 9),
|
|
73
|
+
eyeColor: Math.floor(rand() * 8),
|
|
74
|
+
eyebrows: Math.floor(rand() * 8),
|
|
75
|
+
nose: Math.floor(rand() * 8),
|
|
71
76
|
mouth: Math.floor(rand() * 8),
|
|
72
77
|
hairStyle: Math.floor(rand() * 10),
|
|
73
78
|
hairColor: Math.floor(rand() * 10),
|
|
74
|
-
accessory: Math.floor(rand() *
|
|
75
|
-
bgColor: Math.floor(rand() *
|
|
79
|
+
accessory: Math.floor(rand() * 12),
|
|
80
|
+
bgColor: Math.floor(rand() * 12)
|
|
76
81
|
};
|
|
77
82
|
return overrides ? { ...traits, ...overrides } : traits;
|
|
78
83
|
}
|
|
79
84
|
function effectiveAccessory(traits) {
|
|
80
|
-
const ai = traits.accessory %
|
|
81
|
-
const hi = traits.hairStyle % 10;
|
|
82
|
-
if ((ai === 4 || ai === 7) && (hi === 5 || hi === 6)) return 0;
|
|
85
|
+
const ai = traits.accessory % 12;
|
|
83
86
|
return ai;
|
|
84
87
|
}
|
|
85
88
|
var FACE_LABELS = ["Squircle"];
|
|
@@ -95,22 +98,22 @@ var SKIN_LABELS = [
|
|
|
95
98
|
"Brown",
|
|
96
99
|
"Deep"
|
|
97
100
|
];
|
|
98
|
-
var EYE_STYLE_LABELS = ["Round", "Minimal", "Almond", "Wide", "Relaxed", "Joyful", "Bright", "Gentle"];
|
|
99
|
-
var EYE_COLOR_LABELS = ["Chocolate", "Sky", "Emerald", "Hazel", "Storm"];
|
|
100
|
-
var BROW_LABELS = ["Wispy", "Straight", "Natural", "Arched", "Angled"];
|
|
101
|
-
var NOSE_LABELS = ["Shadow", "Button", "Soft", "Nostrils"];
|
|
101
|
+
var EYE_STYLE_LABELS = ["Round", "Minimal", "Almond", "Wide", "Relaxed", "Joyful", "Bright", "Gentle", "Side-look"];
|
|
102
|
+
var EYE_COLOR_LABELS = ["Chocolate", "Sky", "Emerald", "Hazel", "Storm", "Amber", "Violet", "Gray"];
|
|
103
|
+
var BROW_LABELS = ["Wispy", "Straight", "Natural", "Arched", "Angled", "Worried", "Bushy", "Thin"];
|
|
104
|
+
var NOSE_LABELS = ["Shadow", "Button", "Soft", "Nostrils", "Pointed", "Wide", "Bridge", "Snub"];
|
|
102
105
|
var MOUTH_LABELS = ["Smile", "Calm", "Happy", "Oh", "Smirk", "Grin", "Flat", "Pout"];
|
|
103
106
|
var HAIR_STYLE_LABELS = [
|
|
104
107
|
"Bald",
|
|
105
|
-
"
|
|
108
|
+
"Crew",
|
|
106
109
|
"Curly",
|
|
107
|
-
"Side
|
|
108
|
-
"Puff",
|
|
110
|
+
"Side Part",
|
|
109
111
|
"Long",
|
|
110
|
-
"Bob",
|
|
111
112
|
"Buzz",
|
|
112
|
-
"
|
|
113
|
-
"
|
|
113
|
+
"Beanie",
|
|
114
|
+
"Cap",
|
|
115
|
+
"Mohawk",
|
|
116
|
+
"Bun"
|
|
114
117
|
];
|
|
115
118
|
var HAIR_COLOR_LABELS = [
|
|
116
119
|
"Black",
|
|
@@ -134,7 +137,9 @@ var ACCESSORY_LABELS = [
|
|
|
134
137
|
"Freckles",
|
|
135
138
|
"Stud Earrings",
|
|
136
139
|
"Aviators",
|
|
137
|
-
"Band-Aid"
|
|
140
|
+
"Band-Aid",
|
|
141
|
+
"Left Eyebrow Slit",
|
|
142
|
+
"Right Eyebrow Slit"
|
|
138
143
|
];
|
|
139
144
|
var BG_COLOR_LABELS = [
|
|
140
145
|
"Rose",
|
|
@@ -146,7 +151,9 @@ var BG_COLOR_LABELS = [
|
|
|
146
151
|
"Sky",
|
|
147
152
|
"Lavender",
|
|
148
153
|
"Orchid",
|
|
149
|
-
"Blush"
|
|
154
|
+
"Blush",
|
|
155
|
+
"Lilac",
|
|
156
|
+
"Seafoam"
|
|
150
157
|
];
|
|
151
158
|
function getTraitLabels(traits) {
|
|
152
159
|
return {
|
|
@@ -209,7 +216,21 @@ function blend(a, b, t = 0.5) {
|
|
|
209
216
|
}
|
|
210
217
|
function luminance(hex) {
|
|
211
218
|
const [r, g, b] = hexToRgb(hex);
|
|
212
|
-
return
|
|
219
|
+
return 0.299 * r + 0.587 * g + 0.114 * b;
|
|
220
|
+
}
|
|
221
|
+
function relativeLuminance(hex) {
|
|
222
|
+
const [r, g, b] = hexToRgb(hex).map((c) => {
|
|
223
|
+
const s = c / 255;
|
|
224
|
+
return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
|
|
225
|
+
});
|
|
226
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
227
|
+
}
|
|
228
|
+
function contrastRatio(hex1, hex2) {
|
|
229
|
+
const l1 = relativeLuminance(hex1);
|
|
230
|
+
const l2 = relativeLuminance(hex2);
|
|
231
|
+
const lighter = Math.max(l1, l2);
|
|
232
|
+
const darker = Math.min(l1, l2);
|
|
233
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
213
234
|
}
|
|
214
235
|
function deriveSkinColors(skin) {
|
|
215
236
|
const sL = luminance(skin);
|
|
@@ -243,11 +264,20 @@ function deriveSkinColors(skin) {
|
|
|
243
264
|
const lipRaw = blend(skin, lipBase, Math.min(0.82, lipBlend));
|
|
244
265
|
const [lr, lg, lb] = hexToRgb(lipRaw);
|
|
245
266
|
const lipD = Math.abs(sr - lr) + Math.abs(sg - lg) + Math.abs(sb - lb);
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
267
|
+
let lipColor = lipD < 60 ? blend(skin, lipBase, 0.78) : lipRaw;
|
|
268
|
+
let attempts = 0;
|
|
269
|
+
while (contrastRatio(lipColor, skin) < 1.8 && attempts < 12) {
|
|
270
|
+
lipColor = darken(lipColor, 0.06);
|
|
271
|
+
attempts++;
|
|
272
|
+
}
|
|
273
|
+
const browColor = isDark ? lighten(skin, sL < 80 ? 0.35 : sL < 100 ? 0.32 : 0.25) : darken(skin, 0.55);
|
|
274
|
+
const noseShift = 0.2 + 0.06 * (1 - Math.abs(sL - 100) / 140);
|
|
275
|
+
const noseFill = isDark ? lighten(skin, noseShift) : darken(skin, noseShift);
|
|
249
276
|
const earT = Math.max(0, Math.min(1, (sL - 100) / 60));
|
|
250
|
-
|
|
277
|
+
let earFill = blend(lighten(skin, 0.08), skinMid, earT);
|
|
278
|
+
if (contrastRatio(earFill, skin) < 1.05) {
|
|
279
|
+
earFill = isDark ? lighten(earFill, 0.06) : darken(earFill, 0.06);
|
|
280
|
+
}
|
|
251
281
|
const earShadow = darken(skin, 0.1 + 0.06 * (1 - Math.min(1, sL / 160)));
|
|
252
282
|
const lidColor = isDark ? lighten(skin, 0.18) : darken(skin, 0.15);
|
|
253
283
|
const ewT = Math.max(0, Math.min(1, (sL - 60) / 180));
|
|
@@ -271,10 +301,209 @@ function deriveSkinColors(skin) {
|
|
|
271
301
|
accessoryColor
|
|
272
302
|
};
|
|
273
303
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
304
|
+
|
|
305
|
+
// src/core/describe.ts
|
|
306
|
+
var SKIN_TONES = {
|
|
307
|
+
0: "porcelain",
|
|
308
|
+
1: "ivory",
|
|
309
|
+
2: "fair",
|
|
310
|
+
3: "light",
|
|
311
|
+
4: "sand",
|
|
312
|
+
5: "golden",
|
|
313
|
+
6: "warm",
|
|
314
|
+
7: "caramel",
|
|
315
|
+
8: "brown",
|
|
316
|
+
9: "deep"
|
|
317
|
+
};
|
|
318
|
+
var EYE_STYLES = {
|
|
319
|
+
0: "round, wide-open",
|
|
320
|
+
1: "small and minimal",
|
|
321
|
+
2: "almond-shaped",
|
|
322
|
+
3: "wide and expressive",
|
|
323
|
+
4: "relaxed, half-lidded",
|
|
324
|
+
5: "joyful, crescent-shaped",
|
|
325
|
+
6: "bright and sparkling",
|
|
326
|
+
7: "gentle and narrow",
|
|
327
|
+
8: "side-looking, shifted"
|
|
328
|
+
};
|
|
329
|
+
var EYE_COLORS_DESC = {
|
|
330
|
+
0: "dark brown",
|
|
331
|
+
1: "blue",
|
|
332
|
+
2: "green",
|
|
333
|
+
3: "hazel",
|
|
334
|
+
4: "gray",
|
|
335
|
+
5: "amber",
|
|
336
|
+
6: "violet",
|
|
337
|
+
7: "steel gray"
|
|
338
|
+
};
|
|
339
|
+
var EYEBROW_STYLES = {
|
|
340
|
+
0: "wispy",
|
|
341
|
+
1: "straight",
|
|
342
|
+
2: "natural",
|
|
343
|
+
3: "elegantly arched",
|
|
344
|
+
4: "sharply angled",
|
|
345
|
+
5: "worried, furrowed",
|
|
346
|
+
6: "bushy",
|
|
347
|
+
7: "thin, delicate"
|
|
348
|
+
};
|
|
349
|
+
var NOSE_STYLES = {
|
|
350
|
+
0: "a subtle shadow nose",
|
|
351
|
+
1: "a small button nose",
|
|
352
|
+
2: "a soft curved nose",
|
|
353
|
+
3: "a button nose with visible nostrils",
|
|
354
|
+
4: "a pointed nose",
|
|
355
|
+
5: "a wide, broad nose",
|
|
356
|
+
6: "a nose with a visible bridge",
|
|
357
|
+
7: "a small snub nose"
|
|
358
|
+
};
|
|
359
|
+
var MOUTH_STYLES = {
|
|
360
|
+
0: "a gentle smile",
|
|
361
|
+
1: "a calm, neutral expression",
|
|
362
|
+
2: "a happy grin",
|
|
363
|
+
3: "a surprised O-shaped mouth",
|
|
364
|
+
4: "a confident smirk",
|
|
365
|
+
5: "a wide, toothy grin",
|
|
366
|
+
6: "a flat, straight expression",
|
|
367
|
+
7: "a soft pout"
|
|
368
|
+
};
|
|
369
|
+
var ACCESSORY_DESC = {
|
|
370
|
+
0: "",
|
|
371
|
+
1: "a beauty mark",
|
|
372
|
+
2: "round glasses",
|
|
373
|
+
3: "rectangular glasses",
|
|
374
|
+
4: "a dangling earring",
|
|
375
|
+
5: "a headband",
|
|
376
|
+
6: "freckles",
|
|
377
|
+
7: "stud earrings",
|
|
378
|
+
8: "aviator sunglasses",
|
|
379
|
+
9: "a band-aid",
|
|
380
|
+
10: "a left eyebrow slit",
|
|
381
|
+
11: "a right eyebrow slit"
|
|
382
|
+
};
|
|
383
|
+
var BG_COLORS_DESC = {
|
|
384
|
+
0: "rose",
|
|
385
|
+
1: "olive",
|
|
386
|
+
2: "sage",
|
|
387
|
+
3: "fern",
|
|
388
|
+
4: "mint",
|
|
389
|
+
5: "ocean",
|
|
390
|
+
6: "sky",
|
|
391
|
+
7: "lavender",
|
|
392
|
+
8: "orchid",
|
|
393
|
+
9: "blush",
|
|
394
|
+
10: "lilac",
|
|
395
|
+
11: "seafoam"
|
|
396
|
+
};
|
|
397
|
+
function describeAppearance(walletAddress, options) {
|
|
398
|
+
const traits = generateTraits(walletAddress);
|
|
399
|
+
const {
|
|
400
|
+
includeBackground = true,
|
|
401
|
+
format = "paragraph",
|
|
402
|
+
perspective = "third",
|
|
403
|
+
name
|
|
404
|
+
} = options ?? {};
|
|
405
|
+
if (format === "structured") return buildStructured(traits, includeBackground);
|
|
406
|
+
if (format === "compact") return buildCompact(traits);
|
|
407
|
+
return buildParagraph(traits, perspective, name, includeBackground);
|
|
408
|
+
}
|
|
409
|
+
function describeTraits(traits, options) {
|
|
410
|
+
const {
|
|
411
|
+
includeBackground = true,
|
|
412
|
+
format = "paragraph",
|
|
413
|
+
perspective = "third",
|
|
414
|
+
name
|
|
415
|
+
} = options ?? {};
|
|
416
|
+
if (format === "structured") return buildStructured(traits, includeBackground);
|
|
417
|
+
if (format === "compact") return buildCompact(traits);
|
|
418
|
+
return buildParagraph(traits, perspective, name, includeBackground);
|
|
419
|
+
}
|
|
420
|
+
function buildParagraph(t, perspective, name, includeBg) {
|
|
421
|
+
const parts = [];
|
|
422
|
+
const ai = effectiveAccessory(t);
|
|
423
|
+
const subject = perspective === "first" ? name ? `I'm ${name}. I have` : "I have" : name ? `${name} has` : "This SolFace has";
|
|
424
|
+
const im = perspective === "first" ? "I'm" : "They're";
|
|
425
|
+
parts.push(`${subject} a squircle face with ${SKIN_TONES[t.skinColor] ?? "warm"} skin`);
|
|
426
|
+
const eyeStyle = EYE_STYLES[t.eyeStyle] ?? "round";
|
|
427
|
+
const eyeColor = EYE_COLORS_DESC[t.eyeColor] ?? "dark";
|
|
428
|
+
parts.push(`${eyeStyle} ${eyeColor} eyes`);
|
|
429
|
+
const brows = EYEBROW_STYLES[t.eyebrows];
|
|
430
|
+
if (brows) parts.push(`${brows} eyebrows`);
|
|
431
|
+
parts.push(perspective === "first" ? "and am bald" : "and is bald");
|
|
432
|
+
let desc = parts[0];
|
|
433
|
+
if (parts.length > 2) {
|
|
434
|
+
desc += ", " + parts.slice(1, -1).join(", ") + ", " + parts[parts.length - 1];
|
|
435
|
+
} else if (parts.length === 2) {
|
|
436
|
+
desc += " and " + parts[1];
|
|
437
|
+
}
|
|
438
|
+
desc += ".";
|
|
439
|
+
const nose = NOSE_STYLES[t.nose];
|
|
440
|
+
if (nose) {
|
|
441
|
+
const noseSubject = perspective === "first" ? "I have" : (name ?? "They") + (name ? " has" : " have");
|
|
442
|
+
desc += ` ${noseSubject} ${nose}.`;
|
|
443
|
+
}
|
|
444
|
+
const acc = ACCESSORY_DESC[ai];
|
|
445
|
+
if (acc) {
|
|
446
|
+
desc += ` ${im} wearing ${acc}.`;
|
|
447
|
+
}
|
|
448
|
+
const mouth = MOUTH_STYLES[t.mouth] ?? "a smile";
|
|
449
|
+
const mouthVerb = perspective === "first" ? "I have" : (name ?? "They") + (name ? " has" : " have");
|
|
450
|
+
desc += ` ${mouthVerb} ${mouth}.`;
|
|
451
|
+
if (includeBg) {
|
|
452
|
+
const bg = BG_COLORS_DESC[t.bgColor] ?? "colorful";
|
|
453
|
+
desc += ` The background is ${bg}.`;
|
|
454
|
+
}
|
|
455
|
+
return desc;
|
|
456
|
+
}
|
|
457
|
+
function buildStructured(t, includeBg) {
|
|
458
|
+
const ai = effectiveAccessory(t);
|
|
459
|
+
const lines = [
|
|
460
|
+
`Face: squircle`,
|
|
461
|
+
`Skin: ${SKIN_TONES[t.skinColor] ?? "warm"}`,
|
|
462
|
+
`Eyes: ${EYE_STYLES[t.eyeStyle] ?? "round"}, ${EYE_COLORS_DESC[t.eyeColor] ?? "dark"}`,
|
|
463
|
+
`Eyebrows: ${EYEBROW_STYLES[t.eyebrows] ?? "wispy"}`
|
|
464
|
+
];
|
|
465
|
+
const nose = NOSE_STYLES[t.nose];
|
|
466
|
+
if (nose) lines.push(`Nose: ${nose.replace(/^a /, "")}`);
|
|
467
|
+
lines.push(`Mouth: ${MOUTH_STYLES[t.mouth] ?? "smile"}`);
|
|
468
|
+
lines.push("Hair: bald");
|
|
469
|
+
const acc = ACCESSORY_DESC[ai];
|
|
470
|
+
if (acc) lines.push(`Accessory: ${acc}`);
|
|
471
|
+
if (includeBg) {
|
|
472
|
+
lines.push(`Background: ${BG_COLORS_DESC[t.bgColor] ?? "colorful"}`);
|
|
473
|
+
}
|
|
474
|
+
return lines.join("\n");
|
|
475
|
+
}
|
|
476
|
+
function buildCompact(t) {
|
|
477
|
+
const ai = effectiveAccessory(t);
|
|
478
|
+
const parts = [];
|
|
479
|
+
parts.push(`squircle face`);
|
|
480
|
+
parts.push(`${SKIN_TONES[t.skinColor] ?? "warm"} skin`);
|
|
481
|
+
parts.push(`${EYE_COLORS_DESC[t.eyeColor] ?? "dark"} ${EYE_STYLES[t.eyeStyle] ?? "round"} eyes`);
|
|
482
|
+
parts.push("bald");
|
|
483
|
+
const acc = ACCESSORY_DESC[ai];
|
|
484
|
+
if (acc) parts.push(acc);
|
|
485
|
+
parts.push((MOUTH_STYLES[t.mouth] ?? "smiling").replace(/^a /, ""));
|
|
486
|
+
return parts.join(", ");
|
|
487
|
+
}
|
|
488
|
+
function solFaceAltText(walletAddress) {
|
|
489
|
+
return `SolFace avatar: ${describeAppearance(walletAddress, { format: "compact", includeBackground: false })}`;
|
|
490
|
+
}
|
|
491
|
+
function agentAppearancePrompt(walletAddress, agentName) {
|
|
492
|
+
const desc = describeAppearance(walletAddress, {
|
|
493
|
+
perspective: "first",
|
|
494
|
+
name: agentName,
|
|
495
|
+
includeBackground: false,
|
|
496
|
+
format: "paragraph"
|
|
497
|
+
});
|
|
498
|
+
const hash = (djb2Simple(walletAddress) >>> 0).toString(16).padStart(8, "0");
|
|
499
|
+
return `My visual identity is a SolFace avatar (ID: ${hash}) derived from my wallet address. ${desc} This appearance is deterministic \u2014 anyone who looks up my wallet will see the same face.`;
|
|
500
|
+
}
|
|
501
|
+
function djb2Simple(str) {
|
|
502
|
+
let hash = 5381;
|
|
503
|
+
for (let i = 0; i < str.length; i++) {
|
|
504
|
+
hash = (hash << 5) + hash + str.charCodeAt(i) | 0;
|
|
505
|
+
}
|
|
506
|
+
return hash >>> 0;
|
|
278
507
|
}
|
|
279
508
|
|
|
280
509
|
// src/core/renderer.ts
|
|
@@ -290,12 +519,9 @@ function buildDefs(id, skin, skinHi, skinLo, hairCol, bgCol, cheekColor, cheekOp
|
|
|
290
519
|
let d = "<defs>";
|
|
291
520
|
d += `<linearGradient id="${id}sg" x1="0" y1="0" x2="0" y2="1">`;
|
|
292
521
|
d += `<stop offset="0%" stop-color="${skinHi}"/>`;
|
|
522
|
+
d += `<stop offset="50%" stop-color="${skin}"/>`;
|
|
293
523
|
d += `<stop offset="100%" stop-color="${skinLo}"/>`;
|
|
294
524
|
d += `</linearGradient>`;
|
|
295
|
-
d += `<linearGradient id="${id}hg" x1="0" y1="0" x2="0" y2="1">`;
|
|
296
|
-
d += `<stop offset="0%" stop-color="${lighten(hairCol, 0.15)}"/>`;
|
|
297
|
-
d += `<stop offset="100%" stop-color="${darken(hairCol, 0.15)}"/>`;
|
|
298
|
-
d += `</linearGradient>`;
|
|
299
525
|
d += `<linearGradient id="${id}bg" x1="0" y1="0" x2="1" y2="1">`;
|
|
300
526
|
d += `<stop offset="0%" stop-color="${lighten(bgCol, 0.12)}"/>`;
|
|
301
527
|
d += `<stop offset="100%" stop-color="${darken(bgCol, 0.12)}"/>`;
|
|
@@ -321,18 +547,8 @@ function buildDefs(id, skin, skinHi, skinLo, hairCol, bgCol, cheekColor, cheekOp
|
|
|
321
547
|
d += "</defs>";
|
|
322
548
|
return d;
|
|
323
549
|
}
|
|
324
|
-
function renderHairBack(
|
|
325
|
-
|
|
326
|
-
switch (hi) {
|
|
327
|
-
case 5:
|
|
328
|
-
return `<g fill="${fill}"><rect x="10" y="14" width="44" height="42" rx="6"/></g>`;
|
|
329
|
-
case 6:
|
|
330
|
-
return `<g fill="${fill}"><rect x="12" y="14" width="40" height="32" rx="8"/></g>`;
|
|
331
|
-
case 8:
|
|
332
|
-
return `<g fill="${fill}"><rect x="11" y="14" width="42" height="38" rx="8"/></g>`;
|
|
333
|
-
default:
|
|
334
|
-
return "";
|
|
335
|
-
}
|
|
550
|
+
function renderHairBack(_hi, _id, _flat) {
|
|
551
|
+
return "";
|
|
336
552
|
}
|
|
337
553
|
function renderEars(earFill, earShadow) {
|
|
338
554
|
return `<ellipse cx="11" cy="34" rx="4" ry="5" fill="${earFill}"/><ellipse cx="11" cy="34" rx="2.5" ry="3.5" fill="${earShadow}" opacity="0.3"/><ellipse cx="53" cy="34" rx="4" ry="5" fill="${earFill}"/><ellipse cx="53" cy="34" rx="2.5" ry="3.5" fill="${earShadow}" opacity="0.3"/>`;
|
|
@@ -346,35 +562,8 @@ function renderFaceOverlays(id, flat) {
|
|
|
346
562
|
if (flat) return "";
|
|
347
563
|
return `<rect x="14" y="16" width="36" height="38" rx="12" ry="12" fill="url(#${id}glow)"/><rect x="14" y="16" width="36" height="38" rx="12" ry="12" fill="url(#${id}chin)"/><ellipse cx="22" cy="42" rx="5" ry="3.5" fill="url(#${id}cL)"/><ellipse cx="42" cy="42" rx="5" ry="3.5" fill="url(#${id}cR)"/><line x1="20" y1="50" x2="44" y2="50" stroke="currentColor" stroke-width="0.3" opacity="0.08" stroke-linecap="round"/>`;
|
|
348
564
|
}
|
|
349
|
-
function renderHairFront(
|
|
350
|
-
|
|
351
|
-
switch (hi) {
|
|
352
|
-
case 0:
|
|
353
|
-
return "";
|
|
354
|
-
// Bald
|
|
355
|
-
case 1:
|
|
356
|
-
return `<path d="M14 28 Q14 14 32 12 Q50 14 50 28 L50 22 Q50 12 32 10 Q14 12 14 22 Z" fill="${fill}"/>`;
|
|
357
|
-
case 2:
|
|
358
|
-
return `<g fill="${fill}"><circle cx="20" cy="14" r="5"/><circle cx="28" cy="11" r="5.5"/><circle cx="36" cy="11" r="5.5"/><circle cx="44" cy="14" r="5"/><circle cx="16" cy="20" r="4"/><circle cx="48" cy="20" r="4"/></g>`;
|
|
359
|
-
case 3:
|
|
360
|
-
return `<path d="M14 26 Q14 12 32 10 Q50 12 50 26 L50 20 Q50 10 32 8 Q14 10 14 20 Z" fill="${fill}"/><path d="M14 20 Q8 16 10 8 Q14 10 20 16 Z" fill="${fill}"/>`;
|
|
361
|
-
case 4:
|
|
362
|
-
return `<ellipse cx="32" cy="10" rx="14" ry="8" fill="${fill}"/>`;
|
|
363
|
-
case 5:
|
|
364
|
-
return `<path d="M14 28 Q14 12 32 10 Q50 12 50 28 L50 20 Q50 10 32 8 Q14 10 14 20 Z" fill="${fill}"/>`;
|
|
365
|
-
case 6:
|
|
366
|
-
return `<path d="M14 28 Q14 12 32 10 Q50 12 50 28 L50 20 Q50 10 32 8 Q14 10 14 20 Z" fill="${fill}"/><rect x="10" y="28" width="8" height="14" rx="4" fill="${fill}"/><rect x="46" y="28" width="8" height="14" rx="4" fill="${fill}"/>`;
|
|
367
|
-
case 7: {
|
|
368
|
-
const bOp = buzzOpacity(hairCol, skin);
|
|
369
|
-
return `<rect x="15" y="13" width="34" height="16" rx="10" ry="8" fill="${hairCol}" opacity="${bOp.toFixed(2)}"/>`;
|
|
370
|
-
}
|
|
371
|
-
case 8:
|
|
372
|
-
return `<path d="M14 28 Q14 12 32 10 Q50 12 50 28 L50 20 Q50 10 32 8 Q14 10 14 20 Z" fill="${fill}"/><path d="M12 30 Q10 20 14 16" fill="none" stroke="${fill}" stroke-width="4" stroke-linecap="round"/><path d="M52 30 Q54 20 50 16" fill="none" stroke="${fill}" stroke-width="4" stroke-linecap="round"/>`;
|
|
373
|
-
case 9:
|
|
374
|
-
return `<path d="M14 28 Q14 14 32 12 Q50 14 50 28 L50 22 Q50 12 32 10 Q14 12 14 22 Z" fill="${fill}"/><ellipse cx="32" cy="6" rx="6" ry="5" fill="${fill}"/>`;
|
|
375
|
-
default:
|
|
376
|
-
return "";
|
|
377
|
-
}
|
|
565
|
+
function renderHairFront(_hi, _id, _hairCol, _skin, _flat) {
|
|
566
|
+
return "";
|
|
378
567
|
}
|
|
379
568
|
function renderEyes(ei, eyeCol, eyeWhite, lidColor, full) {
|
|
380
569
|
const lx = 25, rx = 39, y = 33;
|
|
@@ -389,8 +578,10 @@ function renderEyes(ei, eyeCol, eyeWhite, lidColor, full) {
|
|
|
389
578
|
if (full) s += `<circle cx="${rx + 1.5}" cy="${y - 1}" r="0.7" fill="white" opacity="0.8"/>`;
|
|
390
579
|
break;
|
|
391
580
|
case 1:
|
|
392
|
-
s += `<circle cx="${lx}" cy="${y}" r="2" fill="${eyeCol}"/>`;
|
|
393
|
-
s += `<circle cx="${
|
|
581
|
+
s += `<circle cx="${lx}" cy="${y}" r="2.2" fill="${eyeCol}"/>`;
|
|
582
|
+
if (full) s += `<circle cx="${lx + 0.5}" cy="${y - 0.5}" r="0.5" fill="white" opacity="0.4"/>`;
|
|
583
|
+
s += `<circle cx="${rx}" cy="${y}" r="2.2" fill="${eyeCol}"/>`;
|
|
584
|
+
if (full) s += `<circle cx="${rx + 0.5}" cy="${y - 0.5}" r="0.5" fill="white" opacity="0.4"/>`;
|
|
394
585
|
break;
|
|
395
586
|
case 2:
|
|
396
587
|
s += `<ellipse cx="${lx}" cy="${y}" rx="4.5" ry="2.8" fill="${eyeWhite}"/>`;
|
|
@@ -417,24 +608,16 @@ function renderEyes(ei, eyeCol, eyeWhite, lidColor, full) {
|
|
|
417
608
|
if (full) s += `<line x1="${rx - 4.5}" y1="${y - 0.5}" x2="${rx + 4.5}" y2="${y - 0.5}" stroke="${lidColor}" stroke-width="0.8" stroke-linecap="round"/>`;
|
|
418
609
|
break;
|
|
419
610
|
case 5:
|
|
420
|
-
s += `<path d="M${lx - 4} ${y} Q${lx} ${y + 4} ${lx + 4} ${y}" fill="none" stroke="${eyeCol}" stroke-width="
|
|
421
|
-
s += `<path d="M${rx - 4} ${y} Q${rx} ${y + 4} ${rx + 4} ${y}" fill="none" stroke="${eyeCol}" stroke-width="
|
|
611
|
+
s += `<path d="M${lx - 4} ${y} Q${lx} ${y + 4.5} ${lx + 4} ${y}" fill="none" stroke="${eyeCol}" stroke-width="2" stroke-linecap="round"/>`;
|
|
612
|
+
s += `<path d="M${rx - 4} ${y} Q${rx} ${y + 4.5} ${rx + 4} ${y}" fill="none" stroke="${eyeCol}" stroke-width="2" stroke-linecap="round"/>`;
|
|
422
613
|
break;
|
|
423
614
|
case 6:
|
|
424
615
|
s += `<circle cx="${lx}" cy="${y}" r="3.5" fill="${eyeWhite}"/>`;
|
|
425
616
|
s += `<circle cx="${lx + 0.5}" cy="${y}" r="2" fill="${eyeCol}"/>`;
|
|
426
617
|
s += `<circle cx="${lx + 1.5}" cy="${y - 1}" r="1" fill="white" opacity="0.9"/>`;
|
|
427
|
-
if (full) {
|
|
428
|
-
s += `<line x1="${lx + 2.5}" y1="${y - 3.5}" x2="${lx + 4}" y2="${y - 5}" stroke="${eyeCol}" stroke-width="0.8" stroke-linecap="round"/>`;
|
|
429
|
-
s += `<line x1="${lx + 3.5}" y1="${y - 2.5}" x2="${lx + 5}" y2="${y - 3.5}" stroke="${eyeCol}" stroke-width="0.8" stroke-linecap="round"/>`;
|
|
430
|
-
}
|
|
431
618
|
s += `<circle cx="${rx}" cy="${y}" r="3.5" fill="${eyeWhite}"/>`;
|
|
432
619
|
s += `<circle cx="${rx + 0.5}" cy="${y}" r="2" fill="${eyeCol}"/>`;
|
|
433
620
|
s += `<circle cx="${rx + 1.5}" cy="${y - 1}" r="1" fill="white" opacity="0.9"/>`;
|
|
434
|
-
if (full) {
|
|
435
|
-
s += `<line x1="${rx + 2.5}" y1="${y - 3.5}" x2="${rx + 4}" y2="${y - 5}" stroke="${eyeCol}" stroke-width="0.8" stroke-linecap="round"/>`;
|
|
436
|
-
s += `<line x1="${rx + 3.5}" y1="${y - 2.5}" x2="${rx + 5}" y2="${y - 3.5}" stroke="${eyeCol}" stroke-width="0.8" stroke-linecap="round"/>`;
|
|
437
|
-
}
|
|
438
621
|
break;
|
|
439
622
|
case 7:
|
|
440
623
|
s += `<ellipse cx="${lx}" cy="${y}" rx="4.5" ry="1.5" fill="${eyeWhite}"/>`;
|
|
@@ -442,6 +625,14 @@ function renderEyes(ei, eyeCol, eyeWhite, lidColor, full) {
|
|
|
442
625
|
s += `<ellipse cx="${rx}" cy="${y}" rx="4.5" ry="1.5" fill="${eyeWhite}"/>`;
|
|
443
626
|
s += `<ellipse cx="${rx + 0.5}" cy="${y}" rx="2.2" ry="1.2" fill="${eyeCol}"/>`;
|
|
444
627
|
break;
|
|
628
|
+
case 8:
|
|
629
|
+
s += `<circle cx="${lx}" cy="${y}" r="3.5" fill="${eyeWhite}"/>`;
|
|
630
|
+
s += `<circle cx="${lx - 1}" cy="${y}" r="2" fill="${eyeCol}"/>`;
|
|
631
|
+
if (full) s += `<circle cx="${lx - 0.3}" cy="${y - 0.8}" r="0.7" fill="white" opacity="0.8"/>`;
|
|
632
|
+
s += `<circle cx="${rx}" cy="${y}" r="3.5" fill="${eyeWhite}"/>`;
|
|
633
|
+
s += `<circle cx="${rx - 1}" cy="${y}" r="2" fill="${eyeCol}"/>`;
|
|
634
|
+
if (full) s += `<circle cx="${rx - 0.3}" cy="${y - 0.8}" r="0.7" fill="white" opacity="0.8"/>`;
|
|
635
|
+
break;
|
|
445
636
|
default:
|
|
446
637
|
s += `<circle cx="${lx}" cy="${y}" r="3.5" fill="${eyeWhite}"/>`;
|
|
447
638
|
s += `<circle cx="${lx + 0.8}" cy="${y}" r="2" fill="${eyeCol}"/>`;
|
|
@@ -454,7 +645,7 @@ function renderEyes(ei, eyeCol, eyeWhite, lidColor, full) {
|
|
|
454
645
|
}
|
|
455
646
|
return s;
|
|
456
647
|
}
|
|
457
|
-
function renderEyebrows(bi, browColor) {
|
|
648
|
+
function renderEyebrows(bi, browColor, full = true) {
|
|
458
649
|
const lx = 25, rx = 39, y = 27;
|
|
459
650
|
switch (bi) {
|
|
460
651
|
case 0:
|
|
@@ -467,6 +658,14 @@ function renderEyebrows(bi, browColor) {
|
|
|
467
658
|
return `<path d="M${lx - 4} ${y + 1} Q${lx} ${y - 3} ${lx + 4} ${y + 1}" fill="none" stroke="${browColor}" stroke-width="1" stroke-linecap="round"/><path d="M${rx - 4} ${y + 1} Q${rx} ${y - 3} ${rx + 4} ${y + 1}" fill="none" stroke="${browColor}" stroke-width="1" stroke-linecap="round"/>`;
|
|
468
659
|
case 4:
|
|
469
660
|
return `<polyline points="${lx - 3},${y + 1} ${lx},${y - 2} ${lx + 3},${y}" fill="none" stroke="${browColor}" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/><polyline points="${rx - 3},${y} ${rx},${y - 2} ${rx + 3},${y + 1}" fill="none" stroke="${browColor}" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>`;
|
|
661
|
+
case 5:
|
|
662
|
+
return `<line x1="${lx - 3}" y1="${y - 1}" x2="${lx + 3}" y2="${y + 1}" stroke="${browColor}" stroke-width="1.1" stroke-linecap="round"/><line x1="${rx - 3}" y1="${y + 1}" x2="${rx + 3}" y2="${y - 1}" stroke="${browColor}" stroke-width="1.1" stroke-linecap="round"/>`;
|
|
663
|
+
case 6: {
|
|
664
|
+
const bw = full ? "2.0" : "1.5";
|
|
665
|
+
return `<path d="M${lx - 4} ${y + 0.5} Q${lx} ${y - 2} ${lx + 4} ${y + 0.5}" fill="none" stroke="${browColor}" stroke-width="${bw}" stroke-linecap="round"/><path d="M${rx - 4} ${y + 0.5} Q${rx} ${y - 2} ${rx + 4} ${y + 0.5}" fill="none" stroke="${browColor}" stroke-width="${bw}" stroke-linecap="round"/>`;
|
|
666
|
+
}
|
|
667
|
+
case 7:
|
|
668
|
+
return `<path d="M${lx - 3.5} ${y} Q${lx} ${y - 1.5} ${lx + 3.5} ${y}" fill="none" stroke="${browColor}" stroke-width="0.5" stroke-linecap="round"/><path d="M${rx - 3.5} ${y} Q${rx} ${y - 1.5} ${rx + 3.5} ${y}" fill="none" stroke="${browColor}" stroke-width="0.5" stroke-linecap="round"/>`;
|
|
470
669
|
default:
|
|
471
670
|
return "";
|
|
472
671
|
}
|
|
@@ -482,6 +681,14 @@ function renderNose(ni, noseFill) {
|
|
|
482
681
|
return `<path d="M${cx - 2} ${y + 1} Q${cx} ${y - 2} ${cx + 2} ${y + 1}" fill="none" stroke="${noseFill}" stroke-width="1" stroke-linecap="round" opacity="0.5"/>`;
|
|
483
682
|
case 3:
|
|
484
683
|
return `<circle cx="${cx - 1.8}" cy="${y}" r="1.2" fill="${noseFill}" opacity="0.4"/><circle cx="${cx + 1.8}" cy="${y}" r="1.2" fill="${noseFill}" opacity="0.4"/>`;
|
|
684
|
+
case 4:
|
|
685
|
+
return `<path d="M${cx} ${y - 2} L${cx - 2} ${y + 1.5} L${cx + 2} ${y + 1.5} Z" fill="${noseFill}" opacity="0.4"/>`;
|
|
686
|
+
case 5:
|
|
687
|
+
return `<ellipse cx="${cx}" cy="${y}" rx="3.5" ry="1.5" fill="${noseFill}" opacity="0.35"/>`;
|
|
688
|
+
case 6:
|
|
689
|
+
return `<line x1="${cx}" y1="${y - 3}" x2="${cx}" y2="${y + 1}" stroke="${noseFill}" stroke-width="1.2" stroke-linecap="round" opacity="0.4"/>`;
|
|
690
|
+
case 7:
|
|
691
|
+
return `<circle cx="${cx}" cy="${y + 0.5}" r="2" fill="${noseFill}" opacity="0.35"/><ellipse cx="${cx}" cy="${y - 0.5}" rx="1" ry="0.5" fill="${noseFill}" opacity="0.15"/>`;
|
|
485
692
|
default:
|
|
486
693
|
return `<ellipse cx="${cx}" cy="${y}" rx="2" ry="1.2" fill="${noseFill}" opacity="0.35"/>`;
|
|
487
694
|
}
|
|
@@ -503,20 +710,20 @@ function renderMouth(mi, lipColor, isDark) {
|
|
|
503
710
|
case 5:
|
|
504
711
|
return `<path d="M${cx - 5} ${y} Q${cx} ${y + 6} ${cx + 5} ${y}" fill="${teethCol}" stroke="${lipColor}" stroke-width="1"/><line x1="${cx - 4}" y1="${y + 1.5}" x2="${cx + 4}" y2="${y + 1.5}" stroke="${lipColor}" stroke-width="0.3" opacity="0.3"/>`;
|
|
505
712
|
case 6:
|
|
506
|
-
return `<
|
|
713
|
+
return `<path d="M${cx - 4} ${y + 0.5} Q${cx} ${y + 1.5} ${cx + 4} ${y + 0.5}" fill="none" stroke="${lipColor}" stroke-width="1.4" stroke-linecap="round"/>`;
|
|
507
714
|
case 7:
|
|
508
715
|
return `<ellipse cx="${cx}" cy="${y + 1}" rx="3.5" ry="2" fill="${lipColor}" opacity="0.25"/><path d="M${cx - 3} ${y} Q${cx} ${y + 2.5} ${cx + 3} ${y}" fill="none" stroke="${lipColor}" stroke-width="1.2" stroke-linecap="round"/>`;
|
|
509
716
|
default:
|
|
510
717
|
return `<path d="M${cx - 4} ${y} Q${cx} ${y + 4} ${cx + 4} ${y}" fill="none" stroke="${lipColor}" stroke-width="1.4" stroke-linecap="round"/>`;
|
|
511
718
|
}
|
|
512
719
|
}
|
|
513
|
-
function renderAccessory(ai, accessoryColor, glassesColor, earringColor, headbandColor) {
|
|
720
|
+
function renderAccessory(ai, accessoryColor, glassesColor, earringColor, headbandColor, beautyMarkColor = "#3a2a2a", freckleColor = "#a0785a", skinColor = "#E8BA8B") {
|
|
514
721
|
switch (ai) {
|
|
515
722
|
case 0:
|
|
516
723
|
return "";
|
|
517
724
|
// None
|
|
518
725
|
case 1:
|
|
519
|
-
return `<circle cx="40" cy="44" r="0.8" fill="
|
|
726
|
+
return `<circle cx="40" cy="44" r="0.8" fill="${beautyMarkColor}"/>`;
|
|
520
727
|
case 2:
|
|
521
728
|
return `<g fill="none" stroke="${glassesColor}" stroke-width="1"><circle cx="25" cy="33" r="5.5"/><circle cx="39" cy="33" r="5.5"/><line x1="30.5" y1="33" x2="33.5" y2="33"/><line x1="19.5" y1="33" x2="14" y2="31"/><line x1="44.5" y1="33" x2="50" y2="31"/></g>`;
|
|
522
729
|
case 3:
|
|
@@ -526,13 +733,17 @@ function renderAccessory(ai, accessoryColor, glassesColor, earringColor, headban
|
|
|
526
733
|
case 5:
|
|
527
734
|
return `<rect x="13" y="20" width="38" height="3.5" rx="1.5" fill="${headbandColor}" opacity="0.85"/>`;
|
|
528
735
|
case 6:
|
|
529
|
-
return `<g fill="
|
|
736
|
+
return `<g fill="${freckleColor}" opacity="0.35"><circle cx="21" cy="40" r="0.6"/><circle cx="23" cy="42" r="0.5"/><circle cx="19" cy="41.5" r="0.5"/><circle cx="43" cy="40" r="0.6"/><circle cx="41" cy="42" r="0.5"/><circle cx="45" cy="41.5" r="0.5"/></g>`;
|
|
530
737
|
case 7:
|
|
531
738
|
return `<circle cx="10" cy="37" r="1.2" fill="${earringColor}"/><circle cx="54" cy="37" r="1.2" fill="${earringColor}"/>`;
|
|
532
739
|
case 8:
|
|
533
740
|
return `<g fill="none" stroke="${glassesColor}" stroke-width="1.2"><path d="M19 30 Q19 28 25 28 Q31 28 31 33 Q31 38 25 38 Q19 38 19 33 Z" fill="${glassesColor}" fill-opacity="0.15"/><path d="M33 30 Q33 28 39 28 Q45 28 45 33 Q45 38 39 38 Q33 38 33 33 Z" fill="${glassesColor}" fill-opacity="0.15"/><line x1="31" y1="32" x2="33" y2="32"/><line x1="19" y1="31" x2="14" y2="29"/><line x1="45" y1="31" x2="50" y2="29"/></g>`;
|
|
534
741
|
case 9:
|
|
535
|
-
return `<g><rect x="38" y="38" width="
|
|
742
|
+
return `<g><rect x="38" y="38" width="9" height="4.5" rx="1.2" fill="#f0d0a0" transform="rotate(-15 42 40)"/><rect x="39.5" y="38.5" width="6" height="3.5" rx="0.8" fill="#f5ddb5" transform="rotate(-15 42 40)"/><circle cx="42.5" cy="40.25" r="0.5" fill="#d4b898" transform="rotate(-15 42 40)"/></g>`;
|
|
743
|
+
case 10:
|
|
744
|
+
return `<line x1="23" y1="24.8" x2="23.8" y2="29.2" stroke="${skinColor}" stroke-width="1.3" stroke-linecap="butt"/>`;
|
|
745
|
+
case 11:
|
|
746
|
+
return `<line x1="41" y1="24.8" x2="40.2" y2="29.2" stroke="${skinColor}" stroke-width="1.3" stroke-linecap="butt"/>`;
|
|
536
747
|
default:
|
|
537
748
|
return "";
|
|
538
749
|
}
|
|
@@ -562,14 +773,17 @@ function renderSolFaceSVG(walletAddress, options) {
|
|
|
562
773
|
const glassesColor = theme?.glassesColor ?? "#4a4a5a";
|
|
563
774
|
const earringColor = theme?.earringColor ?? blend(skin, "#d4a840", 0.4);
|
|
564
775
|
const headbandColor = theme?.headbandColor ?? blend(hairCol, "#c04040", 0.5);
|
|
776
|
+
const beautyMarkColor = theme?.beautyMarkColor ?? "#3a2a2a";
|
|
777
|
+
const freckleColor = theme?.freckleColor ?? "#a0785a";
|
|
565
778
|
const id = "sf" + djb22(walletAddress).toString(36);
|
|
566
779
|
const cheekEnabled = theme?.cheekEnabled ?? true;
|
|
567
780
|
const cheekColor = theme?.cheekColor ?? derived.cheekColor;
|
|
568
781
|
const cheekOpacity = theme?.cheekOpacity ?? derived.cheekOpacity;
|
|
569
|
-
|
|
782
|
+
traits.hairStyle % 10;
|
|
570
783
|
const ai = effectiveAccessory(traits);
|
|
571
784
|
const classAttr = className ? ` class="${className}"` : "";
|
|
572
|
-
|
|
785
|
+
const altText = solFaceAltText(walletAddress).replace(/"/g, """);
|
|
786
|
+
let svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="${size}" height="${size}"${classAttr} role="img" aria-label="${altText}">`;
|
|
573
787
|
const glowIntensity = theme?.glowIntensity ?? 0.1;
|
|
574
788
|
svg += buildDefs(id, skin, derived.skinHi, derived.skinLo, hairCol, bgCol, cheekColor, cheekOpacity, flat, full && cheekEnabled, glowIntensity);
|
|
575
789
|
const blinkEnabled = !!enableBlink;
|
|
@@ -582,29 +796,29 @@ function renderSolFaceSVG(walletAddress, options) {
|
|
|
582
796
|
}
|
|
583
797
|
const bgFill = flat ? bgCol : `url(#${id}bg)`;
|
|
584
798
|
svg += `<rect x="0" y="0" width="64" height="64" fill="${bgFill}" opacity="${bgOpacity}" rx="${bgRadius}"/>`;
|
|
585
|
-
svg += renderHairBack(
|
|
586
|
-
svg += renderEars(derived.earFill, derived.earShadow);
|
|
799
|
+
if (theme?.hairEnabled !== false) svg += renderHairBack();
|
|
800
|
+
if (theme?.earsEnabled !== false) svg += renderEars(theme?.earColor ?? derived.earFill, derived.earShadow);
|
|
587
801
|
const skinOpacity = theme?.skinOpacity ?? 1;
|
|
588
802
|
svg += renderFace(id, skin, flat, skinOpacity);
|
|
589
803
|
const shadowEnabled = theme?.shadowEnabled ?? true;
|
|
590
804
|
if (full && cheekEnabled && shadowEnabled) {
|
|
591
805
|
svg += renderFaceOverlays(id, flat);
|
|
592
806
|
}
|
|
593
|
-
if (
|
|
594
|
-
|
|
807
|
+
if (theme?.hairEnabled !== false) svg += renderHairFront();
|
|
808
|
+
if (ai === 5 && theme?.accessoriesEnabled !== false) {
|
|
809
|
+
svg += renderAccessory(5, accColor, glassesColor, earringColor, headbandColor, beautyMarkColor, freckleColor, skin);
|
|
595
810
|
}
|
|
596
|
-
svg += renderHairFront(hi, id, hairCol, skin, flat);
|
|
597
811
|
if (blinkEnabled) {
|
|
598
812
|
const uid = `sf-${walletAddress.slice(0, 8)}`;
|
|
599
813
|
svg += `<g class="${uid}-eyes">`;
|
|
600
814
|
}
|
|
601
|
-
svg += renderEyes(traits.eyeStyle %
|
|
815
|
+
svg += renderEyes(traits.eyeStyle % 9, eyeCol, eyeWhite, theme?.lidColor ?? derived.lidColor, full);
|
|
602
816
|
if (blinkEnabled) svg += `</g>`;
|
|
603
|
-
svg += renderEyebrows(traits.eyebrows %
|
|
604
|
-
svg += renderNose(traits.nose %
|
|
817
|
+
if (theme?.eyebrowsEnabled !== false) svg += renderEyebrows(traits.eyebrows % 8, browColor, full);
|
|
818
|
+
if (theme?.noseEnabled !== false) svg += renderNose(traits.nose % 8, noseFill);
|
|
605
819
|
svg += renderMouth(traits.mouth % 8, lipColor, derived.isDark);
|
|
606
|
-
if (ai !== 0 && ai !== 5) {
|
|
607
|
-
svg += renderAccessory(ai, accColor, glassesColor, earringColor, headbandColor);
|
|
820
|
+
if (ai !== 0 && ai !== 5 && theme?.accessoriesEnabled !== false) {
|
|
821
|
+
svg += renderAccessory(ai, accColor, glassesColor, earringColor, headbandColor, beautyMarkColor, freckleColor, skin);
|
|
608
822
|
}
|
|
609
823
|
if (theme?.border) {
|
|
610
824
|
svg += `<rect x="0" y="0" width="64" height="64" fill="none" stroke="${theme.border.color}" stroke-width="${theme.border.width}" rx="${bgRadius}"/>`;
|
|
@@ -621,6 +835,6 @@ function renderSolFaceBase64(walletAddress, options) {
|
|
|
621
835
|
return `data:image/svg+xml;base64,${btoa(svg)}`;
|
|
622
836
|
}
|
|
623
837
|
|
|
624
|
-
export { BG_COLORS, EYE_COLORS, HAIR_COLORS, SKIN_COLORS, blend,
|
|
625
|
-
//# sourceMappingURL=chunk-
|
|
626
|
-
//# sourceMappingURL=chunk-
|
|
838
|
+
export { BG_COLORS, EYE_COLORS, HAIR_COLORS, SKIN_COLORS, agentAppearancePrompt, blend, contrastRatio, darken, deriveSkinColors, describeAppearance, describeTraits, effectiveAccessory, generateTraits, getTraitLabels, hexToRgb, lighten, luminance, mergeTheme, renderSolFaceBase64, renderSolFaceDataURI, renderSolFaceSVG, resolveTheme, rgbToHex, solFaceAltText, traitHash };
|
|
839
|
+
//# sourceMappingURL=chunk-N5GDLCCL.js.map
|
|
840
|
+
//# sourceMappingURL=chunk-N5GDLCCL.js.map
|