Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add frame names to spritesheet manifest data #84

Merged
merged 14 commits into from
Sep 3, 2024
43 changes: 40 additions & 3 deletions packages/assetpack/src/core/Asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export class Asset

metaData: Record<string, any> = {};
inheritedMetaData: Record<string, any> = {};
allMetaData: Record<string, any> = {};
transformData: Record<string, any> = {};

settings?: Record<string, any>;
Expand Down Expand Up @@ -63,7 +62,6 @@ export class Asset
asset.parent = this;

asset.inheritedMetaData = { ...this.inheritedMetaData, ...this.metaData };
asset.allMetaData = { ...asset.inheritedMetaData, ...asset.metaData };
asset.transformData = { ...this.transformData, ...asset.transformData };
}

Expand All @@ -87,12 +85,16 @@ export class Asset
asset.transformParent = this;

asset.inheritedMetaData = { ...this.inheritedMetaData, ...this.metaData };
asset.allMetaData = { ...asset.inheritedMetaData, ...asset.metaData };
asset.transformData = { ...this.transformData, ...asset.transformData };

asset.settings = this.settings;
}

get allMetaData()
{
return { ...this.inheritedMetaData, ...this.metaData };
}

get state()
{
return this._state;
Expand Down Expand Up @@ -251,5 +253,40 @@ export class Asset
this.children[i].releaseChildrenBuffers();
}
}

/**
* Get the public meta data for this asset
* This will exclude any internal data
*/
getPublicMetaData(internalPipeData: Record<string, any>)
{
const internalKeys = new Set(Object.keys(internalPipeData));
const metaData = Object.keys(this.allMetaData).reduce((result: Record<string, any>, key) =>
{
if (!internalKeys.has(key))
{
result[key] = this.allMetaData[key];
}

return result;
}, {} as Record<string, any>);

return metaData;
}

getInternalMetaData(internalPipeData: Record<string, any>)
{
const res: Record<string, any> = {};

Object.keys(internalPipeData).forEach((key) =>
{
if (this.allMetaData[key])
{
res[key] = this.allMetaData[key];
}
});

return res;
}
}

7 changes: 6 additions & 1 deletion packages/assetpack/src/core/pipes/AssetPipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export type DeepRequired<T> = T extends Primitive
};
export interface PluginOptions {}

export interface AssetPipe<OPTIONS=Record<string, any>, TAGS extends string = string>
export interface AssetPipe<OPTIONS=Record<string, any>, TAGS extends string = string, INTERNAL_TAGS extends string = string>
{
/** Whether the process runs on a folder */
folder?: boolean;
Expand All @@ -31,6 +31,11 @@ export interface AssetPipe<OPTIONS=Record<string, any>, TAGS extends string = st
/** Tags that can be used to control the plugin */
tags?: Record<TAGS, string>;

/**
* Any tags here will not be placed in the manifest data.
*/
internalTags?: Record<INTERNAL_TAGS, string>;

/**
* Called once at the start.
* @param asser - the root asset
Expand Down
6 changes: 6 additions & 0 deletions packages/assetpack/src/core/pipes/PipeSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ export class PipeSystem

assetSettings: AssetSettings[] = [];

internalMetaData: Record<string, any> = {
copy: 'copy',
ignore: 'ignore',
};

constructor(options: PipeSystemOptions)
{
const pipes = [];
Expand All @@ -49,6 +54,7 @@ export class PipeSystem
options.pipes.flat().forEach((pipe) =>
{
this.pipeHash[pipe.name] = pipe;
this.internalMetaData = { ...this.internalMetaData, ...Object.values(pipe.internalTags ?? pipe.tags ?? {}).reduce((acc, tag) => ({ ...acc, [tag]: true }), {}) };
});

this.pipes = pipes;
Expand Down
2 changes: 1 addition & 1 deletion packages/assetpack/src/image/compress.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export function compress(options: CompressOptions = {}): AssetPipe<CompressOptio
},
async transform(asset: Asset, options)
{
const shouldCompress = compress && !asset.metaData.nc;
const shouldCompress = compress && !asset.metaData[this.tags!.nc];

if (!shouldCompress)
{
Expand Down
62 changes: 56 additions & 6 deletions packages/assetpack/src/manifest/pixiManifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,49 @@ export interface PixiManifestEntry

export interface PixiManifestOptions extends PluginOptions
{
/**
* The output location for the manifest file.
*/
output?: string;
/**
* if true, the alias will be created with the basename of the file.
*/
createShortcuts?: boolean;
/**
* if true, the extensions will be removed from the alias names.
*/
trimExtensions?: boolean;
/**
* if true, the metaData will be outputted in the data field of the manifest.
*/
includeMetaData?: boolean;
/**
* if true, the all tags will be outputted in the data.tags field of the manifest.
* If false, only internal tags will be outputted to the data.tags field. All other tags will be outputted to the data field directly.
* @example
* ```json
* {
* "bundles": [
* {
* "name": "default",
* "assets": [
* {
* "alias": ["test"],
* "src": ["test.png"],
* "data": {
* "tags": {
* "nc": true,
* "customTag": true // this tag will be outputted to the data field directly instead of the data.tags field
* }
* }
* }
* ]
* }
* ]
* }
* @default true
*/
legacyMetaDataOutput?: boolean;
}

