@babylonjsmarket/arcade 0.3.11 → 0.3.12

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 (56) hide show
  1. package/dist/cli/eject.d.ts +24 -1
  2. package/dist/cli/eject.d.ts.map +1 -1
  3. package/dist/cli/eject.js +27 -22
  4. package/dist/cli/eject.js.map +1 -1
  5. package/package.json +3 -2
  6. package/src/Components/Animation/Animation.core.test.ts +11 -0
  7. package/src/Components/Animation/Animation.test.ts +26 -0
  8. package/src/Components/ArcCamera/ArcCamera.test.ts +168 -0
  9. package/src/Components/Bullet/Bullet.test.ts +223 -0
  10. package/src/Components/BulletPool/BulletPool.test.ts +50 -1
  11. package/src/Components/Bumper/Bumper.test.ts +18 -0
  12. package/src/Components/CameraFollow/CameraFollow.core.test.ts +19 -0
  13. package/src/Components/CameraFollow/CameraFollow.test.ts +92 -0
  14. package/src/Components/DirectionalLight/DirectionalLight.test.ts +48 -0
  15. package/src/Components/Enemy/Enemy.core.test.ts +20 -1
  16. package/src/Components/Enemy/Enemy.test.ts +456 -1
  17. package/src/Components/EnemySpawner/EnemySpawner.test.ts +155 -0
  18. package/src/Components/EntityPool/EntityPool.test.ts +95 -1
  19. package/src/Components/EnvironmentTexture/EnvironmentTexture.test.ts +31 -0
  20. package/src/Components/Flash/Flash.test.ts +44 -0
  21. package/src/Components/Flipper/Flipper.core.test.ts +9 -0
  22. package/src/Components/Flipper/Flipper.test.ts +63 -0
  23. package/src/Components/Health/Health.test.ts +184 -0
  24. package/src/Components/HealthBar/HealthBar.test.ts +158 -0
  25. package/src/Components/HemisphericLight/HemisphericLight.test.ts +36 -0
  26. package/src/Components/KeyboardMover/KeyboardMover.test.ts +120 -0
  27. package/src/Components/LineOfSight/LineOfSight.core.test.ts +26 -0
  28. package/src/Components/LineOfSight/LineOfSight.test.ts +38 -0
  29. package/src/Components/Mesh/Mesh.test.ts +201 -0
  30. package/src/Components/MeshPrimitive/MeshPrimitive.test.ts +222 -0
  31. package/src/Components/MouseHole/MouseHole.test.ts +40 -0
  32. package/src/Components/Movement/Movement.core.test.ts +50 -0
  33. package/src/Components/Movement/Movement.test.ts +73 -0
  34. package/src/Components/Obstacle/Obstacle.core.test.ts +82 -0
  35. package/src/Components/Obstacle/Obstacle.test.ts +72 -0
  36. package/src/Components/ObstacleField/ObstacleField.test.ts +8 -0
  37. package/src/Components/Physics/Physics.core.test.ts +48 -0
  38. package/src/Components/Physics/Physics.test.ts +101 -0
  39. package/src/Components/PinballBuilder/PinballBuilder.test.ts +129 -0
  40. package/src/Components/PinballBuilderInput/PinballBuilderInput.test.ts +76 -0
  41. package/src/Components/PinballCamera/PinballCamera.test.ts +39 -0
  42. package/src/Components/PinballLayout/PinballLayout.test.ts +82 -0
  43. package/src/Components/PinballTable/PinballTable.test.ts +91 -0
  44. package/src/Components/PlayerInput/PlayerInput.core.test.ts +56 -0
  45. package/src/Components/PlayerInput/PlayerInput.test.ts +139 -0
  46. package/src/Components/Plunger/Plunger.test.ts +55 -0
  47. package/src/Components/Score/Score.test.ts +60 -0
  48. package/src/Components/Scoreboard/Scoreboard.core.test.ts +12 -0
  49. package/src/Components/Scoreboard/Scoreboard.test.ts +36 -0
  50. package/src/Components/Shadow/Shadow.test.ts +69 -0
  51. package/src/Components/ShooterCamera/ShooterCamera.test.ts +11 -0
  52. package/src/Components/SkeletonAnimator/SkeletonAnimator.test.ts +182 -0
  53. package/src/Components/Skybox/Skybox.test.ts +83 -0
  54. package/src/Components/Spinner/Spinner.test.ts +30 -0
  55. package/src/Components/TwinStickShooter/TwinStickShooter.test.ts +105 -0
  56. package/templates/main.ts +27 -8
