improvements
This commit is contained in:
@@ -258,11 +258,22 @@ test('complete import prepares all stages, actor models, local textures and defi
|
||||
const plan = h.context.importedPlan;
|
||||
assert.equal(plan.rows[0].resolved.kind, 'Local');
|
||||
assert.equal(plan.rows[0].entity, 'minecraft:wolf');
|
||||
const actorForm = h.dialogs.find((dialog) => dialog.title.endsWith('Actors')).form;
|
||||
const importDialog = h.dialogs.find((dialog) => dialog.title.endsWith('Actors & Models'));
|
||||
const actorForm = importDialog.form;
|
||||
assert.equal(actorForm.entity_0.type, 'select');
|
||||
assert.equal(actorForm.entity_0.value, 'minecraft:wolf');
|
||||
assert.equal(actorForm.entity_0.options['minecraft:fox'], 'minecraft:fox');
|
||||
assert.equal(actorForm.gender_0.value, 'm');
|
||||
assert.equal(actorForm.models_section.type, 'info');
|
||||
assert.match(actorForm.source_0.value, /Local:.*wolf\.m\.geo\.json/);
|
||||
assert.equal(actorForm.model_0.type, 'file');
|
||||
assert.equal(h.dialogs.length, 1, 'Import needs only one configuration dialog');
|
||||
let updated;
|
||||
importDialog.onFormChange.call({ form: { setValues(values, rerender) {
|
||||
assert.equal(rerender, false);
|
||||
updated = values;
|
||||
} } }, { entity_0: 'minecraft:fox', gender_0: 'f', slim_0: false });
|
||||
assert.match(updated.source_0, /No automatic model found/);
|
||||
assert.equal(plan.rows[0].textures.size, 1);
|
||||
assert.deepEqual(Array.from(plan.imported.stageNames), ['example.p1', 'example.p2']);
|
||||
assert.ok(plan.imported.fileObj.animations['example.p2'].bones.actor1_body);
|
||||
@@ -306,6 +317,36 @@ test('complete import finds model texture in cached assets and uses its PNG dime
|
||||
assert.equal(JSON.parse(importing.context.Project.multiactor_actor_textures)['1'], row.defaultTexture);
|
||||
});
|
||||
|
||||
test('alternative vanilla texture paths do not add unused textures unless a bone references them', (t) => {
|
||||
const f = fixtures(t), h = harness(), source = f.makePack('source');
|
||||
const model = f.model(source, 'test:source/entity/silverfish.m');
|
||||
const cache = path.join(f.root, 'cached-assets');
|
||||
const png = Buffer.alloc(24);
|
||||
Buffer.from('89504e470d0a1a0a', 'hex').copy(png);
|
||||
png.writeUInt32BE(64, 16); png.writeUInt32BE(32, 20);
|
||||
for (const relative of ['silverfish.png', 'silverfish/silverfish.png']) {
|
||||
const file = path.join(cache, 'assets/minecraft/textures/entity', relative);
|
||||
fs.mkdirSync(path.dirname(file), { recursive: true });
|
||||
fs.writeFileSync(file, png);
|
||||
}
|
||||
h.storage.set('animationdirector_prop_source', cache);
|
||||
const json = JSON.parse(fs.readFileSync(model, 'utf8'));
|
||||
const row = { json, geo: json['minecraft:geometry'][0], entity: 'minecraft:silverfish', slim: false,
|
||||
label: 'silverfish', resolved: { file: model } };
|
||||
h.loadImportTextures(row, [source], io);
|
||||
assert.equal(row.defaultTexture, 'minecraft:textures/entity/silverfish/silverfish.png');
|
||||
assert.deepEqual(Array.from(row.textures.keys()), [row.defaultTexture]);
|
||||
|
||||
const plan = { parsed: { animationId: 'example' }, rows: [row], definition: { actors: [{}] },
|
||||
imported: { stageNames: [], fileObj: { animations: {} } }, blockEntry: null };
|
||||
h.commitAutomaticImport(plan);
|
||||
assert.equal(h.context.Texture.all.length, 1);
|
||||
|
||||
row.json.afw_bone_textures = { body: 'minecraft:textures/entity/silverfish.png' };
|
||||
h.loadImportTextures(row, [source], io);
|
||||
assert.deepEqual(Array.from(row.textures.keys()), [row.defaultTexture, 'minecraft:textures/entity/silverfish.png']);
|
||||
});
|
||||
|
||||
test('complete import uses the matching Alex skin as a player-only texture fallback', async (t) => {
|
||||
const f = fixtures(t), source = f.makePack('source');
|
||||
const defFile = f.write(path.join(source.root, 'data/test/afw_animdefs/example.json'), {
|
||||
@@ -329,7 +370,7 @@ test('complete import uses the matching Alex skin as a player-only texture fallb
|
||||
const h = harness(true);
|
||||
h.storage.set('animationdirector_prop_source', cache);
|
||||
h.context.selectedFile = { path: defFile };
|
||||
h.context.answer = (dialog, result) => dialog.title.endsWith('Actors')
|
||||
h.context.answer = (dialog, result) => dialog.title.endsWith('Actors & Models')
|
||||
? { ...result, slim_0: slim } : result;
|
||||
await h.automaticallyImportAnimation();
|
||||
assert.deepEqual(h.errors, []);
|
||||
@@ -352,7 +393,7 @@ test('definition actors exclude extra clips, their effects and stages containing
|
||||
} });
|
||||
f.model(source, 'test:source/entity/wolf.m');
|
||||
h.context.selectedFile = { path: file };
|
||||
h.context.answer = (dialog, result) => dialog.title.endsWith('Actors') ? { ...result, gender_0: 'm' } : result;
|
||||
h.context.answer = (dialog, result) => dialog.title.endsWith('Actors & Models') ? { ...result, gender_0: 'm' } : result;
|
||||
await h.automaticallyImportAnimation();
|
||||
assert.deepEqual(h.errors, []);
|
||||
const plan = h.context.importedPlan;
|
||||
@@ -364,7 +405,7 @@ test('definition actors exclude extra clips, their effects and stages containing
|
||||
assert.deepEqual(Object.keys(clip.bones), ['actor1_body']);
|
||||
assert.equal(clip.sound_effects, undefined);
|
||||
assert.equal(clip.particle_effects, undefined);
|
||||
assert.match(h.dialogs.at(-1).form.info.text, /Ignored animation actors.*unused/);
|
||||
assert.ok(h.messages.some((message) => /Ignored animation actors.*unused/.test(message)));
|
||||
});
|
||||
|
||||
test('a definition actor without a distinct clip still requires a valid mapping', async (t) => {
|
||||
@@ -442,13 +483,13 @@ test('missing models can be supplied manually, and their locally supplied textur
|
||||
});
|
||||
const model = f.model(source, 'test:unrelated/wolf.m', { afw_texture: 'test:textures/unavailable.png' });
|
||||
h.context.selectedFile = { path: file };
|
||||
h.context.answer = (dialog, result) => dialog.title.endsWith('Actors') ? { ...result, gender_0: 'm' }
|
||||
: dialog.title.endsWith('Models') ? { ...result, model_0: { path: model } } : result;
|
||||
h.context.answer = (dialog, result) => dialog.title.endsWith('Actors & Models')
|
||||
? { ...result, gender_0: 'm', model_0: { path: model } } : result;
|
||||
await h.automaticallyImportAnimation();
|
||||
assert.deepEqual(h.errors, []);
|
||||
assert.equal(h.context.importedPlan.rows[0].resolved.kind, 'Manually selected');
|
||||
assert.equal(h.context.importedPlan.rows[0].textures.size, 0);
|
||||
assert.match(h.dialogs.at(-1).form.info.text, /no base texture found locally/);
|
||||
assert.ok(h.messages.some((message) => /Imported with notes:.*no base texture/.test(message)));
|
||||
});
|
||||
|
||||
test('batch import uses a new project, one undo entry, actor prefixes and texture override bindings', () => {
|
||||
|
||||
Reference in New Issue
Block a user