lecodes-cli 0.17.2 → 0.18.1
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 +1 -1
- package/dist/index.js +2376 -755
- package/package.json +4 -4
- package/runtime/scene-harness.json +1 -1
- package/runtime/sdk/compile/aspectMacro.ts +52 -8
- package/runtime/sdk/compile/assetMacro.ts +116 -15
- package/runtime/sdk/compile/bundler.ts +39 -4
- package/runtime/sdk/compile/compileProject.ts +16 -1
- package/runtime/sdk/compile/header.ts +6 -1
- package/runtime/sdk/compile/index.ts +31 -0
- package/runtime/sdk/compile/liteMaterial.ts +247 -0
- package/runtime/sdk/compile/sceneEditor.ts +11 -1
- package/runtime/sdk/compile/shaderSchema.ts +202 -0
- package/runtime/sdk/compile/shaderTargets.ts +81 -0
- package/runtime/sdk/core/Aspect.ts +363 -95
- package/runtime/sdk/core/compWrite.ts +42 -0
- package/runtime/sdk/core/fields.ts +1 -1
- package/runtime/sdk/core/time.ts +81 -0
- package/runtime/sdk/g2/Camera2D.ts +8 -1
- package/runtime/sdk/g2/CharacterController2D.ts +253 -53
- package/runtime/sdk/g2/Node2D.ts +80 -10
- package/runtime/sdk/g2/OneWay2D.ts +66 -0
- package/runtime/sdk/g2/Physics2D.ts +240 -30
- package/runtime/sdk/g2/Scene2D.ts +33 -1
- package/runtime/sdk/g2/Shape2D.ts +218 -22
- package/runtime/sdk/g2/Trigger2D.ts +42 -12
- package/runtime/sdk/g2/groups2d.ts +106 -0
- package/runtime/sdk/g2/loop.ts +15 -4
- package/runtime/sdk/gl/Camera.ts +41 -0
- package/runtime/sdk/gl/CameraPlace.ts +52 -0
- package/runtime/sdk/gl/CharacterController.ts +184 -55
- package/runtime/sdk/gl/Gearbox.ts +212 -0
- package/runtime/sdk/gl/Geometry.ts +70 -9
- package/runtime/sdk/gl/IK.ts +193 -174
- package/runtime/sdk/gl/Light.ts +64 -2
- package/runtime/sdk/gl/Lightmap.ts +179 -0
- package/runtime/sdk/gl/Material.ts +36 -0
- package/runtime/sdk/gl/Mesh.ts +6 -23
- package/runtime/sdk/gl/Model.ts +23 -8
- package/runtime/sdk/gl/Node.ts +350 -285
- package/runtime/sdk/gl/Physics.ts +222 -126
- package/runtime/sdk/gl/Scene.ts +175 -8
- package/runtime/sdk/gl/Shape.ts +255 -12
- package/runtime/sdk/gl/Trigger.ts +1 -6
- package/runtime/sdk/gl/Vehicle.ts +473 -0
- package/runtime/sdk/gl/Wheel.ts +240 -0
- package/runtime/sdk/gl/{AnimationClip.ts → animation/AnimationClip.ts} +37 -7
- package/runtime/sdk/gl/animation/Animator.ts +87 -0
- package/runtime/sdk/gl/animation/Layer.ts +29 -0
- package/runtime/sdk/gl/animation/Loop.ts +25 -0
- package/runtime/sdk/gl/animation/Playback.ts +43 -0
- package/runtime/sdk/gl/animation/core.ts +294 -0
- package/runtime/sdk/gl/scenarios.ts +291 -349
- package/runtime/sdk/inject.ts +186 -162
- package/runtime/sdk/runtime/app.ts +13 -0
- package/runtime/sdk/runtime/input.ts +169 -6
- package/runtime/sdk/scene/defineScene.ts +1227 -1016
- package/runtime/sdk/scene/gizmos.ts +148 -0
- package/runtime/sdk/scene/material.ts +188 -0
- package/runtime/sdk-types.json +1 -1
- package/runtime/sdk/gl/Animator.ts +0 -642
- package/runtime/sdk/gl/ModelAnimation.ts +0 -95
package/runtime/sdk/inject.ts
CHANGED
|
@@ -1,162 +1,186 @@
|
|
|
1
|
-
// THE aggregation point. Every public global the SDK provides is re-exported here under the exact
|
|
2
|
-
// name user code uses it as. The bundler passes this file to esbuild's `inject:` option, so user
|
|
3
|
-
// code references `Scene`, `Sprite`, `toast`, … with no imports; esbuild tree-shakes away whatever
|
|
4
|
-
// a given project does not use (so a pure-2D project drops all 3D classes, and vice versa).
|
|
5
|
-
//
|
|
6
|
-
// Rule: this is the ONLY file that `export`s public names. Everything else is internal and imported
|
|
7
|
-
// by it. Host-provided globals (setLoop, console, setTimeout, DEG2RAD, asset, …) are NOT here —
|
|
8
|
-
// they live in src/host.d.ts as declarations and stay as free references at runtime.
|
|
9
|
-
|
|
10
|
-
// ---- math ----
|
|
11
|
-
export { Mathf } from "./math/Mathf"
|
|
12
|
-
export { Vec2, Vec3 } from "./math/vec"
|
|
13
|
-
export { Quat } from "./math/quat"
|
|
14
|
-
export { Mat4 } from "./math/mat4"
|
|
15
|
-
export { Color } from "./core/color"
|
|
16
|
-
|
|
17
|
-
// ---- aspects (attachable node capabilities) ----
|
|
18
|
-
export { Aspect, type With } from "./core/Aspect"
|
|
19
|
-
export {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
export {
|
|
26
|
-
|
|
27
|
-
// ----
|
|
28
|
-
export {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
export {
|
|
32
|
-
export {
|
|
33
|
-
export {
|
|
34
|
-
export {
|
|
35
|
-
export {
|
|
36
|
-
export {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
export {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
export {
|
|
43
|
-
export {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
export {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
export {
|
|
50
|
-
export {
|
|
51
|
-
export {
|
|
52
|
-
export {
|
|
53
|
-
export {
|
|
54
|
-
export {
|
|
55
|
-
export {
|
|
56
|
-
export {
|
|
57
|
-
|
|
58
|
-
export {
|
|
59
|
-
export
|
|
60
|
-
|
|
61
|
-
export {
|
|
62
|
-
|
|
63
|
-
export {
|
|
64
|
-
export type {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
} from "./g2/autotile"
|
|
68
|
-
|
|
69
|
-
export {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
export {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
export {
|
|
115
|
-
|
|
116
|
-
// ----
|
|
117
|
-
export {
|
|
118
|
-
export {
|
|
119
|
-
export {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
export {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
export {
|
|
126
|
-
export
|
|
127
|
-
export
|
|
128
|
-
|
|
129
|
-
// ----
|
|
130
|
-
export {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
export {
|
|
138
|
-
export {
|
|
139
|
-
export {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
export {
|
|
143
|
-
export {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
export {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
export
|
|
150
|
-
export {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
export {
|
|
154
|
-
export {
|
|
155
|
-
export {
|
|
156
|
-
export
|
|
157
|
-
export {
|
|
158
|
-
export {
|
|
159
|
-
export {
|
|
160
|
-
export {
|
|
161
|
-
export {
|
|
162
|
-
export {
|
|
1
|
+
// THE aggregation point. Every public global the SDK provides is re-exported here under the exact
|
|
2
|
+
// name user code uses it as. The bundler passes this file to esbuild's `inject:` option, so user
|
|
3
|
+
// code references `Scene`, `Sprite`, `toast`, … with no imports; esbuild tree-shakes away whatever
|
|
4
|
+
// a given project does not use (so a pure-2D project drops all 3D classes, and vice versa).
|
|
5
|
+
//
|
|
6
|
+
// Rule: this is the ONLY file that `export`s public names. Everything else is internal and imported
|
|
7
|
+
// by it. Host-provided globals (setLoop, console, setTimeout, DEG2RAD, asset, …) are NOT here —
|
|
8
|
+
// they live in src/host.d.ts as declarations and stay as free references at runtime.
|
|
9
|
+
|
|
10
|
+
// ---- math ----
|
|
11
|
+
export { Mathf } from "./math/Mathf"
|
|
12
|
+
export { Vec2, Vec3 } from "./math/vec"
|
|
13
|
+
export { Quat } from "./math/quat"
|
|
14
|
+
export { Mat4 } from "./math/mat4"
|
|
15
|
+
export { Color } from "./core/color"
|
|
16
|
+
|
|
17
|
+
// ---- aspects (attachable node capabilities) ----
|
|
18
|
+
export { Aspect, System, type With, type SystemHost } from "./core/Aspect"
|
|
19
|
+
export { type EventMap } from "./core/events"
|
|
20
|
+
export { Time } from "./core/time"
|
|
21
|
+
export { InspectorUI } from "./core/InspectorUI"
|
|
22
|
+
|
|
23
|
+
// ---- reactivity (signals; UI text/style props also accept `() => value` bindings) ----
|
|
24
|
+
export { signal, computed, effect, type Signal, type Computed } from "./core/signals"
|
|
25
|
+
export { __compWrite, __compOp, type CompAxis, type CompWriter } from "./core/compWrite"
|
|
26
|
+
|
|
27
|
+
// ---- canvas (core 2D drawing that bakes to a texture; shared by 2D/3D/UI) ----
|
|
28
|
+
export { Canvas, Bitmap } from "./canvas/Canvas"
|
|
29
|
+
|
|
30
|
+
// ---- platform runtime (injected globals; the host provides the lower-level _creator* bridges) ----
|
|
31
|
+
export { toast, openURL, SvgSource } from "./runtime/misc"
|
|
32
|
+
export { app, type AppState, type OrientationLock } from "./runtime/app"
|
|
33
|
+
export { clipboard } from "./runtime/clipboard"
|
|
34
|
+
export { date, type DateValue, type DateInput, type Unit, type Locale } from "./runtime/datetime"
|
|
35
|
+
export { fetch, fetchLocal, FormData, File, type FetchResponse } from "./runtime/fetch"
|
|
36
|
+
export { localStorage } from "./runtime/storage"
|
|
37
|
+
export { device, type HapticStyle, type MotionOptions } from "./runtime/device"
|
|
38
|
+
export { Input, InputChannel, type InputKeyEvent, type InputGamepadEvent, type InputEventName, type GamepadState, type GamepadAxisName } from "./runtime/input"
|
|
39
|
+
export { WebSocket } from "./runtime/net"
|
|
40
|
+
// App-backend transport: the compiler-generated stubs of `*.server.ts` modules call these; user code
|
|
41
|
+
// only ever imports its server functions (docs/backend-plan.md §4).
|
|
42
|
+
export { __rpc, __channel, __serverOnly, RpcError, type ClientChannel } from "./runtime/rpc"
|
|
43
|
+
export { AudioPlayer, VideoPlayer } from "./runtime/media"
|
|
44
|
+
export { openFilePicker } from "./runtime/files"
|
|
45
|
+
export { share } from "./runtime/share"
|
|
46
|
+
export { ClickEvent, TouchStartEvent, LongPressEvent } from "./runtime/touch"
|
|
47
|
+
|
|
48
|
+
// ---- 2D engine (creator-2d) ----
|
|
49
|
+
export { Scene2D } from "./g2/Scene2D"
|
|
50
|
+
export { Node2D } from "./g2/Node2D"
|
|
51
|
+
export { Camera2D } from "./g2/Camera2D"
|
|
52
|
+
export { Sprite } from "./g2/Sprite"
|
|
53
|
+
export { SpriteAnimation } from "./g2/SpriteAnimation"
|
|
54
|
+
export { Shape2D } from "./g2/Shape2D"
|
|
55
|
+
export { Physics2D } from "./g2/Physics2D"
|
|
56
|
+
export { Trigger2D } from "./g2/Trigger2D"
|
|
57
|
+
export { CharacterController2D } from "./g2/CharacterController2D"
|
|
58
|
+
export { OneWay2D } from "./g2/OneWay2D"
|
|
59
|
+
export { PhysicsGroup2D } from "./g2/groups2d"
|
|
60
|
+
export { Tilemap } from "./g2/Tilemap"
|
|
61
|
+
export { Texture2D } from "./g2/Texture2D"
|
|
62
|
+
// sprite sheets as data (.sprite.ts files — see src/g2/SpriteSheet.ts)
|
|
63
|
+
export { SpriteSheet, defineSpriteSheet } from "./g2/SpriteSheet"
|
|
64
|
+
export type { SpriteSheetDef, SheetSprite, SpriteMakeOptions } from "./g2/SpriteSheet"
|
|
65
|
+
// tilesets as data (.tiles.ts files — autotile materials, see src/g2/Tileset.ts + autotile.ts)
|
|
66
|
+
export { Tileset, defineTileset, Autotile2D } from "./g2/Tileset"
|
|
67
|
+
export { rawCell, isRawCell, rawIndex } from "./g2/autotile"
|
|
68
|
+
export { rot90, rot180, rot270, flipX, packTile, tileIndex, tileTurns, tileFlip, tileOriented } from "./g2/autotile"
|
|
69
|
+
export type {
|
|
70
|
+
TilesetDef, TileMaterial, PatchMaterial, PathMaterial, PatchSlots, EdgeSlot, FillBlock, BlockEntry,
|
|
71
|
+
TileBlock, TilePart,
|
|
72
|
+
} from "./g2/autotile"
|
|
73
|
+
// 2D scenes as data (.scene2d.ts files — see src/g2/defineScene2d.ts) + the cells('…') payload
|
|
74
|
+
export { defineScene2d, Scene2dHandle } from "./g2/defineScene2d"
|
|
75
|
+
export type { Scene2dDef, Scene2dNodeDef, Scene2dEnv, SpriteSourceDef, TilemapSourceDef, Camera2dNodeDef, LoadedScene2d } from "./g2/defineScene2d"
|
|
76
|
+
export { cells, encodeCells, type CellsData } from "./g2/cells"
|
|
77
|
+
// no-code 2D scenario aspects (attachable in scene files — see src/g2/scenarios2d.ts)
|
|
78
|
+
export { CameraFollow } from "./g2/scenarios2d"
|
|
79
|
+
|
|
80
|
+
// ---- UI (creator-ui) ----
|
|
81
|
+
export {
|
|
82
|
+
UIScreen, type UIScreenStyle,
|
|
83
|
+
UIRow, UIColumn, UIBox, type UIContainerStyle,
|
|
84
|
+
UIText, type UITextStyle,
|
|
85
|
+
UIButton, type UIButtonStyle,
|
|
86
|
+
UIImage, type UIImageStyle,
|
|
87
|
+
UIVideo, type UIVideoStyle,
|
|
88
|
+
UIInput, UITextArea, type UIInputStyle,
|
|
89
|
+
UIScrollable, type UIScrollableStyle,
|
|
90
|
+
UIPager, type UIPagerStyle,
|
|
91
|
+
UITabs, type UITabDef,
|
|
92
|
+
defineTabs, type TabDef, type TabsHandle,
|
|
93
|
+
UIWidget, type UIWidgetStyle,
|
|
94
|
+
UIModal, type UIModalStyle,
|
|
95
|
+
UIBottomSheet, type UIBottomSheetStyle,
|
|
96
|
+
UIPopover, type UIPopoverStyle,
|
|
97
|
+
UISpacer, type UISpacerStyle,
|
|
98
|
+
UIVirtualizedList,
|
|
99
|
+
Router,
|
|
100
|
+
NativeView, type UINativeViewStyle,
|
|
101
|
+
registerFont,
|
|
102
|
+
__uiMap,
|
|
103
|
+
__UIColumn, __UIRow, __UIBox, __UIButton, __UIScreen, __UIScrollable, __UIWidget,
|
|
104
|
+
} from "./ui/UI"
|
|
105
|
+
// The Presentable navigation contract (docs/navigation-presentable-plan.md). `Presentable` is
|
|
106
|
+
// interface + runtime companion (declaration merging): `Presentable.current` = what's on screen.
|
|
107
|
+
export { Presentable } from "./ui/UI"
|
|
108
|
+
export type { PresentOptions, Transition, TransitionName, TransitionSpec, TransitionTransform } from "./ui/UI"
|
|
109
|
+
// The base node type + the union a container accepts as children — documented as the signature of
|
|
110
|
+
// UIColumn/UIRow/append/etc., so they must be global (type-only; erased at runtime).
|
|
111
|
+
export type { UINode, UINodeChild } from "./ui/UINode"
|
|
112
|
+
// App theme variables (docs/ui-theme-plan.md): theme({...}) merges + returns typed var()
|
|
113
|
+
// accessors; system vars are static props (theme.primaryColor, theme["comfort-top"], …).
|
|
114
|
+
export { theme, type ThemeValues, type ThemeAccessors } from "./ui/theme"
|
|
115
|
+
|
|
116
|
+
// ---- animate ----
|
|
117
|
+
export { animate, animateMat4, stopAnimation, pauseAnimation, resumeAnimation } from "./animate/animate"
|
|
118
|
+
export { cubicBezier } from "./animate/bezier"
|
|
119
|
+
export { easeIn, easeOut, easeInOut } from "./animate/easings"
|
|
120
|
+
|
|
121
|
+
// ---- plugins (optional, host-provided capabilities — typed NativeView/service wrappers, see src/plugins/) ----
|
|
122
|
+
export { QRScanner } from "./plugins/qr"
|
|
123
|
+
export { CameraView, type CameraFacing } from "./plugins/camera"
|
|
124
|
+
export { Geolocation, type GeoPosition, type GeoOptions, type GeoWatch } from "./plugins/geolocation"
|
|
125
|
+
export { Push, type PushPayload, type PushStatus, type PushRegisterOptions, type PushEvent } from "./plugins/push"
|
|
126
|
+
export { OAuth, type OAuthCredential, type OAuthProviderName } from "./plugins/oauth"
|
|
127
|
+
export { Service } from "./plugins/service"
|
|
128
|
+
|
|
129
|
+
// ---- scenes as data (.scene.ts files — see src/scene/defineScene.ts) ----
|
|
130
|
+
export { defineScene, use, ref, make, SceneHandle, applyEditorPose as __applyEditorPose } from "./scene/defineScene"
|
|
131
|
+
export {
|
|
132
|
+
defineMaterial, MaterialHandle,
|
|
133
|
+
// editor-harness helpers (the scene editor's live material paths — not app API)
|
|
134
|
+
assignMaterialDef as __assignMaterialDef, applyMaterialParam as __applyMaterialParam,
|
|
135
|
+
} from "./scene/material"
|
|
136
|
+
export type { MaterialData, MaterialParamValue, ShaderMaterialDef, LitMaterialDef, UnlitMaterialDef } from "./scene/material"
|
|
137
|
+
export type { SceneDef, SceneNodeDef, MeshDef, LightDef, MaterialDef, CameraNodeDef, AspectEntry, MakeEntry, LoadedScene, SceneInstance } from "./scene/defineScene"
|
|
138
|
+
export { CameraPlace } from "./gl/CameraPlace"
|
|
139
|
+
export type { FieldMeta } from "./core/fields"
|
|
140
|
+
// Editor-only line drawing from generator rebuild() / make() factories / tool hooks — drawn by the
|
|
141
|
+
// scene editor's viewport overlay, a no-op everywhere else (see src/scene/gizmos.ts).
|
|
142
|
+
export { Gizmos, GizmoBuffer as __GizmoBuffer, withGizmoScope as __withGizmoScope } from "./scene/gizmos"
|
|
143
|
+
export type { GizmoStyle, GizmoAnchor } from "./scene/gizmos"
|
|
144
|
+
|
|
145
|
+
// ---- no-code scenario aspects (attachable in the scene editor — see src/gl/scenarios.ts) ----
|
|
146
|
+
export { MoveTo, FollowPath, Spin, LookAt, PlayAnimation } from "./gl/scenarios"
|
|
147
|
+
|
|
148
|
+
// ---- editor plugins (called from `*.editor.ts` files — editor bundles only; DCE'd from apps) ----
|
|
149
|
+
export { registerEditorWindow, registerEditorTool, __editorPlugins } from "./scene/editorPlugins"
|
|
150
|
+
export type { EditorApi, EditorRayHit, EditorToolHooks, EditorWindowFn } from "./scene/editorPlugins"
|
|
151
|
+
|
|
152
|
+
// ---- 3D engine (creator-gl) ----
|
|
153
|
+
export { Scene, ARScene, VRScene } from "./gl/Scene"
|
|
154
|
+
export { Node } from "./gl/Node"
|
|
155
|
+
export { Mesh } from "./gl/Mesh"
|
|
156
|
+
export { Model } from "./gl/Model"
|
|
157
|
+
export { Shape } from "./gl/Shape"
|
|
158
|
+
export { Physics } from "./gl/Physics"
|
|
159
|
+
export { Trigger } from "./gl/Trigger"
|
|
160
|
+
export { CharacterController } from "./gl/CharacterController"
|
|
161
|
+
export { Vehicle } from "./gl/Vehicle"
|
|
162
|
+
export type { DriveLayout, DifferentialMode, EngineConfig, SteeringConfig, AeroConfig } from "./gl/Vehicle"
|
|
163
|
+
export { Wheel } from "./gl/Wheel"
|
|
164
|
+
export type { TireCurve, WheelSuspension, WheelTire, WheelVisual } from "./gl/Wheel"
|
|
165
|
+
export { Gearbox } from "./gl/Gearbox"
|
|
166
|
+
export { AnimationClip } from "./gl/animation/AnimationClip"
|
|
167
|
+
export type { ClipDef, ClipTrackDef, ClipKey } from "./gl/animation/AnimationClip"
|
|
168
|
+
export { Animator } from "./gl/animation/Animator"
|
|
169
|
+
export { Playback } from "./gl/animation/Playback"
|
|
170
|
+
export { Loop } from "./gl/animation/Loop"
|
|
171
|
+
export { Layer } from "./gl/animation/Layer"
|
|
172
|
+
export type { PlayOptions, StopOptions, LayerOptions, LoopOptions, LoopDef, BlendPosition } from "./gl/animation/core"
|
|
173
|
+
export { IK } from "./gl/IK"
|
|
174
|
+
export type { IKTwoBone, IKLookAt } from "./gl/IK"
|
|
175
|
+
export { Light } from "./gl/Light"
|
|
176
|
+
export { Lightmap } from "./gl/Lightmap"
|
|
177
|
+
export { Material } from "./gl/Material"
|
|
178
|
+
export { Geometry } from "./gl/Geometry"
|
|
179
|
+
export { InstancedMesh } from "./gl/InstancedMesh"
|
|
180
|
+
export type { InstanceTransform } from "./gl/InstancedMesh"
|
|
181
|
+
export { Texture } from "./gl/Texture"
|
|
182
|
+
export { Camera } from "./gl/Camera"
|
|
183
|
+
export { Ray } from "./gl/Ray"
|
|
184
|
+
export { Plane } from "./gl/Plane"
|
|
185
|
+
export { Noise } from "./gl/Noise"
|
|
186
|
+
export { Particles, Trail, curve, colorCurve } from "./gl/Particles"
|
|
@@ -6,6 +6,10 @@ import { appEventsOn, appEventsOff, keyboardEventsOn, keyboardEventsOff } from "
|
|
|
6
6
|
|
|
7
7
|
export type AppState = "active" | "background"
|
|
8
8
|
|
|
9
|
+
/** `"landscape"` — either landscape direction (sensor landscape), `"portrait"` — upright only,
|
|
10
|
+
* `"auto"` — released: the device's own rotation rules apply. */
|
|
11
|
+
export type OrientationLock = "auto" | "portrait" | "landscape"
|
|
12
|
+
|
|
9
13
|
type AppEventMap = {
|
|
10
14
|
/** The app left the foreground (home button, tab hidden, another app on top). Delivered before
|
|
11
15
|
* the host halts the frame loop — the last chance to persist state / pause work. */
|
|
@@ -40,6 +44,15 @@ export const app = {
|
|
|
40
44
|
get keyboardHeight(): number {
|
|
41
45
|
return _creatorUtils.keyboardHeight?.() ?? 0
|
|
42
46
|
},
|
|
47
|
+
/** Lock the screen orientation — `"landscape"` for a horizontal game (the device rotates to
|
|
48
|
+
* landscape right away and stays there whichever way it is held), `"portrait"` for upright
|
|
49
|
+
* only, `"auto"` to release. Call it once at startup; the lock is per app run (it resets
|
|
50
|
+
* when the app quits or restarts), so there is nothing to undo. The rotation arrives as an
|
|
51
|
+
* ordinary resize — layouts reflow, a scene's viewport follows. Silent no-op on hosts
|
|
52
|
+
* without a rotatable screen (desktop, headless, web). */
|
|
53
|
+
setOrientation(mode: OrientationLock): void {
|
|
54
|
+
_creatorUtils.setOrientation?.(mode)
|
|
55
|
+
},
|
|
43
56
|
/** Re-run this app's bundle in a fresh world — the platform's `location.reload()`. Pass `url`
|
|
44
57
|
* to reboot with different launch arguments (the new run reads them via `app.launchUrl`),
|
|
45
58
|
* `null` to reboot with a cleared one, or omit it to replay the current one. No-op on hosts
|
|
@@ -1,12 +1,175 @@
|
|
|
1
|
-
// Keyboard/
|
|
2
|
-
//
|
|
1
|
+
// Keyboard / mouse / gamepad input behind one `Input` global (docs/input-plan.md).
|
|
2
|
+
//
|
|
3
|
+
// Two kinds of signal, two shapes of API:
|
|
4
|
+
// - BUTTONS — anything that goes down and up: keyboard keys, mouse buttons, gamepad buttons. One
|
|
5
|
+
// code vocabulary ('KeyW', 'MouseLeft', 'GamepadSouth'), one held-poll (`Input.key`) and one
|
|
6
|
+
// event pair (`Input.on('keydown' | 'keyup')`). A mouse button IS a key.
|
|
7
|
+
// - CONTINUOUS — mouse motion/wheel, sticks, triggers: polled every frame (`Input.mouse.delta`,
|
|
8
|
+
// `Input.gamepad(0).axis('leftX')`), never events.
|
|
9
|
+
// Bindings ("jump = Space | GamepadSouth") are app code: compare `e.code`, OR a few `Input.key`s.
|
|
10
|
+
// Hosts report physical state only (`_creatorUtils.inputKey/inputRead/registerInputEvent`).
|
|
11
|
+
|
|
12
|
+
/** Continuous channel ids — the `_creatorUtils.inputRead` contract (bridges.d.ts). */
|
|
13
|
+
export const InputChannel = {
|
|
14
|
+
MouseX: 0, MouseY: 1, MouseDX: 2, MouseDY: 3, WheelX: 4, WheelY: 5, PointerLocked: 6,
|
|
15
|
+
GamepadCount: 7,
|
|
16
|
+
GamepadBase: 16, GamepadStride: 16,
|
|
17
|
+
PadConnected: 0, PadLeftX: 1, PadLeftY: 2, PadRightX: 3, PadRightY: 4, PadLeftTrigger: 5, PadRightTrigger: 6,
|
|
18
|
+
} as const
|
|
19
|
+
|
|
20
|
+
export type InputEventName = "keydown" | "keyup" | "gamepadconnected" | "gamepaddisconnected"
|
|
21
|
+
|
|
22
|
+
/** `keydown` / `keyup` payload. `code` is the same string `Input.key()` takes. */
|
|
23
|
+
export interface InputKeyEvent {
|
|
24
|
+
readonly type: "keydown" | "keyup"
|
|
25
|
+
/** Button code: KeyboardEvent.code ('KeyW', 'Space'), 'MouseLeft|Right|Middle|Back|Forward', or
|
|
26
|
+
* 'GamepadSouth|East|West|North|L1|R1|L2|R2|Select|Start|L3|R3|Up|Down|Left|Right'. */
|
|
27
|
+
readonly code: string
|
|
28
|
+
/** Which device: 'keyboard' | 'mouse' | 'gamepad'. */
|
|
29
|
+
readonly source: "keyboard" | "mouse" | "gamepad"
|
|
30
|
+
/** Pad index (0..3) for gamepad buttons, undefined otherwise. */
|
|
31
|
+
readonly gamepad?: number
|
|
32
|
+
/** OS auto-repeat keydown (key still held) — ignore for one-shot actions. */
|
|
33
|
+
readonly repeat: boolean
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface InputGamepadEvent {
|
|
37
|
+
readonly type: "gamepadconnected" | "gamepaddisconnected"
|
|
38
|
+
readonly gamepad: number
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type Listener<E> = (e: E) => void
|
|
42
|
+
type InputEventMap = {
|
|
43
|
+
keydown: InputKeyEvent
|
|
44
|
+
keyup: InputKeyEvent
|
|
45
|
+
gamepadconnected: InputGamepadEvent
|
|
46
|
+
gamepaddisconnected: InputGamepadEvent
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const listeners: { [K in InputEventName]?: Listener<InputEventMap[K]>[] } = {}
|
|
50
|
+
let hostListenerInstalled = false
|
|
51
|
+
|
|
52
|
+
const sourceOf = (code: string): InputKeyEvent["source"] =>
|
|
53
|
+
code.startsWith("Mouse") ? "mouse" : code.startsWith("Gamepad") ? "gamepad" : "keyboard"
|
|
54
|
+
|
|
55
|
+
const emit = <K extends InputEventName>(name: K, e: InputEventMap[K]) => {
|
|
56
|
+
const list = listeners[name]
|
|
57
|
+
if (!list || list.length === 0) return
|
|
58
|
+
for (const fn of [...list]) fn(e as any)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// One fan-out for the host channel and the test/host `_emit` seam.
|
|
62
|
+
const deliver = (kind: number, code: string, gamepad: number, repeat: number) => {
|
|
63
|
+
if (kind === 0 || kind === 1) {
|
|
64
|
+
const src = sourceOf(code)
|
|
65
|
+
emit(kind === 0 ? "keydown" : "keyup", {
|
|
66
|
+
type: kind === 0 ? "keydown" : "keyup", code, source: src,
|
|
67
|
+
gamepad: src === "gamepad" && gamepad >= 0 ? gamepad : undefined, repeat: repeat !== 0,
|
|
68
|
+
})
|
|
69
|
+
} else if (kind === 2 || kind === 3) {
|
|
70
|
+
emit(kind === 2 ? "gamepadconnected" : "gamepaddisconnected",
|
|
71
|
+
{ type: kind === 2 ? "gamepadconnected" : "gamepaddisconnected", gamepad })
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Lazily claim the host's single listener slot (never at module scope — chisel drops top-level
|
|
76
|
+
// side effects, and a host without the channel simply never fires).
|
|
77
|
+
const ensureHostListener = () => {
|
|
78
|
+
if (hostListenerInstalled) return
|
|
79
|
+
hostListenerInstalled = true
|
|
80
|
+
_creatorUtils.registerInputEvent?.(deliver)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const read = (channel: number): number => _creatorUtils.inputRead?.(channel) ?? 0
|
|
84
|
+
|
|
85
|
+
/** Mouse state — polled. Position is the cursor inside the viewport in logical px; `delta` is the
|
|
86
|
+
* motion during the previous frame (raw where the OS offers it) and keeps counting while locked —
|
|
87
|
+
* that's FPS look. Hosts without a mouse report zeros. */
|
|
88
|
+
export const mouse = {
|
|
89
|
+
get position(): { x: number, y: number } { return { x: read(InputChannel.MouseX), y: read(InputChannel.MouseY) } },
|
|
90
|
+
get delta(): { x: number, y: number } { return { x: read(InputChannel.MouseDX), y: read(InputChannel.MouseDY) } },
|
|
91
|
+
/** Wheel notches during the previous frame (+y = wheel toward you / scroll down). */
|
|
92
|
+
get wheel(): { x: number, y: number } { return { x: read(InputChannel.WheelX), y: read(InputChannel.WheelY) } },
|
|
93
|
+
/** Pointer lock: cursor hidden + confined, `delta` keeps flowing. Web grants it only from a user
|
|
94
|
+
* gesture (call it in a 'keydown' handler for MouseLeft); hosts drop it on focus loss and
|
|
95
|
+
* re-acquire on focus. Escape does NOT unlock by itself on native hosts — call `unlock()`. */
|
|
96
|
+
get locked(): boolean { return read(InputChannel.PointerLocked) !== 0 },
|
|
97
|
+
lock(): boolean { return _creatorUtils.inputSetPointerLock?.(true) ?? false },
|
|
98
|
+
unlock(): void { _creatorUtils.inputSetPointerLock?.(false) },
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export type GamepadAxisName = "leftX" | "leftY" | "rightX" | "rightY" | "leftTrigger" | "rightTrigger"
|
|
102
|
+
const PAD_AXIS: Record<GamepadAxisName, number> = {
|
|
103
|
+
leftX: InputChannel.PadLeftX, leftY: InputChannel.PadLeftY, rightX: InputChannel.PadRightX,
|
|
104
|
+
rightY: InputChannel.PadRightY, leftTrigger: InputChannel.PadLeftTrigger, rightTrigger: InputChannel.PadRightTrigger,
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface GamepadState {
|
|
108
|
+
readonly index: number
|
|
109
|
+
readonly connected: boolean
|
|
110
|
+
/** Stick axes −1..1 (+Y = down, like the web Gamepad API), triggers 0..1. `deadzone` (default
|
|
111
|
+
* 0.15) zeroes small stick drift — pass 0 for the raw value. */
|
|
112
|
+
axis(name: GamepadAxisName, deadzone?: number): number
|
|
113
|
+
/** Held? Same as `Input.key(code, index)`. */
|
|
114
|
+
button(code: string): boolean
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const padCache: GamepadState[] = []
|
|
118
|
+
const gamepadAt = (index: number): GamepadState => {
|
|
119
|
+
let g = padCache[index]
|
|
120
|
+
if (!g) {
|
|
121
|
+
const base = InputChannel.GamepadBase + InputChannel.GamepadStride * index
|
|
122
|
+
g = padCache[index] = {
|
|
123
|
+
index,
|
|
124
|
+
get connected() { return read(base + InputChannel.PadConnected) !== 0 },
|
|
125
|
+
axis(name, deadzone = 0.15) {
|
|
126
|
+
const v = read(base + PAD_AXIS[name])
|
|
127
|
+
return deadzone > 0 && Math.abs(v) < deadzone ? 0 : v
|
|
128
|
+
},
|
|
129
|
+
button(code) { return _creatorUtils.inputKey(code, index) },
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return g
|
|
133
|
+
}
|
|
3
134
|
|
|
4
135
|
export const Input = {
|
|
5
136
|
/**
|
|
6
|
-
* Is a
|
|
7
|
-
* '
|
|
137
|
+
* Is a button held? `code` is the physical key (`KeyboardEvent.code`: 'ArrowRight', 'KeyW',
|
|
138
|
+
* 'Space'), a mouse button ('MouseLeft', 'MouseRight', 'MouseMiddle') or a gamepad button
|
|
139
|
+
* ('GamepadSouth' = A/Cross, 'GamepadR2' = right trigger as a button …). Poll inside setLoop for
|
|
140
|
+
* frame-independent movement. `gamepad` scopes a Gamepad* code to one pad; omitted = any pad.
|
|
8
141
|
*/
|
|
9
|
-
key(code: string): boolean {
|
|
10
|
-
return _creatorUtils.inputKey(code)
|
|
142
|
+
key(code: string, gamepad?: number): boolean {
|
|
143
|
+
return _creatorUtils.inputKey(code, gamepad)
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
/** Listen for a discrete input moment. `keydown`/`keyup` cover EVERY button — keyboard, mouse,
|
|
147
|
+
* gamepad — filter on `e.code`. Use these for one-shot actions (jump, shoot, charge-release);
|
|
148
|
+
* `Input.key` for continuous ones (walk). */
|
|
149
|
+
on<K extends InputEventName>(name: K, listener: Listener<InputEventMap[K]>): void {
|
|
150
|
+
ensureHostListener()
|
|
151
|
+
const list = (listeners[name] ??= []) as Listener<InputEventMap[K]>[]
|
|
152
|
+
if (!list.includes(listener)) list.push(listener)
|
|
153
|
+
},
|
|
154
|
+
off<K extends InputEventName>(name: K, listener: Listener<InputEventMap[K]>): void {
|
|
155
|
+
const list = listeners[name] as Listener<InputEventMap[K]>[] | undefined
|
|
156
|
+
if (!list) return
|
|
157
|
+
const i = list.indexOf(listener)
|
|
158
|
+
if (i >= 0) list.splice(i, 1)
|
|
11
159
|
},
|
|
160
|
+
|
|
161
|
+
mouse,
|
|
162
|
+
|
|
163
|
+
/** Gamepad `index` (0..3). Always returns an object — check `.connected`. */
|
|
164
|
+
gamepad(index = 0): GamepadState { return gamepadAt(index) },
|
|
165
|
+
/** Indices of the currently connected gamepads. */
|
|
166
|
+
gamepads(): number[] {
|
|
167
|
+
const out: number[] = []
|
|
168
|
+
const n = read(InputChannel.GamepadCount)
|
|
169
|
+
for (let i = 0; i < 4 && out.length < n; i++) if (gamepadAt(i).connected) out.push(i)
|
|
170
|
+
return out
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
/** @internal — hosts/tests: deliver an event exactly as the host listener would. */
|
|
174
|
+
_emit(kind: number, code: string, gamepad: number, repeat: number): void { deliver(kind, code, gamepad, repeat) },
|
|
12
175
|
}
|