lecodes-sdk 1.1.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/editor.d.ts +12 -0
- package/dist/global.d.ts +4 -8
- package/dist/host.d.ts +2 -3
- package/dist/types/animate/tween/Animation.d.ts +0 -3
- package/dist/types/animate/tween/animateValue.d.ts +4 -2
- package/dist/types/animate/tween/easing.d.ts +8 -0
- package/dist/types/animate/tween/spec.d.ts +15 -7
- package/dist/types/audio/audio.d.ts +2 -1
- package/dist/types/canvas/Canvas.d.ts +40 -108
- package/dist/types/canvas/gen/cssColor.d.ts +17 -0
- package/dist/types/canvas/gen/recorder.d.ts +118 -0
- package/dist/types/canvas/gen/spec.d.ts +144 -0
- package/dist/types/core/color.d.ts +3 -1
- package/dist/types/core/pins.d.ts +18 -0
- package/dist/types/g2/Node2D.d.ts +5 -8
- package/dist/types/g2/Scene2D.d.ts +6 -2
- package/dist/types/gl/Foliage.d.ts +30 -7
- package/dist/types/gl/Light.d.ts +11 -0
- package/dist/types/gl/Lightmap.d.ts +13 -2
- package/dist/types/gl/Material.d.ts +17 -3
- package/dist/types/gl/Model.d.ts +6 -2
- package/dist/types/gl/Node.d.ts +3 -6
- package/dist/types/gl/Particles.d.ts +15 -0
- package/dist/types/gl/Scene.d.ts +41 -13
- package/dist/types/gl/Texture.d.ts +1 -1
- package/dist/types/gl/animation/Locomotion.d.ts +59 -3
- package/dist/types/gl/terrain/Terrain.d.ts +8 -0
- package/dist/types/inject.d.ts +11 -11
- package/dist/types/inject.editor.d.ts +1 -0
- package/dist/types/net/core.d.ts +7 -0
- package/dist/types/plugin.d.ts +76 -0
- package/dist/types/plugins/gen/camera/sdk/camera.d.ts +24 -0
- package/dist/types/plugins/gen/camera/sdk/camera.gen.d.ts +25 -0
- package/dist/types/plugins/{geolocation.d.ts → gen/geolocation/sdk/geolocation.d.ts} +2 -20
- package/dist/types/plugins/gen/geolocation/sdk/geolocation.gen.d.ts +31 -0
- package/dist/types/plugins/{map.d.ts → gen/map/sdk/map.d.ts} +9 -50
- package/dist/types/plugins/gen/map/sdk/map.gen.d.ts +53 -0
- package/dist/types/plugins/gen/push/sdk/push.d.ts +23 -0
- package/dist/types/plugins/gen/push/sdk/push.gen.d.ts +35 -0
- package/dist/types/plugins/{qr.d.ts → gen/qr-scanner/sdk/qr-scanner.d.ts} +2 -3
- package/dist/types/plugins/gen/qr-scanner/sdk/qr-scanner.gen.d.ts +15 -0
- package/dist/types/runtime/app.d.ts +9 -2
- package/dist/types/runtime/fetch.d.ts +2 -0
- package/dist/types/runtime/input.d.ts +8 -1
- package/dist/types/runtime/media.d.ts +6 -10
- package/dist/types/runtime/misc.d.ts +4 -1
- package/dist/types/runtime/net.d.ts +3 -2
- package/dist/types/runtime/touch.d.ts +32 -0
- package/dist/types/scene/defineScene.d.ts +43 -2
- package/dist/types/scene/editor.d.ts +52 -0
- package/dist/types/scene/gizmos.d.ts +7 -4
- package/dist/types/ui/NativeView.d.ts +6 -4
- package/dist/types/ui/UI.d.ts +1 -1
- package/dist/types/ui/UIBottomSheet.d.ts +6 -12
- package/dist/types/ui/UIButton.d.ts +12 -14
- package/dist/types/ui/UIContainer.d.ts +0 -6
- package/dist/types/ui/UIImage.d.ts +1 -4
- package/dist/types/ui/UIInput.d.ts +8 -24
- package/dist/types/ui/UIModal.d.ts +0 -2
- package/dist/types/ui/UINode.d.ts +70 -56
- package/dist/types/ui/UIPager.d.ts +28 -27
- package/dist/types/ui/UIPopover.d.ts +0 -2
- package/dist/types/ui/UIScreen.d.ts +12 -17
- package/dist/types/ui/UIScrollable.d.ts +1 -4
- package/dist/types/ui/UIText.d.ts +0 -2
- package/dist/types/ui/UIVideo.d.ts +3 -5
- package/dist/types/ui/UIVirtualizedList.d.ts +14 -16
- package/dist/types/ui/UIWidget.d.ts +10 -9
- package/dist/types/ui/colorKeys.gen.d.ts +9 -0
- package/dist/types/ui/presentable.d.ts +46 -32
- package/dist/types/ui/router.d.ts +18 -7
- package/dist/types/ui/styleColor.d.ts +1 -0
- package/dist/types/ui/transitions.d.ts +18 -0
- package/dist/types/ui/tree.d.ts +75 -0
- package/dist/types/version.d.ts +10 -0
- package/dist/types.json +1 -1
- package/package.json +12 -3
- package/prompts/2d.md +2 -6
- package/prompts/3d.md +1 -5
- package/prompts/README.md +142 -142
- package/prompts/canvas.md +9 -8
- package/prompts/compose.ts +1 -1
- package/prompts/core.md +3 -3
- package/prompts/design.md +1 -1
- package/prompts/dist/2d-game.md +77 -54
- package/prompts/dist/3d-app.md +75 -52
- package/prompts/dist/ar-app.md +74 -51
- package/prompts/dist/design.md +30 -8
- package/prompts/dist/ui-app.md +73 -46
- package/prompts/ui-design.md +2 -3
- package/prompts/ui.md +45 -37
- package/src/animate/tween/Animation.ts +262 -378
- package/src/animate/tween/animateValue.ts +103 -100
- package/src/animate/tween/easing.ts +10 -3
- package/src/animate/tween/spec.ts +505 -479
- package/src/audio/Sound.ts +3 -3
- package/src/audio/audio.ts +162 -161
- package/src/bridges/2d.d.ts +317 -0
- package/src/bridges/app.d.ts +91 -0
- package/src/bridges/audio.d.ts +97 -0
- package/src/bridges/canvas.d.ts +79 -0
- package/src/bridges/device.d.ts +72 -0
- package/src/bridges/fetch.d.ts +80 -0
- package/src/bridges/files.d.ts +70 -0
- package/src/bridges/gl.d.ts +1133 -0
- package/src/bridges/input.d.ts +72 -0
- package/src/bridges/media.d.ts +55 -0
- package/src/bridges/nav.d.ts +71 -0
- package/src/bridges/net.d.ts +52 -0
- package/src/bridges/service.d.ts +52 -0
- package/src/bridges/socket.d.ts +31 -0
- package/src/bridges/storage.d.ts +33 -0
- package/src/bridges/tree.d.ts +301 -0
- package/src/bridges/types.d.ts +49 -0
- package/src/canvas/Canvas.ts +114 -159
- package/src/canvas/gen/cssColor.ts +224 -0
- package/src/canvas/gen/recorder.ts +212 -0
- package/src/canvas/gen/spec.ts +201 -0
- package/src/chisel.ts +193 -0
- package/src/compile/assetMacro.ts +1 -1
- package/src/compile/bundler.ts +11 -2
- package/src/compile/compileProject.ts +43 -4
- package/src/compile/fontMacro.ts +3 -4
- package/src/compile/header.ts +26 -5
- package/src/compile/index.ts +3 -1
- package/src/compile/liteMaterial.ts +1 -1
- package/src/compile/sceneEditor.ts +11 -26
- package/src/core/color.ts +73 -30
- package/src/core/pins.ts +51 -0
- package/src/core/signals.ts +8 -1
- package/src/g2/CharacterController2D.ts +3 -3
- package/src/g2/Node2D.ts +57 -39
- package/src/g2/Physics2D.ts +2 -2
- package/src/g2/Scene2D.ts +35 -23
- package/src/g2/Texture2D.ts +1 -1
- package/src/g2/loop.ts +4 -4
- package/src/gl/Foliage.ts +72 -17
- package/src/gl/Geometry.ts +1 -2
- package/src/gl/Light.ts +13 -0
- package/src/gl/Lightmap.ts +45 -29
- package/src/gl/Material.ts +95 -51
- package/src/gl/Model.ts +172 -167
- package/src/gl/Node.ts +91 -24
- package/src/gl/Particles.ts +20 -1
- package/src/gl/Scene.ts +100 -44
- package/src/gl/Texture.ts +8 -7
- package/src/gl/animation/AnimationClip.ts +1 -1
- package/src/gl/animation/Locomotion.ts +77 -8
- package/src/gl/nav/NavMesh.ts +3 -4
- package/src/gl/physics/Physics.ts +2 -2
- package/src/gl/physics/physicsEvents.ts +3 -3
- package/src/gl/terrain/Terrain.ts +33 -5
- package/src/gl/touch.ts +14 -15
- package/src/host.d.ts +2 -3
- package/src/inject.editor.ts +7 -0
- package/src/inject.ts +233 -236
- package/src/net/core.ts +6 -5
- package/src/net/index.ts +1 -1
- package/src/net/replication.ts +1 -1
- package/src/plugin.ts +191 -0
- package/src/plugins/gen/camera/contract.d.ts +27 -0
- package/src/plugins/gen/camera/sdk/camera.gen.ts +46 -0
- package/src/plugins/gen/camera/sdk/camera.ts +57 -0
- package/src/plugins/gen/geolocation/contract.d.ts +50 -0
- package/src/plugins/gen/geolocation/sdk/geolocation.gen.ts +54 -0
- package/src/plugins/{geolocation.ts → gen/geolocation/sdk/geolocation.ts} +22 -43
- package/src/plugins/gen/map/contract.d.ts +144 -0
- package/src/plugins/gen/map/sdk/map.gen.ts +88 -0
- package/src/plugins/{map.ts → gen/map/sdk/map.ts} +68 -102
- package/src/plugins/gen/push/contract.d.ts +61 -0
- package/src/plugins/gen/push/sdk/push.gen.ts +60 -0
- package/src/plugins/gen/push/sdk/push.ts +105 -0
- package/src/plugins/gen/qr-scanner/contract.d.ts +16 -0
- package/src/plugins/gen/qr-scanner/sdk/qr-scanner.gen.ts +29 -0
- package/src/plugins/gen/qr-scanner/sdk/qr-scanner.ts +52 -0
- package/src/plugins/permission.ts +5 -4
- package/src/runtime/app.ts +20 -9
- package/src/runtime/appEvents.ts +5 -4
- package/src/runtime/channel.ts +18 -15
- package/src/runtime/clipboard.ts +4 -3
- package/src/runtime/datetime.ts +2 -1
- package/src/runtime/device.ts +17 -15
- package/src/runtime/fetch.ts +30 -20
- package/src/runtime/files.ts +16 -15
- package/src/runtime/input.ts +21 -8
- package/src/runtime/media.ts +50 -46
- package/src/runtime/misc.ts +7 -3
- package/src/runtime/net.ts +8 -7
- package/src/runtime/rpc.ts +1 -3
- package/src/runtime/service.ts +19 -14
- package/src/runtime/share.ts +4 -3
- package/src/runtime/storage.ts +6 -4
- package/src/runtime/touch.ts +32 -0
- package/src/scene/defineScene.ts +61 -365
- package/src/scene/editor.ts +408 -0
- package/src/scene/editorPlugins.ts +3 -3
- package/src/scene/gizmos.ts +154 -148
- package/src/server/db/marci/query.ts +1 -1
- package/src/server/host.ts +1 -1
- package/src/server/runtime.ts +1 -1
- package/src/ui/NativeView.ts +72 -25
- package/src/ui/UI.ts +3 -3
- package/src/ui/UIBottomSheet.ts +16 -17
- package/src/ui/UIButton.ts +54 -16
- package/src/ui/UIContainer.ts +0 -6
- package/src/ui/UIImage.ts +34 -30
- package/src/ui/UIInput.ts +29 -37
- package/src/ui/UIModal.ts +1 -3
- package/src/ui/UINode.ts +347 -297
- package/src/ui/UIPager.ts +93 -78
- package/src/ui/UIPopover.ts +0 -2
- package/src/ui/UIScreen.ts +41 -36
- package/src/ui/UIScrollable.ts +19 -13
- package/src/ui/UISpacer.ts +1 -1
- package/src/ui/UITabs.ts +8 -6
- package/src/ui/UIText.ts +7 -17
- package/src/ui/UIVideo.ts +30 -27
- package/src/ui/UIVirtualizedList.ts +58 -59
- package/src/ui/UIWidget.ts +38 -18
- package/src/ui/colorKeys.gen.ts +37 -0
- package/src/ui/fonts.ts +2 -2
- package/src/ui/presentable.ts +59 -42
- package/src/ui/router.ts +52 -35
- package/src/ui/styleColor.ts +56 -0
- package/src/ui/theme.ts +7 -6
- package/src/ui/transitions.ts +249 -0
- package/src/ui/tree.ts +346 -0
- package/src/version.ts +24 -0
- package/tests/helpers/engineWorld.ts +11 -0
- package/tests/helpers/fakeTree.ts +353 -0
- package/tests/helpers/hostStubs.ts +31 -0
- package/tests/helpers/index.ts +14 -0
- package/tests/helpers/memoryMarci.ts +124 -0
- package/tests/helpers/phases.ts +23 -0
- package/tests/helpers/preload.ts +18 -0
- package/tests/helpers/stubApp.ts +2 -0
- package/tests/helpers/stubDevice.ts +2 -0
- package/tests/helpers/stubFetch.ts +2 -0
- package/tests/helpers/stubInput.ts +2 -0
- package/dist/inject.js +0 -4730
- package/dist/types/core/registry.d.ts +0 -7
- package/dist/types/plugins/camera.d.ts +0 -25
- package/dist/types/plugins/push.d.ts +0 -46
- package/src/bridges.d.ts +0 -1760
- package/src/compile/__tests__/assetIconMacro.test.ts +0 -219
- package/src/compile/__tests__/assetMacro.test.ts +0 -100
- package/src/compile/__tests__/assetName.test.ts +0 -55
- package/src/compile/__tests__/compile.test.ts +0 -310
- package/src/compile/__tests__/detectEntry.test.ts +0 -151
- package/src/compile/__tests__/fontMacro.test.ts +0 -199
- package/src/compile/__tests__/serverSplit.test.ts +0 -27
- package/src/core/__tests__/stateMachine.test.ts +0 -132
- package/src/core/registry.ts +0 -23
- package/src/plugins/camera.ts +0 -81
- package/src/plugins/push.ts +0 -132
- package/src/plugins/qr.ts +0 -73
package/src/g2/Node2D.ts
CHANGED
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
|
|
12
12
|
import { AspectHost } from "../core/Aspect"
|
|
13
13
|
import type { CompAxis, CompWriter } from "../core/compWrite"
|
|
14
|
-
import {
|
|
14
|
+
import { DEAD_HANDLE, Pins, registerFreedKind } from "../core/pins"
|
|
15
|
+
import { OWNED_KIND_ENTITY_2D } from "../ui/tree"
|
|
15
16
|
import { Vec2, cx, cy, type Vec2Like } from "../math/vec"
|
|
16
17
|
import type { ClickEvent, TouchStartEvent } from "../runtime/touch"
|
|
17
18
|
import { ensurePointerEvents } from "./touch"
|
|
@@ -55,11 +56,15 @@ export type Node2DEvents = {
|
|
|
55
56
|
export type Contact2D = { point: Vec2, normal: Vec2, speed: number }
|
|
56
57
|
|
|
57
58
|
/** id → Node2D, so host callbacks (animation events) route back to the owning JS object. */
|
|
58
|
-
|
|
59
|
+
/** @internal The 2D nodes native owns right now (in a scene / under a parent), by entity id — what a
|
|
60
|
+
* contact or a pointer hit resolves to. See core/pins.ts. */
|
|
61
|
+
export const nodes2d = new Pins<Node2D>()
|
|
59
62
|
|
|
60
63
|
export class Node2D extends AspectHost<Node2DEvents> implements CompWriter {
|
|
61
|
-
/**
|
|
62
|
-
|
|
64
|
+
/** @internal The entity's owned handle (`_h.id` = the entity id; DEAD_HANDLE once destroyed). */
|
|
65
|
+
_h: Handle
|
|
66
|
+
/** Native entity id. */
|
|
67
|
+
get id(): number { return this._h.id }
|
|
63
68
|
|
|
64
69
|
/** Optional debug/editor name (plain JS data — scene2d files stamp their node names here). */
|
|
65
70
|
name?: string
|
|
@@ -98,13 +103,18 @@ export class Node2D extends AspectHost<Node2DEvents> implements CompWriter {
|
|
|
98
103
|
else if (this._xfKind === 1) _creator2d.characterSetFromEntity(this._xf)
|
|
99
104
|
}
|
|
100
105
|
|
|
101
|
-
|
|
102
|
-
private _children: Node2D[] = []
|
|
103
|
-
|
|
104
|
-
constructor(internalId?: number) {
|
|
106
|
+
constructor(internalId?: number | Handle) {
|
|
105
107
|
super()
|
|
106
|
-
|
|
107
|
-
|
|
108
|
+
registerFreedKind(OWNED_KIND_ENTITY_2D, nodes2d)
|
|
109
|
+
if (internalId === undefined) {
|
|
110
|
+
const h = _creator2d.createEntity()
|
|
111
|
+
this._h = typeof h === "number" ? { id: h } : h // a number only from a test stub
|
|
112
|
+
} else if (typeof internalId === "number") {
|
|
113
|
+
this._h = { id: internalId } // engine-owned: findable while the engine keeps it
|
|
114
|
+
nodes2d.pin(this)
|
|
115
|
+
} else {
|
|
116
|
+
this._h = internalId
|
|
117
|
+
}
|
|
108
118
|
}
|
|
109
119
|
|
|
110
120
|
// --- transform (Y-up, LOCAL to the parent; at zoom 1, units == logical pixels) ---
|
|
@@ -185,10 +195,20 @@ export class Node2D extends AspectHost<Node2DEvents> implements CompWriter {
|
|
|
185
195
|
set visible(v: boolean) { this._visible = v; _creator2d.setVisible(this.id, v) }
|
|
186
196
|
|
|
187
197
|
// --- hierarchy (parent/child; transforms above are LOCAL to the parent) ---
|
|
188
|
-
|
|
198
|
+
// The tree lives in the engine (phase 10): parent / children are read back; a node the SDK never
|
|
199
|
+
// wrapped (none today — every 2D entity is created here) reads as absent.
|
|
200
|
+
get parent(): Node2D | null {
|
|
201
|
+
const p = _creator2d.getParent(this.id)
|
|
202
|
+
return p !== 0 ? nodes2d.get(p) ?? null : null
|
|
203
|
+
}
|
|
189
204
|
set parent(p: Node2D | null) { this.setParent(p) }
|
|
190
205
|
|
|
191
|
-
get children(): readonly Node2D[] {
|
|
206
|
+
get children(): readonly Node2D[] {
|
|
207
|
+
const out: Node2D[] = []
|
|
208
|
+
const n = _creator2d.getChildCount(this.id)
|
|
209
|
+
for (let i = 0; i < n; i++) { const c = nodes2d.get(_creator2d.getChild(this.id, i)); if (c) out.push(c) }
|
|
210
|
+
return out
|
|
211
|
+
}
|
|
192
212
|
|
|
193
213
|
/** Attach children to this node (each keeps its current world transform). Returns this. */
|
|
194
214
|
add(...children: Node2D[]): this {
|
|
@@ -198,7 +218,7 @@ export class Node2D extends AspectHost<Node2DEvents> implements CompWriter {
|
|
|
198
218
|
|
|
199
219
|
/** Detach a direct child (reparents it to root, keeping its world transform). Returns this. */
|
|
200
220
|
remove(child: Node2D): this {
|
|
201
|
-
if (child.
|
|
221
|
+
if (child.parent === this) child.setParent(null)
|
|
202
222
|
return this
|
|
203
223
|
}
|
|
204
224
|
|
|
@@ -209,14 +229,9 @@ export class Node2D extends AspectHost<Node2DEvents> implements CompWriter {
|
|
|
209
229
|
*/
|
|
210
230
|
setParent(parent: Node2D | null, keepWorld = true): this {
|
|
211
231
|
if (parent === this) return this
|
|
212
|
-
if (this._parent) {
|
|
213
|
-
const arr = this._parent._children
|
|
214
|
-
const i = arr.indexOf(this)
|
|
215
|
-
if (i >= 0) arr.splice(i, 1)
|
|
216
|
-
}
|
|
217
|
-
this._parent = parent
|
|
218
|
-
if (parent) parent._children.push(this)
|
|
219
232
|
_creator2d.setParent(this.id, parent?.id ?? 0, keepWorld)
|
|
233
|
+
if (parent) nodes2d.pin(this) // the parent owns it now
|
|
234
|
+
else if (!_creator2d.entityIsOwned(this.id)) nodes2d.unpin(this.id) // loose again: its handle owns it
|
|
220
235
|
if (keepWorld) this._syncLocalFromNative() // native recomputed our local transform
|
|
221
236
|
return this
|
|
222
237
|
}
|
|
@@ -278,28 +293,31 @@ export class Node2D extends AspectHost<Node2DEvents> implements CompWriter {
|
|
|
278
293
|
this.dispatch(channel, ...args)
|
|
279
294
|
}
|
|
280
295
|
|
|
296
|
+
/** Destroy this node and its whole subtree (children go with it — the 3D / UI contract). Every
|
|
297
|
+
* aspect in the subtree detaches first (physics bodies released, updaters unregistered). */
|
|
281
298
|
destroy(): void {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
this
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
//
|
|
299
|
+
if (this._h.id === 0) return
|
|
300
|
+
const subtree: Node2D[] = []
|
|
301
|
+
const collect = (n: Node2D) => { subtree.push(n); for (const c of n.children) collect(c) }
|
|
302
|
+
collect(this)
|
|
303
|
+
for (let i = subtree.length - 1; i >= 0; i--) subtree[i]._detachAll()
|
|
304
|
+
const id = this.id
|
|
305
|
+
// Dead NOW — entity ids are recycled, and the runtime's freed report lands a drain later.
|
|
306
|
+
for (const n of subtree) { nodes2d.unpin(n.id); n._dead() }
|
|
307
|
+
_creator2d.destroyEntity(id)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** @internal The wrapper's resource is gone: no more native calls from here. */
|
|
311
|
+
_dead(): void {
|
|
289
312
|
this._xf = 0
|
|
290
313
|
this._xfKind = 0
|
|
291
314
|
this._physicsDriven = false
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
const orphans = this._children.slice()
|
|
300
|
-
this._children.length = 0
|
|
301
|
-
node2dRegistry.delete(this.id)
|
|
302
|
-
_creator2d.destroyEntity(this.id)
|
|
303
|
-
for (const c of orphans) { c._parent = null; c._syncLocalFromNative() }
|
|
315
|
+
this._h = DEAD_HANDLE
|
|
316
|
+
}
|
|
317
|
+
/** @internal The runtime freed the entity underneath (an ancestor destroyed or dropped). */
|
|
318
|
+
_freed(): void {
|
|
319
|
+
if (this._h.id === 0) return
|
|
320
|
+
this._detachAll()
|
|
321
|
+
this._dead()
|
|
304
322
|
}
|
|
305
323
|
}
|
package/src/g2/Physics2D.ts
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
import { Aspect } from "../core/Aspect"
|
|
21
21
|
import { Vec2, cx, cy, type Vec2Like } from "../math/vec"
|
|
22
|
-
import {
|
|
22
|
+
import { nodes2d, type Node2D } from "./Node2D"
|
|
23
23
|
import { Shape2D } from "./Shape2D"
|
|
24
24
|
import {
|
|
25
25
|
PhysicsGroup2D, _addGroup, _watchGroupChanges, _unwatchGroupChanges,
|
|
@@ -51,7 +51,7 @@ export interface RayHit {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
// Resolve a native entity id to its Node2D (0 = none).
|
|
54
|
-
const node2dById = (id: number): Node2D | null => (id ?
|
|
54
|
+
const node2dById = (id: number): Node2D | null => (id ? nodes2d.get(id) ?? null : null)
|
|
55
55
|
|
|
56
56
|
export class Physics2D extends Aspect<"physics", Node2D> {
|
|
57
57
|
static readonly aspect = "physics"
|
package/src/g2/Scene2D.ts
CHANGED
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
|
|
4
4
|
import { Color, type ColorInput } from "../core/color"
|
|
5
5
|
import { _installAspectFrames, _installTimeScale, _attachSystem, _detachSystem, _detachAllSystems, type Aspect, type AspectCtor, type FieldOf, type TargetOf } from "../core/Aspect"
|
|
6
|
-
import { _bumpNavEpoch,
|
|
6
|
+
import { _bumpNavEpoch, _setCurrent, Presentable, type DestTuple, type DismissOptions, type PresentOptions } from "../ui/presentable"
|
|
7
|
+
import { _transitionId, TRANSITION_NONE } from "../ui/transitions"
|
|
8
|
+
import { TREE_DEST_SCENE2D, ensureEmitter, registerDest } from "../ui/tree"
|
|
7
9
|
import { cx, cy, type Vec2Like } from "../math/vec"
|
|
8
10
|
import type { ClickEvent, TouchStartEvent } from "../runtime/touch"
|
|
9
11
|
import { Camera2D } from "./Camera2D"
|
|
10
|
-
import {
|
|
12
|
+
import { nodes2d, type Node2D } from "./Node2D"
|
|
11
13
|
import { ensurePointerEvents } from "./touch"
|
|
12
14
|
|
|
13
15
|
// Route aspect update(dt) through the render-synced native phases (c2dRender early = before physics,
|
|
@@ -88,7 +90,7 @@ export class Scene2D implements Presentable {
|
|
|
88
90
|
* hit-test for tap/click picking — pair with camera.screenToWorld(). */
|
|
89
91
|
pick(worldPoint: Vec2Like): Node2D | null {
|
|
90
92
|
const id = _creator2d.pickSprite(this.id, cx(worldPoint), cy(worldPoint))
|
|
91
|
-
return id ?
|
|
93
|
+
return id ? nodes2d.get(id) ?? null : null
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
/** Scene-level pointer events. The handler fires for every tap/press in the scene, with
|
|
@@ -106,11 +108,14 @@ export class Scene2D implements Presentable {
|
|
|
106
108
|
}
|
|
107
109
|
|
|
108
110
|
add(...nodes: Node2D[]): this {
|
|
109
|
-
for (const n of nodes) _creator2d.addEntityToScene(this.id, n.id)
|
|
111
|
+
for (const n of nodes) { _creator2d.addEntityToScene(this.id, n.id); nodes2d.pin(n) } // the scene owns it now
|
|
110
112
|
return this
|
|
111
113
|
}
|
|
112
114
|
remove(...nodes: Node2D[]): this {
|
|
113
|
-
for (const n of nodes)
|
|
115
|
+
for (const n of nodes) {
|
|
116
|
+
_creator2d.removeEntityFromScene(this.id, n.id)
|
|
117
|
+
if (!_creator2d.entityIsOwned(n.id)) nodes2d.unpin(n.id) // loose again: its handle owns it
|
|
118
|
+
}
|
|
114
119
|
return this
|
|
115
120
|
}
|
|
116
121
|
|
|
@@ -162,10 +167,14 @@ export class Scene2D implements Presentable {
|
|
|
162
167
|
this.cl.push(callback)
|
|
163
168
|
return this
|
|
164
169
|
}
|
|
165
|
-
|
|
170
|
+
/** Hardware/system back while the scene is current. */
|
|
171
|
+
onBack(callback: () => void): this {
|
|
166
172
|
this._backButtonCallback = callback
|
|
167
173
|
return this
|
|
168
174
|
}
|
|
175
|
+
/** @deprecated Renamed `onBack` (2026-09-26). An alias for the projects compiled before the
|
|
176
|
+
* rename; removed with the release that recompiles them. */
|
|
177
|
+
onBackPressed(callback: () => void): this { return this.onBack(callback) }
|
|
169
178
|
|
|
170
179
|
/** @internal UIImage source marker (UIImage.toSrc): `UIImage(scene)` shows this scene live — the
|
|
171
180
|
* host draws it into the image node's box every frame with the scene's own camera (a minimap, a
|
|
@@ -174,9 +183,20 @@ export class Scene2D implements Presentable {
|
|
|
174
183
|
return { scene2d: this.id }
|
|
175
184
|
}
|
|
176
185
|
|
|
177
|
-
/** @internal
|
|
178
|
-
|
|
179
|
-
|
|
186
|
+
/** @internal The destination tuple (ui/presentable.ts). */
|
|
187
|
+
_dest(): DestTuple {
|
|
188
|
+
registerDest(TREE_DEST_SCENE2D, this.id, this)
|
|
189
|
+
return [TREE_DEST_SCENE2D, this.id, "", ""]
|
|
190
|
+
}
|
|
191
|
+
/** @internal presentation lifecycle from the runtime */
|
|
192
|
+
_emitOpen(): void { for (const cb of this.ol.slice()) cb() }
|
|
193
|
+
/** @internal */
|
|
194
|
+
_emitClose(): void { for (const cb of this.cl.slice()) cb() }
|
|
195
|
+
/** @internal */
|
|
196
|
+
_emitBack(): boolean {
|
|
197
|
+
if (!this._backButtonCallback) return false
|
|
198
|
+
this._backButtonCallback()
|
|
199
|
+
return true
|
|
180
200
|
}
|
|
181
201
|
|
|
182
202
|
/** Make this the active scene — shows it as the current destination (replaces a screen /
|
|
@@ -185,25 +205,17 @@ export class Scene2D implements Presentable {
|
|
|
185
205
|
_bumpNavEpoch()
|
|
186
206
|
// Reassert this scene's texture filter (the sampler is global — see Scene2DOptions.filter).
|
|
187
207
|
if (this._filter !== undefined) _creator2d.setDefaultFilter(this._filter === 'linear')
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
_creator2d.openScene(this.id)
|
|
193
|
-
for (const cb of this.ol) cb()
|
|
194
|
-
}
|
|
208
|
+
// The runtime activates the engine (openScene) as part of presenting the destination.
|
|
209
|
+
ensureEmitter()
|
|
210
|
+
registerDest(TREE_DEST_SCENE2D, this.id, this)
|
|
211
|
+
_creatorTree.open(TREE_DEST_SCENE2D, this.id, "", "", _transitionId(options?.transition, TRANSITION_NONE))
|
|
195
212
|
Scene2D._active = this
|
|
196
213
|
_setCurrent(this)
|
|
197
214
|
return this
|
|
198
215
|
}
|
|
199
|
-
close(): this {
|
|
216
|
+
close(options?: DismissOptions): this {
|
|
200
217
|
_bumpNavEpoch()
|
|
201
|
-
|
|
202
|
-
_creatorUI.closeView!()
|
|
203
|
-
} else {
|
|
204
|
-
_creator2d.closeScene()
|
|
205
|
-
for (const cb of this.cl) cb()
|
|
206
|
-
}
|
|
218
|
+
_creatorTree.close(TREE_DEST_SCENE2D, this.id, _transitionId(options?.transition, TRANSITION_NONE))
|
|
207
219
|
if (Scene2D._active === this) Scene2D._active = null
|
|
208
220
|
if (Presentable.current === this) _setCurrent(null)
|
|
209
221
|
return this
|
package/src/g2/Texture2D.ts
CHANGED
|
@@ -37,7 +37,7 @@ export class Texture2D {
|
|
|
37
37
|
})
|
|
38
38
|
}
|
|
39
39
|
return new Promise<Texture2D>((resolve, reject) => {
|
|
40
|
-
_creator2d.createTexture((source as any).
|
|
40
|
+
_creator2d.createTexture((source as any)._h.id, (id, w, h) => resolve(new Texture2D(id, w, h)), reject)
|
|
41
41
|
})
|
|
42
42
|
}
|
|
43
43
|
|
package/src/g2/loop.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// pulls none of this in.
|
|
7
7
|
|
|
8
8
|
import { Vec2 } from "../math/vec"
|
|
9
|
-
import {
|
|
9
|
+
import { nodes2d } from "./Node2D"
|
|
10
10
|
|
|
11
11
|
export const onUpdate = (callback: (dt: number) => void): void => _creator2d.onUpdate(callback)
|
|
12
12
|
export const offUpdate = (callback: (dt: number) => void): void => _creator2d.offUpdate(callback)
|
|
@@ -18,7 +18,7 @@ export const ensureAnimEvents = (): void => {
|
|
|
18
18
|
if (animEventsRegistered) return
|
|
19
19
|
animEventsRegistered = true
|
|
20
20
|
_creator2d.setOnAnimEvent(({ entityId, clipId, type }) => {
|
|
21
|
-
|
|
21
|
+
nodes2d.get(entityId)?._dispatchAnimEvent(clipId, type)
|
|
22
22
|
})
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -37,8 +37,8 @@ export const ensurePhysicsEvents = (): void => {
|
|
|
37
37
|
if (physicsEventsRegistered) return
|
|
38
38
|
physicsEventsRegistered = true
|
|
39
39
|
_creator2d.setOnPhysicsEvent((a, b, type, px, py, nx, ny, speed) => {
|
|
40
|
-
const na =
|
|
41
|
-
const nb =
|
|
40
|
+
const na = nodes2d.get(a)
|
|
41
|
+
const nb = nodes2d.get(b)
|
|
42
42
|
if (!na || !nb) return
|
|
43
43
|
const channel = type === 1 || type === 3 ? "exit" : "enter"
|
|
44
44
|
// Box2D's manifold normal points from A TOWARD B. Each listener wants the normal of the surface
|
package/src/gl/Foliage.ts
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
// Foliage — the vegetation tier of the lightmap material family (creator-gl materials/src/foliage.mat).
|
|
2
2
|
//
|
|
3
3
|
// A model loaded with `Model.load(src, { foliage: true })` (scene files: `foliage: true` on a `model`
|
|
4
|
-
// node) takes a shader whose vertices
|
|
4
|
+
// node) takes a shader whose vertices bend in the wind, lean away from BENDERS (the hero, enemies —
|
|
5
5
|
// any node registered with `Foliage.bend`) and thin out over a distance range, and whose fragment
|
|
6
6
|
// tints every copy a little differently. All of it is level-wide state the engine keeps: the wind
|
|
7
|
-
// and the
|
|
7
|
+
// and the options apply to every foliage model, present and future; benders are read from
|
|
8
8
|
// their live world transforms each frame (the 8 nearest the camera reach the shader); a fade is per
|
|
9
9
|
// ASSET — every copy of that model, present and future.
|
|
10
10
|
//
|
|
11
|
+
// THE WIND (2026-09-23) is the model of Unity HDRP's Wind.hlsl, what NatureManufacture's vegetation is
|
|
12
|
+
// authored for: a scrolling noise field read at each plant's root bends the whole plant about its root
|
|
13
|
+
// (the angle grows with the distance from the root: a cantilever's curve), a second, finer field read at
|
|
14
|
+
// each vertex moves the leaves (their shiver) — no fixed periods, the turbulence turns a tree off the mean
|
|
15
|
+
// wind, the gusts ride a slow third field. What differs per PLANT comes from the model, not from here:
|
|
16
|
+
// the material's drag / stiffness / permanent lean / shiver drag ride the GLB's material extras
|
|
17
|
+
// (`lecodes.wind`, written by `lecodes assets scene` from the Unity material), or default by the plant's
|
|
18
|
+
// size (grass under ~2 m, trees over ~5 m); the per-vertex shiver weight is the GLB's COLOR_0.a.
|
|
19
|
+
//
|
|
11
20
|
// Hosts without the tier (no `foliageSet*` bridge) ignore every call; the models then load through
|
|
12
21
|
// the ordinary lightmap tier where that exists, else the standard shader.
|
|
13
22
|
import { Model } from "./Model"
|
|
@@ -16,20 +25,21 @@ import { Node } from "./Node"
|
|
|
16
25
|
export type FoliageWind = {
|
|
17
26
|
/** Direction on the ground (x, z); normalised by the engine. Default [1, 0.3]. */
|
|
18
27
|
direction?: [number, number]
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
/** Radians per second of the main sway. Default 1.2. */
|
|
28
|
+
/** The wind speed in m/s — the plants' permanent bend and how fast the field drifts past them. Default 8.3
|
|
29
|
+
* (30 km/h, the pack's demo). 0 = still. */
|
|
22
30
|
speed?: number
|
|
23
|
-
/** 0..
|
|
31
|
+
/** 0..2: the random share of the speed — how far the bend wanders off the mean wind and how much the leaves move.
|
|
32
|
+
* Default 0.4. */
|
|
33
|
+
turbulence?: number
|
|
34
|
+
/** 0..1: the gusts' strength — waves of extra wind that travel over the level, calm between. Default 0.35. */
|
|
24
35
|
gust?: number
|
|
36
|
+
/** m/s the gust pattern travels at. Default 5.6 (20 km/h). */
|
|
37
|
+
gustSpeed?: number
|
|
25
38
|
}
|
|
26
39
|
|
|
27
40
|
export type FoliageOptions = {
|
|
28
41
|
/** The wind, or `false` for none. */
|
|
29
42
|
wind?: FoliageWind | false
|
|
30
|
-
/** Height above the instance origin (m) where the full sway / touch applies; the base never moves.
|
|
31
|
-
* Default 1.5. */
|
|
32
|
-
bendHeight?: number
|
|
33
43
|
/** Metres the TOP of a small plant leans away from a bender standing at its centre; the whole plant leans
|
|
34
44
|
* as one, rooted at its base. Plants over ~2 m react less, trees over ~5 m not at all (the engine
|
|
35
45
|
* measures each asset). Default 0.6. 0 = no touch reaction. */
|
|
@@ -39,20 +49,51 @@ export type FoliageOptions = {
|
|
|
39
49
|
variation?: number
|
|
40
50
|
/** 0..1: wrapped sun lighting — thin leaves let light through. Default 0.5. */
|
|
41
51
|
sunWrap?: number
|
|
52
|
+
/** A multiplier on every material's shiver drag (the leaves' own motion on top of the bend): 1 = as the
|
|
53
|
+
* model's materials say, 0 = the leaves ride the bend alone. Default 1. */
|
|
54
|
+
shiver?: number
|
|
55
|
+
/** 0..1: the sun through a thin leaf lit from behind (a back-lit crown glows). Default 0.35. */
|
|
56
|
+
translucency?: number
|
|
57
|
+
/** 0..1: how much of a light's shadow a leaf card takes. A crown scatters light through itself, so its cards take the
|
|
58
|
+
* shadow map partly — at 1 a distant crown is a dark silhouette lit only on its top layer. Bark always takes the
|
|
59
|
+
* shadow in full. Default 0.6. */
|
|
60
|
+
leafShadow?: number
|
|
61
|
+
/** 0..1: how far the baked per-vertex sky visibility (the crown's interior, the trunk under it) darkens the ambient.
|
|
62
|
+
* Default 0.7. */
|
|
63
|
+
skyAo?: number
|
|
64
|
+
/** 0..1: a leaf card's shading normal, from the card's own plane (0) to the crown's hull normal (1) — what hides that a
|
|
65
|
+
* crown is flat quads: each card is lit as the part of the volume it sits in. Default 0.7. */
|
|
66
|
+
canopy?: number
|
|
67
|
+
/** The cards' normal-map strength (a strong map brings the planes back). Default 0.5. */
|
|
68
|
+
normalMap?: number
|
|
69
|
+
/** A card seen edge-on dissolves over this much of |N·V| — no paper edges on the silhouette. Default 0.15, 0 = none. */
|
|
70
|
+
edgeFade?: number
|
|
71
|
+
/** Coverage held over distance: the cards' alpha × (1 + coverage × mip level), so a far crown does not thin out as its
|
|
72
|
+
* atlas mips away. Default 0.25, 0 = none; past ~0.5 a crown turns into a solid mass. */
|
|
73
|
+
coverage?: number
|
|
42
74
|
}
|
|
43
75
|
|
|
76
|
+
const DEFAULT_WIND: Required<FoliageWind> = { direction: [ 1, 0.3 ], speed: 8.3, turbulence: 0.4, gust: 0.35, gustSpeed: 5.6 }
|
|
77
|
+
|
|
44
78
|
const state: Required<Omit<FoliageOptions, "wind">> & { wind: Required<FoliageWind> | false } = {
|
|
45
|
-
wind: {
|
|
46
|
-
bendHeight: 1.5,
|
|
79
|
+
wind: { ...DEFAULT_WIND },
|
|
47
80
|
touch: 0.6,
|
|
48
81
|
variation: 0.35,
|
|
49
82
|
sunWrap: 0.5,
|
|
83
|
+
shiver: 1,
|
|
84
|
+
translucency: 0.35,
|
|
85
|
+
leafShadow: 0.6,
|
|
86
|
+
skyAo: 0.7,
|
|
87
|
+
canopy: 0.7,
|
|
88
|
+
normalMap: 0.5,
|
|
89
|
+
edgeFade: 0.15,
|
|
90
|
+
coverage: 0.25,
|
|
50
91
|
}
|
|
51
92
|
|
|
52
93
|
const pushWind = (): void => {
|
|
53
94
|
const w = state.wind
|
|
54
|
-
if (w === false) _creator.foliageSetWind?.(1, 0, 0,
|
|
55
|
-
else _creator.foliageSetWind?.(w.direction[0], w.direction[1], w.
|
|
95
|
+
if (w === false) _creator.foliageSetWind?.(1, 0, 0, 0, 0, 0)
|
|
96
|
+
else _creator.foliageSetWind?.(w.direction[0], w.direction[1], w.speed, w.turbulence, w.gust, w.gustSpeed)
|
|
56
97
|
}
|
|
57
98
|
|
|
58
99
|
export const Foliage = {
|
|
@@ -61,19 +102,33 @@ export const Foliage = {
|
|
|
61
102
|
configure(options: FoliageOptions): void {
|
|
62
103
|
if (options.wind !== undefined) Foliage.wind(options.wind)
|
|
63
104
|
let sway = false
|
|
64
|
-
if (options.bendHeight !== undefined) { state.bendHeight = options.bendHeight; sway = true }
|
|
65
105
|
if (options.touch !== undefined) { state.touch = options.touch; sway = true }
|
|
66
106
|
if (options.variation !== undefined) { state.variation = options.variation; sway = true }
|
|
67
107
|
if (options.sunWrap !== undefined) { state.sunWrap = options.sunWrap; sway = true }
|
|
68
|
-
if (sway) _creator.foliageSetOptions?.(state.
|
|
108
|
+
if (sway) _creator.foliageSetOptions?.(state.touch, state.variation, state.sunWrap)
|
|
109
|
+
let leaf = false
|
|
110
|
+
if (options.shiver !== undefined) { state.shiver = options.shiver; leaf = true }
|
|
111
|
+
if (options.translucency !== undefined) { state.translucency = options.translucency; leaf = true }
|
|
112
|
+
if (options.leafShadow !== undefined) { state.leafShadow = options.leafShadow; leaf = true }
|
|
113
|
+
if (options.skyAo !== undefined) { state.skyAo = options.skyAo; leaf = true }
|
|
114
|
+
if (leaf) _creator.foliageSetLeaf?.(state.shiver, state.translucency, state.leafShadow, state.skyAo)
|
|
115
|
+
let look = false
|
|
116
|
+
if (options.canopy !== undefined) { state.canopy = options.canopy; look = true }
|
|
117
|
+
if (options.normalMap !== undefined) { state.normalMap = options.normalMap; look = true }
|
|
118
|
+
if (options.edgeFade !== undefined) { state.edgeFade = options.edgeFade; look = true }
|
|
119
|
+
if (options.coverage !== undefined) { state.coverage = options.coverage; look = true }
|
|
120
|
+
if (look) _creator.foliageSetLook?.(state.canopy, state.normalMap, state.edgeFade, state.coverage)
|
|
69
121
|
},
|
|
70
122
|
|
|
71
123
|
/** The wind: fields given replace the current ones; `false` = calm. Live. */
|
|
72
124
|
wind(wind: FoliageWind | false): void {
|
|
73
125
|
if (wind === false) state.wind = false
|
|
74
126
|
else {
|
|
75
|
-
const cur = state.wind === false ?
|
|
76
|
-
state.wind = {
|
|
127
|
+
const cur = state.wind === false ? DEFAULT_WIND : state.wind
|
|
128
|
+
state.wind = {
|
|
129
|
+
direction: wind.direction ?? cur.direction, speed: wind.speed ?? cur.speed, turbulence: wind.turbulence ?? cur.turbulence,
|
|
130
|
+
gust: wind.gust ?? cur.gust, gustSpeed: wind.gustSpeed ?? cur.gustSpeed,
|
|
131
|
+
}
|
|
77
132
|
}
|
|
78
133
|
pushWind()
|
|
79
134
|
},
|
package/src/gl/Geometry.ts
CHANGED
|
@@ -109,9 +109,8 @@ export class Geometry {
|
|
|
109
109
|
if (typeof source !== "string") return Geometry.fromData(source)
|
|
110
110
|
const url = source
|
|
111
111
|
const resp = await fetch(url, { useOnce: true })
|
|
112
|
-
if (resp.status >= 400) {
|
|
112
|
+
if (resp.status >= 400) { throw new Error(`Geometry.load: ${url} → HTTP ${resp.status}`) }
|
|
113
113
|
const data = resp.json<GeometryData>()
|
|
114
|
-
resp.dispose()
|
|
115
114
|
return Geometry.fromData(data)
|
|
116
115
|
}
|
|
117
116
|
}
|
package/src/gl/Light.ts
CHANGED
|
@@ -27,6 +27,9 @@ export type SunOptions = {
|
|
|
27
27
|
* 3 - 2048 map, contact-hardening soft edges (PCSS: sharp where the caster touches, softer
|
|
28
28
|
* away; discrete-GPU territory, ~+60 % of a frame on an iGPU)
|
|
29
29
|
* A lightmapped level already carries every static shadow, so 0 is a legitimate choice there.
|
|
30
|
+
* On a level with a baked light grid the variance / PCSS filters cannot be used (they need every
|
|
31
|
+
* receiver in the shadow map, and the baked statics are kept out of it): 3 renders as PCSS on the
|
|
32
|
+
* depth map - the same contact-hardening look - and 2 renders as 1.
|
|
30
33
|
*/
|
|
31
34
|
shadowsQuality?: 0 | 1 | 2 | 3
|
|
32
35
|
/**
|
|
@@ -35,6 +38,13 @@ export type SunOptions = {
|
|
|
35
38
|
* the same quality and puts fewer casters in the shadow pass. 30-40 is plenty in first person.
|
|
36
39
|
*/
|
|
37
40
|
shadowDistance?: number
|
|
41
|
+
/**
|
|
42
|
+
* How many shadow-map cascades split `shadowDistance` (default 1). One map over the whole range gives a tall
|
|
43
|
+
* tree 5-10 cm shadow texels on its own trunk; 3 cascades put a tight map on the first metres and coarser
|
|
44
|
+
* ones behind, fit to their texel grids so the shadow does not swim as the camera moves. Each cascade is
|
|
45
|
+
* another caster pass, so it costs in proportion to what casts: forests, not a lightmapped level.
|
|
46
|
+
*/
|
|
47
|
+
shadowCascades?: 1 | 2 | 3 | 4
|
|
38
48
|
}
|
|
39
49
|
|
|
40
50
|
export type PointOptions = {
|
|
@@ -96,6 +106,7 @@ export class Light extends Node {
|
|
|
96
106
|
/** @internal sun shadow options as created (creation-time in the engine). */
|
|
97
107
|
_shadowsQuality = 1
|
|
98
108
|
_shadowDistance = 100
|
|
109
|
+
_shadowCascades = 1
|
|
99
110
|
|
|
100
111
|
/** A directional sun light. */
|
|
101
112
|
static sun(options: SunOptions = {}): Light {
|
|
@@ -106,6 +117,7 @@ export class Light extends Node {
|
|
|
106
117
|
light._color = options.color ?? 0xffffff
|
|
107
118
|
light._shadowsQuality = options.shadowsQuality ?? 1
|
|
108
119
|
light._shadowDistance = options.shadowDistance ?? 100
|
|
120
|
+
light._shadowCascades = options.shadowCascades ?? 1
|
|
109
121
|
Light.lastSun = light
|
|
110
122
|
_creator.createSunLight(
|
|
111
123
|
light.id, dx, dy, dz,
|
|
@@ -113,6 +125,7 @@ export class Light extends Node {
|
|
|
113
125
|
Color.toPackedRgb(options.color ?? 0xffffff),
|
|
114
126
|
options.shadowsQuality ?? 1,
|
|
115
127
|
options.shadowDistance ?? 100,
|
|
128
|
+
light._shadowCascades,
|
|
116
129
|
)
|
|
117
130
|
return light
|
|
118
131
|
}
|