aispritejs 0.5.6 → 0.5.7
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 +3 -3
- package/README_ZHTW.md +3 -3
- package/dist/atlas/index.cjs +24 -470
- package/dist/atlas/index.cjs.map +1 -1
- package/dist/atlas/index.js +13 -459
- package/dist/atlas/index.js.map +1 -1
- package/dist/chunk-F4MDNT4Y.js +488 -0
- package/dist/chunk-F4MDNT4Y.js.map +1 -0
- package/dist/chunk-Y663UAIF.cjs +495 -0
- package/dist/chunk-Y663UAIF.cjs.map +1 -0
- package/dist/index.cjs +21 -462
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -461
- package/dist/index.js.map +1 -1
- package/dist/pixi/index.cjs +3 -461
- package/dist/pixi/index.cjs.map +1 -1
- package/dist/pixi/index.js +2 -460
- package/dist/pixi/index.js.map +1 -1
- package/llms-full.txt +82 -3
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
Part of the **ai\*js** family: zero cross-package dependencies, framework-agnostic core, AI-readable docs.
|
|
14
14
|
|
|
15
|
+
> **Status: 0.5.7 — aligned with the ai\*js family version line.** Renderer-agnostic core plus `/pixi`, `/atlas`, `/schema` subpaths; hardened atlas/graph validation. See [CHANGELOG.md](CHANGELOG.md) for history.
|
|
16
|
+
|
|
15
17
|
## Why aispritejs
|
|
16
18
|
|
|
17
19
|
- **Input-driven, not name-driven.** You set parameters (`speed=4`, `isGrounded=false`, `fireTrigger("jump")`), not animation names. Visual transitions live in data, decoupled from game code.
|
|
@@ -256,9 +258,7 @@ pnpm example:explosion # 6-frame play-once FX via the /pixi adapter
|
|
|
256
258
|
|
|
257
259
|
## Status
|
|
258
260
|
|
|
259
|
-
**
|
|
260
|
-
|
|
261
|
-
`aispritejs` is the newest package in the **ai\*js** family and follows its **own independent version line** — the `0.1.x` series reflects this package's own maturation, not alignment with any sibling's version number. Low usage in a given game (e.g. one built on static sprites) is expected, not a defect.
|
|
261
|
+
**Aligned with the ai\*js family version line.** The package version is synchronised with the shared family version (`0.5.x` — the banner above and [CHANGELOG.md](CHANGELOG.md) carry the exact release). All four roadmap modules are live: the renderer-agnostic core (`.`), the PixiJS v8 adapter (`aispritejs/pixi`), the atlas parser (`aispritejs/atlas`), and the JSON Schema (`aispritejs/schema`). Prior hardening waves delivered compile-time rejection of non-finite `speed` / `duration` / `defaultFrameDuration`, runtime clamping of non-finite or non-positive `dt` to `0` in `update()`, and named-error coverage for hostile atlas shapes. Zero runtime dependencies; the root import graph contains no `pixi.js`; `pixi.js` is an optional, type-only peer used only by the `/pixi` subpath.
|
|
262
262
|
|
|
263
263
|
## Roadmap
|
|
264
264
|
|
package/README_ZHTW.md
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
|
|
13
13
|
屬於 **ai\*js** 家族:零跨套件相依、核心與框架無關、AI 可讀的文件。
|
|
14
14
|
|
|
15
|
+
> **狀態:0.5.7 — 已對齊 ai\*js 家族版本線。** Renderer-agnostic core 加上 `/pixi`、`/atlas`、`/schema` subpath;atlas/graph 驗證已強化。歷史見 [CHANGELOG.md](CHANGELOG.md)。
|
|
16
|
+
|
|
15
17
|
## 為什麼用 aispritejs
|
|
16
18
|
|
|
17
19
|
- **輸入驅動,而非名稱驅動。** 你設定參數(`speed=4`、`isGrounded=false`、`fireTrigger("jump")`),而不是動畫名稱。視覺轉移存在於資料中,與遊戲程式解耦。
|
|
@@ -253,9 +255,7 @@ pnpm example:platformer
|
|
|
253
255
|
|
|
254
256
|
## 狀態
|
|
255
257
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
`aispritejs` 是 **ai\*js** 家族中最新的套件,採用**自己獨立的版本線** —— `0.1.x` 系列反映的是這個套件自身的成熟度,而非與任何手足套件的版本號對齊。在某個遊戲裡使用率低(例如以靜態 sprite 為主的遊戲)是正常現象,並非缺陷。
|
|
258
|
+
**已對齊 ai\*js 家族版本線。** 套件版本與家族共享版本(`0.5.x`)同步——精確版次見上方 banner 與 [CHANGELOG.md](CHANGELOG.md)。所有四個 roadmap 模組均已上線:與渲染器無關的核心(`.`)、PixiJS v8 轉接器(`aispritejs/pixi`)、atlas parser(`aispritejs/atlas`)、JSON Schema(`aispritejs/schema`)。先前強化波次已完成:在編譯期拒絕非有限的 `speed` / `duration` / `defaultFrameDuration`、在 `update()` 執行期把非有限或非正值的 `dt` 夾到 `0`,以及惡意 atlas 格式的具名錯誤覆蓋。零執行期相依;根 import 圖不含 `pixi.js`;`pixi.js` 是選用、type-only 的 peer,僅 `/pixi` 子路徑使用。
|
|
259
259
|
|
|
260
260
|
## Roadmap
|
|
261
261
|
|
package/dist/atlas/index.cjs
CHANGED
|
@@ -1,464 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
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 chunkY663UAIF_cjs = require('../chunk-Y663UAIF.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 chunkY663UAIF_cjs.isObject(states) && typeof states.initial === "string" && chunkY663UAIF_cjs.isObject(states.definitions);
|
|
472
14
|
}
|
|
473
15
|
function assertAnimations(value) {
|
|
474
|
-
if (!isObject(value)) {
|
|
16
|
+
if (!chunkY663UAIF_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 (!chunkY663UAIF_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 && !chunkY663UAIF_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 (chunkY663UAIF_cjs.isObject(frames)) {
|
|
494
36
|
for (const [key, entry] of Object.entries(frames)) {
|
|
495
|
-
if (!isObject(entry)) {
|
|
37
|
+
if (!chunkY663UAIF_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 (!chunkY663UAIF_cjs.isObject(atlas.inputs) || !chunkY663UAIF_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 (!chunkY663UAIF_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 (!chunkY663UAIF_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 (!chunkY663UAIF_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 (!chunkY663UAIF_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 chunkY663UAIF_cjs.createSpriteAnimator(parseAtlas(atlas, control));
|
|
555
109
|
}
|
|
556
110
|
|
|
557
111
|
exports.InvalidAtlasError = InvalidAtlasError;
|