@zylem/game-lib 0.6.2 → 0.6.4

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.
Files changed (82) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +9 -16
  3. package/dist/actions.d.ts +30 -21
  4. package/dist/actions.js +793 -146
  5. package/dist/actions.js.map +1 -1
  6. package/dist/behavior/jumper-2d.d.ts +114 -0
  7. package/dist/behavior/jumper-2d.js +711 -0
  8. package/dist/behavior/jumper-2d.js.map +1 -0
  9. package/dist/behavior/platformer-3d.d.ts +296 -0
  10. package/dist/behavior/platformer-3d.js +761 -0
  11. package/dist/behavior/platformer-3d.js.map +1 -0
  12. package/dist/behavior/ricochet-2d.d.ts +275 -0
  13. package/dist/behavior/ricochet-2d.js +425 -0
  14. package/dist/behavior/ricochet-2d.js.map +1 -0
  15. package/dist/behavior/ricochet-3d.d.ts +117 -0
  16. package/dist/behavior/ricochet-3d.js +443 -0
  17. package/dist/behavior/ricochet-3d.js.map +1 -0
  18. package/dist/behavior/screen-visibility.d.ts +79 -0
  19. package/dist/behavior/screen-visibility.js +358 -0
  20. package/dist/behavior/screen-visibility.js.map +1 -0
  21. package/dist/behavior/screen-wrap.d.ts +87 -0
  22. package/dist/behavior/screen-wrap.js +246 -0
  23. package/dist/behavior/screen-wrap.js.map +1 -0
  24. package/dist/behavior/shooter-2d.d.ts +79 -0
  25. package/dist/behavior/shooter-2d.js +180 -0
  26. package/dist/behavior/shooter-2d.js.map +1 -0
  27. package/dist/behavior/thruster.d.ts +11 -0
  28. package/dist/behavior/thruster.js +292 -0
  29. package/dist/behavior/thruster.js.map +1 -0
  30. package/dist/behavior/top-down-movement.d.ts +56 -0
  31. package/dist/behavior/top-down-movement.js +125 -0
  32. package/dist/behavior/top-down-movement.js.map +1 -0
  33. package/dist/behavior/world-boundary-2d.d.ts +142 -0
  34. package/dist/behavior/world-boundary-2d.js +235 -0
  35. package/dist/behavior/world-boundary-2d.js.map +1 -0
  36. package/dist/behavior/world-boundary-3d.d.ts +76 -0
  37. package/dist/behavior/world-boundary-3d.js +274 -0
  38. package/dist/behavior/world-boundary-3d.js.map +1 -0
  39. package/dist/behavior-descriptor-BXnVR8Ki.d.ts +159 -0
  40. package/dist/{blueprints-Cq3Ko6_G.d.ts → blueprints-DmbK2dki.d.ts} +2 -2
  41. package/dist/camera-4XO5gbQH.d.ts +905 -0
  42. package/dist/camera.d.ts +3 -2
  43. package/dist/camera.js +1653 -377
  44. package/dist/camera.js.map +1 -1
  45. package/dist/composition-BASvMKrW.d.ts +218 -0
  46. package/dist/{core-bO8TzV7u.d.ts → core-CARRaS55.d.ts} +110 -69
  47. package/dist/core.d.ts +11 -6
  48. package/dist/core.js +10766 -5626
  49. package/dist/core.js.map +1 -1
  50. package/dist/{entities-DvByhMGU.d.ts → entities-ChFirVL9.d.ts} +133 -29
  51. package/dist/entities.d.ts +5 -3
  52. package/dist/entities.js +4679 -3202
  53. package/dist/entities.js.map +1 -1
  54. package/dist/entity-vj-HTjzU.d.ts +1169 -0
  55. package/dist/global-change-2JvMaz44.d.ts +25 -0
  56. package/dist/main.d.ts +1118 -16
  57. package/dist/main.js +17538 -8499
  58. package/dist/main.js.map +1 -1
  59. package/dist/physics-pose-DCc4oE44.d.ts +25 -0
  60. package/dist/physics-protocol-BDD3P5W2.d.ts +200 -0
  61. package/dist/physics-worker.d.ts +21 -0
  62. package/dist/physics-worker.js +306 -0
  63. package/dist/physics-worker.js.map +1 -0
  64. package/dist/physics.d.ts +205 -0
  65. package/dist/physics.js +577 -0
  66. package/dist/physics.js.map +1 -0
  67. package/dist/stage-types-C19IhuzA.d.ts +731 -0
  68. package/dist/stage.d.ts +11 -7
  69. package/dist/stage.js +8024 -3852
  70. package/dist/stage.js.map +1 -1
  71. package/dist/sync-state-machine-CZyspBpj.d.ts +16 -0
  72. package/dist/thruster-23lzoPZd.d.ts +180 -0
  73. package/dist/world-DfgxoNMt.d.ts +105 -0
  74. package/package.json +53 -13
  75. package/dist/behaviors.d.ts +0 -854
  76. package/dist/behaviors.js +0 -1209
  77. package/dist/behaviors.js.map +0 -1
  78. package/dist/camera-CeJPAgGg.d.ts +0 -116
  79. package/dist/moveable-B_vyA6cw.d.ts +0 -67
  80. package/dist/stage-types-Bd-KtcYT.d.ts +0 -375
  81. package/dist/transformable-CUhvyuYO.d.ts +0 -67
  82. package/dist/world-C8tQ7Plj.d.ts +0 -774
