aispritejs 0.5.6 → 0.5.8

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.
@@ -1,464 +1,6 @@
1
1
  'use strict';
2
2
 
3
- // src/sprite/errors.ts
4
- var SpriteAnimatorDisposedError = class extends Error {
5
- constructor() {
6
- super("aispritejs: animator has been disposed; this operation is not allowed");
7
- this.name = "SpriteAnimatorDisposedError";
8
- }
9
- };
10
- var InvalidGraphError = class extends Error {
11
- constructor(message) {
12
- super(`aispritejs: invalid graph \u2014 ${message}`);
13
- this.name = "InvalidGraphError";
14
- }
15
- };
16
- var UnknownInputError = class extends Error {
17
- input;
18
- constructor(input) {
19
- super(`aispritejs: unknown input "${input}"; declare it in the graph's inputs block`);
20
- this.name = "UnknownInputError";
21
- this.input = input;
22
- }
23
- };
24
- var InputTypeError = class extends Error {
25
- input;
26
- constructor(input, message) {
27
- super(`aispritejs: input "${input}" \u2014 ${message}`);
28
- this.name = "InputTypeError";
29
- this.input = input;
30
- }
31
- };
32
-
33
- // src/sprite/compile.ts
34
- var DEFAULT_FRAME_DURATION = 100;
35
- function isObject(v) {
36
- return typeof v === "object" && v !== null && !Array.isArray(v);
37
- }
38
- function compileGraph(graph) {
39
- const stateEntries = Object.entries(graph.states);
40
- if (stateEntries.length === 0) {
41
- throw new InvalidGraphError("states must declare at least one state");
42
- }
43
- for (const [name, def] of Object.entries(graph.inputs)) {
44
- if (def.type !== "number" && def.type !== "boolean" && def.type !== "trigger") {
45
- throw new InvalidGraphError(
46
- `input "${name}" has unknown type "${def.type}"`
47
- );
48
- }
49
- }
50
- const defaultDuration = graph.defaultFrameDuration ?? DEFAULT_FRAME_DURATION;
51
- if (!Number.isFinite(defaultDuration) || defaultDuration <= 0) {
52
- throw new InvalidGraphError(
53
- `defaultFrameDuration must be a finite number > 0, got ${defaultDuration}`
54
- );
55
- }
56
- if (graph.frames) {
57
- for (const [key, timing] of Object.entries(graph.frames)) {
58
- if (!isObject(timing)) {
59
- throw new InvalidGraphError(`frame "${key}" timing must be an object`);
60
- }
61
- if (timing.duration !== void 0 && (!Number.isFinite(timing.duration) || timing.duration <= 0)) {
62
- throw new InvalidGraphError(
63
- `frame "${key}" duration must be a finite number > 0, got ${timing.duration}`
64
- );
65
- }
66
- }
67
- }
68
- const initial = graph.initial ?? stateEntries[0][0];
69
- if (!Object.hasOwn(graph.states, initial)) {
70
- throw new InvalidGraphError(`initial state "${initial}" is not declared`);
71
- }
72
- const states = /* @__PURE__ */ new Map();
73
- for (const [name, st] of stateEntries) {
74
- const frameKeys = graph.animations[st.animation];
75
- if (frameKeys === void 0 || !Object.hasOwn(graph.animations, st.animation)) {
76
- throw new InvalidGraphError(`state "${name}" references unknown animation "${st.animation}"`);
77
- }
78
- if (frameKeys.length === 0) {
79
- throw new InvalidGraphError(`animation "${st.animation}" (state "${name}") has no frames`);
80
- }
81
- const speed = st.speed ?? 1;
82
- if (!Number.isFinite(speed) || speed <= 0) {
83
- throw new InvalidGraphError(
84
- `state "${name}" speed must be a finite number > 0, got ${speed}`
85
- );
86
- }
87
- const loop = st.loop === true;
88
- if (loop && st.onEnd !== void 0) {
89
- throw new InvalidGraphError(
90
- `state "${name}" loops, so onEnd "${st.onEnd}" would never fire; set loop:false or drop onEnd`
91
- );
92
- }
93
- if (st.onEnd !== void 0 && !Object.hasOwn(graph.states, st.onEnd)) {
94
- throw new InvalidGraphError(`state "${name}" onEnd target "${st.onEnd}" is not declared`);
95
- }
96
- const cumulative = [];
97
- let running = 0;
98
- for (const key of frameKeys) {
99
- running += graph.frames?.[key]?.duration ?? defaultDuration;
100
- cumulative.push(running);
101
- }
102
- states.set(name, {
103
- name,
104
- animation: st.animation,
105
- loop,
106
- speed,
107
- onEnd: st.onEnd,
108
- frameKeys,
109
- cumulative,
110
- total: running
111
- });
112
- }
113
- const compiled = [];
114
- graph.transitions.forEach((t, order) => {
115
- if (!isObject(t)) {
116
- throw new InvalidGraphError(`transition #${order} must be an object`);
117
- }
118
- if (t.when !== void 0 && !Array.isArray(t.when)) {
119
- throw new InvalidGraphError(`transition #${order} "when" must be an array`);
120
- }
121
- if (t.from !== "*" && !Object.hasOwn(graph.states, t.from)) {
122
- throw new InvalidGraphError(`transition #${order} from "${t.from}" is not a declared state`);
123
- }
124
- if (!Object.hasOwn(graph.states, t.to)) {
125
- throw new InvalidGraphError(`transition #${order} to "${t.to}" is not a declared state`);
126
- }
127
- const conditions = [];
128
- const triggers = [];
129
- for (const c of t.when ?? []) {
130
- const def = graph.inputs[c.input];
131
- if (def === void 0 || !Object.hasOwn(graph.inputs, c.input)) {
132
- throw new InvalidGraphError(
133
- `transition #${order} condition references unknown input "${c.input}"`
134
- );
135
- }
136
- compileCondition(order, c.input, c.op, c.value, def.type, conditions, triggers);
137
- }
138
- compiled.push({
139
- from: t.from,
140
- to: t.to,
141
- priority: t.priority ?? 0,
142
- order,
143
- conditions,
144
- triggers
145
- });
146
- });
147
- const candidatesByState = /* @__PURE__ */ new Map();
148
- for (const [name] of stateEntries) {
149
- const list = compiled.filter((t) => t.from === name || t.from === "*");
150
- list.sort((a, b) => b.priority - a.priority || a.order - b.order);
151
- candidatesByState.set(name, list);
152
- }
153
- return { initial, states, candidatesByState };
154
- }
155
- function compileCondition(order, input, op, value, kind, out, triggers) {
156
- switch (op) {
157
- case "Trigger": {
158
- if (kind !== "trigger") {
159
- throw new InvalidGraphError(
160
- `transition #${order}: op Trigger requires a trigger input, but "${input}" is ${kind}`
161
- );
162
- }
163
- if (value !== void 0) {
164
- throw new InvalidGraphError(
165
- `transition #${order}: Trigger condition on "${input}" must not carry a value`
166
- );
167
- }
168
- out.push((s) => s.isPending(input));
169
- triggers.push(input);
170
- return;
171
- }
172
- case "GreaterThan":
173
- case "LessThan": {
174
- if (kind !== "number") {
175
- throw new InvalidGraphError(
176
- `transition #${order}: op ${op} requires a number input, but "${input}" is ${kind}`
177
- );
178
- }
179
- if (typeof value !== "number") {
180
- throw new InvalidGraphError(
181
- `transition #${order}: op ${op} on "${input}" needs a numeric value`
182
- );
183
- }
184
- const v = value;
185
- out.push(
186
- op === "GreaterThan" ? (s) => s.readNumber(input) > v : (s) => s.readNumber(input) < v
187
- );
188
- return;
189
- }
190
- case "Equals":
191
- case "NotEquals": {
192
- if (kind === "trigger") {
193
- throw new InvalidGraphError(
194
- `transition #${order}: op ${op} cannot apply to trigger input "${input}"`
195
- );
196
- }
197
- if (kind === "number") {
198
- if (typeof value !== "number") {
199
- throw new InvalidGraphError(
200
- `transition #${order}: op ${op} on number input "${input}" needs a numeric value`
201
- );
202
- }
203
- const v2 = value;
204
- out.push(
205
- op === "Equals" ? (s) => s.readNumber(input) === v2 : (s) => s.readNumber(input) !== v2
206
- );
207
- return;
208
- }
209
- if (typeof value !== "boolean") {
210
- throw new InvalidGraphError(
211
- `transition #${order}: op ${op} on boolean input "${input}" needs a boolean value`
212
- );
213
- }
214
- const v = value;
215
- out.push(
216
- op === "Equals" ? (s) => s.readBoolean(input) === v : (s) => s.readBoolean(input) !== v
217
- );
218
- return;
219
- }
220
- default:
221
- throw new InvalidGraphError(`transition #${order}: unknown operator "${op}"`);
222
- }
223
- }
224
-
225
- // src/sprite/emitter.ts
226
- function createSignal() {
227
- const listeners = /* @__PURE__ */ new Set();
228
- function on(handler, options) {
229
- if (options?.signal?.aborted) return () => {
230
- };
231
- let detachAbort;
232
- const cleanup = () => {
233
- listeners.delete(wrapped);
234
- if (detachAbort) {
235
- detachAbort();
236
- detachAbort = void 0;
237
- }
238
- };
239
- let wrapped = handler;
240
- if (options?.once) {
241
- wrapped = (payload) => {
242
- cleanup();
243
- handler(payload);
244
- };
245
- }
246
- listeners.add(wrapped);
247
- const sig = options?.signal;
248
- if (sig) {
249
- const onAbort = () => cleanup();
250
- sig.addEventListener("abort", onAbort, { once: true });
251
- detachAbort = () => sig.removeEventListener("abort", onAbort);
252
- }
253
- return cleanup;
254
- }
255
- function emit(payload) {
256
- if (listeners.size === 0) return;
257
- for (const fn of [...listeners]) fn(payload);
258
- }
259
- function clear() {
260
- listeners.clear();
261
- }
262
- return { on, emit, clear };
263
- }
264
-
265
- // src/sprite/inputs.ts
266
- function createInputStore(inputs) {
267
- const kinds = /* @__PURE__ */ new Map();
268
- const numberDefaults = /* @__PURE__ */ new Map();
269
- const booleanDefaults = /* @__PURE__ */ new Map();
270
- const numbers = /* @__PURE__ */ new Map();
271
- const booleans = /* @__PURE__ */ new Map();
272
- const triggers = /* @__PURE__ */ new Map();
273
- for (const [name, def] of Object.entries(inputs)) {
274
- kinds.set(name, def.type);
275
- if (def.type === "number") {
276
- const d = def.default ?? 0;
277
- numberDefaults.set(name, d);
278
- numbers.set(name, d);
279
- } else if (def.type === "boolean") {
280
- const d = def.default ?? false;
281
- booleanDefaults.set(name, d);
282
- booleans.set(name, d);
283
- } else {
284
- triggers.set(name, false);
285
- }
286
- }
287
- function setInput(name, value) {
288
- const kind = kinds.get(name);
289
- if (kind === void 0) throw new UnknownInputError(name);
290
- if (kind === "trigger") {
291
- throw new InputTypeError(name, "is a Trigger; use fireTrigger()");
292
- }
293
- if (kind === "number") {
294
- if (typeof value !== "number") {
295
- throw new InputTypeError(name, `expects a number, received ${typeof value}`);
296
- }
297
- if (Number.isNaN(value)) {
298
- throw new InputTypeError(name, "cannot be set to NaN");
299
- }
300
- numbers.set(name, value);
301
- return;
302
- }
303
- if (typeof value !== "boolean") {
304
- throw new InputTypeError(name, `expects a boolean, received ${typeof value}`);
305
- }
306
- booleans.set(name, value);
307
- }
308
- function fireTrigger(name) {
309
- const kind = kinds.get(name);
310
- if (kind === void 0) throw new UnknownInputError(name);
311
- if (kind !== "trigger") {
312
- throw new InputTypeError(name, "is not a Trigger; use setInput()");
313
- }
314
- triggers.set(name, true);
315
- }
316
- return {
317
- setInput,
318
- fireTrigger,
319
- // `!` is sound: every declared input is seeded at construction and the
320
- // compiler validates that conditions only read declared inputs of the
321
- // matching kind, so these reads always hit a present entry.
322
- readNumber: (name) => numbers.get(name),
323
- readBoolean: (name) => booleans.get(name),
324
- isPending: (name) => triggers.get(name) === true,
325
- consume: (name) => {
326
- triggers.set(name, false);
327
- },
328
- reset: () => {
329
- for (const [name, d] of numberDefaults) numbers.set(name, d);
330
- for (const [name, d] of booleanDefaults) booleans.set(name, d);
331
- for (const name of triggers.keys()) triggers.set(name, false);
332
- }
333
- };
334
- }
335
-
336
- // src/sprite/machine.ts
337
- var NO_TRIGGERS = [];
338
- function createSpriteAnimator(graph) {
339
- const compiled = compileGraph(graph);
340
- const store = createInputStore(graph.inputs);
341
- const stateChange = createSignal();
342
- const complete = createSignal();
343
- let current = mustState(compiled.initial);
344
- let elapsed = 0;
345
- let completed = false;
346
- let activeFrameIndex = 0;
347
- let activeFrameKey = current.frameKeys[0];
348
- let disposed = false;
349
- function mustState(name) {
350
- return compiled.states.get(name);
351
- }
352
- function enter(to, consume) {
353
- const from = current.name;
354
- for (let i = 0; i < consume.length; i++) {
355
- store.consume(consume[i]);
356
- }
357
- current = mustState(to);
358
- elapsed = 0;
359
- completed = false;
360
- activeFrameIndex = 0;
361
- activeFrameKey = current.frameKeys[0];
362
- if (to !== from) stateChange.emit({ to, from });
363
- }
364
- function resolve() {
365
- const list = compiled.candidatesByState.get(current.name);
366
- for (let i = 0; i < list.length; i++) {
367
- const t = list[i];
368
- let ok = true;
369
- const conds = t.conditions;
370
- for (let j = 0; j < conds.length; j++) {
371
- if (!conds[j](store)) {
372
- ok = false;
373
- break;
374
- }
375
- }
376
- if (!ok) continue;
377
- if (t.to === current.name && t.triggers.length === 0) continue;
378
- return { to: t.to, triggers: t.triggers };
379
- }
380
- return void 0;
381
- }
382
- function update(deltaMs) {
383
- if (disposed) throw new SpriteAnimatorDisposedError();
384
- elapsed += (Number.isFinite(deltaMs) && deltaMs > 0 ? deltaMs : 0) * current.speed;
385
- const chosen = resolve();
386
- if (chosen) {
387
- enter(chosen.to, chosen.triggers);
388
- return;
389
- }
390
- const cs = current;
391
- const n = cs.frameKeys.length;
392
- let ended = false;
393
- if (!cs.loop && elapsed >= cs.total) {
394
- activeFrameIndex = n - 1;
395
- ended = true;
396
- } else {
397
- const t = cs.loop ? elapsed % cs.total : elapsed;
398
- let i = 0;
399
- while (i < n - 1 && t >= cs.cumulative[i]) i++;
400
- activeFrameIndex = i;
401
- }
402
- activeFrameKey = cs.frameKeys[activeFrameIndex];
403
- if (ended && !completed) {
404
- completed = true;
405
- complete.emit(cs.name);
406
- if (cs.onEnd !== void 0) enter(cs.onEnd, NO_TRIGGERS);
407
- }
408
- }
409
- function reset() {
410
- if (disposed) throw new SpriteAnimatorDisposedError();
411
- const from = current.name;
412
- store.reset();
413
- current = mustState(compiled.initial);
414
- elapsed = 0;
415
- completed = false;
416
- activeFrameIndex = 0;
417
- activeFrameKey = current.frameKeys[0];
418
- if (from !== compiled.initial) stateChange.emit({ to: compiled.initial, from });
419
- }
420
- function dispose() {
421
- if (disposed) return;
422
- disposed = true;
423
- stateChange.clear();
424
- complete.clear();
425
- }
426
- return {
427
- setInput(name, value) {
428
- if (disposed) throw new SpriteAnimatorDisposedError();
429
- store.setInput(name, value);
430
- },
431
- fireTrigger(name) {
432
- if (disposed) throw new SpriteAnimatorDisposedError();
433
- store.fireTrigger(name);
434
- },
435
- update,
436
- reset,
437
- dispose,
438
- onStateChange(handler, options) {
439
- if (disposed) return () => {
440
- };
441
- return stateChange.on((p) => handler(p.to, p.from), options);
442
- },
443
- onComplete(handler, options) {
444
- if (disposed) return () => {
445
- };
446
- return complete.on(handler, options);
447
- },
448
- get activeState() {
449
- return current.name;
450
- },
451
- get activeFrameKey() {
452
- return activeFrameKey;
453
- },
454
- get activeFrameIndex() {
455
- return activeFrameIndex;
456
- },
457
- get disposed() {
458
- return disposed;
459
- }
460
- };
461
- }
3
+ var chunkQF5N7LOI_cjs = require('../chunk-QF5N7LOI.cjs');
462
4
 
