1 | import { ExtensionType, extensions } from '@pixi/extensions';
|
2 | import { Matrix, Rectangle } from '@pixi/math';
|
3 | import { settings } from '@pixi/settings';
|
4 | import { AbstractMaskSystem } from './AbstractMaskSystem.mjs';
|
5 |
|
6 | const tempMatrix = new Matrix();
|
7 | const rectPool = [];
|
8 | const _ScissorSystem = class extends AbstractMaskSystem {
|
9 | constructor(renderer) {
|
10 | super(renderer);
|
11 | this.glConst = settings.ADAPTER.getWebGLRenderingContext().SCISSOR_TEST;
|
12 | }
|
13 | getStackLength() {
|
14 | const maskData = this.maskStack[this.maskStack.length - 1];
|
15 | if (maskData) {
|
16 | return maskData._scissorCounter;
|
17 | }
|
18 | return 0;
|
19 | }
|
20 | calcScissorRect(maskData) {
|
21 | if (maskData._scissorRectLocal) {
|
22 | return;
|
23 | }
|
24 | const prevData = maskData._scissorRect;
|
25 | const { maskObject } = maskData;
|
26 | const { renderer } = this;
|
27 | const renderTextureSystem = renderer.renderTexture;
|
28 | const rect = maskObject.getBounds(true, rectPool.pop() ?? new Rectangle());
|
29 | this.roundFrameToPixels(rect, renderTextureSystem.current ? renderTextureSystem.current.resolution : renderer.resolution, renderTextureSystem.sourceFrame, renderTextureSystem.destinationFrame, renderer.projection.transform);
|
30 | if (prevData) {
|
31 | rect.fit(prevData);
|
32 | }
|
33 | maskData._scissorRectLocal = rect;
|
34 | }
|
35 | static isMatrixRotated(matrix) {
|
36 | if (!matrix) {
|
37 | return false;
|
38 | }
|
39 | const { a, b, c, d } = matrix;
|
40 | return (Math.abs(b) > 1e-4 || Math.abs(c) > 1e-4) && (Math.abs(a) > 1e-4 || Math.abs(d) > 1e-4);
|
41 | }
|
42 | testScissor(maskData) {
|
43 | const { maskObject } = maskData;
|
44 | if (!maskObject.isFastRect || !maskObject.isFastRect()) {
|
45 | return false;
|
46 | }
|
47 | if (_ScissorSystem.isMatrixRotated(maskObject.worldTransform)) {
|
48 | return false;
|
49 | }
|
50 | if (_ScissorSystem.isMatrixRotated(this.renderer.projection.transform)) {
|
51 | return false;
|
52 | }
|
53 | this.calcScissorRect(maskData);
|
54 | const rect = maskData._scissorRectLocal;
|
55 | return rect.width > 0 && rect.height > 0;
|
56 | }
|
57 | roundFrameToPixels(frame, resolution, bindingSourceFrame, bindingDestinationFrame, transform) {
|
58 | if (_ScissorSystem.isMatrixRotated(transform)) {
|
59 | return;
|
60 | }
|
61 | transform = transform ? tempMatrix.copyFrom(transform) : tempMatrix.identity();
|
62 | transform.translate(-bindingSourceFrame.x, -bindingSourceFrame.y).scale(bindingDestinationFrame.width / bindingSourceFrame.width, bindingDestinationFrame.height / bindingSourceFrame.height).translate(bindingDestinationFrame.x, bindingDestinationFrame.y);
|
63 | this.renderer.filter.transformAABB(transform, frame);
|
64 | frame.fit(bindingDestinationFrame);
|
65 | frame.x = Math.round(frame.x * resolution);
|
66 | frame.y = Math.round(frame.y * resolution);
|
67 | frame.width = Math.round(frame.width * resolution);
|
68 | frame.height = Math.round(frame.height * resolution);
|
69 | }
|
70 | push(maskData) {
|
71 | if (!maskData._scissorRectLocal) {
|
72 | this.calcScissorRect(maskData);
|
73 | }
|
74 | const { gl } = this.renderer;
|
75 | if (!maskData._scissorRect) {
|
76 | gl.enable(gl.SCISSOR_TEST);
|
77 | }
|
78 | maskData._scissorCounter++;
|
79 | maskData._scissorRect = maskData._scissorRectLocal;
|
80 | this._useCurrent();
|
81 | }
|
82 | pop(maskData) {
|
83 | const { gl } = this.renderer;
|
84 | if (maskData) {
|
85 | rectPool.push(maskData._scissorRectLocal);
|
86 | }
|
87 | if (this.getStackLength() > 0) {
|
88 | this._useCurrent();
|
89 | } else {
|
90 | gl.disable(gl.SCISSOR_TEST);
|
91 | }
|
92 | }
|
93 | _useCurrent() {
|
94 | const rect = this.maskStack[this.maskStack.length - 1]._scissorRect;
|
95 | let y;
|
96 | if (this.renderer.renderTexture.current) {
|
97 | y = rect.y;
|
98 | } else {
|
99 | y = this.renderer.height - rect.height - rect.y;
|
100 | }
|
101 | this.renderer.gl.scissor(rect.x, y, rect.width, rect.height);
|
102 | }
|
103 | };
|
104 | let ScissorSystem = _ScissorSystem;
|
105 | ScissorSystem.extension = {
|
106 | type: ExtensionType.RendererSystem,
|
107 | name: "scissor"
|
108 | };
|
109 | extensions.add(ScissorSystem);
|
110 |
|
111 | export { ScissorSystem };
|
112 |
|