package/dist/actions.js CHANGED
@@ -1,113 +1,616 @@
1
- var __defProp = Object.defineProperty;
2
- var __export = (target, all) => {
3
- for (var name in all)
4
- __defProp(target, name, { get: all[name], enumerable: true });
1
+ // src/lib/actions/action.ts
2
+ var BaseAction = class {
3
+ duration;
4
+ done = false;
5
+ persistent = false;
6
+ elapsed = 0;
7
+ /** @param durationMs Duration in milliseconds */
8
+ constructor(durationMs) {
9
+ this.duration = durationMs / 1e3;
10
+ }
11
+ tick(entity, delta) {
12
+ if (this.done) return;
13
+ this.elapsed += delta;
14
+ const progress = this.duration > 0 ? Math.min(this.elapsed / this.duration, 1) : 1;
15
+ this.onTick(entity, delta, progress);
16
+ if (this.elapsed >= this.duration) {
17
+ this.done = true;
18
+ }
19
+ }
20
+ reset() {
21
+ this.elapsed = 0;
22
+ this.done = false;
23
+ }
5
24
  };
6
25
 
7
- // src/lib/actions/behaviors/actions.ts
8
- var actions_exports = {};
9
- __export(actions_exports, {
10
- actionOnPress: () => actionOnPress,
11
- actionOnRelease: () => actionOnRelease,
12
- actionWithCooldown: () => actionWithCooldown,
13
- actionWithThrottle: () => actionWithThrottle,
14
- wait: () => wait
15
- });
16
- function wait(delay, callback) {
17
- setTimeout(callback, delay);
18
- }
19
- var actionOnPress = /* @__PURE__ */ (() => {
20
- let buttonPressed = false;
21
- return (isPressed, callback) => {
22
- if (isPressed && !buttonPressed) {
23
- buttonPressed = true;
24
- callback();
25
- } else if (!isPressed) {
26
- buttonPressed = false;
27
- }
26
+ // src/lib/actions/capabilities/velocity-intents.ts
27
+ function setVelocityIntent(store, sourceId, vector, options = {}) {
28
+ const prev = store.velocityChannels[sourceId];
29
+ const mode = options.mode ?? prev?.mode ?? "replace";
30
+ const priority = options.priority ?? prev?.priority ?? 0;
31
+ const isAdditiveMerge = mode === "add" && prev?.mode === "add";
32
+ const x = vector.x == null ? prev?.x : isAdditiveMerge ? (prev?.x ?? 0) + vector.x : vector.x;
33
+ const y = vector.y == null ? prev?.y : isAdditiveMerge ? (prev?.y ?? 0) + vector.y : vector.y;
34
+ const z = vector.z == null ? prev?.z : isAdditiveMerge ? (prev?.z ?? 0) + vector.z : vector.z;
35
+ store.velocityChannels[sourceId] = {
36
+ x,
37
+ y,
38
+ z,
39
+ mode,
40
+ priority
28
41
  };
29
- })();
30
- var actionOnRelease = /* @__PURE__ */ (() => {
31
- let buttonPressed = false;
32
- return (isPressed, callback) => {
33
- if (!isPressed && buttonPressed) {
34
- buttonPressed = false;
35
- callback();
36
- } else if (isPressed) {
37
- buttonPressed = true;
42
+ store.dirty.velocityChannels = true;
43
+ }
44
+
45
+ // src/lib/actions/interval-actions.ts
46
+ function moveBy(opts) {
47
+ return new MoveByAction(opts);
48
+ }
49
+ var MoveByAction = class extends BaseAction {
50
+ dx;
51
+ dy;
52
+ dz;
53
+ constructor(opts) {
54
+ super(opts.duration);
55
+ this.dx = opts.x ?? 0;
56
+ this.dy = opts.y ?? 0;
57
+ this.dz = opts.z ?? 0;
58
+ }
59
+ onTick(entity, delta, _progress) {
60
+ if (this.duration <= 0) return;
61
+ const vx = this.dx / this.duration;
62
+ const vy = this.dy / this.duration;
63
+ const vz = this.dz / this.duration;
64
+ const store = entity.transformStore;
65
+ if (!store) return;
66
+ setVelocityIntent(store, "actions", { x: vx, y: vy, z: vz }, { mode: "add" });
67
+ }
68
+ };
69
+ function moveTo(opts) {
70
+ return new MoveToAction(opts);
71
+ }
72
+ var MoveToAction = class extends BaseAction {
73
+ targetX;
74
+ targetY;
75
+ targetZ;
76
+ dx = 0;
77
+ dy = 0;
78
+ dz = 0;
79
+ initialized = false;
80
+ constructor(opts) {
81
+ super(opts.duration);
82
+ this.targetX = opts.x;
83
+ this.targetY = opts.y;
84
+ this.targetZ = opts.z;
85
+ }
86
+ onTick(entity, delta, _progress) {
87
+ if (this.duration <= 0) return;
88
+ if (!this.initialized) {
89
+ const pos = entity.getPosition?.();
90
+ const cx = pos?.x ?? 0;
91
+ const cy = pos?.y ?? 0;
92
+ const cz = pos?.z ?? 0;
93
+ this.dx = this.targetX - cx;
94
+ this.dy = this.targetY - cy;
95
+ this.dz = this.targetZ - cz;
96
+ this.initialized = true;
38
97
  }
39
- };
40
- })();
41
- var actionWithCooldown = /* @__PURE__ */ (() => {
42
- let lastExecutionTime = -Infinity;
43
- let flagImmediate = false;
44
- return ({ timer, immediate = true }, callback, update) => {
45
- let currentTime = Date.now();
46
- if (!flagImmediate && !immediate) {
47
- flagImmediate = true;
48
- lastExecutionTime = currentTime;
98
+ const vx = this.dx / this.duration;
99
+ const vy = this.dy / this.duration;
100
+ const vz = this.dz / this.duration;
101
+ const store = entity.transformStore;
102
+ if (!store) return;
103
+ setVelocityIntent(store, "actions", { x: vx, y: vy, z: vz }, { mode: "add" });
104
+ }
105
+ reset() {
106
+ super.reset();
107
+ this.initialized = false;
108
+ }
109
+ };
110
+ function rotateBy(opts) {
111
+ return new RotateByAction(opts);
112
+ }
113
+ var RotateByAction = class extends BaseAction {
114
+ rx;
115
+ ry;
116
+ rz;
117
+ constructor(opts) {
118
+ super(opts.duration);
119
+ const toRad = Math.PI / 180;
120
+ this.rx = (opts.x ?? 0) * toRad;
121
+ this.ry = (opts.y ?? 0) * toRad;
122
+ this.rz = (opts.z ?? 0) * toRad;
123
+ }
124
+ onTick(entity, delta, _progress) {
125
+ if (this.duration <= 0) return;
126
+ const wx = this.rx / this.duration;
127
+ const wy = this.ry / this.duration;
128
+ const wz = this.rz / this.duration;
129
+ const store = entity.transformStore;
130
+ store.angularVelocity.x += wx;
131
+ store.angularVelocity.y += wy;
132
+ store.angularVelocity.z += wz;
133
+ store.dirty.angularVelocity = true;
134
+ }
135
+ };
136
+ function delay(ms) {
137
+ return new DelayAction(ms);
138
+ }
139
+ var DelayAction = class extends BaseAction {
140
+ constructor(ms) {
141
+ super(ms);
142
+ }
143
+ onTick() {
144
+ }
145
+ };
146
+ function callFunc(fn) {
147
+ return new CallFuncAction(fn);
148
+ }
149
+ var CallFuncAction = class extends BaseAction {
150
+ fn;
151
+ called = false;
152
+ constructor(fn) {
153
+ super(0);
154
+ this.fn = fn;
155
+ }
156
+ onTick() {
157
+ if (!this.called) {
158
+ this.fn();
159
+ this.called = true;
160
+ }
161
+ }
162
+ reset() {
163
+ super.reset();
164
+ this.called = false;
165
+ }
166
+ };
167
+
168
+ // src/lib/actions/persistent-actions.ts
169
+ function throttle(opts) {
170
+ return new ThrottleAction(opts.duration);
171
+ }
172
+ var ThrottleAction = class {
173
+ duration;
174
+ done = false;
175
+ persistent = true;
176
+ ready = false;
177
+ elapsed = 0;
178
+ /** @param durationMs Duration in milliseconds */
179
+ constructor(durationMs) {
180
+ this.duration = durationMs / 1e3;
181
+ }
182
+ tick(_entity, delta) {
183
+ this.elapsed += delta;
184
+ if (this.elapsed >= this.duration) {
185
+ this.ready = true;
186
+ }
187
+ }
188
+ /** Consume the ready state and reset the timer */
189
+ consume() {
190
+ this.ready = false;
191
+ this.elapsed = 0;
192
+ }
193
+ reset() {
194
+ this.elapsed = 0;
195
+ this.ready = false;
196
+ }
197
+ };
198
+ function onPress() {
199
+ return new OnPressAction();
200
+ }
201
+ var OnPressAction = class {
202
+ duration = Infinity;
203
+ done = false;
204
+ persistent = true;
205
+ triggered = false;
206
+ wasPressed = false;
207
+ tick() {
208
+ this.triggered = false;
209
+ }
210
+ /**
211
+ * Feed the current pressed state. Sets `.triggered = true` on the
212
+ * frame where `isPressed` transitions from false to true.
213
+ */
214
+ check(isPressed) {
215
+ if (isPressed && !this.wasPressed) {
216
+ this.triggered = true;
217
+ }
218
+ this.wasPressed = isPressed;
219
+ }
220
+ reset() {
221
+ this.triggered = false;
222
+ this.wasPressed = false;
223
+ }
224
+ };
225
+ function onRelease() {
226
+ return new OnReleaseAction();
227
+ }
228
+ var OnReleaseAction = class {
229
+ duration = Infinity;
230
+ done = false;
231
+ persistent = true;
232
+ triggered = false;
233
+ wasPressed = false;
234
+ tick() {
235
+ this.triggered = false;
236
+ }
237
+ /**
238
+ * Feed the current pressed state. Sets `.triggered = true` on the
239
+ * frame where `isPressed` transitions from true to false.
240
+ */
241
+ check(isPressed) {
242
+ if (!isPressed && this.wasPressed) {
243
+ this.triggered = true;
244
+ }
245
+ this.wasPressed = isPressed;
246
+ }
247
+ reset() {
248
+ this.triggered = false;
249
+ this.wasPressed = false;
250
+ }
251
+ };
252
+
253
+ // src/lib/actions/composition.ts
254
+ function sequence(...actions) {
255
+ return new SequenceAction(actions);
256
+ }
257
+ var SequenceAction = class {
258
+ duration;
259
+ done = false;
260
+ persistent = false;
261
+ actions;
262
+ currentIndex = 0;
263
+ constructor(actions) {
264
+ this.actions = actions;
265
+ this.duration = actions.reduce((sum, a) => sum + a.duration, 0);
266
+ }
267
+ tick(entity, delta) {
268
+ if (this.done || this.actions.length === 0) {
269
+ this.done = true;
270
+ return;
271
+ }
272
+ let remaining = delta;
273
+ while (remaining > 0 && this.currentIndex < this.actions.length) {
274
+ const current = this.actions[this.currentIndex];
275
+ current.tick(entity, remaining);
276
+ if (current.done) {
277
+ const actionDuration = current.duration;
278
+ const actionElapsed = current.elapsed ?? actionDuration;
279
+ const overflow = Math.max(0, actionElapsed - actionDuration);
280
+ remaining = overflow;
281
+ this.currentIndex++;
282
+ } else {
283
+ remaining = 0;
284
+ }
285
+ }
286
+ if (this.currentIndex >= this.actions.length) {
287
+ this.done = true;
288
+ }
289
+ }
290
+ reset() {
291
+ this.currentIndex = 0;
292
+ this.done = false;
293
+ for (const action of this.actions) {
294
+ action.reset();
295
+ }
296
+ }
297
+ };
298
+ function parallel(...actions) {
299
+ return new ParallelAction(actions);
300
+ }
301
+ var ParallelAction = class {
302
+ duration;
303
+ done = false;
304
+ persistent = false;
305
+ actions;
306
+ constructor(actions) {
307
+ this.actions = actions;
308
+ this.duration = Math.max(0, ...actions.map((a) => a.duration));
309
+ }
310
+ tick(entity, delta) {
311
+ if (this.done) return;
312
+ let allDone = true;
313
+ for (const action of this.actions) {
314
+ if (!action.done) {
315
+ action.tick(entity, delta);
316
+ }
317
+ if (!action.done) {
318
+ allDone = false;
319
+ }
320
+ }
321
+ if (allDone) {
322
+ this.done = true;
323
+ }
324
+ }
325
+ reset() {
326
+ this.done = false;
327
+ for (const action of this.actions) {
328
+ action.reset();
329
+ }
330
+ }
331
+ };
332
+ function repeat(action, times) {
333
+ return new RepeatAction(action, times);
334
+ }
335
+ var RepeatAction = class {
336
+ duration;
337
+ done = false;
338
+ persistent = false;
339
+ action;
340
+ totalTimes;
341
+ currentCount = 0;
342
+ constructor(action, times) {
343
+ this.action = action;
344
+ this.totalTimes = times;
345
+ this.duration = action.duration * times;
346
+ }
347
+ tick(entity, delta) {
348
+ if (this.done) return;
349
+ this.action.tick(entity, delta);
350
+ if (this.action.done) {
351
+ this.currentCount++;
352
+ if (this.currentCount >= this.totalTimes) {
353
+ this.done = true;
354
+ } else {
355
+ this.action.reset();
356
+ }
49
357
  }
50
- const delta = currentTime - lastExecutionTime;
51
- if (delta >= timer) {
52
- lastExecutionTime = currentTime;
53
- callback();
358
+ }
359
+ reset() {
360
+ this.currentCount = 0;
361
+ this.done = false;
362
+ this.action.reset();
363
+ }
364
+ };
365
+ function repeatForever(action) {
366
+ return new RepeatForeverAction(action);
367
+ }
368
+ var RepeatForeverAction = class {
369
+ duration = Infinity;
370
+ done = false;
371
+ persistent = false;
372
+ action;
373
+ constructor(action) {
374
+ this.action = action;
375
+ }
376
+ tick(entity, delta) {
377
+ this.action.tick(entity, delta);
378
+ if (this.action.done) {
379
+ this.action.reset();
380
+ }
381
+ }
382
+ reset() {
383
+ this.done = false;
384
+ this.action.reset();
385
+ }
386
+ };
387
+
388
+ // src/lib/actions/capabilities/transform-store.ts
389
+ import { proxy } from "valtio";
390
+ function createTransformStore(initial) {
391
+ const defaultState = {
392
+ position: { x: 0, y: 0, z: 0 },
393
+ rotation: { x: 0, y: 0, z: 0, w: 1 },
394
+ velocity: { x: 0, y: 0, z: 0 },
395
+ angularVelocity: { x: 0, y: 0, z: 0 },
396
+ velocityChannels: {},
397
+ dirty: {
398
+ position: false,
399
+ rotation: false,
400
+ velocity: false,
401
+ velocityX: false,
402
+ velocityY: false,
403
+ velocityZ: false,
404
+ velocityChannels: false,
405
+ angularVelocity: false
54
406
  }
55
- update({ delta });
56
407
  };
57
- })();
58
- var actionWithThrottle = /* @__PURE__ */ (() => {
59
- let lastExecutionTime = 0;
60
- return (timer, callback) => {
61
- const currentTime = Date.now();
62
- const delta = currentTime - lastExecutionTime;
63
- if (delta >= timer) {
64
- lastExecutionTime = currentTime;
65
- callback();
408
+ return proxy({
409
+ ...defaultState,
410
+ ...initial,
411
+ // Ensure dirty flags are properly initialized even if partial initial state
412
+ dirty: {
413
+ ...defaultState.dirty,
414
+ ...initial?.dirty
415
+ }
416
+ });
417
+ }
418
+ function resetTransformStore(store) {
419
+ store.position.x = 0;
420
+ store.position.y = 0;
421
+ store.position.z = 0;
422
+ store.rotation.x = 0;
423
+ store.rotation.y = 0;
424
+ store.rotation.z = 0;
425
+ store.rotation.w = 1;
426
+ store.velocity.x = 0;
427
+ store.velocity.y = 0;
428
+ store.velocity.z = 0;
429
+ store.angularVelocity.x = 0;
430
+ store.angularVelocity.y = 0;
431
+ store.angularVelocity.z = 0;
432
+ for (const sourceId of Object.keys(store.velocityChannels)) {
433
+ delete store.velocityChannels[sourceId];
434
+ }
435
+ store.dirty.position = false;
436
+ store.dirty.rotation = false;
437
+ store.dirty.velocity = false;
438
+ store.dirty.velocityX = false;
439
+ store.dirty.velocityY = false;
440
+ store.dirty.velocityZ = false;
441
+ store.dirty.velocityChannels = false;
442
+ store.dirty.angularVelocity = false;
443
+ }
444
+
445
+ // src/lib/actions/capabilities/apply-transform.ts
446
+ function sortIntents(a, b) {
447
+ if (a.priority !== b.priority) return a.priority - b.priority;
448
+ return a.sourceId.localeCompare(b.sourceId);
449
+ }
450
+ function composeAxis(current, intents, axis) {
451
+ let touched = false;
452
+ let addSum = 0;
453
+ let hasReplace = false;
454
+ let replaceValue = current;
455
+ let replacePriority = Number.NEGATIVE_INFINITY;
456
+ for (const intent of intents) {
457
+ const axisValue = intent[axis];
458
+ if (axisValue == null) continue;
459
+ touched = true;
460
+ if (intent.mode === "add") {
461
+ addSum += axisValue;
462
+ continue;
463
+ }
464
+ if (!hasReplace || intent.priority >= replacePriority) {
465
+ hasReplace = true;
466
+ replacePriority = intent.priority;
467
+ replaceValue = axisValue;
66
468
  }
469
+ }
470
+ return {
471
+ touched,
472
+ value: (hasReplace ? replaceValue : 0) + addSum
473
+ };
474
+ }
475
+ function composeVelocity(current, intents) {
476
+ return {
477
+ x: composeAxis(current.x, intents, "x"),
478
+ y: composeAxis(current.y, intents, "y"),
479
+ z: composeAxis(current.z, intents, "z")
67
480
  };
68
- })();
481
+ }
482
+ function clearVelocityChannels(store) {
483
+ for (const sourceId in store.velocityChannels) {
484
+ delete store.velocityChannels[sourceId];
485
+ }
486
+ store.dirty.velocityChannels = false;
487
+ }
488
+ function applyTransformChanges(entity, store) {
489
+ if (!entity.body) return;
490
+ const hasPosition = store.dirty.position;
491
+ const hasRotation = store.dirty.rotation;
492
+ const hasAngularVelocity = store.dirty.angularVelocity;
493
+ const hasPerAxis = store.dirty.velocityX || store.dirty.velocityY || store.dirty.velocityZ;
494
+ const hasLegacyVelocity = store.dirty.velocity;
495
+ const hasChannels = store.dirty.velocityChannels;
496
+ if (!hasPosition && !hasRotation && !hasAngularVelocity && !hasPerAxis && !hasLegacyVelocity && !hasChannels) {
497
+ return;
498
+ }
499
+ const intents = [];
500
+ if (hasChannels) {
501
+ for (const sourceId in store.velocityChannels) {
502
+ const intent = store.velocityChannels[sourceId];
503
+ intents.push({
504
+ sourceId,
505
+ mode: intent.mode ?? "replace",
506
+ priority: intent.priority ?? 0,
507
+ x: intent.x,
508
+ y: intent.y,
509
+ z: intent.z
510
+ });
511
+ }
512
+ }
513
+ if (hasLegacyVelocity) {
514
+ intents.push({
515
+ sourceId: "__legacy_velocity__",
516
+ mode: "replace",
517
+ priority: -100,
518
+ x: store.velocity.x,
519
+ y: store.velocity.y,
520
+ z: store.velocity.z
521
+ });
522
+ } else if (hasPerAxis) {
523
+ intents.push({
524
+ sourceId: "__legacy_per_axis__",
525
+ mode: "replace",
526
+ priority: -100,
527
+ x: store.dirty.velocityX ? store.velocity.x : void 0,
528
+ y: store.dirty.velocityY ? store.velocity.y : void 0,
529
+ z: store.dirty.velocityZ ? store.velocity.z : void 0
530
+ });
531
+ }
532
+ if (intents.length > 0) {
533
+ const current = entity.body.linvel();
534
+ if (intents.length > 1) {
535
+ intents.sort(sortIntents);
536
+ }
537
+ const composed = composeVelocity(current, intents);
538
+ entity.body.setLinvel(
539
+ {
540
+ x: composed.x.touched ? composed.x.value : current.x,
541
+ y: composed.y.touched ? composed.y.value : current.y,
542
+ z: composed.z.touched ? composed.z.value : current.z
543
+ },
544
+ true
545
+ );
546
+ }
547
+ if (hasRotation) {
548
+ entity.body.setRotation(store.rotation, true);
549
+ }
550
+ if (hasAngularVelocity) {
551
+ entity.body.setAngvel(store.angularVelocity, true);
552
+ }
553
+ if (hasPosition) {
554
+ const current = entity.body.translation();
555
+ entity.body.setTranslation(
556
+ {
557
+ x: current.x + store.position.x,
558
+ y: current.y + store.position.y,
559
+ z: current.z + store.position.z
560
+ },
561
+ true
562
+ );
563
+ }
564
+ store.dirty.position = false;
565
+ store.dirty.rotation = false;
566
+ store.dirty.velocity = false;
567
+ store.dirty.velocityX = false;
568
+ store.dirty.velocityY = false;
569
+ store.dirty.velocityZ = false;
570
+ clearVelocityChannels(store);
571
+ store.dirty.angularVelocity = false;
572
+ }
69
573
 
70
574
  // src/lib/actions/capabilities/moveable.ts
71
575
  import { Vector3 } from "three";
72
576
  function moveX(entity, delta) {
73
- if (!entity.body) return;
74
- const currentVelocity = entity.body.linvel();
75
- const newVelocity = new Vector3(delta, currentVelocity.y, currentVelocity.z);
76
- entity.body.setLinvel(newVelocity, true);
577
+ if (!entity.transformStore) return;
578
+ setVelocityIntent(entity.transformStore, "actions", { x: delta }, { mode: "replace" });
77
579
  }
78
580
  function moveY(entity, delta) {
79
- if (!entity.body) return;
80
- const currentVelocity = entity.body.linvel();
81
- const newVelocity = new Vector3(currentVelocity.x, delta, currentVelocity.z);
82
- entity.body.setLinvel(newVelocity, true);
581
+ if (!entity.transformStore) return;
582
+ setVelocityIntent(entity.transformStore, "actions", { y: delta }, { mode: "replace" });
83
583
  }
84
584
  function moveZ(entity, delta) {
85
- if (!entity.body) return;
86
- const currentVelocity = entity.body.linvel();
87
- const newVelocity = new Vector3(currentVelocity.x, currentVelocity.y, delta);
88
- entity.body.setLinvel(newVelocity, true);
585
+ if (!entity.transformStore) return;
586
+ setVelocityIntent(entity.transformStore, "actions", { z: delta }, { mode: "replace" });
89
587
  }
90
588
  function moveXY(entity, deltaX, deltaY) {
91
- if (!entity.body) return;
92
- const currentVelocity = entity.body.linvel();
93
- const newVelocity = new Vector3(deltaX, deltaY, currentVelocity.z);
94
- entity.body.setLinvel(newVelocity, true);
589
+ if (!entity.transformStore) return;
590
+ setVelocityIntent(
591
+ entity.transformStore,
592
+ "actions",
593
+ { x: deltaX, y: deltaY },
594
+ { mode: "replace" }
595
+ );
95
596
  }
96
597
  function moveXZ(entity, deltaX, deltaZ) {
97
- if (!entity.body) return;
98
- const currentVelocity = entity.body.linvel();
99
- const newVelocity = new Vector3(deltaX, currentVelocity.y, deltaZ);
100
- entity.body.setLinvel(newVelocity, true);
598
+ if (!entity.transformStore) return;
599
+ setVelocityIntent(
600
+ entity.transformStore,
601
+ "actions",
602
+ { x: deltaX, z: deltaZ },
603
+ { mode: "replace" }
604
+ );
101
605
  }
102
606
  function move(entity, vector) {
103
- if (!entity.body) return;
104
- const currentVelocity = entity.body.linvel();
105
- const newVelocity = new Vector3(
106
- currentVelocity.x + vector.x,
107
- currentVelocity.y + vector.y,
108
- currentVelocity.z + vector.z
607
+ if (!entity.transformStore) return;
608
+ setVelocityIntent(
609
+ entity.transformStore,
610
+ "actions",
611
+ { x: vector.x, y: vector.y, z: vector.z },
612
+ { mode: "add" }
109
613
  );
110
- entity.body.setLinvel(newVelocity, true);
111
614
  }
112
615
  function resetVelocity(entity) {
113
616
  if (!entity.body) return;
@@ -167,29 +670,20 @@ function wrapAround3D(entity, boundsX, boundsY, boundsZ) {
167
670
  setPosition(entity, newX, newY, newZ);
168
671
  }
169
672
  }
170
- function makeMoveable(entity) {
171
- const moveable = entity;
172
- moveable.moveX = (delta) => moveX(entity, delta);
173
- moveable.moveY = (delta) => moveY(entity, delta);
174
- moveable.moveZ = (delta) => moveZ(entity, delta);
175
- moveable.moveXY = (deltaX, deltaY) => moveXY(entity, deltaX, deltaY);
176
- moveable.moveXZ = (deltaX, deltaZ) => moveXZ(entity, deltaX, deltaZ);
177
- moveable.move = (vector) => move(entity, vector);
178
- moveable.resetVelocity = () => resetVelocity(entity);
179
- moveable.moveForwardXY = (delta, rotation2DAngle) => moveForwardXY(entity, delta, rotation2DAngle);
180
- moveable.getPosition = () => getPosition(entity);
181
- moveable.getVelocity = () => getVelocity(entity);
182
- moveable.setPosition = (x, y, z) => setPosition(entity, x, y, z);
183
- moveable.setPositionX = (x) => setPositionX(entity, x);
184
- moveable.setPositionY = (y) => setPositionY(entity, y);
185
- moveable.setPositionZ = (z) => setPositionZ(entity, z);
186
- moveable.wrapAroundXY = (boundsX, boundsY) => wrapAroundXY(entity, boundsX, boundsY);
187
- moveable.wrapAround3D = (boundsX, boundsY, boundsZ) => wrapAround3D(entity, boundsX, boundsY, boundsZ);
188
- return moveable;
189
- }
190
673
 
191
674
  // src/lib/actions/capabilities/rotatable.ts
192
675
  import { Euler, Vector3 as Vector32, MathUtils, Quaternion } from "three";
676
+ function syncImmediateRotation(entity) {
677
+ if (!entity.group || !entity.transformStore) return;
678
+ entity.group.setRotationFromQuaternion(
679
+ new Quaternion(
680
+ entity.transformStore.rotation.x,
681
+ entity.transformStore.rotation.y,
682
+ entity.transformStore.rotation.z,
683
+ entity.transformStore.rotation.w
684
+ )
685
+ );
686
+ }
193
687
  function rotateInDirection(entity, moveVector) {
194
688
  if (!entity.body) return;
195
689
  const rotate = Math.atan2(-moveVector.x, moveVector.z);
@@ -199,53 +693,128 @@ function rotateYEuler(entity, amount) {
199
693
  rotateEuler(entity, new Vector32(0, -amount, 0));
200
694
  }
201
695
  function rotateEuler(entity, rotation) {
202
- if (!entity.group) return;
203
- const euler = new Euler(rotation.x, rotation.y, rotation.z);
204
- entity.group.setRotationFromEuler(euler);
696
+ if (!entity.transformStore) return;
697
+ const quat = new Quaternion().setFromEuler(
698
+ new Euler(rotation.x, rotation.y, rotation.z)
699
+ );
700
+ entity.transformStore.rotation.w = quat.w;
701
+ entity.transformStore.rotation.x = quat.x;
702
+ entity.transformStore.rotation.y = quat.y;
703
+ entity.transformStore.rotation.z = quat.z;
704
+ entity.transformStore.dirty.rotation = true;
705
+ syncImmediateRotation(entity);
205
706
  }
206
707
  function rotateY(entity, delta) {
207
- setRotationY(entity, delta);
708
+ if (!entity.transformStore) return;
709
+ const halfAngle = delta / 2;
710
+ const deltaW = Math.cos(halfAngle);
711
+ const deltaY = Math.sin(halfAngle);
712
+ const q = entity.transformStore.rotation;
713
+ const newW = q.w * deltaW - q.y * deltaY;
714
+ const newX = q.x * deltaW + q.z * deltaY;
715
+ const newY = q.y * deltaW + q.w * deltaY;
716
+ const newZ = q.z * deltaW - q.x * deltaY;
717
+ entity.transformStore.rotation.w = newW;
718
+ entity.transformStore.rotation.x = newX;
719
+ entity.transformStore.rotation.y = newY;
720
+ entity.transformStore.rotation.z = newZ;
721
+ entity.transformStore.dirty.rotation = true;
722
+ syncImmediateRotation(entity);
723
+ }
724
+ function rotateX(entity, delta) {
725
+ if (!entity.transformStore) return;
726
+ const halfAngle = delta / 2;
727
+ const deltaW = Math.cos(halfAngle);
728
+ const deltaX = Math.sin(halfAngle);
729
+ const q = entity.transformStore.rotation;
730
+ const newW = q.w * deltaW - q.x * deltaX;
731
+ const newX = q.x * deltaW + q.w * deltaX;
732
+ const newY = q.y * deltaW + q.z * deltaX;
733
+ const newZ = q.z * deltaW - q.y * deltaX;
734
+ entity.transformStore.rotation.w = newW;
735
+ entity.transformStore.rotation.x = newX;
736
+ entity.transformStore.rotation.y = newY;
737
+ entity.transformStore.rotation.z = newZ;
738
+ entity.transformStore.dirty.rotation = true;
739
+ syncImmediateRotation(entity);
208
740
  }
209
741
  function rotateZ(entity, delta) {
210
- setRotationZ(entity, delta);
742
+ if (!entity.transformStore) return;
743
+ const halfAngle = delta / 2;
744
+ const deltaW = Math.cos(halfAngle);
745
+ const deltaZ = Math.sin(halfAngle);
746
+ const q = entity.transformStore.rotation;
747
+ const newW = q.w * deltaW - q.z * deltaZ;
748
+ const newX = q.x * deltaW - q.y * deltaZ;
749
+ const newY = q.y * deltaW + q.x * deltaZ;
750
+ const newZ = q.z * deltaW + q.w * deltaZ;
751
+ entity.transformStore.rotation.w = newW;
752
+ entity.transformStore.rotation.x = newX;
753
+ entity.transformStore.rotation.y = newY;
754
+ entity.transformStore.rotation.z = newZ;
755
+ entity.transformStore.dirty.rotation = true;
756
+ entity._rotation2DAngle = (entity._rotation2DAngle ?? 0) + delta;
757
+ syncImmediateRotation(entity);
211
758
  }
212
759
  function setRotationY(entity, y) {
213
- if (!entity.body) return;
760
+ if (!entity.transformStore) return;
214
761
  const halfAngle = y / 2;
215
762
  const w = Math.cos(halfAngle);
216
763
  const yComponent = Math.sin(halfAngle);
217
- entity.body.setRotation({ w, x: 0, y: yComponent, z: 0 }, true);
764
+ entity.transformStore.rotation.w = w;
765
+ entity.transformStore.rotation.x = 0;
766
+ entity.transformStore.rotation.y = yComponent;
767
+ entity.transformStore.rotation.z = 0;
768
+ entity.transformStore.dirty.rotation = true;
769
+ syncImmediateRotation(entity);
218
770
  }
219
771
  function setRotationDegreesY(entity, y) {
220
772
  if (!entity.body) return;
221
773
  setRotationY(entity, MathUtils.degToRad(y));
222
774
  }
223
775
  function setRotationX(entity, x) {
224
- if (!entity.body) return;
776
+ if (!entity.transformStore) return;
225
777
  const halfAngle = x / 2;
226
778
  const w = Math.cos(halfAngle);
227
779
  const xComponent = Math.sin(halfAngle);
228
- entity.body.setRotation({ w, x: xComponent, y: 0, z: 0 }, true);
780
+ entity.transformStore.rotation.w = w;
781
+ entity.transformStore.rotation.x = xComponent;
782
+ entity.transformStore.rotation.y = 0;
783
+ entity.transformStore.rotation.z = 0;
784
+ entity.transformStore.dirty.rotation = true;
785
+ syncImmediateRotation(entity);
229
786
  }
230
787
  function setRotationDegreesX(entity, x) {
231
788
  if (!entity.body) return;
232
789
  setRotationX(entity, MathUtils.degToRad(x));
233
790
  }
234
791
  function setRotationZ(entity, z) {
235
- if (!entity.body) return;
792
+ if (!entity.transformStore) return;
236
793
  const halfAngle = z / 2;
237
794
  const w = Math.cos(halfAngle);
238
795
  const zComponent = Math.sin(halfAngle);
239
- entity.body.setRotation({ w, x: 0, y: 0, z: zComponent }, true);
796
+ entity.transformStore.rotation.w = w;
797
+ entity.transformStore.rotation.x = 0;
798
+ entity.transformStore.rotation.y = 0;
799
+ entity.transformStore.rotation.z = zComponent;
800
+ entity.transformStore.dirty.rotation = true;
801
+ entity._rotation2DAngle = z;
802
+ syncImmediateRotation(entity);
240
803
  }
241
804
  function setRotationDegreesZ(entity, z) {
242
805
  if (!entity.body) return;
243
806
  setRotationZ(entity, MathUtils.degToRad(z));
244
807
  }
245
808
  function setRotation(entity, x, y, z) {
246
- if (!entity.body) return;
809
+ if (!entity.transformStore) return;
247
810
  const quat = new Quaternion().setFromEuler(new Euler(x, y, z));
248
- entity.body.setRotation({ w: quat.w, x: quat.x, y: quat.y, z: quat.z }, true);
811
+ entity.transformStore.rotation.w = quat.w;
812
+ entity.transformStore.rotation.x = quat.x;
813
+ entity.transformStore.rotation.y = quat.y;
814
+ entity.transformStore.rotation.z = quat.z;
815
+ entity.transformStore.dirty.rotation = true;
816
+ entity._rotation2DAngle = z;
817
+ syncImmediateRotation(entity);
249
818
  }
250
819
  function setRotationDegrees(entity, x, y, z) {
251
820
  if (!entity.body) return;
@@ -255,35 +824,113 @@ function getRotation(entity) {
255
824
  if (!entity.body) return null;
256
825
  return entity.body.rotation();
257
826
  }
258
- function makeRotatable(entity) {
259
- const rotatableEntity = entity;
260
- rotatableEntity.rotateInDirection = (moveVector) => rotateInDirection(entity, moveVector);
261
- rotatableEntity.rotateYEuler = (amount) => rotateYEuler(entity, amount);
262
- rotatableEntity.rotateEuler = (rotation) => rotateEuler(entity, rotation);
263
- rotatableEntity.rotateY = (delta) => rotateY(entity, delta);
264
- rotatableEntity.rotateZ = (delta) => rotateZ(entity, delta);
265
- rotatableEntity.setRotationY = (y) => setRotationY(entity, y);
266
- rotatableEntity.setRotationX = (x) => setRotationX(entity, x);
267
- rotatableEntity.setRotationZ = (z) => setRotationZ(entity, z);
268
- rotatableEntity.setRotationDegreesY = (y) => setRotationDegreesY(entity, y);
269
- rotatableEntity.setRotationDegreesX = (x) => setRotationDegreesX(entity, x);
270
- rotatableEntity.setRotationDegreesZ = (z) => setRotationDegreesZ(entity, z);
271
- rotatableEntity.setRotationDegrees = (x, y, z) => setRotationDegrees(entity, x, y, z);
272
- rotatableEntity.setRotation = (x, y, z) => setRotation(entity, x, y, z);
273
- rotatableEntity.getRotation = () => getRotation(entity);
274
- return rotatableEntity;
275
- }
276
827
 
277
- // src/lib/actions/capabilities/transformable.ts
278
- function makeTransformable(entity) {
279
- const withMovement = makeMoveable(entity);
280
- const withRotation = makeRotatable(withMovement);
281
- return withRotation;
828
+ // src/lib/actions/global-change.ts
829
+ function globalChange(key, callback) {
830
+ let previousValue = void 0;
831
+ return (ctx) => {
832
+ const currentValue = ctx.globals?.[key];
833
+ if (previousValue !== currentValue) {
834
+ if (!(previousValue === void 0 && currentValue === void 0)) {
835
+ callback(currentValue, ctx);
836
+ }
837
+ previousValue = currentValue;
838
+ }
839
+ };
840
+ }
841
+ function globalChanges(keys, callback) {
842
+ let previousValues = new Array(keys.length).fill(void 0);
843
+ return (ctx) => {
844
+ const currentValues = keys.map((k) => ctx.globals?.[k]);
845
+ const hasAnyChange = currentValues.some((val, idx) => previousValues[idx] !== val);
846
+ if (hasAnyChange) {
847
+ const allPrevUndef = previousValues.every((v) => v === void 0);
848
+ const allCurrUndef = currentValues.every((v) => v === void 0);
849
+ if (!(allPrevUndef && allCurrUndef)) {
850
+ callback(currentValues, ctx);
851
+ }
852
+ previousValues = currentValues;
853
+ }
854
+ };
855
+ }
856
+ function variableChange(key, callback) {
857
+ let previousValue = void 0;
858
+ return (ctx) => {
859
+ const currentValue = ctx.stage?.getVariable?.(key) ?? void 0;
860
+ if (previousValue !== currentValue) {
861
+ if (!(previousValue === void 0 && currentValue === void 0)) {
862
+ callback(currentValue, ctx);
863
+ }
864
+ previousValue = currentValue;
865
+ }
866
+ };
867
+ }
868
+ function variableChanges(keys, callback) {
869
+ let previousValues = new Array(keys.length).fill(void 0);
870
+ return (ctx) => {
871
+ const reader = (k) => ctx.stage?.getVariable?.(k);
872
+ const currentValues = keys.map(reader);
873
+ const hasAnyChange = currentValues.some((val, idx) => previousValues[idx] !== val);
874
+ if (hasAnyChange) {
875
+ const allPrevUndef = previousValues.every((v) => v === void 0);
876
+ const allCurrUndef = currentValues.every((v) => v === void 0);
877
+ if (!(allPrevUndef && allCurrUndef)) {
878
+ callback(currentValues, ctx);
879
+ }
880
+ previousValues = currentValues;
881
+ }
882
+ };
282
883
  }
283
884
  export {
284
- actions_exports as actions,
285
- makeMoveable,
286
- makeRotatable,
287
- makeTransformable
885
+ applyTransformChanges,
886
+ callFunc,
887
+ createTransformStore,
888
+ delay,
889
+ getPosition,
890
+ getRotation,
891
+ getVelocity,
892
+ globalChange,
893
+ globalChanges,
894
+ move,
895
+ moveBy,
896
+ moveForwardXY,
897
+ moveTo,
898
+ moveX,
899
+ moveXY,
900
+ moveXZ,
901
+ moveY,
902
+ moveZ,
903
+ onPress,
904
+ onRelease,
905
+ parallel,
906
+ repeat,
907
+ repeatForever,
908
+ resetTransformStore,
909
+ resetVelocity,
910
+ rotateBy,
911
+ rotateEuler,
912
+ rotateInDirection,
913
+ rotateX,
914
+ rotateY,
915
+ rotateYEuler,
916
+ rotateZ,
917
+ sequence,
918
+ setPosition,
919
+ setPositionX,
920
+ setPositionY,
921
+ setPositionZ,
922
+ setRotation,
923
+ setRotationDegrees,
924
+ setRotationDegreesX,
925
+ setRotationDegreesY,
926
+ setRotationDegreesZ,
927
+ setRotationX,
928
+ setRotationY,
929
+ setRotationZ,
930
+ throttle,
931
+ variableChange,
932
+ variableChanges,
933
+ wrapAround3D,
934
+ wrapAroundXY
288
935
  };
289
936
  //# sourceMappingURL=actions.js.map