'use strict';

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

var Extensions = require('../../../../extensions/Extensions.js');
var Matrix = require('../../../../maths/Matrix.js');
var Point = require('../../../../maths/Point.js');
var BindGroup = require('../../gpu/shader/BindGroup.js');
var UniformGroup = require('../shader/UniformGroup.js');

class GlobalUniformSystem {
  constructor(renderer) {
    this._stackIndex = 0;
    this._globalUniformDataStack = [];
    this._uniformsPool = [];
    this._activeUniforms = [];
    this._bindGroupPool = [];
    this._activeBindGroups = [];
    this._renderer = renderer;
  }
  reset() {
    this._stackIndex = 0;
    for (let i = 0; i < this._activeUniforms.length; i++) {
      this._uniformsPool.push(this._activeUniforms[i]);
    }
    for (let i = 0; i < this._activeBindGroups.length; i++) {
      this._bindGroupPool.push(this._activeBindGroups[i]);
    }
    this._activeUniforms.length = 0;
    this._activeBindGroups.length = 0;
  }
  start(options) {
    this.reset();
    this.push(options);
  }
  bind({
    projectionMatrix,
    worldTransformMatrix,
    worldColor,
    offset
  }) {
    const currentGlobalUniformData = this._stackIndex ? this._globalUniformDataStack[this._stackIndex - 1] : {
      projectionMatrix: this._renderer.renderTarget.renderTarget.projectionMatrix,
      worldTransformMatrix: new Matrix.Matrix(),
      worldColor: 4294967295,
      offset: new Point.Point()
    };
    const globalUniformData = {
      projectionMatrix: projectionMatrix || this._renderer.renderTarget.renderTarget.projectionMatrix,
      worldTransformMatrix: worldTransformMatrix || currentGlobalUniformData.worldTransformMatrix,
      worldColor: worldColor || currentGlobalUniformData.worldColor,
      offset: offset || currentGlobalUniformData.offset,
      bindGroup: null
    };
    const uniformGroup = this._uniformsPool.pop() || this._createUniforms();
    this._activeUniforms.push(uniformGroup);
    const uniforms = uniformGroup.uniforms;
    uniforms.projectionMatrix = globalUniformData.projectionMatrix;
    uniforms.worldTransformMatrix.copyFrom(globalUniformData.worldTransformMatrix);
    uniforms.worldTransformMatrix.tx -= globalUniformData.offset.x;
    uniforms.worldTransformMatrix.ty -= globalUniformData.offset.y;
    uniforms.worldAlpha = (globalUniformData.worldColor >> 24 & 255) / 255;
    uniformGroup.update();
    let bindGroup;
    if (this._renderer.renderPipes.uniformBatch) {
      bindGroup = this._renderer.renderPipes.uniformBatch.getUniformBindGroup(uniformGroup, false);
    } else {
      this._renderer.uniformBuffer.updateUniformGroup(uniformGroup);
      bindGroup = this._bindGroupPool.pop() || new BindGroup.BindGroup();
      this._activeBindGroups.push(bindGroup);
      bindGroup.setResource(uniformGroup, 0);
    }
    globalUniformData.bindGroup = bindGroup;
    this._currentGlobalUniformData = globalUniformData;
  }
  push(options) {
    this.bind(options);
    this._globalUniformDataStack[this._stackIndex++] = this._currentGlobalUniformData;
  }
  pop() {
    this._currentGlobalUniformData = this._globalUniformDataStack[--this._stackIndex - 1];
  }
  get bindGroup() {
    return this._currentGlobalUniformData.bindGroup;
  }
  get uniformGroup() {
    return this._currentGlobalUniformData.bindGroup.resources[0];
  }
  _createUniforms() {
    const globalUniforms = new UniformGroup.UniformGroup({
      projectionMatrix: { value: new Matrix.Matrix(), type: "mat3x3<f32>" },
      worldTransformMatrix: { value: new Matrix.Matrix(), type: "mat3x3<f32>" },
      // TODO - someone smart - set this to be a unorm8x4 rather than a vec4<f32>
      worldAlpha: { value: 1, type: "f32" }
    }, {
      ubo: true,
      isStatic: true
    });
    return globalUniforms;
  }
  destroy() {
    const writeable = this;
    writeable._renderer = null;
  }
}
/** @ignore */
GlobalUniformSystem.extension = {
  type: [
    Extensions.ExtensionType.WebGLSystem,
    Extensions.ExtensionType.WebGPUSystem,
    Extensions.ExtensionType.CanvasSystem
  ],
  name: "globalUniforms"
};

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