Skip to content

Instantly share code, notes, and snippets.

@TimvanScherpenzeel
Created August 16, 2019 09:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TimvanScherpenzeel/5ac2871df7a5cf13d3576a8d93cc67c7 to your computer and use it in GitHub Desktop.
Save TimvanScherpenzeel/5ac2871df7a5cf13d3576a8d93cc67c7 to your computer and use it in GitHub Desktop.
Loading a .binpack file
private loadBinpack = (item: ILoadItem): Promise<any> =>
this.loadArrayBuffer(item).then((data: TVoidable<ArrayBuffer>): any => {
if (data) {
let content = null;
let contentArray = null;
let binaryChunk: TNullable<ArrayBuffer> = null;
let byteOffset = null;
let chunkIndex = 0;
let chunkLength = 0;
let chunkType = null;
const headerMagic = new Uint8Array(data, 0, 4).reduce(
(magic, char) => (magic += String.fromCharCode(char)),
''
);
assert(headerMagic === 'BINP', 'AssetLoader -> Unsupported Binpacker header');
const chunkView = new DataView(data, 12);
while (chunkIndex < chunkView.byteLength) {
chunkLength = chunkView.getUint32(chunkIndex, true);
chunkIndex += 4;
chunkType = chunkView.getUint32(chunkIndex, true);
chunkIndex += 4;
if (chunkType === 0x4e4f534a) {
contentArray = new Uint8Array(data, 12 + chunkIndex, chunkLength);
content = contentArray.reduce((str, char) => (str += String.fromCharCode(char)), '');
} else if (chunkType === 0x004e4942) {
byteOffset = 12 + chunkIndex;
binaryChunk = data.slice(byteOffset, byteOffset + chunkLength);
}
chunkIndex += chunkLength;
}
assert(content !== null, 'AssetLoader -> JSON content chunk not found');
if (content && binaryChunk) {
const jsonChunk = JSON.parse(content);
return Promise.resolve(
Promise.all(
jsonChunk.map(
(entry: {
name: string;
mimeType: string;
bufferStart: number;
bufferEnd: number;
}) => {
const { name, mimeType } = entry;
const binary =
binaryChunk && binaryChunk.slice(entry.bufferStart, entry.bufferEnd);
assert(binary !== null, 'AssetLoader -> Binary content chunk not found');
const blob =
binary &&
new Blob([new Uint8Array(binary)], {
type: mimeType,
});
const loaderType = this.getLoaderByFileExtension(name);
const url = URL.createObjectURL(blob);
assert(
loaderType === ELoaderKey.JSON ||
loaderType === ELoaderKey.Text ||
loaderType === ELoaderKey.Image ||
loaderType === ELoaderKey.XML,
'AssetLoader -> Binpack currently only supports JSON, plain text, XML (SVG) and images'
);
switch (loaderType) {
case ELoaderKey.JSON:
return { id: name, src: this.loadJSON({ src: url, id: name }) };
case ELoaderKey.Text:
return { id: name, src: this.loadText({ src: url, id: name }) };
case ELoaderKey.XML:
return { id: name, src: this.loadXML({ src: url, id: name }) };
case ELoaderKey.Image:
default:
return { id: name, src: this.loadImage({ src: url, id: name }) };
}
}
)
).then((assets: any) =>
Object.assign({}, ...assets.map((asset: any) => {
return { [asset.id]: asset.src };
}))
)
);
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment