@deepblend/dsh-blender-contracts 0.1.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.
@@ -0,0 +1,1307 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://deepblend.local/schemas/scene-patch.schema.json",
4
+ "title": "DeepBlend ScenePatch v1",
5
+ "description": "A structured modification intent against one project revision (SPEC §8.3). A patch is never free-form: it carries the revision it was computed against, so a stale call can never silently overwrite newer work (SPEC §8.5, §9.4), and an idempotency key so a retried call can never apply twice. The key is DERIVED from the project, base revision and operations when the caller omits it, which makes an accidental retry safe by default; supply one explicitly only to re-apply the same operations on purpose.",
6
+ "type": "object",
7
+ "additionalProperties": false,
8
+ "required": [
9
+ "projectId",
10
+ "baseRevision",
11
+ "operations"
12
+ ],
13
+ "properties": {
14
+ "projectId": {
15
+ "type": "string",
16
+ "minLength": 1,
17
+ "maxLength": 64
18
+ },
19
+ "baseRevision": {
20
+ "type": "string",
21
+ "pattern": "^r[0-9]{4,}$",
22
+ "description": "The revision the caller read before computing this patch. A mismatch against currentRevision is rejected — no implicit overwrite."
23
+ },
24
+ "idempotencyKey": {
25
+ "type": "string",
26
+ "minLength": 1,
27
+ "maxLength": 128,
28
+ "description": "Caller-chosen key identifying THIS logical intent. OPTIONAL: when omitted, one is derived from {projectId, baseRevision, actor, stage, operations}, so an identical retry returns the recorded outcome without re-applying anything, while a genuinely different patch still applies normally. Supply an explicit key only when you deliberately want the same operations to produce a new revision."
29
+ },
30
+ "operations": {
31
+ "type": "array",
32
+ "minItems": 1,
33
+ "maxItems": 500,
34
+ "items": {
35
+ "$ref": "#/$defs/operation"
36
+ }
37
+ },
38
+ "saveCheckpoint": {
39
+ "type": "boolean",
40
+ "default": true,
41
+ "description": "Compile the patched spec and persist `<revision>/scene.blend` as the revision checkpoint. Required before a preview can be rendered from a checkpoint rather than a fresh compile (SPEC §9.1)."
42
+ },
43
+ "renderPreview": {
44
+ "type": "boolean",
45
+ "default": false,
46
+ "description": "Also render the preview profile as part of the same commit, so the first revision of a project already has a viewable artifact."
47
+ },
48
+ "actor": {
49
+ "type": "string",
50
+ "maxLength": 200,
51
+ "description": "Who asked for the change, for the audit trail: a session id, a stage name such as `visual_review`, or an operator."
52
+ },
53
+ "stage": {
54
+ "type": "string",
55
+ "maxLength": 64,
56
+ "description": "Orchestrator stage that produced this patch (SPEC §12.1), recorded in operation-manifest.json."
57
+ },
58
+ "note": {
59
+ "type": "string",
60
+ "maxLength": 2000,
61
+ "description": "Human-readable rationale, stored in the operation manifest so a revision history reads as prose."
62
+ }
63
+ },
64
+ "$defs": {
65
+ "id": {
66
+ "type": "string",
67
+ "minLength": 1,
68
+ "maxLength": 64,
69
+ "pattern": "^[a-zA-Z][a-zA-Z0-9._-]*$"
70
+ },
71
+ "license": {
72
+ "type": "object",
73
+ "additionalProperties": false,
74
+ "properties": {
75
+ "source": {
76
+ "type": "string",
77
+ "maxLength": 200
78
+ },
79
+ "commercialUse": {
80
+ "type": "boolean"
81
+ },
82
+ "attribution": {
83
+ "type": "string",
84
+ "maxLength": 500
85
+ }
86
+ }
87
+ },
88
+ "vec3": {
89
+ "type": "array",
90
+ "minItems": 3,
91
+ "maxItems": 3,
92
+ "items": {
93
+ "type": "number"
94
+ }
95
+ },
96
+ "world": {
97
+ "type": "object",
98
+ "additionalProperties": false,
99
+ "description": "The scene's environment illumination, replacing the whole block.",
100
+ "properties": {
101
+ "color": {
102
+ "$ref": "#/$defs/unitColor"
103
+ },
104
+ "strength": {
105
+ "type": "number",
106
+ "minimum": 0,
107
+ "maximum": 1000
108
+ }
109
+ }
110
+ },
111
+ "unitColor": {
112
+ "type": "array",
113
+ "minItems": 3,
114
+ "maxItems": 4,
115
+ "items": {
116
+ "type": "number",
117
+ "minimum": 0,
118
+ "maximum": 1
119
+ }
120
+ },
121
+ "positiveNumber": {
122
+ "type": "number",
123
+ "exclusiveMinimum": 0
124
+ },
125
+ "nonNegativeNumber": {
126
+ "type": "number",
127
+ "minimum": 0
128
+ },
129
+ "transformPatch": {
130
+ "type": "object",
131
+ "additionalProperties": false,
132
+ "properties": {
133
+ "location": {
134
+ "$ref": "#/$defs/vec3"
135
+ },
136
+ "rotationEuler": {
137
+ "$ref": "#/$defs/vec3"
138
+ },
139
+ "scale": {
140
+ "$ref": "#/$defs/vec3"
141
+ }
142
+ },
143
+ "description": "Only the supplied components change; the rest of the transform is preserved."
144
+ },
145
+ "materialParameters": {
146
+ "type": "object",
147
+ "additionalProperties": false,
148
+ "properties": {
149
+ "baseColor": {
150
+ "$ref": "#/$defs/unitColor"
151
+ },
152
+ "metallic": {
153
+ "type": "number",
154
+ "minimum": 0,
155
+ "maximum": 1
156
+ },
157
+ "roughness": {
158
+ "type": "number",
159
+ "minimum": 0,
160
+ "maximum": 1
161
+ },
162
+ "ior": {
163
+ "type": "number",
164
+ "exclusiveMinimum": 0,
165
+ "maximum": 5
166
+ },
167
+ "alpha": {
168
+ "type": "number",
169
+ "minimum": 0,
170
+ "maximum": 1
171
+ },
172
+ "emissionColor": {
173
+ "$ref": "#/$defs/unitColor"
174
+ },
175
+ "emissionStrength": {
176
+ "$ref": "#/$defs/nonNegativeNumber"
177
+ },
178
+ "coatWeight": {
179
+ "type": "number",
180
+ "minimum": 0,
181
+ "maximum": 1
182
+ },
183
+ "transmissionWeight": {
184
+ "type": "number",
185
+ "minimum": 0,
186
+ "maximum": 1
187
+ }
188
+ }
189
+ },
190
+ "proceduralTexture": {
191
+ "type": "object",
192
+ "additionalProperties": false,
193
+ "required": [
194
+ "type",
195
+ "scale"
196
+ ],
197
+ "description": "A procedural surface texture. Duplicated from scene-spec.schema.json because this schema is deliberately self-contained (it never $refs across files), so the two copies are kept in step by hand.",
198
+ "properties": {
199
+ "type": {
200
+ "type": "string",
201
+ "enum": [
202
+ "noise",
203
+ "wave",
204
+ "voronoi"
205
+ ]
206
+ },
207
+ "scale": {
208
+ "type": "number",
209
+ "exclusiveMinimum": 0
210
+ },
211
+ "detail": {
212
+ "type": "number",
213
+ "minimum": 0,
214
+ "maximum": 16
215
+ },
216
+ "distortion": {
217
+ "type": "number",
218
+ "minimum": 0
219
+ },
220
+ "stretch": {
221
+ "type": "array",
222
+ "minItems": 3,
223
+ "maxItems": 3,
224
+ "items": {
225
+ "type": "number",
226
+ "exclusiveMinimum": 0
227
+ }
228
+ },
229
+ "bump": {
230
+ "type": "number",
231
+ "minimum": 0,
232
+ "maximum": 1
233
+ },
234
+ "roughnessVariation": {
235
+ "type": "number",
236
+ "minimum": 0,
237
+ "maximum": 1
238
+ },
239
+ "colorVariation": {
240
+ "type": "number",
241
+ "minimum": 0,
242
+ "maximum": 1
243
+ }
244
+ }
245
+ },
246
+ "generator": {
247
+ "type": "object",
248
+ "additionalProperties": false,
249
+ "required": [
250
+ "shape"
251
+ ],
252
+ "properties": {
253
+ "shape": {
254
+ "type": "string",
255
+ "enum": [
256
+ "cube",
257
+ "uv_sphere",
258
+ "cylinder",
259
+ "cone",
260
+ "plane",
261
+ "torus",
262
+ "rounded_box"
263
+ ]
264
+ },
265
+ "size": {
266
+ "$ref": "#/$defs/positiveNumber"
267
+ },
268
+ "radius": {
269
+ "$ref": "#/$defs/positiveNumber"
270
+ },
271
+ "depth": {
272
+ "$ref": "#/$defs/positiveNumber"
273
+ },
274
+ "segments": {
275
+ "type": "integer",
276
+ "minimum": 3,
277
+ "maximum": 512
278
+ },
279
+ "ringCount": {
280
+ "type": "integer",
281
+ "minimum": 3,
282
+ "maximum": 512
283
+ },
284
+ "majorRadius": {
285
+ "$ref": "#/$defs/positiveNumber"
286
+ },
287
+ "minorRadius": {
288
+ "$ref": "#/$defs/positiveNumber"
289
+ },
290
+ "bevel": {
291
+ "type": "object",
292
+ "additionalProperties": false,
293
+ "properties": {
294
+ "width": {
295
+ "$ref": "#/$defs/positiveNumber"
296
+ },
297
+ "segments": {
298
+ "type": "integer",
299
+ "minimum": 1,
300
+ "maximum": 16
301
+ }
302
+ }
303
+ }
304
+ }
305
+ },
306
+ "entity": {
307
+ "type": "object",
308
+ "additionalProperties": false,
309
+ "required": [
310
+ "id",
311
+ "type"
312
+ ],
313
+ "properties": {
314
+ "id": {
315
+ "$ref": "#/$defs/id"
316
+ },
317
+ "type": {
318
+ "type": "string",
319
+ "enum": [
320
+ "asset-instance",
321
+ "generator",
322
+ "empty"
323
+ ]
324
+ },
325
+ "assetId": {
326
+ "type": "string"
327
+ },
328
+ "generator": {
329
+ "$ref": "#/$defs/generator"
330
+ },
331
+ "materialId": {
332
+ "type": "string"
333
+ },
334
+ "transform": {
335
+ "type": "object",
336
+ "additionalProperties": false,
337
+ "properties": {
338
+ "location": {
339
+ "$ref": "#/$defs/vec3"
340
+ },
341
+ "rotationEuler": {
342
+ "$ref": "#/$defs/vec3"
343
+ },
344
+ "scale": {
345
+ "$ref": "#/$defs/vec3"
346
+ }
347
+ }
348
+ },
349
+ "tags": {
350
+ "type": "array",
351
+ "items": {
352
+ "type": "string",
353
+ "maxLength": 64
354
+ }
355
+ },
356
+ "locked": {
357
+ "type": "boolean"
358
+ },
359
+ "visible": {
360
+ "type": "boolean"
361
+ }
362
+ }
363
+ },
364
+ "light": {
365
+ "type": "object",
366
+ "additionalProperties": false,
367
+ "required": [
368
+ "id",
369
+ "type"
370
+ ],
371
+ "properties": {
372
+ "id": {
373
+ "$ref": "#/$defs/id"
374
+ },
375
+ "type": {
376
+ "type": "string",
377
+ "enum": [
378
+ "area",
379
+ "point",
380
+ "spot",
381
+ "sun"
382
+ ]
383
+ },
384
+ "transform": {
385
+ "type": "object",
386
+ "additionalProperties": false,
387
+ "properties": {
388
+ "location": {
389
+ "$ref": "#/$defs/vec3"
390
+ },
391
+ "rotationEuler": {
392
+ "$ref": "#/$defs/vec3"
393
+ },
394
+ "scale": {
395
+ "$ref": "#/$defs/vec3"
396
+ }
397
+ }
398
+ },
399
+ "energy": {
400
+ "$ref": "#/$defs/nonNegativeNumber"
401
+ },
402
+ "color": {
403
+ "$ref": "#/$defs/unitColor"
404
+ },
405
+ "size": {
406
+ "$ref": "#/$defs/positiveNumber"
407
+ },
408
+ "spotSize": {
409
+ "type": "number",
410
+ "exclusiveMinimum": 0,
411
+ "maximum": 3.14159265358979
412
+ },
413
+ "spotBlend": {
414
+ "type": "number",
415
+ "minimum": 0,
416
+ "maximum": 1
417
+ },
418
+ "angle": {
419
+ "type": "number",
420
+ "exclusiveMinimum": 0,
421
+ "maximum": 3.14159265358979
422
+ }
423
+ }
424
+ },
425
+ "camera": {
426
+ "type": "object",
427
+ "additionalProperties": false,
428
+ "required": [
429
+ "id"
430
+ ],
431
+ "properties": {
432
+ "id": {
433
+ "$ref": "#/$defs/id"
434
+ },
435
+ "role": {
436
+ "type": "string",
437
+ "enum": [
438
+ "active-camera",
439
+ "three-quarter",
440
+ "top",
441
+ "detail"
442
+ ],
443
+ "description": "What this camera is FOR in a multi-view preview. The view plan assigns roles by this field; without it a camera has no role and the plan can only fall back to camera id order, which is not an author statement about anything."
444
+ },
445
+ "lens": {
446
+ "$ref": "#/$defs/positiveNumber"
447
+ },
448
+ "sensorWidth": {
449
+ "$ref": "#/$defs/positiveNumber"
450
+ },
451
+ "clipping": {
452
+ "type": "array",
453
+ "minItems": 2,
454
+ "maxItems": 2,
455
+ "items": {
456
+ "$ref": "#/$defs/positiveNumber"
457
+ }
458
+ },
459
+ "transform": {
460
+ "type": "object",
461
+ "additionalProperties": false,
462
+ "properties": {
463
+ "location": {
464
+ "$ref": "#/$defs/vec3"
465
+ },
466
+ "rotationEuler": {
467
+ "$ref": "#/$defs/vec3"
468
+ },
469
+ "scale": {
470
+ "$ref": "#/$defs/vec3"
471
+ }
472
+ }
473
+ },
474
+ "targetEntityId": {
475
+ "type": "string"
476
+ },
477
+ "targetPoint": {
478
+ "$ref": "#/$defs/vec3"
479
+ },
480
+ "fStop": {
481
+ "$ref": "#/$defs/positiveNumber"
482
+ }
483
+ }
484
+ },
485
+ "animationTrack": {
486
+ "type": "object",
487
+ "additionalProperties": false,
488
+ "required": [
489
+ "id",
490
+ "targetEntityId",
491
+ "property",
492
+ "keyframes"
493
+ ],
494
+ "properties": {
495
+ "id": {
496
+ "$ref": "#/$defs/id"
497
+ },
498
+ "targetKind": {
499
+ "type": "string",
500
+ "enum": [
501
+ "entity",
502
+ "camera",
503
+ "material"
504
+ ],
505
+ "default": "entity",
506
+ "description": "What `targetEntityId` names: an entity (default), a camera, or a material. Only entity tracks existed before, which is why \"the camera orbits the product\" and \"the dial lights up\" both had to be faked with entity transforms."
507
+ },
508
+ "targetEntityId": {
509
+ "type": "string",
510
+ "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."
511
+ },
512
+ "property": {
513
+ "type": "string",
514
+ "enum": [
515
+ "location.x",
516
+ "location.y",
517
+ "location.z",
518
+ "rotationEuler.x",
519
+ "rotationEuler.y",
520
+ "rotationEuler.z",
521
+ "scale.x",
522
+ "scale.y",
523
+ "scale.z",
524
+ "emissionStrength",
525
+ "roughness",
526
+ "metallic",
527
+ "ior",
528
+ "alpha",
529
+ "coatWeight",
530
+ "transmissionWeight",
531
+ "baseColor.r",
532
+ "baseColor.g",
533
+ "baseColor.b",
534
+ "emissionColor.r",
535
+ "emissionColor.g",
536
+ "emissionColor.b"
537
+ ],
538
+ "description": "The channel to animate. Transform channels apply to entities and cameras; material parameters apply to materials and use the same names `material.parameter.update` takes."
539
+ },
540
+ "keyframes": {
541
+ "type": "array",
542
+ "minItems": 2,
543
+ "items": {
544
+ "type": "object",
545
+ "additionalProperties": false,
546
+ "required": [
547
+ "frame",
548
+ "value"
549
+ ],
550
+ "properties": {
551
+ "frame": {
552
+ "type": "integer",
553
+ "minimum": 0
554
+ },
555
+ "value": {
556
+ "type": "number"
557
+ },
558
+ "interpolation": {
559
+ "type": "string",
560
+ "enum": [
561
+ "constant",
562
+ "linear",
563
+ "bezier",
564
+ "ease_in",
565
+ "ease_out",
566
+ "ease_in_out"
567
+ ]
568
+ }
569
+ }
570
+ }
571
+ }
572
+ }
573
+ },
574
+ "renderProfile": {
575
+ "type": "object",
576
+ "additionalProperties": false,
577
+ "properties": {
578
+ "engine": {
579
+ "type": "string",
580
+ "enum": [
581
+ "eevee",
582
+ "cycles",
583
+ "workbench"
584
+ ]
585
+ },
586
+ "resolution": {
587
+ "type": "array",
588
+ "minItems": 2,
589
+ "maxItems": 2,
590
+ "items": {
591
+ "type": "integer",
592
+ "minimum": 16,
593
+ "maximum": 16384
594
+ }
595
+ },
596
+ "samples": {
597
+ "type": "integer",
598
+ "minimum": 1,
599
+ "maximum": 8192
600
+ },
601
+ "filmTransparent": {
602
+ "type": "boolean"
603
+ },
604
+ "colorManagement": {
605
+ "type": "object",
606
+ "additionalProperties": false,
607
+ "properties": {
608
+ "viewTransform": {
609
+ "type": "string",
610
+ "enum": [
611
+ "Standard",
612
+ "AgX",
613
+ "Filmic",
614
+ "False Color",
615
+ "Raw"
616
+ ]
617
+ },
618
+ "look": {
619
+ "type": "string"
620
+ },
621
+ "exposure": {
622
+ "type": "number",
623
+ "minimum": -10,
624
+ "maximum": 10
625
+ }
626
+ }
627
+ },
628
+ "maxSamplesBudget": {
629
+ "type": "integer",
630
+ "minimum": 1
631
+ },
632
+ "raytracing": {
633
+ "type": "boolean"
634
+ }
635
+ }
636
+ },
637
+ "operation": {
638
+ "title": "ScenePatch operation",
639
+ "oneOf": [
640
+ {
641
+ "type": "object",
642
+ "additionalProperties": false,
643
+ "required": [
644
+ "op",
645
+ "entityId"
646
+ ],
647
+ "properties": {
648
+ "op": {
649
+ "type": "string",
650
+ "const": "entity.transform.update"
651
+ },
652
+ "entityId": {
653
+ "$ref": "#/$defs/id"
654
+ },
655
+ "location": {
656
+ "$ref": "#/$defs/vec3"
657
+ },
658
+ "rotationEuler": {
659
+ "$ref": "#/$defs/vec3"
660
+ },
661
+ "scale": {
662
+ "$ref": "#/$defs/vec3"
663
+ }
664
+ }
665
+ },
666
+ {
667
+ "type": "object",
668
+ "additionalProperties": false,
669
+ "required": [
670
+ "op",
671
+ "entityId",
672
+ "visible"
673
+ ],
674
+ "properties": {
675
+ "op": {
676
+ "type": "string",
677
+ "const": "entity.visibility.set"
678
+ },
679
+ "entityId": {
680
+ "$ref": "#/$defs/id"
681
+ },
682
+ "visible": {
683
+ "type": "boolean"
684
+ }
685
+ }
686
+ },
687
+ {
688
+ "type": "object",
689
+ "additionalProperties": false,
690
+ "required": [
691
+ "op",
692
+ "entityId",
693
+ "tags"
694
+ ],
695
+ "properties": {
696
+ "op": {
697
+ "type": "string",
698
+ "const": "entity.tags.set"
699
+ },
700
+ "entityId": {
701
+ "$ref": "#/$defs/id"
702
+ },
703
+ "tags": {
704
+ "type": "array",
705
+ "items": {
706
+ "type": "string",
707
+ "maxLength": 64
708
+ },
709
+ "description": "The entity's complete tag list, replacing whatever it had. Tags are how a scene states intent that geometry cannot: \"environment\" excludes backdrop from occlusion tracking, \"hero-product\" marks the subject, and \"subject-part\" says this entity is part of the subject's own body rather than something standing in front of it. An empty array removes the tags key entirely."
710
+ }
711
+ }
712
+ },
713
+ {
714
+ "type": "object",
715
+ "additionalProperties": false,
716
+ "required": [
717
+ "op",
718
+ "entity"
719
+ ],
720
+ "properties": {
721
+ "op": {
722
+ "type": "string",
723
+ "const": "entity.add"
724
+ },
725
+ "entity": {
726
+ "$ref": "#/$defs/entity"
727
+ }
728
+ }
729
+ },
730
+ {
731
+ "type": "object",
732
+ "additionalProperties": false,
733
+ "required": [
734
+ "op",
735
+ "entityId"
736
+ ],
737
+ "properties": {
738
+ "op": {
739
+ "type": "string",
740
+ "const": "entity.remove"
741
+ },
742
+ "entityId": {
743
+ "$ref": "#/$defs/id"
744
+ }
745
+ }
746
+ },
747
+ {
748
+ "type": "object",
749
+ "additionalProperties": false,
750
+ "required": [
751
+ "op",
752
+ "entityId",
753
+ "materialId"
754
+ ],
755
+ "properties": {
756
+ "op": {
757
+ "type": "string",
758
+ "const": "entity.material.set"
759
+ },
760
+ "entityId": {
761
+ "$ref": "#/$defs/id"
762
+ },
763
+ "materialId": {
764
+ "type": [
765
+ "string",
766
+ "null"
767
+ ]
768
+ }
769
+ }
770
+ },
771
+ {
772
+ "type": "object",
773
+ "additionalProperties": false,
774
+ "required": [
775
+ "op",
776
+ "materialId",
777
+ "texture"
778
+ ],
779
+ "properties": {
780
+ "op": {
781
+ "type": "string",
782
+ "const": "material.texture.set"
783
+ },
784
+ "materialId": {
785
+ "$ref": "#/$defs/id"
786
+ },
787
+ "texture": {
788
+ "oneOf": [
789
+ {
790
+ "$ref": "#/$defs/proceduralTexture"
791
+ },
792
+ {
793
+ "type": "null"
794
+ }
795
+ ]
796
+ }
797
+ }
798
+ },
799
+ {
800
+ "type": "object",
801
+ "additionalProperties": false,
802
+ "required": [
803
+ "op",
804
+ "material"
805
+ ],
806
+ "properties": {
807
+ "op": {
808
+ "type": "string",
809
+ "const": "material.add"
810
+ },
811
+ "material": {
812
+ "type": "object",
813
+ "additionalProperties": false,
814
+ "required": [
815
+ "id",
816
+ "shader"
817
+ ],
818
+ "properties": {
819
+ "id": {
820
+ "$ref": "#/$defs/id"
821
+ },
822
+ "shader": {
823
+ "type": "string",
824
+ "enum": [
825
+ "principled",
826
+ "emission",
827
+ "glass"
828
+ ]
829
+ },
830
+ "parameters": {
831
+ "$ref": "#/$defs/materialParameters"
832
+ },
833
+ "texture": {
834
+ "$ref": "#/$defs/proceduralTexture"
835
+ }
836
+ }
837
+ }
838
+ }
839
+ },
840
+ {
841
+ "type": "object",
842
+ "additionalProperties": false,
843
+ "required": [
844
+ "op",
845
+ "materialId",
846
+ "parameter",
847
+ "value"
848
+ ],
849
+ "properties": {
850
+ "op": {
851
+ "type": "string",
852
+ "const": "material.parameter.update"
853
+ },
854
+ "materialId": {
855
+ "$ref": "#/$defs/id"
856
+ },
857
+ "parameter": {
858
+ "type": "string",
859
+ "enum": [
860
+ "baseColor",
861
+ "metallic",
862
+ "roughness",
863
+ "ior",
864
+ "alpha",
865
+ "emissionColor",
866
+ "emissionStrength",
867
+ "coatWeight",
868
+ "transmissionWeight"
869
+ ]
870
+ },
871
+ "value": {
872
+ "oneOf": [
873
+ {
874
+ "type": "number"
875
+ },
876
+ {
877
+ "$ref": "#/$defs/unitColor"
878
+ }
879
+ ]
880
+ }
881
+ }
882
+ },
883
+ {
884
+ "type": "object",
885
+ "additionalProperties": false,
886
+ "required": [
887
+ "op",
888
+ "light"
889
+ ],
890
+ "properties": {
891
+ "op": {
892
+ "type": "string",
893
+ "const": "light.add"
894
+ },
895
+ "light": {
896
+ "$ref": "#/$defs/light"
897
+ }
898
+ }
899
+ },
900
+ {
901
+ "type": "object",
902
+ "additionalProperties": false,
903
+ "required": [
904
+ "op",
905
+ "lightId"
906
+ ],
907
+ "properties": {
908
+ "op": {
909
+ "type": "string",
910
+ "const": "light.update"
911
+ },
912
+ "lightId": {
913
+ "$ref": "#/$defs/id"
914
+ },
915
+ "transform": {
916
+ "type": "object",
917
+ "additionalProperties": false,
918
+ "properties": {
919
+ "location": {
920
+ "$ref": "#/$defs/vec3"
921
+ },
922
+ "rotationEuler": {
923
+ "$ref": "#/$defs/vec3"
924
+ },
925
+ "scale": {
926
+ "$ref": "#/$defs/vec3"
927
+ }
928
+ }
929
+ },
930
+ "energy": {
931
+ "$ref": "#/$defs/nonNegativeNumber"
932
+ },
933
+ "color": {
934
+ "$ref": "#/$defs/unitColor"
935
+ },
936
+ "size": {
937
+ "$ref": "#/$defs/positiveNumber"
938
+ },
939
+ "spotSize": {
940
+ "type": "number",
941
+ "exclusiveMinimum": 0,
942
+ "maximum": 3.14159265358979
943
+ },
944
+ "spotBlend": {
945
+ "type": "number",
946
+ "minimum": 0,
947
+ "maximum": 1
948
+ },
949
+ "angle": {
950
+ "type": "number",
951
+ "exclusiveMinimum": 0,
952
+ "maximum": 3.14159265358979
953
+ }
954
+ }
955
+ },
956
+ {
957
+ "type": "object",
958
+ "additionalProperties": false,
959
+ "required": [
960
+ "op",
961
+ "lightId"
962
+ ],
963
+ "properties": {
964
+ "op": {
965
+ "type": "string",
966
+ "const": "light.remove"
967
+ },
968
+ "lightId": {
969
+ "$ref": "#/$defs/id"
970
+ }
971
+ }
972
+ },
973
+ {
974
+ "type": "object",
975
+ "additionalProperties": false,
976
+ "required": [
977
+ "op",
978
+ "camera"
979
+ ],
980
+ "properties": {
981
+ "op": {
982
+ "type": "string",
983
+ "const": "camera.add"
984
+ },
985
+ "camera": {
986
+ "$ref": "#/$defs/camera"
987
+ }
988
+ }
989
+ },
990
+ {
991
+ "type": "object",
992
+ "additionalProperties": false,
993
+ "required": [
994
+ "op",
995
+ "cameraId"
996
+ ],
997
+ "properties": {
998
+ "op": {
999
+ "type": "string",
1000
+ "const": "camera.update"
1001
+ },
1002
+ "cameraId": {
1003
+ "$ref": "#/$defs/id"
1004
+ },
1005
+ "role": {
1006
+ "type": "string",
1007
+ "enum": [
1008
+ "active-camera",
1009
+ "three-quarter",
1010
+ "top",
1011
+ "detail"
1012
+ ],
1013
+ "description": "What this camera is FOR in a multi-view preview (see the scene-spec schema)."
1014
+ },
1015
+ "lens": {
1016
+ "$ref": "#/$defs/positiveNumber"
1017
+ },
1018
+ "sensorWidth": {
1019
+ "$ref": "#/$defs/positiveNumber"
1020
+ },
1021
+ "clipping": {
1022
+ "type": "array",
1023
+ "minItems": 2,
1024
+ "maxItems": 2,
1025
+ "items": {
1026
+ "$ref": "#/$defs/positiveNumber"
1027
+ }
1028
+ },
1029
+ "transform": {
1030
+ "type": "object",
1031
+ "additionalProperties": false,
1032
+ "properties": {
1033
+ "location": {
1034
+ "$ref": "#/$defs/vec3"
1035
+ },
1036
+ "rotationEuler": {
1037
+ "$ref": "#/$defs/vec3"
1038
+ },
1039
+ "scale": {
1040
+ "$ref": "#/$defs/vec3"
1041
+ }
1042
+ }
1043
+ },
1044
+ "targetEntityId": {
1045
+ "type": "string"
1046
+ },
1047
+ "targetPoint": {
1048
+ "$ref": "#/$defs/vec3"
1049
+ },
1050
+ "fStop": {
1051
+ "$ref": "#/$defs/positiveNumber"
1052
+ }
1053
+ }
1054
+ },
1055
+ {
1056
+ "type": "object",
1057
+ "additionalProperties": false,
1058
+ "required": [
1059
+ "op",
1060
+ "cameraId"
1061
+ ],
1062
+ "properties": {
1063
+ "op": {
1064
+ "type": "string",
1065
+ "const": "camera.remove"
1066
+ },
1067
+ "cameraId": {
1068
+ "$ref": "#/$defs/id"
1069
+ }
1070
+ }
1071
+ },
1072
+ {
1073
+ "type": "object",
1074
+ "additionalProperties": false,
1075
+ "required": [
1076
+ "op",
1077
+ "track"
1078
+ ],
1079
+ "properties": {
1080
+ "op": {
1081
+ "type": "string",
1082
+ "const": "animation.track.set"
1083
+ },
1084
+ "track": {
1085
+ "$ref": "#/$defs/animationTrack"
1086
+ }
1087
+ }
1088
+ },
1089
+ {
1090
+ "type": "object",
1091
+ "additionalProperties": false,
1092
+ "required": [
1093
+ "op",
1094
+ "trackId"
1095
+ ],
1096
+ "properties": {
1097
+ "op": {
1098
+ "type": "string",
1099
+ "const": "animation.track.remove"
1100
+ },
1101
+ "trackId": {
1102
+ "$ref": "#/$defs/id"
1103
+ }
1104
+ }
1105
+ },
1106
+ {
1107
+ "type": "object",
1108
+ "additionalProperties": false,
1109
+ "required": [
1110
+ "op",
1111
+ "shot"
1112
+ ],
1113
+ "properties": {
1114
+ "op": {
1115
+ "type": "string",
1116
+ "const": "shot.set"
1117
+ },
1118
+ "shot": {
1119
+ "type": "object",
1120
+ "additionalProperties": false,
1121
+ "required": [
1122
+ "id",
1123
+ "cameraId"
1124
+ ],
1125
+ "properties": {
1126
+ "id": {
1127
+ "$ref": "#/$defs/id"
1128
+ },
1129
+ "cameraId": {
1130
+ "type": "string"
1131
+ },
1132
+ "frameRange": {
1133
+ "type": "array",
1134
+ "minItems": 2,
1135
+ "maxItems": 2,
1136
+ "items": {
1137
+ "type": "integer",
1138
+ "minimum": 0
1139
+ }
1140
+ },
1141
+ "description": {
1142
+ "type": "string",
1143
+ "maxLength": 1000
1144
+ }
1145
+ }
1146
+ }
1147
+ }
1148
+ },
1149
+ {
1150
+ "type": "object",
1151
+ "additionalProperties": false,
1152
+ "required": [
1153
+ "op",
1154
+ "shotId"
1155
+ ],
1156
+ "properties": {
1157
+ "op": {
1158
+ "type": "string",
1159
+ "const": "shot.remove"
1160
+ },
1161
+ "shotId": {
1162
+ "$ref": "#/$defs/id"
1163
+ }
1164
+ }
1165
+ },
1166
+ {
1167
+ "type": "object",
1168
+ "additionalProperties": false,
1169
+ "required": [
1170
+ "op",
1171
+ "frameStart",
1172
+ "frameEnd"
1173
+ ],
1174
+ "properties": {
1175
+ "op": {
1176
+ "type": "string",
1177
+ "const": "project.frameRange.set"
1178
+ },
1179
+ "frameStart": {
1180
+ "type": "integer",
1181
+ "minimum": 0
1182
+ },
1183
+ "frameEnd": {
1184
+ "type": "integer",
1185
+ "minimum": 1
1186
+ },
1187
+ "fps": {
1188
+ "type": "number",
1189
+ "exclusiveMinimum": 0,
1190
+ "maximum": 240
1191
+ }
1192
+ }
1193
+ },
1194
+ {
1195
+ "type": "object",
1196
+ "additionalProperties": false,
1197
+ "required": [
1198
+ "op",
1199
+ "profileName",
1200
+ "profile"
1201
+ ],
1202
+ "properties": {
1203
+ "op": {
1204
+ "type": "string",
1205
+ "const": "render.profile.set"
1206
+ },
1207
+ "profileName": {
1208
+ "type": "string",
1209
+ "enum": [
1210
+ "preview",
1211
+ "final"
1212
+ ]
1213
+ },
1214
+ "profile": {
1215
+ "$ref": "#/$defs/renderProfile"
1216
+ }
1217
+ }
1218
+ },
1219
+ {
1220
+ "type": "object",
1221
+ "additionalProperties": false,
1222
+ "required": [
1223
+ "op",
1224
+ "world"
1225
+ ],
1226
+ "properties": {
1227
+ "op": {
1228
+ "type": "string",
1229
+ "const": "world.set"
1230
+ },
1231
+ "world": {
1232
+ "$ref": "#/$defs/world"
1233
+ }
1234
+ }
1235
+ },
1236
+ {
1237
+ "type": "object",
1238
+ "additionalProperties": false,
1239
+ "required": [
1240
+ "op",
1241
+ "asset"
1242
+ ],
1243
+ "properties": {
1244
+ "op": {
1245
+ "type": "string",
1246
+ "const": "asset.add"
1247
+ },
1248
+ "asset": {
1249
+ "type": "object",
1250
+ "additionalProperties": false,
1251
+ "required": [
1252
+ "id",
1253
+ "type",
1254
+ "path"
1255
+ ],
1256
+ "properties": {
1257
+ "id": {
1258
+ "$ref": "#/$defs/id"
1259
+ },
1260
+ "type": {
1261
+ "type": "string",
1262
+ "enum": [
1263
+ "glb",
1264
+ "gltf",
1265
+ "fbx",
1266
+ "obj",
1267
+ "usd",
1268
+ "blend"
1269
+ ]
1270
+ },
1271
+ "path": {
1272
+ "type": "string",
1273
+ "minLength": 1,
1274
+ "description": "Project-relative POSIX path, exactly as blender_asset_ingest reports it. Absolute paths and any \"..\" segment are rejected by the path guard (SPEC §15.2)."
1275
+ },
1276
+ "sha256": {
1277
+ "type": "string",
1278
+ "pattern": "^[a-f0-9]{64}$"
1279
+ },
1280
+ "license": {
1281
+ "$ref": "#/$defs/license"
1282
+ }
1283
+ }
1284
+ }
1285
+ }
1286
+ },
1287
+ {
1288
+ "type": "object",
1289
+ "additionalProperties": false,
1290
+ "required": [
1291
+ "op",
1292
+ "assetId"
1293
+ ],
1294
+ "properties": {
1295
+ "op": {
1296
+ "type": "string",
1297
+ "const": "asset.remove"
1298
+ },
1299
+ "assetId": {
1300
+ "$ref": "#/$defs/id"
1301
+ }
1302
+ }
1303
+ }
1304
+ ]
1305
+ }
1306
+ }
1307
+ }