@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
@@ -0,0 +1,142 @@
1
+ import * as THREE from "three/webgpu";
2
+ import { Object3DBehaviour } from "three-start";
3
+ //#region packages/world-runtime/src/behaviours/physics/RapierFpsPlayerController.ts
4
+ var RapierFpsPlayerController = class extends Object3DBehaviour {
5
+ halfHeight = .85;
6
+ radius = .5;
7
+ offset = .01;
8
+ walkSpeed = 3.5;
9
+ runSpeed = 8;
10
+ useShiftRun = true;
11
+ maxSlopeClimbAngle = 45 * Math.PI / 180;
12
+ minSlopeSlideAngle = 30 * Math.PI / 180;
13
+ slideEnabled = false;
14
+ snapToGround = .2;
15
+ applyImplusesToDynamicBodies = false;
16
+ enableAutostep = true;
17
+ autostepMaxHeight = .3;
18
+ autostepMinWidth = .2;
19
+ autostepIncludeDynamicBodies = false;
20
+ controlsEnabled = true;
21
+ rb;
22
+ col;
23
+ kcc;
24
+ _isVaryTimeStep = true;
25
+ _detach;
26
+ onEnable() {
27
+ const rapier = this.modules.rapier;
28
+ const world = rapier.world;
29
+ const RAPIER = rapier.api;
30
+ this._isVaryTimeStep = rapier.timeStep === "vary";
31
+ const pos = this.object.position;
32
+ const rbDesc = RAPIER.RigidBodyDesc.kinematicPositionBased().setTranslation(pos.x, pos.y, pos.z);
33
+ this.rb = world.createRigidBody(rbDesc);
34
+ const height = (this.halfHeight + this.radius) * 2;
35
+ this.col = world.createCollider(RAPIER.ColliderDesc.capsule(this.halfHeight, this.radius).setTranslation(0, height / 2, 0), this.rb);
36
+ const kcc = world.createCharacterController(this.offset);
37
+ kcc.setMaxSlopeClimbAngle(this.maxSlopeClimbAngle);
38
+ kcc.enableSnapToGround(this.snapToGround);
39
+ kcc.setApplyImpulsesToDynamicBodies(this.applyImplusesToDynamicBodies);
40
+ if (this.enableAutostep) kcc.enableAutostep(this.autostepMaxHeight, this.autostepMinWidth, this.autostepIncludeDynamicBodies);
41
+ this.kcc = kcc;
42
+ const onStep = () => {
43
+ if (this.controlsEnabled) this.update();
44
+ };
45
+ rapier.on("stepbefore", onStep);
46
+ this._detach = () => {
47
+ rapier.off("stepbefore", onStep);
48
+ world.removeCharacterController(kcc);
49
+ };
50
+ }
51
+ onDisable() {
52
+ this._detach?.();
53
+ this._detach = void 0;
54
+ }
55
+ _inputDir = new THREE.Vector3();
56
+ correctedMovement = new THREE.Vector3();
57
+ getDt() {
58
+ return this._isVaryTimeStep ? this.ctx.getDeltaTime() : this.modules.rapier.timeStep;
59
+ }
60
+ update() {
61
+ const kcc = this.kcc;
62
+ const col = this.col;
63
+ const dt = this.getDt();
64
+ const input = this.modules.input;
65
+ const dir = this._inputDir;
66
+ dir.setScalar(0);
67
+ const playerInput = input.player;
68
+ let speed = this.walkSpeed;
69
+ switch (playerInput.mode) {
70
+ case 0: {
71
+ const keys = input.isKeyDown;
72
+ if (keys("KeyW") || keys("ArrowUp")) dir.z -= 1;
73
+ if (keys("KeyS") || keys("ArrowDown")) dir.z += 1;
74
+ if (keys("KeyA") || keys("ArrowLeft")) dir.x -= 1;
75
+ if (keys("KeyD") || keys("ArrowRight")) dir.x += 1;
76
+ if (this.useShiftRun && input.shiftKey) speed = this.runSpeed;
77
+ break;
78
+ }
79
+ case 1: {
80
+ const { forward, lateral, force } = input.player;
81
+ dir.z -= forward;
82
+ dir.x += lateral;
83
+ speed = force > 2 ? THREE.MathUtils.lerp(this.walkSpeed, this.runSpeed, THREE.MathUtils.clamp(force - 2, 0, 1.5)) : this.walkSpeed;
84
+ break;
85
+ }
86
+ }
87
+ dir.normalize();
88
+ const camera = this.ctx.camera;
89
+ if (dir.lengthSq() > 0) {
90
+ const cameraForward = _vt1;
91
+ camera.getWorldDirection(cameraForward);
92
+ cameraForward.y = 0;
93
+ cameraForward.normalize();
94
+ const cameraRight = _vt2.setScalar(0);
95
+ cameraRight.crossVectors(up, cameraForward).normalize();
96
+ const move = _vt3.setScalar(0);
97
+ move.addScaledVector(cameraForward, -dir.z);
98
+ move.addScaledVector(cameraRight, -dir.x);
99
+ move.normalize();
100
+ dir.copy(move);
101
+ }
102
+ const hitGround = this.hitGround();
103
+ const desiredTranslationDelta = _vt.copy(dir).multiplyScalar(speed * dt);
104
+ if (hitGround && hitGround.timeOfImpact > .01) desiredTranslationDelta.y = -hitGround.timeOfImpact + .08;
105
+ kcc.computeColliderMovement(col, desiredTranslationDelta);
106
+ const correctedMovement = kcc.computedMovement();
107
+ this.correctedMovement.copy(correctedMovement);
108
+ const newTranslatation = _vt.copy(this.rb.translation()).add(correctedMovement);
109
+ this.rb.setNextKinematicTranslation(newTranslatation);
110
+ _vt.copy(this.rb.translation());
111
+ const obj = this.object;
112
+ if (obj.parent) {
113
+ obj.parent.worldToLocal(_vt);
114
+ obj.position.copy(_vt);
115
+ }
116
+ }
117
+ _hitGround = null;
118
+ hitGround() {
119
+ const rapier = this.modules.rapier;
120
+ const rayOrigin = this.rb.translation();
121
+ const ray = new rapier.api.Ray(rayOrigin, down);
122
+ const hitGround = rapier.world.castRay(ray, 100, false, void 0, void 0, this.col, this.rb);
123
+ this._hitGround = hitGround;
124
+ return hitGround;
125
+ }
126
+ teleport(position) {
127
+ this.object.position.copy(position);
128
+ this.rb.setTranslation(position, true);
129
+ }
130
+ };
131
+ var _vt = new THREE.Vector3();
132
+ var _vt1 = new THREE.Vector3();
133
+ var _vt2 = new THREE.Vector3();
134
+ var _vt3 = new THREE.Vector3();
135
+ var down = {
136
+ x: 0,
137
+ y: -1,
138
+ z: 0
139
+ };
140
+ var up = new THREE.Vector3(0, 1, 0);
141
+ //#endregion
142
+ export { RapierFpsPlayerController as default };
@@ -0,0 +1,74 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
+ import { ContextModule, ThreeContextEvents, defineProps, readOnly } from "three-start";
3
+ //#region packages/world-runtime/src/behaviours/physics/rapier-addon-core/RapierPhysics.ts
4
+ var RapierPhysics_exports = /* @__PURE__ */ __exportAll({
5
+ RapierPhysics: () => RapierPhysics,
6
+ default: () => RapierPhysics
7
+ });
8
+ var RapierPhysics = class RapierPhysics extends ContextModule {
9
+ isRapierPhysics;
10
+ api;
11
+ world;
12
+ eventQueue;
13
+ /** @default "vary" */
14
+ timeStep;
15
+ _steppingState = { accumulator: 0 };
16
+ constructor(Rapier, options = {}) {
17
+ super();
18
+ const { timeStep = "vary", gravity = [
19
+ 0,
20
+ -9.81,
21
+ 0
22
+ ] } = options;
23
+ const world = new Rapier.World({
24
+ x: gravity[0],
25
+ y: gravity[1],
26
+ z: gravity[2]
27
+ });
28
+ this.timeStep = timeStep;
29
+ console.log(`Rapier version: ${Rapier.version()}`);
30
+ defineProps(this, {
31
+ isRapierPhysics: readOnly(true),
32
+ api: readOnly(Rapier),
33
+ world: readOnly(world),
34
+ eventQueue: readOnly(new Rapier.EventQueue(false))
35
+ });
36
+ }
37
+ onStart() {
38
+ requestAnimationFrame(() => {
39
+ requestAnimationFrame(() => {
40
+ this.ctx.on(ThreeContextEvents.RenderBefore, this.update);
41
+ });
42
+ });
43
+ }
44
+ /** three-start ContextModule has no onDestroy; teardown is explicit. */
45
+ dispose() {
46
+ this.ctx.off(ThreeContextEvents.RenderBefore, this.update);
47
+ }
48
+ update = () => {
49
+ const steppingState = this._steppingState;
50
+ const timeStep = this.timeStep;
51
+ const timeStepVariable = timeStep === "vary";
52
+ const clampedDelta = Math.max(Math.min(.1, this.ctx.getDeltaTime()), 0);
53
+ if (timeStepVariable) this.stepWorld(clampedDelta);
54
+ else {
55
+ steppingState.accumulator += clampedDelta;
56
+ while (steppingState.accumulator >= timeStep) {
57
+ this.stepWorld(timeStep);
58
+ steppingState.accumulator -= timeStep;
59
+ }
60
+ }
61
+ };
62
+ stepWorld = (delta) => {
63
+ this.emit("stepbefore");
64
+ this.world.timestep = delta;
65
+ this.world.step();
66
+ this.emit("stepafter");
67
+ };
68
+ static findInCtx(ctx) {
69
+ const rapier = ctx.modules.rapier;
70
+ return rapier instanceof RapierPhysics ? rapier : void 0;
71
+ }
72
+ };
73
+ //#endregion
74
+ export { RapierPhysics_exports as n, RapierPhysics as t };
@@ -0,0 +1,107 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
+ import * as THREE from "three/webgpu";
3
+ import { Object3DBehaviour, assertDefined, defineProps, readOnly } from "three-start";
4
+ //#region packages/world-runtime/src/behaviours/physics/Rigidbody.ts
5
+ var Rigidbody_exports = /* @__PURE__ */ __exportAll({ default: () => Rigidbody });
6
+ /**
7
+ * @see {@link https://github.com/vladkrutenyuk/three-kvy-core/blob/main/src/addons/Rigidbody.ts | Source}
8
+ */
9
+ var Rigidbody = class extends Object3DBehaviour {
10
+ isRigidbody = true;
11
+ get instance() {
12
+ return assertDefined(this._instance, "instance");
13
+ }
14
+ _instance;
15
+ rigidbodyType = 0;
16
+ _world;
17
+ constructor() {
18
+ super();
19
+ defineProps(this, { isRigidbody: readOnly(true) });
20
+ }
21
+ onEnable() {
22
+ const rapier = this.modules.rapier;
23
+ const Rapier = rapier.api;
24
+ let desc;
25
+ const type = Number(this.rigidbodyType);
26
+ console.log("creating rigidbody with type", type);
27
+ switch (type) {
28
+ case Rapier.RigidBodyType.Dynamic:
29
+ desc = Rapier.RigidBodyDesc.dynamic();
30
+ break;
31
+ case Rapier.RigidBodyType.Fixed:
32
+ desc = Rapier.RigidBodyDesc.fixed();
33
+ break;
34
+ case Rapier.RigidBodyType.KinematicPositionBased:
35
+ desc = Rapier.RigidBodyDesc.kinematicPositionBased();
36
+ break;
37
+ case Rapier.RigidBodyType.KinematicVelocityBased:
38
+ desc = Rapier.RigidBodyDesc.kinematicVelocityBased();
39
+ break;
40
+ default:
41
+ console.error("invalid rigidbody type", type);
42
+ return;
43
+ }
44
+ const pos = this.getObjWorldPos();
45
+ const quat = this.getObjWorldQuat();
46
+ desc.setTranslation(pos.x, pos.y, pos.z).setRotation(quat);
47
+ const world = rapier.world;
48
+ const rb = world.createRigidBody(desc);
49
+ this._instance = rb;
50
+ this._world = world;
51
+ this.emit("ready", rb);
52
+ }
53
+ onDisable() {
54
+ if (this._instance && this._world) this._world.removeRigidBody(this._instance);
55
+ this._instance = void 0;
56
+ this._world = void 0;
57
+ }
58
+ onBeforeRender() {
59
+ const rb = this._instance;
60
+ if (!rb) return;
61
+ if (rb.isDynamic()) this.syncObjectToBody();
62
+ else if (rb.isKinematic()) this.syncBodyToObjectKinematically();
63
+ }
64
+ syncBodyToObjectKinematically() {
65
+ const rb = this._instance;
66
+ if (!rb) return;
67
+ const obj = this.object;
68
+ obj.getWorldPosition(_v);
69
+ obj.getWorldQuaternion(_qt1);
70
+ rb.setNextKinematicTranslation(_v);
71
+ rb.setNextKinematicRotation(_qt1);
72
+ }
73
+ withReady(cb) {
74
+ if (this._instance) return cb(this._instance);
75
+ this.once("ready", cb);
76
+ }
77
+ getObjWorldPos() {
78
+ this.object.getWorldPosition(_v);
79
+ return _v;
80
+ }
81
+ getObjWorldQuat() {
82
+ this.object.getWorldQuaternion(_qt1);
83
+ return _qt1;
84
+ }
85
+ syncObjectToBody() {
86
+ const rb = this._instance;
87
+ if (!rb || rb.isSleeping()) return;
88
+ const obj = this.object;
89
+ const parent = obj.parent;
90
+ if (!parent) return;
91
+ _v.copy(rb.translation());
92
+ parent.worldToLocal(_v);
93
+ obj.position.copy(_v);
94
+ const rbWorldQuat = _qt1;
95
+ rbWorldQuat.copy(rb.rotation());
96
+ const parentWorldQuat = _qt2;
97
+ parent.getWorldQuaternion(parentWorldQuat);
98
+ _qt3.copy(parentWorldQuat).invert().multiply(rbWorldQuat);
99
+ obj.setRotationFromQuaternion(_qt3);
100
+ }
101
+ };
102
+ var _v = new THREE.Vector3();
103
+ var _qt1 = new THREE.Quaternion();
104
+ var _qt2 = new THREE.Quaternion();
105
+ var _qt3 = new THREE.Quaternion();
106
+ //#endregion
107
+ export { Rigidbody_exports as n, Rigidbody as t };
@@ -0,0 +1,21 @@
1
+ import { Object3DBehaviour } from "three-start";
2
+ //#region packages/world-runtime/src/behaviours/animation/ScalingToFro.ts
3
+ var ScalingToFro = class extends Object3DBehaviour {
4
+ scale = 1;
5
+ max = 2;
6
+ min = .2;
7
+ direction = 1;
8
+ onBeforeRender() {
9
+ if (this.scale >= this.max) {
10
+ this.direction = -1;
11
+ this.scale = this.max;
12
+ } else if (this.scale <= this.min) {
13
+ this.direction = 1;
14
+ this.scale = this.min;
15
+ }
16
+ this.scale += this.ctx.getDeltaTime() * this.direction;
17
+ this.object.scale.setScalar(this.scale);
18
+ }
19
+ };
20
+ //#endregion
21
+ export { ScalingToFro as default };
@@ -0,0 +1,79 @@
1
+ import * as THREE from "three/webgpu";
2
+ import { Object3DBehaviour } from "three-start";
3
+ //#region packages/world-runtime/src/behaviours/player/SightInteractableArea.ts
4
+ var raycaster = new THREE.Raycaster();
5
+ var SightInteractableArea = class SightInteractableArea extends Object3DBehaviour {
6
+ static _CURRENT = null;
7
+ isSightInteractableArea = true;
8
+ radius = 3;
9
+ hint = "Interact";
10
+ interactEnabled = true;
11
+ isStatic = true;
12
+ _sqRadius = 9;
13
+ _active = false;
14
+ _initWorldPos = new THREE.Vector3();
15
+ onEnable() {
16
+ const r = this.radius;
17
+ this._sqRadius = r * r;
18
+ this.object.getWorldPosition(this._initWorldPos);
19
+ }
20
+ onDisable() {
21
+ this._deactivate();
22
+ }
23
+ setRadius(r) {
24
+ this.radius = r;
25
+ this._sqRadius = r * r;
26
+ }
27
+ onBeforeRender() {
28
+ if (!this.interactEnabled) return;
29
+ const camera = this.ctx.camera;
30
+ const thisWorldPos = this.isStatic ? this._initWorldPos : this.object.getWorldPosition(_vt1);
31
+ const cameraWorldPos = camera.getWorldPosition(_vt2);
32
+ const inside = thisWorldPos.distanceToSquared(cameraWorldPos) <= this._sqRadius;
33
+ let active = false;
34
+ if (inside) {
35
+ raycaster.setFromCamera(screenCenter, camera);
36
+ if (raycaster.intersectObject(this.object, false).length > 0) active = true;
37
+ }
38
+ if (this._active === active) return;
39
+ this._active = active;
40
+ this.emit("activechanged", active);
41
+ if (active) this._activate();
42
+ else this._deactivate();
43
+ }
44
+ _activate() {
45
+ const modules = this.modules;
46
+ SightInteractableArea._CURRENT = this.object.id;
47
+ modules.html.setCrosshair(this.hint);
48
+ if (modules.env.isMobile) {
49
+ modules.html.crosshair.style.pointerEvents = "auto";
50
+ modules.html.crosshair.addEventListener("pointerdown", this._interact);
51
+ } else this.ctx.renderer.domElement.addEventListener("mousedown", this._interact);
52
+ }
53
+ _deactivate() {
54
+ const modules = this.modules;
55
+ if (SightInteractableArea._CURRENT === this.object.id) {
56
+ SightInteractableArea._CURRENT = null;
57
+ modules.html.setCrosshair("");
58
+ }
59
+ if (modules.env.isMobile) {
60
+ modules.html.crosshair.style.pointerEvents = "";
61
+ modules.html.crosshair.removeEventListener("pointerdown", this._interact);
62
+ } else this.ctx.renderer.domElement.removeEventListener("mousedown", this._interact);
63
+ }
64
+ _interact = () => {
65
+ if (!this.interactEnabled) return;
66
+ const current = SightInteractableArea._CURRENT;
67
+ if (!(current === this.object.id || current === null)) return;
68
+ this.interactEnabled = false;
69
+ this._deactivate();
70
+ this._active = false;
71
+ this.emit("interaction");
72
+ console.log("interaction with ", this.object.name);
73
+ };
74
+ };
75
+ var screenCenter = new THREE.Vector2(0, 0);
76
+ var _vt1 = new THREE.Vector3();
77
+ var _vt2 = new THREE.Vector3();
78
+ //#endregion
79
+ export { SightInteractableArea as default };
@@ -0,0 +1,17 @@
1
+ import { Object3DBehaviour } from "three-start";
2
+ //#region packages/world-runtime/src/behaviours/controls/SimpleWASDMovement.ts
3
+ var SimpleWASDMovement = class extends Object3DBehaviour {
4
+ speed = 4;
5
+ onBeforeRender() {
6
+ const dt = this.ctx.getDeltaTime();
7
+ const s = this.speed;
8
+ const pos = this.object.position;
9
+ const key = this.modules.input.isKeyDown;
10
+ if (key("KeyW")) pos.z -= s * dt;
11
+ if (key("KeyS")) pos.z += s * dt;
12
+ if (key("KeyD")) pos.x += s * dt;
13
+ if (key("KeyA")) pos.x -= s * dt;
14
+ }
15
+ };
16
+ //#endregion
17
+ export { SimpleWASDMovement as default };
@@ -0,0 +1,10 @@
1
+ import { Object3DBehaviour } from "three-start";
2
+ //#region packages/world-runtime/src/behaviours/animation/Spinning.ts
3
+ var Spinning = class extends Object3DBehaviour {
4
+ speed = 5;
5
+ onBeforeRender() {
6
+ this.object.rotateY(this.ctx.getDeltaTime() * this.speed);
7
+ }
8
+ };
9
+ //#endregion
10
+ export { Spinning as default };
@@ -0,0 +1,37 @@
1
+ import * as THREE from "three/webgpu";
2
+ import { Object3DBehaviour } from "three-start";
3
+ //#region packages/world-runtime/src/behaviours/animation/StartAnimation.ts
4
+ var StartAnimation = class extends Object3DBehaviour {
5
+ mixer;
6
+ _action;
7
+ onEnable() {
8
+ const anims = this.object.animations;
9
+ const mixer = new THREE.AnimationMixer(this.object);
10
+ this.mixer = mixer;
11
+ if (anims.length > 0) {
12
+ this._action = mixer.clipAction(anims[0]);
13
+ this._action.play();
14
+ }
15
+ }
16
+ onDisable() {
17
+ const mixer = this.mixer;
18
+ const action = this._action;
19
+ if (action) {
20
+ action.stop();
21
+ mixer?.uncacheAction(action.getClip(), this.object);
22
+ }
23
+ mixer?.stopAllAction();
24
+ mixer?.uncacheRoot(this.object);
25
+ if (mixer) {
26
+ mixer._actions = [];
27
+ mixer._bindings = [];
28
+ }
29
+ this.mixer = void 0;
30
+ this._action = void 0;
31
+ }
32
+ onBeforeRender() {
33
+ this.mixer?.update(this.ctx.getDeltaTime());
34
+ }
35
+ };
36
+ //#endregion
37
+ export { StartAnimation as default };
@@ -0,0 +1,62 @@
1
+ import { Object3DBehaviour } from "three-start";
2
+ //#region packages/world-runtime/src/behaviours/physics/TrimeshCollider.ts
3
+ var TrimeshCollider = class extends Object3DBehaviour {
4
+ recursive = false;
5
+ _detach;
6
+ onEnable() {
7
+ const { api: RAPIER, world } = this.modules.rapier;
8
+ if (this.recursive) {
9
+ const colliders = [];
10
+ this.object.traverse((node) => {
11
+ if (!isMesh(node)) return;
12
+ const [vertices, indices] = createTrimeshColliderArgsFromMesh(node);
13
+ const col = world.createCollider(RAPIER.ColliderDesc.trimesh(vertices, indices));
14
+ colliders.push(col);
15
+ });
16
+ this._detach = () => {
17
+ colliders.forEach((x) => world.removeCollider(x, false));
18
+ };
19
+ return;
20
+ }
21
+ const mesh = this.object;
22
+ if (!isMesh(mesh)) {
23
+ console.error("TrimeshCollider can be applied only for Mesh");
24
+ return;
25
+ }
26
+ const [vertices, indices] = createTrimeshColliderArgsFromMesh(mesh);
27
+ const col = world.createCollider(RAPIER.ColliderDesc.trimesh(vertices, indices));
28
+ this._detach = () => {
29
+ world.removeCollider(col, false);
30
+ };
31
+ }
32
+ onDisable() {
33
+ this._detach?.();
34
+ this._detach = void 0;
35
+ }
36
+ };
37
+ function isMesh(obj) {
38
+ return obj.isMesh;
39
+ }
40
+ function createTrimeshColliderArgsFromMesh(mesh) {
41
+ mesh.updateWorldMatrix(true, false);
42
+ const geom = mesh.geometry.clone();
43
+ geom.applyMatrix4(mesh.matrixWorld);
44
+ if (!geom.getAttribute("normal")) geom.computeVertexNormals();
45
+ const position = geom.getAttribute("position");
46
+ const vertices = new Float32Array(position.count * 3);
47
+ for (let i = 0; i < position.count; i++) {
48
+ vertices[i * 3 + 0] = position.getX(i);
49
+ vertices[i * 3 + 1] = position.getY(i);
50
+ vertices[i * 3 + 2] = position.getZ(i);
51
+ }
52
+ let indices;
53
+ if (geom.index) indices = new Uint32Array(geom.index.array);
54
+ else {
55
+ indices = new Uint32Array(position.count);
56
+ for (let i = 0; i < position.count; i++) indices[i] = i;
57
+ }
58
+ geom.dispose();
59
+ return [vertices, indices];
60
+ }
61
+ //#endregion
62
+ export { createTrimeshColliderArgsFromMesh, TrimeshCollider as default };
@@ -0,0 +1,19 @@
1
+ import { ThreeStart } from "three-start";
2
+ import type { ThreeStartOptions } from "three-start";
3
+ import type { WorldRuntime } from "./WorldRuntime";
4
+ /**
5
+ * A loaded world is a three-start app with the scene already assembled.
6
+ * Mounting and starting are manual: `mount(container)` attaches the canvas and
7
+ * runs the render loop, `start()` activates behaviours (idempotent — call it
8
+ * after a user gesture if the world plays audio or captures the pointer).
9
+ */
10
+ export declare class World extends ThreeStart {
11
+ private readonly _runtime;
12
+ constructor(options: ThreeStartOptions, _runtime: WorldRuntime);
13
+ /** Asset URL by project path — same resolving as `getUrl` in scripts. */
14
+ getUrl: (path: string) => string;
15
+ /** World lifecycle event bus — the same one as `world.events` in scripts. */
16
+ get events(): WorldRuntime["emitter"];
17
+ start(): this;
18
+ dispose(): void;
19
+ }
@@ -0,0 +1,94 @@
1
+ import EventEmitter from "eventemitter3";
2
+ import * as THREE from "three/webgpu";
3
+ import type { Object3DBehaviourConstructor, ThreeContext, ThreeStart } from "three-start";
4
+ import type { SceneBloom } from "./rendering/SceneBloom";
5
+ import type { LoadWorldOptions, RuntimeApi, WorldDefinition } from "./types";
6
+ /** Slice of the world definition the runtime needs: independent of the asset bag type. */
7
+ export type RuntimeDefinitionSlice = Pick<WorldDefinition, "assets" | "scripts" | "entryScript" | "styles" | "fontPaths" | "usedBuiltins" | "addons">;
8
+ /**
9
+ * Owner of the world's runtime state: assets, script execution, ctx access.
10
+ * The only object the generated code receives.
11
+ */
12
+ export declare class WorldRuntime implements RuntimeApi {
13
+ readonly definition: RuntimeDefinitionSlice;
14
+ readonly options: LoadWorldOptions;
15
+ /** World lifecycle event bus (`world.events` in scripts). */
16
+ readonly emitter: EventEmitter<string | symbol, any>;
17
+ private readonly _addons;
18
+ private readonly _executedScripts;
19
+ private readonly _builtins;
20
+ private readonly _styleElements;
21
+ private _resources;
22
+ private _ctx;
23
+ private _bloom;
24
+ private _scriptContext;
25
+ constructor(definition: RuntimeDefinitionSlice, options: LoadWorldOptions);
26
+ /** ctx appears at the 3d-context creation step; unavailable to scripts before that. */
27
+ get ctx(): ThreeContext;
28
+ /** @internal Set by bootstrap. */
29
+ setContext(ctx: ThreeContext): void;
30
+ /** @internal World bloom, if enabled in the renderer config. */
31
+ setBloom(bloom: SceneBloom): void;
32
+ /** @internal Built-in libs and external scripts from `settings.addons.json`. */
33
+ loadAddons(): Promise<void>;
34
+ /** @internal World resources by asset path — result of `loadAssets`. */
35
+ setResources(resources: Record<string, unknown>): void;
36
+ reportProgress(stage: string, details?: string): void;
37
+ getUrl: (path: string) => string;
38
+ /**
39
+ * Built-in behaviour class by uuid. Classes are preloaded by bootstrap,
40
+ * so attaching in `buildScene` is synchronous.
41
+ */
42
+ builtin: (uuid: string) => Object3DBehaviourConstructor;
43
+ /** @internal Loads classes of the used built-in behaviours (before scene assembly). */
44
+ loadBuiltins(): Promise<void>;
45
+ /**
46
+ * @internal Registers ctx modules required by built-in behaviours (physics).
47
+ * Strictly before `start()` — three-start forbids `addModules` afterwards.
48
+ */
49
+ applyRequiredPatches(starter: ThreeStart): Promise<void>;
50
+ /** Addon (built-in lib / external) → script by path → asset resource. Same
51
+ * resolve order as in play mode. */
52
+ require: (key: string) => unknown;
53
+ /**
54
+ * Runtime spawn: a prefab (build-time factory) is assembled anew, a regular
55
+ * object is cloned. Returns a detached object — the caller adds it.
56
+ */
57
+ instantiate: (source: THREE.Object3D | PrefabFactory, options?: InstantiateOptions) => THREE.Object3D;
58
+ /** Runs a script once and caches its `output`. The cache entry is set before
59
+ * execution — this breaks cyclic `require`. */
60
+ executeScript(path: string): unknown;
61
+ /** World entry script (`main.ts`), once. */
62
+ executeEntryScript(): void;
63
+ /** Mounts world css scripts into the document where the canvas actually renders. */
64
+ mountStyles(): void;
65
+ /** `@font-face` of all world fonts in a single tag — before styles and entry script. */
66
+ mountFonts(): void;
67
+ dispose(): void;
68
+ /** Narrow bloom facade for scripts: mode is read-only, params are live
69
+ * (uniforms, can be animated per frame). `null` — bloom is disabled. */
70
+ private get bloomApi();
71
+ /** Script-scope globals: all of three-start + `world`, `require`, libs.
72
+ * `ctx` is a getter: script components run before the 3d context is created. */
73
+ private get scriptContext();
74
+ private appendStyle;
75
+ }
76
+ /** Shape of `world.rendering.bloom` in scripts. */
77
+ export interface WorldBloomApi {
78
+ readonly mode: SceneBloom["mode"];
79
+ strength: number;
80
+ radius: number;
81
+ threshold: number;
82
+ }
83
+ /** A prefab in an exported world — a factory that assembles a fresh hierarchy. */
84
+ export type PrefabFactory = () => THREE.Object3D;
85
+ export interface InstantiateOptions {
86
+ position?: Vec3Like;
87
+ rotation?: Vec3Like;
88
+ scale?: Vec3Like | number;
89
+ }
90
+ export type Vec3Like = [number, number, number] | {
91
+ x: number;
92
+ y: number;
93
+ z: number;
94
+ };
@@ -0,0 +1,8 @@
1
+ import { Object3DBehaviour } from "three-start";
2
+ export default class ScalingToFro extends Object3DBehaviour {
3
+ scale: number;
4
+ max: number;
5
+ min: number;
6
+ direction: number;
7
+ onBeforeRender(): void;
8
+ }
@@ -0,0 +1,5 @@
1
+ import { Object3DBehaviour } from "three-start";
2
+ export default class Spinning extends Object3DBehaviour {
3
+ speed: number;
4
+ onBeforeRender(): void;
5
+ }