@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,127 @@
1
+ /**
2
+ * `nodetool.blender.ExportModel` — glTF scene → FBX, OBJ, or USD file.
3
+ *
4
+ * Stage 3: the `export_model` op over `LocalBlenderRunner` (D8). Takes a
5
+ * `Model3DRef` and returns an `AssetRef`, never a `Model3DRef`: FBX, OBJ,
6
+ * and USD are not glTF documents, and the `model_3d` socket keeps meaning
7
+ * glTF everywhere. The node persists the export through
8
+ * `context.createAsset` and returns `{ type: "asset", uri, asset_id,
9
+ * metadata: { format, mime } }`. GLB is deliberately not a format here:
10
+ * `PrepareForEngine` and `FormatConverter` already produce a `Model3DRef`
11
+ * for it.
12
+ *
13
+ * Every failure rethrows with the node name prefixed. An abort through
14
+ * `context.signal` passes through unwrapped so the node rejects with the
15
+ * abort reason and no partial output.
16
+ */
17
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
18
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
19
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20
+ 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;
21
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
22
+ };
23
+ import { BaseNode, prop } from "@nodetool-ai/node-sdk";
24
+ import { resolveModelBytes } from "@nodetool-ai/nodes-utils";
25
+ import { isRecord, isString } from "@nodetool-ai/protocol";
26
+ import { BlenderJobError } from "../runner.js";
27
+ import { runBlenderJob } from "../run-job.js";
28
+ import { runBlenderNodeStep } from "./blender-error.js";
29
+ import { DEFAULT_MODEL_3D } from "./defaults.js";
30
+ import { blenderProgressHandler } from "./progress.js";
31
+ const NODE_NAME = "nodetool.blender.ExportModel";
32
+ const FORMAT_FILES = {
33
+ fbx: { file: "model.fbx", mime: "application/octet-stream" },
34
+ obj: { file: "model.obj", mime: "text/plain" },
35
+ usd: { file: "model.usd", mime: "application/octet-stream" }
36
+ };
37
+ const EXPORT_FORMATS = ["fbx", "obj", "usd"];
38
+ /** The format a user typed, or null when it names no exporter. */
39
+ function toExportFormat(value) {
40
+ const normalized = value.toLowerCase();
41
+ return EXPORT_FORMATS.find((format) => format === normalized) ?? null;
42
+ }
43
+ /** Blender ran past its wall clock: point at the knob that fixes it. */
44
+ function timeoutMessage(timeoutMs) {
45
+ return (`${NODE_NAME}: Blender export timed out after ${timeoutMs}ms. ` +
46
+ `Decimate the scene first, or raise the timeout.`);
47
+ }
48
+ export class ExportModelNode extends BaseNode {
49
+ static nodeType = "nodetool.blender.ExportModel";
50
+ static title = "Export 3D Model With Blender";
51
+ static description = "Export a 3D model (GLB/glTF) to FBX, OBJ, or USD with Blender, persisted as a stored asset.\n 3d, mesh, model, export, fbx, obj, usd, file, blender\n\n Use cases:\n - Hand a generated mesh to a game engine as FBX\n - Export an OBJ for tools without glTF support\n - Export USD for pipelines built on it";
52
+ static metadataOutputTypes = {
53
+ file: "asset"
54
+ };
55
+ static inlineFields = [];
56
+ static inputFields = ["model"];
57
+ async process(context) {
58
+ const bytes = await resolveModelBytes(this.model, context);
59
+ if (bytes.length === 0) {
60
+ throw new Error(`${NODE_NAME}: model input is empty — connect a 3D model (GLB)`);
61
+ }
62
+ const requested = this.format ?? "fbx";
63
+ const format = toExportFormat(requested);
64
+ if (format === null) {
65
+ throw new BlenderJobError("bad_job", `${NODE_NAME}: unknown export format "${requested}" — choose fbx, obj, or usd.`);
66
+ }
67
+ const target = FORMAT_FILES[format];
68
+ if (!context) {
69
+ throw new BlenderJobError("bad_job", `${NODE_NAME}: exporting needs a processing context with createAsset.`);
70
+ }
71
+ const timeoutMs = Math.max(1, Number(this.timeout ?? 600)) * 1000;
72
+ return runBlenderNodeStep({
73
+ nodeName: NODE_NAME,
74
+ timeoutMessage: timeoutMessage(timeoutMs),
75
+ signal: context.signal
76
+ }, async () => {
77
+ const result = await runBlenderJob(context, bytes, { op: "export_model", params: { format } }, { file: target.file }, {
78
+ timeoutMs,
79
+ signal: context.signal,
80
+ onProgress: blenderProgressHandler(context, this.__node_id)
81
+ });
82
+ const raw = result.outputs["file"];
83
+ if (!raw || raw.length === 0) {
84
+ throw new BlenderJobError("missing_output", "Blender produced no export bytes.");
85
+ }
86
+ const created = await context.createAsset({
87
+ name: target.file,
88
+ contentType: target.mime,
89
+ content: raw
90
+ });
91
+ const assetId = isRecord(created) && isString(created["id"]) ? created["id"] : null;
92
+ if (assetId === null) {
93
+ throw new BlenderJobError("bad_result", "The export asset was created without an id.");
94
+ }
95
+ return {
96
+ file: {
97
+ type: "asset",
98
+ uri: `asset://${assetId}`,
99
+ asset_id: assetId,
100
+ metadata: { format, mime: target.mime }
101
+ }
102
+ };
103
+ });
104
+ }
105
+ }
106
+ __decorate([
107
+ prop({
108
+ type: "model_3d",
109
+ default: DEFAULT_MODEL_3D,
110
+ title: "Model",
111
+ description: "The 3D model to export (GLB or glTF with embedded buffers)"
112
+ })
113
+ ], ExportModelNode.prototype, "model", void 0);
114
+ __decorate([
115
+ prop({
116
+ type: "enum",
117
+ default: "fbx",
118
+ title: "Format",
119
+ description: "Export format: fbx, obj, or usd (OBJ is geometry-only, no .mtl; GLB stays a Model3DRef — see Prepare For Engine)",
120
+ values: ["fbx", "obj", "usd"]
121
+ })
122
+ ], ExportModelNode.prototype, "format", void 0);
123
+ __decorate([
124
+ prop({ type: "int", default: 600, title: "Timeout", description: "Maximum export time in seconds", min: 1, max: 3600 })
125
+ ], ExportModelNode.prototype, "timeout", void 0);
126
+ export const BLENDER_EXPORT_NODES = [ExportModelNode];
127
+ //# sourceMappingURL=export-model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-model.js","sourceRoot":"","sources":["../../src/nodes/export-model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * `nodetool.blender.PrepareForEngine` — glTF mesh → game-engine GLB + LODs.
3
+ *
4
+ * Stage 3: the `prepare_for_engine` op over `LocalBlenderRunner` (D8). Takes
5
+ * a `Model3DRef`, decimates every mesh toward `target_faces`, optionally
6
+ * unwraps and bakes (`ao`, `normal`, or both) into the materials, then
7
+ * returns the prepared model as an inline `model_3d` ref (GLB, like every
8
+ * other `model_3d` socket) plus `lod_count` LODs at halving face targets.
9
+ * Downstream save nodes decide persistence.
10
+ *
11
+ * Every failure rethrows with the node name prefixed. An abort through
12
+ * `context.signal` passes through unwrapped so the node rejects with the
13
+ * abort reason and no partial output.
14
+ */
15
+ import { BaseNode } from "@nodetool-ai/node-sdk";
16
+ import type { ModelBytesRefLike } from "@nodetool-ai/nodes-utils";
17
+ import type { ProcessingContext } from "@nodetool-ai/runtime";
18
+ import type { BakeMode } from "../job.js";
19
+ /** An inline `model_3d` ref carrying GLB bytes, like `RenderToImage`'s image. */
20
+ interface InlineModel3DRef {
21
+ type: string;
22
+ uri: string;
23
+ asset_id: null;
24
+ data: string;
25
+ }
26
+ /** Output handles PrepareForEngineNode.process() emits. */
27
+ type PrepareForEngineNodeOutputs = {
28
+ model: InlineModel3DRef;
29
+ lods: InlineModel3DRef[];
30
+ };
31
+ export declare class PrepareForEngineNode extends BaseNode {
32
+ static readonly nodeType = "nodetool.blender.PrepareForEngine";
33
+ static readonly title = "Prepare 3D Model For Engine";
34
+ static readonly description = "Prepare a 3D model (GLB/glTF) for a game engine with Blender: decimate to a face budget, unwrap UVs, bake AO and normal maps, and emit LODs at halving face counts.\n 3d, mesh, decimate, unwrap, bake, lod, glb, game, engine, blender\n\n Use cases:\n - Shrink a generated mesh to a face budget for a game engine\n - Bake AO and normal maps into the materials\n - Emit LODs alongside the prepared model";
35
+ static readonly metadataOutputTypes: {
36
+ model: string;
37
+ lods: string;
38
+ };
39
+ static readonly inlineFields: never[];
40
+ static readonly inputFields: string[];
41
+ model: ModelBytesRefLike;
42
+ target_faces: number;
43
+ unwrap: boolean;
44
+ bake: BakeMode;
45
+ bake_resolution: number;
46
+ lod_count: number;
47
+ timeout: number;
48
+ process(context?: ProcessingContext): Promise<PrepareForEngineNodeOutputs>;
49
+ }
50
+ export declare const BLENDER_PREPARE_NODES: readonly [typeof PrepareForEngineNode];
51
+ export {};
52
+ //# sourceMappingURL=prepare-for-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepare-for-engine.d.ts","sourceRoot":"","sources":["../../src/nodes/prepare-for-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,QAAQ,EAAQ,MAAM,uBAAuB,CAAC;AAEvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAS1C,iFAAiF;AACjF,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,IAAI,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,2DAA2D;AAC3D,KAAK,2BAA2B,GAAG;IACjC,KAAK,EAAE,gBAAgB,CAAC;IACxB,IAAI,EAAE,gBAAgB,EAAE,CAAC;CAC1B,CAAC;AAcF,qBAAa,oBAAqB,SAAQ,QAAQ;IAChD,MAAM,CAAC,QAAQ,CAAC,QAAQ,uCAAuC;IAC/D,MAAM,CAAC,QAAQ,CAAC,KAAK,iCAAiC;IACtD,MAAM,CAAC,QAAQ,CAAC,WAAW,oaACwY;IACna,MAAM,CAAC,QAAQ,CAAC,mBAAmB;QACjC,KAAK;QACL,IAAI;MACJ;IACF,MAAM,CAAC,QAAQ,CAAC,YAAY,UAAM;IAClC,MAAM,CAAC,QAAQ,CAAC,WAAW,WAAa;IAQhC,KAAK,EAAE,iBAAiB,CAAC;IAGzB,YAAY,EAAE,MAAM,CAAC;IAGrB,MAAM,EAAE,OAAO,CAAC;IAShB,IAAI,EAAE,QAAQ,CAAC;IAGf,eAAe,EAAE,MAAM,CAAC;IAGxB,SAAS,EAAE,MAAM,CAAC;IAGlB,OAAO,EAAE,MAAM,CAAC;IAElB,OAAO,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAwE/E;CACF;AAED,eAAO,MAAM,qBAAqB,wCAAkC,CAAC"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * `nodetool.blender.PrepareForEngine` — glTF mesh → game-engine GLB + LODs.
3
+ *
4
+ * Stage 3: the `prepare_for_engine` op over `LocalBlenderRunner` (D8). Takes
5
+ * a `Model3DRef`, decimates every mesh toward `target_faces`, optionally
6
+ * unwraps and bakes (`ao`, `normal`, or both) into the materials, then
7
+ * returns the prepared model as an inline `model_3d` ref (GLB, like every
8
+ * other `model_3d` socket) plus `lod_count` LODs at halving face targets.
9
+ * Downstream save nodes decide persistence.
10
+ *
11
+ * Every failure rethrows with the node name prefixed. An abort through
12
+ * `context.signal` passes through unwrapped so the node rejects with the
13
+ * abort reason and no partial output.
14
+ */
15
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
16
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
17
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
18
+ 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;
19
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
20
+ };
21
+ import { BaseNode, prop } from "@nodetool-ai/node-sdk";
22
+ import { bytesToBase64, resolveModelBytes } from "@nodetool-ai/nodes-utils";
23
+ import { BlenderJobError } from "../runner.js";
24
+ import { runBlenderJob } from "../run-job.js";
25
+ import { runBlenderNodeStep } from "./blender-error.js";
26
+ import { DEFAULT_MODEL_3D } from "./defaults.js";
27
+ import { blenderProgressHandler } from "./progress.js";
28
+ const NODE_NAME = "nodetool.blender.PrepareForEngine";
29
+ function modelRef(bytes) {
30
+ return { type: "model_3d", uri: "", asset_id: null, data: bytesToBase64(bytes) };
31
+ }
32
+ /** Blender ran past its wall clock: point at the knob that fixes it. */
33
+ function timeoutMessage(timeoutMs) {
34
+ return (`${NODE_NAME}: Blender mesh preparation timed out after ${timeoutMs}ms. ` +
35
+ `Lower the bake resolution, decimate first, or raise the timeout.`);
36
+ }
37
+ export class PrepareForEngineNode extends BaseNode {
38
+ static nodeType = "nodetool.blender.PrepareForEngine";
39
+ static title = "Prepare 3D Model For Engine";
40
+ static description = "Prepare a 3D model (GLB/glTF) for a game engine with Blender: decimate to a face budget, unwrap UVs, bake AO and normal maps, and emit LODs at halving face counts.\n 3d, mesh, decimate, unwrap, bake, lod, glb, game, engine, blender\n\n Use cases:\n - Shrink a generated mesh to a face budget for a game engine\n - Bake AO and normal maps into the materials\n - Emit LODs alongside the prepared model";
41
+ static metadataOutputTypes = {
42
+ model: "model_3d",
43
+ lods: "list[model_3d]"
44
+ };
45
+ static inlineFields = [];
46
+ static inputFields = ["model"];
47
+ async process(context) {
48
+ const bytes = await resolveModelBytes(this.model, context);
49
+ if (bytes.length === 0) {
50
+ throw new Error(`${NODE_NAME}: model input is empty — connect a 3D model (GLB)`);
51
+ }
52
+ const lodCount = Math.min(8, Math.max(0, Math.round(Number(this.lod_count ?? 0))));
53
+ const outputs = {};
54
+ outputs["model"] = "model.glb";
55
+ for (let index = 1; index <= lodCount; index++) {
56
+ outputs[`lod_${index}`] = `lod_${index}.glb`;
57
+ }
58
+ const timeoutMs = Math.max(1, Number(this.timeout ?? 600)) * 1000;
59
+ return runBlenderNodeStep({
60
+ nodeName: NODE_NAME,
61
+ timeoutMessage: timeoutMessage(timeoutMs),
62
+ signal: context?.signal
63
+ }, async () => {
64
+ const result = await runBlenderJob(context, bytes, {
65
+ op: "prepare_for_engine",
66
+ params: {
67
+ target_faces: Math.min(1000000, Math.max(1, Math.round(Number(this.target_faces ?? 5000)))),
68
+ unwrap: this.unwrap !== false,
69
+ bake: this.bake ?? "none",
70
+ bake_resolution: Math.min(4096, Math.max(16, Math.round(Number(this.bake_resolution ?? 1024)))),
71
+ lod_count: lodCount
72
+ }
73
+ }, outputs, {
74
+ timeoutMs,
75
+ signal: context?.signal,
76
+ onProgress: blenderProgressHandler(context, this.__node_id)
77
+ });
78
+ const model = result.outputs["model"];
79
+ if (!model || model.length === 0) {
80
+ throw new BlenderJobError("missing_output", "Blender produced no model bytes.");
81
+ }
82
+ const lods = [];
83
+ for (let index = 1; index <= lodCount; index++) {
84
+ const raw = result.outputs[`lod_${index}`];
85
+ if (!raw || raw.length === 0) {
86
+ throw new BlenderJobError("missing_output", `Blender produced no bytes for LOD ${index}.`);
87
+ }
88
+ lods.push(modelRef(raw));
89
+ }
90
+ return { model: modelRef(model), lods };
91
+ });
92
+ }
93
+ }
94
+ __decorate([
95
+ prop({
96
+ type: "model_3d",
97
+ default: DEFAULT_MODEL_3D,
98
+ title: "Model",
99
+ description: "The 3D model to prepare (GLB or glTF with embedded buffers)"
100
+ })
101
+ ], PrepareForEngineNode.prototype, "model", void 0);
102
+ __decorate([
103
+ prop({ type: "int", default: 5000, title: "Target Faces", description: "Face budget every mesh is decimated toward; meshes already under it are left alone", min: 1, max: 1000000 })
104
+ ], PrepareForEngineNode.prototype, "target_faces", void 0);
105
+ __decorate([
106
+ prop({ type: "bool", default: true, title: "Unwrap", description: "UV-unwrap every mesh (smart project) before baking; baking projects missing UVs anyway" })
107
+ ], PrepareForEngineNode.prototype, "unwrap", void 0);
108
+ __decorate([
109
+ prop({
110
+ type: "enum",
111
+ default: "none",
112
+ title: "Bake",
113
+ description: "Maps to bake into the materials at Bake Resolution: none, ao (occlusion multiplied into base color), normal (tangent-space normal map), or both",
114
+ values: ["none", "ao", "normal", "both"]
115
+ })
116
+ ], PrepareForEngineNode.prototype, "bake", void 0);
117
+ __decorate([
118
+ prop({ type: "int", default: 1024, title: "Bake Resolution", description: "Width and height in pixels of each baked map", min: 16, max: 4096 })
119
+ ], PrepareForEngineNode.prototype, "bake_resolution", void 0);
120
+ __decorate([
121
+ prop({ type: "int", default: 0, title: "LOD Count", description: "How many LODs to emit alongside the model, at halving face targets (LOD 1 is half the prepared faces, LOD 2 a quarter, and so on)", min: 0, max: 8 })
122
+ ], PrepareForEngineNode.prototype, "lod_count", void 0);
123
+ __decorate([
124
+ prop({ type: "int", default: 600, title: "Timeout", description: "Maximum preparation time in seconds", min: 1, max: 3600 })
125
+ ], PrepareForEngineNode.prototype, "timeout", void 0);
126
+ export const BLENDER_PREPARE_NODES = [PrepareForEngineNode];
127
+ //# sourceMappingURL=prepare-for-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prepare-for-engine.js","sourceRoot":"","sources":["../../src/nodes/prepare-for-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Blender `Fra:` progress as `node_progress` messages (D6).
3
+ *
4
+ * `LocalBlenderRunner` turns the op's `Fra:<n>` stderr lines into
5
+ * `onProgress` calls; this binds them to `context.postMessage`, the way the
6
+ * ComfyUI node reports progress. Returns undefined without a context, so
7
+ * context-free node tests stay silent.
8
+ */
9
+ import type { ProcessingContext } from "@nodetool-ai/runtime";
10
+ export declare function blenderProgressHandler(context: ProcessingContext | undefined, nodeId: string): ((frame: number, total: number) => void) | undefined;
11
+ //# sourceMappingURL=progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/nodes/progress.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,iBAAiB,GAAG,SAAS,EACtC,MAAM,EAAE,MAAM,GACb,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAUtD"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Blender `Fra:` progress as `node_progress` messages (D6).
3
+ *
4
+ * `LocalBlenderRunner` turns the op's `Fra:<n>` stderr lines into
5
+ * `onProgress` calls; this binds them to `context.postMessage`, the way the
6
+ * ComfyUI node reports progress. Returns undefined without a context, so
7
+ * context-free node tests stay silent.
8
+ */
9
+ export function blenderProgressHandler(context, nodeId) {
10
+ if (!context)
11
+ return undefined;
12
+ return (frame, total) => {
13
+ context.postMessage({
14
+ type: "node_progress",
15
+ node_id: nodeId,
16
+ progress: frame,
17
+ total
18
+ });
19
+ };
20
+ }
21
+ //# sourceMappingURL=progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/nodes/progress.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,UAAU,sBAAsB,CACpC,OAAsC,EACtC,MAAc;IAEd,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,OAAO,CAAC,KAAa,EAAE,KAAa,EAAE,EAAE;QACtC,OAAO,CAAC,WAAW,CAAC;YAClB,IAAI,EAAE,eAAe;YACrB,OAAO,EAAE,MAAM;YACf,QAAQ,EAAE,KAAK;YACf,KAAK;SACN,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * `nodetool.blender.RenderAnimation` — glTF scene + camera → video via Blender.
3
+ *
4
+ * Stage 2: the `render_animation` op over `LocalBlenderRunner` (D8). Takes
5
+ * a `Model3DRef`, builds the versioned `BlenderJob` for the frame range at
6
+ * `fps`, and returns an inline video ref like the video nodes, so
7
+ * downstream save nodes decide persistence. The scene fps is set to `fps`
8
+ * before import, so a glTF animation timestamp `t` seconds lands on frame
9
+ * `round(t * fps)`; with no glTF animation under `camera_mode: orbit` the
10
+ * orbit turns `orbit_degrees` across the range. Video comes from Blender's
11
+ * own FFMPEG writer (MPEG-4, H.264, `yuv420p`), and per-frame `Fra:`
12
+ * progress reaches the run as `node_progress` messages.
13
+ *
14
+ * Every failure rethrows with the node name prefixed. An abort through
15
+ * `context.signal` passes through unwrapped so the node rejects with the
16
+ * abort reason and no partial output.
17
+ */
18
+ import type { ProcessingContext } from "@nodetool-ai/runtime";
19
+ import type { CameraMode } from "../job.js";
20
+ import { BlenderRenderBase } from "./render-base.js";
21
+ /** Output handle RenderAnimationNode.process() emits. */
22
+ type RenderAnimationNodeOutputs = {
23
+ video: {
24
+ type: string;
25
+ uri: string;
26
+ asset_id: null;
27
+ data: string;
28
+ };
29
+ };
30
+ export declare class RenderAnimationNode extends BlenderRenderBase {
31
+ static readonly nodeType = "nodetool.blender.RenderAnimation";
32
+ static readonly title = "Render 3D Animation With Blender";
33
+ static readonly description = "Render a 3D model (GLB/glTF) to a video with Blender: glTF animations play on their timeline, or the orbit camera sweeps across the frame range.\n 3d, render, animation, video, camera, orbit, blender, eevee, cycles\n\n Use cases:\n - Turn an animated 3D model into a video\n - Sweep the camera around a static scene for a turntable clip\n - Feed camera-consistent frames into video models";
34
+ static readonly metadataOutputTypes: {
35
+ video: string;
36
+ };
37
+ static readonly inlineFields: never[];
38
+ static readonly inputFields: string[];
39
+ camera_mode: CameraMode;
40
+ width: number;
41
+ height: number;
42
+ transparent: boolean;
43
+ frame_start: number;
44
+ frame_end: number;
45
+ fps: number;
46
+ orbit_degrees: number;
47
+ timeout: number;
48
+ process(context?: ProcessingContext): Promise<RenderAnimationNodeOutputs>;
49
+ }
50
+ export declare const BLENDER_ANIMATION_NODES: readonly [typeof RenderAnimationNode];
51
+ export {};
52
+ //# sourceMappingURL=render-animation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-animation.d.ts","sourceRoot":"","sources":["../../src/nodes/render-animation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAK5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAIrD,yDAAyD;AACzD,KAAK,0BAA0B,GAAG;IAChC,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,mBAAoB,SAAQ,iBAAiB;IACxD,MAAM,CAAC,QAAQ,CAAC,QAAQ,sCAAsC;IAC9D,MAAM,CAAC,QAAQ,CAAC,KAAK,sCAAsC;IAC3D,MAAM,CAAC,QAAQ,CAAC,WAAW,yZAC6X;IACxZ,MAAM,CAAC,QAAQ,CAAC,mBAAmB;QACjC,KAAK;MACL;IACF,MAAM,CAAC,QAAQ,CAAC,YAAY,UAAM;IAClC,MAAM,CAAC,QAAQ,CAAC,WAAW,WAAa;IAahC,WAAW,EAAE,UAAU,CAAC;IAGxB,KAAK,EAAE,MAAM,CAAC;IAGd,MAAM,EAAE,MAAM,CAAC;IAGf,WAAW,EAAE,OAAO,CAAC;IAGrB,WAAW,EAAE,MAAM,CAAC;IAGpB,SAAS,EAAE,MAAM,CAAC;IAGlB,GAAG,EAAE,MAAM,CAAC;IAGZ,aAAa,EAAE,MAAM,CAAC;IAGtB,OAAO,EAAE,MAAM,CAAC;IAElB,OAAO,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,0BAA0B,CAAC,CA2E9E;CACF;AAED,eAAO,MAAM,uBAAuB,uCAAiC,CAAC"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * `nodetool.blender.RenderAnimation` — glTF scene + camera → video via Blender.
3
+ *
4
+ * Stage 2: the `render_animation` op over `LocalBlenderRunner` (D8). Takes
5
+ * a `Model3DRef`, builds the versioned `BlenderJob` for the frame range at
6
+ * `fps`, and returns an inline video ref like the video nodes, so
7
+ * downstream save nodes decide persistence. The scene fps is set to `fps`
8
+ * before import, so a glTF animation timestamp `t` seconds lands on frame
9
+ * `round(t * fps)`; with no glTF animation under `camera_mode: orbit` the
10
+ * orbit turns `orbit_degrees` across the range. Video comes from Blender's
11
+ * own FFMPEG writer (MPEG-4, H.264, `yuv420p`), and per-frame `Fra:`
12
+ * progress reaches the run as `node_progress` messages.
13
+ *
14
+ * Every failure rethrows with the node name prefixed. An abort through
15
+ * `context.signal` passes through unwrapped so the node rejects with the
16
+ * abort reason and no partial output.
17
+ */
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ 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;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ import { prop } from "@nodetool-ai/node-sdk";
25
+ import { bytesToBase64, resolveModelBytes } from "@nodetool-ai/nodes-utils";
26
+ import { BlenderJobError } from "../runner.js";
27
+ import { runBlenderJob } from "../run-job.js";
28
+ import { runBlenderNodeStep } from "./blender-error.js";
29
+ import { blenderProgressHandler } from "./progress.js";
30
+ import { BlenderRenderBase } from "./render-base.js";
31
+ const NODE_NAME = "nodetool.blender.RenderAnimation";
32
+ /** Blender ran past its wall clock: point at the two knobs that fix it. */
33
+ function timeoutMessage(timeoutMs) {
34
+ return (`${NODE_NAME}: Blender animation render timed out after ${timeoutMs}ms. ` +
35
+ `Lower the samples, use EEVEE, shorten the range, or raise the timeout.`);
36
+ }
37
+ export class RenderAnimationNode extends BlenderRenderBase {
38
+ static nodeType = "nodetool.blender.RenderAnimation";
39
+ static title = "Render 3D Animation With Blender";
40
+ static description = "Render a 3D model (GLB/glTF) to a video with Blender: glTF animations play on their timeline, or the orbit camera sweeps across the frame range.\n 3d, render, animation, video, camera, orbit, blender, eevee, cycles\n\n Use cases:\n - Turn an animated 3D model into a video\n - Sweep the camera around a static scene for a turntable clip\n - Feed camera-consistent frames into video models";
41
+ static metadataOutputTypes = {
42
+ video: "video"
43
+ };
44
+ static inlineFields = [];
45
+ static inputFields = ["model"];
46
+ async process(context) {
47
+ const bytes = await resolveModelBytes(this.model, context);
48
+ if (bytes.length === 0) {
49
+ throw new Error(`${NODE_NAME}: model input is empty — connect a 3D model (GLB)`);
50
+ }
51
+ const frameStart = Math.max(0, Math.round(Number(this.frame_start ?? 1)));
52
+ const frameEnd = Math.max(frameStart, Math.round(Number(this.frame_end ?? 24)));
53
+ const timeoutMs = Math.max(1, Number(this.timeout ?? 600)) * 1000;
54
+ return runBlenderNodeStep({
55
+ nodeName: NODE_NAME,
56
+ timeoutMessage: timeoutMessage(timeoutMs),
57
+ signal: context?.signal
58
+ }, async () => {
59
+ const result = await runBlenderJob(context, bytes, {
60
+ op: "render_animation",
61
+ params: {
62
+ camera_mode: this.camera_mode ?? "auto",
63
+ azimuth: Number(this.azimuth ?? 45),
64
+ elevation: Number(this.elevation ?? 25),
65
+ fov: Number(this.fov ?? 35),
66
+ zoom: Number(this.zoom ?? 1),
67
+ lighting: this.lighting ?? "studio",
68
+ light_intensity: Number(this.light_intensity ?? 1),
69
+ background_color: String(this.background_color ?? "#808080"),
70
+ transparent: this.transparent === true,
71
+ engine: this.engine ?? "eevee",
72
+ samples: Math.max(1, Math.round(Number(this.samples ?? 16))),
73
+ denoise: this.denoise !== false,
74
+ resolution_percentage: Math.max(1, Math.round(Number(this.resolution_percentage ?? 100))),
75
+ width: Math.max(1, Math.round(Number(this.width ?? 1024))),
76
+ height: Math.max(1, Math.round(Number(this.height ?? 1024))),
77
+ frame_start: frameStart,
78
+ frame_end: frameEnd,
79
+ fps: Math.max(1, Math.round(Number(this.fps ?? 24))),
80
+ orbit_degrees: Number(this.orbit_degrees ?? 360)
81
+ }
82
+ }, { video: "anim.mp4" }, {
83
+ timeoutMs,
84
+ signal: context?.signal,
85
+ onProgress: blenderProgressHandler(context, this.__node_id)
86
+ });
87
+ const mp4 = result.outputs["video"];
88
+ if (!mp4 || mp4.length === 0) {
89
+ throw new BlenderJobError("missing_output", "Blender produced no video bytes.");
90
+ }
91
+ return {
92
+ video: {
93
+ type: "video",
94
+ uri: "",
95
+ asset_id: null,
96
+ data: bytesToBase64(mp4)
97
+ }
98
+ };
99
+ });
100
+ }
101
+ }
102
+ __decorate([
103
+ prop({
104
+ type: "enum",
105
+ default: "auto",
106
+ title: "Camera Mode",
107
+ 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; with no glTF animation it sweeps orbit_degrees across the range)",
108
+ values: ["auto", "scene", "orbit"]
109
+ })
110
+ ], RenderAnimationNode.prototype, "camera_mode", void 0);
111
+ __decorate([
112
+ prop({ type: "int", default: 1024, title: "Width", description: "Output video width in pixels", min: 16, max: 4096 })
113
+ ], RenderAnimationNode.prototype, "width", void 0);
114
+ __decorate([
115
+ prop({ type: "int", default: 1024, title: "Height", description: "Output video height in pixels", min: 16, max: 4096 })
116
+ ], RenderAnimationNode.prototype, "height", void 0);
117
+ __decorate([
118
+ prop({ type: "bool", default: false, title: "Transparent", description: "Render on a transparent background (video alpha; container support varies)" })
119
+ ], RenderAnimationNode.prototype, "transparent", void 0);
120
+ __decorate([
121
+ prop({ type: "int", default: 1, title: "Frame Start", description: "First frame in the glTF timeline (timestamp t seconds lands on round(t * fps))", min: 0, max: 100000 })
122
+ ], RenderAnimationNode.prototype, "frame_start", void 0);
123
+ __decorate([
124
+ prop({ type: "int", default: 24, title: "Frame End", description: "Last frame rendered, inclusive", min: 0, max: 100000 })
125
+ ], RenderAnimationNode.prototype, "frame_end", void 0);
126
+ __decorate([
127
+ prop({ type: "int", default: 24, title: "FPS", description: "Scene frames per second; glTF animation timestamps map onto this timeline", min: 1, max: 120 })
128
+ ], RenderAnimationNode.prototype, "fps", void 0);
129
+ __decorate([
130
+ prop({ type: "float", default: 360, title: "Orbit Degrees", description: "Camera sweep in degrees across the range when the model has no animation and Camera Mode is orbit", min: -1080, max: 1080 })
131
+ ], RenderAnimationNode.prototype, "orbit_degrees", void 0);
132
+ __decorate([
133
+ prop({ type: "int", default: 600, title: "Timeout", description: "Maximum render time in seconds", min: 1, max: 3600 })
134
+ ], RenderAnimationNode.prototype, "timeout", void 0);
135
+ export const BLENDER_ANIMATION_NODES = [RenderAnimationNode];
136
+ //# sourceMappingURL=render-animation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-animation.js","sourceRoot":"","sources":["../../src/nodes/render-animation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
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
+ import { BaseNode } from "@nodetool-ai/node-sdk";
15
+ import type { ModelBytesRefLike } from "@nodetool-ai/nodes-utils";
16
+ import type { BlenderEngine, CameraMode, LightingPreset } from "../job.js";
17
+ export declare abstract class BlenderRenderBase extends BaseNode {
18
+ model: ModelBytesRefLike;
19
+ camera_mode: CameraMode;
20
+ width: number;
21
+ height: number;
22
+ azimuth: number;
23
+ elevation: number;
24
+ fov: number;
25
+ zoom: number;
26
+ lighting: LightingPreset;
27
+ light_intensity: number;
28
+ background_color: string;
29
+ transparent: boolean;
30
+ engine: BlenderEngine;
31
+ samples: number;
32
+ denoise: boolean;
33
+ resolution_percentage: number;
34
+ }
35
+ //# sourceMappingURL=render-base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-base.d.ts","sourceRoot":"","sources":["../../src/nodes/render-base.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAQ,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,cAAc,EACf,MAAM,WAAW,CAAC;AAGnB,8BAAsB,iBAAkB,SAAQ,QAAQ;IAO9C,KAAK,EAAE,iBAAiB,CAAC;IAUzB,WAAW,EAAE,UAAU,CAAC;IAGxB,KAAK,EAAE,MAAM,CAAC;IAGd,MAAM,EAAE,MAAM,CAAC;IAGf,OAAO,EAAE,MAAM,CAAC;IAGhB,SAAS,EAAE,MAAM,CAAC;IAGlB,GAAG,EAAE,MAAM,CAAC;IAGZ,IAAI,EAAE,MAAM,CAAC;IASb,QAAQ,EAAE,cAAc,CAAC;IAGzB,eAAe,EAAE,MAAM,CAAC;IAGxB,gBAAgB,EAAE,MAAM,CAAC;IAGzB,WAAW,EAAE,OAAO,CAAC;IASrB,MAAM,EAAE,aAAa,CAAC;IAGtB,OAAO,EAAE,MAAM,CAAC;IAGhB,OAAO,EAAE,OAAO,CAAC;IAGjB,qBAAqB,EAAE,MAAM,CAAC;CACvC"}