@botharness/pixel-avatar 0.5.0 → 0.6.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 +1 -0
- package/dist/index.d.ts +59 -14
- package/dist/index.js +343 -207
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,6 +21,7 @@ const svg = pixelAvatarSvg(recipe); // 32×32 viewBox, crisp edges, no ids or sc
|
|
|
21
21
|
- `AVATAR_SPECIES`, `AVATAR_SPECIES_SWATCHES`, `AVATAR_PIECE_COLORS`, `withSpecies(recipe, species)`: Avatar Species (`human`, `goblin`) on the same rig, as asset version 2. `withSpecies` keeps every choice, splits side hair into `sideHair` (left) and `rightSideHair`, and accepts optional `leftSideHairColor`/`rightSideHairColor`, where left and right are as seen on screen. Consumers built before version 2 reject these recipes with `isPixelAvatarRecipe` and can show a saved snapshot instead.
|
|
22
22
|
- `AVATAR_PARTS_V2`, `AVATAR_EXTRA_PARTS`, `hiddenChoices(recipe)`: version 2 adds elf, dwarf, orc and flower species, armor/robe/tunic/cloak outfits, helmet/hood headwear, an optional `beard`, and a flower's `petals` and `flowerBase`. `hiddenChoices` names saved choices the current species or headwear keeps but does not draw, so an editor can say so instead of discarding them.
|
|
23
23
|
- `PixelCustomPart`, `withHeadpiece(recipe, part)`, `customPartId`, `isPixelCustomPart`: a Human-drawn Custom Part in the `headpiece` slot (the top 32×16 of the tile). Its back layer is drawn behind the hair and its front layer over it, and both follow the head through turns. Each cell is `[x, y, color, tone]`, where `color` is an appearance color slot (`hairColor`, `skinColor`, `eyeColor`, `shirtColor`), so the part recolors with the Avatar, or a fixed `#rrggbb`, and `tone` is a step from −2 to 2 on the rig's shade ramp (`partToneColor`). A recipe wearing a part embeds its own copy as asset version 3. `customPartId` is the SHA-256 of the canonical content; names, authors and origins belong to the consumer's library.
|
|
24
|
+
- `HAIR_PART_SLOTS`, `hairPieceStart(recipe, slot)`, `withCustomPart(recipe, slot, part)`, `wornPart`: drawn hair pieces. `bangs`, `leftSideHair`, `rightSideHair` and `backHair` each take a Custom Part (front layer only) that replaces the built-in piece while it stays saved underneath. In a hair part, a `hairColor` cell at tone 0 is live hair: it is shaded with the rest of the hair exactly like the built-in piece, so `hairPieceStart` flattens the worn built-in piece into such cells and an unchanged copy renders identically. Other cells show their own color. Drawn hair follows turns and is hidden under a helmet or hood and on a flower, like built-in hair.
|
|
24
25
|
- `emptyPartLayer`, `paintPartLayer`, `fillPartLayer`, `mirrorPartX`, `partLayer`, `partCells`, `createCustomPart`: drawing on dense layers, with pencil and eraser strokes, 4-connected flood fill and mirroring across the Avatar centerline.
|
|
25
26
|
- `faceCells`, `pixelSymbolCells`, `symbolArtCells`: pixels for [`@botharness/pixel-morph`](../morph).
|
|
26
27
|
- `pixelAvatarSvg(recipe, { turns, classPrefix })`: optional pre-rendered head turns, and rig layer classes (`<prefix>-body`, `-head`, `-face`, `-gaze`, `-blink`) for CSS animation.
|
package/dist/index.d.ts
CHANGED
|
@@ -72,9 +72,7 @@ type PixelAvatarRecipeV1 = Meta & {
|
|
|
72
72
|
} & { [P in AvatarPart]: (typeof AVATAR_PARTS)[P][number] } & { [P in AvatarHairPart]?: (typeof AVATAR_PARTS)['hair'][number] } & { [P in AvatarRange]?: number } & {
|
|
73
73
|
species?: never;
|
|
74
74
|
rightSideHair?: never;
|
|
75
|
-
} & { [P in AvatarPieceColor | AvatarExtraPart]?: never } & {
|
|
76
|
-
headpiece?: never;
|
|
77
|
-
};
|
|
75
|
+
} & { [P in AvatarPieceColor | AvatarExtraPart]?: never } & { [P in CustomPartKey]?: never };
|
|
78
76
|
/**
|
|
79
77
|
* Asset version 2: a species, the full split hair and geometry, a separate right side hair
|
|
80
78
|
* (`sideHair` is then the left side) and optional per-side hair colors.
|
|
@@ -84,14 +82,23 @@ type PixelAvatarRecipeV2 = Meta & {
|
|
|
84
82
|
} & { [P in AvatarPart]: (typeof AVATAR_PARTS_V2)[P][number] } & { [P in AvatarHairPart]: (typeof AVATAR_PARTS)['hair'][number] } & { [P in AvatarRange]: number } & {
|
|
85
83
|
species: AvatarSpecies;
|
|
86
84
|
rightSideHair: (typeof AVATAR_HAIR_PARTS)['sideHair'][number];
|
|
87
|
-
} & { [P in AvatarPieceColor]?: string } & { [P in AvatarExtraPart]?: (typeof AVATAR_EXTRA_PARTS)[P][number] } & {
|
|
88
|
-
|
|
85
|
+
} & { [P in AvatarPieceColor]?: string } & { [P in AvatarExtraPart]?: (typeof AVATAR_EXTRA_PARTS)[P][number] } & { [P in CustomPartKey]?: never };
|
|
86
|
+
/** The recipe key that embeds the Custom Part worn in each slot. */
|
|
87
|
+
declare const CUSTOM_PART_KEYS: {
|
|
88
|
+
readonly headpiece: "headpiece";
|
|
89
|
+
readonly bangs: "bangsPart";
|
|
90
|
+
readonly leftSideHair: "leftSideHairPart";
|
|
91
|
+
readonly rightSideHair: "rightSideHairPart";
|
|
92
|
+
readonly backHair: "backHairPart";
|
|
89
93
|
};
|
|
90
|
-
|
|
91
|
-
|
|
94
|
+
type CustomPartKey = (typeof CUSTOM_PART_KEYS)[PartSlot];
|
|
95
|
+
/**
|
|
96
|
+
* Asset version 3: version 2 wearing at least one embedded Custom Part. A drawn hair piece
|
|
97
|
+
* replaces the built-in piece, which stays saved and returns when the part is taken off.
|
|
98
|
+
*/
|
|
99
|
+
type PixelAvatarRecipeV3 = Omit<PixelAvatarRecipeV2, 'assetVersion' | CustomPartKey> & {
|
|
92
100
|
assetVersion: 3;
|
|
93
|
-
|
|
94
|
-
};
|
|
101
|
+
} & { [P in CustomPartKey]?: PixelCustomPart };
|
|
95
102
|
type PixelAvatarRecipe = PixelAvatarRecipeV1 | PixelAvatarRecipeV2 | PixelAvatarRecipeV3;
|
|
96
103
|
declare const DEFAULT_RECIPE: PixelAvatarRecipeV1;
|
|
97
104
|
declare function isPixelAvatarRecipe(value: unknown): value is PixelAvatarRecipe;
|
|
@@ -112,10 +119,14 @@ declare function withSpecies(recipe: PixelAvatarRecipeV3, species: AvatarSpecies
|
|
|
112
119
|
declare function withSpecies(recipe: PixelAvatarRecipeV1 | PixelAvatarRecipeV2, species: AvatarSpecies): PixelAvatarRecipeV2;
|
|
113
120
|
declare function withSpecies(recipe: PixelAvatarRecipe, species: AvatarSpecies): PixelAvatarRecipeV2 | PixelAvatarRecipeV3;
|
|
114
121
|
/**
|
|
115
|
-
* Returns the recipe wearing
|
|
116
|
-
*
|
|
122
|
+
* Returns the recipe wearing `part` in `slot`, or with that slot's part taken off. The recipe
|
|
123
|
+
* embeds its own copy; it is asset version 3 while it wears any part and version 2 otherwise.
|
|
117
124
|
*/
|
|
125
|
+
declare function withCustomPart(recipe: PixelAvatarRecipe, slot: PartSlot, part: PixelCustomPart | undefined): PixelAvatarRecipeV2 | PixelAvatarRecipeV3;
|
|
126
|
+
/** `withCustomPart` for the headpiece slot. */
|
|
118
127
|
declare function withHeadpiece(recipe: PixelAvatarRecipe, part: PixelCustomPart | undefined): PixelAvatarRecipeV2 | PixelAvatarRecipeV3;
|
|
128
|
+
/** The Custom Part worn in a slot, if any. */
|
|
129
|
+
declare function wornPart(recipe: PixelAvatarRecipe, slot: PartSlot): PixelCustomPart | undefined;
|
|
119
130
|
declare function detailedRecipe(recipe: PixelAvatarRecipe): PixelAvatarRecipe;
|
|
120
131
|
declare const AVATAR_SWATCHES: Record<AvatarColor, readonly string[]>;
|
|
121
132
|
/**
|
|
@@ -141,16 +152,40 @@ declare const AVATAR_PRESETS: readonly PixelAvatarRecipe[];
|
|
|
141
152
|
//#region src/part.d.ts
|
|
142
153
|
/**
|
|
143
154
|
* Custom Part slots. A headpiece covers the top of the tile, around the hair: its back layer is
|
|
144
|
-
* drawn behind the hair and its front layer over it.
|
|
145
|
-
*
|
|
155
|
+
* drawn behind the hair and its front layer over it. Hair slots replace one built-in hair piece
|
|
156
|
+
* and use only the front layer. Cells are in tile coordinates, so the Avatar centerline sits
|
|
157
|
+
* between x = 15 and x = 16.
|
|
146
158
|
*/
|
|
147
159
|
declare const PART_SLOTS: {
|
|
148
160
|
readonly headpiece: {
|
|
149
161
|
readonly width: 32;
|
|
150
162
|
readonly height: 16;
|
|
151
163
|
};
|
|
164
|
+
readonly bangs: {
|
|
165
|
+
readonly width: 32;
|
|
166
|
+
readonly height: 32;
|
|
167
|
+
};
|
|
168
|
+
readonly leftSideHair: {
|
|
169
|
+
readonly width: 32;
|
|
170
|
+
readonly height: 32;
|
|
171
|
+
};
|
|
172
|
+
readonly rightSideHair: {
|
|
173
|
+
readonly width: 32;
|
|
174
|
+
readonly height: 32;
|
|
175
|
+
};
|
|
176
|
+
readonly backHair: {
|
|
177
|
+
readonly width: 32;
|
|
178
|
+
readonly height: 32;
|
|
179
|
+
};
|
|
152
180
|
};
|
|
153
181
|
type PartSlot = keyof typeof PART_SLOTS;
|
|
182
|
+
/**
|
|
183
|
+
* Hair slots. In a hair part, a `hairColor` cell at tone 0 is live hair: it is shaded with the
|
|
184
|
+
* rest of the hair, exactly like a built-in piece. Every other cell shows its own color.
|
|
185
|
+
*/
|
|
186
|
+
declare const HAIR_PART_SLOTS: readonly ["bangs", "leftSideHair", "rightSideHair", "backHair"];
|
|
187
|
+
type HairPartSlot = (typeof HAIR_PART_SLOTS)[number];
|
|
188
|
+
declare const isHairPartSlot: (slot: PartSlot) => slot is HairPartSlot;
|
|
154
189
|
/** Tone steps on the rig's shade ramp: two darker, the color itself, two lighter. */
|
|
155
190
|
declare const PART_TONES: readonly [-2, -1, 0, 1, 2];
|
|
156
191
|
type PartTone = (typeof PART_TONES)[number];
|
|
@@ -215,6 +250,16 @@ declare function pixelFigure(recipe: Recipe, yawDeg: number, options?: PixelFigu
|
|
|
215
250
|
head: string;
|
|
216
251
|
cells: PixelCell$1[];
|
|
217
252
|
};
|
|
253
|
+
/**
|
|
254
|
+
* The hair piece in `slot` as a Custom Part to start drawing from: the drawn part worn there,
|
|
255
|
+
* or the built-in piece flattened for this recipe in the front pose as live `hairColor` cells.
|
|
256
|
+
* A flattened piece keeps this shape and no longer follows face shape or hair length.
|
|
257
|
+
*/
|
|
258
|
+
declare function hairPieceStart(recipe: PixelAvatarRecipe, slot: HairPartSlot): {
|
|
259
|
+
slot: HairPartSlot;
|
|
260
|
+
front: PartCell[];
|
|
261
|
+
back: PartCell[];
|
|
262
|
+
};
|
|
218
263
|
//#endregion
|
|
219
264
|
//#region src/random.d.ts
|
|
220
265
|
declare function seededRandom(seed: string): () => number;
|
|
@@ -264,5 +309,5 @@ declare function pixelSymbolCells(symbol: PixelSymbol, color: string): PixelCell
|
|
|
264
309
|
*/
|
|
265
310
|
declare function symbolArtCells(rows: readonly string[], color: string): PixelCell$1[];
|
|
266
311
|
//#endregion
|
|
267
|
-
export { AVATAR_COLORS, AVATAR_EXTRA_PARTS, AVATAR_HAIR_PARTS, AVATAR_PARTS, AVATAR_PARTS_V2, AVATAR_PIECE_COLORS, AVATAR_PRESETS, AVATAR_RANGES, AVATAR_SPECIES, AVATAR_SPECIES_SWATCHES, AVATAR_SWATCHES, AVATAR_TURNS, type AvatarColor, type AvatarExtraPart, type AvatarHairPart, type AvatarPart, type AvatarPieceColor, type AvatarRange, type AvatarSpecies, DEFAULT_RECIPE, MAX_PART_FIXED_COLORS, PART_LAYERS, PART_SLOTS, PART_TONES, PIXEL_SYMBOLS, type PartCell, type PartColor, type PartInk, type PartLayer, type PartLayerName, type PartSlot, type PartTone, type PixelAvatarRecipe, type PixelAvatarRecipeV1, type PixelAvatarRecipeV2, type PixelAvatarRecipeV3, type PixelAvatarSvgOptions, type PixelCell, type PixelCustomPart, type PixelFigureOptions, type PixelGrid, type PixelMouthState, type PixelSymbol, canonicalCustomPart, canonicalRecipe, createCustomPart, createSeededRecipe, createSeededRecipeV2, customPartId, detailedRecipe, emptyPartLayer, faceCells, fillPartLayer, hiddenChoices, isPixelAvatarRecipe, isPixelCustomPart, mirrorPartX, paintPartLayer, partCells, partLayer, partToneColor, pixelAvatarSvg, pixelFigure, pixelSymbolCells, pixelTileColor, seededRandom, seededRecipe, seededRecipeV2, symbolArtCells, withHeadpiece, withSpecies };
|
|
312
|
+
export { AVATAR_COLORS, AVATAR_EXTRA_PARTS, AVATAR_HAIR_PARTS, AVATAR_PARTS, AVATAR_PARTS_V2, AVATAR_PIECE_COLORS, AVATAR_PRESETS, AVATAR_RANGES, AVATAR_SPECIES, AVATAR_SPECIES_SWATCHES, AVATAR_SWATCHES, AVATAR_TURNS, type AvatarColor, type AvatarExtraPart, type AvatarHairPart, type AvatarPart, type AvatarPieceColor, type AvatarRange, type AvatarSpecies, CUSTOM_PART_KEYS, type CustomPartKey, DEFAULT_RECIPE, HAIR_PART_SLOTS, type HairPartSlot, MAX_PART_FIXED_COLORS, PART_LAYERS, PART_SLOTS, PART_TONES, PIXEL_SYMBOLS, type PartCell, type PartColor, type PartInk, type PartLayer, type PartLayerName, type PartSlot, type PartTone, type PixelAvatarRecipe, type PixelAvatarRecipeV1, type PixelAvatarRecipeV2, type PixelAvatarRecipeV3, type PixelAvatarSvgOptions, type PixelCell, type PixelCustomPart, type PixelFigureOptions, type PixelGrid, type PixelMouthState, type PixelSymbol, canonicalCustomPart, canonicalRecipe, createCustomPart, createSeededRecipe, createSeededRecipeV2, customPartId, detailedRecipe, emptyPartLayer, faceCells, fillPartLayer, hairPieceStart, hiddenChoices, isHairPartSlot, isPixelAvatarRecipe, isPixelCustomPart, mirrorPartX, paintPartLayer, partCells, partLayer, partToneColor, pixelAvatarSvg, pixelFigure, pixelSymbolCells, pixelTileColor, seededRandom, seededRecipe, seededRecipeV2, symbolArtCells, withCustomPart, withHeadpiece, withSpecies, wornPart };
|
|
268
313
|
//# sourceMappingURL=index.d.ts.map
|