'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var Extensions = require('../../../extensions/Extensions.js');
var _const$1 = require('../../renderers/gl/const.js');
var _const = require('../../renderers/shared/state/const.js');
var buildInstructions = require('../../scene/utils/buildInstructions.js');

class StencilMaskPipe {
  constructor(renderer) {
    // used when building and also when executing..
    this._maskStackHash = {};
    this._maskHash = /* @__PURE__ */ new WeakMap();
    this._renderer = renderer;
  }
  push(mask, _container, instructionSet) {
    const effect = mask;
    const renderer = this._renderer;
    renderer.renderPipes.batch.break(instructionSet);
    renderer.renderPipes.blendMode.setBlendMode(effect.mask, "none", instructionSet);
    instructionSet.add({
      type: "stencilMask",
      action: "pushMaskBegin",
      mask,
      canBundle: false
    });
    const maskContainer = effect.mask;
    maskContainer.includeInBuild = true;
    if (!this._maskHash.has(effect)) {
      this._maskHash.set(effect, {
        instructionsStart: 0,
        instructionsLength: 0
      });
    }
    const maskData = this._maskHash.get(effect);
    maskData.instructionsStart = instructionSet.instructionSize;
    buildInstructions.collectAllRenderables(
      maskContainer,
      instructionSet,
      renderer.renderPipes
    );
    maskContainer.includeInBuild = false;
    renderer.renderPipes.batch.break(instructionSet);
    instructionSet.add({
      type: "stencilMask",
      action: "pushMaskEnd",
      mask,
      canBundle: false
    });
    const instructionsLength = instructionSet.instructionSize - maskData.instructionsStart - 1;
    maskData.instructionsLength = instructionsLength;
    const renderTargetUid = renderer.renderTarget.renderTarget.uid;
    if (this._maskStackHash[renderTargetUid] === void 0) {
      this._maskStackHash[renderTargetUid] = 0;
    }
    this._maskStackHash[renderTargetUid]++;
  }
  pop(mask, _container, instructionSet) {
    const effect = mask;
    const renderer = this._renderer;
    const renderTargetUid = renderer.renderTarget.renderTarget.uid;
    this._maskStackHash[renderTargetUid]--;
    renderer.renderPipes.batch.break(instructionSet);
    renderer.renderPipes.blendMode.setBlendMode(effect.mask, "none", instructionSet);
    instructionSet.add({
      type: "stencilMask",
      action: "popMaskBegin",
      canBundle: false
    });
    const maskData = this._maskHash.get(mask);
    if (this._maskStackHash[renderTargetUid] !== 0) {
      for (let i = 0; i < maskData.instructionsLength; i++) {
        instructionSet.instructions[instructionSet.instructionSize++] = instructionSet.instructions[maskData.instructionsStart++];
      }
    }
    instructionSet.add({
      type: "stencilMask",
      action: "popMaskEnd",
      canBundle: false
    });
  }
  execute(instruction) {
    const renderer = this._renderer;
    const renderTargetUid = renderer.renderTarget.renderTarget.uid;
    let maskStackIndex = this._maskStackHash[renderTargetUid] ?? 0;
    if (instruction.action === "pushMaskBegin") {
      maskStackIndex++;
      renderer.stencil.setStencilMode(_const.STENCIL_MODES.RENDERING_MASK_ADD, maskStackIndex);
      renderer.colorMask.setMask(0);
    } else if (instruction.action === "pushMaskEnd") {
      renderer.stencil.setStencilMode(_const.STENCIL_MODES.MASK_ACTIVE, maskStackIndex);
      renderer.colorMask.setMask(15);
    } else if (instruction.action === "popMaskBegin") {
      maskStackIndex--;
      if (maskStackIndex !== 0) {
        renderer.stencil.setStencilMode(_const.STENCIL_MODES.RENDERING_MASK_REMOVE, maskStackIndex);
        renderer.colorMask.setMask(0);
      } else {
        renderer.renderTarget.clear(_const$1.CLEAR.STENCIL);
      }
    } else if (instruction.action === "popMaskEnd") {
      if (maskStackIndex === 0) {
        renderer.stencil.setStencilMode(_const.STENCIL_MODES.DISABLED, maskStackIndex);
      } else {
        renderer.stencil.setStencilMode(_const.STENCIL_MODES.MASK_ACTIVE, maskStackIndex);
      }
      renderer.colorMask.setMask(15);
    }
    this._maskStackHash[renderTargetUid] = maskStackIndex;
  }
  destroy() {
    this._renderer = null;
    this._maskStackHash = null;
    this._maskHash = null;
  }
}
StencilMaskPipe.extension = {
  type: [
    Extensions.ExtensionType.WebGLPipes,
    Extensions.ExtensionType.WebGPUPipes,
    Extensions.ExtensionType.CanvasPipes
  ],
  name: "stencilMask"
};

exports.StencilMaskPipe = StencilMaskPipe;
//# sourceMappingURL=StencilMaskPipe.js.map
