Files
workinf_Blender_Wasm/tools/web/check-image-resources.mjs
2026-08-12 04:47:48 -04:00

92 lines
3.7 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));
async function openFixture(name) {
const engine = await factory({ wasmBinary: wasmBinary.slice() });
const handle = engine._web_engine_create();
const blend = fs.readFileSync(new URL(`tests/files/web/${name}`, root));
const input = engine._malloc(blend.byteLength);
engine.HEAPU8.set(blend, input);
assert.equal(engine._web_engine_open_blend(handle, input, blend.byteLength), 0, `${name} open`);
engine._free(input);
const dataOut = engine._malloc(4);
const lengthOut = engine._malloc(4);
assert.equal(engine._web_engine_get_scene_snapshot(handle, dataOut, lengthOut), 0);
const pointer = engine.HEAPU32[dataOut >>> 2];
const length = engine.HEAPU32[lengthOut >>> 2];
const snapshot = JSON.parse(new TextDecoder().decode(engine.HEAPU8.slice(pointer, pointer + length)));
engine._free(dataOut);
engine._free(lengthOut);
return { engine, handle, snapshot };
}
function packedAsset(engine, handle, assetId) {
const encoded = new TextEncoder().encode(assetId);
const id = engine._malloc(encoded.byteLength);
const dataOut = engine._malloc(4);
const lengthOut = engine._malloc(4);
engine.HEAPU8.set(encoded, id);
try {
assert.equal(engine._web_engine_get_packed_asset(handle, id, encoded.byteLength, dataOut, lengthOut), 0, assetId);
const pointer = engine.HEAPU32[dataOut >>> 2];
const length = engine.HEAPU32[lengthOut >>> 2];
return engine.HEAPU8.slice(pointer, pointer + length);
}
finally {
engine._free(id);
engine._free(dataOut);
engine._free(lengthOut);
}
}
const matrix = await openFixture("image_resource_matrix.blend");
try {
const byName = new Map(matrix.snapshot.images.map((image) => [image.name, image]));
const generated = byName.get("GeneratedTexture");
assert.equal(generated?.sourceKind, "GENERATED");
assert.equal(generated?.assetStatus, "GENERATED");
assert.equal(generated?.width, 12);
assert.equal(generated?.height, 6);
const udim = byName.get("UDIMTexture");
assert.equal(udim?.sourceKind, "TILED");
assert.equal(udim?.assetStatus, "PACKED");
assert.deepEqual(udim?.tiles.map((tile) => tile.number), [1001, 1002]);
for (const tile of udim.tiles) {
assert.equal(tile.packed, true);
assert.equal(tile.validSignature, true);
assert.deepEqual([...packedAsset(matrix.engine, matrix.handle, tile.assetId).slice(0, 8)], [137, 80, 78, 71, 13, 10, 26, 10]);
}
const linked = matrix.snapshot.libraries.find((library) => /image_resource_library\.blend$/.test(library.sourcePath));
assert.ok(linked, "linked image library resource is missing");
assert.equal(linked.packed, false);
assert.equal(linked.status, "EXTERNAL_REQUIRED");
assert.equal(linked.errorCode, "LINKED_LIBRARY_RESOURCE_REQUIRED");
const missing = byName.get("MissingExternalTexture");
assert.equal(missing?.sourceKind, "FILE");
assert.equal(missing?.assetStatus, "EXTERNAL");
assert.match(missing?.sourcePath, /missing\/not-present\.png$/);
}
finally {
matrix.engine._web_engine_destroy(matrix.handle);
}
const corrupt = await openFixture("corrupt_packed_image.blend");
try {
const image = corrupt.snapshot.images.find((candidate) => candidate.name === "CorruptPackedTexture");
assert.equal(image?.packed, true);
assert.equal(image?.assetStatus, "CORRUPT");
assert.equal(image?.errorCode, "PACKED_IMAGE_SIGNATURE_INVALID");
}
finally {
corrupt.engine._web_engine_destroy(corrupt.handle);
}
process.stdout.write("image-resources-ok udimTiles=2 generated=1 linked=1 corrupt=1 external=1\n");