lecodes-cli 0.18.0 → 0.18.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 +1 -1
- package/dist/index.js +2013 -564
- package/package.json +4 -4
- package/runtime/scene-harness.json +1 -1
- package/runtime/sdk/core/Aspect.ts +512 -255
- 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 +40 -1
- package/runtime/sdk/gl/CameraPlace.ts +52 -51
- package/runtime/sdk/gl/CharacterController.ts +184 -56
- package/runtime/sdk/gl/Gearbox.ts +212 -0
- package/runtime/sdk/gl/Geometry.ts +70 -9
- package/runtime/sdk/gl/Light.ts +64 -2
- package/runtime/sdk/gl/Lightmap.ts +179 -0
- package/runtime/sdk/gl/Material.ts +25 -0
- package/runtime/sdk/gl/Mesh.ts +6 -23
- package/runtime/sdk/gl/Model.ts +16 -2
- package/runtime/sdk/gl/Node.ts +119 -39
- package/runtime/sdk/gl/Physics.ts +75 -24
- package/runtime/sdk/gl/Scene.ts +161 -5
- package/runtime/sdk/gl/Shape.ts +42 -3
- package/runtime/sdk/gl/Trigger.ts +45 -50
- package/runtime/sdk/gl/Vehicle.ts +276 -322
- package/runtime/sdk/gl/Wheel.ts +240 -0
- package/runtime/sdk/gl/scenarios.ts +4 -30
- package/runtime/sdk/gl/state.ts +6 -6
- package/runtime/sdk/inject.ts +186 -171
- package/runtime/sdk/runtime/device.ts +102 -1
- package/runtime/sdk/scene/defineScene.ts +108 -53
- package/runtime/sdk/scene/gizmos.ts +31 -11
- package/runtime/sdk/scene/material.ts +188 -0
- package/runtime/sdk-types.json +1 -1
- package/runtime/sdk/compile/aspectMacro.ts +0 -42
- package/runtime/sdk/compile/assetIconMacro.ts +0 -384
- package/runtime/sdk/compile/assetMacro.ts +0 -45
- package/runtime/sdk/compile/assetName.ts +0 -50
- package/runtime/sdk/compile/bundler.ts +0 -252
- package/runtime/sdk/compile/compileProject.ts +0 -129
- package/runtime/sdk/compile/detectEntry.ts +0 -128
- package/runtime/sdk/compile/fontMacro.ts +0 -459
- package/runtime/sdk/compile/fontRegistry.ts +0 -78
- package/runtime/sdk/compile/header.ts +0 -67
- package/runtime/sdk/compile/index.ts +0 -85
- package/runtime/sdk/compile/libraryImports.ts +0 -52
- package/runtime/sdk/compile/liteMaterial.ts +0 -247
- package/runtime/sdk/compile/sceneEditor.ts +0 -78
- package/runtime/sdk/compile/serverSplit.ts +0 -233
- package/runtime/sdk/compile/serverTypes.ts +0 -227
- package/runtime/sdk/compile/sfnt.ts +0 -98
- package/runtime/sdk/compile/shaderTargets.ts +0 -42
- package/runtime/sdk/compile/sourcemap.ts +0 -25
package/runtime/sdk/gl/Shape.ts
CHANGED
|
@@ -98,6 +98,8 @@ export class Shape extends Aspect<"shape", Node> {
|
|
|
98
98
|
onDetach(): void {
|
|
99
99
|
if (this._bodyId) { _creator.physicsRemoveBody(this._bodyId); this._bodyId = 0 }
|
|
100
100
|
if (this._shapeId) { _creator.physicsDestroyShape(this._shapeId); this._shapeId = 0 }
|
|
101
|
+
this.node._xf = 0
|
|
102
|
+
this.node._xfKind = 0
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
/** Re-configuring (`node.aspect(Shape, { origin })`) rebuilds the geometry when a dimension, the
|
|
@@ -206,14 +208,20 @@ export class Shape extends Aspect<"shape", Node> {
|
|
|
206
208
|
|
|
207
209
|
// ---- body/shape lifetime --------------------------------------------------------------------
|
|
208
210
|
|
|
209
|
-
/** @internal Physics/Trigger take over: drop the pick body and hand back
|
|
211
|
+
/** @internal Physics/Trigger/CharacterController/Vehicle take over: drop the pick body and hand back
|
|
212
|
+
* the shape id. The node's transform owner goes with the body (the new owner sets its own). */
|
|
210
213
|
_claim(): number {
|
|
211
214
|
if (this._bodyId) { _creator.physicsRemoveBody(this._bodyId); this._bodyId = 0 }
|
|
215
|
+
this.node._xf = 0
|
|
216
|
+
this.node._xfKind = 0
|
|
212
217
|
return this._shapeId
|
|
213
218
|
}
|
|
214
|
-
/** @internal Physics/Trigger report the body they created, so Shape owns its lifetime + pickability.
|
|
219
|
+
/** @internal Physics/Trigger report the body they created, so Shape owns its lifetime + pickability.
|
|
220
|
+
* 0 = they are detaching and no longer own it. */
|
|
215
221
|
_ownBody(bodyId: number): void {
|
|
216
222
|
this._bodyId = bodyId
|
|
223
|
+
this.node._xf = bodyId // route node.position writes to the body (see Node._setOwnedPosition)
|
|
224
|
+
this.node._xfKind = bodyId ? 2 : 0
|
|
217
225
|
if (!this.raycast && bodyId) _creator.physicsSetPickable(bodyId, false)
|
|
218
226
|
}
|
|
219
227
|
/** @internal restore a pick-only body when Physics/Trigger detach but the Shape remains. */
|
|
@@ -223,6 +231,10 @@ export class Shape extends Aspect<"shape", Node> {
|
|
|
223
231
|
|
|
224
232
|
private _createPickBody(): void {
|
|
225
233
|
this._bodyId = _creator.physicsCreateBody(this.node.id, this._shapeId, 0, 0, false, /*pickOnly*/ true)
|
|
234
|
+
// Route position writes here too: the pick body is a static snapshot, so without this a moved node
|
|
235
|
+
// would keep taking its clicks at the old place.
|
|
236
|
+
this.node._xf = this._bodyId
|
|
237
|
+
this.node._xfKind = this._bodyId ? 2 : 0
|
|
226
238
|
if (!this.raycast && this._bodyId) _creator.physicsSetPickable(this._bodyId, false)
|
|
227
239
|
}
|
|
228
240
|
|
|
@@ -235,18 +247,45 @@ export class Shape extends Aspect<"shape", Node> {
|
|
|
235
247
|
private _rebuild(): void {
|
|
236
248
|
if (!this._shapeId) return // never attached, or a build without physics
|
|
237
249
|
const previous = this._shapeId
|
|
250
|
+
const previousSig = this._sig
|
|
238
251
|
const id = this._build()
|
|
239
252
|
if (!id) return // build failed — keep what works
|
|
253
|
+
|
|
254
|
+
// A CharacterController owns its shape and can REFUSE the swap: standing up under a pipe doesn't
|
|
255
|
+
// fit. Nothing is half-applied on refusal, so the fix is to stay UNCOMMITTED — leave `_sig` on the
|
|
256
|
+
// old geometry, and the next `node.aspect(Shape, …)` with the same dimensions sees a difference
|
|
257
|
+
// and tries again. That retry is the headroom test, and it is exact (the real capsule, not a ray).
|
|
258
|
+
const charId = this.node._xfKind === 1 ? this.node._xf : 0
|
|
259
|
+
if (charId) {
|
|
260
|
+
if (_creator.characterSetShape?.(charId, id)) {
|
|
261
|
+
this._shapeId = id
|
|
262
|
+
this._resizeRefused = false
|
|
263
|
+
_creator.physicsDestroyShape(previous)
|
|
264
|
+
} else {
|
|
265
|
+
_creator.physicsDestroyShape(id) // drop what we just built; the old collider stays live
|
|
266
|
+
this._sig = previousSig
|
|
267
|
+
this._resizeRefused = !!_creator.characterSetShape
|
|
268
|
+
if (!_creator.characterSetShape) {
|
|
269
|
+
console.warn(`Shape: this host can't resize a live CharacterController — "${this.node.name}" keeps its current collider`)
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return
|
|
273
|
+
}
|
|
274
|
+
|
|
240
275
|
this._shapeId = id
|
|
241
276
|
if (this._bodyId) {
|
|
242
277
|
if (_creator.physicsSetBodyShape) _creator.physicsSetBodyShape(this._bodyId, id, true)
|
|
243
278
|
else console.warn("Shape: this host can't re-shape a live body — the new dimensions apply from the next attach")
|
|
244
279
|
} else {
|
|
245
|
-
console.warn(`Shape: "${this.node.name}"'s geometry is owned by a
|
|
280
|
+
console.warn(`Shape: "${this.node.name}"'s geometry is owned by a Vehicle — re-attach it to pick up the new dimensions`)
|
|
246
281
|
}
|
|
247
282
|
_creator.physicsDestroyShape(previous)
|
|
248
283
|
}
|
|
249
284
|
|
|
285
|
+
/** @internal True while a requested resize has been refused — the fields say one thing, the engine
|
|
286
|
+
* is still using another. Surfaced as `controller.resizing`. */
|
|
287
|
+
_resizeRefused = false
|
|
288
|
+
|
|
250
289
|
private _build(): number {
|
|
251
290
|
this._autoOrigin = null
|
|
252
291
|
this._sig = this._signature()
|
|
@@ -1,50 +1,45 @@
|
|
|
1
|
-
// A trigger zone, as an aspect on a 3D Node. Requires a Shape (its geometry); creates a static SENSOR
|
|
2
|
-
// body from it, so a physics body overlapping the zone fires the node's 'enter' / 'exit' events
|
|
3
|
-
// instead of colliding. A trigger does not block movement, and is still pointer-pickable.
|
|
4
|
-
//
|
|
5
|
-
// const goal = new Mesh(box(), material)
|
|
6
|
-
// .aspect(Shape, { box: [1, 2, 1] })
|
|
7
|
-
// .aspect(Trigger)
|
|
8
|
-
// goal.addEventListener('enter', other => win(other))
|
|
9
|
-
// goal.addEventListener('exit', other => …)
|
|
10
|
-
|
|
11
|
-
import { Aspect } from "../core/Aspect"
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
shape.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
moveTo(p: Vec3Like): this {
|
|
47
|
-
if (this._bodyId) _creator.physicsSetBodyPosition(this._bodyId, cx(p), cy(p), cz(p))
|
|
48
|
-
return this
|
|
49
|
-
}
|
|
50
|
-
}
|
|
1
|
+
// A trigger zone, as an aspect on a 3D Node. Requires a Shape (its geometry); creates a static SENSOR
|
|
2
|
+
// body from it, so a physics body overlapping the zone fires the node's 'enter' / 'exit' events
|
|
3
|
+
// instead of colliding. A trigger does not block movement, and is still pointer-pickable.
|
|
4
|
+
//
|
|
5
|
+
// const goal = new Mesh(box(), material)
|
|
6
|
+
// .aspect(Shape, { box: [1, 2, 1] })
|
|
7
|
+
// .aspect(Trigger)
|
|
8
|
+
// goal.addEventListener('enter', other => win(other))
|
|
9
|
+
// goal.addEventListener('exit', other => …)
|
|
10
|
+
|
|
11
|
+
import { Aspect } from "../core/Aspect"
|
|
12
|
+
import { Shape } from "./Shape"
|
|
13
|
+
import { ensurePhysicsEvents } from "./physicsEvents"
|
|
14
|
+
import type { Node } from "./Node"
|
|
15
|
+
|
|
16
|
+
export class Trigger extends Aspect<"trigger", Node> {
|
|
17
|
+
static readonly aspect = "trigger"
|
|
18
|
+
|
|
19
|
+
private _bodyId = 0
|
|
20
|
+
/** Native body id (0 if no physics support). */
|
|
21
|
+
get id(): number { return this._bodyId }
|
|
22
|
+
|
|
23
|
+
onAttach(): void {
|
|
24
|
+
if (!_creator.physicsHasSupport || !_creator.physicsHasSupport()) return
|
|
25
|
+
const shape = this.node.get(Shape)
|
|
26
|
+
if (!shape) {
|
|
27
|
+
throw new Error("Trigger requires a Shape aspect — add it first: node.aspect(Shape, {…}).aspect(Trigger)")
|
|
28
|
+
}
|
|
29
|
+
const shapeId = shape._claim()
|
|
30
|
+
this._bodyId = _creator.physicsCreateBody(this.node.id, shapeId, 0 /* static */, 0, true /* sensor */, false)
|
|
31
|
+
shape._ownBody(this._bodyId)
|
|
32
|
+
ensurePhysicsEvents() // routes overlap events → the node's 'enter' / 'exit'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
onDetach(): void {
|
|
36
|
+
if (this._bodyId) { _creator.physicsRemoveBody(this._bodyId); this._bodyId = 0 }
|
|
37
|
+
const shape = this.node.get(Shape)
|
|
38
|
+
if (shape) {
|
|
39
|
+
shape._ownBody(0) // the Shape held OUR body id — forget it, or its own detach removes it twice (native crash)
|
|
40
|
+
shape._recreatePickBody()
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// No moveTo(): `node.position = p` moves the node AND the sensor body it owns (see Node._xf).
|
|
45
|
+
}
|