- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
import type { TYPES } from '@pixi/constants';
import { MIPMAP_MODES, ALPHA_MODES, FORMATS } from '@pixi/constants';
import type { BufferResource, ExtensionMetadata } from '@pixi/core';
import { BaseTexture, ExtensionType, Texture } from '@pixi/core';
import { CompressedTextureResource } from '@pixi/compressed-textures';
import type {
BasisBinding } from './Basis';
import {
BASIS_FORMATS,
BASIS_FORMAT_TO_TYPE,
} from './Basis';
import { TranscoderWorker } from './TranscoderWorker';
import { LoaderResource } from '@pixi/loaders';
import type { IResourceMetadata } from '@pixi/loaders';
import type { TranscodedResourcesArray } from './BasisParser';
import { BasisParser } from './BasisParser';
/**
* Result when calling registerCompressedTextures.
* @ignore
*/
type BasisTexturesResult = Pick<LoaderResource, 'textures' | 'texture'>;
LoaderResource.setExtensionXhrType('basis', LoaderResource.XHR_RESPONSE_TYPE.BUFFER);
/**
* Loader plugin for handling BASIS supercompressed texture files.
*
* To use this loader, you must bind the basis_universal WebAssembly transcoder. There are two ways of
* doing this:
*
* 1. Adding a <script> tag to your HTML page to the transcoder bundle in this package, and serving
* the WASM binary from the same location.
*
* ```js
* // Copy ./node_modules/@pixi/basis/assets/basis_.wasm into your assets directory
* // as well, so it is served from the same folder as the JavaScript!
* <script src="./node_modules/@pixi/basis/assets/basis_transcoder.js" />
* ```
*
* NOTE: `basis_transcoder.js` expects the WebAssembly binary to be named `basis_transcoder.wasm`.
* NOTE-2: This method supports transcoding on the main-thread. Only use this if you have 1 or 2 *.basis
* files.
*
* 2. Loading the transcoder source from a URL.
*
* ```js
* // Use this if you to use the default CDN url for @pixi/basis
* BasisLoader.loadTranscoder();
*
* // Use this if you want to serve the transcoder on your own
* BasisLoader.loadTranscoder('./basis_transcoder.js', './basis_transcoder.wasm');
* ```
*
* NOTE: This can only be used with web-workers.
* @class
* @memberof PIXI
* @implements {PIXI.ILoaderPlugin}
*/
export class BasisLoader
{
/** @ignore */
static extension: ExtensionMetadata = ExtensionType.Loader;
/**
* Transcodes the *.basis data when the data is loaded. If the transcoder is not bound yet, it
* will hook transcoding to {@link BasisResource#onTranscoderInitialized}.
* @see PIXI.Loader.loaderMiddleware
* @param resource - loader resource that is checked to see if it is a basis file
* @param next - callback Function to call when done
*/
public static use(resource: LoaderResource, next: (...args: any[]) => void): void
{
if (resource.extension === 'basis' && resource.data)
{
(async () =>
{
if (!BasisParser.basisBinding && (!BasisParser.TranscoderWorker.wasmSource))
{
await TranscoderWorker.onTranscoderInitialized;
}
const resources = await BasisParser.transcode(resource.data);
Object.assign(resource, BasisLoader.registerTextures(
resource.url,
resources,
resource.metadata,
));
next();
})();
}
else
{
next();
}
}
/**
* Creates textures and adds them to the texture cache
* @private
* @param url - url of the texture to be used as its ID for the texture cache
* @param resources - the transcoded resources
* @param metadata - resource metadata
*/
private static registerTextures(
url: string,
resources: TranscodedResourcesArray,
metadata: IResourceMetadata,
): BasisTexturesResult
{
const result: BasisTexturesResult = {
textures: {},
texture: null,
};
if (!resources)
{
return result;
}
// Should be a valid TYPES, FORMATS for uncompressed basis formats
const type: TYPES = BASIS_FORMAT_TO_TYPE[resources.basisFormat];
const format: FORMATS = resources.basisFormat !== BASIS_FORMATS.cTFRGBA32 ? FORMATS.RGB : FORMATS.RGBA;
const resourceList = resources as Array<CompressedTextureResource | BufferResource>;
const textures = resourceList.map((resource) =>
(
new Texture(new BaseTexture(resource, Object.assign({
mipmap: resource instanceof CompressedTextureResource && resource.levels > 1
? MIPMAP_MODES.ON_MANUAL
: MIPMAP_MODES.OFF,
alphaMode: ALPHA_MODES.NO_PREMULTIPLIED_ALPHA,
type,
format,
}, metadata)))
));
textures.forEach((texture: Texture, i: number) =>
{
const { baseTexture } = texture;
const cacheID = `${url}-${i + 1}`;
BaseTexture.addToCache(baseTexture, cacheID);
Texture.addToCache(texture, cacheID);
if (i === 0)
{
BaseTexture.addToCache(baseTexture, url);
Texture.addToCache(texture, url);
result.texture = texture;
}
result.textures[cacheID] = texture;
});
return result;
}
/**
* Binds the basis_universal transcoder to decompress *.basis files. You must initialize the transcoder library yourself.
*
* ```js
* import { BasisLoader } from '@pixi/basis';
* import { Loader } from '@pixi/loaders';
*
* // window.BASIS() returns a Promise-like object
* window.BASIS().then((basisLibrary) =>
* {
* // Initialize basis-library; otherwise, transcoded results maybe corrupt!
* basisLibrary.initializeBasis();
*
* // Bind BasisLoader to the transcoder
* BasisLoader.bindTranscoder(basisLibrary);
* });
* ```
* @param basisLibrary - the initialized transcoder library
* @private
*/
static bindTranscoder(basisLibrary: BasisBinding): void
{
BasisParser.basisBinding = basisLibrary;
}
/**
* Loads the transcoder source code for use in {@link PIXI.BasisLoader.TranscoderWorker}.
* @private
* @param jsURL - URL to the javascript basis transcoder
* @param wasmURL - URL to the wasm basis transcoder
*/
static loadTranscoder(jsURL: string, wasmURL: string): Promise<[void, void]>
{
return BasisParser.TranscoderWorker.loadTranscoder(jsURL, wasmURL);
}
/**
* Set the transcoder source code directly
* @private
* @param jsSource - source for the javascript basis transcoder
* @param wasmSource - source for the wasm basis transcoder
*/
static setTranscoder(jsSource: string, wasmSource: ArrayBuffer): void
{
BasisParser.TranscoderWorker.setTranscoder(jsSource, wasmSource);
}
}