@deepblend/dsh-blender-contracts 0.2.15 → 0.2.16
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
|
@@ -96,6 +96,8 @@ export const ANIMATION_PROPERTIES_BY_KIND = Object.freeze({
|
|
|
96
96
|
export function collectionNameForKind(kind) {
|
|
97
97
|
if (kind === 'camera') return 'cameras'
|
|
98
98
|
if (kind === 'material') return 'materials'
|
|
99
|
+
// A BONE TRACK RESOLVES AGAINST THE ARMATURES, because that is the collection its id belongs to.
|
|
100
|
+
if (kind === 'bone') return 'armatures'
|
|
99
101
|
return 'entities'
|
|
100
102
|
}
|
|
101
103
|
|
|
@@ -360,6 +362,25 @@ export function validateSceneSpec(spec) {
|
|
|
360
362
|
// is what every track written before kinds existed meant.
|
|
361
363
|
const kind = track.targetKind ?? 'entity'
|
|
362
364
|
requiresId(collectionNameForKind(kind), track.targetEntityId, `${at}.targetEntityId`, kind)
|
|
365
|
+
// AND THE BONE INSIDE IT. MEASURED: this is the same shape as `armatureId` last round — the schema
|
|
366
|
+
// can say `boneName` is a string, and only a cross-reference can say the armature HAS that bone.
|
|
367
|
+
// A track pointing at a bone nobody declares animates nothing while the file says the rig moves.
|
|
368
|
+
if (kind === 'bone') {
|
|
369
|
+
if (typeof track.boneName !== 'string' || track.boneName.length === 0) {
|
|
370
|
+
errors.push({
|
|
371
|
+
severity: 'error', code: 'SCENE_REFERENCE_MISSING', path: `${at}.boneName`,
|
|
372
|
+
message: 'a bone track must name the bone it drives',
|
|
373
|
+
})
|
|
374
|
+
} else {
|
|
375
|
+
const armature = (document.armatures ?? []).find(entry => entry?.id === track.targetEntityId)
|
|
376
|
+
if (armature !== undefined && !(armature.bones ?? []).some(bone => bone?.name === track.boneName)) {
|
|
377
|
+
errors.push({
|
|
378
|
+
severity: 'error', code: 'SCENE_REFERENCE_MISSING', path: `${at}.boneName`,
|
|
379
|
+
message: `bone "${track.boneName}" does not exist in armature "${track.targetEntityId}"`,
|
|
380
|
+
})
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
363
384
|
|
|
364
385
|
// A property that does not belong to the target's kind is not a typo the
|
|
365
386
|
// compiler can shrug off: `emissionStrength` on an entity, or `location.x` on a
|
|
@@ -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.
|
|
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. Entities are skinned to an armature (`entity.armatureId`, with Blender's automatic weights) and animation tracks can drive a bone of it (`targetKind: \"bone\"` with `boneName`), so a rig both moves and moves its mesh."
|
|
35
35
|
},
|
|
36
36
|
"materials": {
|
|
37
37
|
"type": "array",
|
|
@@ -677,15 +677,21 @@
|
|
|
677
677
|
"enum": [
|
|
678
678
|
"entity",
|
|
679
679
|
"camera",
|
|
680
|
-
"material"
|
|
680
|
+
"material",
|
|
681
|
+
"bone"
|
|
681
682
|
],
|
|
682
683
|
"default": "entity",
|
|
683
|
-
"description": "What `targetEntityId` names: an entity (default), a camera, or
|
|
684
|
+
"description": "What `targetEntityId` names: an entity (default), a camera, a material, or AN ARMATURE whose bone this track drives (with `boneName`). Ids are unique per collection, so the kind is the only thing that says whether \"watch-dial\" means the mesh or the material \u2014 and `bone` is what made a rig able to move rather than merely exist."
|
|
684
685
|
},
|
|
685
686
|
"targetEntityId": {
|
|
686
687
|
"type": "string",
|
|
687
688
|
"description": "The id of the target named by `targetKind`. The field name says Entity because every track written before target kinds existed used it and revisions are immutable; renaming it would make r0001-r0023 unreadable. Resolution is against the collection `targetKind` names, which matters because ids are unique per collection, not globally."
|
|
688
689
|
},
|
|
690
|
+
"boneName": {
|
|
691
|
+
"type": "string",
|
|
692
|
+
"maxLength": 64,
|
|
693
|
+
"description": "Required when targetKind is `bone`: the name of the bone inside the named armature. A name the armature does not have is refused \u2014 a track that silently animates nothing is a scene that claims to move and does not."
|
|
694
|
+
},
|
|
689
695
|
"property": {
|
|
690
696
|
"type": "string",
|
|
691
697
|
"enum": [
|
package/package.json
CHANGED