lecodes-cli 0.17.1 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/index.js +1340 -648
  2. package/package.json +3 -3
  3. package/runtime/scene-harness.json +1 -1
  4. package/runtime/sdk/compile/bundler.ts +1 -1
  5. package/runtime/sdk/compile/compileProject.ts +16 -1
  6. package/runtime/sdk/compile/header.ts +6 -1
  7. package/runtime/sdk/compile/index.ts +16 -0
  8. package/runtime/sdk/compile/liteMaterial.ts +247 -0
  9. package/runtime/sdk/compile/shaderTargets.ts +42 -0
  10. package/runtime/sdk/core/Aspect.ts +255 -244
  11. package/runtime/sdk/g2/CharacterController2D.ts +2 -2
  12. package/runtime/sdk/gl/Camera.ts +41 -0
  13. package/runtime/sdk/gl/CameraPlace.ts +51 -0
  14. package/runtime/sdk/gl/CharacterController.ts +6 -2
  15. package/runtime/sdk/gl/IK.ts +193 -174
  16. package/runtime/sdk/gl/Material.ts +23 -0
  17. package/runtime/sdk/gl/Model.ts +7 -6
  18. package/runtime/sdk/gl/Node.ts +270 -285
  19. package/runtime/sdk/gl/Particles.ts +676 -625
  20. package/runtime/sdk/gl/Physics.ts +53 -1
  21. package/runtime/sdk/gl/Scene.ts +323 -291
  22. package/runtime/sdk/gl/Shape.ts +248 -8
  23. package/runtime/sdk/gl/Trigger.ts +50 -46
  24. package/runtime/sdk/gl/Vehicle.ts +519 -0
  25. package/runtime/sdk/gl/{AnimationClip.ts → animation/AnimationClip.ts} +37 -7
  26. package/runtime/sdk/gl/animation/Animator.ts +87 -0
  27. package/runtime/sdk/gl/animation/Layer.ts +29 -0
  28. package/runtime/sdk/gl/animation/Loop.ts +25 -0
  29. package/runtime/sdk/gl/animation/Playback.ts +43 -0
  30. package/runtime/sdk/gl/animation/core.ts +294 -0
  31. package/runtime/sdk/gl/scenarios.ts +26 -58
  32. package/runtime/sdk/inject.ts +18 -9
  33. package/runtime/sdk/runtime/app.ts +13 -0
  34. package/runtime/sdk/runtime/input.ts +169 -6
  35. package/runtime/sdk/scene/defineScene.ts +182 -26
  36. package/runtime/sdk/scene/gizmos.ts +128 -0
  37. package/runtime/sdk-types.json +1 -1
  38. package/runtime/sdk/gl/Animator.ts +0 -642
  39. package/runtime/sdk/gl/ModelAnimation.ts +0 -95
@@ -12,6 +12,7 @@
12
12
  // are driven with moveTo.
13
13
 
14
14
  import { Aspect } from "../core/Aspect"
15
+ import type { FieldMeta } from "../core/fields"
15
16
  import { Vec3, cx, cy, cz, type Vec3Like } from "../math/vec"
16
17
  import { nodeRegistry, type Node } from "./Node"
17
18
  import { Shape } from "./Shape"
