Source: tiny/core/renderers/webgl/managers/MaskManager.js

import WebGLManager from './WebGLManager';
import AlphaMaskFilter from '../filters/SpriteMaskFilter';

/**
 * @class
 * @extends Tiny.WebGLManager
 * @memberof Tiny
 */
export default class MaskManager extends WebGLManager {
  /**
   * @param {Tiny.WebGLRenderer} renderer - The renderer this manager works for.
   */
  constructor(renderer) {
    super(renderer);

    // TODO - we don't need both!
    this.scissor = false;
    this.scissorData = null;
    this.scissorRenderTarget = null;

    this.enableScissor = true;

    this.alphaMaskPool = [];
    this.alphaMaskIndex = 0;
  }

  /**
   * Applies the Mask and adds it to the current filter stack.
   *
   * @param {Tiny.DisplayObject} target - Display Object to push the mask to
   * @param {Tiny.Sprite|Tiny.Graphics} maskData - The masking data.
   */
  pushMask(target, maskData) {
    // TODO the root check means scissor rect will not
    // be used on render textures more info here:
    // https://github.com/pixijs/pixi.js/pull/3545

    if (maskData.texture) {
      this.pushSpriteMask(target, maskData);
    } else if (this.enableScissor && !this.scissor && this.renderer._activeRenderTarget.root && !this.renderer.stencilManager.stencilMaskStack.length && maskData.isFastRect()) {
      const matrix = maskData.worldTransform;

      let rot = Math.atan2(matrix.b, matrix.a);

      // use the nearest degree!
      rot = Math.round(rot * (180 / Math.PI));

      if (rot % 90) {
        this.pushStencilMask(maskData);
      } else {
        this.pushScissorMask(target, maskData);
      }
    } else {
      this.pushStencilMask(maskData);
    }
  }

  /**
   * Removes the last mask from the mask stack and doesn't return it.
   *
   * @param {Tiny.DisplayObject} target - Display Object to pop the mask from
   * @param {Tiny.Sprite|Tiny.Graphics} maskData - The masking data.
   */
  popMask(target, maskData) {
    if (maskData.texture) {
      this.popSpriteMask(target, maskData);
    } else if (this.enableScissor && !this.renderer.stencilManager.stencilMaskStack.length) {
      this.popScissorMask(target, maskData);
    } else {
      this.popStencilMask(target, maskData);
    }
  }

  /**
   * Applies the Mask and adds it to the current filter stack.
   *
   * @param {Tiny.RenderTarget} target - Display Object to push the sprite mask to
   * @param {Tiny.Sprite} maskData - Sprite to be used as the mask
   */
  pushSpriteMask(target, maskData) {
    let alphaMaskFilter = this.alphaMaskPool[this.alphaMaskIndex];

    if (!alphaMaskFilter) {
      alphaMaskFilter = this.alphaMaskPool[this.alphaMaskIndex] = [new AlphaMaskFilter(maskData)];
    }

    alphaMaskFilter[0].resolution = this.renderer.resolution;
    alphaMaskFilter[0].maskSprite = maskData;

    const stashFilterArea = target.filterArea;

    target.filterArea = maskData.getBounds(true);
    this.renderer.filterManager.pushFilter(target, alphaMaskFilter);
    target.filterArea = stashFilterArea;

    this.alphaMaskIndex++;
  }

  /**
   * Removes the last filter from the filter stack and doesn't return it.
   *
   */
  popSpriteMask() {
    this.renderer.filterManager.popFilter();
    this.alphaMaskIndex--;
  }

  /**
   * Applies the Mask and adds it to the current filter stack.
   *
   * @param {Tiny.Sprite|Tiny.Graphics} maskData - The masking data.
   */
  pushStencilMask(maskData) {
    this.renderer.currentRenderer.stop();
    this.renderer.stencilManager.pushStencil(maskData);
  }

  /**
   * Removes the last filter from the filter stack and doesn't return it.
   *
   */
  popStencilMask() {
    this.renderer.currentRenderer.stop();
    this.renderer.stencilManager.popStencil();
  }

  /**
   *
   * @param {Tiny.DisplayObject} target - Display Object to push the mask to
   * @param {Tiny.Graphics} maskData - The masking data.
   */
  pushScissorMask(target, maskData) {
    maskData.renderable = true;

    const renderTarget = this.renderer._activeRenderTarget;

    const bounds = maskData.getBounds();

    bounds.fit(renderTarget.size);
    maskData.renderable = false;

    this.renderer.gl.enable(this.renderer.gl.SCISSOR_TEST);

    const resolution = this.renderer.resolution;

    this.renderer.gl.scissor(
      bounds.x * resolution,
      (renderTarget.root ? renderTarget.size.height - bounds.y - bounds.height : bounds.y) * resolution,
      bounds.width * resolution,
      bounds.height * resolution
    );

    this.scissorRenderTarget = renderTarget;
    this.scissorData = maskData;
    this.scissor = true;
  }

  /**
   *
   *
   */
  popScissorMask() {
    this.scissorRenderTarget = null;
    this.scissorData = null;
    this.scissor = false;

    // must be scissor!
    const gl = this.renderer.gl;

    gl.disable(gl.SCISSOR_TEST);
  }
}
Documentation generated by JSDoc 3.4.3 on Fri Jul 09 2021 19:32:25 GMT+0800 (CST)