export function pixiManifest(_options: PixiManifestOptions = {}): AssetPipe<PixiManifestOptions, 'manifest' | 'mIgnore'>
Expand All @@ -45,6 +84,7 @@ export function pixiManifest(_options: PixiManifestOptions = {}): AssetPipe<Pixi
createShortcuts: false,
trimExtensions: false,
includeMetaData: true,
legacyMetaDataOutput: true,
..._options,
},
tags: {
Expand Down Expand Up @@ -72,7 +112,8 @@ export function pixiManifest(_options: PixiManifestOptions = {}): AssetPipe<Pixi
pipeSystem.entryPath,
manifest.bundles,
defaultBundle,
this.tags!
this.tags!,
pipeSystem.internalMetaData
);
filterUniqueNames(manifest);
await fs.writeJSON(newFileName, manifest, { spaces: 2 });
Expand Down Expand Up @@ -109,7 +150,8 @@ function collectAssets(
entryPath = '',
bundles: PixiBundle[],
bundle: PixiBundle,
tags: AssetPipe<null, 'manifest' | 'mIgnore'>['tags']
tags: AssetPipe<null, 'manifest' | 'mIgnore'>['tags'],
internalTags: Record<string, any>
)
{
if (asset.skip) return;
Expand Down Expand Up @@ -137,20 +179,28 @@ function collectAssets(

if (finalManifestAssets.length === 0) return;

const metadata = {
tags: { ...asset.getInternalMetaData(internalTags) },
...asset.getPublicMetaData(internalTags)
} as Record<string, any>;

if (options.legacyMetaDataOutput)
{
metadata.tags = asset.allMetaData;
}

bundleAssets.push({
alias: getShortNames(stripTags(path.relative(entryPath, asset.path)), options),
src: finalManifestAssets
.map((finalAsset) => path.relative(outputPath, finalAsset.path))
.sort((a, b) => b.localeCompare(a)),
data: options.includeMetaData ? {
tags: asset.allMetaData
} : undefined
data: options.includeMetaData ? metadata : undefined
});
}

asset.children.forEach((child) =>
{
collectAssets(child, options, outputPath, entryPath, bundles, localBundle, tags);
collectAssets(child, options, outputPath, entryPath, bundles, localBundle, tags, internalTags);
});

// for all assets.. check for atlas and remove them from the bundle..
Expand Down
11 changes: 11 additions & 0 deletions packages/assetpack/src/texture-packer/texturePacker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export interface TexturePackerOptions extends PluginOptions
/** The maximum size a sprite sheet can be before its split out */
maximumTextureSize?: number;
}
/** If true, the frame names for the sprite sheet will be added to the asset meta data. */
addFrameNames?: boolean;
}

