@dopaminefx/effect-fail 0.1.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/dist/fail-shader.d.ts +19 -0
- package/dist/fail-shader.d.ts.map +1 -0
- package/dist/fail-shader.js +196 -0
- package/dist/fail-shader.js.map +1 -0
- package/dist/fail.dope.json +523 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/package.json +46 -0
- package/src/fail-shader.ts +205 -0
- package/src/fail.dope.json +523 -0
- package/src/index.ts +56 -0
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fmt": "dopamine-effect",
|
|
3
|
+
"v": "1.0.0",
|
|
4
|
+
"id": "dopamine.error.fail",
|
|
5
|
+
"meta": {
|
|
6
|
+
"name": "Fail Stamp",
|
|
7
|
+
"description": "A failure/denied moment — the emotional opposite of the success effects. A red/amber cross is stamped in over a recoiling error flare with a sharp hit + shake, then desaturates and collapses. Short and punchy.",
|
|
8
|
+
"tags": [
|
|
9
|
+
"error",
|
|
10
|
+
"fail",
|
|
11
|
+
"denied",
|
|
12
|
+
"negative"
|
|
13
|
+
]
|
|
14
|
+
},
|
|
15
|
+
"controls": {
|
|
16
|
+
"mood": {
|
|
17
|
+
"type": "enum",
|
|
18
|
+
"label": "Mood",
|
|
19
|
+
"default": "error",
|
|
20
|
+
"options": [
|
|
21
|
+
"try-again",
|
|
22
|
+
"error",
|
|
23
|
+
"denied"
|
|
24
|
+
],
|
|
25
|
+
"ui": "segmented"
|
|
26
|
+
},
|
|
27
|
+
"intensity": {
|
|
28
|
+
"type": "scalar",
|
|
29
|
+
"label": "Severity",
|
|
30
|
+
"default": 0.7,
|
|
31
|
+
"min": 0,
|
|
32
|
+
"max": 1,
|
|
33
|
+
"step": 0.01,
|
|
34
|
+
"ui": "slider",
|
|
35
|
+
"help": "How hard the failure lands: flare heat/size, shake amount, recoil."
|
|
36
|
+
},
|
|
37
|
+
"whimsy": {
|
|
38
|
+
"type": "scalar",
|
|
39
|
+
"label": "Whimsy",
|
|
40
|
+
"default": 0.5,
|
|
41
|
+
"min": 0,
|
|
42
|
+
"max": 1,
|
|
43
|
+
"step": 0.01,
|
|
44
|
+
"ui": "slider",
|
|
45
|
+
"help": "Photoreal flare (0) to desaturated RGB-split glitch collapse (1)."
|
|
46
|
+
},
|
|
47
|
+
"seed": {
|
|
48
|
+
"type": "int",
|
|
49
|
+
"label": "Seed",
|
|
50
|
+
"default": null,
|
|
51
|
+
"nullable": true,
|
|
52
|
+
"help": "Null = unique error palette per fire; pin to reproduce."
|
|
53
|
+
},
|
|
54
|
+
"origin": {
|
|
55
|
+
"type": "point",
|
|
56
|
+
"label": "Origin",
|
|
57
|
+
"default": "center"
|
|
58
|
+
},
|
|
59
|
+
"target": {
|
|
60
|
+
"type": "selector",
|
|
61
|
+
"label": "Target",
|
|
62
|
+
"default": "document.body"
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"baselines": {
|
|
66
|
+
"try-again": {
|
|
67
|
+
"durationMs": 900,
|
|
68
|
+
"lightness": 0.78,
|
|
69
|
+
"chroma": 0.13,
|
|
70
|
+
"hueCenter": 70,
|
|
71
|
+
"hueRange": 40,
|
|
72
|
+
"shakeAmount": 0.5
|
|
73
|
+
},
|
|
74
|
+
"error": {
|
|
75
|
+
"durationMs": 760,
|
|
76
|
+
"lightness": 0.72,
|
|
77
|
+
"chroma": 0.17,
|
|
78
|
+
"hueCenter": 40,
|
|
79
|
+
"hueRange": 36,
|
|
80
|
+
"shakeAmount": 0.85
|
|
81
|
+
},
|
|
82
|
+
"denied": {
|
|
83
|
+
"durationMs": 640,
|
|
84
|
+
"lightness": 0.66,
|
|
85
|
+
"chroma": 0.21,
|
|
86
|
+
"hueCenter": 22,
|
|
87
|
+
"hueRange": 30,
|
|
88
|
+
"shakeAmount": 1.25
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
"palette": {
|
|
92
|
+
"model": "oklch",
|
|
93
|
+
"space": "linear-srgb",
|
|
94
|
+
"generator": "golden-angle",
|
|
95
|
+
"goldenAngleDeg": 137.50776405003785,
|
|
96
|
+
"stops": 3,
|
|
97
|
+
"hueSpread": 0.18,
|
|
98
|
+
"lightness": {
|
|
99
|
+
"baseline": "lightness",
|
|
100
|
+
"perStop": [
|
|
101
|
+
0,
|
|
102
|
+
0.06,
|
|
103
|
+
-0.05
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
"chroma": {
|
|
107
|
+
"from": {
|
|
108
|
+
"mul": [
|
|
109
|
+
{
|
|
110
|
+
"baseline": "chroma"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"lerp": [
|
|
114
|
+
"intensity",
|
|
115
|
+
0.8,
|
|
116
|
+
1.4
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
},
|
|
121
|
+
"perStop": [
|
|
122
|
+
0,
|
|
123
|
+
0.02,
|
|
124
|
+
-0.01
|
|
125
|
+
]
|
|
126
|
+
},
|
|
127
|
+
"seed": {
|
|
128
|
+
"deterministic": true,
|
|
129
|
+
"source": "controls.seed",
|
|
130
|
+
"prng": "mulberry32",
|
|
131
|
+
"note": "Algorithmic OKLCH biased to error reds/ambers: a narrow hueRange around a hot hueCenter keeps every fire inside the red/amber error band while still being generated (unique per fire)."
|
|
132
|
+
},
|
|
133
|
+
"perMood": {
|
|
134
|
+
"try-again": {
|
|
135
|
+
"hueCenter": 70,
|
|
136
|
+
"hueRange": 40,
|
|
137
|
+
"lightness": 0.78,
|
|
138
|
+
"chroma": 0.13
|
|
139
|
+
},
|
|
140
|
+
"error": {
|
|
141
|
+
"hueCenter": 40,
|
|
142
|
+
"hueRange": 36,
|
|
143
|
+
"lightness": 0.72,
|
|
144
|
+
"chroma": 0.17
|
|
145
|
+
},
|
|
146
|
+
"denied": {
|
|
147
|
+
"hueCenter": 22,
|
|
148
|
+
"hueRange": 30,
|
|
149
|
+
"lightness": 0.66,
|
|
150
|
+
"chroma": 0.21
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
"tempo": {
|
|
155
|
+
"durationMs": {
|
|
156
|
+
"from": {
|
|
157
|
+
"round": {
|
|
158
|
+
"mul": [
|
|
159
|
+
{
|
|
160
|
+
"baseline": "durationMs"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"lerp": [
|
|
164
|
+
"intensity",
|
|
165
|
+
1.15,
|
|
166
|
+
0.85
|
|
167
|
+
]
|
|
168
|
+
}
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
"frame": {
|
|
174
|
+
"amp": {
|
|
175
|
+
"lt": [
|
|
176
|
+
{
|
|
177
|
+
"clamp01": {
|
|
178
|
+
"input": "life"
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
0.05,
|
|
182
|
+
{
|
|
183
|
+
"easeOutCubic": {
|
|
184
|
+
"div": [
|
|
185
|
+
{
|
|
186
|
+
"clamp01": {
|
|
187
|
+
"input": "life"
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
0.05
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"lt": [
|
|
196
|
+
{
|
|
197
|
+
"clamp01": {
|
|
198
|
+
"input": "life"
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
0.55,
|
|
202
|
+
1,
|
|
203
|
+
{
|
|
204
|
+
"pow": [
|
|
205
|
+
{
|
|
206
|
+
"clamp01": {
|
|
207
|
+
"sub": [
|
|
208
|
+
1,
|
|
209
|
+
{
|
|
210
|
+
"div": [
|
|
211
|
+
{
|
|
212
|
+
"sub": [
|
|
213
|
+
{
|
|
214
|
+
"clamp01": {
|
|
215
|
+
"input": "life"
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
0.55
|
|
219
|
+
]
|
|
220
|
+
},
|
|
221
|
+
0.45
|
|
222
|
+
]
|
|
223
|
+
}
|
|
224
|
+
]
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
1.7
|
|
228
|
+
]
|
|
229
|
+
}
|
|
230
|
+
]
|
|
231
|
+
}
|
|
232
|
+
]
|
|
233
|
+
},
|
|
234
|
+
"extras": {
|
|
235
|
+
"stamp": {
|
|
236
|
+
"sub": [
|
|
237
|
+
1,
|
|
238
|
+
{
|
|
239
|
+
"pow": [
|
|
240
|
+
{
|
|
241
|
+
"sub": [
|
|
242
|
+
1,
|
|
243
|
+
{
|
|
244
|
+
"clamp01": {
|
|
245
|
+
"div": [
|
|
246
|
+
{
|
|
247
|
+
"input": "elapsedMs"
|
|
248
|
+
},
|
|
249
|
+
170
|
|
250
|
+
]
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
]
|
|
254
|
+
},
|
|
255
|
+
5
|
|
256
|
+
]
|
|
257
|
+
}
|
|
258
|
+
]
|
|
259
|
+
},
|
|
260
|
+
"shake": {
|
|
261
|
+
"lt": [
|
|
262
|
+
0,
|
|
263
|
+
{
|
|
264
|
+
"input": "elapsedMs"
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
"mul": [
|
|
268
|
+
{
|
|
269
|
+
"sin": {
|
|
270
|
+
"mul": [
|
|
271
|
+
{
|
|
272
|
+
"div": [
|
|
273
|
+
{
|
|
274
|
+
"input": "elapsedMs"
|
|
275
|
+
},
|
|
276
|
+
300
|
|
277
|
+
]
|
|
278
|
+
},
|
|
279
|
+
3.141592653589793,
|
|
280
|
+
7
|
|
281
|
+
]
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
"exp": {
|
|
286
|
+
"div": [
|
|
287
|
+
{
|
|
288
|
+
"sub": [
|
|
289
|
+
0,
|
|
290
|
+
{
|
|
291
|
+
"input": "elapsedMs"
|
|
292
|
+
}
|
|
293
|
+
]
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
"mul": [
|
|
297
|
+
300,
|
|
298
|
+
0.35
|
|
299
|
+
]
|
|
300
|
+
}
|
|
301
|
+
]
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"param": "shakeAmount"
|
|
306
|
+
}
|
|
307
|
+
]
|
|
308
|
+
},
|
|
309
|
+
0
|
|
310
|
+
]
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
"reducedMotion": {
|
|
315
|
+
"peakMs": 200,
|
|
316
|
+
"holdMs": 320
|
|
317
|
+
},
|
|
318
|
+
"note": "The negative, punchy counterpart to the held-breath success envelope: frame.amp is the slam/hold/collapse fail envelope; stamp (the ✗ slash-in over 170 ms) and shake (a damped ~3.5-oscillation recoil over 300 ms) run on the REAL un-stepped clock (elapsedMs) on every platform."
|
|
319
|
+
},
|
|
320
|
+
"geometry": {
|
|
321
|
+
"kind": "radial",
|
|
322
|
+
"viewBox": [
|
|
323
|
+
0,
|
|
324
|
+
0,
|
|
325
|
+
100,
|
|
326
|
+
100
|
|
327
|
+
],
|
|
328
|
+
"outlines": {
|
|
329
|
+
"cross": {
|
|
330
|
+
"role": "deny-glyph",
|
|
331
|
+
"source": "baked-sdf",
|
|
332
|
+
"note": "GEOMETRY SEAM: the ✗ icon is driven by this svgPath, baked to the inline SDF below (scripts/bake-sdf.mjs). The fail shader samples it (uSdfTex). Swap the path + re-bake to change the rejected icon with no shader edit. Two diagonal bars (a clean cross).",
|
|
333
|
+
"svgPath": "M 24 24 L 76 76 M 76 24 L 24 76",
|
|
334
|
+
"sdf": {
|
|
335
|
+
"size": 64,
|
|
336
|
+
"range": 18,
|
|
337
|
+
"viewBox": [
|
|
338
|
+
0,
|
|
339
|
+
0,
|
|
340
|
+
100,
|
|
341
|
+
100
|
|
342
|
+
],
|
|
343
|
+
"data": "data:application/octet-stream;base64,RFMAQP/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////59PHw8vX6///////////////////////////////////69fLw8fT5/////////////////////////////vPq497b2tzf5e32//////////////////////////////bt5d/c2tve4+rz/v//////////////////////+Ovg1s7IxcTGytDY4+/8/////////////////////////O/j2NDKxsTFyM7W4Ov4////////////////////9ufZzcK5s6+usLS7xdDd6/r/////////////////////+uvd0MW7tLCur7O5ws3Z5/b/////////////////+OfXyLqupZ2ZmJqfp7G+zNvr+v//////////////////+uvbzL6xp5+amJmdpa66yNfn+P///////////////uvZyLepm5CIg4KEipOfrbzL2+v6////////////////+uvby7ytn5OKhIKDiJCbqbfI2ev+//////////////PgzbqpmIl9c21sbnaAjZ2svMvb6/r/////////////+uvby7ysnY2Adm5sbXN9iZipus3g8//////////////q1sKum4l5al9YVVlibn2Nnay8y9vr+v//////////+uvby7ysnY19bmJZVVhfanmJm67C1ur////////////54865pZB9alpMQj9ET15ufY2drLzL2+v6////////+uvby7ysnY19bl5PRD9CTFpqfZCluc7j+f//////////9N7Is52Ic19MOi0pMD9OXm59jZ2svMvb6/r/////+uvby7ysnY19bl5OPzApLTpMX3OInbPI3vT///////////Hbxa+Zg21YQi0bEx8vP05ebn2Nnay8y9vr+v//+uvby7ysnY19bl5OPy8fExstQlhtg5mvxdvx///////////w2sSumIJsVT8pEwAQHy8/Tl5ufY2drLzL2+v6+uvby7ysnY19bl5OPy8fEAATKT9VbIKYrsTa8P//////////8tzGsJqEbllEMB8QABAfLz9OXm59jZ2svMvb6+vby7ysnY19bl5OPy8fEAAQHzBEWW6EmrDG3PL///////////XfyrSfinZiTz8vHxAAEB8vP05ebn2Nnay8y9vby7ysnY19bl5OPy8fEAAQHy8/T2J2ip+0yt/1///////////65dC7p5OAbl5OPy8fEAAQHy8/Tl5ufY2drLzLy7ysnY19bl5OPy8fEAAQHy8/Tl5ugJOnu9Dl+v///////////+3YxbGfjX1uXk4/Lx8QABAfLz9OXm59jZ2svLysnY19bl5OPy8fEAAQHy8/Tl5ufY2fscXY7f/////////////249C+rZ2NfW5eTj8vHxAAEB8vP05ebn2NnaysnY19bl5OPy8fEAAQHy8/Tl5ufY2drb7Q4/b//////////////+/dzLysnY19bl5OPy8fEAAQHy8/Tl5ufY2dnY19bl5OPy8fEAAQHy8/Tl5ufY2drLzM3e/////////////////869vLvKydjX1uXk4/Lx8QABAfLz9OXm59jY19bl5OPy8fEAAQHy8/Tl5ufY2drLzL2+v8//////////////////rr28u8rJ2NfW5eTj8vHxAAEB8vP05ebn19bl5OPy8fEAAQHy8/Tl5ufY2drLzL2+v6////////////////////+uvby7ysnY19bl5OPy8fEAAQHy8/Tl5ubl5OPy8fEAAQHy8/Tl5ufY2drLzL2+v6///////////////////////669vLvKydjX1uXk4/Lx8QABAfLz9OXl5OPy8fEAAQHy8/Tl5ufY2drLzL2+v6//////////////////////////rr28u8rJ2NfW5eTj8vHxAAEB8vP05OPy8fEAAQHy8/Tl5ufY2drLzL2+v6////////////////////////////+uvby7ysnY19bl5OPy8fEAAQHy8/Py8fEAAQHy8/Tl5ufY2drLzL2+v6///////////////////////////////669vLvKydjX1uXk4/Lx8QABAfLy8fEAAQHy8/Tl5ufY2drLzL2+v6//////////////////////////////////rr28u8rJ2NfW5eTj8vHxAAEB8fEAAQHy8/Tl5ufY2drLzL2+v6////////////////////////////////////+uvby7ysnY19bl5OPy8fEAAQEAAQHy8/Tl5ufY2drLzL2+v6///////////////////////////////////////669vLvKydjX1uXk4/Lx8QAAAQHy8/Tl5ufY2drLzL2+v6////////////////////////////////////////+uvby7ysnY19bl5OPy8fEAAAEB8vP05ebn2Nnay8y9vr+v//////////////////////////////////////+uvby7ysnY19bl5OPy8fEAAQEAAQHy8/Tl5ufY2drLzL2+v6////////////////////////////////////+uvby7ysnY19bl5OPy8fEAAQHx8QABAfLz9OXm59jZ2svMvb6/r/////////////////////////////////+uvby7ysnY19bl5OPy8fEAAQHy8vHxAAEB8vP05ebn2Nnay8y9vr+v//////////////////////////////+uvby7ysnY19bl5OPy8fEAAQHy8/Py8fEAAQHy8/Tl5ufY2drLzL2+v6////////////////////////////+uvby7ysnY19bl5OPy8fEAAQHy8/Tk4/Lx8QABAfLz9OXm59jZ2svMvb6/r/////////////////////////+uvby7ysnY19bl5OPy8fEAAQHy8/Tl5eTj8vHxAAEB8vP05ebn2Nnay8y9vr+v//////////////////////+uvby7ysnY19bl5OPy8fEAAQHy8/Tl5ubl5OPy8fEAAQHy8/Tl5ufY2drLzL2+v6////////////////////+uvby7ysnY19bl5OPy8fEAAQHy8/Tl5ufX1uXk4/Lx8QABAfLz9OXm59jZ2svMvb6/r//////////////////Ovby7ysnY19bl5OPy8fEAAQHy8/Tl5ufY2NfW5eTj8vHxAAEB8vP05ebn2Nnay8y9vr/P///////////////+/dzLysnY19bl5OPy8fEAAQHy8/Tl5ufY2dnY19bl5OPy8fEAAQHy8/Tl5ufY2drLzM3e////////////////bj0L6tnY19bl5OPy8fEAAQHy8/Tl5ufY2drKydjX1uXk4/Lx8QABAfLz9OXm59jZ2tvtDj9v/////////////t2MWxn419bl5OPy8fEAAQHy8/Tl5ufY2drLy8rJ2NfW5eTj8vHxAAEB8vP05ebn2Nn7HF2O3////////////65dC7p5OAbl5OPy8fEAAQHy8/Tl5ufY2drLzLy7ysnY19bl5OPy8fEAAQHy8/Tl5ugJOnu9Dl+v//////////9d/KtJ+KdmJPPy8fEAAQHy8/Tl5ufY2drLzL29vLvKydjX1uXk4/Lx8QABAfLz9PYnaKn7TK3/X///////////LcxrCahG5ZRDAfEAAQHy8/Tl5ufY2drLzL2+vr28u8rJ2NfW5eTj8vHxAAEB8wRFluhJqwxtzy///////////w2sSumIJsVT8pEwAQHy8/Tl5ufY2drLzL2+v6+uvby7ysnY19bl5OPy8fEAATKT9VbIKYrsTa8P//////////8dvFr5mDbVhCLRsTHy8/Tl5ufY2drLzL2+v6///669vLvKydjX1uXk4/Lx8TGy1CWG2Dma/F2/H///////////TeyLOdiHNfTDotKTA/Tl5ufY2drLzL2+v6//////rr28u8rJ2NfW5eTj8wKS06TF9ziJ2zyN70///////////54865pZB9alpMQj9ET15ufY2drLzL2+v6////////+uvby7ysnY19bl5PRD9CTFpqfZCluc7j+f///////////+rWwq6biXlqX1hVWWJufY2drLzL2+v6///////////669vLvKydjX1uYllVWF9qeYmbrsLW6v/////////////z4M26qZiJfXNtbG52gI2drLzL2+v6//////////////rr28u8rJ2NgHZubG1zfYmYqbrN4PP//////////////uvZyLepm5CIg4KEipOfrbzL2+v6////////////////+uvby7ytn5OKhIKDiJCbqbfI2ev+///////////////459fIuq6lnZmYmp+nsb7M2+v6///////////////////669vMvrGnn5qYmZ2lrrrI1+f4//////////////////bn2c3CubOvrrC0u8XQ3ev6//////////////////////rr3dDFu7Swrq+zucLN2ef2////////////////////+Ovg1s7IxcTGytDY4+/8/////////////////////////O/j2NDKxsTFyM7W4Ov4///////////////////////+8+rj3tva3N/l7fb/////////////////////////////9u3l39za297j6vP+////////////////////////////+fTx8PL1+v//////////////////////////////////+vXy8PH0+f////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8="
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
"content": {
|
|
349
|
+
"note": "No word set for the fail effect — the ✗ cross is the whole message. Kept here for symmetry with the other effects' content blocks.",
|
|
350
|
+
"tokens": [
|
|
351
|
+
"✗"
|
|
352
|
+
]
|
|
353
|
+
},
|
|
354
|
+
"render": {
|
|
355
|
+
"params": {
|
|
356
|
+
"exposure": {
|
|
357
|
+
"type": "float",
|
|
358
|
+
"from": {
|
|
359
|
+
"lerp": [
|
|
360
|
+
"intensity",
|
|
361
|
+
0.9,
|
|
362
|
+
1.6
|
|
363
|
+
]
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
"severity": {
|
|
367
|
+
"type": "float",
|
|
368
|
+
"from": {
|
|
369
|
+
"control": "intensity"
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
"shakeAmount": {
|
|
373
|
+
"type": "float",
|
|
374
|
+
"from": {
|
|
375
|
+
"mul": [
|
|
376
|
+
{
|
|
377
|
+
"baseline": "shakeAmount"
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
"lerp": [
|
|
381
|
+
"intensity",
|
|
382
|
+
0.7,
|
|
383
|
+
1.3
|
|
384
|
+
]
|
|
385
|
+
}
|
|
386
|
+
]
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
"style": {
|
|
390
|
+
"type": "float",
|
|
391
|
+
"from": {
|
|
392
|
+
"control": "whimsy"
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
"shadowHeightFrac": 0.42,
|
|
397
|
+
"pass": {
|
|
398
|
+
"note": "PER-PASS uniforms (evaluated once per pass, never per frame): the ✗ box half-size + SDF stroke/range in device px, sized to the TARGETED element (targetMinDimPx falls back to the full canvas when untargeted). sdfRange/sdfViewBoxW come from the cross sampler's baked-SDF metadata; sdfOn is deliberately NOT here — the web aux-texture binding flips it, natives keep the analytic ✗ at 0.",
|
|
399
|
+
"boxPx": {
|
|
400
|
+
"mul": [
|
|
401
|
+
0.15,
|
|
402
|
+
{
|
|
403
|
+
"input": "targetMinDimPx"
|
|
404
|
+
}
|
|
405
|
+
]
|
|
406
|
+
},
|
|
407
|
+
"sdfStrokePx": {
|
|
408
|
+
"mul": [
|
|
409
|
+
0.15,
|
|
410
|
+
{
|
|
411
|
+
"input": "targetMinDimPx"
|
|
412
|
+
},
|
|
413
|
+
0.13
|
|
414
|
+
]
|
|
415
|
+
},
|
|
416
|
+
"sdfRangePx": {
|
|
417
|
+
"mul": [
|
|
418
|
+
{
|
|
419
|
+
"input": "sdfRange"
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
"div": [
|
|
423
|
+
{
|
|
424
|
+
"mul": [
|
|
425
|
+
2,
|
|
426
|
+
{
|
|
427
|
+
"mul": [
|
|
428
|
+
0.15,
|
|
429
|
+
{
|
|
430
|
+
"input": "targetMinDimPx"
|
|
431
|
+
}
|
|
432
|
+
]
|
|
433
|
+
}
|
|
434
|
+
]
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
"max": [
|
|
438
|
+
{
|
|
439
|
+
"input": "sdfViewBoxW"
|
|
440
|
+
},
|
|
441
|
+
0.000001
|
|
442
|
+
]
|
|
443
|
+
}
|
|
444
|
+
]
|
|
445
|
+
}
|
|
446
|
+
]
|
|
447
|
+
}
|
|
448
|
+
},
|
|
449
|
+
"consts": {},
|
|
450
|
+
"config": {
|
|
451
|
+
"usesOrigin": true
|
|
452
|
+
},
|
|
453
|
+
"backends": {
|
|
454
|
+
"webgl2": {
|
|
455
|
+
"stage": "fullscreen-triangle",
|
|
456
|
+
"blend": "screen",
|
|
457
|
+
"shader": {
|
|
458
|
+
"program": "fail"
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
},
|
|
462
|
+
"fallbackOrder": [
|
|
463
|
+
"webgl2"
|
|
464
|
+
]
|
|
465
|
+
},
|
|
466
|
+
"binding": {
|
|
467
|
+
"note": "CROSS-PLATFORM uniform-binding contract. Which render.params are NOT shader uniforms, the seed-keyed scatter field (no scatterWeb — the fail shader reads no seed uniform), the per-frame/host extras, and the texture samplers — one source of truth for the web u<Name> list, the Swift struct + packer, and the MSL struct. SHIPS in the portable .dope (the runtime derives its uniform bindings from it); the toolchain consumes it too for the Metal struct codegen. Only `x-build`, `slug` and `kind` stay toolchain-only.",
|
|
468
|
+
"excludeParams": [
|
|
469
|
+
"style",
|
|
470
|
+
"shakeAmount",
|
|
471
|
+
"seed"
|
|
472
|
+
],
|
|
473
|
+
"scatterKey": "failSeed",
|
|
474
|
+
"extras": [
|
|
475
|
+
{
|
|
476
|
+
"name": "stamp",
|
|
477
|
+
"type": "float",
|
|
478
|
+
"web": "uStamp",
|
|
479
|
+
"note": "stampProgress(animMs)"
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
"name": "shake",
|
|
483
|
+
"type": "float",
|
|
484
|
+
"web": "uShake",
|
|
485
|
+
"note": "signed recoil shake (-1..1)"
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
"name": "sdfOn",
|
|
489
|
+
"type": "float",
|
|
490
|
+
"web": "uSdfOn",
|
|
491
|
+
"note": "1 = drive the cross from the baked SDF"
|
|
492
|
+
},
|
|
493
|
+
{
|
|
494
|
+
"name": "sdfRangePx",
|
|
495
|
+
"type": "float",
|
|
496
|
+
"web": "uSdfRangePx",
|
|
497
|
+
"note": "device px mapping to the SDF 0..1 range"
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
"name": "sdfStrokePx",
|
|
501
|
+
"type": "float",
|
|
502
|
+
"web": "uSdfStrokePx",
|
|
503
|
+
"note": "half stroke width (device px)"
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
"name": "boxPx",
|
|
507
|
+
"type": "float",
|
|
508
|
+
"web": "uBoxPx",
|
|
509
|
+
"note": "half-size (device px) of the ✗ box"
|
|
510
|
+
}
|
|
511
|
+
],
|
|
512
|
+
"samplers": [
|
|
513
|
+
{
|
|
514
|
+
"web": "uSdfTex",
|
|
515
|
+
"name": "sdfTex",
|
|
516
|
+
"texture": 1,
|
|
517
|
+
"outline": "cross",
|
|
518
|
+
"on": "sdfOn",
|
|
519
|
+
"note": "Declarative SDF source: the baked geometry.outlines.cross SDF binds here on web (flipping the sdfOn extra to 1); the native runtimes don't bind aux textures yet — sdfOn stays 0 and the shader's analytic two-bar ✗ renders."
|
|
520
|
+
}
|
|
521
|
+
]
|
|
522
|
+
}
|
|
523
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fail / error effect — the emotional OPPOSITE of the three success effects.
|
|
3
|
+
*
|
|
4
|
+
* A red/amber ✗ cross is STAMPED in over a recoiling error flare with a sharp
|
|
5
|
+
* hit + damped shake, then desaturates and collapses. Short and punchy, not a
|
|
6
|
+
* celebratory bloom.
|
|
7
|
+
*
|
|
8
|
+
* FULLY DATA-DRIVEN: the params/palette/tempo come from fail.dope.json via the
|
|
9
|
+
* loader; the per-frame logic — the slam/hold/collapse `amp`, the 170 ms stamp
|
|
10
|
+
* and the damped recoil shake — is `tempo.frame` (stamp/shake run on the REAL
|
|
11
|
+
* un-stepped `elapsedMs`, matching the Swift/Android ports); and the ✗ plumbing
|
|
12
|
+
* that used to be code hooks is now data too: `render.pass` declares the
|
|
13
|
+
* box/stroke/range pixel uniforms (sized to `targetMinDimPx`) and the
|
|
14
|
+
* `binding.samplers` `outline`/`on` source declares the baked-SDF aux texture
|
|
15
|
+
* (geometry seam). The only hand-written web sources left are this
|
|
16
|
+
* registration shim (the fail moods are web-runtime-only) and the shader.
|
|
17
|
+
*/
|
|
18
|
+
import { type RGB, type EffectFactory, type PassParams } from "@dopaminefx/core";
|
|
19
|
+
/** The fail render params (the loader bag + the typed fields the shader reads). */
|
|
20
|
+
export interface FailParams extends PassParams {
|
|
21
|
+
seed: number;
|
|
22
|
+
palette: [RGB, RGB, RGB];
|
|
23
|
+
exposure: number;
|
|
24
|
+
severity: number;
|
|
25
|
+
shakeAmount: number;
|
|
26
|
+
style: number;
|
|
27
|
+
failSeed: number;
|
|
28
|
+
}
|
|
29
|
+
export declare const fail: EffectFactory<FailParams>;
|
|
30
|
+
export default fail;
|
|
31
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAIL,KAAK,GAAG,EACR,KAAK,aAAa,EAClB,KAAK,UAAU,EAChB,MAAM,kBAAkB,CAAC;AAU1B,mFAAmF;AACnF,MAAM,WAAW,UAAW,SAAQ,UAAU;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAKD,eAAO,MAAM,IAAI,EAGkB,aAAa,CAAC,UAAU,CAAC,CAAC;AAE7D,eAAe,IAAI,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fail / error effect — the emotional OPPOSITE of the three success effects.
|
|
3
|
+
*
|
|
4
|
+
* A red/amber ✗ cross is STAMPED in over a recoiling error flare with a sharp
|
|
5
|
+
* hit + damped shake, then desaturates and collapses. Short and punchy, not a
|
|
6
|
+
* celebratory bloom.
|
|
7
|
+
*
|
|
8
|
+
* FULLY DATA-DRIVEN: the params/palette/tempo come from fail.dope.json via the
|
|
9
|
+
* loader; the per-frame logic — the slam/hold/collapse `amp`, the 170 ms stamp
|
|
10
|
+
* and the damped recoil shake — is `tempo.frame` (stamp/shake run on the REAL
|
|
11
|
+
* un-stepped `elapsedMs`, matching the Swift/Android ports); and the ✗ plumbing
|
|
12
|
+
* that used to be code hooks is now data too: `render.pass` declares the
|
|
13
|
+
* box/stroke/range pixel uniforms (sized to `targetMinDimPx`) and the
|
|
14
|
+
* `binding.samplers` `outline`/`on` source declares the baked-SDF aux texture
|
|
15
|
+
* (geometry seam). The only hand-written web sources left are this
|
|
16
|
+
* registration shim (the fail moods are web-runtime-only) and the shader.
|
|
17
|
+
*/
|
|
18
|
+
import { FAIL_FRAGMENT_SRC, FAIL_VERTEX_SRC } from "./fail-shader.js";
|
|
19
|
+
import { registerDopeEffect, registerMood, parseDope, } from "@dopaminefx/core";
|
|
20
|
+
import doc from "./fail.dope.json";
|
|
21
|
+
const DOPE = parseDope(doc);
|
|
22
|
+
/** Register the fail-appropriate moods so they light up the registry (energy). */
|
|
23
|
+
registerMood("try-again", { hueCenter: 70, hueRange: 40, lightness: 0.78, chroma: 0.13, energy: 0.2 });
|
|
24
|
+
registerMood("error", { hueCenter: 40, hueRange: 36, lightness: 0.72, chroma: 0.17, energy: 0.55 });
|
|
25
|
+
registerMood("denied", { hueCenter: 22, hueRange: 30, lightness: 0.66, chroma: 0.21, energy: 1.0 });
|
|
26
|
+
// The whole factory (resolve / frame / pass uniforms / SDF aux texture /
|
|
27
|
+
// shadow / bindings / program registration) is data: fail.dope.json
|
|
28
|
+
// interpreted by the core backbone.
|
|
29
|
+
export const fail = registerDopeEffect(DOPE, {
|
|
30
|
+
vertex: FAIL_VERTEX_SRC,
|
|
31
|
+
fragment: FAIL_FRAGMENT_SRC,
|
|
32
|
+
});
|
|
33
|
+
export default fail;
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,SAAS,GAIV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,GAAG,MAAM,kBAAkB,CAAC;AAEnC,MAAM,IAAI,GAAG,SAAS,CAAC,GAAa,CAAC,CAAC;AAEtC,kFAAkF;AAClF,YAAY,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;AACvG,YAAY,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AACpG,YAAY,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;AAapG,yEAAyE;AACzE,oEAAoE;AACpE,oCAAoC;AACpC,MAAM,CAAC,MAAM,IAAI,GAAG,kBAAkB,CAAC,IAAI,EAAE;IAC3C,MAAM,EAAE,eAAe;IACvB,QAAQ,EAAE,iBAAiB;CAC5B,CAA2D,CAAC;AAE7D,eAAe,IAAI,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dopaminefx/effect-fail",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Fail — a stamped-cross error/failure effect for Dopamine.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"dopamine-effect"
|
|
7
|
+
],
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"module": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"src"
|
|
21
|
+
],
|
|
22
|
+
"sideEffects": [
|
|
23
|
+
"./src/index.ts",
|
|
24
|
+
"./dist/index.js"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc -p tsconfig.json"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@dopaminefx/core": "^0.1.0"
|
|
31
|
+
},
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"author": "10in30",
|
|
34
|
+
"homepage": "https://github.com/10in30/dopamine#readme",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/10in30/dopamine.git",
|
|
38
|
+
"directory": "effects/fail/web"
|
|
39
|
+
},
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/10in30/dopamine/issues"
|
|
42
|
+
},
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
}
|
|
46
|
+
}
|