1 | {"version":3,"file":"ScissorSystem.mjs","sources":["../../src/mask/ScissorSystem.ts"],"sourcesContent":["import { extensions, ExtensionType } from '@pixi/extensions';\nimport { Matrix, Rectangle } from '@pixi/math';\nimport { settings } from '@pixi/settings';\nimport { AbstractMaskSystem } from './AbstractMaskSystem';\n\nimport type { ExtensionMetadata } from '@pixi/extensions';\nimport type { Renderer } from '../Renderer';\nimport type { MaskData } from './MaskData';\n\nconst tempMatrix = new Matrix();\nconst rectPool: Rectangle[] = [];\n\n/**\n * System plugin to the renderer to manage scissor masking.\n *\n * Scissor masking discards pixels outside of a rectangle called the scissor box. The scissor box is in the framebuffer\n * viewport's space; however, the mask's rectangle is projected from world-space to viewport space automatically\n * by this system.\n * @memberof PIXI\n */\nexport class ScissorSystem extends AbstractMaskSystem\n{\n /** @ignore */\n static extension: ExtensionMetadata = {\n type: ExtensionType.RendererSystem,\n name: 'scissor',\n };\n\n /**\n * @param {PIXI.Renderer} renderer - The renderer this System works for.\n */\n constructor(renderer: Renderer)\n {\n super(renderer);\n\n this.glConst = settings.ADAPTER.getWebGLRenderingContext().SCISSOR_TEST;\n }\n\n getStackLength(): number\n {\n const maskData = this.maskStack[this.maskStack.length - 1];\n\n if (maskData)\n {\n return maskData._scissorCounter;\n }\n\n return 0;\n }\n\n /**\n * evaluates _boundsTransformed, _scissorRect for MaskData\n * @param maskData\n */\n calcScissorRect(maskData: MaskData): void\n {\n if (maskData._scissorRectLocal)\n {\n return;\n }\n\n const prevData = maskData._scissorRect;\n const { maskObject } = maskData;\n const { renderer } = this;\n const renderTextureSystem = renderer.renderTexture;\n const rect = maskObject.getBounds(true, rectPool.pop() ?? new Rectangle());\n\n this.roundFrameToPixels(rect,\n renderTextureSystem.current ? renderTextureSystem.current.resolution : renderer.resolution,\n renderTextureSystem.sourceFrame,\n renderTextureSystem.destinationFrame,\n renderer.projection.transform);\n\n if (prevData)\n {\n rect.fit(prevData);\n }\n maskData._scissorRectLocal = rect;\n }\n\n private static isMatrixRotated(matrix: Matrix)\n {\n if (!matrix)\n {\n return false;\n }\n const { a, b, c, d } = matrix;\n\n // Skip if skew/rotation present in matrix, except for multiple of 90° rotation. If rotation\n // is a multiple of 90°, then either pair of (b,c) or (a,d) will be (0,0).\n return ((Math.abs(b) > 1e-4 || Math.abs(c) > 1e-4)\n && (Math.abs(a) > 1e-4 || Math.abs(d) > 1e-4));\n }\n\n /**\n * Test, whether the object can be scissor mask with current renderer projection.\n * Calls \"calcScissorRect()\" if its true.\n * @param maskData - mask data\n * @returns whether Whether the object can be scissor mask\n */\n public testScissor(maskData: MaskData): boolean\n {\n const { maskObject } = maskData;\n\n if (!maskObject.isFastRect || !maskObject.isFastRect())\n {\n return false;\n }\n if (ScissorSystem.isMatrixRotated(maskObject.worldTransform))\n {\n return false;\n }\n if (ScissorSystem.isMatrixRotated(this.renderer.projection.transform))\n {\n return false;\n }\n\n this.calcScissorRect(maskData);\n\n const rect = maskData._scissorRectLocal;\n\n return rect.width > 0 && rect.height > 0;\n }\n\n private roundFrameToPixels(\n frame: Rectangle,\n resolution: number,\n bindingSourceFrame: Rectangle,\n bindingDestinationFrame: Rectangle,\n transform?: Matrix,\n )\n {\n if (ScissorSystem.isMatrixRotated(transform))\n {\n return;\n }\n\n transform = transform ? tempMatrix.copyFrom(transform) : tempMatrix.identity();\n\n // Get forward transform from world space to screen space\n transform\n .translate(-bindingSourceFrame.x, -bindingSourceFrame.y)\n .scale(\n bindingDestinationFrame.width / bindingSourceFrame.width,\n bindingDestinationFrame.height / bindingSourceFrame.height)\n .translate(bindingDestinationFrame.x, bindingDestinationFrame.y);\n\n // Convert frame to screen space\n (this.renderer.filter as any).transformAABB(transform, frame);\n\n frame.fit(bindingDestinationFrame);\n frame.x = Math.round(frame.x * resolution);\n frame.y = Math.round(frame.y * resolution);\n frame.width = Math.round(frame.width * resolution);\n frame.height = Math.round(frame.height * resolution);\n }\n\n /**\n * Applies the Mask and adds it to the current stencil stack.\n * @author alvin\n * @param maskData - The mask data.\n */\n push(maskData: MaskData): void\n {\n if (!maskData._scissorRectLocal)\n {\n this.calcScissorRect(maskData);\n }\n\n const { gl } = this.renderer;\n\n if (!maskData._scissorRect)\n {\n gl.enable(gl.SCISSOR_TEST);\n }\n\n maskData._scissorCounter++;\n maskData._scissorRect = maskData._scissorRectLocal;\n this._useCurrent();\n }\n\n /**\n * This should be called after a mask is popped off the mask stack. It will rebind the scissor box to be latest with the\n * last mask in the stack.\n *\n * This can also be called when you directly modify the scissor box and want to restore PixiJS state.\n * @param maskData - The mask data.\n */\n pop(maskData?: MaskData): void\n {\n const { gl } = this.renderer;\n\n if (maskData)\n {\n rectPool.push(maskData._scissorRectLocal);\n }\n\n if (this.getStackLength() > 0)\n {\n this._useCurrent();\n }\n else\n {\n gl.disable(gl.SCISSOR_TEST);\n }\n }\n\n /**\n * Setup renderer to use the current scissor data.\n * @private\n */\n _useCurrent(): void\n {\n const rect = this.maskStack[this.maskStack.length - 1]._scissorRect;\n let y: number;\n\n if (this.renderer.renderTexture.current)\n {\n y = rect.y;\n }\n else\n {\n // flipY. In future we'll have it over renderTextures as an option\n y = this.renderer.height - rect.height - rect.y;\n }\n\n this.renderer.gl.scissor(rect.x, y, rect.width, rect.height);\n }\n}\n\nextensions.add(ScissorSystem);\n"],"names":["_ScissorSystem"],"mappings":"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"} |