@volter/blender-engine 0.1.141 → 0.1.143

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.
@@ -72,7 +72,7 @@ export type WorkerRequest =
72
72
  * bone, the LOCAL transform at every integer frame of the action's range,
73
73
  * plus the scene's frame range/fps and the summary row's key columns.
74
74
  * READ ONLY: keying, moving a key and setting a range are edits. */
75
- | { id: number; op: 'action-clip'; object?: string; bake?: boolean; action?: string }
75
+ | { id: number; op: 'action-clip'; object?: string; bake?: boolean; action?: string; summary?: boolean }
76
76
  /** ONE RESTRICTION COLUMN, written (`session.py`'s `outliner_set`). A column
77
77
  * Blender draws on no row of that type is refused by name. */
78
78
  | { id: number; op: 'outliner-set'; path: string; column: string; value: boolean }
package/browser/rna.ts CHANGED
@@ -602,6 +602,8 @@ export interface BlenderActionClip {
602
602
  readonly armature: string | null;
603
603
  readonly action: string | null;
604
604
  readonly slot: string | null;
605
+ /** The action's object slots: at most one means every armature reads the same curves. */
606
+ readonly objectSlots?: number;
605
607
  /** `layered` at this pin — an `Action` has no `.fcurves`; they live at
606
608
  * `layers[0].strips[0].channelbags[0].fcurves`. `legacy` is the branch for
607
609
  * a build where the old attribute is still there. */
@@ -424,13 +424,14 @@ export class BlenderRuntime {
424
424
  * false` answers the header and the summary row's key columns without the
425
425
  * sampled tracks, which is what a Timeline that only needs to DRAW asks
426
426
  * for. */
427
- async actionClip(options?: { object?: string; bake?: boolean; action?: string }): Promise<BlenderActionClip> {
427
+ async actionClip(options?: { object?: string; bake?: boolean; action?: string; summary?: boolean }): Promise<BlenderActionClip> {
428
428
  await this.#ready();
429
429
  return (await this.#request({
430
430
  op: 'action-clip',
431
431
  ...(options?.object === undefined ? {} : { object: options.object }),
432
432
  ...(options?.bake === undefined ? {} : { bake: options.bake }),
433
433
  ...(options?.action === undefined ? {} : { action: options.action }),
434
+ ...(options?.summary === undefined ? {} : { summary: options.summary }),
434
435
  })) as BlenderActionClip;
435
436
  }
436
437
 
@@ -5081,7 +5081,7 @@ def _summary_objects():
5081
5081
  return out
5082
5082
 
5083
5083
 
5084
- def rna_action_clip(object_name=None, bake=True, action_name=None):
5084
+ def rna_action_clip(object_name=None, bake=True, action_name=None, summary=True):
5085
5085
  """ONE ACTION AS A THREE.JS CLIP: per bone, the LOCAL transform it has at
5086
5086
  every integer frame of the action's own range.
5087
5087
 
@@ -5148,7 +5148,10 @@ def rna_action_clip(object_name=None, bake=True, action_name=None):
5148
5148
  # (`show_keys_from_selected_only`) and the view is what decides which
5149
5149
  # side of that filter it is on, so the door answers both halves even
5150
5150
  # when the subject below turns out to be nothing at all.
5151
- "summary": _summary_objects(),
5151
+ # `summary=False` for a reader that plays the clip (a game's clip library): the row walks
5152
+ # every animated object in the view layer, which was ~690 of a ~700 ms read on a level of
5153
+ # 23 armatures (measured 2026-10-08), and nothing that plays a clip draws it.
5154
+ "summary": _summary_objects() if summary else [],
5152
5155
  }
5153
5156
  adt = arm_obj.animation_data if arm_obj is not None else None
5154
5157
  assigned = adt.action if adt is not None else None
@@ -5181,6 +5184,11 @@ def rna_action_clip(object_name=None, bake=True, action_name=None):
5181
5184
  header["reason"] = ("%r has %d object slots and none named for %r; the first, %r, is played."
5182
5185
  % (action.name, len(slots), arm_obj.name, getattr(slot, "identifier", "?")))
5183
5186
  curves, shape = _action_channelbag(action, getattr(slot, "handle", None))
5187
+ # HOW MANY OBJECT SLOTS THE ACTION HAS: with one (or a legacy action, none) every armature
5188
+ # reads the same curves, so a reader may share the clip across armatures with the same bones;
5189
+ # with several, which one plays depends on the armature, so it may not.
5190
+ header["objectSlots"] = len([one for one in getattr(action, "slots", ())
5191
+ if getattr(one, "target_id_type", "OBJECT") == "OBJECT"])
5184
5192
  header.update({
5185
5193
  "action": action.name,
5186
5194
  "slot": getattr(slot, "name_display", None),
@@ -5882,7 +5890,8 @@ def _dispatch(request):
5882
5890
  # and neither owes a derivation. There is deliberately no writer beside
5883
5891
  # them -- keying, moving a key and setting a range are edits.
5884
5892
  if op == "action-clip":
5885
- return rna_action_clip(request.get("object"), request.get("bake", True), request.get("action"))
5893
+ return rna_action_clip(request.get("object"), request.get("bake", True), request.get("action"),
5894
+ request.get("summary", True))
5886
5895
  if op == "outliner":
5887
5896
  return rna_outliner(request.get("selected"))
5888
5897
  if op == "outliner-set":
package/browser/worker.ts CHANGED
@@ -811,6 +811,7 @@ async function handle(request: WorkerRequest): Promise<unknown> {
811
811
  ...(request.object === undefined ? {} : { object: request.object }),
812
812
  ...(request.bake === undefined ? {} : { bake: request.bake }),
813
813
  ...(request.action === undefined ? {} : { action: request.action }),
814
+ ...(request.summary === undefined ? {} : { summary: request.summary }),
814
815
  });
815
816
  case 'outliner-set':
816
817
  return ask({
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@volter/blender-engine",
3
3
  "author": "Volter AI, Inc.",
4
4
  "license": "GPL-3.0-or-later",
5
- "version": "0.1.141",
5
+ "version": "0.1.143",
6
6
  "publishConfig": {
7
7
  "access": "public"
8
8
  },