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