'use strict';

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

var Extensions = require('../../../extensions/Extensions.js');
var Matrix = require('../../../maths/Matrix.js');
var PoolGroup = require('../../../utils/pool/PoolGroup.js');
var BindGroup = require('../../renderers/gpu/shader/BindGroup.js');
var UniformGroup = require('../../renderers/shared/shader/UniformGroup.js');
var BatchableMesh = require('./BatchableMesh.js');

class MeshPipe {
  constructor(renderer, adaptor) {
    this.localUniforms = new UniformGroup.UniformGroup({
      uTransformMatrix: { value: new Matrix.Matrix(), type: "mat3x3<f32>" },
      uColor: { value: new Float32Array([1, 1, 1, 1]), type: "vec4<f32>" }
    });
    this.localUniformsBindGroup = new BindGroup.BindGroup({
      0: this.localUniforms
    });
    this._renderableHash = /* @__PURE__ */ Object.create(null);
    this._gpuBatchableMeshHash = /* @__PURE__ */ Object.create(null);
    this.renderer = renderer;
    this._adaptor = adaptor;
    this._adaptor.init();
  }
  validateRenderable(renderable) {
    const renderableData = this._getRenderableData(renderable);
    const wasBatched = renderableData.batched;
    const isBatched = renderable.view.batched;
    renderableData.batched = isBatched;
    if (wasBatched !== isBatched) {
      return true;
    } else if (isBatched) {
      const geometry = renderable.view._geometry;
      if (geometry.indices.length !== renderableData.indexSize || geometry.positions.length !== renderableData.vertexSize) {
        renderableData.indexSize = geometry.indices.length;
        renderableData.vertexSize = geometry.positions.length;
        return true;
      }
      const batchableMesh = this._getBatchableMesh(renderable);
      const texture = renderable.view.texture;
      if (batchableMesh.texture._source !== texture._source) {
        if (batchableMesh.texture._source !== texture._source) {
          return batchableMesh.batcher.checkAndUpdateTexture(batchableMesh, texture);
        }
      }
    }
    return false;
  }
  addRenderable(renderable, instructionSet) {
    const batcher = this.renderer.renderPipes.batch;
    const { batched } = this._getRenderableData(renderable);
    if (batched) {
      const gpuBatchableMesh = this._getBatchableMesh(renderable);
      gpuBatchableMesh.texture = renderable.view._texture;
      batcher.addToBatch(gpuBatchableMesh);
    } else {
      batcher.break(instructionSet);
      instructionSet.add({
        type: "mesh",
        renderable
      });
    }
  }
  updateRenderable(renderable) {
    if (renderable.view.batched) {
      const gpuBatchableMesh = this._gpuBatchableMeshHash[renderable.uid];
      gpuBatchableMesh.texture = renderable.view._texture;
      gpuBatchableMesh.batcher.updateElement(gpuBatchableMesh);
    }
  }
  destroyRenderable(renderable) {
    this._renderableHash[renderable.uid] = null;
    const gpuMesh = this._gpuBatchableMeshHash[renderable.uid];
    PoolGroup.BigPool.return(gpuMesh);
    this._gpuBatchableMeshHash[renderable.uid] = null;
  }
  execute({ renderable }) {
    if (!renderable.isRenderable)
      return;
    this._adaptor.execute(this, renderable);
  }
  _getRenderableData(renderable) {
    return this._renderableHash[renderable.uid] || this._initRenderableData(renderable);
  }
  _initRenderableData(renderable) {
    const view = renderable.view;
    this._renderableHash[renderable.uid] = {
      batched: view.batched,
      indexSize: view._geometry.indices.length,
      vertexSize: view._geometry.positions.length
    };
    renderable.on("destroyed", () => {
      this.destroyRenderable(renderable);
    });
    return this._renderableHash[renderable.uid];
  }
  _getBatchableMesh(renderable) {
    return this._gpuBatchableMeshHash[renderable.uid] || this._initBatchableMesh(renderable);
  }
  _initBatchableMesh(renderable) {
    const gpuMesh = PoolGroup.BigPool.get(BatchableMesh.BatchableMesh);
    gpuMesh.renderable = renderable;
    gpuMesh.texture = renderable.view._texture;
    this._gpuBatchableMeshHash[renderable.uid] = gpuMesh;
    gpuMesh.renderable = renderable;
    return gpuMesh;
  }
  destroy() {
    for (const i in this._gpuBatchableMeshHash) {
      if (this._gpuBatchableMeshHash[i]) {
        PoolGroup.BigPool.return(this._gpuBatchableMeshHash[i]);
      }
    }
    this._gpuBatchableMeshHash = null;
    this._renderableHash = null;
    this.localUniforms = null;
    this.localUniformsBindGroup = null;
    this._adaptor.destroy();
    this._adaptor = null;
    this.renderer = null;
  }
}
/** @ignore */
MeshPipe.extension = {
  type: [
    Extensions.ExtensionType.WebGLPipes,
    Extensions.ExtensionType.WebGPUPipes,
    Extensions.ExtensionType.CanvasPipes
  ],
  name: "mesh"
};

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