UNPKG

@pixi/core

Version:
175 lines (172 loc) 5.78 kB
import { MASK_TYPES } from '@pixi/constants'; import { ExtensionType, extensions } from '@pixi/extensions'; import { SpriteMaskFilter } from '../filters/spriteMask/SpriteMaskFilter.mjs'; import { MaskData } from './MaskData.mjs'; class MaskSystem { constructor(renderer) { this.renderer = renderer; this.enableScissor = true; this.alphaMaskPool = []; this.maskDataPool = []; this.maskStack = []; this.alphaMaskIndex = 0; } setMaskStack(maskStack) { this.maskStack = maskStack; this.renderer.scissor.setMaskStack(maskStack); this.renderer.stencil.setMaskStack(maskStack); } push(target, maskDataOrTarget) { let maskData = maskDataOrTarget; if (!maskData.isMaskData) { const d = this.maskDataPool.pop() || new MaskData(); d.pooled = true; d.maskObject = maskDataOrTarget; maskData = d; } const maskAbove = this.maskStack.length !== 0 ? this.maskStack[this.maskStack.length - 1] : null; maskData.copyCountersOrReset(maskAbove); maskData._colorMask = maskAbove ? maskAbove._colorMask : 15; if (maskData.autoDetect) { this.detect(maskData); } maskData._target = target; if (maskData.type !== MASK_TYPES.SPRITE) { this.maskStack.push(maskData); } if (maskData.enabled) { switch (maskData.type) { case MASK_TYPES.SCISSOR: this.renderer.scissor.push(maskData); break; case MASK_TYPES.STENCIL: this.renderer.stencil.push(maskData); break; case MASK_TYPES.SPRITE: maskData.copyCountersOrReset(null); this.pushSpriteMask(maskData); break; case MASK_TYPES.COLOR: this.pushColorMask(maskData); break; default: break; } } if (maskData.type === MASK_TYPES.SPRITE) { this.maskStack.push(maskData); } } pop(target) { const maskData = this.maskStack.pop(); if (!maskData || maskData._target !== target) { return; } if (maskData.enabled) { switch (maskData.type) { case MASK_TYPES.SCISSOR: this.renderer.scissor.pop(maskData); break; case MASK_TYPES.STENCIL: this.renderer.stencil.pop(maskData.maskObject); break; case MASK_TYPES.SPRITE: this.popSpriteMask(maskData); break; case MASK_TYPES.COLOR: this.popColorMask(maskData); break; default: break; } } maskData.reset(); if (maskData.pooled) { this.maskDataPool.push(maskData); } if (this.maskStack.length !== 0) { const maskCurrent = this.maskStack[this.maskStack.length - 1]; if (maskCurrent.type === MASK_TYPES.SPRITE && maskCurrent._filters) { maskCurrent._filters[0].maskSprite = maskCurrent.maskObject; } } } detect(maskData) { const maskObject = maskData.maskObject; if (!maskObject) { maskData.type = MASK_TYPES.COLOR; } else if (maskObject.isSprite) { maskData.type = MASK_TYPES.SPRITE; } else if (this.enableScissor && this.renderer.scissor.testScissor(maskData)) { maskData.type = MASK_TYPES.SCISSOR; } else { maskData.type = MASK_TYPES.STENCIL; } } pushSpriteMask(maskData) { const { maskObject } = maskData; const target = maskData._target; let alphaMaskFilter = maskData._filters; if (!alphaMaskFilter) { alphaMaskFilter = this.alphaMaskPool[this.alphaMaskIndex]; if (!alphaMaskFilter) { alphaMaskFilter = this.alphaMaskPool[this.alphaMaskIndex] = [new SpriteMaskFilter()]; } } const renderer = this.renderer; const renderTextureSystem = renderer.renderTexture; let resolution; let multisample; if (renderTextureSystem.current) { const renderTexture = renderTextureSystem.current; resolution = maskData.resolution || renderTexture.resolution; multisample = maskData.multisample ?? renderTexture.multisample; } else { resolution = maskData.resolution || renderer.resolution; multisample = maskData.multisample ?? renderer.multisample; } alphaMaskFilter[0].resolution = resolution; alphaMaskFilter[0].multisample = multisample; alphaMaskFilter[0].maskSprite = maskObject; const stashFilterArea = target.filterArea; target.filterArea = maskObject.getBounds(true); renderer.filter.push(target, alphaMaskFilter); target.filterArea = stashFilterArea; if (!maskData._filters) { this.alphaMaskIndex++; } } popSpriteMask(maskData) { this.renderer.filter.pop(); if (maskData._filters) { maskData._filters[0].maskSprite = null; } else { this.alphaMaskIndex--; this.alphaMaskPool[this.alphaMaskIndex][0].maskSprite = null; } } pushColorMask(maskData) { const currColorMask = maskData._colorMask; const nextColorMask = maskData._colorMask = currColorMask & maskData.colorMask; if (nextColorMask !== currColorMask) { this.renderer.gl.colorMask((nextColorMask & 1) !== 0, (nextColorMask & 2) !== 0, (nextColorMask & 4) !== 0, (nextColorMask & 8) !== 0); } } popColorMask(maskData) { const currColorMask = maskData._colorMask; const nextColorMask = this.maskStack.length > 0 ? this.maskStack[this.maskStack.length - 1]._colorMask : 15; if (nextColorMask !== currColorMask) { this.renderer.gl.colorMask((nextColorMask & 1) !== 0, (nextColorMask & 2) !== 0, (nextColorMask & 4) !== 0, (nextColorMask & 8) !== 0); } } destroy() { this.renderer = null; } } MaskSystem.extension = { type: ExtensionType.RendererSystem, name: "mask" }; extensions.add(MaskSystem); export { MaskSystem }; //# sourceMappingURL=MaskSystem.mjs.map