@kvyverse/world-runtime 0.7.0 → 0.10.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/README.md CHANGED
@@ -73,14 +73,23 @@ pointer, call `start()` from a user gesture — browsers require it.
73
73
 
74
74
  ### The `world` object
75
75
 
76
- `World` extends `ThreeStart` from `three-start`, so the usual lifecycle and
77
- context are yours:
76
+ `World` extends `ThreeStart` from `three-start` (0.3 or newer), so the usual
77
+ lifecycle and context are yours. An exception in a behaviour or module hook, or
78
+ in a `world.ctx` listener, doesn't stop the world: three-start logs it to the
79
+ console, or hands it to your `world.ctx.on(ThreeContextEvents.Error, (error,
80
+ source, hook) => …)` listener if you add one.
78
81
 
79
82
  ```js
80
83
  world.ctx.scene, world.ctx.camera, world.ctx.renderer
81
84
  world.unmount(), world.runLoop(), world.stopLoop(), world.dispose()
82
85
  ```
83
86
 
87
+ `world.ctx.camera` starts as the world's main camera: the one picked in the
88
+ editor's Scene settings, otherwise the first perspective camera in the scene,
89
+ prefab and model contents included, otherwise the first orthographic one
90
+ (`resolveMainCamera`). An orthographic main camera is `world.ctx.ortho`, and
91
+ `world.ctx.isOrtho` is `true`.
92
+
84
93
  On top of that: `world.getUrl(path)` resolves an asset URL the same way scripts
85
94
  inside the world do, `world.events` is the world lifecycle emitter (the same
86
95
  `world.events` your scripts use), and `world.stores` is the world's shared
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export type { InstantiateOptions, PrefabFactory } from "./WorldRuntime";
4
4
  export { setColor } from "./values";
5
5
  export { RUNTIME_VERSION, WORLD_FORMAT_VERSION } from "./version";
6
6
  export { WorldEvent } from "./world-events";
7
+ export { isMainCameraKind, resolveMainCamera, setActiveCamera } from "./main-camera";
7
8
  export { lazyProxy } from "./utils/lazy";
8
9
  export { WorldStores } from "./world-stores";
9
10
  export type { WorldStore } from "./world-stores";
@@ -26,7 +27,7 @@ export { BUILTIN_BEHAVIOUR_LIST, BUILTIN_BEHAVIOURS, getBuiltinBehaviour, } from
26
27
  export type { BuiltinBehaviour, RequiredPatch } from "./behaviours/registry";
27
28
  export { rapierPhysicsPatch } from "./behaviours/physics/_required-patch";
28
29
  export { AddonsRuntime } from "./addons/AddonsRuntime";
29
- export { applyRendererConfig } from "./rendering/renderer-apply";
30
+ export { applyRendererConfig, resolveToneMapping } from "./rendering/renderer-apply";
30
31
  export { enableSceneEmissiveMrt, SceneBloom } from "./rendering/SceneBloom";
31
32
  export { createTslNode, TslNode } from "./rendering/tsl-node";
32
33
  export type { TslNodeBuilder } from "./rendering/tsl-node";
