tweak
This commit is contained in:
@@ -2415,6 +2415,11 @@
|
|||||||
return sanitizeFilePart(String(name).replace(/\.geo\.json$/i, '').replace(/\.json$/i, '')) || 'model';
|
return sanitizeFilePart(String(name).replace(/\.geo\.json$/i, '').replace(/\.json$/i, '')) || 'model';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeGeckoExportName(name) {
|
||||||
|
return String(name || '').trim().replace(/\.(?:bbmodel|bbench)$/i, '')
|
||||||
|
.replace(/\.json$/i, '').replace(/(?:\.geo)+$/i, '');
|
||||||
|
}
|
||||||
|
|
||||||
async function cemTemplateCatalog() {
|
async function cemTemplateCatalog() {
|
||||||
if (typeof window === 'undefined' || typeof window.loadCEMTemplateModels !== 'function') {
|
if (typeof window === 'undefined' || typeof window.loadCEMTemplateModels !== 'function') {
|
||||||
throw new Error('Install and enable CEM Template Loader before creating a JEM model.');
|
throw new Error('Install and enable CEM Template Loader before creating a JEM model.');
|
||||||
@@ -2909,8 +2914,9 @@
|
|||||||
const bones = jem ? jemVariantBones(output) : [...new Map((output['minecraft:geometry'] || [])
|
const bones = jem ? jemVariantBones(output) : [...new Map((output['minecraft:geometry'] || [])
|
||||||
.flatMap((geometry) => geometry.bones || []).map((bone) => [bone.name, bone])).values()];
|
.flatMap((geometry) => geometry.bones || []).map((bone) => [bone.name, bone])).values()];
|
||||||
const form = {
|
const form = {
|
||||||
name: { type: 'text', label: 'Base model filename', value: saved.name || (jem
|
name: { type: 'text', label: 'Base model filename', value: jem
|
||||||
? getModelExportFileName().replace(/\.jem$/i, '').replace(/[123]$/, '') : getModelExportFileName().replace(/\.(m|f|mf)$/i, '')) },
|
? saved.name || getModelExportFileName().replace(/\.jem$/i, '').replace(/[123]$/, '')
|
||||||
|
: normalizeGeckoExportName(saved.name || normalizeGeckoExportName(getModelExportFileName()).replace(/\.(m|f|mf)$/i, '')) },
|
||||||
base: { type: 'checkbox', label: `Export unqualified model (.${extension})`, value: saved.base ?? true },
|
base: { type: 'checkbox', label: `Export unqualified model (.${extension})`, value: saved.base ?? true },
|
||||||
info: { type: 'info', text: 'Export one or more variants from this model. Excluded bones and their descendants are completely omitted, including geometry and locators. The source project is unchanged.' },
|
info: { type: 'info', text: 'Export one or more variants from this model. Excluded bones and their descendants are completely omitted, including geometry and locators. The source project is unchanged.' },
|
||||||
};
|
};
|
||||||
@@ -2930,7 +2936,7 @@
|
|||||||
onConfirm(result) {
|
onConfirm(result) {
|
||||||
try {
|
try {
|
||||||
if (Project !== sourceProject) throw new Error('Return to the source model project and retry.');
|
if (Project !== sourceProject) throw new Error('Return to the source model project and retry.');
|
||||||
const name = String(result.name || '').trim().replace(jem ? /\.jem$/i : /\.geo\.json$/i, '');
|
const name = jem ? String(result.name || '').trim().replace(/\.jem$/i, '') : normalizeGeckoExportName(result.name);
|
||||||
if (!name || /[<>:"/\\|?*]/.test(name)) throw new Error('Choose a valid base model filename without a folder path.');
|
if (!name || /[<>:"/\\|?*]/.test(name)) throw new Error('Choose a valid base model filename without a folder path.');
|
||||||
const genders = ['m', 'f', 'mf'].filter((gender) => result[gender]);
|
const genders = ['m', 'f', 'mf'].filter((gender) => result[gender]);
|
||||||
if (!result.base && !genders.length) throw new Error('Select at least one model to export.');
|
if (!result.base && !genders.length) throw new Error('Select at least one model to export.');
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ const vm = require('node:vm');
|
|||||||
function variantBuilder() {
|
function variantBuilder() {
|
||||||
const source = fs.readFileSync(path.join(__dirname, '..', 'AnimationDirector.js'), 'utf8').replace(
|
const source = fs.readFileSync(path.join(__dirname, '..', 'AnimationDirector.js'), 'utf8').replace(
|
||||||
' Plugin.register(PLUGIN_ID, {',
|
' Plugin.register(PLUGIN_ID, {',
|
||||||
' globalThis.variantTest = { buildGenderModelVariant, refreshModelVariantFields, createModelVariantBoneSections, buildJemModelVariant };\n Plugin.register(PLUGIN_ID, {'
|
' globalThis.variantTest = { buildGenderModelVariant, refreshModelVariantFields, createModelVariantBoneSections, buildJemModelVariant, normalizeGeckoExportName };\n Plugin.register(PLUGIN_ID, {'
|
||||||
);
|
);
|
||||||
const context = { Plugin: { register() {} }, console };
|
const context = { Plugin: { register() {} }, console };
|
||||||
vm.runInNewContext(source, context);
|
vm.runInNewContext(source, context);
|
||||||
return Object.assign(context.variantTest.buildGenderModelVariant, { refresh: context.variantTest.refreshModelVariantFields,
|
return Object.assign(context.variantTest.buildGenderModelVariant, { refresh: context.variantTest.refreshModelVariantFields,
|
||||||
sections: context.variantTest.createModelVariantBoneSections, jem: context.variantTest.buildJemModelVariant });
|
sections: context.variantTest.createModelVariantBoneSections, jem: context.variantTest.buildJemModelVariant,
|
||||||
|
normalizeName: context.variantTest.normalizeGeckoExportName });
|
||||||
}
|
}
|
||||||
|
|
||||||
test('gender variants omit selected bones, descendants, locators and texture overrides without changing source', () => {
|
test('gender variants omit selected bones, descendants, locators and texture overrides without changing source', () => {
|
||||||
@@ -35,6 +36,15 @@ test('gender variants omit selected bones, descendants, locators and texture ove
|
|||||||
assert.equal(JSON.stringify(source), before);
|
assert.equal(JSON.stringify(source), before);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('GeckoLib export filenames strip repeated geo and project extensions', () => {
|
||||||
|
const normalize = variantBuilder().normalizeName;
|
||||||
|
for (const name of ['horse', 'horse.geo', 'horse.geo.geo', 'horse.geo.json', 'horse.geo.bbench', 'horse.geo.bbmodel']) {
|
||||||
|
assert.equal(normalize(name), 'horse');
|
||||||
|
}
|
||||||
|
assert.equal(normalize('horse.f.geo.geo.json'), 'horse.f');
|
||||||
|
assert.equal(normalize('geology'), 'geology');
|
||||||
|
});
|
||||||
|
|
||||||
test('variant subtree propagation handles nested children and unknown saved selections', () => {
|
test('variant subtree propagation handles nested children and unknown saved selections', () => {
|
||||||
const build = variantBuilder();
|
const build = variantBuilder();
|
||||||
const source = { 'minecraft:geometry': [{ bones: [
|
const source = { 'minecraft:geometry': [{ bones: [
|
||||||
|
|||||||
Reference in New Issue
Block a user