"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

var _iterableUtils = require("./iterable-utils");

var _typedArrayManager = _interopRequireDefault(require("./typed-array-manager"));

var _assert = _interopRequireDefault(require("./assert"));

var _core = require("@luma.gl/core");

function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

var Tesselator = function () {
  function Tesselator(opts) {
    (0, _classCallCheck2.default)(this, Tesselator);
    this.opts = void 0;
    this.typedArrayManager = void 0;
    this.indexStarts = [0];
    this.vertexStarts = [0];
    this.vertexCount = 0;
    this.instanceCount = 0;
    this.attributes = void 0;
    this._attributeDefs = void 0;
    this.data = void 0;
    this.getGeometry = void 0;
    this.geometryBuffer = void 0;
    this.buffers = void 0;
    this.positionSize = void 0;
    this.normalize = void 0;
    var _opts$attributes = opts.attributes,
        attributes = _opts$attributes === void 0 ? {} : _opts$attributes;
    this.typedArrayManager = _typedArrayManager.default;
    this.attributes = {};
    this._attributeDefs = attributes;
    this.opts = opts;
    this.updateGeometry(opts);
  }

  var _proto = Tesselator.prototype;

  _proto.updateGeometry = function updateGeometry(opts) {
    Object.assign(this.opts, opts);
    var _this$opts = this.opts,
        data = _this$opts.data,
        _this$opts$buffers = _this$opts.buffers,
        buffers = _this$opts$buffers === void 0 ? {} : _this$opts$buffers,
        getGeometry = _this$opts.getGeometry,
        geometryBuffer = _this$opts.geometryBuffer,
        positionFormat = _this$opts.positionFormat,
        dataChanged = _this$opts.dataChanged,
        _this$opts$normalize = _this$opts.normalize,
        normalize = _this$opts$normalize === void 0 ? true : _this$opts$normalize;
    this.data = data;
    this.getGeometry = getGeometry;
    this.positionSize = geometryBuffer && geometryBuffer.size || (positionFormat === 'XY' ? 2 : 3);
    this.buffers = buffers;
    this.normalize = normalize;

    if (geometryBuffer) {
      (0, _assert.default)(data.startIndices);
      this.getGeometry = this.getGeometryFromBuffer(geometryBuffer);

      if (!normalize) {
        buffers.vertexPositions = geometryBuffer;
      }
    }

    this.geometryBuffer = buffers.vertexPositions;

    if (Array.isArray(dataChanged)) {
      var _iterator = _createForOfIteratorHelper(dataChanged),
          _step;

      try {
        for (_iterator.s(); !(_step = _iterator.n()).done;) {
          var dataRange = _step.value;

          this._rebuildGeometry(dataRange);
        }
      } catch (err) {
        _iterator.e(err);
      } finally {
        _iterator.f();
      }
    } else {
      this._rebuildGeometry();
    }
  };

  _proto.updatePartialGeometry = function updatePartialGeometry(_ref) {
    var startRow = _ref.startRow,
        endRow = _ref.endRow;

    this._rebuildGeometry({
      startRow: startRow,
      endRow: endRow
    });
  };

  _proto.getGeometryFromBuffer = function getGeometryFromBuffer(geometryBuffer) {
    var value = geometryBuffer.value || geometryBuffer;

    if (!ArrayBuffer.isView(value)) {
      return null;
    }

    return (0, _iterableUtils.getAccessorFromBuffer)(value, {
      size: this.positionSize,
      offset: geometryBuffer.offset,
      stride: geometryBuffer.stride,
      startIndices: this.data.startIndices
    });
  };

  _proto._allocate = function _allocate(instanceCount, copy) {
    var attributes = this.attributes,
        buffers = this.buffers,
        _attributeDefs = this._attributeDefs,
        typedArrayManager = this.typedArrayManager;

    for (var name in _attributeDefs) {
      if (name in buffers) {
        typedArrayManager.release(attributes[name]);
        attributes[name] = null;
      } else {
        var def = _attributeDefs[name];
        def.copy = copy;
        attributes[name] = typedArrayManager.allocate(attributes[name], instanceCount, def);
      }
    }
  };

  _proto._forEachGeometry = function _forEachGeometry(visitor, startRow, endRow) {
    var data = this.data,
        getGeometry = this.getGeometry;

    var _createIterable = (0, _iterableUtils.createIterable)(data, startRow, endRow),
        iterable = _createIterable.iterable,
        objectInfo = _createIterable.objectInfo;

    var _iterator2 = _createForOfIteratorHelper(iterable),
        _step2;

    try {
      for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
        var object = _step2.value;
        objectInfo.index++;

        var _geometry = getGeometry ? getGeometry(object, objectInfo) : null;

        visitor(_geometry, objectInfo.index);
      }
    } catch (err) {
      _iterator2.e(err);
    } finally {
      _iterator2.f();
    }
  };

  _proto._rebuildGeometry = function _rebuildGeometry(dataRange) {
    var _this = this;

    if (!this.data) {
      return;
    }

    var indexStarts = this.indexStarts,
        vertexStarts = this.vertexStarts,
        instanceCount = this.instanceCount;
    var data = this.data,
        geometryBuffer = this.geometryBuffer;

    var _ref2 = dataRange || {},
        _ref2$startRow = _ref2.startRow,
        startRow = _ref2$startRow === void 0 ? 0 : _ref2$startRow,
        _ref2$endRow = _ref2.endRow,
        endRow = _ref2$endRow === void 0 ? Infinity : _ref2$endRow;

    var normalizedData = {};

    if (!dataRange) {
      indexStarts = [0];
      vertexStarts = [0];
    }

    if (this.normalize || !geometryBuffer) {
      this._forEachGeometry(function (geometry, dataIndex) {
        var normalizedGeometry = geometry && _this.normalizeGeometry(geometry);

        normalizedData[dataIndex] = normalizedGeometry;
        vertexStarts[dataIndex + 1] = vertexStarts[dataIndex] + (normalizedGeometry ? _this.getGeometrySize(normalizedGeometry) : 0);
      }, startRow, endRow);

      instanceCount = vertexStarts[vertexStarts.length - 1];
    } else {
      vertexStarts = data.startIndices;
      instanceCount = vertexStarts[data.length] || 0;

      if (ArrayBuffer.isView(geometryBuffer)) {
        instanceCount = instanceCount || geometryBuffer.length / this.positionSize;
      } else if (geometryBuffer instanceof _core.Buffer) {
        var byteStride = this.positionSize * 4;
        instanceCount = instanceCount || geometryBuffer.byteLength / byteStride;
      } else if (geometryBuffer.buffer) {
        var _byteStride = geometryBuffer.stride || this.positionSize * 4;

        instanceCount = instanceCount || geometryBuffer.buffer.byteLength / _byteStride;
      } else if (geometryBuffer.value) {
        var bufferValue = geometryBuffer.value;
        var elementStride = geometryBuffer.stride / bufferValue.BYTES_PER_ELEMENT || this.positionSize;
        instanceCount = instanceCount || bufferValue.length / elementStride;
      }
    }

    this._allocate(instanceCount, Boolean(dataRange));

    this.indexStarts = indexStarts;
    this.vertexStarts = vertexStarts;
    this.instanceCount = instanceCount;
    var context = {};

    this._forEachGeometry(function (geometry, dataIndex) {
      var normalizedGeometry = normalizedData[dataIndex] || geometry;
      context.vertexStart = vertexStarts[dataIndex];
      context.indexStart = indexStarts[dataIndex];
      var vertexEnd = dataIndex < vertexStarts.length - 1 ? vertexStarts[dataIndex + 1] : instanceCount;
      context.geometrySize = vertexEnd - vertexStarts[dataIndex];
      context.geometryIndex = dataIndex;

      _this.updateGeometryAttributes(normalizedGeometry, context);
    }, startRow, endRow);

    this.vertexCount = indexStarts[indexStarts.length - 1];
  };

  return Tesselator;
}();

exports.default = Tesselator;
//# sourceMappingURL=tesselator.js.map