@@ -48,6 +49,29 @@ export class Physics extends Aspect<"physics", Node> {
48
49
  motion: MotionType = "dynamic"
49
50
  /** Mass in kg for dynamic bodies (default 1). Ignored for static/kinematic. */
50
51
  mass = 1
52
+ /**
53
+ * Surface friction: 0 = ice, ~1 = grippy asphalt, and values above 1 are allowed (rubber on
54
+ * tarmac).
55
+ *
56
+ * The engine COMBINES the two touching bodies as `sqrt(a * b)`, so the LOWER value dominates and
57
+ * the floor caps everything standing on it. The default **0.6** is a neutral solid surface (the
58
+ * raw Jolt default of 0.2 is ice by game standards); dry tarmac a car should corner on wants a
59
+ * `1`, ice `0.02`. A Vehicle's tires read the GROUND body's value, so this is the single number
60
+ * that decides how well a car corners.
61
+ *
62
+ * Change it at runtime by re-configuring — `floor.aspect(Physics, { friction: 0.02 })` (an ice
63
+ * patch). It is a PLAIN FIELD on purpose: an accessor pair would be tree-shaken out of the
64
+ * bundle, because passing `{ friction }` in a config object is not a member reference the
65
+ * bundler can see, and the write would then silently land on a dead property.
66
+ */
67
+ friction = 0.6
68
+
69
+ /** Scene-editor inspector: `motion` as a dropdown (a string default alone infers a text box). */
70
+ static fields: FieldMeta<Physics> = {
71
+ motion: { options: [ "static", "kinematic", "dynamic" ] },
72
+ mass: { min: 0, step: 0.1 },
73
+ friction: { min: 0, max: 2, step: 0.05 },
74
+ }
51
75
 
52
76
  private _bodyId = 0
53
77
 
@@ -57,14 +81,29 @@ export class Physics extends Aspect<"physics", Node> {
57
81
  if (!shape) {
58
82
  throw new Error("Physics requires a Shape aspect — add it first: node.aspect(Shape, {…}).aspect(Physics, {…})")
59
83
  }
84
+ if (this.motion === "dynamic" && shape._isTriangleMesh) {
85
+ throw new Error("Physics: a dynamic body cannot use Shape { mesh: true } (triangle meshes are static/kinematic only) — use { mesh: 'convex' } or a primitive shape")
86
+ }
60
87
  const shapeId = shape._claim() // drop the pick-only body; reuse its shape
61
88
  this._bodyId = _creator.physicsCreateBody(this.node.id, shapeId, MOTION[this.motion], this.mass, false, false)
89
+ this._applyFriction()
62
90
  shape._ownBody(this._bodyId)
63
91
  }
64
92
 
65
93
  onDetach(): void {
66
94
  if (this._bodyId) { _creator.physicsRemoveBody(this._bodyId); this._bodyId = 0 }
67
- this.node.get(Shape)?._recreatePickBody() // keep the node pickable if the Shape stays
95
+ const shape = this.node.get(Shape)
96
+ if (shape) {
97
+ shape._ownBody(0) // the Shape held OUR body id — forget it, or its own detach removes it twice (native crash)
98
+ shape._recreatePickBody() // keep the node pickable if the Shape stays
99
+ }
100
+ }
101
+
102
+ /** Re-configuring (`node.aspect(Physics, { friction })`) pushes the new surface to the live body. */
103
+ onReconfigure(): void { this._applyFriction() }
104
+
105
+ private _applyFriction(): void {
106
+ if (this._bodyId) _creator.physicsSetFriction?.(this._bodyId, this.friction)
68
107
  }
69
108
 
70
109
  /** Native Jolt body id. 0 until attached, or if the build has no physics support. */
@@ -86,6 +125,19 @@ export class Physics extends Aspect<"physics", Node> {
86
125
  return this
87
126
  }
88
127
 
128
+ /** The same impulse applied at a WORLD-SPACE point instead of the centre of mass: the lever arm
129
+ * becomes angular impulse, so the body spins as well as moves (a bullet hitting a crate off
130
+ * centre, a blast lifting it by its base). Falls back to the central impulse on an older host. */
131
+ applyImpulseAt(v: Vec3Like, point: Vec3Like): this {
132
+ if (!this._bodyId) return this
133
+ if (_creator.physicsApplyImpulseAt) {
134
+ _creator.physicsApplyImpulseAt(this._bodyId, cx(v), cy(v), cz(v), cx(point), cy(point), cz(point))
135
+ } else {
136
+ _creator.physicsApplyImpulse(this._bodyId, cx(v), cy(v), cz(v))
137
+ }
138
+ return this
139
+ }
140
+
89
141
  /** Teleport / drive a kinematic (or dynamic) body to a world position. */
90
142
  moveTo(p: Vec3Like): this {
91
143
  if (this._bodyId) _creator.physicsSetBodyPosition(this._bodyId, cx(p), cy(p), cz(p))