@relu-interactives/spatial-ecs 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +125 -0
- package/dist/System-rXAmagXA.d.cts +659 -0
- package/dist/System-rXAmagXA.d.ts +659 -0
- package/dist/Video-CDemv74U.d.cts +1261 -0
- package/dist/Video-ChKV1UI7.d.ts +1261 -0
- package/dist/assets/draco/draco_decoder.js +34 -0
- package/dist/assets/draco/draco_decoder.wasm +0 -0
- package/dist/assets/draco/draco_wasm_wrapper.js +117 -0
- package/dist/chunk-AYEF3X2P.js +223 -0
- package/dist/chunk-AYEF3X2P.js.map +1 -0
- package/dist/chunk-MAWBTMCG.js +1722 -0
- package/dist/chunk-MAWBTMCG.js.map +1 -0
- package/dist/chunk-NFDTIYR4.js +248 -0
- package/dist/chunk-NFDTIYR4.js.map +1 -0
- package/dist/chunk-OY7ZODZP.js +16 -0
- package/dist/chunk-OY7ZODZP.js.map +1 -0
- package/dist/chunk-P2YDX5DB.js +3304 -0
- package/dist/chunk-P2YDX5DB.js.map +1 -0
- package/dist/chunk-QHILSPT4.js +3 -0
- package/dist/chunk-QHILSPT4.js.map +1 -0
- package/dist/chunk-XWIEEJ7Z.js +1315 -0
- package/dist/chunk-XWIEEJ7Z.js.map +1 -0
- package/dist/components/index.cjs +1745 -0
- package/dist/components/index.cjs.map +1 -0
- package/dist/components/index.d.cts +4 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +4 -0
- package/dist/components/index.js.map +1 -0
- package/dist/docs/api/Behaviour/classes/Behaviour.md +554 -0
- package/dist/docs/api/Behaviour/index.md +15 -0
- package/dist/docs/api/Component/classes/Component.md +57 -0
- package/dist/docs/api/Component/index.md +15 -0
- package/dist/docs/api/components/classes/AnimationComponent.md +318 -0
- package/dist/docs/api/components/classes/AudioComponent.md +114 -0
- package/dist/docs/api/components/classes/CameraComponent.md +59 -0
- package/dist/docs/api/components/classes/EntityType.md +48 -0
- package/dist/docs/api/components/classes/Environment.md +47 -0
- package/dist/docs/api/components/classes/ImageComponent.md +57 -0
- package/dist/docs/api/components/classes/ImageTarget.md +60 -0
- package/dist/docs/api/components/classes/ImageTargetAnchor.md +48 -0
- package/dist/docs/api/components/classes/LightComponent.md +70 -0
- package/dist/docs/api/components/classes/MaterialComponent.md +181 -0
- package/dist/docs/api/components/classes/MeshComponent.md +48 -0
- package/dist/docs/api/components/classes/MeshGeometryComponent.md +64 -0
- package/dist/docs/api/components/classes/ModelComponent.md +49 -0
- package/dist/docs/api/components/classes/Name.md +46 -0
- package/dist/docs/api/components/classes/Object3DRef.md +54 -0
- package/dist/docs/api/components/classes/ParentId.md +47 -0
- package/dist/docs/api/components/classes/PhysicsComponent.md +82 -0
- package/dist/docs/api/components/classes/Postprocessing.md +49 -0
- package/dist/docs/api/components/classes/ScriptComponent.md +54 -0
- package/dist/docs/api/components/classes/Selectable.md +46 -0
- package/dist/docs/api/components/classes/SelectionTransformState.md +54 -0
- package/dist/docs/api/components/classes/SpriteComponent.md +55 -0
- package/dist/docs/api/components/classes/TransformComponent.md +197 -0
- package/dist/docs/api/components/classes/VideoComponent.md +123 -0
- package/dist/docs/api/components/functions/normalizePhysicsState.md +23 -0
- package/dist/docs/api/components/index.md +94 -0
- package/dist/docs/api/components/type-aliases/AnimationComponentOptions.md +42 -0
- package/dist/docs/api/components/type-aliases/CameraComponentOptions.md +45 -0
- package/dist/docs/api/components/type-aliases/CameraProjection.md +15 -0
- package/dist/docs/api/components/type-aliases/CameraRuntimeType.md +15 -0
- package/dist/docs/api/components/type-aliases/ColliderShape.md +15 -0
- package/dist/docs/api/components/type-aliases/ColliderState.md +62 -0
- package/dist/docs/api/components/type-aliases/CubeMeshParameters.md +27 -0
- package/dist/docs/api/components/type-aliases/EditableMeshObjectKind.md +15 -0
- package/dist/docs/api/components/type-aliases/EnvironmentFogState.md +37 -0
- package/dist/docs/api/components/type-aliases/EnvironmentFogType.md +15 -0
- package/dist/docs/api/components/type-aliases/EnvironmentGradientEffect.md +15 -0
- package/dist/docs/api/components/type-aliases/EnvironmentSkyboxState.md +34 -0
- package/dist/docs/api/components/type-aliases/EnvironmentSkyboxType.md +15 -0
- package/dist/docs/api/components/type-aliases/EnvironmentState.md +29 -0
- package/dist/docs/api/components/type-aliases/ImageTargetAnchorOptions.md +25 -0
- package/dist/docs/api/components/type-aliases/ImageTargetReference.md +33 -0
- package/dist/docs/api/components/type-aliases/LightValueState.md +41 -0
- package/dist/docs/api/components/type-aliases/MaterialTypeValue.md +15 -0
- package/dist/docs/api/components/type-aliases/MaterialValueState.md +75 -0
- package/dist/docs/api/components/type-aliases/MeshGeometryParameters.md +13 -0
- package/dist/docs/api/components/type-aliases/MeshGeometryParametersByKind.md +33 -0
- package/dist/docs/api/components/type-aliases/PhysicsState.md +25 -0
- package/dist/docs/api/components/type-aliases/PlaneMeshParameters.md +25 -0
- package/dist/docs/api/components/type-aliases/PostprocessingState.md +164 -0
- package/dist/docs/api/components/type-aliases/RadiusHeightMeshParameters.md +25 -0
- package/dist/docs/api/components/type-aliases/RadiusMeshParameters.md +23 -0
- package/dist/docs/api/components/type-aliases/RigidbodyState.md +53 -0
- package/dist/docs/api/components/type-aliases/RigidbodyType.md +19 -0
- package/dist/docs/api/components/type-aliases/ScriptEntry.md +38 -0
- package/dist/docs/api/components/type-aliases/TextureFilteringValue.md +15 -0
- package/dist/docs/api/components/type-aliases/TransformData.md +27 -0
- package/dist/docs/api/components/type-aliases/TransformModeValue.md +15 -0
- package/dist/docs/api/components/type-aliases/TransformSpaceValue.md +15 -0
- package/dist/docs/api/components/type-aliases/Vec3.md +27 -0
- package/dist/docs/api/components/variables/DEFAULT_COLLIDER_STATE.md +13 -0
- package/dist/docs/api/components/variables/DEFAULT_ENVIRONMENT_STATE.md +13 -0
- package/dist/docs/api/components/variables/DEFAULT_MESH_GEOMETRY_PARAMETERS.md +13 -0
- package/dist/docs/api/components/variables/DEFAULT_PHYSICS_STATE.md +13 -0
- package/dist/docs/api/components/variables/DEFAULT_POSTPROCESSING_STATE.md +13 -0
- package/dist/docs/api/components/variables/DEFAULT_RIGIDBODY_STATE.md +13 -0
- package/dist/docs/api/index/classes/AnimationStateMachine.md +201 -0
- package/dist/docs/api/index/classes/AnimationStateManager.md +253 -0
- package/dist/docs/api/index/classes/AnimationSystem.md +68 -0
- package/dist/docs/api/index/classes/AudioSystem.md +98 -0
- package/dist/docs/api/index/classes/CameraSyncSystem.md +49 -0
- package/dist/docs/api/index/classes/EnvironmentSyncSystem.md +75 -0
- package/dist/docs/api/index/classes/InputSystem.md +449 -0
- package/dist/docs/api/index/classes/LightSyncSystem.md +49 -0
- package/dist/docs/api/index/classes/MaterialSyncSystem.md +67 -0
- package/dist/docs/api/index/classes/MeshGeometrySystem.md +49 -0
- package/dist/docs/api/index/classes/ObjectManagementSystem.md +298 -0
- package/dist/docs/api/index/classes/ObjectVisibilitySystem.md +49 -0
- package/dist/docs/api/index/classes/PhysicsSyncSystem.md +83 -0
- package/dist/docs/api/index/classes/PostprocessingSyncSystem.md +80 -0
- package/dist/docs/api/index/classes/RenderSystem.md +64 -0
- package/dist/docs/api/index/classes/ScriptBehaviourSystem.md +83 -0
- package/dist/docs/api/index/classes/TransformSyncSystem.md +49 -0
- package/dist/docs/api/index/classes/VideoSystem.md +97 -0
- package/dist/docs/api/index/classes/World.md +1405 -0
- package/dist/docs/api/index/functions/createAnimationComponent.md +28 -0
- package/dist/docs/api/index/functions/createAudioComponent.md +32 -0
- package/dist/docs/api/index/functions/createCameraComponent.md +28 -0
- package/dist/docs/api/index/functions/createEntityTypeComponent.md +28 -0
- package/dist/docs/api/index/functions/createEnvironmentComponent.md +28 -0
- package/dist/docs/api/index/functions/createImageComponent.md +28 -0
- package/dist/docs/api/index/functions/createImageTargetAnchorComponent.md +28 -0
- package/dist/docs/api/index/functions/createImageTargetComponent.md +28 -0
- package/dist/docs/api/index/functions/createLightComponent.md +28 -0
- package/dist/docs/api/index/functions/createMaterialComponent.md +28 -0
- package/dist/docs/api/index/functions/createMeshComponent.md +28 -0
- package/dist/docs/api/index/functions/createMeshGeometryComponent.md +28 -0
- package/dist/docs/api/index/functions/createModelComponent.md +28 -0
- package/dist/docs/api/index/functions/createNameComponent.md +28 -0
- package/dist/docs/api/index/functions/createObject3DRefComponent.md +28 -0
- package/dist/docs/api/index/functions/createParentIdComponent.md +28 -0
- package/dist/docs/api/index/functions/createPhysicsComponent.md +30 -0
- package/dist/docs/api/index/functions/createPostprocessingComponent.md +28 -0
- package/dist/docs/api/index/functions/createScriptComponent.md +28 -0
- package/dist/docs/api/index/functions/createSelectableComponent.md +28 -0
- package/dist/docs/api/index/functions/createSelectionTransformStateComponent.md +28 -0
- package/dist/docs/api/index/functions/createSpriteComponent.md +28 -0
- package/dist/docs/api/index/functions/createTransformComponent.md +28 -0
- package/dist/docs/api/index/functions/createVideoComponent.md +28 -0
- package/dist/docs/api/index/functions/hydrateWorldFromSnapshot.md +28 -0
- package/dist/docs/api/index/functions/hydrateWorldFromSnapshotDetailed.md +28 -0
- package/dist/docs/api/index/functions/registerDefaultComponentFactories.md +23 -0
- package/dist/docs/api/index/functions/registerDefaultFactories.md +23 -0
- package/dist/docs/api/index/index.md +249 -0
- package/dist/docs/api/index/interfaces/EcsSystem.md +50 -0
- package/dist/docs/api/index/interfaces/StateMachine.md +26 -0
- package/dist/docs/api/index/type-aliases/AnimationStateCallbacks.md +25 -0
- package/dist/docs/api/index/type-aliases/ComponentFactory.md +25 -0
- package/dist/docs/api/index/type-aliases/EcsComponentFactoryKind.md +37 -0
- package/dist/docs/api/index/type-aliases/EcsWorldComponentSnapshot.md +26 -0
- package/dist/docs/api/index/type-aliases/EcsWorldStateSnapshotLike.md +25 -0
- package/dist/docs/api/index/type-aliases/HydrateWorldFromSnapshotResult.md +23 -0
- package/dist/docs/api/index/type-aliases/KeyboardKey.md +13 -0
- package/dist/docs/api/index/type-aliases/MouseButton.md +13 -0
- package/dist/docs/api/index/type-aliases/SelectionContext.md +31 -0
- package/dist/docs/api/index/variables/HYDRATABLE_ENTITY_KINDS.md +13 -0
- package/dist/docs/api/index/variables/KeyboardKeys.md +195 -0
- package/dist/docs/api/index.md +15 -0
- package/dist/docs/api/typedoc-sidebar.json +1 -0
- package/dist/docs/api/types/index.md +34 -0
- package/dist/docs/api/types/type-aliases/AssetInput.md +23 -0
- package/dist/docs/api/types/type-aliases/CheckboxInput.md +13 -0
- package/dist/docs/api/types/type-aliases/ColorInput.md +13 -0
- package/dist/docs/api/types/type-aliases/ComponentInput.md +52 -0
- package/dist/docs/api/types/type-aliases/ComponentKind.md +37 -0
- package/dist/docs/api/types/type-aliases/DropdownInput.md +23 -0
- package/dist/docs/api/types/type-aliases/DropdownOption.md +23 -0
- package/dist/docs/api/types/type-aliases/EcsEntityEditorKind.md +15 -0
- package/dist/docs/api/types/type-aliases/EcsEntityKind.md +35 -0
- package/dist/docs/api/types/type-aliases/EntityId.md +16 -0
- package/dist/docs/api/types/type-aliases/EntityInput.md +23 -0
- package/dist/docs/api/types/type-aliases/FloatInput.md +13 -0
- package/dist/docs/api/types/type-aliases/IntersectionResult.md +29 -0
- package/dist/docs/api/types/type-aliases/ParentLookup.md +26 -0
- package/dist/docs/api/types/type-aliases/SelectionListener.md +25 -0
- package/dist/docs/api/types/type-aliases/SliderInput.md +27 -0
- package/dist/docs/api/types/type-aliases/TextInput.md +13 -0
- package/dist/docs/api/types/type-aliases/ToggleInput.md +13 -0
- package/dist/docs/api/types/type-aliases/Vec3.md +23 -0
- package/dist/docs/api/types/type-aliases/Vector2Input.md +23 -0
- package/dist/docs/api/types/type-aliases/Vector3Input.md +25 -0
- package/dist/docs/api/types/type-aliases/WorldEntityView.md +17 -0
- package/dist/docs/guide/accessing-components.md +399 -0
- package/dist/docs/guide/authoring-a-behaviour.md +166 -0
- package/dist/docs/guide/behaviour-lifecycle.md +43 -0
- package/dist/docs/guide/component-catalog.md +59 -0
- package/dist/docs/guide/components/_sidebar.json +78 -0
- package/dist/docs/guide/components/animation.md +171 -0
- package/dist/docs/guide/components/audio.md +181 -0
- package/dist/docs/guide/components/camera.md +179 -0
- package/dist/docs/guide/components/entity-type.md +141 -0
- package/dist/docs/guide/components/image-target-anchor.md +103 -0
- package/dist/docs/guide/components/image-target.md +122 -0
- package/dist/docs/guide/components/image.md +146 -0
- package/dist/docs/guide/components/light.md +157 -0
- package/dist/docs/guide/components/material.md +161 -0
- package/dist/docs/guide/components/mesh-geometry.md +153 -0
- package/dist/docs/guide/components/mesh.md +151 -0
- package/dist/docs/guide/components/model.md +96 -0
- package/dist/docs/guide/components/name.md +121 -0
- package/dist/docs/guide/components/object3d-ref.md +115 -0
- package/dist/docs/guide/components/parent-id.md +108 -0
- package/dist/docs/guide/components/physics.md +163 -0
- package/dist/docs/guide/components/script.md +142 -0
- package/dist/docs/guide/components/sprite.md +155 -0
- package/dist/docs/guide/components/transform.md +155 -0
- package/dist/docs/guide/components/video.md +153 -0
- package/dist/docs/guide/concepts.md +34 -0
- package/dist/docs/guide/getting-started/creating-objects.md +50 -0
- package/dist/docs/guide/getting-started/editing-objects.md +62 -0
- package/dist/docs/guide/getting-started/editor/assets-browser.md +55 -0
- package/dist/docs/guide/getting-started/editor/hierarchy.md +47 -0
- package/dist/docs/guide/getting-started/editor/index.md +16 -0
- package/dist/docs/guide/getting-started/editor/inspector.md +36 -0
- package/dist/docs/guide/getting-started/editor/modules.md +35 -0
- package/dist/docs/guide/getting-started/editor/scene-inspector.md +64 -0
- package/dist/docs/guide/getting-started/editor/toolbar.md +39 -0
- package/dist/docs/guide/getting-started/editor/viewport.md +43 -0
- package/dist/docs/guide/getting-started/first-launch.md +17 -0
- package/dist/docs/guide/getting-started/index.md +37 -0
- package/dist/docs/guide/getting-started/installation.md +59 -0
- package/dist/docs/guide/getting-started/preview-and-test.md +55 -0
- package/dist/docs/guide/getting-started/project-types/3d.md +30 -0
- package/dist/docs/guide/getting-started/project-types/ar.md +6 -0
- package/dist/docs/guide/getting-started/project-types/face-tracking.md +6 -0
- package/dist/docs/guide/getting-started/project-types/image-tracking.md +42 -0
- package/dist/docs/guide/getting-started/project-types/index.md +25 -0
- package/dist/docs/guide/getting-started/project-types/vr.md +6 -0
- package/dist/docs/guide/getting-started/projects.md +53 -0
- package/dist/docs/guide/getting-started/shortcuts.md +43 -0
- package/dist/docs/guide/inspector-data-binding.md +367 -0
- package/dist/docs/guide/reading-input.md +202 -0
- package/dist/docs/guide/scene/environment.md +101 -0
- package/dist/docs/guide/scene/index.md +36 -0
- package/dist/docs/guide/scene/postprocessing.md +108 -0
- package/dist/docs/guide/spawning/ambient-light.md +28 -0
- package/dist/docs/guide/spawning/area-light.md +32 -0
- package/dist/docs/guide/spawning/audio.md +42 -0
- package/dist/docs/guide/spawning/camera.md +50 -0
- package/dist/docs/guide/spawning/capsule.md +29 -0
- package/dist/docs/guide/spawning/cube.md +31 -0
- package/dist/docs/guide/spawning/cylinder.md +29 -0
- package/dist/docs/guide/spawning/directional-light.md +32 -0
- package/dist/docs/guide/spawning/empty.md +31 -0
- package/dist/docs/guide/spawning/image-target.md +48 -0
- package/dist/docs/guide/spawning/image.md +33 -0
- package/dist/docs/guide/spawning/index.md +79 -0
- package/dist/docs/guide/spawning/model.md +31 -0
- package/dist/docs/guide/spawning/plane.md +31 -0
- package/dist/docs/guide/spawning/point-light.md +32 -0
- package/dist/docs/guide/spawning/sphere.md +29 -0
- package/dist/docs/guide/spawning/spot-light.md +32 -0
- package/dist/docs/guide/spawning/sprite.md +31 -0
- package/dist/docs/guide/spawning/video.md +53 -0
- package/dist/docs/guide/system-overview.md +73 -0
- package/dist/docs/guide/systems/_sidebar.json +66 -0
- package/dist/docs/guide/systems/animation-system.md +32 -0
- package/dist/docs/guide/systems/audio-system.md +28 -0
- package/dist/docs/guide/systems/camera-sync-system.md +31 -0
- package/dist/docs/guide/systems/environment-sync-system.md +31 -0
- package/dist/docs/guide/systems/input-system.md +217 -0
- package/dist/docs/guide/systems/light-sync-system.md +29 -0
- package/dist/docs/guide/systems/material-sync-system.md +32 -0
- package/dist/docs/guide/systems/mesh-geometry-system.md +40 -0
- package/dist/docs/guide/systems/object-management-system.md +38 -0
- package/dist/docs/guide/systems/object-visibility-system.md +26 -0
- package/dist/docs/guide/systems/physics-sync-system.md +56 -0
- package/dist/docs/guide/systems/postprocessing-sync-system.md +43 -0
- package/dist/docs/guide/systems/render-system.md +22 -0
- package/dist/docs/guide/systems/script-behaviour-system.md +59 -0
- package/dist/docs/guide/systems/transform-sync-system.md +29 -0
- package/dist/docs/guide/systems/video-system.md +30 -0
- package/dist/docs/guide/world-api.md +405 -0
- package/dist/factories/index.cjs +3077 -0
- package/dist/factories/index.cjs.map +1 -0
- package/dist/factories/index.d.cts +69 -0
- package/dist/factories/index.d.ts +69 -0
- package/dist/factories/index.js +6 -0
- package/dist/factories/index.js.map +1 -0
- package/dist/index-B4-YyUNR.d.cts +73 -0
- package/dist/index-BZUOKeTO.d.ts +73 -0
- package/dist/index.cjs +8584 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +283 -0
- package/dist/index.d.ts +283 -0
- package/dist/index.js +1729 -0
- package/dist/index.js.map +1 -0
- package/dist/systems/index.cjs +5119 -0
- package/dist/systems/index.cjs.map +1 -0
- package/dist/systems/index.d.cts +200 -0
- package/dist/systems/index.d.ts +200 -0
- package/dist/systems/index.js +6 -0
- package/dist/systems/index.js.map +1 -0
- package/dist/types.cjs +4 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +3 -0
- package/dist/types.d.ts +3 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/worldSnapshotUtils.cjs +259 -0
- package/dist/worldSnapshotUtils.cjs.map +1 -0
- package/dist/worldSnapshotUtils.d.cts +3 -0
- package/dist/worldSnapshotUtils.d.ts +3 -0
- package/dist/worldSnapshotUtils.js +4 -0
- package/dist/worldSnapshotUtils.js.map +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
# Inspector Data Binding
|
|
2
|
+
|
|
3
|
+
The `ScriptComponent.data` field is the bridge between the editor inspector and your `Behaviour` subclass. Anything you place on `data` is:
|
|
4
|
+
|
|
5
|
+
1. Saved with the project.
|
|
6
|
+
2. Rendered as a live inspector control in the editor.
|
|
7
|
+
3. Available at runtime as `this.data` inside the script.
|
|
8
|
+
|
|
9
|
+
The **type annotation** on each field tells the editor which control to render. Import the input types from `@relu-interactives/spatial-ecs` and use them as `as` casts on the initial values in your data object.
|
|
10
|
+
|
|
11
|
+
## Input types reference
|
|
12
|
+
|
|
13
|
+
| Type | Import | Inspector control | Runtime value |
|
|
14
|
+
| --- | --- | --- | --- |
|
|
15
|
+
| `FloatInput` | ✓ | Number input | `number` |
|
|
16
|
+
| `TextInput` | ✓ | Text input | `string` |
|
|
17
|
+
| `ColorInput` | ✓ | Color picker | `string` (hex, e.g. `"#ff0000"`) |
|
|
18
|
+
| `Vector2Input` | ✓ | XY number pair | `{ x: number; y: number }` |
|
|
19
|
+
| `Vector3Input` | ✓ | XYZ number triple | `{ x: number; y: number; z: number }` |
|
|
20
|
+
| `SliderInput` | ✓ | Range slider | `{ min, max, step, value }` (read `field.value` at runtime) |
|
|
21
|
+
| `DropdownInput` | ✓ | Select dropdown | `{ options: DropdownOption[]; value: string }` (read `field.value`) |
|
|
22
|
+
| `CheckboxInput` | ✓ | Checkbox | `boolean` |
|
|
23
|
+
| `ToggleInput` | ✓ | Toggle switch | `boolean` |
|
|
24
|
+
| `AssetInput` | ✓ | Asset file picker | `{ path: string; type: string }` — read `field.path`; `.value` is always `null` |
|
|
25
|
+
| `EntityInput` | ✓ | Entity picker | `{ type: "entity"; value: WorldEntityView \| null }` — read `field.value` |
|
|
26
|
+
| `ComponentInput` | ✓ | Entity + component picker | `{ type: "component"; componentKind?: ComponentKind; value: Component \| null }` — read `field.value` |
|
|
27
|
+
|
|
28
|
+
## Declaring inspector fields
|
|
29
|
+
|
|
30
|
+
Import the input types you need alongside `Behaviour`, then declare them directly on the `data` class property using `as` casts:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import {
|
|
34
|
+
Behaviour,
|
|
35
|
+
type FloatInput,
|
|
36
|
+
type TextInput,
|
|
37
|
+
type ColorInput,
|
|
38
|
+
type Vector2Input,
|
|
39
|
+
type Vector3Input,
|
|
40
|
+
type SliderInput,
|
|
41
|
+
type DropdownInput,
|
|
42
|
+
type CheckboxInput,
|
|
43
|
+
type ToggleInput,
|
|
44
|
+
type AssetInput,
|
|
45
|
+
type EntityInput,
|
|
46
|
+
type ComponentInput,
|
|
47
|
+
} from "@relu-interactives/spatial-ecs";
|
|
48
|
+
|
|
49
|
+
export default class Demo extends Behaviour {
|
|
50
|
+
data = {
|
|
51
|
+
speed: 1 as FloatInput,
|
|
52
|
+
label: "Hello" as TextInput,
|
|
53
|
+
tint: "#ffffff" as ColorInput,
|
|
54
|
+
offset: { x: 0, y: 0 } as Vector2Input,
|
|
55
|
+
origin: { x: 0, y: 0, z: 0 } as Vector3Input,
|
|
56
|
+
range: { min: 0, max: 10, step: 0.1, value: 5 } as SliderInput,
|
|
57
|
+
axis: {
|
|
58
|
+
value: "y",
|
|
59
|
+
options: [
|
|
60
|
+
{ label: "X", value: "x" },
|
|
61
|
+
{ label: "Y", value: "y" },
|
|
62
|
+
{ label: "Z", value: "z" },
|
|
63
|
+
],
|
|
64
|
+
} as DropdownInput,
|
|
65
|
+
active: true as ToggleInput,
|
|
66
|
+
visible: true as CheckboxInput,
|
|
67
|
+
texture: { path: "", type: "texture" } as AssetInput,
|
|
68
|
+
target: { type: "entity", value: null } as EntityInput,
|
|
69
|
+
camera: { type: "component", componentKind: "Camera", value: null } as ComponentInput,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Reading values at runtime
|
|
75
|
+
|
|
76
|
+
Most types map directly to their underlying primitive. The exceptions are `SliderInput`, `DropdownInput`, `AssetInput`, `EntityInput`, and `ComponentInput`, which are objects — read the nested value:
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
export default class Demo extends Behaviour {
|
|
80
|
+
data = {
|
|
81
|
+
speed: 1 as FloatInput,
|
|
82
|
+
active: true as ToggleInput,
|
|
83
|
+
range: { min: 0, max: 1, step: 0.1, value: 0.8 } as SliderInput,
|
|
84
|
+
axis: { value: "y", options: [{ label: "X", value: "x" }, { label: "Y", value: "y" }, { label: "Z", value: "z" }] } as DropdownInput,
|
|
85
|
+
texture: { path: "", type: "texture" } as AssetInput,
|
|
86
|
+
target: { type: "entity", value: null } as EntityInput,
|
|
87
|
+
camera: { type: "component", componentKind: "Camera", value: null } as ComponentInput,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
onUpdate() {
|
|
91
|
+
// FloatInput / TextInput / ColorInput / CheckboxInput / ToggleInput
|
|
92
|
+
// → use directly
|
|
93
|
+
this.transform.rotation.y += this.data.speed * this.deltaTime;
|
|
94
|
+
const isOn = this.data.active;
|
|
95
|
+
|
|
96
|
+
// SliderInput → read .value
|
|
97
|
+
const volume = this.data.range.value;
|
|
98
|
+
|
|
99
|
+
// DropdownInput → read .value
|
|
100
|
+
const axis = this.data.axis.value as "x" | "y" | "z";
|
|
101
|
+
this.transform.rotation[axis] += this.data.speed * this.deltaTime;
|
|
102
|
+
|
|
103
|
+
// AssetInput → read .path (see AssetInput section below)
|
|
104
|
+
const src = this.data.texture.path;
|
|
105
|
+
|
|
106
|
+
// EntityInput → cast to WorldEntityView | null
|
|
107
|
+
const entity = this.data.target.value as WorldEntityView | null;
|
|
108
|
+
|
|
109
|
+
// ComponentInput → cast to the concrete component type
|
|
110
|
+
const cam = this.data.camera.value as CameraComponent | null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## EntityInput — picking and using scene entities
|
|
116
|
+
|
|
117
|
+
`EntityInput` lets the editor user pick any entity from the scene. Declare it with `{ type: "entity", value: null }` as the default (no entity selected).
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
import {
|
|
121
|
+
Behaviour,
|
|
122
|
+
type EntityInput,
|
|
123
|
+
} from "@relu-interactives/spatial-ecs";
|
|
124
|
+
|
|
125
|
+
export default class Follower extends Behaviour {
|
|
126
|
+
data = {
|
|
127
|
+
target: { type: "entity", value: null } as EntityInput,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
At runtime, `this.data.target.value` is resolved to a **`WorldEntityView`** — not a raw ID. You can import and use this type directly:
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
import { type WorldEntityView } from "@relu-interactives/spatial-ecs";
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`WorldEntityView` has the following shape:
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
type WorldEntityView = {
|
|
142
|
+
name: string; // entity name from the NameComponent
|
|
143
|
+
entityId: number; // runtime entity ID
|
|
144
|
+
type: string; // entity type ("mesh", "camera", "light", …)
|
|
145
|
+
object: THREE.Object3D | null; // live three.js scene object
|
|
146
|
+
components: Component[]; // all components attached to this entity
|
|
147
|
+
};
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Reading entity data
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
onUpdate() {
|
|
154
|
+
const target = this.data.target.value as WorldEntityView | null;
|
|
155
|
+
if (!target) return; // no entity assigned in the inspector
|
|
156
|
+
|
|
157
|
+
// Name and ID
|
|
158
|
+
console.log(target.name); // e.g. "Camera"
|
|
159
|
+
console.log(target.entityId); // runtime numeric ID
|
|
160
|
+
|
|
161
|
+
// Access the three.js object directly
|
|
162
|
+
const obj = target.object;
|
|
163
|
+
if (obj) {
|
|
164
|
+
console.log(obj.position); // THREE.Vector3
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Moving another entity from a script
|
|
170
|
+
|
|
171
|
+
Use `getEntity()` on `WorldEntityView` to get the entity's transform and mutate it:
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
import {
|
|
175
|
+
Behaviour,
|
|
176
|
+
TransformComponent,
|
|
177
|
+
type EntityInput,
|
|
178
|
+
type WorldEntityView,
|
|
179
|
+
} from "@relu-interactives/spatial-ecs";
|
|
180
|
+
|
|
181
|
+
export default class Mover extends Behaviour {
|
|
182
|
+
data = {
|
|
183
|
+
target: { type: "entity", value: null } as EntityInput,
|
|
184
|
+
speed: 5 as FloatInput,
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
onUpdate() {
|
|
188
|
+
const target = this.data.target.value as WorldEntityView | null;
|
|
189
|
+
if (!target) return;
|
|
190
|
+
|
|
191
|
+
// Find the TransformComponent on the picked entity
|
|
192
|
+
const transform = target.components.find(
|
|
193
|
+
(c) => c instanceof TransformComponent,
|
|
194
|
+
) as TransformComponent | undefined;
|
|
195
|
+
|
|
196
|
+
if (transform) {
|
|
197
|
+
transform.position.x += this.data.speed * this.deltaTime;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
> [!TIP]
|
|
204
|
+
> Always guard with `if (!target) return;` — the field is `null` until the user picks an entity in the inspector, and may be `null` in new scenes.
|
|
205
|
+
|
|
206
|
+
## ComponentInput — picking and using a specific component
|
|
207
|
+
|
|
208
|
+
`ComponentInput` lets the user pick an entity **and** a specific component kind from that entity. Use this when you want to read or drive a particular component (e.g. a `CameraComponent`, `AudioComponent`, or `AnimationComponent`).
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
import {
|
|
212
|
+
Behaviour,
|
|
213
|
+
type ComponentInput,
|
|
214
|
+
} from "@relu-interactives/spatial-ecs";
|
|
215
|
+
|
|
216
|
+
export default class CameraController extends Behaviour {
|
|
217
|
+
data = {
|
|
218
|
+
cam: { type: "component", componentKind: "CameraComponent", value: null } as ComponentInput,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
At runtime, `this.data.cam.value` is resolved to the **live component instance** — the actual class instance that the ECS manages each frame.
|
|
224
|
+
|
|
225
|
+
### Reading component properties
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
import {
|
|
229
|
+
Behaviour,
|
|
230
|
+
CameraComponent,
|
|
231
|
+
type ComponentInput,
|
|
232
|
+
} from "@relu-interactives/spatial-ecs";
|
|
233
|
+
|
|
234
|
+
export default class FovAnimator extends Behaviour {
|
|
235
|
+
data = {
|
|
236
|
+
camera: { type: "component", componentKind: "CameraComponent", value: null } as ComponentInput,
|
|
237
|
+
targetFov: 90 as FloatInput,
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
onUpdate() {
|
|
241
|
+
const cam = this.data.camera.value as CameraComponent | null;
|
|
242
|
+
if (!cam) return; // no component assigned
|
|
243
|
+
|
|
244
|
+
// Read a property
|
|
245
|
+
console.log(cam.fov); // current field of view in degrees
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Changing component properties
|
|
251
|
+
|
|
252
|
+
Mutate the instance directly — the system that owns the component will pick up the change next frame:
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
import {
|
|
256
|
+
Behaviour,
|
|
257
|
+
CameraComponent,
|
|
258
|
+
type ComponentInput,
|
|
259
|
+
type FloatInput,
|
|
260
|
+
} from "@relu-interactives/spatial-ecs";
|
|
261
|
+
|
|
262
|
+
export default class FovAnimator extends Behaviour {
|
|
263
|
+
data = {
|
|
264
|
+
camera: { type: "component", componentKind: "CameraComponent", value: null } as ComponentInput,
|
|
265
|
+
targetFov: 90 as FloatInput,
|
|
266
|
+
speed: 30 as FloatInput,
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
onUpdate() {
|
|
270
|
+
const cam = this.data.camera.value as CameraComponent | null;
|
|
271
|
+
if (!cam) return;
|
|
272
|
+
|
|
273
|
+
// Lerp the field of view toward targetFov
|
|
274
|
+
cam.fov += (this.data.targetFov - cam.fov) * this.data.speed * this.deltaTime;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
> [!TIP]
|
|
280
|
+
> Cast the resolved value to the concrete component type (e.g. `as CameraComponent | null`) to get full TypeScript autocompletion on its properties. Always guard the null case — the field is `null` until the user picks both an entity and a component in the inspector.
|
|
281
|
+
|
|
282
|
+
## AssetInput — referencing project assets
|
|
283
|
+
|
|
284
|
+
`AssetInput` exposes a file picker in the inspector. The user selects a file from the project's `assets/` folder. The field stores the relative path to that file.
|
|
285
|
+
|
|
286
|
+
```ts
|
|
287
|
+
import {
|
|
288
|
+
Behaviour,
|
|
289
|
+
type AssetInput,
|
|
290
|
+
} from "@relu-interactives/spatial-ecs";
|
|
291
|
+
|
|
292
|
+
export default class AudioPlayer extends Behaviour {
|
|
293
|
+
data = {
|
|
294
|
+
clip: { path: "", type: "audio" } as AssetInput,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
At runtime, **`this.data.clip.value` is always `null`** — `AssetInput` does not resolve to a loaded asset object. Use `this.data.clip.path` to get the relative file path, then load the asset yourself if needed:
|
|
300
|
+
|
|
301
|
+
```ts
|
|
302
|
+
onUpdate() {
|
|
303
|
+
const path = this.data.clip.path;
|
|
304
|
+
if (!path) return;
|
|
305
|
+
|
|
306
|
+
// path is the relative asset path, e.g. "./assets/sounds/click.mp3"
|
|
307
|
+
console.log(path);
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
The `type` field on the default value (`"audio"`, `"texture"`, `"model"`, etc.) is used by the editor to filter the file picker to relevant asset types.
|
|
312
|
+
|
|
313
|
+
## Practical example — spinner with inspector controls
|
|
314
|
+
|
|
315
|
+
```ts
|
|
316
|
+
import {
|
|
317
|
+
Behaviour,
|
|
318
|
+
type FloatInput,
|
|
319
|
+
type ColorInput,
|
|
320
|
+
type DropdownInput,
|
|
321
|
+
type ToggleInput,
|
|
322
|
+
} from "@relu-interactives/spatial-ecs";
|
|
323
|
+
|
|
324
|
+
export default class Spinner extends Behaviour {
|
|
325
|
+
data = {
|
|
326
|
+
speed: 1 as FloatInput,
|
|
327
|
+
color: "#00aaff" as ColorInput,
|
|
328
|
+
enabled: true as ToggleInput,
|
|
329
|
+
axis: {
|
|
330
|
+
value: "y",
|
|
331
|
+
options: [
|
|
332
|
+
{ label: "X", value: "x" },
|
|
333
|
+
{ label: "Y", value: "y" },
|
|
334
|
+
{ label: "Z", value: "z" },
|
|
335
|
+
],
|
|
336
|
+
} as DropdownInput,
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
onUpdate() {
|
|
340
|
+
if (!this.data.enabled) return;
|
|
341
|
+
const axis = this.data.axis.value as "x" | "y" | "z";
|
|
342
|
+
this.transform.rotation[axis] += this.data.speed * this.deltaTime;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## Defaulting fields
|
|
348
|
+
|
|
349
|
+
Defaults are set inline on the `data` property. When a saved project reloads, saved values take precedence — the inline defaults only apply when a field has never been saved. This means:
|
|
350
|
+
|
|
351
|
+
- Adding a new field with an inline default is safe — existing saves will pick it up on next load.
|
|
352
|
+
- The inspector always has a valid initial value when the script is first attached.
|
|
353
|
+
- For `SliderInput` and `DropdownInput`, the full object (including `options`) must be present in the inline default — the editor reads `options` to build the control.
|
|
354
|
+
|
|
355
|
+
## Persistence
|
|
356
|
+
|
|
357
|
+
`ScriptComponent.data` is serialized and saved with the project. On reload, your `data` payload is restored verbatim. If you rename or restructure a field, migrate it inside `init()`:
|
|
358
|
+
|
|
359
|
+
```ts
|
|
360
|
+
init() {
|
|
361
|
+
// migrate renamed field
|
|
362
|
+
if ((this.data as any).oldSpeed !== undefined) {
|
|
363
|
+
this.data.speed = (this.data as any).oldSpeed;
|
|
364
|
+
delete (this.data as any).oldSpeed;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
```
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# Reading Input
|
|
2
|
+
|
|
3
|
+
Call input methods directly on `this.world` inside `onUpdate()` to query keyboard and mouse state each frame. There is no `world.input` accessor — all methods are on the `World` instance itself.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { Behaviour, KeyboardKeys } from "@relu-interactives/spatial-ecs";
|
|
7
|
+
|
|
8
|
+
export default class Example extends Behaviour {
|
|
9
|
+
onUpdate() {
|
|
10
|
+
// held this frame
|
|
11
|
+
if (this.world.getKey(KeyboardKeys.Space)) { /* … */ }
|
|
12
|
+
|
|
13
|
+
// only true on the first frame the key goes down
|
|
14
|
+
if (this.world.getKeyDown(KeyboardKeys.E)) { /* … */ }
|
|
15
|
+
|
|
16
|
+
// only true on the frame the key is released
|
|
17
|
+
if (this.world.getKeyUp(KeyboardKeys.E)) { /* … */ }
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## API
|
|
23
|
+
|
|
24
|
+
All methods are called directly on `this.world`:
|
|
25
|
+
|
|
26
|
+
| Method | Description |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| `this.world.getKey(key)` | `true` while the key is held. |
|
|
29
|
+
| `this.world.getKeyDown(key)` | `true` only on the first frame the key is pressed. |
|
|
30
|
+
| `this.world.getKeyUp(key)` | `true` only on the frame the key is released. |
|
|
31
|
+
| `this.world.getMouse(button)` | `true` while the mouse button is held. `"left"` / `"middle"` / `"right"`. |
|
|
32
|
+
| `this.world.getMouseDown(button)` | `true` only on the first frame the button is pressed. |
|
|
33
|
+
| `this.world.getMouseUp(button)` | `true` only on the frame the button is released. |
|
|
34
|
+
| `this.world.getMousePosition()` | `{ x, y }` in viewport pixels. |
|
|
35
|
+
| `this.world.getMouseDelta()` | `{ x, y }` pointer movement since the last frame. |
|
|
36
|
+
| `this.world.consumeMouseDelta()` | `{ x, y }` movement since last frame; zeroes the delta after reading. |
|
|
37
|
+
| `this.world.getScrollDelta()` | `{ x, y }` scroll wheel delta since the last frame. |
|
|
38
|
+
|
|
39
|
+
## KeyboardKeys reference
|
|
40
|
+
|
|
41
|
+
All constants are available from the `KeyboardKeys` import. Pass any of them to `getKey` / `getKeyDown` / `getKeyUp`.
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { KeyboardKeys } from "@relu-interactives/spatial-ecs";
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Letters
|
|
48
|
+
|
|
49
|
+
`KeyboardKeys.A` through `KeyboardKeys.Z`
|
|
50
|
+
|
|
51
|
+
### Digits
|
|
52
|
+
|
|
53
|
+
`KeyboardKeys.Digit0` through `KeyboardKeys.Digit9`
|
|
54
|
+
|
|
55
|
+
### Navigation & editing
|
|
56
|
+
|
|
57
|
+
| Constant | Key |
|
|
58
|
+
| --- | --- |
|
|
59
|
+
| `KeyboardKeys.ArrowUp` | ↑ Arrow |
|
|
60
|
+
| `KeyboardKeys.ArrowDown` | ↓ Arrow |
|
|
61
|
+
| `KeyboardKeys.ArrowLeft` | ← Arrow |
|
|
62
|
+
| `KeyboardKeys.ArrowRight` | → Arrow |
|
|
63
|
+
| `KeyboardKeys.Space` | Space |
|
|
64
|
+
| `KeyboardKeys.Enter` | Enter / Return |
|
|
65
|
+
| `KeyboardKeys.Escape` | Escape |
|
|
66
|
+
| `KeyboardKeys.Tab` | Tab |
|
|
67
|
+
| `KeyboardKeys.Backspace` | Backspace |
|
|
68
|
+
| `KeyboardKeys.Delete` | Delete |
|
|
69
|
+
| `KeyboardKeys.Insert` | Insert |
|
|
70
|
+
| `KeyboardKeys.Home` | Home |
|
|
71
|
+
| `KeyboardKeys.End` | End |
|
|
72
|
+
| `KeyboardKeys.PageUp` | Page Up |
|
|
73
|
+
| `KeyboardKeys.PageDown` | Page Down |
|
|
74
|
+
|
|
75
|
+
### Modifier keys
|
|
76
|
+
|
|
77
|
+
Generic variants match either the left or right physical key. Use the specific variant when the side matters.
|
|
78
|
+
|
|
79
|
+
| Constant | Physical key |
|
|
80
|
+
| --- | --- |
|
|
81
|
+
| `KeyboardKeys.Shift` | Either Shift key |
|
|
82
|
+
| `KeyboardKeys.ShiftLeft` | Left Shift |
|
|
83
|
+
| `KeyboardKeys.ShiftRight` | Right Shift |
|
|
84
|
+
| `KeyboardKeys.Control` | Either Ctrl key |
|
|
85
|
+
| `KeyboardKeys.ControlLeft` | Left Ctrl |
|
|
86
|
+
| `KeyboardKeys.ControlRight` | Right Ctrl |
|
|
87
|
+
| `KeyboardKeys.Alt` | Alt / Option |
|
|
88
|
+
| `KeyboardKeys.Meta` | Cmd (macOS) / Win key |
|
|
89
|
+
| `KeyboardKeys.CapsLock` | Caps Lock |
|
|
90
|
+
|
|
91
|
+
### Function keys
|
|
92
|
+
|
|
93
|
+
`KeyboardKeys.F1` through `KeyboardKeys.F12`
|
|
94
|
+
|
|
95
|
+
### Punctuation & symbols
|
|
96
|
+
|
|
97
|
+
| Constant | Key |
|
|
98
|
+
| --- | --- |
|
|
99
|
+
| `KeyboardKeys.Minus` | `-` |
|
|
100
|
+
| `KeyboardKeys.Equal` | `=` |
|
|
101
|
+
| `KeyboardKeys.BracketLeft` | `[` |
|
|
102
|
+
| `KeyboardKeys.BracketRight` | `]` |
|
|
103
|
+
| `KeyboardKeys.Backslash` | `\` |
|
|
104
|
+
| `KeyboardKeys.Semicolon` | `;` |
|
|
105
|
+
| `KeyboardKeys.Quote` | `'` |
|
|
106
|
+
| `KeyboardKeys.Backquote` | `` ` `` |
|
|
107
|
+
| `KeyboardKeys.Comma` | `,` |
|
|
108
|
+
| `KeyboardKeys.Period` | `.` |
|
|
109
|
+
| `KeyboardKeys.Slash` | `/` |
|
|
110
|
+
|
|
111
|
+
### Other
|
|
112
|
+
|
|
113
|
+
| Constant | Key |
|
|
114
|
+
| --- | --- |
|
|
115
|
+
| `KeyboardKeys.NumLock` | Num Lock |
|
|
116
|
+
| `KeyboardKeys.ScrollLock` | Scroll Lock |
|
|
117
|
+
| `KeyboardKeys.Pause` | Pause / Break |
|
|
118
|
+
| `KeyboardKeys.PrintScreen` | Print Screen |
|
|
119
|
+
| `KeyboardKeys.ContextMenu` | Context Menu |
|
|
120
|
+
|
|
121
|
+
## Examples
|
|
122
|
+
|
|
123
|
+
### WASD movement with sprint
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
import { Behaviour, KeyboardKeys } from "@relu-interactives/spatial-ecs";
|
|
127
|
+
|
|
128
|
+
export default class Movement extends Behaviour {
|
|
129
|
+
speed = 5;
|
|
130
|
+
sprintMultiplier = 2;
|
|
131
|
+
|
|
132
|
+
onUpdate() {
|
|
133
|
+
const step = this.speed * (this.world.getKey(KeyboardKeys.Shift) ? this.sprintMultiplier : 1) * this.deltaTime;
|
|
134
|
+
|
|
135
|
+
if (this.world.getKey(KeyboardKeys.W)) this.transform.position.z -= step;
|
|
136
|
+
if (this.world.getKey(KeyboardKeys.S)) this.transform.position.z += step;
|
|
137
|
+
if (this.world.getKey(KeyboardKeys.A)) this.transform.position.x -= step;
|
|
138
|
+
if (this.world.getKey(KeyboardKeys.D)) this.transform.position.x += step;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### One-shot action on key press and mouse click
|
|
144
|
+
|
|
145
|
+
`getKeyDown` fires only on the frame the key transitions from up to down, so it is safe to use for one-shot actions.
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
import { Behaviour, KeyboardKeys } from "@relu-interactives/spatial-ecs";
|
|
149
|
+
|
|
150
|
+
export default class ActionHandler extends Behaviour {
|
|
151
|
+
onUpdate() {
|
|
152
|
+
if (this.world.getKeyDown(KeyboardKeys.Space)) {
|
|
153
|
+
console.log("Jump!");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (this.world.getMouseDown("left")) {
|
|
157
|
+
const pos = this.world.getMousePosition();
|
|
158
|
+
console.log("Fired at", pos.x, pos.y);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Distinguishing left vs right modifier
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
import { Behaviour, KeyboardKeys } from "@relu-interactives/spatial-ecs";
|
|
168
|
+
|
|
169
|
+
export default class ModifierDemo extends Behaviour {
|
|
170
|
+
onUpdate() {
|
|
171
|
+
if (this.world.getKeyDown(KeyboardKeys.ControlLeft)) {
|
|
172
|
+
console.log("Left Ctrl");
|
|
173
|
+
}
|
|
174
|
+
if (this.world.getKeyDown(KeyboardKeys.ControlRight)) {
|
|
175
|
+
console.log("Right Ctrl");
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Matches either Shift key
|
|
179
|
+
if (this.world.getKey(KeyboardKeys.Shift)) {
|
|
180
|
+
console.log("Shift held");
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Mouse-delta camera look
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
import { Behaviour } from "@relu-interactives/spatial-ecs";
|
|
190
|
+
|
|
191
|
+
export default class CameraLook extends Behaviour {
|
|
192
|
+
sensitivity = 0.002;
|
|
193
|
+
|
|
194
|
+
onUpdate() {
|
|
195
|
+
const { x, y } = this.world.consumeMouseDelta();
|
|
196
|
+
this.transform.rotation.y -= x * this.sensitivity;
|
|
197
|
+
this.transform.rotation.x -= y * this.sensitivity;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
For `InputSystem` internals and pointer-lock details, see the [InputSystem guide](./systems/input-system).
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Environment
|
|
2
|
+
|
|
3
|
+
The `Environment` component holds scene-wide settings:
|
|
4
|
+
|
|
5
|
+
- **Skybox:** gradient, solid color, equirectangular image, or none.
|
|
6
|
+
- **Fog:** linear, exponential, or none.
|
|
7
|
+
- **Gravity:** the world gravity vector applied by the physics system (in m/s²).
|
|
8
|
+
|
|
9
|
+
It is a **singleton** there is exactly one `Environment` entity per scene, owned by the editor.
|
|
10
|
+
|
|
11
|
+
> **Managed by:** [`EnvironmentSyncSystem`](../systems/environment-sync-system)
|
|
12
|
+
|
|
13
|
+
## Get the component from the world
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { Behaviour, Environment } from "@relu-interactives/spatial-ecs";
|
|
17
|
+
|
|
18
|
+
export default class ReadEnvironment extends Behaviour {
|
|
19
|
+
init() {
|
|
20
|
+
const [entityId] = this.world.query(Environment);
|
|
21
|
+
if (entityId === undefined) return;
|
|
22
|
+
|
|
23
|
+
const env = this.world.getComponent(entityId, Environment);
|
|
24
|
+
if (!env) return;
|
|
25
|
+
|
|
26
|
+
console.log("skybox type", env.values.skybox.type);
|
|
27
|
+
console.log("gravity", env.values.gravity);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`env.values` is the live state object. Mutating fields on it is enough, the `EnvironmentSyncSystem` reads it every frame and pushes changes into the three.js scene.
|
|
33
|
+
|
|
34
|
+
## Change values at runtime
|
|
35
|
+
|
|
36
|
+
### Switch the skybox
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
env.values.skybox.type = "gradient";
|
|
40
|
+
env.values.skybox.gradient.colors = ["#0b1026", "#3b6dd6", "#f7d488"];
|
|
41
|
+
env.values.skybox.gradient.effect = "linear"; // "linear" | "radial" | "angular"
|
|
42
|
+
|
|
43
|
+
// Or use a solid color:
|
|
44
|
+
env.values.skybox.type = "color";
|
|
45
|
+
env.values.skybox.color = "#101010";
|
|
46
|
+
|
|
47
|
+
// Or an equirectangular image:
|
|
48
|
+
env.values.skybox.type = "image";
|
|
49
|
+
env.values.skybox.imageUrl = "/assets/skies/studio.hdr";
|
|
50
|
+
|
|
51
|
+
// Or disable it:
|
|
52
|
+
env.values.skybox.type = "none";
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Configure fog
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
// Linear fog
|
|
59
|
+
env.values.fog.type = "linear";
|
|
60
|
+
env.values.fog.color = "#aabbcc";
|
|
61
|
+
env.values.fog.linear.near = 1;
|
|
62
|
+
env.values.fog.linear.far = 50;
|
|
63
|
+
|
|
64
|
+
// Exponential fog
|
|
65
|
+
env.values.fog.type = "exponential";
|
|
66
|
+
env.values.fog.exponential.density = 0.05;
|
|
67
|
+
|
|
68
|
+
// Off
|
|
69
|
+
env.values.fog.type = "none";
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Change physics gravity
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
// Moon-like gravity
|
|
76
|
+
env.values.gravity = { x: 0, y: -1.62, z: 0 };
|
|
77
|
+
|
|
78
|
+
// Zero-G
|
|
79
|
+
env.values.gravity = { x: 0, y: 0, z: 0 };
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Authorable values
|
|
83
|
+
|
|
84
|
+
| Path | Type | Default | Notes |
|
|
85
|
+
| --- | --- | --- | --- |
|
|
86
|
+
| `skybox.type` | `"gradient" \| "color" \| "image" \| "none"` | `"none"` | Active skybox mode. |
|
|
87
|
+
| `skybox.color` | `string` (hex) | `"#1e1e1e"` | Used when `type` is `"color"`. |
|
|
88
|
+
| `skybox.imageUrl` | `string` | `""` | Used when `type` is `"image"`. |
|
|
89
|
+
| `skybox.gradient.colors` | `string[]` | `["#464766", "#657ea6", "#0f0e1a"]` | Hex color stops. |
|
|
90
|
+
| `skybox.gradient.effect` | `"linear" \| "radial" \| "angular"` | `"linear"` | Gradient distribution. |
|
|
91
|
+
| `fog.type` | `"linear" \| "exponential" \| "none"` | `"none"` | Fog model. |
|
|
92
|
+
| `fog.color` | `string` (hex) | `"#1e1e1e"` | Fog color. |
|
|
93
|
+
| `fog.linear.near` | `number` | `1` | Distance where fog starts. |
|
|
94
|
+
| `fog.linear.far` | `number` | `100` | Distance where fog reaches full opacity. |
|
|
95
|
+
| `fog.exponential.density` | `number` | `0.002` | Higher = thicker fog. |
|
|
96
|
+
| `gravity` | `{ x, y, z }` | `(0, -9.81, 0)` | World units per second squared. |
|
|
97
|
+
|
|
98
|
+
## API reference
|
|
99
|
+
|
|
100
|
+
- Class: [`Environment`](../../api/components/classes/Environment.md)
|
|
101
|
+
- Source: [`core/components/Environment.ts`](https://github.com/Relu-Interactives/relu-spatial-ecs-engine/blob/main/core/components/Environment.ts)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Scene
|
|
2
|
+
|
|
3
|
+
Some settings live on the **scene** rather than on a single object the skybox, fog, gravity, and the post-processing stack. They are stored on a singleton entity so you can read and mutate them from any `Behaviour`.
|
|
4
|
+
|
|
5
|
+
| Page | What it covers |
|
|
6
|
+
| --- | --- |
|
|
7
|
+
| [Environment](./environment) | Skybox (gradient / color / image), fog (linear / exponential), and physics gravity. |
|
|
8
|
+
| [Postprocessing](./postprocessing) | Bloom, vignette, depth-of-field, tone mapping, and other full-screen effects. |
|
|
9
|
+
|
|
10
|
+
## Pattern
|
|
11
|
+
|
|
12
|
+
Both components follow the same access pattern from a script:
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { Behaviour, Environment, Postprocessing } from "@relu-interactives/spatial-ecs";
|
|
16
|
+
|
|
17
|
+
export default class TweakScene extends Behaviour {
|
|
18
|
+
init() {
|
|
19
|
+
// 1. Find the singleton entity that owns the component.
|
|
20
|
+
const [entityId] = this.world.query(Environment);
|
|
21
|
+
if (entityId === undefined) return;
|
|
22
|
+
|
|
23
|
+
// 2. Read the component instance.
|
|
24
|
+
const env = this.world.getComponent(entityId, Environment);
|
|
25
|
+
if (!env) return;
|
|
26
|
+
|
|
27
|
+
// 3. Mutate `env.values` — sync systems pick the change up next frame.
|
|
28
|
+
env.values.fog.type = "linear";
|
|
29
|
+
env.values.fog.color = "#88aaff";
|
|
30
|
+
env.values.fog.linear.near = 5;
|
|
31
|
+
env.values.fog.linear.far = 60;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The same shape works for `Postprocessing` — see each page for the full set of authorable values.
|