function checkForTexturePackerShortcutClashes(
Expand Down Expand Up @@ -67,6 +69,7 @@ export function texturePacker(_options: TexturePackerOptions = {}): AssetPipe<Te
nameStyle: 'relative',
..._options.texturePacker,
},
addFrameNames: false,
},
tags: {
tps: 'tps',
Expand Down Expand Up @@ -130,6 +133,7 @@ export function texturePacker(_options: TexturePackerOptions = {}): AssetPipe<Te
const assets: Asset[] = [];

let checkedForClashes = false;
const imageNames: string[] = [];

Object.values(resolutionHash).sort((a, b) => b - a).forEach((resolution) =>
{
Expand Down Expand Up @@ -160,6 +164,8 @@ export function texturePacker(_options: TexturePackerOptions = {}): AssetPipe<Te

const { json, name: jsonName } = out.jsons[i];

imageNames.push(...Object.keys(json.frames));

const jsonAsset = createNewAssetAt(asset, jsonName);

if (!checkedForClashes)
Expand All @@ -184,6 +190,11 @@ export function texturePacker(_options: TexturePackerOptions = {}): AssetPipe<Te

await Promise.all(promises);

if (options.addFrameNames)
{
asset.metaData.frameNames = imageNames;
}

return assets;
},

Expand Down
4 changes: 3 additions & 1 deletion packages/assetpack/src/webfont/sdf.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fs from 'fs-extra';
import generateBMFont from 'msdf-bmfont-xml';
import { checkExt, createNewAssetAt, stripTags } from '../core/index.js';
import { checkExt, createNewAssetAt, path, stripTags } from '../core/index.js';

import type { BitmapFontOptions } from 'msdf-bmfont-xml';
import type { Asset, AssetPipe, PluginOptions } from '../core/index.js';
Expand Down Expand Up @@ -33,6 +33,8 @@ function signedFont(
{
const newFileName = stripTags(asset.filename.replace(/\.(ttf)$/i, ''));

// set the family name to the filename if it doesn't exist
asset.metaData.family ??= path.trimExt(asset.filename);
const { font, textures } = await GenerateFont(asset.path, {
...options.font,
filename: newFileName,
Expand Down
6 changes: 4 additions & 2 deletions packages/assetpack/src/webfont/webfont.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ export function webfont(): AssetPipe<any, 'wf'>
buffer = fonts.svg.to.woff2(asset.path);
break;
default:
throw new Error(`{Assetpack] Unsupported font type: ${ext}`);
break;
throw new Error(`{AssetPack] Unsupported font type: ${ext}`);
}

const newFileName = asset.filename.replace(/\.(otf|ttf|svg)$/i, '.woff2');
Expand All @@ -44,6 +43,9 @@ export function webfont(): AssetPipe<any, 'wf'>

newAsset.buffer = buffer;

// set the family name to the filename if it doesn't exist
asset.metaData.family ??= path.trimExt(asset.filename);

return [newAsset];
}
};
Expand Down
1 change: 1 addition & 0 deletions packages/assetpack/test/manifest/Manifest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ describe('Manifest', () =>
alias: ['spine/dragon.atlas'],
src: ['spine/dragon@0.5x.atlas', 'spine/dragon.atlas'],
data: {
spine: true,
tags: {
spine: true,
},
Expand Down
3 changes: 3 additions & 0 deletions packages/assetpack/test/spine/spineAtlasManifest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ describe('Atlas Manifest', () =>
'dragon.atlas'
],
data: {
spine: true,
tags: {
spine: true
}
Expand Down Expand Up @@ -182,6 +183,7 @@ describe('Atlas Manifest', () =>
'dragon.atlas'
],
data: {
spine: true,
tags: {
spine: true
}
Expand All @@ -206,6 +208,7 @@ describe('Atlas Manifest', () =>
'nested/dragon.atlas'
],
data: {
spine: true,
tags: {
spine: true
}
Expand Down
Loading