1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, '__esModule', { value: true });
|
4 |
|
5 | var MaskData = require('./MaskData.js');
|
6 | var SpriteMaskFilter = require('../filters/spriteMask/SpriteMaskFilter.js');
|
7 | var constants = require('@pixi/constants');
|
8 | var extensions = require('@pixi/extensions');
|
9 |
|
10 | class MaskSystem {
|
11 | constructor(renderer) {
|
12 | this.renderer = renderer;
|
13 | this.enableScissor = true;
|
14 | this.alphaMaskPool = [];
|
15 | this.maskDataPool = [];
|
16 | this.maskStack = [];
|
17 | this.alphaMaskIndex = 0;
|
18 | }
|
19 | setMaskStack(maskStack) {
|
20 | this.maskStack = maskStack;
|
21 | this.renderer.scissor.setMaskStack(maskStack);
|
22 | this.renderer.stencil.setMaskStack(maskStack);
|
23 | }
|
24 | push(target, maskDataOrTarget) {
|
25 | let maskData = maskDataOrTarget;
|
26 | if (!maskData.isMaskData) {
|
27 | const d = this.maskDataPool.pop() || new MaskData.MaskData();
|
28 | d.pooled = true;
|
29 | d.maskObject = maskDataOrTarget;
|
30 | maskData = d;
|
31 | }
|
32 | const maskAbove = this.maskStack.length !== 0 ? this.maskStack[this.maskStack.length - 1] : null;
|
33 | maskData.copyCountersOrReset(maskAbove);
|
34 | maskData._colorMask = maskAbove ? maskAbove._colorMask : 15;
|
35 | if (maskData.autoDetect) {
|
36 | this.detect(maskData);
|
37 | }
|
38 | maskData._target = target;
|
39 | if (maskData.type !== constants.MASK_TYPES.SPRITE) {
|
40 | this.maskStack.push(maskData);
|
41 | }
|
42 | if (maskData.enabled) {
|
43 | switch (maskData.type) {
|
44 | case constants.MASK_TYPES.SCISSOR:
|
45 | this.renderer.scissor.push(maskData);
|
46 | break;
|
47 | case constants.MASK_TYPES.STENCIL:
|
48 | this.renderer.stencil.push(maskData);
|
49 | break;
|
50 | case constants.MASK_TYPES.SPRITE:
|
51 | maskData.copyCountersOrReset(null);
|
52 | this.pushSpriteMask(maskData);
|
53 | break;
|
54 | case constants.MASK_TYPES.COLOR:
|
55 | this.pushColorMask(maskData);
|
56 | break;
|
57 | default:
|
58 | break;
|
59 | }
|
60 | }
|
61 | if (maskData.type === constants.MASK_TYPES.SPRITE) {
|
62 | this.maskStack.push(maskData);
|
63 | }
|
64 | }
|
65 | pop(target) {
|
66 | const maskData = this.maskStack.pop();
|
67 | if (!maskData || maskData._target !== target) {
|
68 | return;
|
69 | }
|
70 | if (maskData.enabled) {
|
71 | switch (maskData.type) {
|
72 | case constants.MASK_TYPES.SCISSOR:
|
73 | this.renderer.scissor.pop(maskData);
|
74 | break;
|
75 | case constants.MASK_TYPES.STENCIL:
|
76 | this.renderer.stencil.pop(maskData.maskObject);
|
77 | break;
|
78 | case constants.MASK_TYPES.SPRITE:
|
79 | this.popSpriteMask(maskData);
|
80 | break;
|
81 | case constants.MASK_TYPES.COLOR:
|
82 | this.popColorMask(maskData);
|
83 | break;
|
84 | default:
|
85 | break;
|
86 | }
|
87 | }
|
88 | maskData.reset();
|
89 | if (maskData.pooled) {
|
90 | this.maskDataPool.push(maskData);
|
91 | }
|
92 | if (this.maskStack.length !== 0) {
|
93 | const maskCurrent = this.maskStack[this.maskStack.length - 1];
|
94 | if (maskCurrent.type === constants.MASK_TYPES.SPRITE && maskCurrent._filters) {
|
95 | maskCurrent._filters[0].maskSprite = maskCurrent.maskObject;
|
96 | }
|
97 | }
|
98 | }
|
99 | detect(maskData) {
|
100 | const maskObject = maskData.maskObject;
|
101 | if (!maskObject) {
|
102 | maskData.type = constants.MASK_TYPES.COLOR;
|
103 | } else if (maskObject.isSprite) {
|
104 | maskData.type = constants.MASK_TYPES.SPRITE;
|
105 | } else if (this.enableScissor && this.renderer.scissor.testScissor(maskData)) {
|
106 | maskData.type = constants.MASK_TYPES.SCISSOR;
|
107 | } else {
|
108 | maskData.type = constants.MASK_TYPES.STENCIL;
|
109 | }
|
110 | }
|
111 | pushSpriteMask(maskData) {
|
112 | const { maskObject } = maskData;
|
113 | const target = maskData._target;
|
114 | let alphaMaskFilter = maskData._filters;
|
115 | if (!alphaMaskFilter) {
|
116 | alphaMaskFilter = this.alphaMaskPool[this.alphaMaskIndex];
|
117 | if (!alphaMaskFilter) {
|
118 | alphaMaskFilter = this.alphaMaskPool[this.alphaMaskIndex] = [new SpriteMaskFilter.SpriteMaskFilter()];
|
119 | }
|
120 | }
|
121 | const renderer = this.renderer;
|
122 | const renderTextureSystem = renderer.renderTexture;
|
123 | let resolution;
|
124 | let multisample;
|
125 | if (renderTextureSystem.current) {
|
126 | const renderTexture = renderTextureSystem.current;
|
127 | resolution = maskData.resolution || renderTexture.resolution;
|
128 | multisample = maskData.multisample ?? renderTexture.multisample;
|
129 | } else {
|
130 | resolution = maskData.resolution || renderer.resolution;
|
131 | multisample = maskData.multisample ?? renderer.multisample;
|
132 | }
|
133 | alphaMaskFilter[0].resolution = resolution;
|
134 | alphaMaskFilter[0].multisample = multisample;
|
135 | alphaMaskFilter[0].maskSprite = maskObject;
|
136 | const stashFilterArea = target.filterArea;
|
137 | target.filterArea = maskObject.getBounds(true);
|
138 | renderer.filter.push(target, alphaMaskFilter);
|
139 | target.filterArea = stashFilterArea;
|
140 | if (!maskData._filters) {
|
141 | this.alphaMaskIndex++;
|
142 | }
|
143 | }
|
144 | popSpriteMask(maskData) {
|
145 | this.renderer.filter.pop();
|
146 | if (maskData._filters) {
|
147 | maskData._filters[0].maskSprite = null;
|
148 | } else {
|
149 | this.alphaMaskIndex--;
|
150 | this.alphaMaskPool[this.alphaMaskIndex][0].maskSprite = null;
|
151 | }
|
152 | }
|
153 | pushColorMask(maskData) {
|
154 | const currColorMask = maskData._colorMask;
|
155 | const nextColorMask = maskData._colorMask = currColorMask & maskData.colorMask;
|
156 | if (nextColorMask !== currColorMask) {
|
157 | this.renderer.gl.colorMask((nextColorMask & 1) !== 0, (nextColorMask & 2) !== 0, (nextColorMask & 4) !== 0, (nextColorMask & 8) !== 0);
|
158 | }
|
159 | }
|
160 | popColorMask(maskData) {
|
161 | const currColorMask = maskData._colorMask;
|
162 | const nextColorMask = this.maskStack.length > 0 ? this.maskStack[this.maskStack.length - 1]._colorMask : 15;
|
163 | if (nextColorMask !== currColorMask) {
|
164 | this.renderer.gl.colorMask((nextColorMask & 1) !== 0, (nextColorMask & 2) !== 0, (nextColorMask & 4) !== 0, (nextColorMask & 8) !== 0);
|
165 | }
|
166 | }
|
167 | destroy() {
|
168 | this.renderer = null;
|
169 | }
|
170 | }
|
171 | MaskSystem.extension = {
|
172 | type: extensions.ExtensionType.RendererSystem,
|
173 | name: "mask"
|
174 | };
|
175 | extensions.extensions.add(MaskSystem);
|
176 |
|
177 | exports.MaskSystem = MaskSystem;
|
178 |
|