wobnimo 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/AGENTS.md +18 -4
  2. package/README.md +38 -7
  3. package/dist/characters/bao.d.ts +6 -0
  4. package/dist/characters/bao.js +1 -0
  5. package/dist/characters/berry.d.ts +6 -0
  6. package/dist/characters/berry.js +1 -0
  7. package/dist/characters/boo.js +1 -1
  8. package/dist/characters/bumble.d.ts +6 -0
  9. package/dist/characters/bumble.js +1 -0
  10. package/dist/characters/cacti.d.ts +6 -0
  11. package/dist/characters/cacti.js +1 -0
  12. package/dist/characters/cap.d.ts +6 -0
  13. package/dist/characters/cap.js +1 -0
  14. package/dist/characters/drift.d.ts +6 -0
  15. package/dist/characters/drift.js +1 -0
  16. package/dist/characters/ember.d.ts +6 -0
  17. package/dist/characters/ember.js +1 -0
  18. package/dist/characters/hop.d.ts +6 -0
  19. package/dist/characters/hop.js +1 -0
  20. package/dist/characters/index.d.ts +11 -1
  21. package/dist/characters/index.js +11 -11
  22. package/dist/characters/inky.js +1 -1
  23. package/dist/characters/latte.d.ts +6 -0
  24. package/dist/characters/latte.js +1 -0
  25. package/dist/characters/microduck.js +1 -1
  26. package/dist/characters/miso.js +1 -1
  27. package/dist/characters/mochi.js +1 -1
  28. package/dist/characters/pebble.js +1 -1
  29. package/dist/characters/pip.js +1 -1
  30. package/dist/characters/rex.js +1 -1
  31. package/dist/characters/swirl.d.ts +6 -0
  32. package/dist/characters/swirl.js +1 -0
  33. package/dist/characters/tad.js +1 -1
  34. package/dist/characters/volt.js +1 -1
  35. package/dist/cli.js +1888 -0
  36. package/dist/element.d.ts +1 -1
  37. package/dist/element.js +9 -9
  38. package/dist/index-Cm5wWKoT.d.ts +12 -0
  39. package/dist/index.d.ts +4 -0
  40. package/dist/index.js +6 -6
  41. package/dist/react.js +16 -16
  42. package/dist/wobnimo.js +12 -12
  43. package/package.json +14 -4
  44. package/skill/SKILL.md +719 -0
  45. package/skill/examples/bao.ts +73 -0
  46. package/skill/examples/berry.ts +97 -0
  47. package/skill/examples/boo.ts +87 -0
  48. package/skill/examples/bumble.ts +70 -0
  49. package/skill/examples/cacti.ts +79 -0
  50. package/skill/examples/cap.ts +59 -0
  51. package/skill/examples/drift.ts +74 -0
  52. package/skill/examples/ember.ts +78 -0
  53. package/skill/examples/hop.ts +66 -0
  54. package/skill/examples/inky.ts +168 -0
  55. package/skill/examples/latte.ts +73 -0
  56. package/skill/examples/microduck.ts +222 -0
  57. package/skill/examples/miso.ts +182 -0
  58. package/skill/examples/mochi.ts +78 -0
  59. package/skill/examples/pebble.ts +174 -0
  60. package/skill/examples/pip.ts +170 -0
  61. package/skill/examples/rex.ts +193 -0
  62. package/skill/examples/swirl.ts +69 -0
  63. package/skill/examples/tad.ts +117 -0
  64. package/skill/examples/volt.ts +214 -0
  65. package/skill/reference/recipes.md +551 -0
  66. package/skill/reference/spec.md +258 -0
  67. package/skill/templates/starter.ts +73 -0
  68. package/dist/index-DRDEWSGV.d.ts +0 -8
