import assert from "node:assert/strict"; import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { pathToFileURL } from "node:url"; import test from "node:test"; import ts from "typescript"; const repoRoot = path.resolve(import.meta.dirname, "../../.."); const temporary = fs.mkdtempSync(path.join(os.tmpdir(), "weight-paint-unit-")); const sourcePath = path.join(repoRoot, "web/protocol/weight-paint.ts"); const outputPath = path.join(temporary, "weight-paint.mjs"); const transpiled = ts.transpileModule(fs.readFileSync(sourcePath, "utf8"), { compilerOptions: { module: ts.ModuleKind.ES2022, target: ts.ScriptTarget.ES2022 }, fileName: sourcePath, reportDiagnostics: true, }); assert.deepEqual(transpiled.diagnostics, []); fs.writeFileSync(outputPath, transpiled.outputText); const weightPaint = await import(pathToFileURL(outputPath)); const vertices = [ { index: 0, position: [-1, 0, 0], influences: [{ group: "Root", weight: 1 }, { group: "Tip", weight: 0.25 }] }, { index: 1, position: [1, 0, 0], influences: [{ group: "Root", weight: 1 }, { group: "Tip", weight: 0.25 }] }, { index: 2, position: [0, 1, 0], influences: [{ group: "Root", weight: 0.25 }, { group: "Tip", weight: 1 }] }, ]; test("M9-12 normalizes after limiting influences", () => { const result = weightPaint.applyWeightPaintPatch(vertices, { schemaVersion: 1, vertexGroup: "WebPaintGroup", indices: [2], values: [0.5], normalize: true, limit: 2, }); assert.deepEqual(result[2].influences, [ { group: "Tip", weight: 2 / 3 }, { group: "WebPaintGroup", weight: 1 / 3 }, ]); }); test("M9-12 mirrors onto a reciprocal verified coordinate map", () => { const result = weightPaint.applyWeightPaintPatch(vertices, { schemaVersion: 1, vertexGroup: "WebPaintGroup", indices: [0], values: [0.8], mirror: true, mirrorAxis: 0, mirrorTolerance: 1e-4, }); assert.equal(result[0].influences.at(-1).weight, 0.8); assert.equal(result[1].influences.at(-1).weight, 0.8); }); test("M9-12 rejects an unverified symmetry map and invalid limits", () => { assert.throws(() => weightPaint.parseWeightPaintOptions({ limit: 33 }), /PAINT_SCHEMA_INVALID/); assert.throws(() => weightPaint.applyWeightPaintPatch([ ...vertices, { index: 3, position: [4, 0, 0], influences: [] }, ], { schemaVersion: 1, vertexGroup: "WebPaintGroup", indices: [0], values: [0.8], mirror: true, mirrorAxis: 0, mirrorTolerance: 1e-4, }), /WEIGHT_MIRROR_SYMMETRY_UNVERIFIED/); });