@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.
- package/README.md +36 -0
- package/blender_ops/depth.py +133 -0
- package/blender_ops/errors.py +46 -0
- package/blender_ops/exr.py +205 -0
- package/blender_ops/framing.py +75 -0
- package/blender_ops/ops/__init__.py +24 -0
- package/blender_ops/ops/common.py +310 -0
- package/blender_ops/ops/export_model.py +95 -0
- package/blender_ops/ops/prepare_for_engine.py +352 -0
- package/blender_ops/ops/render_animation.py +382 -0
- package/blender_ops/ops/render_image.py +41 -0
- package/blender_ops/ops/render_passes.py +363 -0
- package/blender_ops/run_job.py +110 -0
- package/blender_ops/tests/test_camera_lens.py +107 -0
- package/blender_ops/tests/test_depth.py +158 -0
- package/blender_ops/tests/test_exr.py +218 -0
- package/blender_ops/tests/test_framing.py +50 -0
- package/dist/.nodetool-build-stamp +1 -0
- package/dist/bake.d.ts +107 -0
- package/dist/bake.d.ts.map +1 -0
- package/dist/bake.js +209 -0
- package/dist/bake.js.map +1 -0
- package/dist/blender-binary.d.ts +38 -0
- package/dist/blender-binary.d.ts.map +1 -0
- package/dist/blender-binary.js +169 -0
- package/dist/blender-binary.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/job.d.ts +163 -0
- package/dist/job.d.ts.map +1 -0
- package/dist/job.js +67 -0
- package/dist/job.js.map +1 -0
- package/dist/nodes/bake-timeline-clip.d.ts +48 -0
- package/dist/nodes/bake-timeline-clip.d.ts.map +1 -0
- package/dist/nodes/bake-timeline-clip.js +152 -0
- package/dist/nodes/bake-timeline-clip.js.map +1 -0
- package/dist/nodes/blender-error.d.ts +21 -0
- package/dist/nodes/blender-error.d.ts.map +1 -0
- package/dist/nodes/blender-error.js +38 -0
- package/dist/nodes/blender-error.js.map +1 -0
- package/dist/nodes/defaults.d.ts +18 -0
- package/dist/nodes/defaults.d.ts.map +1 -0
- package/dist/nodes/defaults.js +18 -0
- package/dist/nodes/defaults.js.map +1 -0
- package/dist/nodes/export-model.d.ts +49 -0
- package/dist/nodes/export-model.d.ts.map +1 -0
- package/dist/nodes/export-model.js +127 -0
- package/dist/nodes/export-model.js.map +1 -0
- package/dist/nodes/prepare-for-engine.d.ts +52 -0
- package/dist/nodes/prepare-for-engine.d.ts.map +1 -0
- package/dist/nodes/prepare-for-engine.js +127 -0
- package/dist/nodes/prepare-for-engine.js.map +1 -0
- package/dist/nodes/progress.d.ts +11 -0
- package/dist/nodes/progress.d.ts.map +1 -0
- package/dist/nodes/progress.js +21 -0
- package/dist/nodes/progress.js.map +1 -0
- package/dist/nodes/render-animation.d.ts +52 -0
- package/dist/nodes/render-animation.d.ts.map +1 -0
- package/dist/nodes/render-animation.js +136 -0
- package/dist/nodes/render-animation.js.map +1 -0
- package/dist/nodes/render-base.d.ts +35 -0
- package/dist/nodes/render-base.d.ts.map +1 -0
- package/dist/nodes/render-base.js +95 -0
- package/dist/nodes/render-base.js.map +1 -0
- package/dist/nodes/render-image.d.ts +41 -0
- package/dist/nodes/render-image.d.ts.map +1 -0
- package/dist/nodes/render-image.js +98 -0
- package/dist/nodes/render-image.js.map +1 -0
- package/dist/nodes/render-passes.d.ts +54 -0
- package/dist/nodes/render-passes.d.ts.map +1 -0
- package/dist/nodes/render-passes.js +167 -0
- package/dist/nodes/render-passes.js.map +1 -0
- package/dist/run-job.d.ts +34 -0
- package/dist/run-job.d.ts.map +1 -0
- package/dist/run-job.js +137 -0
- package/dist/run-job.js.map +1 -0
- package/dist/runner.d.ts +124 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +521 -0
- package/dist/runner.js.map +1 -0
- package/package.json +73 -0
package/dist/run-job.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
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 { HostBinaryMissingError, withSpan } from "@nodetool-ai/runtime";
|
|
10
|
+
import { isCloudProfileActive } from "@nodetool-ai/protocol";
|
|
11
|
+
import { resolveBlenderBinary } from "./blender-binary.js";
|
|
12
|
+
import { jobFileNameSchema, BLENDER_JOB_VERSION } from "./job.js";
|
|
13
|
+
import { BlenderJobError, LocalBlenderRunner, MAX_OUTPUT_COUNT, WorkerBlenderRunner } from "./runner.js";
|
|
14
|
+
/** File name the model bytes are staged under. The extension selects import. */
|
|
15
|
+
export const BLENDER_MODEL_INPUT_FILE = "model.glb";
|
|
16
|
+
/**
|
|
17
|
+
* Select the local tier when Blender resolves. Otherwise, an explicitly
|
|
18
|
+
* configured worker is used only after its status advertises Blender.
|
|
19
|
+
*
|
|
20
|
+
* A configured worker is never silently replaced with local after a worker
|
|
21
|
+
* connection or capability failure: the URL is an explicit deployment choice.
|
|
22
|
+
*/
|
|
23
|
+
export async function resolveBlenderRunner(blenderPath, options = {}) {
|
|
24
|
+
if (testRunner)
|
|
25
|
+
return testRunner;
|
|
26
|
+
try {
|
|
27
|
+
await (blenderBinaryResolverForTesting?.() ??
|
|
28
|
+
resolveBlenderBinary({ configuredPath: blenderPath }));
|
|
29
|
+
return new LocalBlenderRunner({ binaryPath: blenderPath ?? undefined });
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
if (!(err instanceof HostBinaryMissingError))
|
|
33
|
+
throw err;
|
|
34
|
+
}
|
|
35
|
+
const workerUrl = process.env["NODETOOL_WORKER_URL"]?.trim();
|
|
36
|
+
if (!workerUrl) {
|
|
37
|
+
return new LocalBlenderRunner({ binaryPath: blenderPath ?? undefined });
|
|
38
|
+
}
|
|
39
|
+
const runner = new WorkerBlenderRunner();
|
|
40
|
+
await runner.assertAvailable(options);
|
|
41
|
+
return runner;
|
|
42
|
+
}
|
|
43
|
+
let testRunner = null;
|
|
44
|
+
let blenderBinaryResolverForTesting = null;
|
|
45
|
+
/**
|
|
46
|
+
* Override `resolveBlenderRunner` for node tests (T6b), so every node test
|
|
47
|
+
* runs against a fake and proves the node never reaches past the
|
|
48
|
+
* `BlenderRunner` interface. Pass null to restore the local runner.
|
|
49
|
+
*/
|
|
50
|
+
export function __setBlenderRunnerForTesting(runner) {
|
|
51
|
+
testRunner = runner;
|
|
52
|
+
}
|
|
53
|
+
/** Test seam for exercising D7 without depending on the host's Blender install. */
|
|
54
|
+
export function __setBlenderBinaryResolverForTesting(resolver) {
|
|
55
|
+
blenderBinaryResolverForTesting = resolver;
|
|
56
|
+
}
|
|
57
|
+
/** Only the render ops carry an engine; the mesh ops have no such param. */
|
|
58
|
+
function engineOf(op) {
|
|
59
|
+
switch (op.op) {
|
|
60
|
+
case "render_image":
|
|
61
|
+
case "render_passes":
|
|
62
|
+
case "render_animation":
|
|
63
|
+
return op.params.engine;
|
|
64
|
+
default:
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export async function runBlenderJob(
|
|
69
|
+
// The local runner stages through the workspace seam (D6 step 1): the
|
|
70
|
+
// scratch parent comes from `context.workspace.scratchDir()`. Fakes in
|
|
71
|
+
// node tests run without a context and never touch the filesystem.
|
|
72
|
+
context, modelBytes, op, outputs, options) {
|
|
73
|
+
if (modelBytes.length === 0) {
|
|
74
|
+
throw new BlenderJobError("bad_job", "Blender model input is empty.");
|
|
75
|
+
}
|
|
76
|
+
const modelFile = jobFileNameSchema.safeParse(BLENDER_MODEL_INPUT_FILE);
|
|
77
|
+
if (!modelFile.success) {
|
|
78
|
+
throw new BlenderJobError("bad_job", `Invalid Blender input file name "${BLENDER_MODEL_INPUT_FILE}".`);
|
|
79
|
+
}
|
|
80
|
+
const outputEntries = Object.entries(outputs);
|
|
81
|
+
const maxOutputCount = options.maxOutputCount ?? MAX_OUTPUT_COUNT;
|
|
82
|
+
if (outputEntries.length > maxOutputCount) {
|
|
83
|
+
throw new BlenderJobError("bad_job", `Too many Blender outputs: ${outputEntries.length} declared, ` +
|
|
84
|
+
`at most ${maxOutputCount} allowed.`);
|
|
85
|
+
}
|
|
86
|
+
for (const [name, file] of outputEntries) {
|
|
87
|
+
if (!jobFileNameSchema.safeParse(file).success) {
|
|
88
|
+
throw new BlenderJobError("bad_job", `Invalid Blender output file name "${file}" for output "${name}".`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const job = {
|
|
92
|
+
version: BLENDER_JOB_VERSION,
|
|
93
|
+
inputs: { model: BLENDER_MODEL_INPUT_FILE },
|
|
94
|
+
outputs: { ...outputs },
|
|
95
|
+
job: op
|
|
96
|
+
};
|
|
97
|
+
// A stored path is executable configuration. The hosted cloud profile must
|
|
98
|
+
// never execute a user-supplied host path.
|
|
99
|
+
const blenderPath = context &&
|
|
100
|
+
!isCloudProfileActive(process.env["NODETOOL_NODE_PROFILE"], process.env["NODETOOL_ENV"])
|
|
101
|
+
? await context.getSetting("BLENDER_PATH")
|
|
102
|
+
: null;
|
|
103
|
+
const runner = await resolveBlenderRunner(blenderPath, {
|
|
104
|
+
signal: options.signal,
|
|
105
|
+
timeoutMs: options.timeoutMs
|
|
106
|
+
});
|
|
107
|
+
const binary = await resolveBlenderBinary({ configuredPath: blenderPath }).catch(() => null);
|
|
108
|
+
const engine = engineOf(op);
|
|
109
|
+
// The local runner needs a real directory, which only the workspace can
|
|
110
|
+
// give it (`scratchDir()` is the seam a cloud workspace implements). A
|
|
111
|
+
// fake runner needs none, so a missing context only fails the local tier.
|
|
112
|
+
let runOptions = options;
|
|
113
|
+
if (runner instanceof LocalBlenderRunner) {
|
|
114
|
+
const workspace = context?.workspace;
|
|
115
|
+
if (!workspace) {
|
|
116
|
+
throw new BlenderJobError("bad_job", `Blender local render needs a processing context with a workspace.`);
|
|
117
|
+
}
|
|
118
|
+
runOptions = { ...options, scratchParent: await workspace.scratchDir() };
|
|
119
|
+
}
|
|
120
|
+
return withSpan("blender.run", {
|
|
121
|
+
"blender.version": binary?.version.join("."),
|
|
122
|
+
"blender.op": op.op,
|
|
123
|
+
"blender.engine": engine,
|
|
124
|
+
"blender.runner": runner.kind
|
|
125
|
+
}, async (span) => {
|
|
126
|
+
const result = await runner.run(job, { model: modelBytes }, runOptions);
|
|
127
|
+
span?.setAttribute("blender.render_seconds", result.stats.render_seconds);
|
|
128
|
+
if (result.exitCode !== undefined) {
|
|
129
|
+
span?.setAttribute("blender.exit_code", result.exitCode);
|
|
130
|
+
}
|
|
131
|
+
if (result.queuedMs !== undefined) {
|
|
132
|
+
span?.setAttribute("blender.queued_ms", result.queuedMs);
|
|
133
|
+
}
|
|
134
|
+
return result;
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=run-job.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-job.js","sourceRoot":"","sources":["../src/run-job.ts"],"names":[],"mappings":"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"}
|
package/dist/runner.d.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The runner interface and its local implementation (D6).
|
|
3
|
+
*
|
|
4
|
+
* The runner works on logical files and nothing else. No scratch directory,
|
|
5
|
+
* no argv, and no path crosses the interface, so the local and worker
|
|
6
|
+
* implementations differ only in where the bytes go.
|
|
7
|
+
*/
|
|
8
|
+
import type { PythonBridge } from "@nodetool-ai/runtime";
|
|
9
|
+
import { type BlenderJob, type BlenderResultStats } from "./job.js";
|
|
10
|
+
/** Per-output byte cap, overridable per call. */
|
|
11
|
+
export declare const MAX_OUTPUT_BYTES: number;
|
|
12
|
+
/** Cap on the sum of all outputs, overridable per call. */
|
|
13
|
+
export declare const MAX_TOTAL_OUTPUT_BYTES: number;
|
|
14
|
+
/** Ceiling on declared outputs. */
|
|
15
|
+
export declare const MAX_OUTPUT_COUNT = 32;
|
|
16
|
+
export type BlenderJobErrorCode = "import_failed" | "no_geometry" | "no_camera" | "unsupported_format" | "render_failed" | "export_failed" | "bake_failed" | "bad_job" | "bad_result" | "missing_output" | "output_too_large" | "timeout"
|
|
17
|
+
/** `NODETOOL_WORKER_URL` names a worker that does not run Blender. */
|
|
18
|
+
| "worker_unavailable";
|
|
19
|
+
export declare class BlenderJobError extends Error {
|
|
20
|
+
readonly code: BlenderJobErrorCode;
|
|
21
|
+
constructor(code: BlenderJobErrorCode, message: string);
|
|
22
|
+
}
|
|
23
|
+
export interface BlenderRunOptions {
|
|
24
|
+
timeoutMs: number;
|
|
25
|
+
signal?: AbortSignal;
|
|
26
|
+
onProgress?: (frame: number, total: number) => void;
|
|
27
|
+
/** Per-output byte cap. Default MAX_OUTPUT_BYTES (512 MiB). */
|
|
28
|
+
maxOutputBytes?: number;
|
|
29
|
+
/** Cap on the sum of all outputs. Default MAX_TOTAL_OUTPUT_BYTES (1 GiB). */
|
|
30
|
+
maxTotalOutputBytes?: number;
|
|
31
|
+
/**
|
|
32
|
+
* Ceiling on declared outputs. Default {@link MAX_OUTPUT_COUNT}. Raised only
|
|
33
|
+
* by the 3D bake, whose PNG sequence is one declared output per frame; the
|
|
34
|
+
* byte caps above still bound what that costs.
|
|
35
|
+
*/
|
|
36
|
+
maxOutputCount?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Parent directory for the per-run scratch directory. `runBlenderJob`
|
|
39
|
+
* derives this from `context.workspace.scratchDir()` (D6 step 1), so the
|
|
40
|
+
* run stages through the workspace seam instead of a bare temp path. The
|
|
41
|
+
* constructor option below is only a test override.
|
|
42
|
+
*/
|
|
43
|
+
scratchParent?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface BlenderRunResult {
|
|
46
|
+
/** Keyed by `job.outputs` name. Only declared outputs are ever read. */
|
|
47
|
+
outputs: Record<string, Uint8Array>;
|
|
48
|
+
stats: BlenderResultStats;
|
|
49
|
+
/** Blender's exit code. Present on local runs. */
|
|
50
|
+
exitCode?: number;
|
|
51
|
+
/**
|
|
52
|
+
* How long the run waited for the `render` concurrency slot, in
|
|
53
|
+
* milliseconds. The local runner copies it from `runHostBinary`; fakes
|
|
54
|
+
* leave it unset.
|
|
55
|
+
*/
|
|
56
|
+
queuedMs?: number;
|
|
57
|
+
}
|
|
58
|
+
export interface BlenderRunner {
|
|
59
|
+
readonly kind: "local" | "worker";
|
|
60
|
+
run(job: BlenderJob, inputs: Record<string, Uint8Array>, options: BlenderRunOptions): Promise<BlenderRunResult>;
|
|
61
|
+
}
|
|
62
|
+
export interface LocalBlenderRunnerOptions {
|
|
63
|
+
/**
|
|
64
|
+
* Parent directory for the per-run scratch directory. Test-only override:
|
|
65
|
+
* production always arrives through `BlenderRunOptions.scratchParent`,
|
|
66
|
+
* which `runBlenderJob` derives from `context.workspace.scratchDir()`.
|
|
67
|
+
*/
|
|
68
|
+
scratchParent?: string;
|
|
69
|
+
/** Already resolved executable for this user-scoped run. */
|
|
70
|
+
binaryPath?: string;
|
|
71
|
+
}
|
|
72
|
+
export interface WorkerBlenderRunnerOptions {
|
|
73
|
+
/**
|
|
74
|
+
* An already-managed worker bridge. The caller retains ownership and must
|
|
75
|
+
* close it. When omitted, each run creates and closes a bridge configured
|
|
76
|
+
* from `NODETOOL_WORKER_URL` and `NODETOOL_WORKER_TOKEN`.
|
|
77
|
+
*/
|
|
78
|
+
bridge?: PythonBridge;
|
|
79
|
+
}
|
|
80
|
+
/** Test seam for D7 selection without opening a real worker socket. */
|
|
81
|
+
export declare function __setWorkerBlenderBridgeFactoryForTesting(factory: (() => PythonBridge) | null): void;
|
|
82
|
+
/**
|
|
83
|
+
* Directory holding the vendored `run_job.py` op script, which differs by
|
|
84
|
+
* deployment and is checked rather than assumed (same shape as
|
|
85
|
+
* `bundledFontsDir` in `@nodetool-ai/timeline`):
|
|
86
|
+
*
|
|
87
|
+
* - a checkout or an npm install resolves `packages/blender-nodes/blender_ops/`,
|
|
88
|
+
* one level above this module's `dist/` output;
|
|
89
|
+
* - the packaged backend is one flat `server.mjs`, so `import.meta.url` is the
|
|
90
|
+
* bundle root and `bundle-backend.mjs` stages the directory beside it as
|
|
91
|
+
* `_blender_ops/`.
|
|
92
|
+
*
|
|
93
|
+
* Throws naming the expected entry point when neither exists, so a missing
|
|
94
|
+
* stage fails here with the fix instead of inside Blender's stderr tail.
|
|
95
|
+
*/
|
|
96
|
+
export declare function resolveOpScriptDir(): string;
|
|
97
|
+
export declare class LocalBlenderRunner implements BlenderRunner {
|
|
98
|
+
readonly kind: "local";
|
|
99
|
+
private readonly scratchParent;
|
|
100
|
+
private readonly binaryPath;
|
|
101
|
+
constructor(options?: LocalBlenderRunnerOptions);
|
|
102
|
+
run(job: BlenderJob, inputs: Record<string, Uint8Array>, options: BlenderRunOptions): Promise<BlenderRunResult>;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Worker implementation of the runner contract (Stage 4b, D6).
|
|
106
|
+
*
|
|
107
|
+
* The worker image carries Blender but not the NodeTool ops. Every run sends
|
|
108
|
+
* the complete ops tree as extra blobs, keyed by paths relative to
|
|
109
|
+
* `blender_ops/`, so its scripts match the NodeTool release that issued the
|
|
110
|
+
* job. Workflow inputs remain the only entries in `job.inputs`.
|
|
111
|
+
*/
|
|
112
|
+
export declare class WorkerBlenderRunner implements BlenderRunner {
|
|
113
|
+
readonly kind: "worker";
|
|
114
|
+
private readonly bridge;
|
|
115
|
+
constructor(options?: WorkerBlenderRunnerOptions);
|
|
116
|
+
/** Connect and check the worker status without retaining an owned socket. */
|
|
117
|
+
assertAvailable(options?: {
|
|
118
|
+
signal?: AbortSignal;
|
|
119
|
+
timeoutMs?: number;
|
|
120
|
+
}): Promise<void>;
|
|
121
|
+
run(job: BlenderJob, inputs: Record<string, Uint8Array>, options: BlenderRunOptions): Promise<BlenderRunResult>;
|
|
122
|
+
private withBridge;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgBH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGzD,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,kBAAkB,EACxB,MAAM,UAAU,CAAC;AAIlB,iDAAiD;AACjD,eAAO,MAAM,gBAAgB,QAAoB,CAAC;AAClD,2DAA2D;AAC3D,eAAO,MAAM,sBAAsB,QAAqB,CAAC;AACzD,mCAAmC;AACnC,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAQnC,MAAM,MAAM,mBAAmB,GAC3B,eAAe,GACf,aAAa,GACb,WAAW,GACX,oBAAoB,GACpB,eAAe,GACf,eAAe,GACf,aAAa,GACb,SAAS,GACT,YAAY,GACZ,gBAAgB,GAChB,kBAAkB,GAClB,SAAS;AACX,sEAAsE;GACpE,oBAAoB,CAAC;AAEzB,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;IACnC,YAAY,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAIrD;CACF;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACpC,KAAK,EAAE,kBAAkB,CAAC;IAC1B,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IAClC,GAAG,CACD,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,EAClC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,0BAA0B;IACzC;;;;OAIG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAID,uEAAuE;AACvE,wBAAgB,yCAAyC,CACvD,OAAO,EAAE,CAAC,MAAM,YAAY,CAAC,GAAG,IAAI,GACnC,IAAI,CAEN;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAe3C;AAoCD,qBAAa,kBAAmB,YAAW,aAAa;IACtD,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IACnD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAEhD,YAAY,OAAO,GAAE,yBAA8B,EAGlD;IAEK,GAAG,CACP,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,EAClC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,gBAAgB,CAAC,CAkL3B;CACF;AAED;;;;;;;GAOG;AACH,qBAAa,mBAAoB,YAAW,aAAa;IACvD,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;IAElD,YAAY,OAAO,GAAE,0BAA+B,EAEnD;IAED,6EAA6E;IACvE,eAAe,CACnB,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO,GACzD,OAAO,CAAC,IAAI,CAAC,CAWf;IAEK,GAAG,CACP,GAAG,EAAE,UAAU,EACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,EAClC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,gBAAgB,CAAC,CA+B3B;YAEa,UAAU;CAoBzB"}
|