@nodetool-ai/blender-nodes 0.8.1

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.
Files changed (83) hide show
  1. package/README.md +36 -0
  2. package/blender_ops/depth.py +133 -0
  3. package/blender_ops/errors.py +46 -0
  4. package/blender_ops/exr.py +205 -0
  5. package/blender_ops/framing.py +75 -0
  6. package/blender_ops/ops/__init__.py +24 -0
  7. package/blender_ops/ops/common.py +310 -0
  8. package/blender_ops/ops/export_model.py +95 -0
  9. package/blender_ops/ops/prepare_for_engine.py +352 -0
  10. package/blender_ops/ops/render_animation.py +382 -0
  11. package/blender_ops/ops/render_image.py +41 -0
  12. package/blender_ops/ops/render_passes.py +363 -0
  13. package/blender_ops/run_job.py +110 -0
  14. package/blender_ops/tests/test_camera_lens.py +107 -0
  15. package/blender_ops/tests/test_depth.py +158 -0
  16. package/blender_ops/tests/test_exr.py +218 -0
  17. package/blender_ops/tests/test_framing.py +50 -0
  18. package/dist/.nodetool-build-stamp +1 -0
  19. package/dist/bake.d.ts +107 -0
  20. package/dist/bake.d.ts.map +1 -0
  21. package/dist/bake.js +209 -0
  22. package/dist/bake.js.map +1 -0
  23. package/dist/blender-binary.d.ts +38 -0
  24. package/dist/blender-binary.d.ts.map +1 -0
  25. package/dist/blender-binary.js +169 -0
  26. package/dist/blender-binary.js.map +1 -0
  27. package/dist/index.d.ts +31 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +40 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/job.d.ts +163 -0
  32. package/dist/job.d.ts.map +1 -0
  33. package/dist/job.js +67 -0
  34. package/dist/job.js.map +1 -0
  35. package/dist/nodes/bake-timeline-clip.d.ts +48 -0
  36. package/dist/nodes/bake-timeline-clip.d.ts.map +1 -0
  37. package/dist/nodes/bake-timeline-clip.js +152 -0
  38. package/dist/nodes/bake-timeline-clip.js.map +1 -0
  39. package/dist/nodes/blender-error.d.ts +21 -0
  40. package/dist/nodes/blender-error.d.ts.map +1 -0
  41. package/dist/nodes/blender-error.js +38 -0
  42. package/dist/nodes/blender-error.js.map +1 -0
  43. package/dist/nodes/defaults.d.ts +18 -0
  44. package/dist/nodes/defaults.d.ts.map +1 -0
  45. package/dist/nodes/defaults.js +18 -0
  46. package/dist/nodes/defaults.js.map +1 -0
  47. package/dist/nodes/export-model.d.ts +49 -0
  48. package/dist/nodes/export-model.d.ts.map +1 -0
  49. package/dist/nodes/export-model.js +127 -0
  50. package/dist/nodes/export-model.js.map +1 -0
  51. package/dist/nodes/prepare-for-engine.d.ts +52 -0
  52. package/dist/nodes/prepare-for-engine.d.ts.map +1 -0
  53. package/dist/nodes/prepare-for-engine.js +127 -0
  54. package/dist/nodes/prepare-for-engine.js.map +1 -0
  55. package/dist/nodes/progress.d.ts +11 -0
  56. package/dist/nodes/progress.d.ts.map +1 -0
  57. package/dist/nodes/progress.js +21 -0
  58. package/dist/nodes/progress.js.map +1 -0
  59. package/dist/nodes/render-animation.d.ts +52 -0
  60. package/dist/nodes/render-animation.d.ts.map +1 -0
  61. package/dist/nodes/render-animation.js +136 -0
  62. package/dist/nodes/render-animation.js.map +1 -0
  63. package/dist/nodes/render-base.d.ts +35 -0
  64. package/dist/nodes/render-base.d.ts.map +1 -0
  65. package/dist/nodes/render-base.js +95 -0
  66. package/dist/nodes/render-base.js.map +1 -0
  67. package/dist/nodes/render-image.d.ts +41 -0
  68. package/dist/nodes/render-image.d.ts.map +1 -0
  69. package/dist/nodes/render-image.js +98 -0
  70. package/dist/nodes/render-image.js.map +1 -0
  71. package/dist/nodes/render-passes.d.ts +54 -0
  72. package/dist/nodes/render-passes.d.ts.map +1 -0
  73. package/dist/nodes/render-passes.js +167 -0
  74. package/dist/nodes/render-passes.js.map +1 -0
  75. package/dist/run-job.d.ts +34 -0
  76. package/dist/run-job.d.ts.map +1 -0
  77. package/dist/run-job.js +137 -0
  78. package/dist/run-job.js.map +1 -0
  79. package/dist/runner.d.ts +124 -0
  80. package/dist/runner.d.ts.map +1 -0
  81. package/dist/runner.js +521 -0
  82. package/dist/runner.js.map +1 -0
  83. package/package.json +73 -0
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Shared props for the three Blender render nodes (`RenderImage`,
3
+ * `RenderPasses`, `RenderAnimation`).
4
+ *
5
+ * The camera, lighting, and engine block is identical across the three
6
+ * nodes, so it lives here once. Per-node wording stays on the node:
7
+ * `RenderAnimation` re-declares `camera_mode`, `width`, `height`, and
8
+ * `transparent` with its own descriptions, which override these through
9
+ * the prototype chain (`collectDeclaredProps` merges base-first, so an
10
+ * override keeps its base position and the prop order never changes).
11
+ * `timeout` also stays per node: it is last everywhere, and inheriting it
12
+ * would move it before `RenderPasses`' `passes`/`depth_format`.
13
+ */
14
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ };
20
+ import { BaseNode, prop } from "@nodetool-ai/node-sdk";
21
+ import { DEFAULT_MODEL_3D } from "./defaults.js";
22
+ export class BlenderRenderBase extends BaseNode {
23
+ }
24
+ __decorate([
25
+ prop({
26
+ type: "model_3d",
27
+ default: DEFAULT_MODEL_3D,
28
+ title: "Model",
29
+ description: "The 3D model to render (GLB or glTF with embedded buffers)"
30
+ })
31
+ ], BlenderRenderBase.prototype, "model", void 0);
32
+ __decorate([
33
+ prop({
34
+ type: "enum",
35
+ default: "auto",
36
+ title: "Camera Mode",
37
+ description: "Whose camera renders: auto (the scene's first camera when the model has one, else an orbit camera), scene (the scene's first camera; an error when the model has none), or orbit (always an orbit camera from the props below)",
38
+ values: ["auto", "scene", "orbit"]
39
+ })
40
+ ], BlenderRenderBase.prototype, "camera_mode", void 0);
41
+ __decorate([
42
+ prop({ type: "int", default: 1024, title: "Width", description: "Output image width in pixels", min: 16, max: 4096 })
43
+ ], BlenderRenderBase.prototype, "width", void 0);
44
+ __decorate([
45
+ prop({ type: "int", default: 1024, title: "Height", description: "Output image height in pixels", min: 16, max: 4096 })
46
+ ], BlenderRenderBase.prototype, "height", void 0);
47
+ __decorate([
48
+ prop({ type: "float", default: 45, title: "Azimuth", description: "Horizontal camera orbit angle in degrees (0 looks along -Z)", min: -360, max: 360 })
49
+ ], BlenderRenderBase.prototype, "azimuth", void 0);
50
+ __decorate([
51
+ prop({ type: "float", default: 25, title: "Elevation", description: "Camera angle above the horizon in degrees", min: -89, max: 89 })
52
+ ], BlenderRenderBase.prototype, "elevation", void 0);
53
+ __decorate([
54
+ prop({ type: "float", default: 35, title: "Field of View", description: "Vertical field of view in degrees", min: 5, max: 120 })
55
+ ], BlenderRenderBase.prototype, "fov", void 0);
56
+ __decorate([
57
+ prop({ type: "float", default: 1, title: "Zoom", description: "Distance multiplier on the auto-framed camera: above 1 moves closer, below 1 farther", min: 0.1, max: 10 })
58
+ ], BlenderRenderBase.prototype, "zoom", void 0);
59
+ __decorate([
60
+ prop({
61
+ type: "enum",
62
+ default: "studio",
63
+ title: "Lighting",
64
+ description: "Lighting preset used when the scene carries no lights of its own: studio (key/fill/rim), soft (hemisphere), or flat (ambient only)",
65
+ values: ["studio", "soft", "flat"]
66
+ })
67
+ ], BlenderRenderBase.prototype, "lighting", void 0);
68
+ __decorate([
69
+ prop({ type: "float", default: 1, title: "Light Intensity", description: "Multiplier applied to all lights in the preset; ignored when the scene carries its own lights", min: 0, max: 10 })
70
+ ], BlenderRenderBase.prototype, "light_intensity", void 0);
71
+ __decorate([
72
+ prop({ type: "str", default: "#808080", title: "Background Color", description: "Background color (hex); ignored when Transparent is on" })
73
+ ], BlenderRenderBase.prototype, "background_color", void 0);
74
+ __decorate([
75
+ prop({ type: "bool", default: false, title: "Transparent", description: "Render on a transparent background (PNG alpha)" })
76
+ ], BlenderRenderBase.prototype, "transparent", void 0);
77
+ __decorate([
78
+ prop({
79
+ type: "enum",
80
+ default: "eevee",
81
+ title: "Engine",
82
+ description: "Render engine: EEVEE (fast preview quality) or Cycles (slower, higher quality)",
83
+ values: ["eevee", "cycles"]
84
+ })
85
+ ], BlenderRenderBase.prototype, "engine", void 0);
86
+ __decorate([
87
+ prop({ type: "int", default: 16, title: "Samples", description: "Render samples per pixel; higher is cleaner and slower", min: 1, max: 4096 })
88
+ ], BlenderRenderBase.prototype, "samples", void 0);
89
+ __decorate([
90
+ prop({ type: "bool", default: true, title: "Denoise", description: "Denoise the render (Cycles; EEVEE ignores it)" })
91
+ ], BlenderRenderBase.prototype, "denoise", void 0);
92
+ __decorate([
93
+ prop({ type: "int", default: 100, title: "Resolution Percentage", description: "Render scale in percent of Width × Height", min: 1, max: 100 })
94
+ ], BlenderRenderBase.prototype, "resolution_percentage", void 0);
95
+ //# sourceMappingURL=render-base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-base.js","sourceRoot":"","sources":["../../src/nodes/render-base.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * `nodetool.blender.RenderImage` — glTF scene + camera → image via Blender.
3
+ *
4
+ * Stage 1b: the `render_image` op over `LocalBlenderRunner` (D8). Takes a
5
+ * `Model3DRef`, builds the versioned `BlenderJob`, and returns an inline
6
+ * image ref like `RenderToImage`, so downstream save nodes decide
7
+ * persistence. Camera props reuse the `RenderToImage` vocabulary; the
8
+ * background defaults to studio gray rather than white because a white
9
+ * model on a white background renders invisible under a standard view
10
+ * transform.
11
+ *
12
+ * Every failure rethrows with the node name prefixed. An abort through
13
+ * `context.signal` passes through unwrapped so the node rejects with the
14
+ * abort reason and no partial output.
15
+ */
16
+ import type { ProcessingContext } from "@nodetool-ai/runtime";
17
+ import { BlenderRenderBase } from "./render-base.js";
18
+ /** Output handle RenderImageNode.process() emits. */
19
+ type RenderImageNodeOutputs = {
20
+ image: {
21
+ type: string;
22
+ uri: string;
23
+ asset_id: null;
24
+ data: string;
25
+ };
26
+ };
27
+ export declare class RenderImageNode extends BlenderRenderBase {
28
+ static readonly nodeType = "nodetool.blender.RenderImage";
29
+ static readonly title = "Render 3D With Blender";
30
+ static readonly description = "Render a 3D model (GLB/glTF) to an image with Blender (EEVEE or Cycles) \u2014 higher quality than the preview renderer, with scene cameras and lights honored.\n 3d, render, image, camera, light, blender, eevee, cycles, snapshot, thumbnail\n\n Use cases:\n - Turn generated 3D models into high-quality images\n - Render a scene with its authored cameras and lights\n - Feed rendered views into image models (img2img, upscaling)";
31
+ static readonly metadataOutputTypes: {
32
+ image: string;
33
+ };
34
+ static readonly inlineFields: never[];
35
+ static readonly inputFields: string[];
36
+ timeout: number;
37
+ process(context?: ProcessingContext): Promise<RenderImageNodeOutputs>;
38
+ }
39
+ export declare const BLENDER_RENDER_NODES: readonly [typeof RenderImageNode];
40
+ export {};
41
+ //# sourceMappingURL=render-image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-image.d.ts","sourceRoot":"","sources":["../../src/nodes/render-image.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAM9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAIrD,qDAAqD;AACrD,KAAK,sBAAsB,GAAG;IAC5B,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACpE,CAAC;AAUF,qBAAa,eAAgB,SAAQ,iBAAiB;IACpD,MAAM,CAAC,QAAQ,CAAC,QAAQ,kCAAkC;IAC1D,MAAM,CAAC,QAAQ,CAAC,KAAK,4BAA4B;IACjD,MAAM,CAAC,QAAQ,CAAC,WAAW,gcAC+Z;IAC1b,MAAM,CAAC,QAAQ,CAAC,mBAAmB;QACjC,KAAK;MACL;IACF,MAAM,CAAC,QAAQ,CAAC,YAAY,UAAM;IAClC,MAAM,CAAC,QAAQ,CAAC,WAAW,WAAa;IAGhC,OAAO,EAAE,MAAM,CAAC;IAElB,OAAO,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAkE1E;CACF;AAED,eAAO,MAAM,oBAAoB,mCAA6B,CAAC"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * `nodetool.blender.RenderImage` — glTF scene + camera → image via Blender.
3
+ *
4
+ * Stage 1b: the `render_image` op over `LocalBlenderRunner` (D8). Takes a
5
+ * `Model3DRef`, builds the versioned `BlenderJob`, and returns an inline
6
+ * image ref like `RenderToImage`, so downstream save nodes decide
7
+ * persistence. Camera props reuse the `RenderToImage` vocabulary; the
8
+ * background defaults to studio gray rather than white because a white
9
+ * model on a white background renders invisible under a standard view
10
+ * transform.
11
+ *
12
+ * Every failure rethrows with the node name prefixed. An abort through
13
+ * `context.signal` passes through unwrapped so the node rejects with the
14
+ * abort reason and no partial output.
15
+ */
16
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
17
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
18
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
19
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
20
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
21
+ };
22
+ import { prop } from "@nodetool-ai/node-sdk";
23
+ import { bytesToBase64, resolveModelBytes } from "@nodetool-ai/nodes-utils";
24
+ import { BlenderJobError } from "../runner.js";
25
+ import { runBlenderJob } from "../run-job.js";
26
+ import { runBlenderNodeStep } from "./blender-error.js";
27
+ import { blenderProgressHandler } from "./progress.js";
28
+ import { BlenderRenderBase } from "./render-base.js";
29
+ const NODE_NAME = "nodetool.blender.RenderImage";
30
+ /** Blender ran past its wall clock: point at the two knobs that fix it. */
31
+ function timeoutMessage(timeoutMs) {
32
+ return (`${NODE_NAME}: Blender render timed out after ${timeoutMs}ms. ` +
33
+ `Lower the samples, use EEVEE, or raise the timeout.`);
34
+ }
35
+ export class RenderImageNode extends BlenderRenderBase {
36
+ static nodeType = "nodetool.blender.RenderImage";
37
+ static title = "Render 3D With Blender";
38
+ static description = "Render a 3D model (GLB/glTF) to an image with Blender (EEVEE or Cycles) — higher quality than the preview renderer, with scene cameras and lights honored.\n 3d, render, image, camera, light, blender, eevee, cycles, snapshot, thumbnail\n\n Use cases:\n - Turn generated 3D models into high-quality images\n - Render a scene with its authored cameras and lights\n - Feed rendered views into image models (img2img, upscaling)";
39
+ static metadataOutputTypes = {
40
+ image: "image"
41
+ };
42
+ static inlineFields = [];
43
+ static inputFields = ["model"];
44
+ async process(context) {
45
+ const bytes = await resolveModelBytes(this.model, context);
46
+ if (bytes.length === 0) {
47
+ throw new Error(`${NODE_NAME}: model input is empty — connect a 3D model (GLB)`);
48
+ }
49
+ const timeoutMs = Math.max(1, Number(this.timeout ?? 600)) * 1000;
50
+ return runBlenderNodeStep({
51
+ nodeName: NODE_NAME,
52
+ timeoutMessage: timeoutMessage(timeoutMs),
53
+ signal: context?.signal
54
+ }, async () => {
55
+ const result = await runBlenderJob(context, bytes, {
56
+ op: "render_image",
57
+ params: {
58
+ camera_mode: this.camera_mode ?? "auto",
59
+ azimuth: Number(this.azimuth ?? 45),
60
+ elevation: Number(this.elevation ?? 25),
61
+ fov: Number(this.fov ?? 35),
62
+ zoom: Number(this.zoom ?? 1),
63
+ lighting: this.lighting ?? "studio",
64
+ light_intensity: Number(this.light_intensity ?? 1),
65
+ background_color: String(this.background_color ?? "#808080"),
66
+ transparent: this.transparent === true,
67
+ engine: this.engine ?? "eevee",
68
+ samples: Math.max(1, Math.round(Number(this.samples ?? 16))),
69
+ denoise: this.denoise !== false,
70
+ resolution_percentage: Math.max(1, Math.round(Number(this.resolution_percentage ?? 100))),
71
+ width: Math.max(1, Math.round(Number(this.width ?? 1024))),
72
+ height: Math.max(1, Math.round(Number(this.height ?? 1024)))
73
+ }
74
+ }, { image: "render.png" }, {
75
+ timeoutMs,
76
+ signal: context?.signal,
77
+ onProgress: blenderProgressHandler(context, this.__node_id)
78
+ });
79
+ const png = result.outputs["image"];
80
+ if (!png || png.length === 0) {
81
+ throw new BlenderJobError("missing_output", "Blender produced no image bytes.");
82
+ }
83
+ return {
84
+ image: {
85
+ type: "image",
86
+ uri: "",
87
+ asset_id: null,
88
+ data: bytesToBase64(png)
89
+ }
90
+ };
91
+ });
92
+ }
93
+ }
94
+ __decorate([
95
+ prop({ type: "int", default: 600, title: "Timeout", description: "Maximum render time in seconds", min: 1, max: 3600 })
96
+ ], RenderImageNode.prototype, "timeout", void 0);
97
+ export const BLENDER_RENDER_NODES = [RenderImageNode];
98
+ //# sourceMappingURL=render-image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-image.js","sourceRoot":"","sources":["../../src/nodes/render-image.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * `nodetool.blender.RenderPasses` — glTF scene + camera → control passes.
3
+ *
4
+ * Stage 2: the `render_passes` op over `LocalBlenderRunner` (D8). Takes a
5
+ * `Model3DRef`, builds the versioned `BlenderJob` for the selected `passes`
6
+ * subset, and returns inline image refs like `RenderToImage`, so downstream
7
+ * save nodes decide persistence. Unselected passes come back as empty-data
8
+ * refs and `depth_near`/`depth_far` as 0. Output contracts in D4.
9
+ *
10
+ * Every failure rethrows with the node name prefixed. An abort through
11
+ * `context.signal` passes through unwrapped so the node rejects with the
12
+ * abort reason and no partial output.
13
+ */
14
+ import type { ProcessingContext } from "@nodetool-ai/runtime";
15
+ import type { DepthFormat, RenderPass } from "../job.js";
16
+ import { BlenderRenderBase } from "./render-base.js";
17
+ /** An inline `image` ref carrying PNG or EXR bytes, like `RenderToImage`'s. */
18
+ interface InlineImageRef {
19
+ type: string;
20
+ uri: string;
21
+ asset_id: null;
22
+ data: string;
23
+ }
24
+ /** Output handles RenderPassesNode.process() emits. */
25
+ type RenderPassesNodeOutputs = {
26
+ color: InlineImageRef;
27
+ depth: InlineImageRef;
28
+ depth_near: number;
29
+ depth_far: number;
30
+ normal: InlineImageRef;
31
+ mask: InlineImageRef;
32
+ };
33
+ export declare class RenderPassesNode extends BlenderRenderBase {
34
+ static readonly nodeType = "nodetool.blender.RenderPasses";
35
+ static readonly title = "Render 3D Passes With Blender";
36
+ static readonly description = "Render a 3D model (GLB/glTF) to control passes with Blender: beauty color, 16-bit or EXR depth with near/far range, camera-space normals, and a binary foreground mask.\n 3d, render, depth, normal, mask, passes, controlnet, blender, camera, light\n\n Use cases:\n - Feed video models with camera-consistent frames and control passes from the same scene\n - Read per-pixel depth with a known near/far range\n - Mask the foreground for compositing";
37
+ static readonly metadataOutputTypes: {
38
+ color: string;
39
+ depth: string;
40
+ depth_near: string;
41
+ depth_far: string;
42
+ normal: string;
43
+ mask: string;
44
+ };
45
+ static readonly inlineFields: never[];
46
+ static readonly inputFields: string[];
47
+ passes: RenderPass[];
48
+ depth_format: DepthFormat;
49
+ timeout: number;
50
+ process(context?: ProcessingContext): Promise<RenderPassesNodeOutputs>;
51
+ }
52
+ export declare const BLENDER_PASSES_NODES: readonly [typeof RenderPassesNode];
53
+ export {};
54
+ //# sourceMappingURL=render-passes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-passes.d.ts","sourceRoot":"","sources":["../../src/nodes/render-passes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAKzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAMrD,+EAA+E;AAC/E,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,IAAI,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,uDAAuD;AACvD,KAAK,uBAAuB,GAAG;IAC7B,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,EAAE,cAAc,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,cAAc,CAAC;IACvB,IAAI,EAAE,cAAc,CAAC;CACtB,CAAC;AAcF,qBAAa,gBAAiB,SAAQ,iBAAiB;IACrD,MAAM,CAAC,QAAQ,CAAC,QAAQ,mCAAmC;IAC3D,MAAM,CAAC,QAAQ,CAAC,KAAK,mCAAmC;IACxD,MAAM,CAAC,QAAQ,CAAC,WAAW,idACqb;IAChd,MAAM,CAAC,QAAQ,CAAC,mBAAmB;QACjC,KAAK;QACL,KAAK;QACL,UAAU;QACV,SAAS;QACT,MAAM;QACN,IAAI;MACJ;IACF,MAAM,CAAC,QAAQ,CAAC,YAAY,UAAM;IAClC,MAAM,CAAC,QAAQ,CAAC,WAAW,WAAa;IAShC,MAAM,EAAE,UAAU,EAAE,CAAC;IAUrB,YAAY,EAAE,WAAW,CAAC;IAG1B,OAAO,EAAE,MAAM,CAAC;IAElB,OAAO,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAkH3E;CACF;AAED,eAAO,MAAM,oBAAoB,oCAA8B,CAAC"}
@@ -0,0 +1,167 @@
1
+ /**
2
+ * `nodetool.blender.RenderPasses` — glTF scene + camera → control passes.
3
+ *
4
+ * Stage 2: the `render_passes` op over `LocalBlenderRunner` (D8). Takes a
5
+ * `Model3DRef`, builds the versioned `BlenderJob` for the selected `passes`
6
+ * subset, and returns inline image refs like `RenderToImage`, so downstream
7
+ * save nodes decide persistence. Unselected passes come back as empty-data
8
+ * refs and `depth_near`/`depth_far` as 0. Output contracts in D4.
9
+ *
10
+ * Every failure rethrows with the node name prefixed. An abort through
11
+ * `context.signal` passes through unwrapped so the node rejects with the
12
+ * abort reason and no partial output.
13
+ */
14
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ };
20
+ import { prop } from "@nodetool-ai/node-sdk";
21
+ import { bytesToBase64, resolveModelBytes } from "@nodetool-ai/nodes-utils";
22
+ import { BlenderJobError } from "../runner.js";
23
+ import { runBlenderJob } from "../run-job.js";
24
+ import { runBlenderNodeStep } from "./blender-error.js";
25
+ import { blenderProgressHandler } from "./progress.js";
26
+ import { BlenderRenderBase } from "./render-base.js";
27
+ const NODE_NAME = "nodetool.blender.RenderPasses";
28
+ const KNOWN_PASSES = ["color", "depth", "normal", "mask"];
29
+ /** Blender ran past its wall clock: point at the two knobs that fix it. */
30
+ function timeoutMessage(timeoutMs) {
31
+ return (`${NODE_NAME}: Blender passes render timed out after ${timeoutMs}ms. ` +
32
+ `Lower the samples, use EEVEE, or raise the timeout.`);
33
+ }
34
+ function emptyImageRef() {
35
+ return { type: "image", uri: "", asset_id: null, data: "" };
36
+ }
37
+ export class RenderPassesNode extends BlenderRenderBase {
38
+ static nodeType = "nodetool.blender.RenderPasses";
39
+ static title = "Render 3D Passes With Blender";
40
+ static description = "Render a 3D model (GLB/glTF) to control passes with Blender: beauty color, 16-bit or EXR depth with near/far range, camera-space normals, and a binary foreground mask.\n 3d, render, depth, normal, mask, passes, controlnet, blender, camera, light\n\n Use cases:\n - Feed video models with camera-consistent frames and control passes from the same scene\n - Read per-pixel depth with a known near/far range\n - Mask the foreground for compositing";
41
+ static metadataOutputTypes = {
42
+ color: "image",
43
+ depth: "image",
44
+ depth_near: "float",
45
+ depth_far: "float",
46
+ normal: "image",
47
+ mask: "image"
48
+ };
49
+ static inlineFields = [];
50
+ static inputFields = ["model"];
51
+ async process(context) {
52
+ const bytes = await resolveModelBytes(this.model, context);
53
+ if (bytes.length === 0) {
54
+ throw new Error(`${NODE_NAME}: model input is empty — connect a 3D model (GLB)`);
55
+ }
56
+ // A `passes` value that is not a list selects nothing, and the empty
57
+ // selection below is the refusal the user sees.
58
+ const requested = this.passes ?? KNOWN_PASSES;
59
+ const passes = Array.isArray(requested)
60
+ ? KNOWN_PASSES.filter((name) => requested.includes(name))
61
+ : [];
62
+ if (passes.length === 0) {
63
+ throw new BlenderJobError("bad_job", `${NODE_NAME}: select at least one pass (color, depth, normal, mask).`);
64
+ }
65
+ const depthFormat = this.depth_format ?? "png16";
66
+ const outputs = {};
67
+ if (passes.includes("color"))
68
+ outputs["color"] = "color.png";
69
+ if (passes.includes("depth")) {
70
+ outputs["depth"] = depthFormat === "exr" ? "depth.exr" : "depth.png";
71
+ }
72
+ if (passes.includes("normal"))
73
+ outputs["normal"] = "normal.png";
74
+ if (passes.includes("mask"))
75
+ outputs["mask"] = "mask.png";
76
+ const timeoutMs = Math.max(1, Number(this.timeout ?? 600)) * 1000;
77
+ return runBlenderNodeStep({
78
+ nodeName: NODE_NAME,
79
+ timeoutMessage: timeoutMessage(timeoutMs),
80
+ signal: context?.signal
81
+ }, async () => {
82
+ const result = await runBlenderJob(context, bytes, {
83
+ op: "render_passes",
84
+ params: {
85
+ camera_mode: this.camera_mode ?? "auto",
86
+ azimuth: Number(this.azimuth ?? 45),
87
+ elevation: Number(this.elevation ?? 25),
88
+ fov: Number(this.fov ?? 35),
89
+ zoom: Number(this.zoom ?? 1),
90
+ lighting: this.lighting ?? "studio",
91
+ light_intensity: Number(this.light_intensity ?? 1),
92
+ background_color: String(this.background_color ?? "#808080"),
93
+ transparent: this.transparent === true,
94
+ engine: this.engine ?? "eevee",
95
+ samples: Math.max(1, Math.round(Number(this.samples ?? 16))),
96
+ denoise: this.denoise !== false,
97
+ resolution_percentage: Math.max(1, Math.round(Number(this.resolution_percentage ?? 100))),
98
+ width: Math.max(1, Math.round(Number(this.width ?? 1024))),
99
+ height: Math.max(1, Math.round(Number(this.height ?? 1024))),
100
+ passes,
101
+ depth_format: depthFormat
102
+ }
103
+ }, outputs, {
104
+ timeoutMs,
105
+ signal: context?.signal,
106
+ onProgress: blenderProgressHandler(context, this.__node_id)
107
+ });
108
+ const imageOut = (name) => {
109
+ if (!passes.includes(name))
110
+ return emptyImageRef();
111
+ const raw = result.outputs[name];
112
+ if (!raw || raw.length === 0) {
113
+ throw new BlenderJobError("missing_output", `Blender produced no bytes for pass "${name}".`);
114
+ }
115
+ return {
116
+ type: "image",
117
+ uri: "",
118
+ asset_id: null,
119
+ data: bytesToBase64(raw)
120
+ };
121
+ };
122
+ let depthNear = 0;
123
+ let depthFar = 0;
124
+ if (passes.includes("depth")) {
125
+ // `blenderResultSchema` already parsed both as optional numbers,
126
+ // so absent is the only failure left to report.
127
+ const near = result.stats.depth_near;
128
+ const far = result.stats.depth_far;
129
+ if (near === undefined || far === undefined) {
130
+ throw new BlenderJobError("missing_output", "Blender produced no depth range (depth_near/depth_far).");
131
+ }
132
+ depthNear = near;
133
+ depthFar = far;
134
+ }
135
+ return {
136
+ color: imageOut("color"),
137
+ depth: imageOut("depth"),
138
+ depth_near: depthNear,
139
+ depth_far: depthFar,
140
+ normal: imageOut("normal"),
141
+ mask: imageOut("mask")
142
+ };
143
+ });
144
+ }
145
+ }
146
+ __decorate([
147
+ prop({
148
+ type: "list[str]",
149
+ default: ["color", "depth", "normal", "mask"],
150
+ title: "Passes",
151
+ description: "Passes to produce: color (beauty), depth (view-axis distance), normal (camera-space), mask (binary foreground)"
152
+ })
153
+ ], RenderPassesNode.prototype, "passes", void 0);
154
+ __decorate([
155
+ prop({
156
+ type: "enum",
157
+ default: "png16",
158
+ title: "Depth Format",
159
+ description: "Depth encoding: png16 (normalized between depth_near and depth_far, background 65535) or exr (raw float, background +inf)",
160
+ values: ["png16", "exr"]
161
+ })
162
+ ], RenderPassesNode.prototype, "depth_format", void 0);
163
+ __decorate([
164
+ prop({ type: "int", default: 600, title: "Timeout", description: "Maximum render time in seconds", min: 1, max: 3600 })
165
+ ], RenderPassesNode.prototype, "timeout", void 0);
166
+ export const BLENDER_PASSES_NODES = [RenderPassesNode];
167
+ //# sourceMappingURL=render-passes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-passes.js","sourceRoot":"","sources":["../../src/nodes/render-passes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * The thin function nodes call (D6).
3
+ *
4
+ * Validates every input and output file name with `jobFileNameSchema`,
5
+ * refuses more than `MAX_OUTPUT_COUNT` declared outputs, builds the
6
+ * `BlenderJob`, picks a runner (D7), and returns the runner's result. A node
7
+ * never touches a runner.
8
+ */
9
+ import type { ProcessingContext } from "@nodetool-ai/runtime";
10
+ import { type BlenderOp } from "./job.js";
11
+ import { type BlenderRunner, type BlenderRunOptions, type BlenderRunResult } from "./runner.js";
12
+ /** File name the model bytes are staged under. The extension selects import. */
13
+ export declare const BLENDER_MODEL_INPUT_FILE = "model.glb";
14
+ /**
15
+ * Select the local tier when Blender resolves. Otherwise, an explicitly
16
+ * configured worker is used only after its status advertises Blender.
17
+ *
18
+ * A configured worker is never silently replaced with local after a worker
19
+ * connection or capability failure: the URL is an explicit deployment choice.
20
+ */
21
+ export declare function resolveBlenderRunner(blenderPath?: string | null, options?: {
22
+ signal?: AbortSignal;
23
+ timeoutMs?: number;
24
+ }): Promise<BlenderRunner>;
25
+ /**
26
+ * Override `resolveBlenderRunner` for node tests (T6b), so every node test
27
+ * runs against a fake and proves the node never reaches past the
28
+ * `BlenderRunner` interface. Pass null to restore the local runner.
29
+ */
30
+ export declare function __setBlenderRunnerForTesting(runner: BlenderRunner | null): void;
31
+ /** Test seam for exercising D7 without depending on the host's Blender install. */
32
+ export declare function __setBlenderBinaryResolverForTesting(resolver: (() => Promise<void>) | null): void;
33
+ export declare function runBlenderJob(context: ProcessingContext | undefined, modelBytes: Uint8Array, op: BlenderOp, outputs: Record<string, string>, options: BlenderRunOptions): Promise<BlenderRunResult>;
34
+ //# sourceMappingURL=run-job.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-job.d.ts","sourceRoot":"","sources":["../src/run-job.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAI9D,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,UAAU,CAAC;AAClB,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AAErB,gFAAgF;AAChF,eAAO,MAAM,wBAAwB,cAAc,CAAC;AAEpD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,EAC3B,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACzD,OAAO,CAAC,aAAa,CAAC,CAgBxB;AAKD;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,aAAa,GAAG,IAAI,GAC3B,IAAI,CAEN;AAED,mFAAmF;AACnF,wBAAgB,oCAAoC,CAClD,QAAQ,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,GACrC,IAAI,CAEN;AAcD,wBAAsB,aAAa,CAIjC,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,UAAU,EAAE,UAAU,EACtB,EAAE,EAAE,SAAS,EACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,gBAAgB,CAAC,CAuF3B"}