{"version":3,"file":"StencilSystem.mjs","sources":["../../src/mask/StencilSystem.ts"],"sourcesContent":["import { extensions, ExtensionType } from '@pixi/extensions';\nimport { settings } from '@pixi/settings';\nimport { AbstractMaskSystem } from './AbstractMaskSystem';\n\nimport type { ExtensionMetadata } from '@pixi/extensions';\nimport type { Renderer } from '../Renderer';\nimport type { IMaskTarget, MaskData } from './MaskData';\n\n/**\n * System plugin to the renderer to manage stencils (used for masks).\n * @memberof PIXI\n */\nexport class StencilSystem extends AbstractMaskSystem\n{\n    /** @ignore */\n    static extension: ExtensionMetadata = {\n        type: ExtensionType.RendererSystem,\n        name: 'stencil',\n    };\n\n    /**\n     * @param renderer - The renderer this System works for.\n     */\n    constructor(renderer: Renderer)\n    {\n        super(renderer);\n\n        this.glConst = settings.ADAPTER.getWebGLRenderingContext().STENCIL_TEST;\n    }\n\n    getStackLength(): number\n    {\n        const maskData = this.maskStack[this.maskStack.length - 1];\n\n        if (maskData)\n        {\n            return maskData._stencilCounter;\n        }\n\n        return 0;\n    }\n\n    /**\n     * Applies the Mask and adds it to the current stencil stack.\n     * @param maskData - The mask data\n     */\n    push(maskData: MaskData): void\n    {\n        const maskObject = maskData.maskObject;\n        const { gl } = this.renderer;\n        const prevMaskCount = maskData._stencilCounter;\n\n        if (prevMaskCount === 0)\n        {\n            // force use stencil texture in current framebuffer\n            this.renderer.framebuffer.forceStencil();\n            gl.clearStencil(0);\n            gl.clear(gl.STENCIL_BUFFER_BIT);\n            gl.enable(gl.STENCIL_TEST);\n        }\n\n        maskData._stencilCounter++;\n\n        const colorMask = maskData._colorMask;\n\n        if (colorMask !== 0)\n        {\n            maskData._colorMask = 0;\n            gl.colorMask(false, false, false, false);\n        }\n\n        // Increment the reference stencil value where the new mask overlaps with the old ones.\n        gl.stencilFunc(gl.EQUAL, prevMaskCount, 0xFFFFFFFF);\n        gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);\n\n        maskObject.renderable = true;\n        maskObject.render(this.renderer);\n        this.renderer.batch.flush();\n        maskObject.renderable = false;\n\n        if (colorMask !== 0)\n        {\n            maskData._colorMask = colorMask;\n            gl.colorMask(\n                (colorMask & 1) !== 0,\n                (colorMask & 2) !== 0,\n                (colorMask & 4) !== 0,\n                (colorMask & 8) !== 0\n            );\n        }\n\n        this._useCurrent();\n    }\n\n    /**\n     * Pops stencil mask. MaskData is already removed from stack\n     * @param {PIXI.DisplayObject} maskObject - object of popped mask data\n     */\n    pop(maskObject: IMaskTarget): void\n    {\n        const gl = this.renderer.gl;\n\n        if (this.getStackLength() === 0)\n        {\n            // the stack is empty!\n            gl.disable(gl.STENCIL_TEST);\n        }\n        else\n        {\n            const maskData = this.maskStack.length !== 0 ? this.maskStack[this.maskStack.length - 1] : null;\n            const colorMask = maskData ? maskData._colorMask : 0xf;\n\n            if (colorMask !== 0)\n            {\n                maskData._colorMask = 0;\n                gl.colorMask(false, false, false, false);\n            }\n\n            // Decrement the reference stencil value where the popped mask overlaps with the other ones\n            gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR);\n\n            maskObject.renderable = true;\n            maskObject.render(this.renderer);\n            this.renderer.batch.flush();\n            maskObject.renderable = false;\n\n            if (colorMask !== 0)\n            {\n                maskData._colorMask = colorMask;\n                gl.colorMask(\n                    (colorMask & 0x1) !== 0,\n                    (colorMask & 0x2) !== 0,\n                    (colorMask & 0x4) !== 0,\n                    (colorMask & 0x8) !== 0\n                );\n            }\n\n            this._useCurrent();\n        }\n    }\n\n    /**\n     * Setup renderer to use the current stencil data.\n     * @private\n     */\n    _useCurrent(): void\n    {\n        const gl = this.renderer.gl;\n\n        gl.stencilFunc(gl.EQUAL, this.getStackLength(), 0xFFFFFFFF);\n        gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);\n    }\n}\n\nextensions.add(StencilSystem);\n"],"names":[],"mappings":";;;AAYO,MAAM,sBAAsB,mBACnC;AAAA;AAAA;AAAA;AAAA,EAUI,YAAY,UACZ;AACI,UAAM,QAAQ,GAEd,KAAK,UAAU,SAAS,QAAQ,yBAA2B,EAAA;AAAA,EAC/D;AAAA,EAEA,iBACA;AACI,UAAM,WAAW,KAAK,UAAU,KAAK,UAAU,SAAS,CAAC;AAErD,WAAA,WAEO,SAAS,kBAGb;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAK,UACL;AACU,UAAA,aAAa,SAAS,YACtB,EAAE,OAAO,KAAK,UACd,gBAAgB,SAAS;AAE3B,sBAAkB,MAGlB,KAAK,SAAS,YAAY,aAAa,GACvC,GAAG,aAAa,CAAC,GACjB,GAAG,MAAM,GAAG,kBAAkB,GAC9B,GAAG,OAAO,GAAG,YAAY,IAG7B,SAAS;AAET,UAAM,YAAY,SAAS;AAEvB,kBAAc,MAEd,SAAS,aAAa,GACtB,GAAG,UAAU,IAAO,IAAO,IAAO,EAAK,IAI3C,GAAG,YAAY,GAAG,OAAO,eAAe,UAAU,GAClD,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAEtC,WAAW,aAAa,IACxB,WAAW,OAAO,KAAK,QAAQ,GAC/B,KAAK,SAAS,MAAM,MACpB,GAAA,WAAW,aAAa,IAEpB,cAAc,MAEd,SAAS,aAAa,WACtB,GAAG;AAAA,OACE,YAAY,OAAO;AAAA,OACnB,YAAY,OAAO;AAAA,OACnB,YAAY,OAAO;AAAA,OACnB,YAAY,OAAO;AAAA,IAAA,IAI5B,KAAK;EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,YACJ;AACU,UAAA,KAAK,KAAK,SAAS;AAErB,QAAA,KAAK,qBAAqB;AAGvB,SAAA,QAAQ,GAAG,YAAY;AAAA,SAG9B;AACI,YAAM,WAAW,KAAK,UAAU,WAAW,IAAI,KAAK,UAAU,KAAK,UAAU,SAAS,CAAC,IAAI,MACrF,YAAY,WAAW,SAAS,aAAa;AAE/C,oBAAc,MAEd,SAAS,aAAa,GACtB,GAAG,UAAU,IAAO,IAAO,IAAO,EAAK,IAI3C,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAEtC,WAAW,aAAa,IACxB,WAAW,OAAO,KAAK,QAAQ,GAC/B,KAAK,SAAS,MAAM,MACpB,GAAA,WAAW,aAAa,IAEpB,cAAc,MAEd,SAAS,aAAa,WACtB,GAAG;AAAA,SACE,YAAY,OAAS;AAAA,SACrB,YAAY,OAAS;AAAA,SACrB,YAAY,OAAS;AAAA,SACrB,YAAY,OAAS;AAAA,MAAA,IAI9B,KAAK;IACT;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cACA;AACU,UAAA,KAAK,KAAK,SAAS;AAEzB,OAAG,YAAY,GAAG,OAAO,KAAK,eAAkB,GAAA,UAAU,GAC1D,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI;AAAA,EAC1C;AACJ;AA5Ia,cAGF,YAA+B;AAAA,EAClC,MAAM,cAAc;AAAA,EACpB,MAAM;AACV;AAwIJ,WAAW,IAAI,aAAa;"}