Files
workinf_Blender_Wasm/tools/web/check-mask-main-reader.mjs
2026-08-14 18:08:29 -04:00

70 lines
3.2 KiB
JavaScript

import assert from "node:assert/strict";
import fs from "node:fs";
import factory from "../../web/app/src/vendor/blender/web_engine.js";
const root = new URL("../../", import.meta.url);
const wasmBinary = fs.readFileSync(new URL("web/app/src/vendor/blender/web_engine.wasm", root));
const fixture = fs.readFileSync(new URL("tests/files/web/mask_scene.blend", root));
function open(engine, handle, bytes) {
const pointer = engine._malloc(bytes.byteLength);
try {
engine.HEAPU8.set(bytes, pointer);
assert.equal(engine._web_engine_open_blend(handle, pointer, bytes.byteLength), 0,
engine.UTF8ToString(engine._web_engine_last_error_message()));
}
finally { engine._free(pointer); }
}
function snapshot(engine, handle) {
const dataOut = engine._malloc(4), lengthOut = engine._malloc(4);
try {
assert.equal(engine._web_engine_get_scene_snapshot(handle, dataOut, lengthOut), 0,
engine.UTF8ToString(engine._web_engine_last_error_message()));
const pointer = engine.HEAPU32[dataOut >>> 2], length = engine.HEAPU32[lengthOut >>> 2];
return JSON.parse(new TextDecoder().decode(engine.HEAPU8.slice(pointer, pointer + length)));
}
finally { engine._free(dataOut); engine._free(lengthOut); }
}
const close = (actual, expected, label) => assert.ok(Math.abs(actual - expected) < 1e-6,
`${label}: ${actual} != ${expected}`);
const engine = await factory({ wasmBinary: wasmBinary.slice() });
const handle = engine._web_engine_create();
open(engine, handle, fixture);
const scene = snapshot(engine, handle);
assert.equal(scene.trackingMaskStatus, "AVAILABLE");
const project = scene.trackingMasks;
assert.equal(project.schemaVersion, 1);
assert.equal(project.clips.length, 0);
assert.equal(project.bindings.length, 0);
assert.equal(project.masks.length, 1);
const mask = project.masks[0];
assert.equal(mask.id, "mask:WebMask");
assert.equal(mask.layers.length, 2);
const layer = mask.layers.find((candidate) => candidate.name === "WebMaskLayer");
assert.equal(layer.name, "WebMaskLayer");
assert.equal(layer.locked, true);
close(layer.opacity, 0.625, "layer opacity");
const spline = layer.splines[0];
assert.equal(spline.cyclic, true);
assert.equal(spline.fill, false);
assert.equal(spline.points.length, 3);
assert.deepEqual(spline.points.map((point) => point.handleType), ["ALIGNED", "VECTOR", "FREE"]);
for (const [label, actual, expected] of [
["point co", spline.points[0].co, [0.1, 0.2]],
["left handle", spline.points[0].handleLeft, [0.2, 0.2]],
["right handle", spline.points[0].handleRight, [0, 0.2]],
]) {
actual.forEach((value, index) => close(value, expected[index], `${label}[${index}]`));
}
close(spline.points[2].feather, 0.75, "point feather");
assert.deepEqual(spline.points.map((point) => point.selected), [true, false, true]);
const editable = mask.layers.find((candidate) => candidate.name === "WebEditableLayer");
assert.equal(editable.locked, false);
assert.equal(editable.visible, true);
assert.equal(editable.splines[0].points.length, 2);
assert.deepEqual(editable.splines[0].points.map((point) => point.handleType), ["FREE", "FREE"]);
engine._web_engine_destroy(handle);
process.stdout.write("mask-main-reader-ok layers-splines=passed handles-feather=passed locked-editable-selection=passed\n");