Source: packages/core/src/mask/ScissorSystem.js

packages/core/src/mask/ScissorSystem.js

import { AbstractMaskSystem } from './AbstractMaskSystem';
/**
 * System plugin to the renderer to manage scissor rects (used for masks).
 *
 * @class
 * @extends PIXI.System
 * @memberof PIXI.systems
 */
export class ScissorSystem extends AbstractMaskSystem {
    /**
     * @param {PIXI.Renderer} renderer - The renderer this System works for.
     */
    constructor(renderer) {
        super(renderer);
        this.glConst = WebGLRenderingContext.SCISSOR_TEST;
    }
    getStackLength() {
        const maskData = this.maskStack[this.maskStack.length - 1];
        if (maskData) {
            return maskData._scissorCounter;
        }
        return 0;
    }
    /**
     * Applies the Mask and adds it to the current stencil stack. @alvin
     *
     * @param {PIXI.MaskData} maskData - The mask data
     */
    push(maskData) {
        const maskObject = maskData.maskObject;
        maskObject.renderable = true;
        const prevData = maskData._scissorRect;
        const bounds = maskObject.getBounds(true);
        const { gl } = this.renderer;
        maskObject.renderable = false;
        if (prevData) {
            bounds.fit(prevData);
        }
        else {
            gl.enable(gl.SCISSOR_TEST);
        }
        maskData._scissorCounter++;
        maskData._scissorRect = bounds;
        this._useCurrent();
    }
    /**
     * Pops scissor mask. MaskData is already removed from stack
     */
    pop() {
        const { gl } = this.renderer;
        if (this.getStackLength() > 0) {
            this._useCurrent();
        }
        else {
            gl.disable(gl.SCISSOR_TEST);
        }
    }
    /**
     * Setup renderer to use the current scissor data.
     * @private
     */
    _useCurrent() {
        const rect = this.maskStack[this.maskStack.length - 1]._scissorRect;
        const rt = this.renderer.renderTexture.current;
        const { transform, sourceFrame, destinationFrame } = this.renderer.projection;
        const resolution = rt ? rt.resolution : this.renderer.resolution;
        let x = ((rect.x - sourceFrame.x) * resolution) + destinationFrame.x;
        let y = ((rect.y - sourceFrame.y) * resolution) + destinationFrame.y;
        const width = rect.width * resolution;
        const height = rect.height * resolution;
        if (transform) {
            x += transform.tx * resolution;
            y += transform.ty * resolution;
        }
        if (!rt) {
            // flipY. In future we'll have it over renderTextures as an option
            y = this.renderer.height - height - y;
        }
        this.renderer.gl.scissor(x, y, width, height);
    }
}