UNPKG

18 kBSource Map (JSON)View Raw
1{"version":3,"file":"MaskSystem.js","sources":["../../src/mask/MaskSystem.ts"],"sourcesContent":["import { MaskData } from './MaskData';\nimport { SpriteMaskFilter } from '../filters/spriteMask/SpriteMaskFilter';\nimport { MASK_TYPES } from '@pixi/constants';\n\nimport type { ISystem } from '../system/ISystem';\nimport type { IMaskTarget } from './MaskData';\nimport type { Renderer } from '../Renderer';\nimport type { ExtensionMetadata } from '@pixi/extensions';\nimport { extensions, ExtensionType } from '@pixi/extensions';\n\n/**\n * System plugin to the renderer to manage masks.\n *\n * There are three built-in types of masking:\n * **Scissor Masking**: Scissor masking discards pixels that are outside of a rectangle called the scissor box. It is\n * the most performant as the scissor test is inexpensive. However, it can only be used when the mask is rectangular.\n * **Stencil Masking**: Stencil masking discards pixels that don't overlap with the pixels rendered into the stencil\n * buffer. It is the next fastest option as it does not require rendering into a separate framebuffer. However, it does\n * cause the mask to be rendered **twice** for each masking operation; hence, minimize the rendering cost of your masks.\n * **Sprite Mask Filtering**: Sprite mask filtering discards pixels based on the red channel of the sprite-mask's\n * texture. (Generally, the masking texture is grayscale). Using advanced techniques, you might be able to embed this\n * type of masking in a custom shader - and hence, bypassing the masking system fully for performance wins.\n *\n * The best type of masking is auto-detected when you `push` one. To use scissor masking, you must pass in a `Graphics`\n * object with just a rectangle drawn.\n *\n * ## Mask Stacks\n *\n * In the scene graph, masks can be applied recursively, i.e. a mask can be applied during a masking operation. The mask\n * stack stores the currently applied masks in order. Each {@link PIXI.BaseRenderTexture} holds its own mask stack, i.e.\n * when you switch render-textures, the old masks only applied when you switch back to rendering to the old render-target.\n * @memberof PIXI\n */\nexport class MaskSystem implements ISystem\n{\n /** @ignore */\n static extension: ExtensionMetadata = {\n type: ExtensionType.RendererSystem,\n name: 'mask',\n };\n\n /**\n * Flag to enable scissor masking.\n * @default true\n */\n public enableScissor: boolean;\n\n /** Pool of used sprite mask filters. */\n protected readonly alphaMaskPool: Array<SpriteMaskFilter[]>;\n\n /**\n * Current index of alpha mask pool.\n * @default 0\n * @readonly\n */\n protected alphaMaskIndex: number;\n\n /** Pool of mask data. */\n private readonly maskDataPool: Array<MaskData>;\n private maskStack: Array<MaskData>;\n private renderer: Renderer;\n\n /**\n * @param renderer - The renderer this System works for.\n */\n constructor(renderer: Renderer)\n {\n this.renderer = renderer;\n\n this.enableScissor = true;\n this.alphaMaskPool = [];\n this.maskDataPool = [];\n\n this.maskStack = [];\n this.alphaMaskIndex = 0;\n }\n\n /**\n * Changes the mask stack that is used by this System.\n * @param maskStack - The mask stack\n */\n setMaskStack(maskStack: Array<MaskData>): void\n {\n this.maskStack = maskStack;\n this.renderer.scissor.setMaskStack(maskStack);\n this.renderer.stencil.setMaskStack(maskStack);\n }\n\n /**\n * Enables the mask and appends it to the current mask stack.\n *\n * NOTE: The batch renderer should be flushed beforehand to prevent pending renders from being masked.\n * @param {PIXI.DisplayObject} target - Display Object to push the mask to\n * @param {PIXI.MaskData|PIXI.Sprite|PIXI.Graphics|PIXI.DisplayObject} maskDataOrTarget - The masking data.\n */\n push(target: IMaskTarget, maskDataOrTarget: MaskData | IMaskTarget): void\n {\n let maskData = maskDataOrTarget as MaskData;\n\n if (!maskData.isMaskData)\n {\n const d = this.maskDataPool.pop() || new MaskData();\n\n d.pooled = true;\n d.maskObject = maskDataOrTarget as IMaskTarget;\n maskData = d;\n }\n\n const maskAbove = this.maskStack.length !== 0 ? this.maskStack[this.maskStack.length - 1] : null;\n\n maskData.copyCountersOrReset(maskAbove);\n maskData._colorMask = maskAbove ? maskAbove._colorMask : 0xf;\n\n if (maskData.autoDetect)\n {\n this.detect(maskData);\n }\n\n maskData._target = target;\n\n if (maskData.type !== MASK_TYPES.SPRITE)\n {\n this.maskStack.push(maskData);\n }\n\n if (maskData.enabled)\n {\n switch (maskData.type)\n {\n case MASK_TYPES.SCISSOR:\n this.renderer.scissor.push(maskData);\n break;\n case MASK_TYPES.STENCIL:\n this.renderer.stencil.push(maskData);\n break;\n case MASK_TYPES.SPRITE:\n maskData.copyCountersOrReset(null);\n this.pushSpriteMask(maskData);\n break;\n case MASK_TYPES.COLOR:\n this.pushColorMask(maskData);\n break;\n default:\n break;\n }\n }\n\n if (maskData.type === MASK_TYPES.SPRITE)\n {\n this.maskStack.push(maskData);\n }\n }\n\n /**\n * Removes the last mask from the mask stack and doesn't return it.\n *\n * NOTE: The batch renderer should be flushed beforehand to render the masked contents before the mask is removed.\n * @param {PIXI.IMaskTarget} target - Display Object to pop the mask from\n */\n pop(target: IMaskTarget): void\n {\n const maskData = this.maskStack.pop();\n\n if (!maskData || maskData._target !== target)\n {\n // TODO: add an assert when we have it\n\n return;\n }\n\n if (maskData.enabled)\n {\n switch (maskData.type)\n {\n case MASK_TYPES.SCISSOR:\n this.renderer.scissor.pop(maskData);\n break;\n case MASK_TYPES.STENCIL:\n this.renderer.stencil.pop(maskData.maskObject);\n break;\n case MASK_TYPES.SPRITE:\n this.popSpriteMask(maskData);\n break;\n case MASK_TYPES.COLOR:\n this.popColorMask(maskData);\n break;\n default:\n break;\n }\n }\n\n maskData.reset();\n\n if (maskData.pooled)\n {\n this.maskDataPool.push(maskData);\n }\n\n if (this.maskStack.length !== 0)\n {\n const maskCurrent = this.maskStack[this.maskStack.length - 1];\n\n if (maskCurrent.type === MASK_TYPES.SPRITE && maskCurrent._filters)\n {\n maskCurrent._filters[0].maskSprite = maskCurrent.maskObject;\n }\n }\n }\n\n /**\n * Sets type of MaskData based on its maskObject.\n * @param maskData\n */\n detect(maskData: MaskData): void\n {\n const maskObject = maskData.maskObject;\n\n if (!maskObject)\n {\n maskData.type = MASK_TYPES.COLOR;\n }\n else if (maskObject.isSprite)\n {\n maskData.type = MASK_TYPES.SPRITE;\n }\n else if (this.enableScissor && this.renderer.scissor.testScissor(maskData))\n {\n maskData.type = MASK_TYPES.SCISSOR;\n }\n else\n {\n maskData.type = MASK_TYPES.STENCIL;\n }\n }\n\n /**\n * Applies the Mask and adds it to the current filter stack.\n * @param maskData - Sprite to be used as the mask.\n */\n pushSpriteMask(maskData: MaskData): void\n {\n const { maskObject } = maskData;\n const target = maskData._target;\n let alphaMaskFilter = maskData._filters;\n\n if (!alphaMaskFilter)\n {\n alphaMaskFilter = this.alphaMaskPool[this.alphaMaskIndex];\n\n if (!alphaMaskFilter)\n {\n alphaMaskFilter = this.alphaMaskPool[this.alphaMaskIndex] = [new SpriteMaskFilter()];\n }\n }\n\n const renderer = this.renderer;\n const renderTextureSystem = renderer.renderTexture;\n\n let resolution;\n let multisample;\n\n if (renderTextureSystem.current)\n {\n const renderTexture = renderTextureSystem.current;\n\n resolution = maskData.resolution || renderTexture.resolution;\n multisample = maskData.multisample ?? renderTexture.multisample;\n }\n else\n {\n resolution = maskData.resolution || renderer.resolution;\n multisample = maskData.multisample ?? renderer.multisample;\n }\n\n alphaMaskFilter[0].resolution = resolution;\n alphaMaskFilter[0].multisample = multisample;\n alphaMaskFilter[0].maskSprite = maskObject;\n\n const stashFilterArea = target.filterArea;\n\n target.filterArea = maskObject.getBounds(true);\n renderer.filter.push(target, alphaMaskFilter);\n target.filterArea = stashFilterArea;\n\n if (!maskData._filters)\n {\n this.alphaMaskIndex++;\n }\n }\n\n /**\n * Removes the last filter from the filter stack and doesn't return it.\n * @param maskData - Sprite to be used as the mask.\n */\n popSpriteMask(maskData: MaskData): void\n {\n this.renderer.filter.pop();\n\n if (maskData._filters)\n {\n maskData._filters[0].maskSprite = null;\n }\n else\n {\n this.alphaMaskIndex--;\n this.alphaMaskPool[this.alphaMaskIndex][0].maskSprite = null;\n }\n }\n\n /**\n * Pushes the color mask.\n * @param maskData - The mask data\n */\n pushColorMask(maskData: MaskData): void\n {\n const currColorMask = maskData._colorMask;\n const nextColorMask = maskData._colorMask = currColorMask & maskData.colorMask;\n\n if (nextColorMask !== currColorMask)\n {\n this.renderer.gl.colorMask(\n (nextColorMask & 0x1) !== 0,\n (nextColorMask & 0x2) !== 0,\n (nextColorMask & 0x4) !== 0,\n (nextColorMask & 0x8) !== 0\n );\n }\n }\n\n /**\n * Pops the color mask.\n * @param maskData - The mask data\n */\n popColorMask(maskData: MaskData): void\n {\n const currColorMask = maskData._colorMask;\n const nextColorMask = this.maskStack.length > 0\n ? this.maskStack[this.maskStack.length - 1]._colorMask : 0xf;\n\n if (nextColorMask !== currColorMask)\n {\n this.renderer.gl.colorMask(\n (nextColorMask & 0x1) !== 0,\n (nextColorMask & 0x2) !== 0,\n (nextColorMask & 0x4) !== 0,\n (nextColorMask & 0x8) !== 0\n );\n }\n }\n\n destroy(): void\n {\n this.renderer = null;\n }\n}\n\nextensions.add(MaskSystem);\n"],"names":["MaskData","MASK_TYPES","SpriteMaskFilter","ExtensionType","extensions"],"mappings":"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"}
\No newline at end of file