Skip to content

Commit

Permalink
chore: improve types for asset parsers (#10572)
Browse files Browse the repository at this point in the history
* wip

* fix: spritesheet resolver not working

* add test

* chore: improve types for asset parsers

* update cache parsers
  • Loading branch information
Zyie committed May 24, 2024
1 parent 0010965 commit 2673b56
Show file tree
Hide file tree
Showing 20 changed files with 118 additions and 74 deletions.
43 changes: 28 additions & 15 deletions src/assets/AssetExtension.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,34 @@
import type { ExtensionType } from '../extensions/Extensions';
import type { CacheParser } from './cache/CacheParser';
import type { FormatDetectionParser } from './detections/types';
import type { LoaderParser } from './loader/parsers/LoaderParser';
import type { LoaderParserAdvanced } from './loader/parsers/LoaderParser';
import type { ResolveURLParser } from './resolver/types';

/**
* A more verbose version of the AssetExtension,
* allowing you to set the cached, loaded, parsed, and unloaded asset separately
* @memberof assets
*/
interface AssetExtensionAdvanced<
ASSET = any,
PARSED_ASSET = ASSET,
UNLOAD_ASSET = ASSET,
CACHE_ASSET = ASSET,
META_DATA = any
>
{
/** The type of extension */
extension: ExtensionType.Asset,
/** the asset loader */
loader?: LoaderParserAdvanced<ASSET, PARSED_ASSET, UNLOAD_ASSET, META_DATA>,
/** the asset resolve parser */
resolver?: Partial<ResolveURLParser>,
/** the asset cache parser */
cache?: Partial<CacheParser<CACHE_ASSET>>,
/** the asset format detection parser */
detection?: Partial<FormatDetectionParser>,
}

/**
* This developer convenience object allows developers to group
* together the various asset parsers into a single object.
Expand Down Expand Up @@ -59,18 +84,6 @@ import type { ResolveURLParser } from './resolver/types';
* }
* @memberof assets
*/
interface AssetExtension<ASSET = any, META_DATA = any>
{
/** The type of extension */
extension: ExtensionType.Asset,
/** the asset loader */
loader?: LoaderParser<ASSET, META_DATA>,
/** the asset resolve parser */
resolver?: Partial<ResolveURLParser>,
/** the asset cache parser */
cache?: Partial<CacheParser<ASSET>>,
/** the asset format detection parser */
detection?: Partial<FormatDetectionParser>,
}
interface AssetExtension<ASSET = any, META_DATA = any> extends AssetExtensionAdvanced<ASSET, META_DATA>{}

export type { AssetExtension };
export type { AssetExtension, AssetExtensionAdvanced };
5 changes: 4 additions & 1 deletion src/assets/cache/parsers/cacheTextureArray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import type { CacheParser } from '../CacheParser';
* @memberof assets
*/
export const cacheTextureArray: CacheParser<Texture[]> = {
extension: ExtensionType.CacheParser,
extension: {
type: ExtensionType.CacheParser,
name: 'cacheTextureArray',
},

test: (asset: any[]) => Array.isArray(asset) && asset.every((t) => t instanceof Texture),

Expand Down
54 changes: 32 additions & 22 deletions src/assets/loader/parsers/LoaderParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,14 @@ export enum LoaderParserPriority
High = 2,
}

/**
* The interface to define a loader parser *(all functions are optional)*.
*
* When you create a `parser` object, the flow for every asset loaded is:
*
* 1. `parser.test()` - Each URL to load will be tested here, if the test is passed the assets are
* loaded using the load function below. Good place to test for things like file extensions!
* 2. `parser.load()` - This is the promise that loads the URL provided resolves with a loaded asset
* if returned by the parser.
* 3. `parser.testParse()` - This function is used to test if the parse function should be run on the
* asset If this returns true then parse is called with the asset
* 4. `parse.parse()` - Gets called on the asset it testParse passes. Useful to convert a raw asset
* into something more useful
*
* <br/>
* Some loaders may only be used for parsing, some only for loading, and some for both!
* @memberof assets
*/
export interface LoaderParser<ASSET = any, META_DATA = any, CONFIG = Record<string, any>>
/** A more verbose version of the LoaderParser, allowing you to set the loaded, parsed, and unloaded asset separately */
export interface LoaderParserAdvanced<
ASSET = any,
PARSED_ASSET = ASSET,
UNLOAD_ASSET = ASSET,
META_DATA = any,
CONFIG = Record<string, any>
>
{
/** Should be ExtensionType.LoaderParser */
extension?: ExtensionMetadata;
Expand Down Expand Up @@ -65,7 +54,7 @@ export interface LoaderParser<ASSET = any, META_DATA = any, CONFIG = Record<stri
* @param resolvedAsset - Any custom additional information relevant to the asset being loaded
* @param loader - The loader instance
*/
load?: <T>(url: string, resolvedAsset?: ResolvedAsset<META_DATA>, loader?: Loader) => Promise<T>;
load?: <T>(url: string, resolvedAsset?: ResolvedAsset<META_DATA>, loader?: Loader) => Promise<ASSET | T>;

/**
* This function is used to test if the parse function should be run on the asset
Expand All @@ -82,7 +71,7 @@ export interface LoaderParser<ASSET = any, META_DATA = any, CONFIG = Record<stri
* @param resolvedAsset - Any custom additional information relevant to the asset being loaded
* @param loader - The loader instance
*/
parse?: <T>(asset: ASSET, resolvedAsset?: ResolvedAsset<META_DATA>, loader?: Loader) => Promise<T>;
parse?: <T>(asset: ASSET, resolvedAsset?: ResolvedAsset<META_DATA>, loader?: Loader) => Promise<PARSED_ASSET | T>;

/**
* If an asset is parsed using this parser, the unload function will be called when the user requests an asset
Expand All @@ -91,5 +80,26 @@ export interface LoaderParser<ASSET = any, META_DATA = any, CONFIG = Record<stri
* @param resolvedAsset - Any custom additional information relevant to the asset being loaded
* @param loader - The loader instance
*/
unload?: (asset: ASSET, resolvedAsset?: ResolvedAsset<META_DATA>, loader?: Loader) => Promise<void>;
unload?: (asset: UNLOAD_ASSET, resolvedAsset?: ResolvedAsset<META_DATA>, loader?: Loader) => Promise<void> | void;
}

/**
* The interface to define a loader parser *(all functions are optional)*.
*
* When you create a `parser` object, the flow for every asset loaded is:
*
* 1. `parser.test()` - Each URL to load will be tested here, if the test is passed the assets are
* loaded using the load function below. Good place to test for things like file extensions!
* 2. `parser.load()` - This is the promise that loads the URL provided resolves with a loaded asset
* if returned by the parser.
* 3. `parser.testParse()` - This function is used to test if the parse function should be run on the
* asset If this returns true then parse is called with the asset
* 4. `parse.parse()` - Gets called on the asset it testParse passes. Useful to convert a raw asset
* into something more useful
*
* <br/>
* Some loaders may only be used for parsing, some only for loading, and some for both!
* @memberof assets
*/
export interface LoaderParser<ASSET = any, META_DATA = any, CONFIG = Record<string, any>>
extends LoaderParserAdvanced<ASSET, ASSET, ASSET, META_DATA, CONFIG> {}
2 changes: 1 addition & 1 deletion src/assets/loader/parsers/loadJson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ export const loadJson = {

return json as T;
},
} as LoaderParser;
} satisfies LoaderParser<string>;
3 changes: 2 additions & 1 deletion src/assets/loader/parsers/loadTxt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const loadTxt = {
extension: {
type: ExtensionType.LoadParser,
priority: LoaderParserPriority.Low,
name: 'loadTxt',
},

test(url: string): boolean
Expand All @@ -35,4 +36,4 @@ export const loadTxt = {

return txt;
},
} as LoaderParser;
} satisfies LoaderParser<string>;
2 changes: 1 addition & 1 deletion src/assets/loader/parsers/loadWebFont.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,4 @@ export const loadWebFont = {
DOMAdapter.get().getFontFaceSet().delete(t);
});
}
} as LoaderParser<FontFace | FontFace[]>;
} satisfies LoaderParser<FontFace | FontFace[]>;
3 changes: 2 additions & 1 deletion src/assets/loader/parsers/textures/loadSVG.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const loadSvg = {
extension: {
type: ExtensionType.LoadParser,
priority: LoaderParserPriority.Low,
name: 'loadSVG',
},

name: 'loadSVG',
Expand Down Expand Up @@ -81,7 +82,7 @@ export const loadSvg = {
asset.destroy(true);
}

} as LoaderParser<Texture | GraphicsContext, TextureSourceOptions, LoadSVGConfig>;
} satisfies LoaderParser<Texture | GraphicsContext, TextureSourceOptions & LoadSVGConfig>;