package/dist/index.js CHANGED
@@ -204,11 +204,15 @@ var TONE_MAPPINGS = {
204
204
  function applyRendererConfig(renderer, cfg) {
205
205
  renderer.shadowMap.enabled = cfg.shadowMap?.enabled ?? true;
206
206
  renderer.shadowMap.type = SHADOW_MAP_TYPES$1[cfg.shadowMap?.type ?? "PCFSoft"] ?? THREE.PCFSoftShadowMap;
207
- renderer.toneMapping = TONE_MAPPINGS[cfg.toneMapping ?? "Neutral"] ?? THREE.NeutralToneMapping;
207
+ renderer.toneMapping = resolveToneMapping(cfg.toneMapping);
208
208
  const pr = cfg.pixelResolution;
209
209
  const pixelResolution = typeof pr === "number" && Number.isFinite(pr) && pr > 0 ? pr : 1;
210
210
  renderer.setPixelRatio(window.devicePixelRatio * pixelResolution);
211
211
  }
212
+ /** `RendererConfig.toneMapping` → three constant; a missing or bad name falls back to Neutral. */
213
+ function resolveToneMapping(name) {
214
+ return TONE_MAPPINGS[name ?? "Neutral"] ?? THREE.NeutralToneMapping;
215
+ }
212
216
  //#endregion
213
217
  //#region packages/world-runtime/src/rendering/SceneBloom.ts
214
218
  /** BloomNode loads as a chunk only when bloom is enabled. */
@@ -1608,7 +1612,7 @@ function isAbsoluteUrl(url) {
1608
1612
  }
1609
1613
  //#endregion
1610
1614
  //#region packages/world-runtime/src/version.gen.ts
1611
- var RUNTIME_VERSION = "0.7.0";
1615
+ var RUNTIME_VERSION = "0.10.0";
1612
1616
  //#endregion
1613
1617
  //#region packages/world-runtime/src/version.ts
1614
1618
  /**
@@ -1624,6 +1628,46 @@ function assertFormatVersion(version) {
1624
1628
  throw new Error(`@kvyverse/world-runtime: world format v${version} is not supported by runtime (expected v1). Re-export the world or pin a matching runtime version.`);
1625
1629
  }
1626
1630
  //#endregion
1631
+ //#region packages/world-runtime/src/main-camera.ts
1632
+ /**
1633
+ * The camera a world starts from: the one picked in scene settings, otherwise the
1634
+ * first `PerspectiveCamera` depth-first, otherwise the first `OrthographicCamera`.
1635
+ * One rule for Play, the editor and export.
1636
+ */
1637
+ function resolveMainCamera(explicit, roots) {
1638
+ if (isMainCameraKind(explicit)) return explicit;
1639
+ const found = { ortho: null };
1640
+ for (const root of roots) {
1641
+ const perspective = findCameras(root, found);
1642
+ if (perspective) return perspective;
1643
+ }
1644
+ return found.ortho;
1645
+ }
1646
+ /** Makes the camera active, through the accessor that matches its kind. */
1647
+ function setActiveCamera(ctx, camera) {
1648
+ if (isOrthographicCamera(camera)) ctx.ortho = camera;
1649
+ else ctx.camera = camera;
1650
+ }
1651
+ /** A camera that can be the main one (`ThreeStartCamera`). */
1652
+ function isMainCameraKind(value) {
1653
+ return isPerspectiveCamera(value) || isOrthographicCamera(value);
1654
+ }
1655
+ function findCameras(obj, found) {
1656
+ if (isPerspectiveCamera(obj)) return obj;
1657
+ if (!found.ortho && isOrthographicCamera(obj)) found.ortho = obj;
1658
+ for (const child of obj.children) {
1659
+ const perspective = findCameras(child, found);
1660
+ if (perspective) return perspective;
1661
+ }
1662
+ return null;
1663
+ }
1664
+ function isPerspectiveCamera(value) {
1665
+ return !!value?.isPerspectiveCamera;
1666
+ }
1667
+ function isOrthographicCamera(value) {
1668
+ return !!value?.isOrthographicCamera;
1669
+ }
1670
+ //#endregion
1627
1671
  //#region packages/world-runtime/src/bootstrap.ts
1628
1672
  /**
1629
1673
  * World assembly order. The only place where it is fixed: the artifact supplies
@@ -1650,7 +1694,8 @@ async function bootstrapWorld(definition, options) {
1650
1694
  await runtime.applyRequiredPatches(world);
1651
1695
  runtime.reportProgress("Applying scene settings");
1652
1696
  definition.applySceneSettings?.(runtime, world.ctx.scene);
1653
- if (built.camera) world.ctx.camera = built.camera;
1697
+ const camera = resolveMainCamera(built.camera, built.children);
1698
+ if (camera) setActiveCamera(world.ctx, camera);
1654
1699
  runtime.reportProgress("Running scripts");
1655
1700
  runtime.mountFonts();
1656
1701
  runtime.mountStyles();
@@ -2208,4 +2253,4 @@ var TONE_MAPPING_NAMES = [
2208
2253
  "Neutral"
2209
2254
  ];
2210
2255
  //#endregion
2211
- export { AddonsRuntime, AssetLoaders, AudioSource, BLOOM_MODES, BUILTIN_BEHAVIOURS, BUILTIN_BEHAVIOUR_LIST, BUILTIN_LIB_DESCRIPTORS, CHAT_INPUT_MODES, DEFAULT_RESOURCE_IDS, DefaultResourceId, EXTERNAL_TYPES, EnvModule, FontSource, HtmlHudModule, InputSystemModule, LIBS, LIB_DESCRIPTORS, LIB_IDS, LOADING_MANAGER, LibId, MaterialShader, NullPlatformModule, OPTIONAL_LIB_DESCRIPTORS, OPTIONAL_LIB_IDS, OPTIONAL_MODULES, OPTIONAL_MODULE_IDS, OptionalModuleId, PHYSICS_ENGINES, RUNTIME_VERSION, SHADOW_MAP_TYPES, SceneBloom, SoundsModule, TONE_MAPPING_NAMES, TslNode, UNIFORM_DEFAULTS, UNIFORM_TYPES, UtilsModule, VideoSource, WORLD_FORMAT_VERSION, World, WorldEvent, WorldStores, applyRendererConfig, applyTextureDefaults, collectModelSubResources, collectRequiredLibs, configureAssetLoaders, createAudio, createFont, createMaterialShader, createTslNode, createUniformNode, createUniformValuesView, createVideo, createWorldModules, defineWorld, enableSceneEmissiveMrt, fontFormatFromMime, getBuiltinBehaviour, getDefaultResource, getHalfheightRadiusScale, getOptionalModuleDescriptor, getRadiusScale, getUniformNodeValue, isDefaultResourceId, isMobileDevice, isUniformType, lazyProxy, libByRequireKey, loadGeometry, loadHdr, loadModel, loadTexture, normalizeChat, normalizePhysics, parseGeometryJson, parseHdr, parseModel, rapierPhysicsPatch, readMaterialShaderOutputs, setColor, setUniformNodeValue, uniformType };
2256
+ export { AddonsRuntime, AssetLoaders, AudioSource, BLOOM_MODES, BUILTIN_BEHAVIOURS, BUILTIN_BEHAVIOUR_LIST, BUILTIN_LIB_DESCRIPTORS, CHAT_INPUT_MODES, DEFAULT_RESOURCE_IDS, DefaultResourceId, EXTERNAL_TYPES, EnvModule, FontSource, HtmlHudModule, InputSystemModule, LIBS, LIB_DESCRIPTORS, LIB_IDS, LOADING_MANAGER, LibId, MaterialShader, NullPlatformModule, OPTIONAL_LIB_DESCRIPTORS, OPTIONAL_LIB_IDS, OPTIONAL_MODULES, OPTIONAL_MODULE_IDS, OptionalModuleId, PHYSICS_ENGINES, RUNTIME_VERSION, SHADOW_MAP_TYPES, SceneBloom, SoundsModule, TONE_MAPPING_NAMES, TslNode, UNIFORM_DEFAULTS, UNIFORM_TYPES, UtilsModule, VideoSource, WORLD_FORMAT_VERSION, World, WorldEvent, WorldStores, applyRendererConfig, applyTextureDefaults, collectModelSubResources, collectRequiredLibs, configureAssetLoaders, createAudio, createFont, createMaterialShader, createTslNode, createUniformNode, createUniformValuesView, createVideo, createWorldModules, defineWorld, enableSceneEmissiveMrt, fontFormatFromMime, getBuiltinBehaviour, getDefaultResource, getHalfheightRadiusScale, getOptionalModuleDescriptor, getRadiusScale, getUniformNodeValue, isDefaultResourceId, isMainCameraKind, isMobileDevice, isUniformType, lazyProxy, libByRequireKey, loadGeometry, loadHdr, loadModel, loadTexture, normalizeChat, normalizePhysics, parseGeometryJson, parseHdr, parseModel, rapierPhysicsPatch, readMaterialShaderOutputs, resolveMainCamera, resolveToneMapping, setActiveCamera, setColor, setUniformNodeValue, uniformType };
@@ -0,0 +1,12 @@
1
+ import type * as THREE from "three/webgpu";
2
+ import type { ThreeContext, ThreeStartCamera } from "three-start";
3
+ /**
4
+ * The camera a world starts from: the one picked in scene settings, otherwise the
5
+ * first `PerspectiveCamera` depth-first, otherwise the first `OrthographicCamera`.
6
+ * One rule for Play, the editor and export.
7
+ */
8
+ export declare function resolveMainCamera(explicit: unknown, roots: readonly THREE.Object3D[]): ThreeStartCamera | null;
9
+ /** Makes the camera active, through the accessor that matches its kind. */
10
+ export declare function setActiveCamera(ctx: ThreeContext, camera: ThreeStartCamera): void;
11
+ /** A camera that can be the main one (`ThreeStartCamera`). */
12
+ export declare function isMainCameraKind(value: unknown): value is ThreeStartCamera;
@@ -12,3 +12,5 @@ import type { RendererConfig } from "./types";
12
12
  * `undefined` constant / `NaN` (silently broken rendering).
13
13
  */
14
14
  export declare function applyRendererConfig(renderer: THREE.Renderer, cfg: RendererConfig): void;
15
+ /** `RendererConfig.toneMapping` → three constant; a missing or bad name falls back to Neutral. */
16
+ export declare function resolveToneMapping(name: string | undefined): THREE.ToneMapping;
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Object3DBehaviourConstructor } from "three-start";
1
+ import type { Object3DBehaviourConstructor, ThreeStartCamera } from "three-start";
2
2
  import type { AddonsConfig, WorldImports } from "./addons/types";
