@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.
- package/LICENSE.md +57 -0
- package/README.md +87 -0
- package/dist/BallCollider-8ZrxReEd.js +16 -0
- package/dist/CapsuleCollider-bynyf6Mc.js +20 -0
- package/dist/Collider-4_rCTHVA.js +82 -0
- package/dist/ConeCollider-DtRZmgK8.js +20 -0
- package/dist/ConvexMeshCollider-BSmDM4o3.js +14 -0
- package/dist/CuboidCollider-CJvq7--s.js +27 -0
- package/dist/CylinderCollider-CQPSh4tu.js +24 -0
- package/dist/FpsCameraController-BE2EirRj.js +55 -0
- package/dist/MeshInstansing-Bxij0Yc9.js +42 -0
- package/dist/PointerLockCameraControls-DYxxMeSw.js +104 -0
- package/dist/RapierDebugRenderer-sURZDLP4.js +55 -0
- package/dist/RapierFpsPlayerController-VsNfQl6v.js +142 -0
- package/dist/RapierPhysics-C_3b7QOn.js +74 -0
- package/dist/Rigidbody-b7QNF4ev.js +107 -0
- package/dist/ScalingToFro-BD-E5-uR.js +21 -0
- package/dist/SightInteractableArea-DrqyB41W.js +79 -0
- package/dist/SimpleWASDMovement-C2m53YYH.js +17 -0
- package/dist/Spinning-sgUhHld8.js +10 -0
- package/dist/StartAnimation-B9eomOS2.js +37 -0
- package/dist/TrimeshCollider-7dIs_xtZ.js +62 -0
- package/dist/World.d.ts +19 -0
- package/dist/WorldRuntime.d.ts +94 -0
- package/dist/behaviours/animation/ScalingToFro.d.ts +8 -0
- package/dist/behaviours/animation/Spinning.d.ts +5 -0
- package/dist/behaviours/animation/StartAnimation.d.ts +9 -0
- package/dist/behaviours/controls/FpsCameraController.d.ts +10 -0
- package/dist/behaviours/controls/PointerLockCameraControls.d.ts +28 -0
- package/dist/behaviours/controls/SimpleWASDMovement.d.ts +5 -0
- package/dist/behaviours/physics/BallCollider.d.ts +10 -0
- package/dist/behaviours/physics/CapsuleCollider.d.ts +14 -0
- package/dist/behaviours/physics/ConeCollider.d.ts +14 -0
- package/dist/behaviours/physics/ConvexMeshCollider.d.ts +6 -0
- package/dist/behaviours/physics/CuboidCollider.d.ts +22 -0
- package/dist/behaviours/physics/CylinderCollider.d.ts +18 -0
- package/dist/behaviours/physics/HalfspaceCollider.d.ts +7 -0
- package/dist/behaviours/physics/RapierFpsPlayerController.d.ts +35 -0
- package/dist/behaviours/physics/Rigidbody.d.ts +24 -0
- package/dist/behaviours/physics/TrimeshCollider.d.ts +9 -0
- package/dist/behaviours/physics/_required-patch.d.ts +10 -0
- package/dist/behaviours/physics/rapier-addon-core/Collider.d.ts +14 -0
- package/dist/behaviours/physics/rapier-addon-core/RapierDebugRenderer.d.ts +17 -0
- package/dist/behaviours/physics/rapier-addon-core/RapierPhysics.d.ts +131 -0
- package/dist/behaviours/physics/rapier-addon-core/get-scale-from-obj.d.ts +8 -0
- package/dist/behaviours/player/SightInteractableArea.d.ts +23 -0
- package/dist/behaviours/registry.d.ts +16 -0
- package/dist/behaviours/utils/MeshInstansing.d.ts +12 -0
- package/dist/bootstrap.d.ts +8 -0
- package/dist/define-world.d.ts +9 -0
- package/dist/get-scale-from-obj-QKv3Fig5.js +22 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.js +1707 -0
- package/dist/modules/EnvModule.d.ts +11 -0
- package/dist/modules/HtmlHudModule.d.ts +14 -0
- package/dist/modules/InputSystemModule.d.ts +87 -0
- package/dist/modules/SoundsModule.d.ts +7 -0
- package/dist/modules/UtilsModule.d.ts +9 -0
- package/dist/modules/contracts/env.module-api.d.ts +7 -0
- package/dist/modules/contracts/html.module-api.d.ts +7 -0
- package/dist/modules/contracts/input.module-api.d.ts +31 -0
- package/dist/modules/contracts/rapier.module-api.d.ts +11 -0
- package/dist/modules/contracts/rapierDebug.module-api.d.ts +5 -0
- package/dist/modules/contracts/sounds.module-api.d.ts +5 -0
- package/dist/modules/contracts/utils.module-api.d.ts +7 -0
- package/dist/modules/index.d.ts +22 -0
- package/dist/modules/is-mobile-device.d.ts +1 -0
- package/dist/modules/registry.d.ts +31 -0
- package/dist/rendering/SceneBloom.d.ts +40 -0
- package/dist/rendering/renderer-apply.d.ts +14 -0
- package/dist/rendering/renderer-options.d.ts +11 -0
- package/dist/rendering/tsl-node.d.ts +21 -0
- package/dist/rendering/tsl-uniforms.d.ts +18 -0
- package/dist/resources/audio.d.ts +15 -0
- package/dist/resources/default-resources.d.ts +36 -0
- package/dist/resources/font.d.ts +32 -0
- package/dist/resources/geometry.d.ts +5 -0
- package/dist/resources/hdr.d.ts +6 -0
- package/dist/resources/loaders.d.ts +45 -0
- package/dist/resources/model.d.ts +24 -0
- package/dist/resources/texture.d.ts +8 -0
- package/dist/resources/video.d.ts +14 -0
- package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
- package/dist/settings/AddonsRuntime.d.ts +19 -0
- package/dist/settings/externals.d.ts +14 -0
- package/dist/settings/lib-loaders.d.ts +7 -0
- package/dist/settings/lib-registry.d.ts +24 -0
- package/dist/settings/module-registry.d.ts +25 -0
- package/dist/settings/types.d.ts +46 -0
- package/dist/types.d.ts +80 -0
- package/dist/utils/lazy.d.ts +4 -0
- package/dist/values.d.ts +6 -0
- package/dist/version.d.ts +10 -0
- package/dist/version.gen.d.ts +1 -0
- package/dist/world-events.d.ts +13 -0
- 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 };
|