async function loadAsTexture(
url: string,
Expand Down
3 changes: 2 additions & 1 deletion src/assets/loader/parsers/textures/loadTextures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export const loadTextures = {
extension: {
type: ExtensionType.LoadParser,
priority: LoaderParserPriority.High,
name: 'loadTextures',
},

config: {
Expand Down Expand Up @@ -167,4 +168,4 @@ export const loadTextures = {
{
texture.destroy(true);
}
} as LoaderParser<Texture, TextureSourceOptions, LoadTextureConfig>;
} satisfies LoaderParser<Texture, TextureSourceOptions, LoadTextureConfig>;
5 changes: 2 additions & 3 deletions src/assets/loader/parsers/textures/loadVideoTextures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,9 @@ export const loadVideoTextures = {

extension: {
type: ExtensionType.LoadParser,
name: 'loadVideo',
},

config: null,

test(url: string): boolean
{
const isValidDataUrl = checkDataUrl(url, validVideoMIMEs);
Expand Down Expand Up @@ -223,4 +222,4 @@ export const loadVideoTextures = {
{
texture.destroy(true);
}
} as LoaderParser<Texture, VideoSourceOptions, null>;
} satisfies LoaderParser<Texture, VideoSourceOptions>;
3 changes: 2 additions & 1 deletion src/assets/resolver/parsers/resolveJsonUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ export const resolveJsonUrl = {
extension: {
type: ExtensionType.ResolveParser,
priority: -2,
name: 'resolveJson',
},
test: (value: string): boolean =>
Resolver.RETINA_PREFIX.test(value) && value.endsWith('.json'),
parse: resolveTextureUrl.parse,
} as ResolveURLParser;
} satisfies ResolveURLParser;
10 changes: 6 additions & 4 deletions src/assets/resolver/parsers/resolveTextureUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@ import { ExtensionType } from '../../../extensions/Extensions';
import { loadTextures } from '../../loader/parsers/textures/loadTextures';
import { Resolver } from '../Resolver';

import type { UnresolvedAsset } from '../../types';
import type { ResolveURLParser } from '../types';

/**
* A parser that will resolve a texture url
* @memberof assets
*/
export const resolveTextureUrl = {
extension: ExtensionType.ResolveParser,
extension: {
type: ExtensionType.ResolveParser,
name: 'resolveTexture',
},
test: loadTextures.test,
parse: (value: string): UnresolvedAsset =>
parse: (value: string) =>
({
resolution: parseFloat(Resolver.RETINA_PREFIX.exec(value)?.[1] ?? '1'),
format: value.split('.').pop(),
src: value,
}),
} as ResolveURLParser;
} satisfies ResolveURLParser;
2 changes: 1 addition & 1 deletion src/assets/resolver/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ export interface ResolveURLParser
/** the test to perform on the url to determine if it should be parsed */
test: (url: string) => boolean;
/** the function that will convert the url into an object */
parse: (value: string) => ResolvedAsset;
parse: (value: string) => ResolvedAsset & {[key: string]: any};
}
4 changes: 2 additions & 2 deletions src/compressed-textures/basis/loadBasis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const loadBasis = {
extension: {
type: ExtensionType.LoadParser,
priority: LoaderParserPriority.High,
name: 'loadBasis',
},

name: 'loadBasis',
Expand Down Expand Up @@ -49,5 +50,4 @@ export const loadBasis = {
}
}

} as LoaderParser<Texture | Texture[], TextureSourceOptions>;

} satisfies LoaderParser<Texture | Texture[], TextureSourceOptions>;
3 changes: 2 additions & 1 deletion src/compressed-textures/dds/loadDDS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const loadDDS = {
extension: {
type: ExtensionType.LoadParser,
priority: LoaderParserPriority.High,
name: 'loadDDS',
},

name: 'loadDDS',
Expand Down Expand Up @@ -53,5 +54,5 @@ export const loadDDS = {
}
}

} as LoaderParser<Texture | Texture[], TextureSourceOptions>;
} satisfies LoaderParser<Texture | Texture[], TextureSourceOptions>;

