import { extensions, ExtensionType } from '@pixi/extensions';
import { Matrix, Transform } from '@pixi/math';
import { RenderTexture } from './RenderTexture';
import type { MSAA_QUALITY, SCALE_MODES } from '@pixi/constants';
import type { ExtensionMetadata } from '@pixi/extensions';
import type { Rectangle } from '@pixi/math';
import type { IRenderableContainer, IRenderableObject, IRenderer } from '../IRenderer';
import type { ISystem } from '../system/ISystem';
const tempTransform = new Transform();
// TODO could this just be part of extract?
export interface IGenerateTextureOptions
{
/** The scale mode of the texture. Optional, defaults to `PIXI.BaseTexture.defaultOptions.scaleMode`. */
scaleMode?: SCALE_MODES;
/** The resolution / device pixel ratio of the texture being generated. Optional defaults to Renderer resolution. */
resolution?: number;
/**
* The region of the displayObject, that shall be rendered,
* if no region is specified, defaults to the local bounds of the displayObject.
*/
region?: Rectangle;
/** The number of samples of the frame buffer. */
multisample?: MSAA_QUALITY;
}
/**
* System that manages the generation of textures from the renderer.
* @memberof PIXI
*/
export class GenerateTextureSystem implements ISystem
{
/** @ignore */
static extension: ExtensionMetadata = {
type: [
ExtensionType.RendererSystem,
ExtensionType.CanvasRendererSystem
],
name: 'textureGenerator',
};
renderer: IRenderer;
private readonly _tempMatrix: Matrix;
constructor(renderer: IRenderer)
{
this.renderer = renderer;
this._tempMatrix = new Matrix();
}
/**
* A Useful function that returns a texture of the display object that can then be used to create sprites
* This can be quite useful if your displayObject is complicated and needs to be reused multiple times.
* @param displayObject - The displayObject the object will be generated from.
* @param {IGenerateTextureOptions} options - Generate texture options.
* @returns a shiny new texture of the display object passed in
*/
generateTexture(displayObject: IRenderableObject, options?: IGenerateTextureOptions): RenderTexture
{
const { region: manualRegion, ...textureOptions } = options || {};
const region = manualRegion || (displayObject as IRenderableContainer).getLocalBounds(null, true);
// minimum texture size is 1x1, 0x0 will throw an error
if (region.width === 0) region.width = 1;
if (region.height === 0) region.height = 1;
const renderTexture = RenderTexture.create(
{
width: region.width,
height: region.height,
...textureOptions,
});
this._tempMatrix.tx = -region.x;
this._tempMatrix.ty = -region.y;
const transform = displayObject.transform;
displayObject.transform = tempTransform;
this.renderer.render(displayObject, {
renderTexture,
transform: this._tempMatrix,
skipUpdateTransform: !!displayObject.parent,
blit: true,
});
displayObject.transform = transform;
return renderTexture;
}
destroy(): void
{
// ka boom!
}
}
extensions.add(GenerateTextureSystem);