Skip to content

Commit

Permalink
feat: add nomip tag to avoid mipmaps being generated (#120)
Browse files Browse the repository at this point in the history
* feat: add nomip tag to avoid mipmaps being generated

* add nomip to texture packer and spine

* fix tests

* update docs
  • Loading branch information
Zyie authored Feb 6, 2025
1 parent e52a15a commit 23d8584
Show file tree
Hide file tree
Showing 12 changed files with 312 additions and 35 deletions.
7 changes: 4 additions & 3 deletions packages/assetpack/src/image/mipmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const defaultMipmapOptions: Required<MipmapOptions> = {
fixedResolution: 'default',
};

export function mipmap(_options: MipmapOptions = {}): AssetPipe<MipmapOptions, 'fix'>
export function mipmap(_options: MipmapOptions = {}): AssetPipe<MipmapOptions, 'fix' | 'nomip'>
{
const mipmap = resolveOptions(_options, defaultMipmapOptions);

Expand All @@ -34,14 +34,15 @@ export function mipmap(_options: MipmapOptions = {}): AssetPipe<MipmapOptions, '
},
tags: {
fix: 'fix',
nomip: 'nomip',
},
test(asset: Asset, options)
{
return options && checkExt(asset.path, '.png', '.jpg', '.jpeg');
return options && checkExt(asset.path, '.png', '.jpg', '.jpeg') && !asset.allMetaData[this.tags!.nomip];
},
async transform(asset: Asset, options)
{
const shouldMipmap = mipmap && !asset.metaData[this.tags!.fix];
const shouldMipmap = mipmap && !asset.allMetaData[this.tags!.fix];

let processedImages: CompressImageData[];

Expand Down
5 changes: 3 additions & 2 deletions packages/assetpack/src/spine/spineAtlasMipmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { MipmapOptions } from '../image/index.js';

export type SpineOptions = PluginOptions & MipmapOptions;

export function spineAtlasMipmap(_options?: SpineOptions): AssetPipe<SpineOptions, 'fix'>
export function spineAtlasMipmap(_options?: SpineOptions): AssetPipe<SpineOptions, 'fix' | 'nomip'>
{
return {
folder: false,
Expand All @@ -18,10 +18,11 @@ export function spineAtlasMipmap(_options?: SpineOptions): AssetPipe<SpineOption
},
tags: {
fix: 'fix',
nomip: 'nomip',
},
test(asset: Asset)
{
return !asset.allMetaData[this.tags!.fix] && checkExt(asset.path, '.atlas');
return !asset.allMetaData[this.tags!.nomip] && checkExt(asset.path, '.atlas');
},
async transform(asset: Asset, options)
{
Expand Down
24 changes: 16 additions & 8 deletions packages/assetpack/src/texture-packer/texturePacker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function checkForTexturePackerShortcutClashes(
}
}

export function texturePacker(_options: TexturePackerOptions = {}): AssetPipe<TexturePackerOptions, 'tps' | 'fix' | 'jpg'>
export function texturePacker(_options: TexturePackerOptions = {}): AssetPipe<TexturePackerOptions, 'tps' | 'fix' | 'jpg' | 'nomip'>
{
let shortcutClash: Record<string, boolean> = {};

Expand All @@ -75,6 +75,7 @@ export function texturePacker(_options: TexturePackerOptions = {}): AssetPipe<Te
tps: 'tps',
fix: 'fix',
jpg: 'jpg',
nomip: 'nomip',
},
test(asset: Asset)
{
Expand All @@ -90,17 +91,23 @@ export function texturePacker(_options: TexturePackerOptions = {}): AssetPipe<Te
async transform(asset: Asset, options)
{
const { resolutionOptions, texturePacker } = options;
const { resolutions, fixedResolution } = resolutionOptions!;

const fixedResolutions: {[x: string]: number} = {};

// eslint-disable-next-line max-len
fixedResolutions[resolutionOptions.fixedResolution] = resolutionOptions.resolutions[resolutionOptions.fixedResolution];
const fixedResolutions = { [fixedResolution]: resolutions[fixedResolution] };

// skip the children so that they do not get processed!
asset.skipChildren();

const largestResolution = Math.max(...Object.values(resolutionOptions.resolutions));
const resolutionHash = asset.allMetaData[this.tags!.fix] ? fixedResolutions : resolutionOptions.resolutions;
const largestResolution = Math.max(...Object.values(resolutions));
let resolutionHash = asset.allMetaData[this.tags!.fix] ? fixedResolutions : resolutions;

// if nomip is set, then we want to use the largest resolution to avoid any scaling
if (asset.allMetaData[this.tags!.nomip])
{
resolutionHash = {
default: largestResolution
};
}

const globPath = `${asset.path}/**/*.{jpg,png,gif}`;
const files = await glob(globPath);
Expand Down Expand Up @@ -183,7 +190,8 @@ export function texturePacker(_options: TexturePackerOptions = {}): AssetPipe<Te

jsonAsset.buffer = Buffer.from(JSON.stringify(json, null, 2));

textureAsset.metaData[this.tags!.fix] = true;
// don't mipmap the texture again, we have already done that
textureAsset.metaData[this.tags!.nomip] = true;

jsonAsset.transformData.page = i;

Expand Down
8 changes: 4 additions & 4 deletions packages/assetpack/src/webfont/sdf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface SDFFontOptions extends PluginOptions

function signedFont(
defaultOptions: SDFFontOptions
): AssetPipe<SDFFontOptions, 'font' | 'nc' | 'fix'>
): AssetPipe<SDFFontOptions, 'font' | 'nc' | 'nomip'>
{
return {
folder: false,
Expand All @@ -23,7 +23,7 @@ function signedFont(
tags: {
font: 'font',
nc: 'nc',
fix: 'fix',
nomip: 'nomip',
},
test(asset: Asset)
{
Expand Down Expand Up @@ -51,9 +51,9 @@ function signedFont(

const newTextureAsset = createNewAssetAt(asset, newTextureName);

// don't compress!
// don't compress or mipmap the font texture, we can't resize or update image paths
newTextureAsset.metaData[this.tags!.nc] = true;
newTextureAsset.metaData[this.tags!.fix] = true;
newTextureAsset.metaData[this.tags!.nomip] = true;
newTextureAsset.metaData.mIgnore = true;

assets.push(newTextureAsset);
Expand Down
2 changes: 1 addition & 1 deletion packages/assetpack/test/core/AssetWatcher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe('AssetWatcher', () =>

it('should have correct file state with a cache', async () =>
{
const testName = 'asset-watcher';
const testName = 'asset-watcher-file';
const inputDir = getInputDir(pkg, testName);

createFolder(
Expand Down
40 changes: 39 additions & 1 deletion packages/assetpack/test/image/Mipmap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,45 @@ describe('Mipmap', () =>
entry: inputDir, cacheLocation: getCacheDir(pkg, testName),
output: outputDir,
cache: false,
pipes: [mipmap()]
pipes: [mipmap({ fixedResolution: 'low' })]
});

await assetpack.run();

expect(existsSync(`${outputDir}/assets/test.png`)).toBe(false);
expect(existsSync(`${outputDir}/assets/[email protected]`)).toBe(true);
});

it('should prevent mipmaps', async () =>
{
const testName = 'mip-nomip';
const inputDir = getInputDir(pkg, testName);
const outputDir = getOutputDir(pkg, testName);

createFolder(
pkg,
{
name: testName,
files: [],
folders: [
{
name: 'assets{nomip}',
files: [
{
name: 'test.png',
content: assetPath('image/png-1.png'),
},
],
folders: [],
},
],
});

const assetpack = new AssetPack({
entry: inputDir, cacheLocation: getCacheDir(pkg, testName),
output: outputDir,
cache: false,
pipes: [mipmap({ fixedResolution: 'low' })]
});

await assetpack.run();
Expand Down
122 changes: 120 additions & 2 deletions packages/assetpack/test/spine/spineAtlasMipmap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,9 @@ describe('Atlas Mipmap', () =>
expect(existsSync(`${outputDir}/[email protected]`)).toBe(true);
});

it('should prevent mipmaps on file when tagged with fix', async () =>
it('should resize atlas to fixed resolution when tagged with fix', async () =>
{
const testName = 'mip-fixed';
const testName = 'mip-fixed-prevent';
const inputDir = getInputDir(pkg, testName);
const outputDir = getOutputDir(pkg, testName);

Expand All @@ -190,6 +190,14 @@ describe('Atlas Mipmap', () =>
name: 'dragon{spine}{fix}.atlas',
content: assetPath('spine/dragon.atlas'),
},
{
name: 'dragon{fix}.png',
content: assetPath('spine/dragon.png'),
},
{
name: 'dragon2{fix}.png',
content: assetPath('spine/dragon2.png'),
},
],
folders: [],
},
Expand All @@ -210,5 +218,115 @@ describe('Atlas Mipmap', () =>

expect(existsSync(`${outputDir}/assets/dragon.atlas`)).toBe(true);
expect(existsSync(`${outputDir}/assets/[email protected]`)).toBe(false);
expect(existsSync(`${outputDir}/assets/[email protected]`)).toBe(false);
expect(existsSync(`${outputDir}/assets/[email protected]`)).toBe(false);
expect(existsSync(`${outputDir}/assets/dragon.png`)).toBe(true);
expect(existsSync(`${outputDir}/assets/dragon2.png`)).toBe(true);
});

it('should resize atlas to low fixed resolution when tagged with fix', async () =>
{
const testName = 'mip-fixed-res';
const inputDir = getInputDir(pkg, testName);
const outputDir = getOutputDir(pkg, testName);

createFolder(
pkg,
{
name: testName,
files: [],
folders: [
{
name: 'assets',
files: [
{
name: 'dragon{spine}{fix}.atlas',
content: assetPath('spine/dragon.atlas'),
},
{
name: 'dragon{fix}.png',
content: assetPath('spine/dragon.png'),
},
{
name: 'dragon2{fix}.png',
content: assetPath('spine/dragon2.png'),
},
],
folders: [],
},
],
});

const assetpack = new AssetPack({
entry: inputDir, cacheLocation: getCacheDir(pkg, testName),
output: outputDir,
cache: false,
pipes: [
mipmap({ fixedResolution: 'low' }),
spineAtlasMipmap({ fixedResolution: 'low' }),
]
});

await assetpack.run();

expect(existsSync(`${outputDir}/assets/dragon.atlas`)).toBe(false);
expect(existsSync(`${outputDir}/assets/[email protected]`)).toBe(true);
expect(existsSync(`${outputDir}/assets/[email protected]`)).toBe(true);
expect(existsSync(`${outputDir}/assets/[email protected]`)).toBe(true);
expect(existsSync(`${outputDir}/assets/dragon.png`)).toBe(false);
expect(existsSync(`${outputDir}/assets/dragon2.png`)).toBe(false);
});

it('should create no mipmaps', async () =>
{
const testName = 'mip-nomip';
const inputDir = getInputDir(pkg, testName);
const outputDir = getOutputDir(pkg, testName);

createFolder(
pkg,
{
name: testName,
files: [],
folders: [
{
name: 'assets',
files: [
{
name: 'dragon{spine}{nomip}.atlas',
content: assetPath('spine/dragon.atlas'),
},
{
name: 'dragon{nomip}.png',
content: assetPath('spine/dragon.png'),
},
{
name: 'dragon2{nomip}.png',
content: assetPath('spine/dragon2.png'),
},
],
folders: [],
},
],
});

const assetpack = new AssetPack({
entry: inputDir, cacheLocation: getCacheDir(pkg, testName),
output: outputDir,
cache: false,
pipes: [
mipmap({ fixedResolution: 'low' }),
spineAtlasMipmap({ fixedResolution: 'low' }),
]
});

await assetpack.run();

expect(existsSync(`${outputDir}/assets/dragon.atlas`)).toBe(true);
expect(existsSync(`${outputDir}/assets/[email protected]`)).toBe(false);
expect(existsSync(`${outputDir}/assets/[email protected]`)).toBe(false);
expect(existsSync(`${outputDir}/assets/[email protected]`)).toBe(false);
expect(existsSync(`${outputDir}/assets/dragon.png`)).toBe(true);
expect(existsSync(`${outputDir}/assets/dragon2.png`)).toBe(true);
});
});
Loading

0 comments on commit 23d8584

Please sign in to comment.