@pixi/core
Version:
Core PixiJS
175 lines (172 loc) • 5.78 kB
JavaScript
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