robot-heads-solid 0.1.0 → 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.
- package/README.md +101 -78
- package/dist/solid2.d.ts +40 -0
- package/dist/solid2.js +1423 -0
- package/dist/solid2.server.js +532 -0
- package/dist/types/RobotHead.d.ts +4 -0
- package/dist/types/color.d.ts +2 -0
- package/dist/types/domain-types.d.ts +8 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/ticker.d.ts +8 -0
- package/dist/types/tv/faces.d.ts +28 -0
- package/dist/types/tv/geometry.d.ts +62 -0
- package/dist/types/tv/light.d.ts +16 -0
- package/dist/types/tv/render.d.ts +44 -0
- package/dist/types/tv/sim.d.ts +59 -0
- package/dist/types/types.d.ts +22 -0
- package/package.json +46 -19
- package/dist/index.d.ts +0 -39
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
import { ssrElement as e } from "@solidjs/web";
|
|
2
|
+
import { createSignal as t, createTrackedEffect as n, createUniqueId as r, omit as i, onSettled as a } from "solid-js";
|
|
3
|
+
var o = [
|
|
4
|
+
"idle",
|
|
5
|
+
"thinking",
|
|
6
|
+
"searching",
|
|
7
|
+
"listening",
|
|
8
|
+
"speaking",
|
|
9
|
+
"working",
|
|
10
|
+
"happy",
|
|
11
|
+
"error",
|
|
12
|
+
"sleeping"
|
|
13
|
+
], s = [
|
|
14
|
+
"rectangle",
|
|
15
|
+
"square",
|
|
16
|
+
"circle",
|
|
17
|
+
"hexagon"
|
|
18
|
+
], c = {
|
|
19
|
+
bevel: .075,
|
|
20
|
+
margin: .045,
|
|
21
|
+
gasket: .022,
|
|
22
|
+
recess: .03,
|
|
23
|
+
earY: .03,
|
|
24
|
+
stem: .2,
|
|
25
|
+
ball: .052
|
|
26
|
+
}, l = {
|
|
27
|
+
plate: c.bevel,
|
|
28
|
+
hole: c.bevel + c.margin,
|
|
29
|
+
glass: c.bevel + c.margin + c.gasket
|
|
30
|
+
}, u = Math.PI * 2;
|
|
31
|
+
function d(e, t, n, r, i, a) {
|
|
32
|
+
let o = t.map(([e, t]) => ({
|
|
33
|
+
x: e,
|
|
34
|
+
y: t,
|
|
35
|
+
t: Math.atan2(t, e)
|
|
36
|
+
})).sort((e, t) => e.t - t.t), s = o.length, d = [];
|
|
37
|
+
for (let e = 0; e < s; e++) {
|
|
38
|
+
let t = o[e], n = o[(e + 1) % s];
|
|
39
|
+
d.push(Math.atan2(-(n.x - t.x), n.y - t.y));
|
|
40
|
+
}
|
|
41
|
+
let f = o.map((e, t) => {
|
|
42
|
+
if (s === 1) return {
|
|
43
|
+
x: e.x,
|
|
44
|
+
y: e.y,
|
|
45
|
+
a0: -Math.PI,
|
|
46
|
+
a1: Math.PI
|
|
47
|
+
};
|
|
48
|
+
let n = d[(t - 1 + s) % s], r = d[t];
|
|
49
|
+
for (; r < n;) r += u;
|
|
50
|
+
return {
|
|
51
|
+
x: e.x,
|
|
52
|
+
y: e.y,
|
|
53
|
+
a0: n,
|
|
54
|
+
a1: r
|
|
55
|
+
};
|
|
56
|
+
}), m = (e, t) => {
|
|
57
|
+
if (s === 1) return Math.hypot(e - o[0].x, t - o[0].y);
|
|
58
|
+
let n = Infinity, r = !0;
|
|
59
|
+
for (let i = 0; i < s; i++) {
|
|
60
|
+
let a = o[i], c = o[(i + 1) % s], l = c.x - a.x, u = c.y - a.y, d = e - a.x, f = t - a.y, p = Math.max(0, Math.min(1, (d * l + f * u) / (l * l + u * u)));
|
|
61
|
+
n = Math.min(n, Math.hypot(d - l * p, f - u * p)), l * f - u * d < 0 && (r = !1);
|
|
62
|
+
}
|
|
63
|
+
return r ? -n : n;
|
|
64
|
+
}, h = (e, t, r) => m(e, t) - (n - r), g = (e, t) => {
|
|
65
|
+
let r = Math.max(5e-4, n - t);
|
|
66
|
+
f.forEach((t, n) => {
|
|
67
|
+
n === 0 && e.moveTo(t.x + r * Math.cos(t.a0), t.y + r * Math.sin(t.a0)), e.arc(t.x, t.y, r, t.a0, t.a1);
|
|
68
|
+
}), e.closePath();
|
|
69
|
+
}, _ = 0, v = 0;
|
|
70
|
+
for (let e of o) _ = Math.max(_, Math.abs(e.x) + n), v = Math.max(v, Math.abs(e.y) + n);
|
|
71
|
+
let y = 0, b = _ + .1;
|
|
72
|
+
for (let e = 0; e < 40; e++) {
|
|
73
|
+
let e = (y + b) / 2;
|
|
74
|
+
h(e, c.earY, 0) < 0 ? y = e : b = e;
|
|
75
|
+
}
|
|
76
|
+
let x = (e, t) => e.map((e, r) => {
|
|
77
|
+
let i = e * Math.PI / 180, a = f.find((e) => [
|
|
78
|
+
i,
|
|
79
|
+
i + u,
|
|
80
|
+
i - u
|
|
81
|
+
].some((t) => t >= e.a0 - 1e-6 && t <= e.a1 + 1e-6)) ?? f[0];
|
|
82
|
+
return [
|
|
83
|
+
a.x + Math.cos(i) * (n - t),
|
|
84
|
+
a.y + Math.sin(i) * (n - t),
|
|
85
|
+
.5 + r * .9
|
|
86
|
+
];
|
|
87
|
+
}), S = 2 * (_ - l.glass), C = 2 * (v - l.glass), w = Math.min(p * S / 14, .65 * C / 10);
|
|
88
|
+
return {
|
|
89
|
+
name: e,
|
|
90
|
+
r: n,
|
|
91
|
+
depth: r,
|
|
92
|
+
corners: f,
|
|
93
|
+
hx: _,
|
|
94
|
+
hy: v,
|
|
95
|
+
pitch: w,
|
|
96
|
+
earX: y - .008,
|
|
97
|
+
screws: x(i, (l.hole - .018 + l.plate) / 2),
|
|
98
|
+
backScrews: x(a, l.plate + .07),
|
|
99
|
+
sd: h,
|
|
100
|
+
path: g
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
var f = (e) => [
|
|
104
|
+
0,
|
|
105
|
+
60,
|
|
106
|
+
120,
|
|
107
|
+
180,
|
|
108
|
+
240,
|
|
109
|
+
300
|
|
110
|
+
].map((t) => [e * Math.cos(t * Math.PI / 180), e * Math.sin(t * Math.PI / 180)]), p = .6, m = [45, 135], h = [
|
|
111
|
+
-135,
|
|
112
|
+
-45,
|
|
113
|
+
45,
|
|
114
|
+
135
|
|
115
|
+
], g = {
|
|
116
|
+
rectangle: () => d("rectangle", [
|
|
117
|
+
[-.29, -.17],
|
|
118
|
+
[.29, -.17],
|
|
119
|
+
[.29, .17],
|
|
120
|
+
[-.29, .17]
|
|
121
|
+
], .21, .6, m, h),
|
|
122
|
+
square: () => d("square", [
|
|
123
|
+
[-.22, -.22],
|
|
124
|
+
[.22, -.22],
|
|
125
|
+
[.22, .22],
|
|
126
|
+
[-.22, .22]
|
|
127
|
+
], .2, .6, m, h),
|
|
128
|
+
circle: () => d("circle", [[0, 0]], .46, .56, m, h),
|
|
129
|
+
hexagon: () => d("hexagon", f(.35), .16, .58, [60, 120], [
|
|
130
|
+
-120,
|
|
131
|
+
-60,
|
|
132
|
+
60,
|
|
133
|
+
120
|
|
134
|
+
])
|
|
135
|
+
}, _ = /* @__PURE__ */ new Map();
|
|
136
|
+
function v(e) {
|
|
137
|
+
let t = _.get(e);
|
|
138
|
+
return t || (t = (g[e] ?? g.rectangle)(), _.set(e, t)), t;
|
|
139
|
+
}
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region ../src/tv/sim.ts
|
|
142
|
+
var y = class {
|
|
143
|
+
x = 0;
|
|
144
|
+
v = 0;
|
|
145
|
+
constructor(e = 0) {
|
|
146
|
+
this.x = e;
|
|
147
|
+
}
|
|
148
|
+
step(e, t, n, r) {
|
|
149
|
+
let i = n * Math.PI * 2;
|
|
150
|
+
this.v += (i * i * (e - this.x) - 2 * r * i * this.v) * t, this.x += this.v * t;
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
function b(e) {
|
|
154
|
+
let t = Math.floor(e * 4294967295) >>> 0 || 1;
|
|
155
|
+
return () => {
|
|
156
|
+
t = t + 1831565813 >>> 0;
|
|
157
|
+
let e = t;
|
|
158
|
+
return e = Math.imul(e ^ e >>> 15, e | 1), e ^= e + Math.imul(e ^ e >>> 7, e | 61), ((e ^ e >>> 14) >>> 0) / 4294967296;
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
var x = (e, t, n) => Math.min(n, Math.max(t, e)), S = (e) => e < .5 ? 4 * e * e * e : 1 - (-2 * e + 2) ** 3 / 2, C = .11, w = class {
|
|
162
|
+
state;
|
|
163
|
+
shown;
|
|
164
|
+
previous;
|
|
165
|
+
switched = 10;
|
|
166
|
+
age = 0;
|
|
167
|
+
time = 0;
|
|
168
|
+
since = 0;
|
|
169
|
+
pose = {
|
|
170
|
+
yaw: 0,
|
|
171
|
+
pitch: 0,
|
|
172
|
+
roll: 0,
|
|
173
|
+
x: 0,
|
|
174
|
+
lift: 0,
|
|
175
|
+
sx: 1,
|
|
176
|
+
sy: 1,
|
|
177
|
+
antennaX: 0,
|
|
178
|
+
antennaZ: 0
|
|
179
|
+
};
|
|
180
|
+
face;
|
|
181
|
+
pointer = null;
|
|
182
|
+
yaw = new y();
|
|
183
|
+
pitch = new y();
|
|
184
|
+
roll = new y();
|
|
185
|
+
sway = new y();
|
|
186
|
+
squash = new y();
|
|
187
|
+
antX = new y();
|
|
188
|
+
antZ = new y();
|
|
189
|
+
lastV = {
|
|
190
|
+
roll: 0,
|
|
191
|
+
pitch: 0,
|
|
192
|
+
sway: 0
|
|
193
|
+
};
|
|
194
|
+
jump = null;
|
|
195
|
+
random;
|
|
196
|
+
lookAt = {
|
|
197
|
+
yaw: 0,
|
|
198
|
+
pitch: 0,
|
|
199
|
+
x: 0,
|
|
200
|
+
y: 0
|
|
201
|
+
};
|
|
202
|
+
nextLook = .6;
|
|
203
|
+
nextBlink = 1.5;
|
|
204
|
+
blinkAge = -1;
|
|
205
|
+
nextHop = 8;
|
|
206
|
+
nextSide = 4;
|
|
207
|
+
reactUntil = -1;
|
|
208
|
+
nextNod = 2.5;
|
|
209
|
+
constructor(e, t) {
|
|
210
|
+
this.random = b(e), this.state = this.shown = this.previous = t, this.face = {
|
|
211
|
+
lookX: 0,
|
|
212
|
+
lookY: 0,
|
|
213
|
+
blink: 0,
|
|
214
|
+
time: 0,
|
|
215
|
+
side: 1,
|
|
216
|
+
seed: e
|
|
217
|
+
}, this.nextBlink = 1 + this.random() * 3, this.nextHop = 6 + this.random() * 6;
|
|
218
|
+
}
|
|
219
|
+
setState(e) {
|
|
220
|
+
e !== this.state && (this.state = e, this.since = 0, this.nextLook = 0, this.nextHop = this.time + (e === "happy" ? .2 : 3 + this.random() * 4), e === "happy" && this.hop(.22, 1));
|
|
221
|
+
}
|
|
222
|
+
poke() {
|
|
223
|
+
this.hop(.24, this.random() < .5 ? 1 : -1), this.reactUntil = this.time + 1.6;
|
|
224
|
+
}
|
|
225
|
+
hop(e, t) {
|
|
226
|
+
this.jump ||= {
|
|
227
|
+
age: 0,
|
|
228
|
+
height: e,
|
|
229
|
+
spin: t,
|
|
230
|
+
lean: (this.random() - .5) * .3,
|
|
231
|
+
air: .42 + e * .45,
|
|
232
|
+
landed: !1
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
update(e) {
|
|
236
|
+
if (!Number.isFinite(e) || !(e > 0)) return;
|
|
237
|
+
let t = Math.min(e, .8), n = Math.max(1, Math.ceil(t / (1 / 120)));
|
|
238
|
+
for (let e = 0; e < n; e++) this.step(t / n);
|
|
239
|
+
}
|
|
240
|
+
stepJump(e) {
|
|
241
|
+
let t = 0, n = 0, r = 0, i = 0, a = this.jump, o = this.random;
|
|
242
|
+
if (a) {
|
|
243
|
+
if (a.age += e, a.age < C) i = .14;
|
|
244
|
+
else {
|
|
245
|
+
let e = (a.age - C) / a.air;
|
|
246
|
+
e < 1 ? (e < .06 && this.squash.x > .05 && (this.squash.v = -2.6, this.antZ.v -= 3), t = 4 * a.height * e * (1 - e), n = a.spin * Math.PI * 2 * S(x(e * 1.08, 0, 1)), r = a.lean * Math.sin(e * Math.PI), i = e < .5 ? -.05 : 0) : a.landed ? a.age - C - a.air > .35 && (this.jump = null) : (a.landed = !0, this.squash.v += 3.2, this.antX.v += (o() < .5 ? -1 : 1) * (2.5 + o() * 2), this.antZ.v += 3.5);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return this.squash.step(i, e, 3.2, .32), {
|
|
250
|
+
lift: t,
|
|
251
|
+
spin: n,
|
|
252
|
+
lean: r
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
hopWithChance(e, t) {
|
|
256
|
+
this.hop(e, this.random() < t ? this.random() < .5 ? 1 : -1 : 0);
|
|
257
|
+
}
|
|
258
|
+
updateLookAt(e) {
|
|
259
|
+
if (e > this.nextLook) {
|
|
260
|
+
let t = this.random;
|
|
261
|
+
this.lookAt = {
|
|
262
|
+
yaw: (t() - .5) * .75,
|
|
263
|
+
pitch: (t() - .5) * .24,
|
|
264
|
+
x: 0,
|
|
265
|
+
y: 0
|
|
266
|
+
}, this.lookAt.x = x(Math.round(this.lookAt.yaw * 5), -2, 2), this.lookAt.y = t() < .3 ? -1 : +(t() < .2), this.nextLook = e + 1.4 + t() * 2.6;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
stateTargets(e) {
|
|
270
|
+
let t = this.random, n = 0, r = 0, i = 0, a = Math.sin(e * 1.9) * .008, o = 0, s = 0, c = 1.3, l = .62, u = 0;
|
|
271
|
+
switch (this.state) {
|
|
272
|
+
case "idle":
|
|
273
|
+
n = this.lookAt.yaw, r = this.lookAt.pitch, i = -this.lookAt.yaw * .16, o = this.lookAt.x, s = this.lookAt.y, e > this.nextHop && (this.hopWithChance(.15 + t() * .07, .35), this.nextHop = e + 7 + t() * 7);
|
|
274
|
+
break;
|
|
275
|
+
case "thinking": {
|
|
276
|
+
e > this.nextSide && (this.face.side = -this.face.side, this.nextSide = e + 3 + t() * 2);
|
|
277
|
+
let a = this.face.side;
|
|
278
|
+
n = .24 * a + Math.sin(e * .9) * .05, r = .17 + Math.sin(e * 1.3) * .03, i = -.13 * a, c = .9;
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
case "searching": {
|
|
282
|
+
let t = e * 1.6;
|
|
283
|
+
n = Math.sin(t) * .55, r = -.04 + Math.sin(t * 2) * .04, i = Math.sin(t) * -.06, o = x(Math.sin(t + .4) * 3, -3, 3), c = 2.2, l = .8;
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
case "listening":
|
|
287
|
+
n = -.14, r = .02, i = .17, e > this.nextNod && (this.pitch.v -= .9, this.nextNod = e + 2 + t() * 2.5);
|
|
288
|
+
break;
|
|
289
|
+
case "speaking":
|
|
290
|
+
n = Math.sin(e * .7) * .12, r = .03 + Math.sin(e * 6.3) * .025 * (.5 + .5 * Math.sin(e * 2.1)), i = Math.sin(e * .9) * .05, a += Math.abs(Math.sin(e * 6.3)) * .01, c = 1.8;
|
|
291
|
+
break;
|
|
292
|
+
case "working":
|
|
293
|
+
n = Math.sin(e * .8) * .08, r = -.16, i = Math.sin(e * .5) * .04, a += Math.abs(Math.sin(e * 7)) * .012, e > this.nextHop && (this.hop(.2, t() < .5 ? 1 : -1), this.nextHop = e + 5 + t() * 3);
|
|
294
|
+
break;
|
|
295
|
+
case "happy":
|
|
296
|
+
n = Math.sin(e * 2.2) * .18, i = Math.sin(e * 4.4) * .12, r = .08, e > this.nextHop && (this.hopWithChance(.17, .34), this.nextHop = e + 1.05 + t() * .4);
|
|
297
|
+
break;
|
|
298
|
+
case "error": {
|
|
299
|
+
let t = e % 2.4 / .7;
|
|
300
|
+
u = t < 1 ? Math.sin(t * Math.PI * 7) * .22 * (1 - t) : 0, r = -.06, i = -.05, c = 1.6;
|
|
301
|
+
break;
|
|
302
|
+
}
|
|
303
|
+
case "sleeping":
|
|
304
|
+
r = -.34, i = .13, n = .06, a = Math.sin(e * 1.15) * .016, c = .55, l = .9, e > this.nextNod && (this.pitch.v -= .5, this.nextNod = e + 5 + t() * 4);
|
|
305
|
+
break;
|
|
306
|
+
default: this.state;
|
|
307
|
+
}
|
|
308
|
+
return {
|
|
309
|
+
yaw: n,
|
|
310
|
+
pitch: r,
|
|
311
|
+
roll: i,
|
|
312
|
+
bob: a,
|
|
313
|
+
lookX: o,
|
|
314
|
+
lookY: s,
|
|
315
|
+
freq: c,
|
|
316
|
+
damping: l,
|
|
317
|
+
shake: u
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
step(e) {
|
|
321
|
+
this.time += e, this.since += e, this.age += e, this.switched += e;
|
|
322
|
+
let t = this.time, n = this.random, r = t < this.reactUntil ? "happy" : this.state;
|
|
323
|
+
r !== this.shown && (this.previous = this.shown, this.shown = r, this.switched = 0), this.updateLookAt(t);
|
|
324
|
+
let { yaw: i, pitch: a, roll: o, bob: s, lookX: c, lookY: l, freq: u, damping: d, shake: f } = this.stateTargets(t), p = this.pointer;
|
|
325
|
+
p && (this.state === "idle" || this.state === "listening" || this.state === "happy" || this.state === "speaking") && p && (i = x(p.x / 260, -1, 1) * .55, a = -x(p.y / 260, -1, 1) * .32, o = -i * .12 + (this.state === "listening" ? .12 : 0), c = x(p.x / 120, -2.4, 2.4), l = x(p.y / 160, -1.4, 1.4)), this.yaw.step(i, e, u, d), this.pitch.step(a, e, u, d), this.roll.step(o, e, u, d), this.sway.step(0, e, 1.2, .7);
|
|
326
|
+
let { lift: m, spin: h, lean: g } = this.stepJump(e);
|
|
327
|
+
t > this.nextBlink && (this.blinkAge = 0, this.nextBlink = t + 2.2 + n() * 3.5, n() < .2 && (this.nextBlink = t + .35));
|
|
328
|
+
let _ = 0;
|
|
329
|
+
this.blinkAge >= 0 && (this.blinkAge += e, _ = Math.sin(x(this.blinkAge / .17, 0, 1) * Math.PI), this.blinkAge > .17 && (this.blinkAge = -1));
|
|
330
|
+
let v = (this.roll.v - this.lastV.roll) / e, y = (this.pitch.v - this.lastV.pitch) / e, b = (this.sway.v - this.lastV.sway) / e;
|
|
331
|
+
this.lastV = {
|
|
332
|
+
roll: this.roll.v,
|
|
333
|
+
pitch: this.pitch.v,
|
|
334
|
+
sway: this.sway.v
|
|
335
|
+
};
|
|
336
|
+
let S = 2.3;
|
|
337
|
+
this.antX.v -= (v * .05 + b * .3) * e * 6, this.antZ.v -= y * .05 * e * 6, this.antX.step(0, e, S, .09), this.antZ.step(0, e, S, .09), this.antX.x = x(this.antX.x, -.7, .7), this.antZ.x = x(this.antZ.x, -.7, .7);
|
|
338
|
+
let C = this.squash.x;
|
|
339
|
+
this.pose = {
|
|
340
|
+
yaw: this.yaw.x + h + f,
|
|
341
|
+
pitch: this.pitch.x,
|
|
342
|
+
roll: this.roll.x + g,
|
|
343
|
+
x: this.sway.x,
|
|
344
|
+
lift: m + s,
|
|
345
|
+
sx: 1 + C * .55,
|
|
346
|
+
sy: 1 - C,
|
|
347
|
+
antennaX: this.antX.x,
|
|
348
|
+
antennaZ: this.antZ.x
|
|
349
|
+
}, this.face.lookX = c, this.face.lookY = l, this.face.blink = this.state === "sleeping" ? 0 : _, this.face.time = this.since;
|
|
350
|
+
}
|
|
351
|
+
}, T = (e, t, n) => {
|
|
352
|
+
let r = Math.hypot(e, t, n);
|
|
353
|
+
return [
|
|
354
|
+
e / r,
|
|
355
|
+
t / r,
|
|
356
|
+
n / r
|
|
357
|
+
];
|
|
358
|
+
}, E = T(-.5, -.78, .62);
|
|
359
|
+
T(.85, .15, .5), T(.55, -.55, -.62), T(E[0], E[1], E[2] + 1);
|
|
360
|
+
var D = (e) => (e / 255) ** 2.2;
|
|
361
|
+
function O(e) {
|
|
362
|
+
return [
|
|
363
|
+
D(e[0]),
|
|
364
|
+
D(e[1]),
|
|
365
|
+
D(e[2])
|
|
366
|
+
];
|
|
367
|
+
}
|
|
368
|
+
//#endregion
|
|
369
|
+
//#region ../src/color.ts
|
|
370
|
+
function k(e) {
|
|
371
|
+
let t = e.trim(), n = t.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);
|
|
372
|
+
if (n) {
|
|
373
|
+
let e = n[1].length === 3 ? n[1].replace(/./g, (e) => e + e) : n[1], t = parseInt(e, 16);
|
|
374
|
+
return [
|
|
375
|
+
t >> 16 & 255,
|
|
376
|
+
t >> 8 & 255,
|
|
377
|
+
t & 255
|
|
378
|
+
];
|
|
379
|
+
}
|
|
380
|
+
let r = t.match(/^rgba?\(\s*([\d.]+)[,\s]+([\d.]+)[,\s]+([\d.]+)/i);
|
|
381
|
+
return r ? [
|
|
382
|
+
Number(r[1]),
|
|
383
|
+
Number(r[2]),
|
|
384
|
+
Number(r[3])
|
|
385
|
+
] : null;
|
|
386
|
+
}
|
|
387
|
+
//#endregion
|
|
388
|
+
//#region ../src/ticker.ts
|
|
389
|
+
var A = {
|
|
390
|
+
x: NaN,
|
|
391
|
+
y: NaN
|
|
392
|
+
}, j = /* @__PURE__ */ new Set(), M = 0, N = 0, P = !1;
|
|
393
|
+
function F() {
|
|
394
|
+
A.x = NaN, A.y = NaN;
|
|
395
|
+
}
|
|
396
|
+
function I(e) {
|
|
397
|
+
A.x = e.clientX, A.y = e.clientY;
|
|
398
|
+
}
|
|
399
|
+
function L() {
|
|
400
|
+
document.hidden ? B() : j.size && z();
|
|
401
|
+
}
|
|
402
|
+
function R(e) {
|
|
403
|
+
M = 0;
|
|
404
|
+
let t = N ? Math.min(.1, (e - N) / 1e3) : 0;
|
|
405
|
+
N = e, j.forEach((e) => e(t)), j.size && (M = requestAnimationFrame(R));
|
|
406
|
+
}
|
|
407
|
+
function z() {
|
|
408
|
+
M || typeof document > "u" || document.hidden || (N = 0, M = requestAnimationFrame(R));
|
|
409
|
+
}
|
|
410
|
+
function B() {
|
|
411
|
+
M && cancelAnimationFrame(M), M = 0;
|
|
412
|
+
}
|
|
413
|
+
function V() {
|
|
414
|
+
P || typeof document > "u" || (P = !0, document.addEventListener("pointermove", I, { passive: !0 }), document.addEventListener("pointerleave", F), window.addEventListener("blur", F), document.addEventListener("visibilitychange", L));
|
|
415
|
+
}
|
|
416
|
+
function H() {
|
|
417
|
+
P && (P = !1, F(), document.removeEventListener("pointermove", I), document.removeEventListener("pointerleave", F), window.removeEventListener("blur", F), document.removeEventListener("visibilitychange", L));
|
|
418
|
+
}
|
|
419
|
+
function U(e) {
|
|
420
|
+
return V(), j.add(e), z(), () => {
|
|
421
|
+
j.delete(e), j.size || (B(), H());
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
//#endregion
|
|
425
|
+
//#region ../src/solid2/RobotHead.tsx
|
|
426
|
+
var W = Symbol(), G = Symbol(), K = {
|
|
427
|
+
get() {
|
|
428
|
+
let e = this[W];
|
|
429
|
+
return e["aria-label"] ?? `Robot, ${Q(e.state)}`;
|
|
430
|
+
},
|
|
431
|
+
enumerable: !0,
|
|
432
|
+
configurable: !0
|
|
433
|
+
}, q = {
|
|
434
|
+
get() {
|
|
435
|
+
let e = this[W];
|
|
436
|
+
return e.class ?? e.className;
|
|
437
|
+
},
|
|
438
|
+
enumerable: !0,
|
|
439
|
+
configurable: !0
|
|
440
|
+
}, J = {
|
|
441
|
+
get() {
|
|
442
|
+
let e = this[W], t = this[G];
|
|
443
|
+
return ee(e.style) ? `width:${t()}px;height:${t()}px;display:block;cursor:${e.interactive === !1 ? "auto" : "pointer"};${e.style}` : {
|
|
444
|
+
width: `${t()}px`,
|
|
445
|
+
height: `${t()}px`,
|
|
446
|
+
display: "block",
|
|
447
|
+
cursor: e.interactive === !1 ? void 0 : "pointer",
|
|
448
|
+
...e.style
|
|
449
|
+
};
|
|
450
|
+
},
|
|
451
|
+
enumerable: !0,
|
|
452
|
+
configurable: !0
|
|
453
|
+
};
|
|
454
|
+
function Y(e, t, n) {
|
|
455
|
+
this[W] = e, this[G] = t, this.role = n, Object.defineProperty(this, "aria-label", K), Object.defineProperty(this, "class", q), Object.defineProperty(this, "style", J);
|
|
456
|
+
}
|
|
457
|
+
Y.prototype = Object.prototype;
|
|
458
|
+
function X(e) {
|
|
459
|
+
let t = 2166136261;
|
|
460
|
+
for (let n = 0; n < e.length; n++) t = Math.imul(t ^ e.charCodeAt(n), 16777619);
|
|
461
|
+
return (t >>> 0) % 1e3 / 1e3;
|
|
462
|
+
}
|
|
463
|
+
function Z(e, t, n) {
|
|
464
|
+
let r = k(e) ?? [
|
|
465
|
+
48,
|
|
466
|
+
80,
|
|
467
|
+
172
|
|
468
|
+
], i = k(t) ?? [
|
|
469
|
+
150,
|
|
470
|
+
168,
|
|
471
|
+
200
|
|
472
|
+
], a = k(n) ?? [
|
|
473
|
+
232,
|
|
474
|
+
242,
|
|
475
|
+
255
|
|
476
|
+
];
|
|
477
|
+
return {
|
|
478
|
+
shell: {
|
|
479
|
+
albedo: O(r),
|
|
480
|
+
f0: .05,
|
|
481
|
+
metal: .15,
|
|
482
|
+
spec: .55,
|
|
483
|
+
shininess: 70,
|
|
484
|
+
rim: .9
|
|
485
|
+
},
|
|
486
|
+
trim: {
|
|
487
|
+
albedo: O(i),
|
|
488
|
+
f0: .2,
|
|
489
|
+
metal: .65,
|
|
490
|
+
spec: .8,
|
|
491
|
+
shininess: 45,
|
|
492
|
+
rim: .7
|
|
493
|
+
},
|
|
494
|
+
led: a
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
var Q = (e) => e && o.includes(e) ? e : "idle", $ = (e) => e && s.includes(e) ? e : "rectangle";
|
|
498
|
+
function ee(e) {
|
|
499
|
+
return typeof e == "string";
|
|
500
|
+
}
|
|
501
|
+
function te(o) {
|
|
502
|
+
let s = r(), c = o, l = i(o, "model", "shape", "state", "size", "color", "trimColor", "screenColor", "speed", "paused", "interactive", "floorShadow", "seed", "class", "className", "style", "onClick", "aria-label", "ref"), u, d = () => Number.isFinite(c.size) && (c.size ?? 0) > 0 ? Math.max(32, Math.min(c.size, 1024)) : 160, f = () => Number.isFinite(c.speed) && (c.speed ?? -1) >= 0 ? Math.min(c.speed, 8) : 1, p = new w(Number.isFinite(c.seed) ? Math.min(1, Math.max(0, c.seed)) : X(s), Q(c.state)), [m, h] = t(!1), [g, _] = t(!0);
|
|
503
|
+
return a(() => {
|
|
504
|
+
let e = new IntersectionObserver(([e]) => _(e.isIntersecting));
|
|
505
|
+
e.observe(u);
|
|
506
|
+
let t = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
507
|
+
h(t.matches);
|
|
508
|
+
let n = () => h(t.matches);
|
|
509
|
+
return t.addEventListener("change", n), () => {
|
|
510
|
+
e.disconnect(), t.removeEventListener("change", n);
|
|
511
|
+
};
|
|
512
|
+
}), n(() => {
|
|
513
|
+
let e = Q(c.state);
|
|
514
|
+
v($(c.shape)), d(), Z(c.color ?? "#2b49a3", c.trimColor ?? "#93a6c8", c.screenColor ?? "#e8f2ff");
|
|
515
|
+
let t = f(), n = c.interactive ?? !0;
|
|
516
|
+
c.floorShadow;
|
|
517
|
+
let r = (c.paused ?? !1) || !(t > 0) || m();
|
|
518
|
+
if (p.setState(e), r || !g()) g();
|
|
519
|
+
else return U((e) => {
|
|
520
|
+
if (n && Number.isFinite(A.x)) {
|
|
521
|
+
let e = u.getBoundingClientRect(), t = A.x - (e.left + e.width / 2), n = A.y - (e.top + e.height * .56);
|
|
522
|
+
p.pointer = Math.hypot(t, n) < 700 ? {
|
|
523
|
+
x: t,
|
|
524
|
+
y: n
|
|
525
|
+
} : null;
|
|
526
|
+
} else p.pointer = null;
|
|
527
|
+
p.update(e * t);
|
|
528
|
+
});
|
|
529
|
+
}), e("canvas", [new Y(c, d, "img"), l], void 0, !0);
|
|
530
|
+
}
|
|
531
|
+
//#endregion
|
|
532
|
+
export { te as RobotHead, s as robotHeadShapes, o as robotHeadStates };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
declare const states: readonly ["idle", "thinking", "searching", "listening", "speaking", "working", "happy", "error", "sleeping"];
|
|
2
|
+
export type RobotHeadState = typeof states[number];
|
|
3
|
+
export declare const robotHeadStates: RobotHeadState[];
|
|
4
|
+
export type RobotHeadModel = 'tv';
|
|
5
|
+
declare const geometries: readonly ["rectangle", "square", "circle", "hexagon"];
|
|
6
|
+
export type RobotHeadShape = typeof geometries[number];
|
|
7
|
+
export declare const robotHeadShapes: RobotHeadShape[];
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { RobotHeadState } from '../domain-types';
|
|
2
|
+
export declare const COLS = 22;
|
|
3
|
+
export declare const ROWS = 14;
|
|
4
|
+
export interface FaceParams {
|
|
5
|
+
lookX: number;
|
|
6
|
+
lookY: number;
|
|
7
|
+
blink: number;
|
|
8
|
+
time: number;
|
|
9
|
+
side: number;
|
|
10
|
+
seed: number;
|
|
11
|
+
}
|
|
12
|
+
export interface Grid {
|
|
13
|
+
v: Float32Array;
|
|
14
|
+
cols: number;
|
|
15
|
+
rows: number;
|
|
16
|
+
ox: number;
|
|
17
|
+
oy: number;
|
|
18
|
+
}
|
|
19
|
+
/** A matrix of `cols` × `rows` (each at least the face area, by even steps) with the face area centred. */
|
|
20
|
+
export declare function makeGrid(cols: number, rows: number): Grid;
|
|
21
|
+
export declare const FACES: Record<RobotHeadState, (g: Grid, f: FaceParams) => void>;
|
|
22
|
+
/** The light the screen and the antenna ball carry in a state. */
|
|
23
|
+
export interface StateLight {
|
|
24
|
+
screen: [number, number, number] | null;
|
|
25
|
+
ball: [number, number, number];
|
|
26
|
+
pulse: (t: number) => number;
|
|
27
|
+
}
|
|
28
|
+
export declare const LIGHTS: Record<RobotHeadState, StateLight>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { RobotHeadShape } from '../domain-types';
|
|
2
|
+
export type V3 = [number, number, number];
|
|
3
|
+
export declare const HEAD: {
|
|
4
|
+
readonly bevel: 0.075;
|
|
5
|
+
readonly margin: 0.045;
|
|
6
|
+
readonly gasket: 0.022;
|
|
7
|
+
readonly recess: 0.03;
|
|
8
|
+
readonly earY: 0.03;
|
|
9
|
+
readonly stem: 0.2;
|
|
10
|
+
readonly ball: 0.052;
|
|
11
|
+
};
|
|
12
|
+
export declare const INSET: {
|
|
13
|
+
readonly plate: 0.075;
|
|
14
|
+
readonly hole: number;
|
|
15
|
+
readonly glass: number;
|
|
16
|
+
};
|
|
17
|
+
export interface Mesh {
|
|
18
|
+
pos: Float32Array;
|
|
19
|
+
quads: Uint16Array;
|
|
20
|
+
normals: Float32Array;
|
|
21
|
+
}
|
|
22
|
+
/** v' = Roll · Yaw · Pitch · v, row-major. */
|
|
23
|
+
export declare function rotation(yaw: number, pitch: number, roll: number): number[];
|
|
24
|
+
export declare function rotate(m: number[], x: number, y: number, z: number): V3;
|
|
25
|
+
interface Corner {
|
|
26
|
+
x: number;
|
|
27
|
+
y: number;
|
|
28
|
+
a0: number;
|
|
29
|
+
a1: number;
|
|
30
|
+
}
|
|
31
|
+
export interface Shape {
|
|
32
|
+
name: RobotHeadShape;
|
|
33
|
+
r: number;
|
|
34
|
+
depth: number;
|
|
35
|
+
corners: Corner[];
|
|
36
|
+
hx: number;
|
|
37
|
+
hy: number;
|
|
38
|
+
pitch: number;
|
|
39
|
+
earX: number;
|
|
40
|
+
screws: Array<[number, number, number]>;
|
|
41
|
+
backScrews: Array<[number, number, number]>;
|
|
42
|
+
/** Signed distance to the outline inset by `inset` (negative inside). */
|
|
43
|
+
sd: (x: number, y: number, inset: number) => number;
|
|
44
|
+
/** Trace the outline inset by `inset` as a closed path. */
|
|
45
|
+
path: (ctx: CanvasRenderingContext2D | Path2D, inset: number) => void;
|
|
46
|
+
}
|
|
47
|
+
export declare function getShape(name: RobotHeadShape): Shape;
|
|
48
|
+
/** The shell's sides and its rolled edges, front and back (the flat faces are drawn as plates). */
|
|
49
|
+
export declare function buildBody(shape: Shape, bevelSteps?: number): Mesh;
|
|
50
|
+
/**
|
|
51
|
+
* A solid of revolution: `profile` is [radius, distance along the axis]
|
|
52
|
+
* from `origin` outward, closing on the axis at its end.
|
|
53
|
+
*/
|
|
54
|
+
export declare function buildLathe(profile: Array<[number, number]>, origin: V3, axis: V3, segments?: number): Mesh;
|
|
55
|
+
export interface HeadMeshes {
|
|
56
|
+
body: Mesh;
|
|
57
|
+
earL: Mesh;
|
|
58
|
+
earR: Mesh;
|
|
59
|
+
collar: Mesh;
|
|
60
|
+
}
|
|
61
|
+
export declare function headMeshes(shape: Shape): HeadMeshes;
|
|
62
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { V3 } from './geometry';
|
|
2
|
+
export interface Material {
|
|
3
|
+
albedo: V3;
|
|
4
|
+
f0: number;
|
|
5
|
+
metal: number;
|
|
6
|
+
spec: number;
|
|
7
|
+
shininess: number;
|
|
8
|
+
rim: number;
|
|
9
|
+
}
|
|
10
|
+
export declare const KEY: V3;
|
|
11
|
+
export declare function linear(rgb: [number, number, number]): V3;
|
|
12
|
+
/** The shell's colour at a world-space normal, as linear light. */
|
|
13
|
+
export declare function radiance(m: Material, nx: number, ny: number, nz: number, out?: V3): V3;
|
|
14
|
+
export declare function css(c: V3, alpha?: number): string;
|
|
15
|
+
export declare function shadeCss(m: Material, nx: number, ny: number, nz: number): string;
|
|
16
|
+
export declare function luma(c: V3): number;
|