@lemoncat7/dsh-theme-xiaohei 0.3.0-alpha.23 → 0.3.2
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 +39 -17
- package/THIRD_PARTY_NOTICES.md +41 -0
- package/lib/appearance.js +26 -10
- package/lib/blink.js +3 -3
- package/lib/bloub-heixiu/ambient.d.ts +3 -0
- package/lib/bloub-heixiu/ambient.js +12 -0
- package/lib/bloub-heixiu/character.d.ts +33 -0
- package/lib/bloub-heixiu/character.js +124 -0
- package/lib/bloub-heixiu/effects.d.ts +4 -0
- package/lib/bloub-heixiu/effects.js +91 -0
- package/lib/bloub-heixiu/flight.d.ts +15 -0
- package/lib/bloub-heixiu/flight.js +66 -0
- package/lib/bloub-heixiu/follow.d.ts +13 -0
- package/lib/bloub-heixiu/follow.js +23 -0
- package/lib/bloub-heixiu/layout.d.ts +18 -0
- package/lib/bloub-heixiu/layout.js +12 -0
- package/lib/bloub-heixiu/renderer.d.ts +16 -0
- package/lib/bloub-heixiu/renderer.js +94 -0
- package/lib/bloub-heixiu/runtime.d.ts +6 -0
- package/lib/bloub-heixiu/runtime.js +395 -0
- package/lib/bloub-heixiu/signals.d.ts +17 -0
- package/lib/bloub-heixiu/signals.js +53 -0
- package/lib/bloub-heixiu/styles.d.ts +2 -0
- package/lib/bloub-heixiu/styles.js +98 -0
- package/lib/chrome/accessibility.d.ts +1 -1
- package/lib/chrome/accessibility.js +5 -13
- package/lib/chrome/composer-avatar.d.ts +10 -0
- package/lib/chrome/composer-avatar.js +599 -0
- package/lib/chrome/composer-send-heixiu.d.ts +3 -0
- package/lib/chrome/composer-send-heixiu.js +143 -0
- package/lib/chrome/composer.d.ts +2 -2
- package/lib/chrome/composer.js +84 -95
- package/lib/chrome/controls.d.ts +8 -0
- package/lib/chrome/controls.js +348 -0
- package/lib/chrome/conversation-messages.d.ts +1 -1
- package/lib/chrome/conversation-messages.js +207 -9
- package/lib/chrome/conversation.d.ts +1 -1
- package/lib/chrome/conversation.js +6 -0
- package/lib/chrome/identity.js +4 -18
- package/lib/chrome/portal.d.ts +1 -1
- package/lib/chrome/portal.js +1 -1
- package/lib/chrome/sidebar.d.ts +1 -1
- package/lib/chrome/sidebar.js +134 -153
- package/lib/chrome/tokens.d.ts +1 -1
- package/lib/chrome/tokens.js +121 -68
- package/lib/chrome/workspace.d.ts +2 -2
- package/lib/chrome/workspace.js +35 -254
- package/lib/chrome.js +4 -0
- package/lib/client.d.ts +5 -12
- package/lib/client.js +6262 -4455
- package/lib/composer-avatar.d.ts +18 -0
- package/lib/composer-avatar.js +441 -0
- package/lib/composer-send-heixiu.d.ts +8 -0
- package/lib/composer-send-heixiu.js +133 -0
- package/lib/gaze.js +3 -3
- package/lib/generated-backgrounds.d.ts +14 -0
- package/lib/generated-backgrounds.js +14 -0
- package/lib/generated-character-motion.d.ts +4 -0
- package/lib/generated-character-motion.js +2 -0
- package/lib/generated-identity.d.ts +1 -0
- package/lib/generated-identity.js +1 -0
- package/lib/generated-keyart.d.ts +18 -3
- package/lib/generated-keyart.js +18 -3
- package/lib/host-contract.d.ts +9 -0
- package/lib/host-contract.js +13 -0
- package/lib/host-dom.d.ts +11 -0
- package/lib/host-dom.js +60 -0
- package/lib/loading-heixiu.js +3 -3
- package/lib/metallic-brand-mark.d.ts +10 -0
- package/lib/metallic-brand-mark.js +323 -0
- package/lib/plugin.d.ts +1 -1
- package/lib/plugin.js +31 -16
- package/lib/portal.js +11 -10
- package/lib/reactions.js +3 -3
- package/lib/scene/avatar-model.d.ts +6 -0
- package/lib/scene/avatar-model.js +646 -0
- package/lib/scene/avatar-motion.d.ts +3 -0
- package/lib/scene/avatar-motion.js +799 -0
- package/lib/scene/character-idle.d.ts +17 -0
- package/lib/scene/character-idle.js +65 -0
- package/lib/scene/character-layout.d.ts +24 -0
- package/lib/scene/character-layout.js +51 -0
- package/lib/scene/character-motion-clock.d.ts +18 -0
- package/lib/scene/character-motion-clock.js +57 -0
- package/lib/scene/character-motion-types.d.ts +12 -0
- package/lib/scene/character-motion-types.js +2 -0
- package/lib/scene/character-motion.d.ts +6 -0
- package/lib/scene/character-motion.js +126 -0
- package/lib/scene/character-poses.d.ts +26 -0
- package/lib/scene/character-poses.js +11 -0
- package/lib/scene/character-rig-renderer.d.ts +4 -0
- package/lib/scene/character-rig-renderer.js +85 -0
- package/lib/scene/character-rig.d.ts +20 -0
- package/lib/scene/character-rig.js +53 -0
- package/lib/scene/heixiu-feedback.d.ts +1 -1
- package/lib/scene/heixiu-feedback.js +0 -17
- package/lib/scene/pointer-bridge.d.ts +21 -0
- package/lib/scene/pointer-bridge.js +155 -0
- package/lib/scene/runtime.d.ts +12 -0
- package/lib/scene/runtime.js +87 -0
- package/lib/scene/styles.d.ts +7 -0
- package/lib/scene/styles.js +75 -0
- package/lib/scene/sylva-performance.d.ts +11 -0
- package/lib/scene/sylva-performance.js +58 -0
- package/lib/scene/wallpaper-character-styles.d.ts +3 -0
- package/lib/scene/wallpaper-character-styles.js +53 -0
- package/lib/scene/wallpaper-character.d.ts +4 -0
- package/lib/scene/wallpaper-character.js +213 -0
- package/lib/scene.d.ts +7 -13
- package/lib/scene.js +7 -1023
- package/lib/sidebar-glass.js +99 -36
- package/lib/sidebar-heixiu-roaming.js +5 -5
- package/lib/sidebar-reveal.d.ts +8 -0
- package/lib/sidebar-reveal.js +51 -0
- package/lib/state.d.ts +14 -2
- package/lib/state.js +12 -4
- package/lib/theme.js +2 -2
- package/lib/vendor/bloub/decor.d.ts +114 -0
- package/lib/vendor/bloub/decor.js +198 -0
- package/lib/vendor/bloub/engine.d.ts +213 -0
- package/lib/vendor/bloub/engine.js +452 -0
- package/lib/vendor/bloub/expressions.d.ts +35 -0
- package/lib/vendor/bloub/expressions.js +143 -0
- package/lib/vendor/bloub/eyefit.d.ts +75 -0
- package/lib/vendor/bloub/eyefit.js +393 -0
- package/lib/vendor/bloub/face.d.ts +63 -0
- package/lib/vendor/bloub/face.js +106 -0
- package/lib/vendor/bloub/math.d.ts +22 -0
- package/lib/vendor/bloub/math.js +36 -0
- package/lib/vendor/bloub/profiles.d.ts +8 -0
- package/lib/vendor/bloub/profiles.js +20 -0
- package/lib/vendor/bloub/repere.d.ts +30 -0
- package/lib/vendor/bloub/repere.js +32 -0
- package/lib/vendor/bloub/shape.d.ts +80 -0
- package/lib/vendor/bloub/shape.js +268 -0
- package/lib/vendor/bloub/skins.d.ts +36 -0
- package/lib/vendor/bloub/skins.js +74 -0
- package/lib/vendor/bloub/states.d.ts +87 -0
- package/lib/vendor/bloub/states.js +468 -0
- package/package.json +23 -6
- package/lib/appearance.d.ts.map +0 -1
- package/lib/appearance.js.map +0 -1
- package/lib/blink.d.ts.map +0 -1
- package/lib/blink.js.map +0 -1
- package/lib/boot-appearance.d.ts.map +0 -1
- package/lib/boot-appearance.js.map +0 -1
- package/lib/boot-loader.d.ts.map +0 -1
- package/lib/boot-loader.js.map +0 -1
- package/lib/chrome/accessibility.d.ts.map +0 -1
- package/lib/chrome/accessibility.js.map +0 -1
- package/lib/chrome/blink.d.ts.map +0 -1
- package/lib/chrome/blink.js.map +0 -1
- package/lib/chrome/composer.d.ts.map +0 -1
- package/lib/chrome/composer.js.map +0 -1
- package/lib/chrome/conversation-messages.d.ts.map +0 -1
- package/lib/chrome/conversation-messages.js.map +0 -1
- package/lib/chrome/conversation.d.ts.map +0 -1
- package/lib/chrome/conversation.js.map +0 -1
- package/lib/chrome/frames.d.ts.map +0 -1
- package/lib/chrome/frames.js.map +0 -1
- package/lib/chrome/gaze.d.ts.map +0 -1
- package/lib/chrome/gaze.js.map +0 -1
- package/lib/chrome/identity.d.ts.map +0 -1
- package/lib/chrome/identity.js.map +0 -1
- package/lib/chrome/overlays.d.ts.map +0 -1
- package/lib/chrome/overlays.js.map +0 -1
- package/lib/chrome/portal.d.ts.map +0 -1
- package/lib/chrome/portal.js.map +0 -1
- package/lib/chrome/reactions.d.ts.map +0 -1
- package/lib/chrome/reactions.js.map +0 -1
- package/lib/chrome/sidebar.d.ts.map +0 -1
- package/lib/chrome/sidebar.js.map +0 -1
- package/lib/chrome/tokens.d.ts.map +0 -1
- package/lib/chrome/tokens.js.map +0 -1
- package/lib/chrome/workspace.d.ts.map +0 -1
- package/lib/chrome/workspace.js.map +0 -1
- package/lib/chrome.d.ts.map +0 -1
- package/lib/chrome.js.map +0 -1
- package/lib/client.d.ts.map +0 -1
- package/lib/client.js.map +0 -7
- package/lib/gaze.d.ts.map +0 -1
- package/lib/gaze.js.map +0 -1
- package/lib/generated-identity.d.ts.map +0 -1
- package/lib/generated-identity.js.map +0 -1
- package/lib/generated-keyart.d.ts.map +0 -1
- package/lib/generated-keyart.js.map +0 -1
- package/lib/generated-loading-assets.d.ts.map +0 -1
- package/lib/generated-loading-assets.js.map +0 -1
- package/lib/generated-sidebar-assets.d.ts +0 -4
- package/lib/generated-sidebar-assets.d.ts.map +0 -1
- package/lib/generated-sidebar-assets.js +0 -4
- package/lib/generated-sidebar-assets.js.map +0 -1
- package/lib/heixiu-interactions.d.ts.map +0 -1
- package/lib/heixiu-interactions.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/loading-heixiu.d.ts.map +0 -1
- package/lib/loading-heixiu.js.map +0 -1
- package/lib/plugin.d.ts.map +0 -1
- package/lib/plugin.js.map +0 -1
- package/lib/portal.d.ts.map +0 -1
- package/lib/portal.js.map +0 -1
- package/lib/reactions.d.ts.map +0 -1
- package/lib/reactions.js.map +0 -1
- package/lib/scene/heixiu-feedback.d.ts.map +0 -1
- package/lib/scene/heixiu-feedback.js.map +0 -1
- package/lib/scene/heixiu-interactions.d.ts.map +0 -1
- package/lib/scene/heixiu-interactions.js.map +0 -1
- package/lib/scene/state-transitions.d.ts.map +0 -1
- package/lib/scene/state-transitions.js.map +0 -1
- package/lib/scene.d.ts.map +0 -1
- package/lib/scene.js.map +0 -1
- package/lib/sidebar-glass.d.ts.map +0 -1
- package/lib/sidebar-glass.js.map +0 -1
- package/lib/sidebar-heixiu-escape.d.ts.map +0 -1
- package/lib/sidebar-heixiu-escape.js.map +0 -1
- package/lib/sidebar-heixiu-roaming.d.ts.map +0 -1
- package/lib/sidebar-heixiu-roaming.js.map +0 -1
- package/lib/state.d.ts.map +0 -1
- package/lib/state.js.map +0 -1
- package/lib/theme.d.ts.map +0 -1
- package/lib/theme.js.map +0 -1
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
// Adapted from bloub, Copyright (c) 2026 Jérémy Perret (MIT).
|
|
2
|
+
// See THIRD_PARTY_NOTICES.md for source revision and local changes.
|
|
3
|
+
import { TAU, clamp, createRng, r2 } from './math.js';
|
|
4
|
+
/* ------------------------------------------------------------------ couleurs */
|
|
5
|
+
/**
|
|
6
|
+
* Les anneaux ne sont pas des couleurs plates : la video montre une roue de
|
|
7
|
+
* teintes complete a luminosite constante, avec un degrade le long de chaque
|
|
8
|
+
* trace. Mesure : S 45-62 %, L 50-67 %.
|
|
9
|
+
*/
|
|
10
|
+
function wheel(hue, s = 0.55, l = 0.62) {
|
|
11
|
+
const h = ((hue % 360) + 360) % 360;
|
|
12
|
+
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
13
|
+
const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
|
|
14
|
+
const m = l - c / 2;
|
|
15
|
+
const [r, g, b] = h < 60
|
|
16
|
+
? [c, x, 0]
|
|
17
|
+
: h < 120
|
|
18
|
+
? [x, c, 0]
|
|
19
|
+
: h < 180
|
|
20
|
+
? [0, c, x]
|
|
21
|
+
: h < 240
|
|
22
|
+
? [0, x, c]
|
|
23
|
+
: h < 300
|
|
24
|
+
? [x, 0, c]
|
|
25
|
+
: [c, 0, x];
|
|
26
|
+
const hex = (v) => Math.round((v + m) * 255)
|
|
27
|
+
.toString(16)
|
|
28
|
+
.padStart(2, '0');
|
|
29
|
+
return `#${hex(r)}${hex(g)}${hex(b)}`;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Projette un cercle 3D incline en orthographique.
|
|
33
|
+
*
|
|
34
|
+
* Le cercle vit dans le plan engendre par u (dans l'ecran) et v (qui plonge
|
|
35
|
+
* dans la profondeur). La composante z sert a couper l'arc en deux : la moitie
|
|
36
|
+
* arriere est dessinee avant le corps, donc occultee par lui. C'est ce vrai tri
|
|
37
|
+
* en profondeur qui fait lire les anneaux comme des orbites et pas comme un
|
|
38
|
+
* dessin plat.
|
|
39
|
+
*/
|
|
40
|
+
export function arcRender(seed, t, scale, id, opacity = 1) {
|
|
41
|
+
const spin = seed.phase + t * seed.speed * TAU;
|
|
42
|
+
const cu = Math.cos(seed.tilt);
|
|
43
|
+
const su = Math.sin(seed.tilt);
|
|
44
|
+
const kz = Math.sqrt(Math.max(0, 1 - seed.k * seed.k));
|
|
45
|
+
const N = 64;
|
|
46
|
+
const span = seed.sweep * TAU;
|
|
47
|
+
let front = '';
|
|
48
|
+
let back = '';
|
|
49
|
+
let prev = null;
|
|
50
|
+
for (let i = 0; i <= N; i++) {
|
|
51
|
+
const th = spin + (i / N) * span;
|
|
52
|
+
const ct = Math.cos(th);
|
|
53
|
+
const st = Math.sin(th);
|
|
54
|
+
// u = (cos tilt, sin tilt, 0) ; v = (-sin tilt * k, cos tilt * k, kz)
|
|
55
|
+
const x = seed.a * (ct * cu + st * -su * seed.k) + seed.cx;
|
|
56
|
+
const y = seed.a * (ct * su + st * cu * seed.k) + seed.cy;
|
|
57
|
+
const z = seed.a * st * kz;
|
|
58
|
+
const behind = z < 0;
|
|
59
|
+
const sx = r2(x * scale);
|
|
60
|
+
const sy = r2(y * scale);
|
|
61
|
+
const cmd = behind !== prev ? 'M' : 'L';
|
|
62
|
+
if (behind)
|
|
63
|
+
back += `${cmd}${sx} ${sy}`;
|
|
64
|
+
else
|
|
65
|
+
front += `${cmd}${sx} ${sy}`;
|
|
66
|
+
prev = behind;
|
|
67
|
+
}
|
|
68
|
+
const gx = Math.cos(seed.tilt) * seed.a * scale;
|
|
69
|
+
const gy = Math.sin(seed.tilt) * seed.a * scale;
|
|
70
|
+
return {
|
|
71
|
+
id,
|
|
72
|
+
front,
|
|
73
|
+
back,
|
|
74
|
+
width: seed.width * scale,
|
|
75
|
+
opacity,
|
|
76
|
+
grad: {
|
|
77
|
+
x1: r2(seed.cx * scale - gx),
|
|
78
|
+
y1: r2(seed.cy * scale - gy),
|
|
79
|
+
x2: r2(seed.cx * scale + gx),
|
|
80
|
+
y2: r2(seed.cy * scale + gy),
|
|
81
|
+
stops: [wheel(seed.hue), wheel(seed.hue + seed.hueSpan * 0.5), wheel(seed.hue + seed.hueSpan)]
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/* ---------------------------------------------------------------- anneaux */
|
|
86
|
+
const RING_RNG = createRng(0xa11ce);
|
|
87
|
+
/**
|
|
88
|
+
* 6 anneaux, demi-grand axe 1.30-1.40 (donc nettement plus grands que la
|
|
89
|
+
* boule), aplatissement toujours <= 0.45, epaisseur 0.055, ~3.3 tours/s.
|
|
90
|
+
*/
|
|
91
|
+
export const RINGS = Array.from({ length: 6 }, (_, i) => ({
|
|
92
|
+
a: 1.3 + RING_RNG() * 0.1,
|
|
93
|
+
k: 0.05 + RING_RNG() * 0.4,
|
|
94
|
+
tilt: (i / 6) * Math.PI + RING_RNG() * 0.5,
|
|
95
|
+
speed: 3 + RING_RNG() * 0.7,
|
|
96
|
+
phase: RING_RNG() * TAU,
|
|
97
|
+
sweep: 0.6 + RING_RNG() * 0.25,
|
|
98
|
+
hue: (i * 360) / 6 + RING_RNG() * 30,
|
|
99
|
+
hueSpan: 60 + RING_RNG() * 60,
|
|
100
|
+
width: 0.05 + RING_RNG() * 0.012,
|
|
101
|
+
cx: 0,
|
|
102
|
+
cy: 0.1
|
|
103
|
+
}));
|
|
104
|
+
/**
|
|
105
|
+
* Bouquet d'arcs emboites qui balaie le triangle juste avant les orbites.
|
|
106
|
+
* Vus quasiment par la tranche (d'ou la forme en epingle a cheveux), rmax 1.37.
|
|
107
|
+
*/
|
|
108
|
+
export const SWOOSH = Array.from({ length: 4 }, (_, i) => ({
|
|
109
|
+
a: 0.78 + i * 0.2,
|
|
110
|
+
k: 0.05 + i * 0.02,
|
|
111
|
+
tilt: -0.62 + i * 0.05,
|
|
112
|
+
speed: 0.3,
|
|
113
|
+
phase: 0.06 * i,
|
|
114
|
+
sweep: 0.4,
|
|
115
|
+
hue: 95 + i * 62,
|
|
116
|
+
hueSpan: 100,
|
|
117
|
+
width: 0.05,
|
|
118
|
+
cx: 0,
|
|
119
|
+
cy: -0.12
|
|
120
|
+
}));
|
|
121
|
+
/* ------------------------------------------------------------- 3 points */
|
|
122
|
+
/** x mesures : -0.557 / -0.013 / +0.532, y = 0. */
|
|
123
|
+
export const DOT_X = [-0.557, -0.013, 0.532];
|
|
124
|
+
export const DOT_R = 0.165;
|
|
125
|
+
export const DOT_PEAK = 1.25;
|
|
126
|
+
/* ------------------------------------------------------------ particules */
|
|
127
|
+
const P_RNG = createRng(0xbeef);
|
|
128
|
+
/** 5 particules, une nouvelle toutes les 0.2 s, duree de vie 0.55 s. */
|
|
129
|
+
const PARTICLES = Array.from({ length: 5 }, (_, i) => ({
|
|
130
|
+
birth: i * 0.2,
|
|
131
|
+
angle: P_RNG() * TAU,
|
|
132
|
+
rho: 0.58 + P_RNG() * 0.18
|
|
133
|
+
}));
|
|
134
|
+
/**
|
|
135
|
+
* Les particules ne partent pas en ligne droite : elles spiralent vers le
|
|
136
|
+
* centre (rayon x0.75 par frame, angle +100 deg/s) en grossissant, et passent
|
|
137
|
+
* derriere le noyau ou elles sont avalees.
|
|
138
|
+
*/
|
|
139
|
+
export function particles(t, scale) {
|
|
140
|
+
const out = [];
|
|
141
|
+
for (const p of PARTICLES) {
|
|
142
|
+
const u = t - p.birth;
|
|
143
|
+
if (u < 0 || u > 0.62)
|
|
144
|
+
continue;
|
|
145
|
+
const rho = p.rho * Math.pow(0.75, u * 10);
|
|
146
|
+
const a = p.angle + (u * 100 * Math.PI) / 180;
|
|
147
|
+
out.push({
|
|
148
|
+
x: Math.cos(a) * rho * scale,
|
|
149
|
+
y: Math.sin(a) * rho * scale,
|
|
150
|
+
r: (0.04 + 0.028 * clamp(u / 0.55)) * scale,
|
|
151
|
+
depth: clamp(1 - rho / 0.8),
|
|
152
|
+
opacity: clamp(u / 0.06) * clamp((0.62 - u) / 0.08)
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return out;
|
|
156
|
+
}
|
|
157
|
+
/* ------------------------------------------------------------------ comete */
|
|
158
|
+
/**
|
|
159
|
+
* Contrairement a l'intuition, le point ne traverse pas l'ecran : il reste au
|
|
160
|
+
* centre et c'est la trainee qui l'orbite. Ellipse a = 0.85, b = 0.15,
|
|
161
|
+
* grand axe incline de +34deg, 4 rubans, ~210 deg/s.
|
|
162
|
+
*/
|
|
163
|
+
const COMET_RNG = createRng(0xc0e7);
|
|
164
|
+
export const COMET_RIBBONS = Array.from({ length: 4 }, (_, i) => {
|
|
165
|
+
const d = i - 1.5;
|
|
166
|
+
return {
|
|
167
|
+
a: 0.85 * (1 + d * 0.03),
|
|
168
|
+
// meme aplatissement a +-5 % pres : les rubans forment un faisceau serre
|
|
169
|
+
k: (0.15 / 0.85) * (1 + d * 0.16),
|
|
170
|
+
tilt: (34 * Math.PI) / 180 + d * 0.035,
|
|
171
|
+
speed: 210 / 360,
|
|
172
|
+
// dephasage mesure : 10 a 20 degres entre rubans, pas davantage
|
|
173
|
+
phase: -i * 0.045 + COMET_RNG() * 0.012,
|
|
174
|
+
sweep: 0.34,
|
|
175
|
+
hue: i * 85 + COMET_RNG() * 20,
|
|
176
|
+
hueSpan: 80,
|
|
177
|
+
width: 0.095,
|
|
178
|
+
cx: 0,
|
|
179
|
+
cy: 0
|
|
180
|
+
};
|
|
181
|
+
});
|
|
182
|
+
/** Rayon du point de la comete, mesure a 0.129. */
|
|
183
|
+
export const COMET_DOT = 0.129;
|
|
184
|
+
/* --------------------------------------------------- pastille notification */
|
|
185
|
+
/** Bleu releve au pixel. */
|
|
186
|
+
export const NOTIF_BLUE = '#2496e8';
|
|
187
|
+
/** La pastille est posee exactement sur la circonference, a -42deg. */
|
|
188
|
+
export const NOTIF_ANGLE = -42;
|
|
189
|
+
export const NOTIF_DIST = 1.003;
|
|
190
|
+
/** Rayon au repos ; le pop culmine 14 % au-dessus. */
|
|
191
|
+
export const NOTIF_R = 0.15;
|
|
192
|
+
export const NOTIF_POP = 1.14;
|
|
193
|
+
/**
|
|
194
|
+
* L'encoche est un disque concentrique a la pastille, soustrait du corps.
|
|
195
|
+
* La marge est constante (0.054 R) et suit l'echelle du corps.
|
|
196
|
+
*/
|
|
197
|
+
export const NOTIF_MARGIN = 0.054;
|
|
198
|
+
//# sourceMappingURL=decor.js.map
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { type ArcRender, type DotRender } from './decor.js';
|
|
2
|
+
import { type BotExpression } from './expressions.js';
|
|
3
|
+
import { type StateId } from './states.js';
|
|
4
|
+
export interface RenderedEye {
|
|
5
|
+
d: string;
|
|
6
|
+
matrix: string;
|
|
7
|
+
alpha: number;
|
|
8
|
+
/** Original local bounds, exposed for the theme's hollow ellipse renderer. */
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
/** Uncompressed tangent and lid allow a stroked eye to close without vanishing. */
|
|
12
|
+
openMatrix: string;
|
|
13
|
+
lid: number;
|
|
14
|
+
}
|
|
15
|
+
export interface BotFrame {
|
|
16
|
+
bodyPath: string;
|
|
17
|
+
bodyAlpha: number;
|
|
18
|
+
eyes: RenderedEye[];
|
|
19
|
+
dots: DotRender[];
|
|
20
|
+
/** true = les points passent derriere le corps (particules de l'eclatement) */
|
|
21
|
+
dotsBehind: boolean;
|
|
22
|
+
arcs: ArcRender[];
|
|
23
|
+
notif: {
|
|
24
|
+
x: number;
|
|
25
|
+
y: number;
|
|
26
|
+
r: number;
|
|
27
|
+
} | null;
|
|
28
|
+
notch: {
|
|
29
|
+
x: number;
|
|
30
|
+
y: number;
|
|
31
|
+
r: number;
|
|
32
|
+
} | null;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Ou le bot porte son regard quand quelque chose d'exterieur le pilote — le
|
|
36
|
+
* pointeur de la souris, aujourd'hui.
|
|
37
|
+
*
|
|
38
|
+
* `yaw` et `pitch` sont des directions ABSOLUES, qui remplacent celles de la pose
|
|
39
|
+
* a mesure que `mix` monte. Deux raisons, chacune un piege deja tombe :
|
|
40
|
+
*
|
|
41
|
+
* - c'est le MOTEUR qui doit faire ce melange, pas l'appelant, parce que lui seul
|
|
42
|
+
* connait la pose A CET INSTANT. Un appelant qui compenserait l'orientation de
|
|
43
|
+
* l'expression lirait sa valeur d'arrivee pendant que le morph est encore en
|
|
44
|
+
* cours, et les yeux sautaient a chaque changement d'humeur ;
|
|
45
|
+
* - et il faut que ce soit absolu sur les DEUX axes. En relatif, la hauteur des
|
|
46
|
+
* yeux suivait celle de chaque expression — « neutre » regarde a +28,6deg quand
|
|
47
|
+
* les autres sont entre -9 et +9 — donc les yeux tombaient d'un coup au premier
|
|
48
|
+
* changement d'humeur. Ce qui fait le caractere d'une expression pendant le
|
|
49
|
+
* suivi, c'est la FORME de ses yeux (plisses, ronds, dissymetriques), pas
|
|
50
|
+
* l'endroit ou elle regarde : celui-la, c'est le curseur qui le decide.
|
|
51
|
+
*
|
|
52
|
+
* `mix` dit a quel point l'exterieur commande la DIRECTION (0 = pas du tout).
|
|
53
|
+
*
|
|
54
|
+
* `wander` dit, separement, ce qui reste de derive automatique. Les deux ne se
|
|
55
|
+
* confondent pas : quand le pointeur bouge, la derive doit s'eteindre — cumulees,
|
|
56
|
+
* le bot aurait l'air de chercher le curseur sans jamais le tenir. Mais quand il
|
|
57
|
+
* n'y a PAS de pointeur (arrivee au clavier, au tactile, ou souris sortie de la
|
|
58
|
+
* fenetre), la tete doit rester tournee ET continuer de vivre. Les confondre
|
|
59
|
+
* figeait le regard des que la vue s'ouvrait.
|
|
60
|
+
*
|
|
61
|
+
* `spin` est un tour a parcourir EN CHEMIN, en degres, qu'on fait fondre vers 0
|
|
62
|
+
* avec l'arrivee. Comme les yeux vivent sur une sphere, un tour les fait passer
|
|
63
|
+
* derriere la boule et revenir de l'autre cote — et `-360deg` etant le meme
|
|
64
|
+
* angle que `0`, il ne change rien a l'endroit ou ils se posent.
|
|
65
|
+
*/
|
|
66
|
+
export interface Look {
|
|
67
|
+
yaw: number;
|
|
68
|
+
pitch: number;
|
|
69
|
+
mix: number;
|
|
70
|
+
spin: number;
|
|
71
|
+
wander: number;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Moteur sans horloge : `sample(t)` est une fonction pure du temps.
|
|
75
|
+
*
|
|
76
|
+
* Consequence pratique : pause, reprise, ralenti et saut a une date arbitraire
|
|
77
|
+
* donnent exactement la meme image, et le rendu est testable sans DOM.
|
|
78
|
+
*/
|
|
79
|
+
export declare class BotEngine {
|
|
80
|
+
/** rayon de la boule au repos, en unites de viewBox */
|
|
81
|
+
readonly scale: number;
|
|
82
|
+
private cur;
|
|
83
|
+
private prev;
|
|
84
|
+
/**
|
|
85
|
+
* Pose de depart FIGEE, posee seulement quand un changement d'etat arrive alors qu'un
|
|
86
|
+
* fondu est deja en cours. Cf. `setState`.
|
|
87
|
+
*/
|
|
88
|
+
private departFige;
|
|
89
|
+
private tCur;
|
|
90
|
+
private tPrev;
|
|
91
|
+
private blinkAt;
|
|
92
|
+
private pts;
|
|
93
|
+
private shape;
|
|
94
|
+
private shapePrev;
|
|
95
|
+
private shapeAt;
|
|
96
|
+
private expr;
|
|
97
|
+
private exprPrev;
|
|
98
|
+
private exprAt;
|
|
99
|
+
private look;
|
|
100
|
+
private lookPrev;
|
|
101
|
+
private lookAt;
|
|
102
|
+
/** duree de rattrapage en cours ; voir `LOOK_MORPH`, sa valeur par defaut */
|
|
103
|
+
private lookMorph;
|
|
104
|
+
/** duree du morph quand on change la forme du corps */
|
|
105
|
+
static readonly SHAPE_MORPH = 0.45;
|
|
106
|
+
/**
|
|
107
|
+
* Duree de rattrapage du regard vers la cible. Plus court que `SHAPE_MORPH` :
|
|
108
|
+
* un regard qui suit doit paraitre attentif, pas visqueux. Comme la cible est
|
|
109
|
+
* reposee a chaque mouvement de souris, c'est cette duree qui donne au suivi
|
|
110
|
+
* son inertie — le regard n'atteint jamais tout a fait un curseur qui bouge.
|
|
111
|
+
*/
|
|
112
|
+
static readonly LOOK_MORPH = 0.24;
|
|
113
|
+
constructor(scale?: number, initial?: StateId, shape?: number[] | null, expression?: BotExpression | null);
|
|
114
|
+
/**
|
|
115
|
+
* Expression de repos choisie dans le personnalisateur. Comme la forme, elle
|
|
116
|
+
* glisse vers la nouvelle valeur au lieu de sauter.
|
|
117
|
+
*/
|
|
118
|
+
setExpression(expression: BotExpression | null, now?: number): void;
|
|
119
|
+
/** Expression effective a l'instant `now`, morph en cours compris. */
|
|
120
|
+
private exprAtTime;
|
|
121
|
+
/**
|
|
122
|
+
* Forme choisie dans le personnalisateur. Elle ne remplace le corps que sur
|
|
123
|
+
* les etats au repos (`baseBody`) : sur les autres, la silhouette EST
|
|
124
|
+
* l'animation et ne doit pas etre ecrasee.
|
|
125
|
+
*
|
|
126
|
+
* Le changement se fait en morph, pas d'un coup : comme toutes les formes sont
|
|
127
|
+
* echantillonnees aux memes angles, il suffit d'interpoler les rayons.
|
|
128
|
+
*/
|
|
129
|
+
setShape(radii: number[] | null, now?: number): void;
|
|
130
|
+
/**
|
|
131
|
+
* Forme effective a l'instant `now`, morph en cours compris.
|
|
132
|
+
*
|
|
133
|
+
* Ne remet PAS `shapePrev` a null en fin de morph : `sample` doit rester une
|
|
134
|
+
* fonction pure du temps, donc relire une date passee doit redonner l'image
|
|
135
|
+
* intermediaire. On garde juste une reference de plus.
|
|
136
|
+
*/
|
|
137
|
+
private shapeAtTime;
|
|
138
|
+
/**
|
|
139
|
+
* Nouvelle cible de regard, `null` pour revenir a celui de l'etat.
|
|
140
|
+
*
|
|
141
|
+
* Elle repart de la valeur COURANTE, et non de la cible precedente comme
|
|
142
|
+
* `setShape` : cette methode est appelee a chaque mouvement de pointeur, et
|
|
143
|
+
* repartir de l'ancienne cible ferait reculer le regard d'un cran avant
|
|
144
|
+
* chaque rattrapage — le suivi tremblerait au lieu de glisser.
|
|
145
|
+
*
|
|
146
|
+
* Meme contrat que `setShape` par ailleurs : l'etat externe entre par un
|
|
147
|
+
* setter horodate, jamais par une variable lue pendant `sample`, sinon le
|
|
148
|
+
* moteur cesse d'etre une fonction pure du temps.
|
|
149
|
+
*/
|
|
150
|
+
setLook(look: Look | null, now: number, morph?: number): void;
|
|
151
|
+
/** Regard effectif a l'instant `now`, rattrapage en cours compris. */
|
|
152
|
+
private lookAtTime;
|
|
153
|
+
private posed;
|
|
154
|
+
/**
|
|
155
|
+
* Decalage des yeux a l'instant `now` pour un etat donne, en unites de rayon de boule.
|
|
156
|
+
*
|
|
157
|
+
* Il est LU dans une table et interpole, jamais recalcule : `eyefit.ts` explique
|
|
158
|
+
* pourquoi cette distinction est tout le correctif. Ici il ne reste qu'a l'interpoler
|
|
159
|
+
* sur l'axe de la forme, avec exactement la courbe et la duree du morph de silhouette
|
|
160
|
+
* — c'est la meme cause, donc ce doit etre le meme mouvement.
|
|
161
|
+
*
|
|
162
|
+
* On interroge la table sur les BORNES du morph (`shapePrev` et `shape`) et non sur le
|
|
163
|
+
* profil que rend `shapeAtTime` : celui-la est un tableau neuf alloue a chaque image,
|
|
164
|
+
* donc sans identite, et il n'existe dans aucune table.
|
|
165
|
+
*/
|
|
166
|
+
private decalageAtTime;
|
|
167
|
+
get state(): StateId;
|
|
168
|
+
/**
|
|
169
|
+
* Repart sur `id` SANS etat precedent, comme un moteur neuf pose sur cet etat.
|
|
170
|
+
*
|
|
171
|
+
* C'est ce que veut dire « rembobiner » pour ce moteur. `setState` seul ne peut pas le
|
|
172
|
+
* faire : il garde l'etat quitte pour le fondre, ce qui est exactement son role en
|
|
173
|
+
* lecture, et exactement ce qu'il ne faut pas quand on revient au debut d'une sequence.
|
|
174
|
+
* Rejouer l'image 0 apres une passe complete melangeait le premier etat avec le DERNIER,
|
|
175
|
+
* et l'export GIF s'ouvrait sur une boule sans yeux — la comete a un `eyeAlpha` nul.
|
|
176
|
+
*
|
|
177
|
+
* `sample` reste une fonction pure du temps : comme `setState`, ceci est un setter DATE,
|
|
178
|
+
* appele par le pilote de la sequence, jamais pendant un echantillonnage.
|
|
179
|
+
*/
|
|
180
|
+
reset(id: StateId, now: number): void;
|
|
181
|
+
/**
|
|
182
|
+
* Origine du fondu en cours : la pose figee s'il y en a une, sinon l'etat quitte evalue
|
|
183
|
+
* a son propre temps ecoule — donc encore en train de s'animer, ce qui est voulu.
|
|
184
|
+
*/
|
|
185
|
+
private origine;
|
|
186
|
+
/**
|
|
187
|
+
* Pose composite a l'instant `now`, fondu en cours compris : exactement ce que `sample`
|
|
188
|
+
* melange, avant la couche de vie au repos et de regard. Extraite pour que `setState`
|
|
189
|
+
* puisse la figer.
|
|
190
|
+
*/
|
|
191
|
+
private poseComposee;
|
|
192
|
+
/**
|
|
193
|
+
* Changement d'etat, date.
|
|
194
|
+
*
|
|
195
|
+
* Le moteur ne garde qu'UNE case d'historique, donc un changement qui arrive pendant un
|
|
196
|
+
* fondu remplacait l'origine du melange par la pose PLEINE de l'etat qu'on quittait, au
|
|
197
|
+
* lieu de l'image partiellement melangee qui etait a l'ecran. Mesure sur
|
|
198
|
+
* `idle -> wide -> idle` a 100 ms : 35,9 px de saut contre 8,0 px de mouvement normal.
|
|
199
|
+
*
|
|
200
|
+
* On fige donc la pose composite courante et on melange depuis elle. Continu par
|
|
201
|
+
* construction, quel que soit le nombre de changements enchaines.
|
|
202
|
+
*
|
|
203
|
+
* Et SEULEMENT dans ce cas. Figer a chaque changement arreterait net l'animation de
|
|
204
|
+
* l'etat qu'on quitte pendant tout le fondu — le « ! » d'`alert` se figerait en pleine
|
|
205
|
+
* course — alors qu'il n'y a rien a corriger hors morph : l'etat quitte y est deja
|
|
206
|
+
* exactement l'image affichee. La lecture d'un montage, dont les blocs durent au moins
|
|
207
|
+
* le plus long fondu (`MIN_BLOCK`), ne fige donc jamais rien et rend au bit ce qu'elle
|
|
208
|
+
* rendait.
|
|
209
|
+
*/
|
|
210
|
+
setState(id: StateId, now: number): void;
|
|
211
|
+
sample(now: number): BotFrame;
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=engine.d.ts.map
|