@loaders.gl/textures
Version:
Framework-independent loaders for compressed and super compressed (basis) textures
73 lines (59 loc) • 1.88 kB
text/typescript
// loaders.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
/*
Asynchronously maps a deep structure of values (e.g. objects and arrays of urls).
E.g. a mipmapped cubemap
{
[CUBE_FACE_FRONT]: [
"image-front-0.jpg",
"image-front-1.jpg",
"image-front-2.jpg",
],
[CUBE_MAP_BACK]: [
...
]
}
*/
export type Options = Record<string, any>;
export type Func = (url: string, options: Options) => unknown;
const isObject = (value: any): boolean => value && typeof value === 'object';
// Loads a deep structure of urls (objects and arrays of urls)
// Returns an object with six key-value pairs containing the images (or image mip arrays)
// for each cube face
export async function asyncDeepMap(tree: unknown, func: Func, options: Options = {}) {
return await mapSubtree(tree, func, options);
}
export async function mapSubtree(object: unknown, func: Func, options: Options) {
if (Array.isArray(object)) {
return await mapArray(object, func, options);
}
if (isObject(object)) {
return await mapObject(object as object, func, options);
}
// TODO - ignore non-urls, non-arraybuffers?
const url = object as string;
return await func(url, options);
}
// HELPERS
async function mapObject(
object: Record<string, any>,
func: Func,
options: Options
): Promise<Record<string, any>> {
const promises: Promise<any>[] = [];
const values: Record<string, any> = {};
for (const key in object) {
const url = object[key];
const promise = mapSubtree(url, func, options).then((value) => {
values[key] = value;
});
promises.push(promise);
}
await Promise.all(promises);
return values;
}
async function mapArray(urlArray: string[], func: Func, options = {}): Promise<any[]> {
const promises = urlArray.map((url) => mapSubtree(url, func, options));
return await Promise.all(promises);
}