- 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
import { AtlasResource } from './AtlasResource';
import { BaseTexture, Texture } from '@pixi/core';
import { GuilloteneAllocator } from '@pixi-essentials/area-allocator';
import { TextureAllocator } from './TextureAllocator';
import { TextureSlab } from './TextureSlab';
import type { AtlasResourceSource } from './AtlasResource';
/**
* This texture allocator auto-manages the base-texture with an {@link AtlasResource}. You can also
* pass a texture source to `allocate`, mimicing {@link Texture.from} functionality.
*
* @public
*/
export class AtlasAllocator extends TextureAllocator
{
/**
* Creates a texture slab backed by an {@link AtlasResource}.
*/
protected createSlab(): TextureSlab
{
return {
managedArea: new GuilloteneAllocator(this.slabWidth, this.slabHeight),
managedTextures: [],
slab: new BaseTexture(new AtlasResource(this.slabWidth, this.slabHeight),
{
width: this.slabWidth,
height: this.slabHeight,
}),
};
}
/**
* Allocates a texture backed by the given atlas source, with the given padding.
*
* @override
* @param width
* @param height
* @param padding
* @param source
*/
allocate(width: number, height: number, padding?: number, source?: AtlasResourceSource): Texture;
/**
* Allocates a texture backed by the given source, with default padding.
*
* @param width
* @param height
* @param source
*/
allocate(width: number, height: number, source?: AtlasResourceSource): Texture;
allocate(width: number, height: number, paddingOrSource?: number | AtlasResourceSource, source?: AtlasResourceSource): Texture
{
let padding: number;
if (typeof paddingOrSource === 'number')
{
padding = paddingOrSource;
}
else
{
padding = this.calculatePadding(width, height);
source = paddingOrSource;
}
const texture = super.allocate(width, height, padding);
if (source)
{
const atlas = texture.baseTexture.resource as AtlasResource;
const item = {
frame: texture.frame,
source,
// dirtyId !== updateId only if image loaded
dirtyId: source instanceof HTMLImageElement && !source.complete ? -1 : 0,
updateId: -1,
texture,
};
atlas.managedItems.push(item);
if (source instanceof HTMLImageElement && !source.complete) {
source.addEventListener('load', () => {
if (texture.baseTexture.valid && !texture.baseTexture.destroyed && atlas.managedItems.indexOf(item) >= 0) {
item.dirtyId++;
texture.baseTexture.update();
}
});
}
texture.baseTexture.update();
}
return texture;
}
free(texture: Texture): void
{
super.free(texture);
const atlas = texture.baseTexture.resource as AtlasResource;
const item = atlas.managedItems.find(item => item.texture === texture);
if (item)
{
atlas.managedItems.splice(atlas.managedItems.indexOf(item), 1);
}
}
}