3 changes: 2 additions & 1 deletion src/compressed-textures/ktx/loadKTX.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const loadKTX = {
extension: {
type: ExtensionType.LoadParser,
priority: LoaderParserPriority.High,
name: 'loadKTX',
},

name: 'loadKTX',
Expand Down Expand Up @@ -53,5 +54,5 @@ export const loadKTX = {
}
}

} as LoaderParser<Texture | Texture[], TextureSourceOptions>;
} satisfies LoaderParser<Texture | Texture[], TextureSourceOptions>;

5 changes: 3 additions & 2 deletions src/compressed-textures/ktx2/loadKTX2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const loadKTX2 = {
extension: {
type: ExtensionType.LoadParser,
priority: LoaderParserPriority.High,
name: 'loadKTX2',
},

name: 'loadKTX2',
Expand All @@ -37,7 +38,7 @@ export const loadKTX2 = {
return createTexture(compressedTextureSource, loader, url);
},

unload(texture: Texture | Texture[]): void
async unload(texture: Texture | Texture[]): Promise<void>
{
if (Array.isArray(texture))
{
Expand All @@ -49,5 +50,5 @@ export const loadKTX2 = {
}
}

} as LoaderParser<Texture | Texture[], TextureSourceOptions>;
} satisfies LoaderParser<Texture | Texture[], TextureSourceOptions>;

5 changes: 2 additions & 3 deletions src/compressed-textures/shared/resolveCompressedTextureUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ import { checkExtension } from '../../assets/utils/checkExtension';
import { ExtensionType } from '../../extensions/Extensions';

import type { ResolveURLParser } from '../../assets/resolver/types';
import type { UnresolvedAsset } from '../../assets/types';

export const validFormats = ['basis', 'bc7', 'bc6h', 'astc', 'etc2', 'bc5', 'bc4', 'bc3', 'bc2', 'bc1', 'eac'];

export const resolveCompressedTextureUrl = {
extension: ExtensionType.ResolveParser,
test: (value: string) =>
checkExtension(value, ['.ktx', '.ktx2', '.dds']),
parse: (value: string): UnresolvedAsset =>
parse: (value: string) =>
{
let format;

Expand All @@ -37,4 +36,4 @@ export const resolveCompressedTextureUrl = {
src: value,
};
}
} as ResolveURLParser;
} satisfies ResolveURLParser;
Loading

0 comments on commit 2673b56

Please sign in to comment.