entangled-worlds-orbiters-shared 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "entangled-worlds-orbiters-shared",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Shared library for entangled worlds orbiters - contains core world rendering, moons system, and UI components",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -7,6 +7,7 @@ async function makeTextureMaterial({
7
7
  opacity = 0.6,
8
8
  textureUrl,
9
9
  speed = 0.015,
10
+ renderer = null,
10
11
  } = {}) {
11
12
  const mat = new THREE.MeshStandardMaterial({
12
13
  color,
@@ -21,7 +22,9 @@ async function makeTextureMaterial({
21
22
  });
22
23
 
23
24
  if (textureUrl) {
24
- const tex = await loadTexture(textureUrl);
25
+ // Thread the owning view's renderer: KTX2 cloud textures must transcode against the caller's
26
+ // context, not the global fallback (which shared-renderer pages don't publish at all).
27
+ const tex = await loadTexture(textureUrl, { renderer });
25
28
  tex.wrapS = THREE.RepeatWrapping;
26
29
  tex.wrapT = THREE.RepeatWrapping;
27
30
  // Use linear space for alpha masks if available
@@ -60,6 +63,7 @@ export async function createCloudShell({
60
63
  color = 0xffffff,
61
64
  opacity = 0.6,
62
65
  speed = 0.015,
66
+ renderer = null,
63
67
  } = {}) {
64
68
  const geom = baseGeometry
65
69
  ? baseGeometry.clone()
@@ -70,6 +74,7 @@ export async function createCloudShell({
70
74
  opacity,
71
75
  textureUrl,
72
76
  speed,
77
+ renderer,
73
78
  });
74
79
 
75
80
  const mesh = new THREE.Mesh(geom, material);
@@ -4,12 +4,17 @@ import { makeSphere } from './worldTexture.js';
4
4
  import { makeNormalSphere } from './worldNormal.js';
5
5
 
6
6
  export class WorldManager {
7
- constructor(scene, { onLoadStart, onLoadEnd, renderer } = {}) {
7
+ constructor(scene, { onLoadStart, onLoadEnd, renderer, externalTick = false } = {}) {
8
8
  this.scene = scene;
9
9
  // The renderer this world belongs to — threaded to the texture loaders so each view's textures
10
10
  // bind to its OWN WebGL context (multi-view: N orbiters / N planets in one page). Falls back to
11
11
  // window.__EW_RENDERER for callers that don't pass one, keeping single-renderer apps unchanged.
12
12
  this.renderer = renderer ?? null;
13
+ // Shared-renderer hosts drive world animation from THEIR loop: with `externalTick` this manager
14
+ // starts no internal rAF for `userData.update` worlds — the host calls `tick(timeSec)` per
15
+ // rendered frame instead. Otherwise N animated worlds on one page would each run their own loop,
16
+ // defeating the one-loop compositor.
17
+ this.externalTick = Boolean(externalTick);
13
18
  this.current = null;
14
19
  this.flags = {};
15
20
  this.onLoadStart = onLoadStart;
@@ -19,6 +24,20 @@ export class WorldManager {
19
24
  this.customCreators = new Map();
20
25
  }
21
26
 
27
+ /** Run the current world's per-frame updater once (externalTick hosts only; no-op otherwise). */
28
+ tick(timeSec) {
29
+ if (!this.externalTick || !this.current) return;
30
+ const updater = this.current.userData?.update;
31
+ if (typeof updater !== 'function') return;
32
+ const renderer = this.renderer ?? (typeof window !== 'undefined' ? window.__EW_RENDERER : null);
33
+ if (!renderer) return;
34
+ try {
35
+ updater(renderer, timeSec);
36
+ } catch (e) {
37
+ console.warn('[WorldManager] update tick error:', e);
38
+ }
39
+ }
40
+
22
41
  setFlags(flags) {
23
42
  this.flags = { ...this.flags, ...flags };
24
43
  }
@@ -66,8 +85,9 @@ export class WorldManager {
66
85
  this.scene.add(obj);
67
86
  this.current = obj;
68
87
 
69
- // If the object exposes a frame updater, run a render-time loop
70
- if (obj && obj.userData && typeof obj.userData.update === 'function' && renderer) {
88
+ // If the object exposes a frame updater, run a render-time loop — unless an external host
89
+ // drives it via tick() (shared-renderer compositor: one loop for all worlds).
90
+ if (!this.externalTick && obj && obj.userData && typeof obj.userData.update === 'function' && renderer) {
71
91
  const updater = obj.userData.update;
72
92
  const tick = () => {
73
93
  if (this.current === obj) {
@@ -309,6 +309,7 @@ export async function makeSphere({
309
309
  color: cloudsColor,
310
310
  opacity: cloudsOpacity,
311
311
  speed: cloudsSpeed,
312
+ renderer,
312
313
  });
313
314
  mesh.add(cloudMesh);
314
315
  }