From 44b9ddd19f2ebb0d1c27b165b6d8959d22751351 Mon Sep 17 00:00:00 2001 From: Stanislav Felinskyi Date: Thu, 19 Sep 2024 18:26:35 +0300 Subject: [PATCH 1/4] Misc: interm commit --- .../src/spine/spineAtlasCacheBuster.ts | 106 ++++++++++++++---- 1 file changed, 85 insertions(+), 21 deletions(-) diff --git a/packages/assetpack/src/spine/spineAtlasCacheBuster.ts b/packages/assetpack/src/spine/spineAtlasCacheBuster.ts index 2e17ab3..d561df8 100644 --- a/packages/assetpack/src/spine/spineAtlasCacheBuster.ts +++ b/packages/assetpack/src/spine/spineAtlasCacheBuster.ts @@ -3,6 +3,14 @@ import { checkExt, findAssets } from '../core/index.js'; import { AtlasView } from './AtlasView.js'; import type { Asset, AssetPipe } from '../core/index.js'; +import { persistMessage } from '../core/logger/render.js'; + +type SpinsAsset = { + name: string; + directory: string; + atlas?: Asset; + json?: Asset; +}; /** * This should be used after the cache buster plugin in the pipes. @@ -18,36 +26,72 @@ import type { Asset, AssetPipe } from '../core/index.js'; * @param _options * @returns */ -export function spineAtlasCacheBuster(): AssetPipe -{ +export function spineAtlasCacheBuster(): AssetPipe { const defaultOptions = {}; const atlasFileToFix: Asset[] = []; + const potentialSpineAssetsToFix: SpinsAsset[] = []; + const atlasExt = '.atlas'; + const jsonExt = '.json'; return { folder: false, name: 'spine-cache-buster', defaultOptions, - test(asset: Asset, _options) - { - return checkExt(asset.path, '.atlas'); - }, + test(asset: Asset, _options) { + persistMessage(`TEST: (${asset.path}): isSuitable=${checkExt(asset.path, '.atlas')}`); - async transform(asset: Asset, _options) - { - atlasFileToFix.push(asset); + return checkExt(asset.path, atlasExt) || checkExt(asset.path, jsonExt); + }, + async transform(asset: Asset, _options) { + persistMessage( + `TRANSFORM: (${asset.filename}) (${getAssetFileNameWithoutHashAndExtension(asset)}) ${asset.directory}`, + ); + const name = getAssetFileNameWithoutHashAndExtension(asset); + let spineAsset: SpinsAsset | undefined = potentialSpineAssetsToFix.find( + (item) => item.name === name && item.directory === asset.directory, + ); + if (spineAsset === undefined) { + spineAsset = { + name: name, + directory: asset.directory, + }; + potentialSpineAssetsToFix.push(spineAsset); + } + + if (asset.extension === atlasExt) { + spineAsset.atlas = asset; + } + + if (asset.extension === jsonExt) { + spineAsset.json = asset; + } + + if (asset.extension === '.atlas') { + atlasFileToFix.push(asset); + } return [asset]; }, - async finish(asset: Asset) - { + async finish(asset: Asset) { + persistMessage(`FINISH: (${asset.path})`); + + persistMessage('PRINTING POTENTIAL SPINE'); + persistMessage('-----------------------'); + const spineAssetsToFix = potentialSpineAssetsToFix.filter( + (item) => item.atlas !== undefined && item.json !== undefined, + ); + spineAssetsToFix.forEach((item) => + persistMessage(`${item.name}: ${item.atlas?.filename} ${item.json?.filename}`), + ); + persistMessage('++++++++++++++++++++++++'); + // first we retrieve the final transformed children - so the atlas files that have been copied // to the output folder. const atlasAssets = atlasFileToFix.map((asset) => asset.getFinalTransformedChildren()[0]); - atlasAssets.forEach((atlasAsset) => - { + atlasAssets.forEach((atlasAsset) => { // we are going to replace the textures in the atlas file with the new cache busted textures // as we do this, the hash of the atlas file will change, so we need to update the path // and also remove the original file. @@ -55,30 +99,50 @@ export function spineAtlasCacheBuster(): AssetPipe const originalHash = atlasAsset.hash; const originalPath = atlasAsset.path; + persistMessage(`${atlasAsset.filename}: HASH=${originalHash} PATH=${originalPath}`); + const atlasView = new AtlasView(atlasAsset.buffer); - atlasView.getTextures().forEach((texture) => - { - const textureAssets = findAssets((asset) => - asset.filename === texture, asset, true); + atlasView.getTextures().forEach((texture) => { + const textureAssets = findAssets((asset) => asset.filename === texture, asset, true); + // const jsons = findAssets((asset) => asset.extension === '.json', asset, true); + + // persistMessage(`Textures ${textureAssets.length}`); + // textureAssets.forEach((t) => + // persistMessage(`${t.filename}: HASH=${t.hash} PATH=${t.path} EXT=${t.extension}`), + // ); + + // persistMessage(`jsons ${jsons.length}`); + // jsons.forEach((t) => + // persistMessage(`${t.filename}: HASH=${t.hash} PATH=${t.path} EXT=${t.extension}`), + // ); + + // persistMessage( + // `FIRST TEXTURE: HASH=${textureAssets[0].hash} PATH=${textureAssets[0].path} EXT=${textureAssets[0].extension}`, + // ); // last transformed child is the renamed texture const cacheBustedTexture = textureAssets[0].getFinalTransformedChildren()[0]; - + // persistMessage( + // `cacheBustedTexture: HASH=${cacheBustedTexture.hash} PATH=${cacheBustedTexture.path} EXT=${cacheBustedTexture.extension}`, + // ); atlasView.replaceTexture(texture, cacheBustedTexture.filename); }); atlasAsset.buffer = atlasView.buffer; - atlasAsset.path = atlasAsset.path.replace(originalHash, atlasAsset.hash); - fs.removeSync(originalPath); + (fs as any).removeSync(originalPath); // rewrite.. fs.writeFileSync(atlasAsset.path, atlasAsset.buffer); }); atlasFileToFix.length = 0; - } + }, }; } + +function getAssetFileNameWithoutHashAndExtension(asset: Asset): string { + return asset.filename.split('-')[0]; +} From f4bf09134570f1aa7b2732ec58bae3ed8e6d4897 Mon Sep 17 00:00:00 2001 From: Stanislav Felinskyi Date: Thu, 19 Sep 2024 18:40:06 +0300 Subject: [PATCH 2/4] Misc: first working prototype --- .../src/spine/spineAtlasCacheBuster.ts | 45 ++++++++----------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/packages/assetpack/src/spine/spineAtlasCacheBuster.ts b/packages/assetpack/src/spine/spineAtlasCacheBuster.ts index d561df8..58d5cf7 100644 --- a/packages/assetpack/src/spine/spineAtlasCacheBuster.ts +++ b/packages/assetpack/src/spine/spineAtlasCacheBuster.ts @@ -87,50 +87,41 @@ export function spineAtlasCacheBuster(): AssetPipe { ); persistMessage('++++++++++++++++++++++++'); - // first we retrieve the final transformed children - so the atlas files that have been copied - // to the output folder. - const atlasAssets = atlasFileToFix.map((asset) => asset.getFinalTransformedChildren()[0]); + - atlasAssets.forEach((atlasAsset) => { + spineAssetsToFix.forEach((spineAsset) => { // we are going to replace the textures in the atlas file with the new cache busted textures // as we do this, the hash of the atlas file will change, so we need to update the path // and also remove the original file. + // first we retrieve the final transformed children - so the atlas files that have been copied + // to the output folder. + const atlasAsset = spineAsset.atlas?.getFinalTransformedChildren()[0]; + const jsonAsset = spineAsset.json?.getFinalTransformedChildren()[0]; + if (atlasAsset === undefined) { + return; + } + if (jsonAsset === undefined) { + return; + } const originalHash = atlasAsset.hash; const originalPath = atlasAsset.path; - - persistMessage(`${atlasAsset.filename}: HASH=${originalHash} PATH=${originalPath}`); - const atlasView = new AtlasView(atlasAsset.buffer); atlasView.getTextures().forEach((texture) => { const textureAssets = findAssets((asset) => asset.filename === texture, asset, true); - // const jsons = findAssets((asset) => asset.extension === '.json', asset, true); - - // persistMessage(`Textures ${textureAssets.length}`); - // textureAssets.forEach((t) => - // persistMessage(`${t.filename}: HASH=${t.hash} PATH=${t.path} EXT=${t.extension}`), - // ); - - // persistMessage(`jsons ${jsons.length}`); - // jsons.forEach((t) => - // persistMessage(`${t.filename}: HASH=${t.hash} PATH=${t.path} EXT=${t.extension}`), - // ); - - // persistMessage( - // `FIRST TEXTURE: HASH=${textureAssets[0].hash} PATH=${textureAssets[0].path} EXT=${textureAssets[0].extension}`, - // ); - // last transformed child is the renamed texture const cacheBustedTexture = textureAssets[0].getFinalTransformedChildren()[0]; - // persistMessage( - // `cacheBustedTexture: HASH=${cacheBustedTexture.hash} PATH=${cacheBustedTexture.path} EXT=${cacheBustedTexture.extension}`, - // ); atlasView.replaceTexture(texture, cacheBustedTexture.filename); }); atlasAsset.buffer = atlasView.buffer; - atlasAsset.path = atlasAsset.path.replace(originalHash, atlasAsset.hash); + + // TODO CHECK FOR OPTIONS + + + // atlasAsset.path = atlasAsset.path.replace(originalHash, atlasAsset.hash); + atlasAsset.path = atlasAsset.path.replace(originalHash, jsonAsset.hash); (fs as any).removeSync(originalPath); From 58ef6169f9c68447e2a7000d7258a25edaa75c40 Mon Sep 17 00:00:00 2001 From: Stanislav Felinskyi Date: Thu, 19 Sep 2024 19:01:01 +0300 Subject: [PATCH 3/4] Misc: created an option to have the same file name for atlas as json file --- .../src/spine/spineAtlasCacheBuster.ts | 54 ++++++++----------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/packages/assetpack/src/spine/spineAtlasCacheBuster.ts b/packages/assetpack/src/spine/spineAtlasCacheBuster.ts index 58d5cf7..4e54ff6 100644 --- a/packages/assetpack/src/spine/spineAtlasCacheBuster.ts +++ b/packages/assetpack/src/spine/spineAtlasCacheBuster.ts @@ -1,10 +1,8 @@ import fs from 'fs-extra'; +import type { Asset, AssetPipe } from '../core/index.js'; import { checkExt, findAssets } from '../core/index.js'; import { AtlasView } from './AtlasView.js'; -import type { Asset, AssetPipe } from '../core/index.js'; -import { persistMessage } from '../core/logger/render.js'; - type SpinsAsset = { name: string; directory: string; @@ -12,6 +10,14 @@ type SpinsAsset = { json?: Asset; }; +export interface SpineAtlasCacheBusterOptions { + /** + * Set this value to true if .atlas file and .json file must have the same file names (including the HASH in the name). + * This is important for the Pixi spineTextureAtlasLoader function + */ + jasonAndAltasHasTheSameNames?: boolean; +} + /** * This should be used after the cache buster plugin in the pipes. * As it relies on the cache buster plugin to have already cache busted all files. @@ -26,10 +32,14 @@ type SpinsAsset = { * @param _options * @returns */ -export function spineAtlasCacheBuster(): AssetPipe { - const defaultOptions = {}; +export function spineAtlasCacheBuster( + _options: SpineAtlasCacheBusterOptions = {}, +): AssetPipe { + const defaultOptions = { + jasonAndAltasHasTheSameNames: false, + ..._options, + }; - const atlasFileToFix: Asset[] = []; const potentialSpineAssetsToFix: SpinsAsset[] = []; const atlasExt = '.atlas'; const jsonExt = '.json'; @@ -39,15 +49,10 @@ export function spineAtlasCacheBuster(): AssetPipe { name: 'spine-cache-buster', defaultOptions, test(asset: Asset, _options) { - persistMessage(`TEST: (${asset.path}): isSuitable=${checkExt(asset.path, '.atlas')}`); - return checkExt(asset.path, atlasExt) || checkExt(asset.path, jsonExt); }, async transform(asset: Asset, _options) { - persistMessage( - `TRANSFORM: (${asset.filename}) (${getAssetFileNameWithoutHashAndExtension(asset)}) ${asset.directory}`, - ); const name = getAssetFileNameWithoutHashAndExtension(asset); let spineAsset: SpinsAsset | undefined = potentialSpineAssetsToFix.find( (item) => item.name === name && item.directory === asset.directory, @@ -68,26 +73,13 @@ export function spineAtlasCacheBuster(): AssetPipe { spineAsset.json = asset; } - if (asset.extension === '.atlas') { - atlasFileToFix.push(asset); - } return [asset]; }, - async finish(asset: Asset) { - persistMessage(`FINISH: (${asset.path})`); - - persistMessage('PRINTING POTENTIAL SPINE'); - persistMessage('-----------------------'); + async finish(asset: Asset, options) { const spineAssetsToFix = potentialSpineAssetsToFix.filter( (item) => item.atlas !== undefined && item.json !== undefined, ); - spineAssetsToFix.forEach((item) => - persistMessage(`${item.name}: ${item.atlas?.filename} ${item.json?.filename}`), - ); - persistMessage('++++++++++++++++++++++++'); - - spineAssetsToFix.forEach((spineAsset) => { // we are going to replace the textures in the atlas file with the new cache busted textures @@ -117,11 +109,11 @@ export function spineAtlasCacheBuster(): AssetPipe { atlasAsset.buffer = atlasView.buffer; - // TODO CHECK FOR OPTIONS - - - // atlasAsset.path = atlasAsset.path.replace(originalHash, atlasAsset.hash); - atlasAsset.path = atlasAsset.path.replace(originalHash, jsonAsset.hash); + if (options.jasonAndAltasHasTheSameNames) { + atlasAsset.path = atlasAsset.path.replace(originalHash, jsonAsset.hash); + } else { + atlasAsset.path = atlasAsset.path.replace(originalHash, atlasAsset.hash); + } (fs as any).removeSync(originalPath); @@ -129,7 +121,7 @@ export function spineAtlasCacheBuster(): AssetPipe { fs.writeFileSync(atlasAsset.path, atlasAsset.buffer); }); - atlasFileToFix.length = 0; + potentialSpineAssetsToFix.length = 0; }, }; } From 571c88744472aec81cd6b83a0d9f340eaff9481f Mon Sep 17 00:00:00 2001 From: Stanislav Felinskyi Date: Thu, 19 Sep 2024 19:34:00 +0300 Subject: [PATCH 4/4] misc: fixed typo in options --- packages/assetpack/src/spine/spineAtlasCacheBuster.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/assetpack/src/spine/spineAtlasCacheBuster.ts b/packages/assetpack/src/spine/spineAtlasCacheBuster.ts index 4e54ff6..3ae8720 100644 --- a/packages/assetpack/src/spine/spineAtlasCacheBuster.ts +++ b/packages/assetpack/src/spine/spineAtlasCacheBuster.ts @@ -15,7 +15,7 @@ export interface SpineAtlasCacheBusterOptions { * Set this value to true if .atlas file and .json file must have the same file names (including the HASH in the name). * This is important for the Pixi spineTextureAtlasLoader function */ - jasonAndAltasHasTheSameNames?: boolean; + jsonAndAltasHasTheSameNames?: boolean; } /** @@ -36,7 +36,7 @@ export function spineAtlasCacheBuster( _options: SpineAtlasCacheBusterOptions = {}, ): AssetPipe { const defaultOptions = { - jasonAndAltasHasTheSameNames: false, + jsonAndAltasHasTheSameNames: false, ..._options, }; @@ -109,7 +109,7 @@ export function spineAtlasCacheBuster( atlasAsset.buffer = atlasView.buffer; - if (options.jasonAndAltasHasTheSameNames) { + if (options.jsonAndAltasHasTheSameNames) { atlasAsset.path = atlasAsset.path.replace(originalHash, jsonAsset.hash); } else { atlasAsset.path = atlasAsset.path.replace(originalHash, atlasAsset.hash);