@@ -1,2 +1,25 @@
1
- export declare function eject(args: string[]): Promise<void>;
1
+ /**
2
+ * Where eject reads its source from. Defaults to this package's shipped dirs;
3
+ * overridable so tests can point at an isolated fixture tree instead of
4
+ * mutating the real package (which other suites read concurrently).
5
+ */
6
+ export interface EjectRoots {
7
+ componentsSrc: string;
8
+ payloadSrc: string;
9
+ }
10
+ /**
11
+ * Rewrite imports in a copied file so they resolve from `src/components/Name/`:
12
+ *
13
+ * - `../Sibling/...` where Sibling was NOT ejected → the package subpath
14
+ * `@babylonjsmarket/arcade/Sibling`. Co-ejected siblings keep their relative
15
+ * path (it still resolves under src/components/).
16
+ * - `../../inputEvents` (arcade-core constants, two levels up to the package
17
+ * root in the source tree) → the package root `@babylonjsmarket/arcade`,
18
+ * which re-exports them. Otherwise the copied path would dangle.
19
+ *
20
+ * ecs/arcade/viz/solid/babylon package imports are left alone — they resolve
21
+ * from node_modules in the ejected project.
22
+ */
23
+ export declare function rewriteImports(src: string, ejected: Set<string>, allNames: Set<string>): string;
24
+ export declare function eject(args: string[], roots?: EjectRoots): Promise<void>;
2
25
  //# sourceMappingURL=eject.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"eject.d.ts","sourceRoot":"","sources":["../../src/cli/eject.ts"],"names":[],"mappings":"AA2NA,wBAAsB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyDzD"}
1
+ {"version":3,"file":"eject.d.ts","sourceRoot":"","sources":["../../src/cli/eject.ts"],"names":[],"mappings":"AAqBA;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAgGD;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,EACpB,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,GACpB,MAAM,CAeR;AA4FD,wBAAsB,KAAK,CACzB,IAAI,EAAE,MAAM,EAAE,EACd,KAAK,GAAE,UAA0B,GAChC,OAAO,CAAC,IAAI,CAAC,CA0Df"}
package/dist/cli/eject.js CHANGED
@@ -9,20 +9,24 @@ const { cyan, green, yellow, dim, bold } = colors;
9
9
  // `src/Components` and `.claude-payload` ship in the published `files` array.
10
10
  const HERE = path.dirname(fileURLToPath(import.meta.url));
11
11
  const PACKAGE_ROOT = path.resolve(HERE, "..", "..");
12
- const COMPONENTS_SRC = path.resolve(PACKAGE_ROOT, "src", "Components");
13
- const PAYLOAD_SRC = path.resolve(PACKAGE_ROOT, ".claude-payload", "skills", "babylonjsmarket");
12
+ const COMPONENTS_SRC_DEFAULT = path.resolve(PACKAGE_ROOT, "src", "Components");
13
+ const PAYLOAD_SRC_DEFAULT = path.resolve(PACKAGE_ROOT, ".claude-payload", "skills", "babylonjsmarket");
14
+ const DEFAULT_ROOTS = {
15
+ componentsSrc: COMPONENTS_SRC_DEFAULT,
16
+ payloadSrc: PAYLOAD_SRC_DEFAULT,
17
+ };
14
18
  /** The component universe = top-level folders under src/Components. */
