@kvyverse/world-runtime 0.1.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.
Files changed (96) hide show
  1. package/LICENSE.md +57 -0
  2. package/README.md +87 -0
  3. package/dist/BallCollider-8ZrxReEd.js +16 -0
  4. package/dist/CapsuleCollider-bynyf6Mc.js +20 -0
  5. package/dist/Collider-4_rCTHVA.js +82 -0
  6. package/dist/ConeCollider-DtRZmgK8.js +20 -0
  7. package/dist/ConvexMeshCollider-BSmDM4o3.js +14 -0
  8. package/dist/CuboidCollider-CJvq7--s.js +27 -0
  9. package/dist/CylinderCollider-CQPSh4tu.js +24 -0
  10. package/dist/FpsCameraController-BE2EirRj.js +55 -0
  11. package/dist/MeshInstansing-Bxij0Yc9.js +42 -0
  12. package/dist/PointerLockCameraControls-DYxxMeSw.js +104 -0
  13. package/dist/RapierDebugRenderer-sURZDLP4.js +55 -0
  14. package/dist/RapierFpsPlayerController-VsNfQl6v.js +142 -0
  15. package/dist/RapierPhysics-C_3b7QOn.js +74 -0
  16. package/dist/Rigidbody-b7QNF4ev.js +107 -0
  17. package/dist/ScalingToFro-BD-E5-uR.js +21 -0
  18. package/dist/SightInteractableArea-DrqyB41W.js +79 -0
  19. package/dist/SimpleWASDMovement-C2m53YYH.js +17 -0
  20. package/dist/Spinning-sgUhHld8.js +10 -0
  21. package/dist/StartAnimation-B9eomOS2.js +37 -0
  22. package/dist/TrimeshCollider-7dIs_xtZ.js +62 -0
  23. package/dist/World.d.ts +19 -0
  24. package/dist/WorldRuntime.d.ts +94 -0
  25. package/dist/behaviours/animation/ScalingToFro.d.ts +8 -0
  26. package/dist/behaviours/animation/Spinning.d.ts +5 -0
  27. package/dist/behaviours/animation/StartAnimation.d.ts +9 -0
  28. package/dist/behaviours/controls/FpsCameraController.d.ts +10 -0
  29. package/dist/behaviours/controls/PointerLockCameraControls.d.ts +28 -0
  30. package/dist/behaviours/controls/SimpleWASDMovement.d.ts +5 -0
  31. package/dist/behaviours/physics/BallCollider.d.ts +10 -0
  32. package/dist/behaviours/physics/CapsuleCollider.d.ts +14 -0
  33. package/dist/behaviours/physics/ConeCollider.d.ts +14 -0
  34. package/dist/behaviours/physics/ConvexMeshCollider.d.ts +6 -0
  35. package/dist/behaviours/physics/CuboidCollider.d.ts +22 -0
  36. package/dist/behaviours/physics/CylinderCollider.d.ts +18 -0
  37. package/dist/behaviours/physics/HalfspaceCollider.d.ts +7 -0
  38. package/dist/behaviours/physics/RapierFpsPlayerController.d.ts +35 -0
  39. package/dist/behaviours/physics/Rigidbody.d.ts +24 -0
  40. package/dist/behaviours/physics/TrimeshCollider.d.ts +9 -0
  41. package/dist/behaviours/physics/_required-patch.d.ts +10 -0
  42. package/dist/behaviours/physics/rapier-addon-core/Collider.d.ts +14 -0
  43. package/dist/behaviours/physics/rapier-addon-core/RapierDebugRenderer.d.ts +17 -0
  44. package/dist/behaviours/physics/rapier-addon-core/RapierPhysics.d.ts +131 -0
  45. package/dist/behaviours/physics/rapier-addon-core/get-scale-from-obj.d.ts +8 -0
  46. package/dist/behaviours/player/SightInteractableArea.d.ts +23 -0
  47. package/dist/behaviours/registry.d.ts +16 -0
  48. package/dist/behaviours/utils/MeshInstansing.d.ts +12 -0
  49. package/dist/bootstrap.d.ts +8 -0
  50. package/dist/define-world.d.ts +9 -0
  51. package/dist/get-scale-from-obj-QKv3Fig5.js +22 -0
  52. package/dist/index.d.ts +48 -0
  53. package/dist/index.js +1707 -0
  54. package/dist/modules/EnvModule.d.ts +11 -0
  55. package/dist/modules/HtmlHudModule.d.ts +14 -0
  56. package/dist/modules/InputSystemModule.d.ts +87 -0
  57. package/dist/modules/SoundsModule.d.ts +7 -0
  58. package/dist/modules/UtilsModule.d.ts +9 -0
  59. package/dist/modules/contracts/env.module-api.d.ts +7 -0
  60. package/dist/modules/contracts/html.module-api.d.ts +7 -0
  61. package/dist/modules/contracts/input.module-api.d.ts +31 -0
  62. package/dist/modules/contracts/rapier.module-api.d.ts +11 -0
  63. package/dist/modules/contracts/rapierDebug.module-api.d.ts +5 -0
  64. package/dist/modules/contracts/sounds.module-api.d.ts +5 -0
  65. package/dist/modules/contracts/utils.module-api.d.ts +7 -0
  66. package/dist/modules/index.d.ts +22 -0
  67. package/dist/modules/is-mobile-device.d.ts +1 -0
  68. package/dist/modules/registry.d.ts +31 -0
  69. package/dist/rendering/SceneBloom.d.ts +40 -0
  70. package/dist/rendering/renderer-apply.d.ts +14 -0
  71. package/dist/rendering/renderer-options.d.ts +11 -0
  72. package/dist/rendering/tsl-node.d.ts +21 -0
  73. package/dist/rendering/tsl-uniforms.d.ts +18 -0
  74. package/dist/resources/audio.d.ts +15 -0
  75. package/dist/resources/default-resources.d.ts +36 -0
  76. package/dist/resources/font.d.ts +32 -0
  77. package/dist/resources/geometry.d.ts +5 -0
  78. package/dist/resources/hdr.d.ts +6 -0
  79. package/dist/resources/loaders.d.ts +45 -0
  80. package/dist/resources/model.d.ts +24 -0
  81. package/dist/resources/texture.d.ts +8 -0
  82. package/dist/resources/video.d.ts +14 -0
  83. package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
  84. package/dist/settings/AddonsRuntime.d.ts +19 -0
  85. package/dist/settings/externals.d.ts +14 -0
  86. package/dist/settings/lib-loaders.d.ts +7 -0
  87. package/dist/settings/lib-registry.d.ts +24 -0
  88. package/dist/settings/module-registry.d.ts +25 -0
  89. package/dist/settings/types.d.ts +46 -0
  90. package/dist/types.d.ts +80 -0
  91. package/dist/utils/lazy.d.ts +4 -0
  92. package/dist/values.d.ts +6 -0
  93. package/dist/version.d.ts +10 -0
  94. package/dist/version.gen.d.ts +1 -0
  95. package/dist/world-events.d.ts +13 -0
  96. package/package.json +53 -0
