lecodes-cli 0.16.2 → 0.17.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lecodes-cli",
3
- "version": "0.16.2",
3
+ "version": "0.17.0",
4
4
  "dependencies": {
5
5
  "@letary/chisel": "^0.8.0",
6
6
  "jimp": "^1.6.1"
@@ -11,11 +11,12 @@
11
11
  "qrcode-terminal": "^0.12.0",
12
12
  "lecodes-3d-editor": "workspace:*",
13
13
  "lecodes-assets": "workspace:*",
14
- "sdk": "workspace:*"
14
+ "sdk": "workspace:*",
15
+ "viewer-lite": "workspace:*"
15
16
  },
16
17
  "peerDependencies": {
17
18
  "lecodes-design": "^0.8.1",
18
- "lecodes-renderer": "^0.8.4",
19
+ "lecodes-renderer": "^0.8.5",
19
20
  "lecodes-3d-editor": "^0.3.0",
20
21
  "lecodes-assets": "^0.1.0"
21
22
  },
@@ -394,7 +394,8 @@ export class Animator extends Aspect<"animator", Node> {
394
394
  /** Default crossfade seconds for play()/stop(). */
395
395
  fade = 0.2
396
396
  /** Root motion: strip the root bone's horizontal travel from the pose and move the NODE with it
397
- * instead (or drive its CharacterController when it has one) — for clips whose hips actually travel
397
+ * instead (or drive its CharacterController — on this node or an ancestor — when it has one; the
398
+ * vertical part stays on the bone, so a jump's height is the clip's) — for clips whose hips actually travel
398
399
  * (Mixamo without "In Place", lunges, rolls). `true` = auto-detect the root bone (the shallowest bone
399
400
  * a clip translates), or a bone name. Read at attach. */
400
401
  rootMotion?: boolean | string
@@ -528,8 +529,15 @@ export class Animator extends Aspect<"animator", Node> {
528
529
  if (this.rootMotion) this._applyRootMotion(dt)
529
530
  }
530
531
 
532
+ /** The CharacterController root motion feeds: on this node, or on the nearest ANCESTOR — the usual
533
+ * rig is a capsule node holding Shape + CharacterController with the model parented under it,
534
+ * shifted down so its feet sit at the capsule's bottom (the controller centers the shape on its node). */
531
535
  private _controller(): CharacterController | undefined {
532
- return (this.node as unknown as { controller?: CharacterController }).controller
536
+ for (let n: Node | null = this.node; n; n = n.parent) {
537
+ const c = (n as unknown as { controller?: CharacterController }).controller
538
+ if (c) return c
539
+ }
540
+ return undefined
533
541
  }
534
542
 
535
543
  /** Root motion (last native frame's delta, node-local, horizontal): move the node, or feed the
@@ -13,6 +13,7 @@ import { Mat4, type Mat4Like } from "../math/mat4"
13
13
  import type { Geometry } from "./Geometry"
14
14
  import { registerTouchEndEvent, registerTouchStartEvent } from "./touch"
15
15
  import { ensurePhysicsEvents } from "./physicsEvents"
16
+ import { glState } from "./state"
16
17
  import type { ClickEvent, TouchStartEvent } from "../runtime/touch"
17
18
 
18
19
  /** id → Node, so host callbacks (touch hits, animation events) route back to the owning object. */
@@ -45,6 +46,7 @@ export class Node extends AspectHost<NodeEvents> {
45
46
 
46
47
  private _matrix?: Float32Array
47
48
  private _lastSync = 0
49
+ private _syncFrame = -1
48
50
  private _worldMatrix?: Float32Array
49
51
  private _scaleCache?: [number, number, number]
50
52
  private _boneCache?: Map<string, Node | null>
@@ -74,10 +76,13 @@ export class Node extends AspectHost<NodeEvents> {
74
76
  // hot path that returns the cache directly for cheap component reads.
75
77
  private _sync(): Float32Array {
76
78
  if (!this._matrix) this._matrix = new Float32Array(16)
77
- if (this._lastSync === 0 || Date.now() - this._lastSync > 10) {
79
+ // stale once per render frame (glState.frame — physics/controllers/animation rewrite transforms
80
+ // between frames), or after 10 ms of wall time when no scene loop is running
81
+ if (this._lastSync === 0 || this._syncFrame !== glState.frame || Date.now() - this._lastSync > 10) {
78
82
  _creator.getMatrix(this.id, this._matrix)
79
83
  this._scaleCache = undefined
80
84
  this._lastSync = Date.now()
85
+ this._syncFrame = glState.frame
81
86
  }
82
87
  return this._matrix
83
88
  }