@deepblend/dsh-blender-contracts 0.3.8 → 0.4.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.
@@ -155,11 +155,12 @@ export function validateScenePatch(patch) {
155
155
  message: `camera.update must supply at least one field to change: ${CAMERA_UPDATE_FIELDS.join(', ')}`,
156
156
  })
157
157
  }
158
- if (operation.targetEntityId !== undefined && operation.targetPoint !== undefined) {
158
+ if ((operation.targetEntityId !== undefined && operation.targetPoint !== undefined)
159
+ || (operation.clearTarget === true && (operation.targetEntityId !== undefined || operation.targetPoint !== undefined))) {
159
160
  errors.push({
160
161
  code: 'PATCH_CAMERA_TARGET_AMBIGUOUS',
161
162
  path: at,
162
- message: 'camera.update must set either targetEntityId or targetPoint, not both',
163
+ message: 'camera.update must choose one of targetEntityId, targetPoint or clearTarget',
163
164
  })
164
165
  }
165
166
  }
@@ -191,7 +192,7 @@ export function validateScenePatch(patch) {
191
192
  * not a crash — it is a rejection that names the wrong problem.
192
193
  */
193
194
  export const CAMERA_UPDATE_FIELDS = Object.freeze([
194
- 'lens', 'sensorWidth', 'clipping', 'transform', 'targetEntityId', 'targetPoint', 'fStop', 'role',
195
+ 'lens', 'sensorWidth', 'clipping', 'transform', 'targetEntityId', 'targetPoint', 'clearTarget', 'fStop', 'role',
195
196
  ])
196
197
 
197
198
  /** Build an anchored error for a failed operation. */
@@ -719,7 +720,7 @@ export function applyPatchToSpec(spec, patch) {
719
720
  fail('PATCH_REFERENCE_MISSING', `camera "${operation.cameraId}" targets entity "${operation.targetEntityId}", which does not exist`)
720
721
  }
721
722
  const camera = next.cameras[at]
722
- const { op: _op, cameraId: _cameraId, transform, ...scalars } = operation
723
+ const { op: _op, cameraId: _cameraId, clearTarget, transform, ...scalars } = operation
723
724
  /** @type {Record<string, unknown>} */
724
725
  const patchFields = {}
725
726
  for (const [key, value] of Object.entries(scalars)) {
@@ -745,7 +746,8 @@ export function applyPatchToSpec(spec, patch) {
745
746
  const clearedAim = operation.targetEntityId !== undefined
746
747
  ? 'targetPoint'
747
748
  : operation.targetPoint !== undefined ? 'targetEntityId' : null
748
- const mergedAim = clearedAim === null ? camera : withoutKey(camera, clearedAim)
749
+ const mergedAim = clearTarget === true ? withoutKey(withoutKey(camera, 'targetEntityId'), 'targetPoint')
750
+ : clearedAim === null ? camera : withoutKey(camera, clearedAim)
749
751
  next.cameras = [...next.cameras]
750
752
  next.cameras[at] = { ...mergedAim, ...patchFields }
751
753
  applied.push({
@@ -755,7 +757,8 @@ export function applyPatchToSpec(spec, patch) {
755
757
  (clearedAim === null ? '' : `, cleared ${clearedAim}`),
756
758
  changedPaths: [
757
759
  ...Object.keys(patchFields).map(key => `cameras.${camera.id}.${key}`),
758
- ...clearedAim === null ? [] : [`cameras.${camera.id}.${clearedAim}`],
760
+ ...clearTarget === true ? ['targetEntityId', 'targetPoint'].filter(key => camera[key] !== undefined).map(key => `cameras.${camera.id}.${key}`)
761
+ : clearedAim === null ? [] : [`cameras.${camera.id}.${clearedAim}`],
759
762
  ],
760
763
  })
761
764
  break
@@ -42,7 +42,7 @@ export namespace SceneSpecSchema {
42
42
  }
43
43
  export type SceneSpec = SceneSpecSchema.Document;
44
44
 
45
- /** Source SHA-256: e71dceb0a4aa93c664dbb8d894a1ffb156f4db13bc34ae4f0fdb2b10db386c06 */
45
+ /** Source SHA-256: bb1e7ee67ba552fff1a14e9eb87fae015ccd40d3c13cd21982e8a2b1674a019e */
46
46
  export namespace ScenePatchSchema {
47
47
  export type Id = string;
48
48
  export type License = { "source"?: string; "commercialUse"?: boolean; "attribution"?: string; };
@@ -60,7 +60,7 @@ export namespace ScenePatchSchema {
60
60
  export type Camera = { "id": ScenePatchSchema.Id; "role"?: "active-camera" | "three-quarter" | "top" | "detail"; "lens"?: ScenePatchSchema.PositiveNumber; "sensorWidth"?: ScenePatchSchema.PositiveNumber; "clipping"?: [ScenePatchSchema.PositiveNumber, ScenePatchSchema.PositiveNumber]; "transform"?: { "location"?: ScenePatchSchema.Vec3; "rotationEuler"?: ScenePatchSchema.Vec3; "scale"?: ScenePatchSchema.Vec3; }; "targetEntityId"?: string; "targetPoint"?: ScenePatchSchema.Vec3; "fStop"?: ScenePatchSchema.PositiveNumber; };
61
61
  export type AnimationTrack = { "id": ScenePatchSchema.Id; "targetKind"?: "entity" | "camera" | "material"; "targetEntityId": string; "property": "location.x" | "location.y" | "location.z" | "rotationEuler.x" | "rotationEuler.y" | "rotationEuler.z" | "scale.x" | "scale.y" | "scale.z" | "emissionStrength" | "roughness" | "metallic" | "ior" | "alpha" | "coatWeight" | "transmissionWeight" | "baseColor.r" | "baseColor.g" | "baseColor.b" | "emissionColor.r" | "emissionColor.g" | "emissionColor.b" | "anisotropic" | "anisotropicRotation"; "keyframes": Array<{ "frame": number; "value": number; "interpolation"?: "constant" | "linear" | "bezier" | "ease_in" | "ease_out" | "ease_in_out"; }>; };
62
62
  export type RenderProfile = { "engine"?: "eevee" | "cycles" | "workbench"; "resolution"?: [number, number]; "samples"?: number; "filmTransparent"?: boolean; "colorManagement"?: { "viewTransform"?: "Standard" | "AgX" | "Filmic" | "False Color" | "Raw"; "look"?: string; "exposure"?: number; }; "maxSamplesBudget"?: number; "raytracing"?: boolean; };
63
- export type Operation = ({ "op": "entity.transform.update"; "entityId": ScenePatchSchema.Id; "location"?: ScenePatchSchema.Vec3; "rotationEuler"?: ScenePatchSchema.Vec3; "scale"?: ScenePatchSchema.Vec3; }) | ({ "op": "entity.visibility.set"; "entityId": ScenePatchSchema.Id; "visible": boolean; }) | ({ "op": "entity.tags.set"; "entityId": ScenePatchSchema.Id; "tags": Array<string>; }) | ({ "op": "entity.add"; "entity": ScenePatchSchema.Entity; }) | ({ "op": "entity.remove"; "entityId": ScenePatchSchema.Id; }) | ({ "op": "entity.material.set"; "entityId": ScenePatchSchema.Id; "materialId": string | null; }) | ({ "op": "material.texture.set"; "materialId": ScenePatchSchema.Id; "texture": (ScenePatchSchema.ProceduralTexture) | (null); }) | ({ "op": "material.add"; "material": { "id": ScenePatchSchema.Id; "shader": "principled" | "emission" | "glass"; "parameters"?: ScenePatchSchema.MaterialParameters; "texture"?: ScenePatchSchema.ProceduralTexture; "images"?: ScenePatchSchema.MaterialImages; "tangent"?: ScenePatchSchema.MaterialTangent; }; }) | ({ "op": "material.parameter.update"; "materialId": ScenePatchSchema.Id; "parameter": "baseColor" | "metallic" | "roughness" | "ior" | "alpha" | "emissionColor" | "emissionStrength" | "coatWeight" | "transmissionWeight" | "anisotropic" | "anisotropicRotation"; "value": (number) | (ScenePatchSchema.UnitColor); }) | ({ "op": "light.add"; "light": ScenePatchSchema.Light; }) | ({ "op": "light.update"; "lightId": ScenePatchSchema.Id; "transform"?: { "location"?: ScenePatchSchema.Vec3; "rotationEuler"?: ScenePatchSchema.Vec3; "scale"?: ScenePatchSchema.Vec3; }; "energy"?: ScenePatchSchema.NonNegativeNumber; "color"?: ScenePatchSchema.UnitColor; "size"?: ScenePatchSchema.PositiveNumber; "spotSize"?: number; "spotBlend"?: number; "angle"?: number; }) | ({ "op": "light.remove"; "lightId": ScenePatchSchema.Id; }) | ({ "op": "camera.add"; "camera": ScenePatchSchema.Camera; }) | ({ "op": "camera.update"; "cameraId": ScenePatchSchema.Id; "role"?: "active-camera" | "three-quarter" | "top" | "detail"; "lens"?: ScenePatchSchema.PositiveNumber; "sensorWidth"?: ScenePatchSchema.PositiveNumber; "clipping"?: [ScenePatchSchema.PositiveNumber, ScenePatchSchema.PositiveNumber]; "transform"?: { "location"?: ScenePatchSchema.Vec3; "rotationEuler"?: ScenePatchSchema.Vec3; "scale"?: ScenePatchSchema.Vec3; }; "targetEntityId"?: string; "targetPoint"?: ScenePatchSchema.Vec3; "fStop"?: ScenePatchSchema.PositiveNumber; }) | ({ "op": "camera.remove"; "cameraId": ScenePatchSchema.Id; }) | ({ "op": "animation.track.set"; "track": ScenePatchSchema.AnimationTrack; }) | ({ "op": "animation.track.remove"; "trackId": ScenePatchSchema.Id; }) | ({ "op": "shot.set"; "shot": { "id": ScenePatchSchema.Id; "cameraId": string; "frameRange"?: [number, number]; "description"?: string; }; }) | ({ "op": "shot.remove"; "shotId": ScenePatchSchema.Id; }) | ({ "op": "project.frameRange.set"; "frameStart": number; "frameEnd": number; "fps"?: number; }) | ({ "op": "render.profile.set"; "profileName": "preview" | "final"; "profile": ScenePatchSchema.RenderProfile; }) | ({ "op": "world.set"; "world": ScenePatchSchema.World; }) | ({ "op": "asset.add"; "asset": { "id": ScenePatchSchema.Id; "type": "glb" | "gltf" | "fbx" | "obj" | "usd" | "blend" | "png" | "jpg" | "jpeg" | "hdr" | "exr"; "path": string; "sha256"?: string; "license"?: ScenePatchSchema.License; }; }) | ({ "op": "asset.remove"; "assetId": ScenePatchSchema.Id; }) | ({ "op": "entity.generator.set"; "entityId": ScenePatchSchema.Id; "generator": ScenePatchSchema.Generator; }) | ({ "op": "entity.modifiers.set"; "entityId": ScenePatchSchema.Id; "modifiers": Array<ScenePatchSchema.ModelModifier>; }) | ({ "op": "material.images.set"; "materialId": ScenePatchSchema.Id; "images": (ScenePatchSchema.MaterialImages) | (null); }) | ({ "op": "entity.materialBindings.set"; "entityId": ScenePatchSchema.Id; "materialBindings": ScenePatchSchema.MaterialBindings; }) | ({ "op": "material.tangent.set"; "materialId": ScenePatchSchema.Id; "tangent": (ScenePatchSchema.MaterialTangent) | (null); }) | ({ "op": "project.brief.set"; "goal": string; "referenceImages": ScenePatchSchema.ReferenceImages; }) | ({ "op": "project.reviewSubject.set"; "entityId": (ScenePatchSchema.Id) | (null); });
63
+ export type Operation = ({ "op": "entity.transform.update"; "entityId": ScenePatchSchema.Id; "location"?: ScenePatchSchema.Vec3; "rotationEuler"?: ScenePatchSchema.Vec3; "scale"?: ScenePatchSchema.Vec3; }) | ({ "op": "entity.visibility.set"; "entityId": ScenePatchSchema.Id; "visible": boolean; }) | ({ "op": "entity.tags.set"; "entityId": ScenePatchSchema.Id; "tags": Array<string>; }) | ({ "op": "entity.add"; "entity": ScenePatchSchema.Entity; }) | ({ "op": "entity.remove"; "entityId": ScenePatchSchema.Id; }) | ({ "op": "entity.material.set"; "entityId": ScenePatchSchema.Id; "materialId": string | null; }) | ({ "op": "material.texture.set"; "materialId": ScenePatchSchema.Id; "texture": (ScenePatchSchema.ProceduralTexture) | (null); }) | ({ "op": "material.add"; "material": { "id": ScenePatchSchema.Id; "shader": "principled" | "emission" | "glass"; "parameters"?: ScenePatchSchema.MaterialParameters; "texture"?: ScenePatchSchema.ProceduralTexture; "images"?: ScenePatchSchema.MaterialImages; "tangent"?: ScenePatchSchema.MaterialTangent; }; }) | ({ "op": "material.parameter.update"; "materialId": ScenePatchSchema.Id; "parameter": "baseColor" | "metallic" | "roughness" | "ior" | "alpha" | "emissionColor" | "emissionStrength" | "coatWeight" | "transmissionWeight" | "anisotropic" | "anisotropicRotation"; "value": (number) | (ScenePatchSchema.UnitColor); }) | ({ "op": "light.add"; "light": ScenePatchSchema.Light; }) | ({ "op": "light.update"; "lightId": ScenePatchSchema.Id; "transform"?: { "location"?: ScenePatchSchema.Vec3; "rotationEuler"?: ScenePatchSchema.Vec3; "scale"?: ScenePatchSchema.Vec3; }; "energy"?: ScenePatchSchema.NonNegativeNumber; "color"?: ScenePatchSchema.UnitColor; "size"?: ScenePatchSchema.PositiveNumber; "spotSize"?: number; "spotBlend"?: number; "angle"?: number; }) | ({ "op": "light.remove"; "lightId": ScenePatchSchema.Id; }) | ({ "op": "camera.add"; "camera": ScenePatchSchema.Camera; }) | ({ "op": "camera.update"; "cameraId": ScenePatchSchema.Id; "role"?: "active-camera" | "three-quarter" | "top" | "detail"; "lens"?: ScenePatchSchema.PositiveNumber; "sensorWidth"?: ScenePatchSchema.PositiveNumber; "clipping"?: [ScenePatchSchema.PositiveNumber, ScenePatchSchema.PositiveNumber]; "transform"?: { "location"?: ScenePatchSchema.Vec3; "rotationEuler"?: ScenePatchSchema.Vec3; "scale"?: ScenePatchSchema.Vec3; }; "targetEntityId"?: string; "targetPoint"?: ScenePatchSchema.Vec3; "fStop"?: ScenePatchSchema.PositiveNumber; "clearTarget"?: true; }) | ({ "op": "camera.remove"; "cameraId": ScenePatchSchema.Id; }) | ({ "op": "animation.track.set"; "track": ScenePatchSchema.AnimationTrack; }) | ({ "op": "animation.track.remove"; "trackId": ScenePatchSchema.Id; }) | ({ "op": "shot.set"; "shot": { "id": ScenePatchSchema.Id; "cameraId": string; "frameRange"?: [number, number]; "description"?: string; }; }) | ({ "op": "shot.remove"; "shotId": ScenePatchSchema.Id; }) | ({ "op": "project.frameRange.set"; "frameStart": number; "frameEnd": number; "fps"?: number; }) | ({ "op": "render.profile.set"; "profileName": "preview" | "final"; "profile": ScenePatchSchema.RenderProfile; }) | ({ "op": "world.set"; "world": ScenePatchSchema.World; }) | ({ "op": "asset.add"; "asset": { "id": ScenePatchSchema.Id; "type": "glb" | "gltf" | "fbx" | "obj" | "usd" | "blend" | "png" | "jpg" | "jpeg" | "hdr" | "exr"; "path": string; "sha256"?: string; "license"?: ScenePatchSchema.License; }; }) | ({ "op": "asset.remove"; "assetId": ScenePatchSchema.Id; }) | ({ "op": "entity.generator.set"; "entityId": ScenePatchSchema.Id; "generator": ScenePatchSchema.Generator; }) | ({ "op": "entity.modifiers.set"; "entityId": ScenePatchSchema.Id; "modifiers": Array<ScenePatchSchema.ModelModifier>; }) | ({ "op": "material.images.set"; "materialId": ScenePatchSchema.Id; "images": (ScenePatchSchema.MaterialImages) | (null); }) | ({ "op": "entity.materialBindings.set"; "entityId": ScenePatchSchema.Id; "materialBindings": ScenePatchSchema.MaterialBindings; }) | ({ "op": "material.tangent.set"; "materialId": ScenePatchSchema.Id; "tangent": (ScenePatchSchema.MaterialTangent) | (null); }) | ({ "op": "project.brief.set"; "goal": string; "referenceImages": ScenePatchSchema.ReferenceImages; }) | ({ "op": "project.reviewSubject.set"; "entityId": (ScenePatchSchema.Id) | (null); });
64
64
  export type ModelModifier = ({ "type": "solidify"; "thickness": number; "offset"?: number; }) | ({ "type": "mirror"; "axis": "x" | "y" | "z"; "merge"?: boolean; }) | ({ "type": "array"; "count": number; "offset": ScenePatchSchema.Vec3; }) | ({ "type": "boolean"; "operation": "union" | "difference" | "intersect"; "targetEntityId": ScenePatchSchema.Id; }) | ({ "type": "bevel"; "width": number; "segments"?: number; "angle"?: number; "miterInner"?: "arc" | "sharp"; });
65
65
  export type ImageBinding = { "assetId": ScenePatchSchema.Id; "scale"?: ScenePatchSchema.Vec3; "offset"?: ScenePatchSchema.Vec3; "uvMap"?: string; "channel"?: "r" | "g" | "b" | "a"; "strength"?: number; };
66
66
  export type MaterialImages = { "baseColor"?: ScenePatchSchema.ImageBinding; "roughness"?: ScenePatchSchema.ImageBinding; "metallic"?: ScenePatchSchema.ImageBinding; "normal"?: ScenePatchSchema.ImageBinding; "alpha"?: ScenePatchSchema.ImageBinding; "emissionColor"?: ScenePatchSchema.ImageBinding; };
@@ -1291,6 +1291,11 @@
1291
1291
  },
1292
1292
  "fStop": {
1293
1293
  "$ref": "#/$defs/positiveNumber"
1294
+ },
1295
+ "clearTarget": {
1296
+ "type": "boolean",
1297
+ "const": true,
1298
+ "description": "Explicitly return to free rotation by removing both aim targets. Cannot accompany targetEntityId or targetPoint."
1294
1299
  }
1295
1300
  }
1296
1301
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepblend/dsh-blender-contracts",
3
- "version": "0.3.8",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "DeepBlend Studio Service Definition, protocol contracts, and stable error codes.",
6
6
  "main": "lib/index.js",