@deepblend/dsh-blender-contracts 0.2.14 → 0.2.15

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/lib/scene-spec.js CHANGED
@@ -185,6 +185,10 @@ export function validateSceneSpec(spec) {
185
185
  // ---- uniqueness ---------------------------------------------------------
186
186
  const collections = [
187
187
  ['assets', document.assets ?? []],
188
+ // ARMATURES ARE A COLLECTION LIKE ANY OTHER: they have ids, they can collide, and other things
189
+ // reference them by id. Leaving them out of this list meant the cross-reference check had nothing to
190
+ // look in, so a skinned entity was reported as naming a rig that does not exist — its own rig.
191
+ ['armatures', document.armatures ?? []],
188
192
  ['materials', document.materials ?? []],
189
193
  ['entities', document.entities],
190
194
  ['lights', document.lights ?? []],
@@ -279,6 +283,11 @@ export function validateSceneSpec(spec) {
279
283
  })
280
284
  }
281
285
  requiresId('materials', entity.materialId, `${at}.materialId`, 'material')
286
+ // AND THE RIG IT IS SKINNED TO. MEASURED: this check was missing at first, and the contract suite
287
+ // caught it — the schema can say `armatureId` is a string, but only a cross-reference can say it
288
+ // names something the scene declares. An entity skinned to an armature nobody declares would render
289
+ // as a static object while the file says it is rigged, which is the failure this code exists for.
290
+ requiresId('armatures', entity.armatureId, `${at}.armatureId`, 'armature')
282
291
  if (entity.type !== 'empty' && entity.materialId === undefined) {
283
292
  notices.push({
284
293
  severity: 'notice', code: 'SCENE_ENTITY_MATERIAL_DEFAULTED', path: at,
@@ -31,7 +31,7 @@
31
31
  "items": {
32
32
  "$ref": "#/$defs/armature"
33
33
  },
34
- "description": "Armatures this scene declares (SPEC \u00a720 M6, character animation). Each is one skeleton, created as its own object and named `<prefix><id>` like every other product object. WHAT THIS SLICE DOES NOT DO YET: bind a mesh to a bone (skinning) and animate a bone \u2014 those are the next two slices, and a rig that exists but drives nothing is honest about being exactly that."
34
+ "description": "Armatures this scene declares (SPEC \u00a720 M6, character animation). Each is one skeleton, created as its own object and named `<prefix><id>` like every other product object. WHAT THIS DOES NOT DO YET: animate a bone. Entities ARE skinned to an armature now (`entity.armatureId`, with Blender's automatic weights), so a rig drives its mesh \u2014 but nothing moves the rig until animation tracks can target bones, which is the next slice."
35
35
  },
36
36
  "materials": {
37
37
  "type": "array",
@@ -473,6 +473,10 @@
473
473
  "type": "string",
474
474
  "description": "Required when type is asset-instance."
475
475
  },
476
+ "armatureId": {
477
+ "type": "string",
478
+ "description": "The armature this entity is skinned to, named by `armatures[].id`. The compiler binds the mesh with Blender's own automatic weights, so the entity follows the bones with no weight table to write by hand. A name the scene does not declare is refused rather than ignored, because an entity that is silently unskinned renders as a static object while the file says it is rigged."
479
+ },
476
480
  "generator": {
477
481
  "$ref": "#/$defs/generator"
478
482
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepblend/dsh-blender-contracts",
3
- "version": "0.2.14",
3
+ "version": "0.2.15",
4
4
  "type": "module",
5
5
  "description": "DeepBlend Studio Service Definition, protocol contracts, and stable error codes.",
6
6
  "main": "lib/index.js",