463
5
  // src/atlas/parse.ts
464
6
  var InvalidAtlasError = class extends Error {
@@ -468,10 +10,10 @@ var InvalidAtlasError = class extends Error {
468
10
  }
469
11
  };
470
12
  function isForeignStates(states) {
471
- return isObject(states) && typeof states.initial === "string" && isObject(states.definitions);
13
+ return chunkQF5N7LOI_cjs.isObject(states) && typeof states.initial === "string" && chunkQF5N7LOI_cjs.isObject(states.definitions);
472
14
  }
473
15
  function assertAnimations(value) {
474
- if (!isObject(value)) {
16
+ if (!chunkQF5N7LOI_cjs.isObject(value)) {
475
17
  throw new InvalidAtlasError("`animations` must be an object of frame-key lists");
476
18
  }
477
19
  for (const [name, list] of Object.entries(value)) {
@@ -482,17 +24,17 @@ function assertAnimations(value) {
482
24
  return value;
483
25
  }
484
26
  function parseAtlas(atlas, control) {
485
- if (!isObject(atlas)) {
27
+ if (!chunkQF5N7LOI_cjs.isObject(atlas)) {
486
28
  throw new InvalidAtlasError("atlas must be an object");
487
29
  }
488
30
  const animations = assertAnimations(atlas.animations);
489
31
  const frames = atlas.frames;
490
- if (frames !== void 0 && !isObject(frames)) {
32
+ if (frames !== void 0 && !chunkQF5N7LOI_cjs.isObject(frames)) {
491
33
  throw new InvalidAtlasError("`frames`, if present, must be an object keyed by frame key");
492
34
  }
493
- if (isObject(frames)) {
35
+ if (chunkQF5N7LOI_cjs.isObject(frames)) {
494
36
  for (const [key, entry] of Object.entries(frames)) {
495
- if (!isObject(entry)) {
37
+ if (!chunkQF5N7LOI_cjs.isObject(entry)) {
496
38
  const actualType = entry === null ? "null" : Array.isArray(entry) ? "array" : typeof entry;
497
39
  throw new InvalidAtlasError(`frame entry "${key}" must be an object, got ${actualType}`);
498
40
  }
@@ -507,19 +49,19 @@ function parseAtlas(atlas, control) {
507
49
  "atlas `states` is event-driven (has `initial`/`definitions`); pass an aispritejs control block as the second argument"
508
50
  );
509
51
  }
510
- if (!isObject(atlas.inputs) || !isObject(atlas.states) || !Array.isArray(atlas.transitions)) {
52
+ if (!chunkQF5N7LOI_cjs.isObject(atlas.inputs) || !chunkQF5N7LOI_cjs.isObject(atlas.states) || !Array.isArray(atlas.transitions)) {
511
53
  throw new InvalidAtlasError(
512
54
  "atlas has no aispritejs control block (inputs/states/transitions); pass one as the second argument"
513
55
  );
514
56
  }
515
57
  for (const [key, val] of Object.entries(atlas.inputs)) {
516
- if (!isObject(val)) {
58
+ if (!chunkQF5N7LOI_cjs.isObject(val)) {
517
59
  const actualType = val === null ? "null" : Array.isArray(val) ? "array" : typeof val;
518
60
  throw new InvalidAtlasError(`input entry "${key}" must be an object, got ${actualType}`);
519
61
  }
520
62
  }
521
63
  for (const [key, val] of Object.entries(atlas.states)) {
522
- if (!isObject(val)) {
64
+ if (!chunkQF5N7LOI_cjs.isObject(val)) {
523
65
  const actualType = val === null ? "null" : Array.isArray(val) ? "array" : typeof val;
524
66
  throw new InvalidAtlasError(`state entry "${key}" must be an object, got ${actualType}`);
525
67
  }
@@ -527,10 +69,22 @@ function parseAtlas(atlas, control) {
527
69
  const rawTransitions = atlas.transitions;
528
70
  for (let i = 0; i < rawTransitions.length; i++) {
529
71
  const entry = rawTransitions[i];
530
- if (!isObject(entry)) {
72
+ if (!chunkQF5N7LOI_cjs.isObject(entry)) {
531
73
  const actualType = entry === null ? "null" : Array.isArray(entry) ? "array" : typeof entry;
532
74
  throw new InvalidAtlasError(`transitions[${i}] must be an object, got ${actualType}`);
533
75
  }
76
+ if (Array.isArray(entry.when)) {
77
+ const rawWhen = entry.when;
78
+ for (let j = 0; j < rawWhen.length; j++) {
79
+ const cond = rawWhen[j];
80
+ if (!chunkQF5N7LOI_cjs.isObject(cond)) {
81
+ const actualType = cond === null ? "null" : Array.isArray(cond) ? "array" : typeof cond;
82
+ throw new InvalidAtlasError(
83
+ `transitions[${i}].when[${j}] must be an object, got ${actualType}`
84
+ );
85
+ }
86
+ }
87
+ }
534
88
  }
535
89
  resolved = {
536
90
  inputs: atlas.inputs,
@@ -551,7 +105,7 @@ function parseAtlas(atlas, control) {
551
105
  };
552
106
  }
553
107
  function loadAtlas(atlas, control) {
554
- return createSpriteAnimator(parseAtlas(atlas, control));
108
+ return chunkQF5N7LOI_cjs.createSpriteAnimator(parseAtlas(atlas, control));
555
109
  }
556
110
 
557
111
  exports.InvalidAtlasError = InvalidAtlasError;