3
3
  import type { RendererConfig } from "./rendering/types";
4
4
  import type * as THREE from "three/webgpu";
@@ -11,7 +11,8 @@ export type ScriptTable = Record<string, ScriptModule>;
11
11
  /** Result of constructing the scene hierarchy (before values are applied). */
12
12
  export interface SceneBuildResult {
13
13
  children: THREE.Object3D[];
14
- camera?: THREE.PerspectiveCamera | null;
14
+ /** The main camera picked in scene settings; absent — the first one in `children`. */
15
+ camera?: ThreeStartCamera | null;
15
16
  }
16
17
  /** Load-step details for the user's UI. */
17
18
  export interface WorldLoadProgress {
@@ -1 +1 @@
1
- export declare const RUNTIME_VERSION = "0.7.0";
1
+ export declare const RUNTIME_VERSION = "0.10.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kvyverse/world-runtime",
3
- "version": "0.7.0",
3
+ "version": "0.10.0",
4
4
  "description": "Runtime for worlds exported from the Kvyverse platform for self-hosting",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "author": "Kvyverse, Inc.",
@@ -39,7 +39,7 @@
39
39
  "nipplejs": "^0.10.2",
40
40
  "stats.js": "^0.17.0",
41
41
  "three": "^0.184.0",
42
- "three-start": "^0.1.3",
42
+ "three-start": "^0.3.1",
43
43
  "vanjs-core": "^1.6.0"
44
44
  },
45
45
  "peerDependenciesMeta": {