package/LICENSE.md ADDED
@@ -0,0 +1,57 @@
1
+ # Kvyverse World Runtime License
2
+
3
+ Copyright (c) 2026 Vladislav Kruteniuk (Kvyverse). All rights reserved.
4
+
5
+ This package (`@kvyverse/world-runtime`, the "Software") is proprietary
6
+ software. It is **not** open source.
7
+
8
+ ## Grant
9
+
10
+ Subject to the terms below, you are granted a non-exclusive, non-transferable,
11
+ royalty-free license to:
12
+
13
+ 1. install the Software via a package manager as a dependency of your project;
14
+ 2. use the Software **solely to load and run worlds exported from the Kvyverse
15
+ platform** (https://kvyverse.com), including in commercial projects;
16
+ 3. bundle, minify and otherwise process the **unmodified** Software with
17
+ standard build tooling as part of building and deploying your application.
18
+
19
+ ## Restrictions
20
+
21
+ You may **not**:
22
+
23
+ 1. modify the Software or create derivative works of it;
24
+ 2. copy, publish or redistribute the Software or its source, except as an
25
+ installed dependency or inside the build output of your application as
26
+ permitted above;
27
+ 3. use the Software to load or run content that was not exported from the
28
+ Kvyverse platform, or as a general-purpose engine or runtime;
29
+ 4. reverse engineer, decompile or disassemble the Software, except to the
30
+ extent such restriction is prohibited by applicable law;
31
+ 5. remove or alter copyright or license notices.
32
+
33
+ ## Third-party software
34
+
35
+ The Software depends on third-party packages (`three`, `three-start`, `howler`,
36
+ `vanjs-core`, `eventemitter3`, `@tweenjs/tween.js`, `animejs`, optionally
37
+ `@dimforge/rapier3d-compat`). They
38
+ are installed separately and remain under their own licenses; this license
39
+ applies only to the Software itself.
40
+
41
+ ## Termination
42
+
43
+ This license terminates automatically if you breach its terms. Upon
44
+ termination you must stop using the Software and remove it from your
45
+ deployments.
46
+
47
+ ## Disclaimer
48
+
49
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
50
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
52
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
53
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
54
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
55
+ SOFTWARE.
56
+
57
+ For other licensing needs, contact: vladislove2402@gmail.com
package/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # @kvyverse/world-runtime
2
+
3
+ Runtime for worlds exported from [Kvyverse](https://kvyverse.com) — a web-based
4
+ 3D world editor. A world exported for self-hosting is a single generated JS
5
+ module; this package is the engine that module runs on.
6
+
7
+ You normally don't install this package by hand out of curiosity: it is only
8
+ useful together with a world module built by the Kvyverse editor
9
+ (`Export → Build for self-hosting`).
10
+
11
+ ## Install
12
+
13
+ ```
14
+ npm i @kvyverse/world-runtime three three-start
15
+ ```
16
+
17
+ All runtime dependencies are `peerDependencies`: the required ones (`howler`,
18
+ `vanjs-core`, `eventemitter3`) are auto-installed by npm 7+, while optional
19
+ ones (`@dimforge/rapier3d-compat` for physics, `@tweenjs/tween.js`, `animejs`)
20
+ are only needed when the world uses them — the export dialog shows the exact
21
+ install command for your world.
22
+
23
+ Requirements: ES modules, a bundler, WebGPU-capable browser
24
+ (`three/webgpu` renderer).
25
+
26
+ ## Usage
27
+
28
+ ```js
29
+ import { loadWorld } from "./my-world-3f9a1c02.js"; // file built by Kvyverse
30
+
31
+ const world = await loadWorld({ onProgress: (p) => console.log(p.stage) });
32
+ world.mount(document.getElementById("app")); // canvas + render loop
33
+ world.start(); // activates world behaviours
34
+ ```
35
+
36
+ `World` extends `ThreeStart` (from `three-start`), so the standard lifecycle
37
+ and context are available: `world.ctx.scene`, `world.ctx.camera`,
38
+ `world.ctx.renderer`, `unmount()`, `runLoop()` / `stopLoop()`, `dispose()`.
39
+ Extra: `world.getUrl(path)` resolves a world asset URL, `world.events` is the
40
+ world lifecycle emitter.
41
+
42
+ `loadWorld` options: `onProgress` callback, `dracoPath` (self-hosted Draco
43
+ decoder folder; defaults to Google's public one), `assetsBaseUrl` (only for
44
+ worlds built with relative asset paths).
45
+
46
+ Call `start()` after a user gesture if the world plays audio or captures the
47
+ pointer — browser policies require it.
48
+
49
+ ## License
50
+
51
+ Proprietary, see [LICENSE.md](./LICENSE.md). In short: free to use (including
52
+ commercially) **only to run worlds exported from Kvyverse**; no modification or
53
+ redistribution; bundling the unmodified package into your app build is allowed.
54
+
55
+ ---
56
+
57
+ ## Development (internal)
58
+
59
+ The app consumes this package **from sources** via the path alias
60
+ `@kvyverse/world-runtime` → `packages/world-runtime/src`; no build needed
61
+ locally. `npm run build:world-runtime` from the repo root produces
62
+ `dist/index.js` + `.d.ts`. The package is covered by the root `tsc -b` and
63
+ `npm run lint`.
64
+
65
+ | Folder | Contents |
66
+ | --- | --- |
67
+ | `modules/` | three-start ctx modules (`env`, `html`, `input`, `sounds`, `utils`) + their contracts and the `ThreeStartRegister` augment. `createWorldModules(mode)` is the single registration point (used by the game too). |
68
+ | `behaviours/` | Built-in behaviour classes (animation, controls, rapier physics), required patches, and the `uuid → class` registry — source of truth for the editor and the export. |
69
+ | `resources/` | Lazy three loaders (`AssetLoaders`), resource factories (`loadTexture`, `parseModel`/`loadModel`, `collectModelSubResources`, `parseHdr`, `parseGeometryJson`, `createAudio`, `createVideo`, `createFont`), built-in resources with fixed uuids (`getDefaultResource`). |
70
+ | `rendering/` | `SceneBloom` (+ MRT contracts), renderer config application, TSL node/uniform factories (`createTslNode`, `createUniformNode`). |
71
+ | `settings/` | World config types (`RendererConfig`, `AddonsConfig`), lib/module registries, `AddonsRuntime`. |
72
+ | `bootstrap.ts` | The world assembly order — the only place it is defined. |
73
+ | `World.ts` / `WorldRuntime.ts` | `ThreeStart` subclass for the host and the runtime state owner (resources by path, `require`, script execution, styles/fonts, `world.events`). |
74
+ | `world-events.ts` | `WorldEvent` lifecycle enum, shared with the game. |
75
+
76
+ Feature docs: [`/docs/self-hosted-export.md`](../../docs/self-hosted-export.md),
77
+ maintenance rules: [`/docs/self-hosted-export-maintenance.md`](../../docs/self-hosted-export-maintenance.md).
78
+
79
+ ### Publishing
80
+
81
+ ```
82
+ npm run build:world-runtime
83
+ cd packages/world-runtime && npm publish # publishConfig.access = public
84
+ ```
85
+
86
+ Versioning: exported worlds pin `^<version>` and update only via `npm update`,
87
+ so breaking runtime changes require a major bump (see maintenance doc).
@@ -0,0 +1,16 @@
1
+ import { n as getRadiusScale } from "./get-scale-from-obj-QKv3Fig5.js";
2
+ import { t as Collider } from "./Collider-4_rCTHVA.js";
3
+ //#region packages/world-runtime/src/behaviours/physics/BallCollider.ts
4
+ var BallCollider = class extends Collider {
5
+ type = "Ball";
6
+ /**
7
+ * @default 0.5
8
+ */
9
+ radius = .5;
10
+ getDesc(rapier) {
11
+ const scale = getRadiusScale(this.object);
12
+ return rapier.ColliderDesc.ball(this.radius * scale.radius);
13
+ }
14
+ };
15
+ //#endregion
16
+ export { BallCollider as default };
@@ -0,0 +1,20 @@
1
+ import { t as getHalfheightRadiusScale } from "./get-scale-from-obj-QKv3Fig5.js";
2
+ import { t as Collider } from "./Collider-4_rCTHVA.js";
3
+ //#region packages/world-runtime/src/behaviours/physics/CapsuleCollider.ts
4
+ var CapsuleCollider = class extends Collider {
5
+ type = "Capsule";
6
+ /**
7
+ * @default 0.5
8
+ */
9
+ halfHeight = .5;
10
+ /**
11
+ * @default 0.5
12
+ */
13
+ radius = .5;
14
+ getDesc(rapier) {
15
+ const scale = getHalfheightRadiusScale(this.object);
16
+ return rapier.ColliderDesc.capsule(this.halfHeight * scale.halfHeight, this.radius * scale.radius);
17
+ }
18
+ };
19
+ //#endregion
20
+ export { CapsuleCollider as default };
@@ -0,0 +1,82 @@
1
+ import { t as Rigidbody } from "./Rigidbody-b7QNF4ev.js";
2
+ import * as THREE from "three/webgpu";
3
+ import { Object3DBehaviour, assertDefined, getComponents } from "three-start";
4
+ //#region packages/world-runtime/src/behaviours/physics/rapier-addon-core/Collider.ts
5
+ /** Walk the parent chain (ancestors only); stop when `cb` returns `false`. */
6
+ function traverseUp(obj, cb) {
7
+ let cur = obj.parent;
8
+ while (cur) {
9
+ if (cb(cur) === false) return;
10
+ cur = cur.parent;
11
+ }
12
+ }
13
+ function findRigidbody(obj) {
14
+ return getComponents(obj).find((x) => x instanceof Rigidbody) ?? null;
15
+ }
16
+ var Collider = class extends Object3DBehaviour {
17
+ get instance() {
18
+ return assertDefined(this._instance, "_instance");
19
+ }
20
+ _instance;
21
+ _world;
22
+ _vt = new THREE.Vector3();
23
+ onEnable() {
24
+ const obj = this.object;
25
+ const rapier = this.modules.rapier;
26
+ const world = rapier.world;
27
+ const Rapier = rapier.api;
28
+ const desc = this.getDesc(Rapier);
29
+ if (desc === null) {
30
+ console.error("colldier desc is null");
31
+ return;
32
+ }
33
+ this._world = world;
34
+ let rbF = findRigidbody(obj);
35
+ let rbObj = rbF?.object ?? null;
36
+ if (!rbF) traverseUp(obj, (ancestor) => {
37
+ const found = findRigidbody(ancestor);
38
+ if (found) {
39
+ rbF = found;
40
+ rbObj = ancestor;
41
+ }
42
+ return !found;
43
+ });
44
+ if (!(rbF && rbObj)) {
45
+ const pos = obj.getWorldPosition(_v);
46
+ const quat = obj.getWorldQuaternion(_qt);
47
+ desc.setTranslation(pos.x, pos.y, pos.z).setRotation(quat);
48
+ this._instance = world.createCollider(desc);
49
+ } else {
50
+ const rbType = rbF.rigidbodyType;
51
+ const shapeType = desc.shape.type;
52
+ const isNonConvex = shapeType === Rapier.ShapeType.TriMesh || shapeType === Rapier.ShapeType.HeightField;
53
+ const isDynamicOrKinematic = rbType === Rapier.RigidBodyType.Dynamic || rbType === Rapier.RigidBodyType.KinematicPositionBased || rbType === Rapier.RigidBodyType.KinematicVelocityBased;
54
+ if (isNonConvex && isDynamicOrKinematic) {
55
+ console.warn(`[Collider] Incompatible shape (${Rapier.ShapeType[shapeType]}) with rigidbody type (${Rapier.RigidBodyType[rbType]}). TriMesh and HeightField are only supported on Fixed bodies.`);
56
+ return;
57
+ }
58
+ if (rbObj !== obj) {
59
+ const localPos = _v.set(0, 0, 0);
60
+ const localQuat = _qt.set(0, 0, 0, 1);
61
+ rbObj.worldToLocal(obj.getWorldPosition(localPos));
62
+ const worldQ = obj.getWorldQuaternion(_qt);
63
+ const rbWorldQ = rbObj.getWorldQuaternion(_qt2);
64
+ localQuat.copy(rbWorldQ.invert()).multiply(worldQ);
65
+ desc.setTranslation(localPos.x, localPos.y, localPos.z).setRotation(localQuat);
66
+ }
67
+ rbF.withReady((rb) => {
68
+ this._instance = world.createCollider(desc, rb);
69
+ });
70
+ }
71
+ }
72
+ onDisable() {
73
+ if (this._instance && this._world) this._world.removeCollider(this._instance, true);
74
+ this._instance = void 0;
75
+ this._world = void 0;
76
+ }
77
+ };
78
+ var _v = new THREE.Vector3();
79
+ var _qt = new THREE.Quaternion();
80
+ var _qt2 = new THREE.Quaternion();
81
+ //#endregion
82
+ export { Collider as t };
@@ -0,0 +1,20 @@
1
+ import { t as getHalfheightRadiusScale } from "./get-scale-from-obj-QKv3Fig5.js";
2
+ import { t as Collider } from "./Collider-4_rCTHVA.js";
3
+ //#region packages/world-runtime/src/behaviours/physics/ConeCollider.ts
4
+ var ConeCollider = class extends Collider {
5
+ type = "Cone";
6
+ /**
7
+ * @default 0.5
8
+ */
9
+ halfHeight = .5;
10
+ /**
11
+ * @default 0.5
12
+ */
13
+ radius = .5;
14
+ getDesc(rapier) {
15
+ const scale = getHalfheightRadiusScale(this.object);
16
+ return rapier.ColliderDesc.cone(this.halfHeight * scale.halfHeight, this.radius * scale.radius);
17
+ }
18
+ };
19
+ //#endregion
20
+ export { ConeCollider as default };
@@ -0,0 +1,14 @@
1
+ import { t as Collider } from "./Collider-4_rCTHVA.js";
2
+ //#region packages/world-runtime/src/behaviours/physics/ConvexMeshCollider.ts
3
+ var ConvexMeshCollider = class extends Collider {
4
+ type = "Convex";
5
+ getDesc(rapier) {
6
+ const mesh = this.object;
7
+ if (!mesh.isMesh || !mesh.geometry) return null;
8
+ mesh.updateWorldMatrix(true, false);
9
+ const positions = mesh.geometry.attributes.position.array;
10
+ return rapier.ColliderDesc.convexHull(positions);
11
+ }
12
+ };
13
+ //#endregion
14
+ export { ConvexMeshCollider as default };
@@ -0,0 +1,27 @@
1
+ import { t as Collider } from "./Collider-4_rCTHVA.js";
2
+ //#region packages/world-runtime/src/behaviours/physics/CuboidCollider.ts
3
+ var CuboidCollider = class extends Collider {
4
+ type = "Cuboid";
5
+ /**
6
+ * @default 0.5
7
+ */
8
+ hx = .5;
9
+ /**
10
+ * @default 0.5
11
+ */
12
+ hy = .5;
13
+ /**
14
+ * @default 0.5
15
+ */
16
+ hz = .5;
17
+ /**
18
+ * @default true
19
+ */
20
+ useObjectScale = true;
21
+ getDesc(rapier) {
22
+ const s = this.object.getWorldScale(this._vt);
23
+ return rapier.ColliderDesc.cuboid(this.hx * s.x, this.hy * s.y, this.hz * s.z);
24
+ }
25
+ };
26
+ //#endregion
27
+ export { CuboidCollider as default };
@@ -0,0 +1,24 @@
1
+ import { t as getHalfheightRadiusScale } from "./get-scale-from-obj-QKv3Fig5.js";
2
+ import { t as Collider } from "./Collider-4_rCTHVA.js";
3
+ //#region packages/world-runtime/src/behaviours/physics/CylinderCollider.ts
4
+ var CylinderCollider = class extends Collider {
5
+ type = "Cylinder";
6
+ /**
7
+ * @default 0.5
8
+ */
9
+ halfHeight = .5;
10
+ /**
11
+ * @default 0.5
12
+ */
13
+ radius = .5;
14
+ /**
15
+ * @default true
16
+ */
17
+ useObjectScale = true;
18
+ getDesc(rapier) {
19
+ const scale = getHalfheightRadiusScale(this.object);
20
+ return rapier.ColliderDesc.cylinder(this.halfHeight * scale.halfHeight, this.radius * scale.radius);
21
+ }
22
+ };
23
+ //#endregion
24
+ export { CylinderCollider as default };
@@ -0,0 +1,55 @@
1
+ import { Object3DBehaviour } from "three-start";
2
+ //#region packages/world-runtime/src/behaviours/controls/FpsCameraController.ts
3
+ var FpsCameraController = class extends Object3DBehaviour {
4
+ sensitivity = .002;
5
+ mobileSensitivity = .006;
6
+ inverted = false;
7
+ useInvertedOnMobile = true;
8
+ _detach;
9
+ onEnable() {
10
+ const renderer = this.ctx.renderer;
11
+ let isDragging = false;
12
+ let prevX = 0;
13
+ let prevY = 0;
14
+ const isMobile = !!this.modules.input.player.mode;
15
+ const sensitivity = isMobile ? this.mobileSensitivity : this.sensitivity;
16
+ const inverted = isMobile && this.useInvertedOnMobile ? true : this.inverted;
17
+ const onMouseDown = (e) => {
18
+ isDragging = true;
19
+ prevX = e.clientX;
20
+ prevY = e.clientY;
21
+ };
22
+ const onMouseUp = () => {
23
+ isDragging = false;
24
+ };
25
+ const onMouseMove = (e) => {
26
+ if (!isDragging) return;
27
+ const sign = inverted ? 1 : -1;
28
+ const cam = this.ctx.camera;
29
+ const dx = e.clientX - prevX;
30
+ const dy = e.clientY - prevY;
31
+ prevX = e.clientX;
32
+ prevY = e.clientY;
33
+ this.object.rotation.y += dx * sensitivity * sign;
34
+ let pitch = cam.rotation.x;
35
+ pitch += dy * sensitivity * sign;
36
+ pitch = Math.max(-Math.PI / 2, Math.min(Math.PI / 2, pitch));
37
+ cam.rotation.x = pitch;
38
+ };
39
+ const dom = renderer.domElement;
40
+ dom.addEventListener("pointerdown", onMouseDown);
41
+ dom.addEventListener("pointerup", onMouseUp);
42
+ dom.addEventListener("pointermove", onMouseMove);
43
+ this._detach = () => {
44
+ dom.removeEventListener("pointerdown", onMouseDown);
45
+ dom.removeEventListener("pointerup", onMouseUp);
46
+ dom.removeEventListener("pointermove", onMouseMove);
47
+ };
48
+ }
49
+ onDisable() {
50
+ this._detach?.();
51
+ this._detach = void 0;
52
+ }
53
+ };
54
+ //#endregion
55
+ export { FpsCameraController as default };
@@ -0,0 +1,42 @@
1
+ import * as THREE from "three/webgpu";
2
+ import { Object3DBehaviour } from "three-start";
3
+ //#region packages/world-runtime/src/behaviours/utils/MeshInstansing.ts
4
+ var MeshInstansing = class MeshInstansing extends Object3DBehaviour {
5
+ static _totalInstance = 0;
6
+ geometry = null;
7
+ material = null;
8
+ transformsRoot = null;
9
+ useThisAsRoot = true;
10
+ _detach;
11
+ onEnable() {
12
+ const geom = this.geometry;
13
+ const mat = this.material;
14
+ const root = this.useThisAsRoot ? this.object : this.transformsRoot;
15
+ if (!geom || !mat || !root) return;
16
+ const children = root.children;
17
+ const count = children.length;
18
+ MeshInstansing._totalInstance += count;
19
+ const instanced = new THREE.InstancedMesh(geom, mat, count);
20
+ for (let i = 0; i < count; i++) {
21
+ const obj = children[i];
22
+ dummy.position.copy(obj.position);
23
+ dummy.quaternion.copy(obj.quaternion);
24
+ dummy.scale.copy(obj.scale);
25
+ dummy.updateMatrix();
26
+ instanced.setMatrixAt(i, dummy.matrix);
27
+ }
28
+ instanced.instanceMatrix.needsUpdate = true;
29
+ this.object.add(instanced);
30
+ this._detach = () => {
31
+ instanced.removeFromParent();
32
+ instanced.dispose();
33
+ };
34
+ }
35
+ onDisable() {
36
+ this._detach?.();
37
+ this._detach = void 0;
38
+ }
39
+ };
40
+ var dummy = new THREE.Object3D();
41
+ //#endregion
42
+ export { MeshInstansing as default };
@@ -0,0 +1,104 @@
1
+ import * as THREE from "three/webgpu";
2
+ import { Object3DBehaviour } from "three-start";
3
+ //#region packages/world-runtime/src/behaviours/controls/PointerLockCameraControls.ts
4
+ var _euler = new THREE.Euler(0, 0, 0, "YXZ");
5
+ var _vector = new THREE.Vector3();
6
+ var _MOUSE_SENSITIVITY = .002;
7
+ var _PI_2 = Math.PI / 2;
8
+ var PointerLockCameraControls = class extends Object3DBehaviour {
9
+ isLocked = false;
10
+ minPolarAngle = 0;
11
+ maxPolarAngle = Math.PI;
12
+ pointerSpeed = 1;
13
+ mobilePointerSpeed = 1.8;
14
+ domElement = null;
15
+ _canBeLocked = true;
16
+ _isMobile = false;
17
+ _detach;
18
+ onEnable() {
19
+ const env = this.modules.env;
20
+ this._canBeLocked = env.prod && !env.isMobile;
21
+ this._isMobile = env.isMobile;
22
+ const dom = this.ctx.renderer.domElement;
23
+ const lock = () => {
24
+ this.lock(true);
25
+ };
26
+ dom.addEventListener("click", lock);
27
+ this.connect(dom);
28
+ this._detach = () => {
29
+ dom.removeEventListener("click", lock);
30
+ this.disconnect();
31
+ };
32
+ }
33
+ onDisable() {
34
+ this._detach?.();
35
+ this._detach = void 0;
36
+ }
37
+ _onPointerMove = (event) => {
38
+ if (this._canBeLocked && !this.isLocked) return;
39
+ const camera = this.object;
40
+ _euler.setFromQuaternion(camera.quaternion);
41
+ const pointerSpeed = this._isMobile ? this.mobilePointerSpeed : this.pointerSpeed;
42
+ _euler.y -= event.movementX * _MOUSE_SENSITIVITY * pointerSpeed;
43
+ _euler.x -= event.movementY * _MOUSE_SENSITIVITY * pointerSpeed;
44
+ _euler.x = Math.max(_PI_2 - this.maxPolarAngle, Math.min(_PI_2 - this.minPolarAngle, _euler.x));
45
+ camera.quaternion.setFromEuler(_euler);
46
+ camera.rotation.setFromQuaternion(camera.quaternion, camera.rotation.order);
47
+ this.emit("change");
48
+ };
49
+ _onPointerlockChange = () => {
50
+ if (!this.domElement) return;
51
+ if (this.domElement.ownerDocument.pointerLockElement === this.domElement) {
52
+ this.emit("lock");
53
+ this.isLocked = true;
54
+ } else {
55
+ this.emit("unlock");
56
+ this.isLocked = false;
57
+ }
58
+ };
59
+ connect(element) {
60
+ if (this.domElement !== null) this.disconnect();
61
+ this.domElement = element;
62
+ const dom = this.domElement;
63
+ if (this._canBeLocked) {
64
+ dom.ownerDocument.addEventListener("pointermove", this._onPointerMove);
65
+ dom.ownerDocument.addEventListener("pointerlockchange", this._onPointerlockChange);
66
+ dom.ownerDocument.addEventListener("pointerlockerror", onPointerlockError);
67
+ } else dom.addEventListener("pointermove", this._onPointerMove);
68
+ }
69
+ disconnect() {
70
+ const dom = this.domElement;
71
+ if (!dom) return;
72
+ if (this._canBeLocked) {
73
+ dom.ownerDocument.removeEventListener("pointermove", this._onPointerMove);
74
+ dom.ownerDocument.removeEventListener("pointerlockchange", this._onPointerlockChange);
75
+ dom.ownerDocument.removeEventListener("pointerlockerror", onPointerlockError);
76
+ } else dom.removeEventListener("pointermove", this._onPointerMove);
77
+ this.domElement = null;
78
+ }
79
+ getDirection(v) {
80
+ return v.set(0, 0, -1).applyQuaternion(this.object.quaternion);
81
+ }
82
+ moveForward(distance) {
83
+ const camera = this.object;
84
+ _vector.setFromMatrixColumn(camera.matrix, 0);
85
+ _vector.crossVectors(camera.up, _vector);
86
+ camera.position.addScaledVector(_vector, distance);
87
+ }
88
+ moveRight(distance) {
89
+ const camera = this.object;
90
+ _vector.setFromMatrixColumn(camera.matrix, 0);
91
+ camera.position.addScaledVector(_vector, distance);
92
+ }
93
+ lock(unadjustedMovement = false) {
94
+ this.domElement?.requestPointerLock({ unadjustedMovement });
95
+ }
96
+ unlock() {
97
+ this.domElement?.ownerDocument.exitPointerLock();
98
+ }
99
+ };
100
+ function onPointerlockError() {
101
+ console.error("THREE.PointerLockControls: Unable to use Pointer Lock API");
102
+ }
103
+ //#endregion
104
+ export { PointerLockCameraControls as default };
@@ -0,0 +1,55 @@
1
+ import { t as RapierPhysics } from "./RapierPhysics-C_3b7QOn.js";
2
+ import * as THREE from "three/webgpu";
3
+ import { ContextModule } from "three-start";
4
+ //#region packages/world-runtime/src/behaviours/physics/rapier-addon-core/RapierDebugRenderer.ts
5
+ /**
6
+ * @see {@link https://github.com/vladkrutenyuk/three-kvy-core/blob/main/src/addons/RapierDebugRenderer.ts | Source}
7
+ */
8
+ var RapierDebugRenderer = class extends ContextModule {
9
+ _lines;
10
+ get enabled() {
11
+ return this._enabled;
12
+ }
13
+ set enabled(value) {
14
+ const lines = this._lines;
15
+ if (lines) lines.visible = value;
16
+ this._enabled = value;
17
+ }
18
+ _enabled = true;
19
+ _clear;
20
+ _inited = false;
21
+ /** three-start ContextModule has no onDestroy; teardown is explicit. */
22
+ dispose() {
23
+ this._clear?.();
24
+ }
25
+ init() {
26
+ if (this._inited) return;
27
+ this._inited = true;
28
+ const ctx = this.ctx;
29
+ const rapier = RapierPhysics.findInCtx(ctx);
30
+ if (!rapier) return;
31
+ const lines = new THREE.LineSegments(new THREE.BufferGeometry(), new THREE.LineBasicMaterial({
32
+ color: 16777215,
33
+ vertexColors: true
34
+ }));
35
+ lines.frustumCulled = false;
36
+ lines.visible = this._enabled;
37
+ ctx.scene.add(lines);
38
+ const draw = () => {
39
+ const { vertices, colors } = rapier.world.debugRender();
40
+ lines.geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
41
+ lines.geometry.setAttribute("color", new THREE.BufferAttribute(colors, 4));
42
+ lines.visible = true;
43
+ };
44
+ rapier.on("stepafter", draw);
45
+ this._clear = () => {
46
+ this._lines = void 0;
47
+ lines.removeFromParent();
48
+ lines.geometry.dispose();
49
+ lines.material.dispose();
50
+ rapier.off("stepafter", draw);
51
+ };
52
+ }
53
+ };
54
+ //#endregion
55
+ export { RapierDebugRenderer, RapierDebugRenderer as default };