@@ -0,0 +1,258 @@
1
+ # CharacterSpec reference
2
+
3
+ Every field, with its type, default and useful range. The TypeScript types
4
+ ship with the package (`import type { CharacterSpec } from 'wobnimo'`), so
5
+ an editor will also tell you when a field is wrong. Units: the floor is
6
+ y = 0, +y up, +x to the viewer's right, +z toward the camera; about 1 unit
7
+ tall; angles in radians. `Vec3` is `[x, y, z]`; colours are `'#rrggbb'`.
8
+
9
+ ## Top level
10
+
11
+ | field | type | required | notes |
12
+ | --- | --- | --- | --- |
13
+ | `id` | string | yes | lowercase letters, digits, dashes; unique |
14
+ | `name` | string | yes | display name |
15
+ | `tagline` | string | yes | one line describing the character |
16
+ | `accent` | colour | yes | a UI colour that goes with the character |
17
+ | `frame` | `{ target, radius }` | yes | camera look-at height and half the visible height; copy from the check |
18
+ | `bound` | `{ y, radius }` | yes | sphere (centre height, radius) above the root containing the body in every state; copy from the check |
19
+ | `motion` | object | no | temperament, below |
20
+ | `materials` | `Record<name, Material>` | yes | at least one |
21
+ | `bones` | `Bone[]` | yes | parents before children |
22
+ | `parts` | `Part[]` | yes | drawn in order; the first must not be a subtraction |
23
+ | `paints` | `Paint[]` | no | colour on the surface |
24
+ | `eyes` | `Eyes` | no | almost always wanted |
25
+ | `face` | `Face` | no | a mouth, or an LED screen face |
26
+ | `anchors` | `Record<name, { bone, at }>` | no | give `top`, `mouth`, `ear`, `feet` |
27
+ | `acting` | `Record<state, Record<bone, Record<axis, Motion>>>` | no | per-state bone motion |
28
+ | `fx` | object | no | extra particle effects |
29
+ | `glowPool` | number | no | 0 to 0.6: the state's light pools on the floor (for glowing characters) |
30
+
31
+ ## motion
32
+
33
+ | field | default | range | meaning |
34
+ | --- | --- | --- | --- |
35
+ | `float` | 0 | 0 to 0.3 | hover height; above 0 the character floats and bobs |
36
+ | `hop` | 0.16 | 0.08 to 0.25 | hop height |
37
+ | `squash` | 1 | 0.6 to 2 | squash and stretch amount |
38
+ | `snap` | 1 | 0.7 to 1.3 | spring speed (higher is snappier) |
39
+ | `look` | 1 | 0.5 to 1.2 | how far the head turns toward things |
40
+ | `snapLook` | 0 | 0 to 1 | 0 eases like a person, 1 snaps and holds like a bird |
41
+ | `talkSquash` | 0 | 0 to 1.3 | body bounce per syllable while speaking |
42
+
43
+ ## materials
44
+
45
+ | field | default | range | meaning |
46
+ | --- | --- | --- | --- |
47
+ | `color` | | colour | base colour (required) |
48
+ | `shadeOf` | | material name | recolours along with that material |
49
+ | `f0` | 0.04 | 0 to 1 | clear-coat reflectance; 0.02 matte, 0.06 glossy, 0.45 metal |
50
+ | `spec` | 0.5 | 0 to 2.6 | highlight strength |
51
+ | `shininess` | 40 | 6 to 420 | highlight tightness (higher is a smaller, sharper highlight) |
52
+ | `metal` | 0 | 0 to 1 | how much reflections take the colour |
53
+ | `rim` | 0.5 | 0 to 1.4 | back light around the silhouette |
54
+ | `gloss` | 0.3 | 0 to 1 | reflection sharpness: 0 satin, 1 wet glass |
55
+ | `sheen` | 0 | 0 to 1 | velvet glow at grazing angles (fur, felt, feathers) |
56
+ | `sss` | 0 | 0 to 0.7 | light through the surface (jelly, wax, ears, leaves) |
57
+ | `sssColor` | | colour | colour of that light, a lighter tint of `color` |
58
+ | `emit` | | colour | light it gives off; use with `emitStrength` 0.05 to 0.1 for a soft glow |
59
+ | `emitStrength` | 1 | 0 to 2 | multiplies `emit` or `glows` |
60
+ | `glows` | false | | takes its light from the current state's colour (lamps, LEDs, bulbs) |
61
+ | `surface` | | object | fine detail, below |
62
+
63
+ `surface: { kind, scale, strength?, color?, bone? }`:
64
+
65
+ | kind | scale | strength | notes |
66
+ | --- | --- | --- | --- |
67
+ | `fur` | 70 to 130 | 0.25 to 0.5 | fine fibres; lower scale is longer, clumpier fur |
68
+ | `scales` | 20 to 45 | 0.5 to 0.75 | pebbled hide with `color` seams; also reads as knit wool |
69
+ | `speckle` | 9 to 30 | 0.4 to 0.85 | scattered `color` spots |
70
+ | `ripple` | 18 to 70 | 0.1 to 0.25 | gentle unevenness; makes gloss look wet or moulded |
71
+
72
+ `bone` fixes the pattern to that bone (default the root). One material per
73
+ moving bone: see SKILL.md section 5.
74
+
75
+ ## bones
76
+
77
+ | field | type | notes |
78
+ | --- | --- | --- |
79
+ | `name` | string | unique; `root` is reserved (the implicit bone on the floor) |
80
+ | `parent` | bone name | default `root`; must be listed earlier |
81
+ | `pivot` | Vec3 | the joint, in the parent's space |
82
+ | `rest` | `{ rx?, ry?, rz? }` | fixed rotation at rest |
83
+ | `drive` | `{ rx?, ry?, rz?: [channel, amount][] }` | channels: `yaw`, `pitch`, `roll` (where it looks), `flap` (0 to 1, arms up), `talk` (0 to 1 per syllable) |
84
+ | `wave` | `{ rx?, ry?, rz?: [amplitude, hz, phase] }` | idle sway, scaled by the state's energy |
85
+ | `jiggle` | `{ axis, length, freq, damping, maxAngle? }` | spring follow-through; `axis` is the bone's direction at rest |
86
+
87
+ Rotation directions, seen from the front: `rz > 0` tips the top toward the
88
+ viewer's left (−x); `rx > 0` tips the top toward the camera; `ry > 0` turns
89
+ the front toward the viewer's right (+x). Rotations apply X, then Y, then Z.
90
+
91
+ ## parts
92
+
93
+ Common fields:
94
+
95
+ | field | type | notes |
96
+ | --- | --- | --- |
97
+ | `bone` | bone name | the part moves with it; `at` is in its space |
98
+ | `material` | material name | |
99
+ | `shape` | see below | |
100
+ | `at` | Vec3 | centre (default `[0, 0, 0]`) |
101
+ | `rot` | Vec3 | rotation about the part's centre, radians |
102
+ | `op` | `'add'` or `'sub'` | default `add`; `sub` carves from parts listed before |
103
+ | `blend` | number | 0 hard, 0.02 to 0.08 seam, 0.1 to 0.25 smooth blob |
104
+ | `clip` | `{ normal: Vec3, offset? }` | keeps the side the normal points away from, in the part's space |
105
+
106
+ Shapes:
107
+
108
+ | shape | fields |
109
+ | --- | --- |
110
+ | `sphere` | `radius` |
111
+ | `ellipsoid` | `radii: [x, y, z]` |
112
+ | `roundBox` | `half: [x, y, z]`, `round` (≤ smallest half) |
113
+ | `capsule` | `from: Vec3`, `to: Vec3`, `radius` |
114
+ | `roundCone` | `from`, `to`, `r1` (at from), `r2` (at to) |
115
+ | `cylinder` | `radius`, `half` (half height, along y), `round` |
116
+ | `plate` | `half: [x, y]`, `corner`, `depth` (half thickness along z) |
117
+ | `frame` | `half: [x, y]`, `corner`, `width` (half the ring's thickness), `depth` |
118
+ | `hem` | `y`, `amplitude`, `waves`, `speed`, `blend`: cuts everything before it below a wavy line at height `y` |
119
+
120
+ ## paints
121
+
122
+ | field | type | notes |
123
+ | --- | --- | --- |
124
+ | `bone` | bone name | `at` is in its space |
125
+ | `on` | material names | only these materials are coloured |
126
+ | `kind` | `'sphere'` or `'ellipse'` | |
127
+ | `at` | Vec3 | sphere: a point on the surface. ellipse: centre, with z a little behind the surface |
128
+ | `radius` | number | sphere only |
129
+ | `radii` | `[x, y]` | ellipse only, as seen from the front |
130
+ | `color` | colour | |
131
+ | `soft` | 0.15 | edge softness as a share of the size; 0.02 crisp, 0.6 a soft blush |
132
+ | `opacity` | 1 | |
133
+
134
+ Later paints cover earlier ones.
135
+
136
+ ## eyes
137
+
138
+ Ball:
139
+
140
+ | field | notes |
141
+ | --- | --- |
142
+ | `kind: 'ball'` | |
143
+ | `bone` | usually `head` |
144
+ | `at: [left, right]` | left (negative x) first; mirror images; centre about 0.7 × radius behind the surface |
145
+ | `radius` | 0.045 to 0.07 |
146
+ | `iris` | colour; dark brown or black reads best |
147
+ | `irisSize` | 0.75 to 0.9 (sine of the iris's half angle) |
148
+ | `pupilSize` | 0.45 to 0.6 |
149
+ | `pupilAspect` | optional; above 1 for a goat's or octopus's wide pupil |
150
+ | `lid` | material name for the eyelids, usually the face's material |
151
+
152
+ Bead:
153
+
154
+ | field | notes |
155
+ | --- | --- |
156
+ | `kind: 'bead'` | |
157
+ | `bone` | |
158
+ | `at: [left, right]` | centre about 0.3 × radii[2] behind the surface |
159
+ | `radii` | `[x, y, z]`, about `[0.04, 0.06, 0.025]` |
160
+ | `material` | a dark glossy material |
161
+
162
+ ## face
163
+
164
+ Mouth:
165
+
166
+ | field | notes |
167
+ | --- | --- |
168
+ | `kind: 'mouth'` | |
169
+ | `bone` | usually `head` |
170
+ | `on` | materials it may be drawn on |
171
+ | `at` | on the surface: z equal to the surface's z, at most 0.02 in front |
172
+ | `width` | 0.03 to 0.07 |
173
+ | `color` | dark: the lips and the inside |
174
+ | `tongue` | pink or red |
175
+
176
+ Screen (an LED matrix face for robots; the eyes and mouth are drawn on it,
177
+ so leave out `eyes`):
178
+
179
+ | field | notes |
180
+ | --- | --- |
181
+ | `kind: 'screen'` | |
182
+ | `bone`, `material` | the bone and material of the screen part (usually a `plate`) |
183
+ | `center: [x, y]` | middle of the screen in the bone's space |
184
+ | `half: [x, y]`, `corner` | its size, matching the plate |
185
+ | `cell` | LED pitch, about 0.025 to 0.04 |
186
+ | `color` | LED colour |
187
+
188
+ See `volt`.
189
+
190
+ ## anchors
191
+
192
+ `{ bone, at }`. The engine's effects use `top` (thinking, working,
193
+ celebrating, error, surprised, sad, sleeping, happy), `mouth` (speaking),
194
+ `ear` (listening) and `feet` (landing after a hop). Effects whose anchor is
195
+ missing are skipped. You can add your own names for your own effects.
196
+
197
+ ## acting
198
+
199
+ ```ts
200
+ acting: {
201
+ <state>: { <bone name>: { rx?: Motion, ry?: Motion, rz?: Motion } },
202
+ }
203
+ ```
204
+
205
+ `Motion` is a number (a held angle, added to the bone's rotation) or
206
+ `[base, amplitude?, hz?, phase?, spin?]`: `base + amplitude · sin(2π · hz · t + phase)`
207
+ plus `spin` radians per second, accumulating. States: `idle`, `thinking`,
208
+ `listening`, `speaking`, `working`, `error`, `surprised`, `celebrating`,
209
+ `sad`, `sleeping`, `happy`. The engine blends between states smoothly.
210
+
211
+ What the engine already does in every state, so you do not need to:
212
+
213
+ | state | face | body | effects (anchor) |
214
+ | --- | --- | --- | --- |
215
+ | idle | relaxed, slight smile, blinks | breathes, glances around | |
216
+ | thinking | lids half down, small frown, head tilt | slower | dots (top) |
217
+ | listening | eyes open, slight smile | leans in | sound arcs (ear) |
218
+ | speaking | smile, mouth talks | bounces per syllable, `talk` channel | sound arcs (mouth) |
219
+ | working | eyes narrowed | busy, arms a little up | gears (top) |
220
+ | error | wince, one eye shut, crooked mouth | shakes | warning sign, smoke (top) |
221
+ | surprised | eyes wide, round mouth | jumps, arms up | exclamation mark (top) |
222
+ | celebrating | eyes squeezed happy, big smile | hops and spins, arms up | confetti, stars (top) |
223
+ | sad | heavy sloping lids, frown | slumps | rain cloud (top) |
224
+ | sleeping | eyes closed, lights dim | slow breathing | z's (top) |
225
+ | happy (on click) | squeezed smile | bounce | sparkles, hearts (top) |
226
+
227
+ ## fx
228
+
229
+ ```ts
230
+ fx: {
231
+ replace?: Trigger[], // triggers whose default effects you replace instead of adding to
232
+ <trigger>: Emitter[],
233
+ }
234
+ ```
235
+
236
+ Triggers: a state name (while in it), `enter:<state>` (once, on entering),
237
+ `ambient` (always), `land` (after each hop), `syllable` (each syllable while
238
+ speaking).
239
+
240
+ Emitter fields:
241
+
242
+ | field | notes |
243
+ | --- | --- |
244
+ | `glyph` | `z bubble sparkle heart note arc puff ring drop spark mote feather dot exclaim warning confetti cloud star gear` |
245
+ | `anchor` | anchor name |
246
+ | `rate` | per second while active, or how many at once for `enter:`/`land`/`syllable` |
247
+ | `offset`, `spread` | start position relative to the anchor, and random spread |
248
+ | `velocity`, `jitter` | units per second, and random variation |
249
+ | `mirror` | mirror half the particles across x |
250
+ | `gravity`, `drag`, `wobble` | motion |
251
+ | `life` | `[min, max]` seconds |
252
+ | `size` | `[at birth, at death]` |
253
+ | `rotation`, `spin` | starting angle, and radians per second |
254
+ | `align` | point along the direction of travel |
255
+ | `color` | colour |
256
+ | `glow` | adds light instead of covering |
257
+
258
+ At most 32 particles are alive at once, shared by all emitters.
@@ -0,0 +1,73 @@
1
+ import type { CharacterSpec } from 'wobnimo';
2
+
3
+ /*
4
+ __NAME__: a starter mascot that passes every check. Reshape it into yours.
5
+
6
+ Units: the floor is y = 0, +y is up, +x is to the right as you look at
7
+ the character, +z points at the camera. One unit is about the height of
8
+ a small mascot. Angles are radians.
9
+ */
10
+ export const __CONST__: CharacterSpec = {
11
+ id: '__ID__',
12
+ name: '__NAME__',
13
+ tagline: 'A round little friend with a springy tuft',
14
+ accent: '#ff9f43',
15
+ /* the camera looks at height `target` and fits a circle of `radius` */
16
+ frame: { target: 0.42, radius: 0.62 },
17
+ /* every part, in every state, must stay inside this sphere above the floor */
18
+ bound: { y: 0.4, radius: 0.6 },
19
+ motion: { hop: 0.16, squash: 1.2, snap: 1, talkSquash: 0.8 },
20
+
21
+ materials: {
22
+ skin: { color: '#ffb35c', f0: 0.04, spec: 0.8, shininess: 60, rim: 0.8, sss: 0.2, sssColor: '#ffd9a8' },
23
+ foot: { color: '#e8893a', shadeOf: 'skin', f0: 0.04, spec: 0.6, shininess: 40, rim: 0.6 },
24
+ tuft: { color: '#ff7a59', f0: 0.04, spec: 0.7, shininess: 50, rim: 0.8 },
25
+ },
26
+
27
+ /* body is the whole character; head nods and turns on top of it; tuft springs */
28
+ bones: [
29
+ { name: 'body', pivot: [0, 0, 0], drive: { ry: [['yaw', 0.3]], rz: [['roll', 0.4]] } },
30
+ { name: 'head', parent: 'body', pivot: [0, 0.3, 0], drive: { rx: [['pitch', -0.6]], ry: [['yaw', 0.6]], rz: [['roll', 0.5]] } },
31
+ { name: 'tuft', parent: 'head', pivot: [0, 0.45, 0], jiggle: { axis: [0, 1, 0], length: 0.12, freq: 2.4, damping: 0.12 } },
32
+ ],
33
+
34
+ /* each part is placed in its bone's space; `blend` melts it into the parts before it */
35
+ parts: [
36
+ { bone: 'body', shape: 'ellipsoid', at: [0, 0.19, 0], radii: [0.25, 0.19, 0.23], material: 'skin' },
37
+ { bone: 'head', shape: 'ellipsoid', at: [0, 0.2, 0], radii: [0.31, 0.27, 0.28], blend: 0.06, material: 'skin' },
38
+ { bone: 'body', shape: 'ellipsoid', at: [-0.15, 0.04, 0.08], radii: [0.1, 0.05, 0.12], blend: 0.04, material: 'foot' },
39
+ { bone: 'body', shape: 'ellipsoid', at: [0.15, 0.04, 0.08], radii: [0.1, 0.05, 0.12], blend: 0.04, material: 'foot' },
40
+ { bone: 'tuft', shape: 'roundCone', from: [0, -0.04, 0], to: [0.02, 0.1, 0], r1: 0.035, r2: 0.012, material: 'tuft' },
41
+ { bone: 'tuft', shape: 'roundCone', from: [0, -0.04, 0], to: [-0.06, 0.07, 0.01], r1: 0.03, r2: 0.01, blend: 0.01, material: 'tuft' },
42
+ ],
43
+
44
+ /* cheeks: soft colour painted where the surface passes near `at` */
45
+ paints: [
46
+ { bone: 'head', on: ['skin'], kind: 'sphere', at: [-0.2, 0.11, 0.22], radius: 0.05, color: '#ff8f8f', soft: 0.6, opacity: 0.8 },
47
+ { bone: 'head', on: ['skin'], kind: 'sphere', at: [0.2, 0.11, 0.22], radius: 0.05, color: '#ff8f8f', soft: 0.6, opacity: 0.8 },
48
+ ],
49
+
50
+ /* the eye on your left (negative x) first; about 70% of each eyeball sits inside the head */
51
+ eyes: { kind: 'ball', bone: 'head', at: [[-0.11, 0.2, 0.22], [0.11, 0.2, 0.22]], radius: 0.06, iris: '#2b1d14', irisSize: 0.85, pupilSize: 0.55, lid: 'skin' },
52
+ face: { kind: 'mouth', bone: 'head', on: ['skin'], at: [0, 0.09, 0.26], width: 0.05, color: '#5a2a1a', tongue: '#ff7d8a' },
53
+
54
+ /* where effects come from: thinking dots (top), speech (mouth), sound (ear), landing dust (feet) */
55
+ anchors: {
56
+ top: { bone: 'head', at: [0.14, 0.44, 0.05] },
57
+ mouth: { bone: 'head', at: [0, 0.04, 0.3] },
58
+ ear: { bone: 'head', at: [-0.27, 0.14, 0] },
59
+ feet: { bone: 'root', at: [0, 0.02, 0.15] },
60
+ },
61
+
62
+ /* how each state moves the bones, on top of the shared rig (radians; [base, amp, hz, phase, spin]) */
63
+ acting: {
64
+ thinking: { head: { rz: 0.12 }, tuft: { rz: [0, 0.15, 1.2, 0] } },
65
+ listening: { head: { rz: -0.1 }, tuft: { rx: -0.3 } },
66
+ sleeping: { tuft: { rx: 0.9 } },
67
+ error: { tuft: { rz: [0, 0.3, 10, 0] } },
68
+ celebrating: { tuft: { ry: [0, 0, 0, 0, 12] } },
69
+ sad: { tuft: { rx: 1.1, rz: 0.4 } },
70
+ },
71
+ };
72
+
73
+ export default __CONST__;
@@ -1,8 +0,0 @@
1
- import { C as CharacterSpec } from './types-PAZ6PnKv.js';
2
-
3
- /** Ten body plans, chosen so each one stresses the engine somewhere new. */
4
- declare const characters: CharacterSpec[];
5
- /** Registers <wobnimo-mascot> with the whole cast: `<wobnimo-mascot character="pip">`. */
6
- declare function defineWobnimoElement(tag?: string): void;
7
-
8
- export { characters as c, defineWobnimoElement as d };