15
- function arcadeComponentNames() {
16
- if (!fs.existsSync(COMPONENTS_SRC))
19
+ function arcadeComponentNames(componentsSrc) {
20
+ if (!fs.existsSync(componentsSrc))
17
21
  return [];
18
22
  return fs
19
- .readdirSync(COMPONENTS_SRC, { withFileTypes: true })
23
+ .readdirSync(componentsSrc, { withFileTypes: true })
20
24
  .filter((e) => e.isDirectory())
21
25
  .map((e) => e.name);
22
26
  }
23
27
  /** Every .ts/.tsx file inside a component folder. */
24
- function componentFiles(name) {
25
- const dir = path.join(COMPONENTS_SRC, name);
28
+ function componentFiles(componentsSrc, name) {
29
+ const dir = path.join(componentsSrc, name);
26
30
  const out = [];
27
31
  const walk = (d) => {
28
32
  for (const e of fs.readdirSync(d, { withFileTypes: true })) {
@@ -54,9 +58,9 @@ function parseUsedComponents(projectDir, names) {
54
58
  return used;
55
59
  }
56
60
  /** Component names a given component imports via `../Sibling/...` or lists in meta.json. */
57
- function directDeps(name, names) {
61
+ function directDeps(componentsSrc, name, names) {
58
62
  const deps = new Set();
59
- const metaPath = path.join(COMPONENTS_SRC, name, "meta.json");
63
+ const metaPath = path.join(componentsSrc, name, "meta.json");
60
64
  if (fs.existsSync(metaPath)) {
61
65
  try {
62
66
  const meta = JSON.parse(fs.readFileSync(metaPath, "utf8"));
@@ -69,7 +73,7 @@ function directDeps(name, names) {
69
73
  }
70
74
  }
71
75
  const importRe = /['"]\.\.\/([A-Z][A-Za-z0-9_]*)\//g;
72
- for (const file of componentFiles(name)) {
76
+ for (const file of componentFiles(componentsSrc, name)) {
73
77
  const src = fs.readFileSync(file, "utf8");
74
78
  let m;
75
79
  while ((m = importRe.exec(src)))
@@ -79,13 +83,13 @@ function directDeps(name, names) {
79
83
  return deps;
80
84
  }
81
85
  /** Expand a seed set to its transitive component-dependency closure. */
82
- function resolveClosure(seed, allNames) {
86
+ function resolveClosure(componentsSrc, seed, allNames) {
83
87
  const all = new Set(allNames);
84
88
  const out = new Set(seed);
85
89
  const queue = [...seed];
86
90
  while (queue.length) {
87
91
  const next = queue.pop();
88
- for (const dep of directDeps(next, all)) {
92
+ for (const dep of directDeps(componentsSrc, next, all)) {
89
93
  if (!out.has(dep)) {
90
94
  out.add(dep);
91
95
  queue.push(dep);
@@ -107,7 +111,7 @@ function resolveClosure(seed, allNames) {
107
111
  * ecs/arcade/viz/solid/babylon package imports are left alone — they resolve
108
112
  * from node_modules in the ejected project.
109
113
  */
110
- function rewriteImports(src, ejected, allNames) {
114
+ export function rewriteImports(src, ejected, allNames) {
111
115
  return src
112
116
  .replace(/(['"])\.\.\/\.\.\/inputEvents\1/g, (_whole, quote) => `${quote}@babylonjsmarket/arcade${quote}`)
113
117
  .replace(/(['"])(\.\.\/([A-Z][A-Za-z0-9_]*)\/[^'"]*)\1/g, (whole, quote, _spec, sibling) => {
@@ -159,11 +163,11 @@ function patchRegistry(projectDir, names, dryRun) {
159
163
  }
160
164
  return added.map((n) => ` patched registry: ${n}`);
161
165
  }
162
- function buildPlan(args, projectDir) {
166
+ function buildPlan(args, projectDir, componentsSrc) {
163
167
  const argv = mri(args, { boolean: ["all", "dry-run"] });
164
168
  const all = argv.all;
165
169
  const explicit = argv._.map(String);
166
- const names = arcadeComponentNames();
170
+ const names = arcadeComponentNames(componentsSrc);
167
171
  if (names.length === 0) {
168
172
  throw new Error("No component source found. Run inside a project with @babylonjsmarket/arcade installed (the package must ship src/Components).");
169
173
  }
@@ -185,10 +189,11 @@ function buildPlan(args, projectDir) {
185
189
  throw new Error("Couldn't detect any arcade components in src/scene.ts or src/registry.ts. Pass names explicitly (`arcade eject Bullet Enemy`) or use --all.");
186
190
  }
187
191
  }
188
- const components = [...resolveClosure(seed, names)].sort();
192
+ const components = [...resolveClosure(componentsSrc, seed, names)].sort();
189
193
  return { components };
190
194
  }
191
- export async function eject(args) {
195
+ export async function eject(args, roots = DEFAULT_ROOTS) {
196
+ const { componentsSrc, payloadSrc } = roots;
192
197
  if (args.includes("-h") || args.includes("--help")) {
193
198
  console.log(EJECT_HELP);
194
199
  return;
@@ -197,7 +202,7 @@ export async function eject(args) {
197
202
  const projectDir = process.cwd();
198
203
  let plan;
199
204
  try {
200
- plan = buildPlan(args, projectDir);
205
+ plan = buildPlan(args, projectDir, componentsSrc);
201
206
  }
202
207
  catch (e) {
203
208
  console.error(yellow(e.message));
@@ -205,14 +210,14 @@ export async function eject(args) {
205
210
  return;
206
211
  }
207
212
  const ejectedSet = new Set(plan.components);
208
- const allNames = new Set(arcadeComponentNames());
213
+ const allNames = new Set(arcadeComponentNames(componentsSrc));
209
214
  const componentsDir = path.join(projectDir, "src", "components");
210
215
  console.log(bold(dryRun ? "\nEject plan (dry run — nothing written):" : "\nEjecting:"));
211
216
  console.log(` components: ${cyan(plan.components.join(", "))}`);
212
217
  // 1. Copy each component folder (with its own tests).
213
218
  for (const name of plan.components) {
214
219
  if (!dryRun)
215
- copyDir(path.join(COMPONENTS_SRC, name), path.join(componentsDir, name));
220
+ copyDir(path.join(componentsSrc, name), path.join(componentsDir, name));
216
221
  console.log(green(` + src/components/${name}/`));
217
222
  }
218
223
  // 2. Rewrite imports across everything copied: a `../X/` whose X was NOT
@@ -227,9 +232,9 @@ export async function eject(args) {
227
232
  }
228
233
  // 4. Drop the babylonjsmarket Claude skill into the project.
229
234
  const skillDest = path.join(projectDir, ".claude", "skills", "babylonjsmarket");
230
- if (fs.existsSync(PAYLOAD_SRC)) {
235
+ if (fs.existsSync(payloadSrc)) {
231
236
  if (!dryRun)
232
- copyDir(PAYLOAD_SRC, skillDest);
237
+ copyDir(payloadSrc, skillDest);
233
238
  console.log(green(" + .claude/skills/babylonjsmarket/"));
234
239
  }
235
240
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"eject.js","sourceRoot":"","sources":["../../src/cli/eject.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"eject.js","sourceRoot":"","sources":["../../src/cli/eject.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babylonjsmarket/arcade",
3
- "version": "0.3.11",
3
+ "version": "0.3.12",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Reusable arcade-style components (mesh, camera, lights, input, physics, scoring, animation) for the @babylonjsmarket/ecs framework",
@@ -79,6 +79,7 @@
79
79
  "build": "tsc -p tsconfig.build.json",
80
80
  "build:watch": "tsc -p tsconfig.build.json --watch --preserveWatchOutput",
81
81
  "test": "vitest run",
82
+ "test:coverage": "vitest run --coverage",
82
83
  "test:watch": "vitest",
83
84
  "typecheck": "tsc -p tsconfig.json --noEmit",
84
85
  "lint": "eslint src",
@@ -86,7 +87,7 @@
86
87
  "sync-templates:check": "node scripts/sync-templates.js --check",
87
88
  "try:scaffold": "node scripts/try-scaffold.mjs",
88
89
  "validate:scenes": "tsx scripts/validate-example-scenes.ts",
89
- "prepublishOnly": "npm run build && npm run test"
90
+ "prepublishOnly": "npm run build && npm run test:coverage"
90
91
  },
91
92
  "dependencies": {
92
93
  "@babylonjsmarket/ecs": "^0.5.3",
@@ -137,6 +137,17 @@ describe('Animation core', () => {
137
137
  }).not.toThrow();
138
138
  });
139
139
 
140
+ it('pins walk (no run band) when runSpeed <= walkSpeed and speed exceeds walk', () => {
141
+ // Degenerate config: runSpeed equals walkSpeed → no meaningful run band.
142
+ // A speed above walkSpeed must settle on pure walk, never run.
143
+ const a = createAnimation({ walkSpeed: 3, runSpeed: 3, blendSpeed: 50 });
144
+ for (let i = 0; i < 400; i++) a.update(5, 1 / 60);
145
+ const out = a.update(5, 1 / 60);
146
+ expect(out.walkWeight).toBeCloseTo(1, 3);
147
+ expect(out.runWeight).toBeCloseTo(0, 3);
148
+ expect(out.state).toBe('walk');
149
+ });
150
+
140
151
  it('treats negative dt as zero (never unwinds weights)', () => {
141
152
  const a = createAnimation();
142
153
  const before = a.getState();
@@ -171,4 +171,30 @@ describe('AnimationSystem', () => {
171
171
  const playCalls = renderer.calls.filter((c) => c.method === 'playAnimation');
172
172
  expect(playCalls).toHaveLength(0);
173
173
  });
174
+
175
+ it('builds instances for entities that exist before the system initializes', () => {
176
+ const bus = new EventBus();
177
+ const r = new MockRendererAdapter();
178
+ const w = new World({ eventBus: bus, renderer: r, detectRaces: false });
179
+ const entity = w.createEntity();
180
+ entity.add(new AnimationComponent({ walkSpeed: 2 }));
181
+ // System added AFTER the entity → onInitialize scans and wires the instance.
182
+ w.addSystem(new AnimationSystem(bus));
183
+ w.initialize();
184
+ const comp = entity.get(AnimationComponent);
185
+ expect(comp?.instance).not.toBeNull();
186
+ expect(comp?.instance?.getParams().walkSpeed).toBe(2);
187
+ });
188
+
189
+ it('does not rebuild the core instance for an entity already wired up', () => {
190
+ const entity = world.createEntity();
191
+ entity.add(new AnimationComponent());
192
+ const comp = entity.get(AnimationComponent)!;
193
+ const firstInstance = comp.instance;
194
+ expect(firstInstance).not.toBeNull();
195
+ // A second update (and the internal ensureInstance guard) must not replace
196
+ // the existing instance.
197
+ world.update(1 / 60);
198
+ expect(comp.instance).toBe(firstInstance);
199
+ });
174
200
  });
@@ -4,8 +4,11 @@ import {
4
4
  ArcCameraSystem,
5
5
  ArcCameraEvents,
6
6
  } from './ArcCamera';
7
+ import { MeshPrimitiveSystem, MeshPrimitiveComponent } from '../MeshPrimitive/MeshPrimitive';
8
+ import { getArcCameraRuntime } from './ArcCamera.core';
7
9
  import { EventBus, World } from '@babylonjsmarket/ecs';
8
10
  import { MockRendererAdapter } from '@babylonjsmarket/ecs';
11
+ import type { MeshHandle } from '@babylonjsmarket/ecs/renderer-types';
9
12
 
10
13
  describe('ArcCameraComponent (core)', () => {
11
14
  it('applies sensible defaults', () => {
@@ -184,4 +187,169 @@ describe('ArcCameraSystem — adapter integration', () => {
184
187
  world.update(4);
185
188
  expect(renderer.calls.some((c) => c.method === 'nudgeCameraAlpha')).toBe(false);
186
189
  });
190
+
191
+ it('locks radius each frame when controls are disabled', () => {
192
+ const entity = world.createEntity();
193
+ entity.add(new ArcCameraComponent({ controlsEnabled: false, distance: 30 }));
194
+ renderer.calls.length = 0;
195
+ world.update(0.016);
196
+ const radius = renderer.calls.find((c) => c.method === 'setCameraRadius');
197
+ expect(radius).toBeDefined();
198
+ expect(radius!.args[1]).toBe(30);
199
+ const limits = renderer.calls.find((c) => c.method === 'setCameraRadiusLimits');
200
+ expect(limits).toBeDefined();
201
+ expect(limits!.args[1]).toBe(30);
202
+ expect(limits!.args[2]).toBe(30);
203
+ });
204
+
205
+ it('does not lock the radius for a free-orbit camera (controls on)', () => {
206
+ const entity = world.createEntity();
207
+ entity.add(new ArcCameraComponent({ controlsEnabled: true }));
208
+ renderer.calls.length = 0;
209
+ world.update(0.016);
210
+ expect(renderer.calls.some((c) => c.method === 'setCameraRadius')).toBe(false);
211
+ });
212
+
213
+ it('tracks an active target by reading its mesh world position each frame', () => {
214
+ const entity = world.createEntity();
215
+ entity.add(new ArcCameraComponent({ target: 'hero', follow: true }));
216
+ const fakeMeshHandle = { __mockHandle: 'mesh:hero' } as unknown as MeshHandle;
217
+ renderer.meshWorldPositions.set(fakeMeshHandle, [10, 2, 6]);
218
+ eventBus.emit('meshprimitive.created', { entityId: 'hero', handle: fakeMeshHandle });
219
+ renderer.calls.length = 0;
220
+ world.update(0.016);
221
+ const setTarget = renderer.calls.find((c) => c.method === 'setCameraTarget');
222
+ expect(setTarget).toBeDefined();
223
+ // base + targetOffset(0,0,0)
224
+ expect(setTarget!.args[1]).toBeCloseTo(10);
225
+ expect(setTarget!.args[2]).toBeCloseTo(2);
226
+ expect(setTarget!.args[3]).toBeCloseTo(6);
227
+ });
228
+
229
+ it('holds a captured free base when a target is named but its mesh is not ready', () => {
230
+ const entity = world.createEntity();
231
+ // target is named but no meshprimitive.created ever fires for it, so the
232
+ // System captures the current look point (origin, the seeded target) as the
233
+ // free base and pans it by targetOffset.
234
+ const comp = new ArcCameraComponent({ target: 'ghost', follow: true, targetOffset: [1, 0, 0] });
235
+ entity.add(comp);
236
+ renderer.calls.length = 0;
237
+ world.update(0.016);
238
+ const setTarget = renderer.calls.find((c) => c.method === 'setCameraTarget');
239
+ expect(setTarget).toBeDefined();
240
+ // base (captured origin) + offset [1,0,0].
241
+ expect(setTarget!.args[1]).toBeCloseTo(1);
242
+ expect(setTarget!.args[2]).toBeCloseTo(0);
243
+ expect(setTarget!.args[3]).toBeCloseTo(0);
244
+
245
+ // The free base is cached on the runtime so panning is relative to it.
246
+ const rt = getArcCameraRuntime(comp);
247
+ expect(rt.freeBase).toEqual([0, 0, 0]);
248
+
249
+ // Second frame still drives the target from the same cached base.
250
+ renderer.calls.length = 0;
251
+ world.update(0.016);
252
+ expect(renderer.calls.some((c) => c.method === 'setCameraTarget')).toBe(true);
253
+ });
254
+
255
+ it('resets the idle timer the frame the camera receives input while auto-rotating', () => {
256
+ const entity = world.createEntity();
257
+ const comp = new ArcCameraComponent({ autoRotate: true, autoRotateSpeed: 1 });
258
+ entity.add(comp);
259
+ // Let it idle past the threshold so it begins nudging.
260
+ world.update(4);
261
+ expect(renderer.calls.some((c) => c.method === 'nudgeCameraAlpha')).toBe(true);
262
+ // Now simulate user input: bump the reported alpha so onUpdate detects
263
+ // rotation, which must reset idleTime to 0 and suppress nudging this frame.
264
+ const angles = [...renderer.cameraAngles.values()][0];
265
+ if (angles) angles.alpha += 1;
266
+ renderer.calls.length = 0;
267
+ world.update(0.016);
268
+ expect(renderer.calls.some((c) => c.method === 'nudgeCameraAlpha')).toBe(false);
269
+ });
270
+
271
+ it('seeds the camera target from a target mesh that already exists at creation', () => {
272
+ // Build a fresh world where the target mesh is created BEFORE the
273
+ // ArcCamera entity, so ensureCamera resolves the handle and seeds from it.
274
+ const bus = new EventBus();
275
+ const r = new MockRendererAdapter();
276
+ const w = new World({ eventBus: bus, renderer: r });
277
+ w.addSystem(new MeshPrimitiveSystem(bus));
278
+ w.addSystem(new ArcCameraSystem(bus));
279
+ w.initialize();
280
+
281
+ const hero = w.createEntity('hero');
282
+ hero.add(new MeshPrimitiveComponent());
283
+ const mp = hero.get(MeshPrimitiveComponent)!;
284
+ r.meshWorldPositions.set(mp.handle as MeshHandle, [5, 1, 3]);
285
+
286
+ const cam = w.createEntity('Cam');
287
+ cam.add(new ArcCameraComponent({ target: 'hero', follow: true, targetOffset: [0, 2, 0] }));
288
+
289
+ const create = r.calls.find((c) => c.method === 'createArcCamera');
290
+ expect(create).toBeDefined();
291
+ const spec = create!.args[1] as { target: [number, number, number] };
292
+ expect(spec.target[0]).toBeCloseTo(5);
293
+ expect(spec.target[1]).toBeCloseTo(3); // 1 + offset 2
294
+ expect(spec.target[2]).toBeCloseTo(3);
295
+ });
296
+
297
+ it('no-ops on a renderer-less world', () => {
298
+ const bus = new EventBus();
299
+ const w = new World({ eventBus: bus });
300
+ w.addSystem(new ArcCameraSystem(bus));
301
+ w.initialize();
302
+ const e = w.createEntity();
303
+ expect(() => e.add(new ArcCameraComponent())).not.toThrow();
304
+ expect(() => w.update(0.016)).not.toThrow();
305
+ });
306
+
307
+ it('creates cameras for entities that exist before the system initializes', () => {
308
+ const bus = new EventBus();
309
+ const r = new MockRendererAdapter();
310
+ const w = new World({ eventBus: bus, renderer: r });
311
+ const entity = w.createEntity();
312
+ entity.add(new ArcCameraComponent({ distance: 22 }));
313
+ // System added AFTER the entity → onInitialize scans and creates it.
314
+ w.addSystem(new ArcCameraSystem(bus));
315
+ w.initialize();
316
+ const create = r.calls.find((c) => c.method === 'createArcCamera');
317
+ expect(create).toBeDefined();
318
+ expect((create!.args[1] as { radius: number }).radius).toBe(22);
319
+ });
320
+
321
+ it('centres restTarget when not following', () => {
322
+ const entity = world.createEntity();
323
+ entity.add(new ArcCameraComponent({ follow: false, restTarget: 'table' }));
324
+ const fakeMeshHandle = { __mockHandle: 'mesh:table' } as unknown as MeshHandle;
325
+ renderer.meshWorldPositions.set(fakeMeshHandle, [0, 0, 9]);
326
+ eventBus.emit('meshprimitive.created', { entityId: 'table', handle: fakeMeshHandle });
327
+ renderer.calls.length = 0;
328
+ world.update(0.016);
329
+ const setTarget = renderer.calls.find((c) => c.method === 'setCameraTarget');
330
+ expect(setTarget).toBeDefined();
331
+ expect(setTarget!.args[3]).toBeCloseTo(9);
332
+ });
333
+
334
+ it('seeds from `target` when not following and no restTarget is set', () => {
335
+ // follow:false with no restTarget → seedName falls back to `target`.
336
+ const bus = new EventBus();
337
+ const r = new MockRendererAdapter();
338
+ const w = new World({ eventBus: bus, renderer: r });
339
+ w.addSystem(new MeshPrimitiveSystem(bus));
340
+ w.addSystem(new ArcCameraSystem(bus));
341
+ w.initialize();
342
+
343
+ const hero = w.createEntity('hero');
344
+ hero.add(new MeshPrimitiveComponent());
345
+ const mp = hero.get(MeshPrimitiveComponent)!;
346
+ r.meshWorldPositions.set(mp.handle as MeshHandle, [7, 0, 0]);
347
+
348
+ const cam = w.createEntity('Cam');
349
+ cam.add(new ArcCameraComponent({ target: 'hero', follow: false }));
350
+
351
+ const create = r.calls.find((c) => c.method === 'createArcCamera');
352
+ const spec = create!.args[1] as { target: [number, number, number] };
353
+ expect(spec.target[0]).toBeCloseTo(7);
354
+ });
187
355
  });