tweaks
This commit is contained in:
@@ -12,7 +12,8 @@ function harness(capture = false) {
|
||||
const source = plugin.replace(' Plugin.register(PLUGIN_ID, {', `
|
||||
globalThis.api = { desktopFiles, importFilePath, insidePack, importResourceId, readImportPack, findImportPack, importPackRegistry,
|
||||
resolveImportModel, importModelCandidates, companionImportFiles, definitionActorKeys, defaultImportClipRoles,
|
||||
validateImportGeometry, automaticallyImportAnimation, loadImportTextures, commitAutomaticImport, resolveDefinitionImportStages };
|
||||
validateImportGeometry, automaticallyImportAnimation, loadImportTextures, commitAutomaticImport, resolveDefinitionImportStages,
|
||||
createImportAssetLookup, importGeometryIntoCurrentProject };
|
||||
Plugin.register(PLUGIN_ID, {`).replace(' function commitAutomaticImport(plan) {',
|
||||
` function commitAutomaticImport(plan) { ${capture ? 'globalThis.importedPlan = plan; return;' : ''}`);
|
||||
const storage = new Map(), dialogs = [], errors = [], undo = [], messages = [];
|
||||
@@ -38,6 +39,7 @@ function harness(capture = false) {
|
||||
Formats: { geckolib_model: { id: 'geckolib_model' } },
|
||||
newProject(format) {
|
||||
assert.equal(format.id, 'geckolib_model');
|
||||
context.Format = format;
|
||||
context.Project = { uuid: 'new-project' };
|
||||
return true;
|
||||
},
|
||||
@@ -530,3 +532,39 @@ test('unexpected animation-load failures cancel the batch rather than keeping a
|
||||
definition: {}, imported: { fileObj: {}, stageNames: [] } }), /load failed/);
|
||||
assert.deepEqual(h.undo.map((entry) => entry.type), ['begin', 'cancel']);
|
||||
});
|
||||
|
||||
test('manual replacement rejects duplicate and cyclic bones before touching the old actor', () => {
|
||||
const h = harness(), original = new h.context.Group({ name: 'actor1_body' }); original.init();
|
||||
for (const bones of [[{ name: 'body' }, { name: 'body' }], [{ name: 'body', parent: 'head' }, { name: 'head', parent: 'body' }]]) {
|
||||
assert.throws(() => h.importGeometryIntoCurrentProject({ bones }, 1, true), /unique|Cyclic/);
|
||||
assert.equal(h.context.Group.all[0], original);
|
||||
assert.equal(h.undo.length, 0);
|
||||
}
|
||||
});
|
||||
|
||||
test('manual geometry import cancels its undo transaction when model creation fails', () => {
|
||||
const h = harness();
|
||||
h.context.Group.prototype.init = () => { throw new Error('model creation failed'); };
|
||||
assert.throws(() => h.importGeometryIntoCurrentProject({ bones: [{ name: 'body' }] }, 1), /model creation failed/);
|
||||
assert.deepEqual(h.undo.map((entry) => entry.type), ['begin', 'cancel']);
|
||||
});
|
||||
|
||||
test('import asset lookup opens sources lazily and reuses positive and negative results', (t) => {
|
||||
const f = fixtures(t), h = harness(), first = f.makePack('first'), second = f.makePack('second');
|
||||
const relative = 'assets/test/textures/demo.png', png = Buffer.alloc(24);
|
||||
Buffer.from('89504e470d0a1a0a', 'hex').copy(png); png.writeUInt32BE(32, 16); png.writeUInt32BE(64, 20);
|
||||
const file = path.join(first.root, relative); fs.mkdirSync(path.dirname(file), { recursive: true }); fs.writeFileSync(file, png);
|
||||
let secondOpened = 0, textureReads = 0;
|
||||
const counted = { path, fs: { ...fs, statSync(file, ...args) {
|
||||
if (file === second.root) secondOpened++;
|
||||
return fs.statSync(file, ...args);
|
||||
}, readFileSync(file, ...args) { if (file.endsWith('demo.png')) textureReads++; return fs.readFileSync(file, ...args); } } };
|
||||
const assets = h.createImportAssetLookup(counted, [first.root, second.root]);
|
||||
assert.equal(assets.read(relative).dimensions.width, 32);
|
||||
assert.equal(secondOpened, 0);
|
||||
assets.read(relative); assert.equal(textureReads, 1);
|
||||
assert.equal(assets.read('assets/test/textures/missing.png'), null);
|
||||
const opened = secondOpened;
|
||||
assert.equal(assets.read('assets/test/textures/missing.png'), null);
|
||||
assert.equal(secondOpened, opened);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user