text: "use strict";
  
  var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
  
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports["default"] = void 0;
  
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
  
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
  
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
  
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
  
  var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
  
  var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
  
  var _get2 = _interopRequireDefault(require("@babel/runtime/helpers/get"));
  
  var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
  
  var _dataColumn = _interopRequireDefault(require("./data-column"));
  
  var _assert = _interopRequireDefault(require("../../utils/assert"));
  
  var _iterableUtils = require("../../utils/iterable-utils");
  
  var _flatten = require("../../utils/flatten");
  
  var range = _interopRequireWildcard(require("../../utils/range"));
  
  var _attributeTransitionUtils = require("./attribute-transition-utils");
  
  var Attribute = function (_DataColumn) {
    (0, _inherits2["default"])(Attribute, _DataColumn);
  
    function Attribute(gl) {
      var _this;
  
      var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
      (0, _classCallCheck2["default"])(this, Attribute);
      _this = (0, _possibleConstructorReturn2["default"])(this, (0, _getPrototypeOf2["default"])(Attribute).call(this, gl, opts));
      var _opts$transition = opts.transition,
          transition = _opts$transition === void 0 ? false : _opts$transition,
          _opts$noAlloc = opts.noAlloc,
          noAlloc = _opts$noAlloc === void 0 ? false : _opts$noAlloc,
          _opts$update = opts.update,
          update = _opts$update === void 0 ? null : _opts$update,
          _opts$accessor = opts.accessor,
          accessor = _opts$accessor === void 0 ? null : _opts$accessor,
          _opts$transform = opts.transform,
          transform = _opts$transform === void 0 ? null : _opts$transform,
          _opts$startIndices = opts.startIndices,
          startIndices = _opts$startIndices === void 0 ? null : _opts$startIndices;
      Object.assign(_this.settings, {
        transition: transition,
        noAlloc: noAlloc,
        update: update || accessor && _this._autoUpdater,
        accessor: accessor,
        transform: transform
      });
      Object.assign(_this.state, {
        lastExternalBuffer: null,
        binaryValue: null,
        binaryAccessor: null,
        needsUpdate: true,
        needsRedraw: false,
        updateRanges: range.FULL,
        startIndices: startIndices
      });
      Object.seal(_this.settings);
      Object.seal(_this.state);
  
      _this._validateAttributeUpdaters();
  
      return _this;
    }
  
    (0, _createClass2["default"])(Attribute, [{
      key: "needsUpdate",
      value: function needsUpdate() {
        return this.state.needsUpdate;
      }
    }, {
      key: "needsRedraw",
      value: function needsRedraw() {
        var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
            _ref$clearChangedFlag = _ref.clearChangedFlags,
            clearChangedFlags = _ref$clearChangedFlag === void 0 ? false : _ref$clearChangedFlag;
  
        var needsRedraw = this.state.needsRedraw;
        this.state.needsRedraw = needsRedraw && !clearChangedFlags;
        return needsRedraw;
      }
    }, {
      key: "getUpdateTriggers",
      value: function getUpdateTriggers() {
        var accessor = this.settings.accessor;
        return [this.id].concat(typeof accessor !== 'function' && accessor || []);
      }
    }, {
      key: "supportsTransition",
      value: function supportsTransition() {
        return Boolean(this.settings.transition);
      }
    }, {
      key: "getTransitionSetting",
      value: function getTransitionSetting(opts) {
        var accessor = this.settings.accessor;
        var layerSettings = this.settings.transition;
  
        if (!this.supportsTransition()) {
          return null;
        }
  
        var userSettings = Array.isArray(accessor) ? opts[accessor.find(function (a) {
          return opts[a];
        })] : opts[accessor];
        return (0, _attributeTransitionUtils.normalizeTransitionSettings)(userSettings, layerSettings);
      }
    }, {
      key: "setNeedsUpdate",
      value: function setNeedsUpdate() {
        var reason = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.id;
        var dataRange = arguments.length > 1 ? arguments[1] : undefined;
        this.state.needsUpdate = this.state.needsUpdate || reason;
        this.setNeedsRedraw(reason);
  
        if (dataRange) {
          var _dataRange$startRow = dataRange.startRow,
              startRow = _dataRange$startRow === void 0 ? 0 : _dataRange$startRow,
              _dataRange$endRow = dataRange.endRow,
              endRow = _dataRange$endRow === void 0 ? Infinity : _dataRange$endRow;
          this.state.updateRanges = range.add(this.state.updateRanges, [startRow, endRow]);
        } else {
          this.state.updateRanges = range.FULL;
        }
      }
    }, {
      key: "clearNeedsUpdate",
      value: function clearNeedsUpdate() {
        this.state.needsUpdate = false;
        this.state.updateRanges = range.EMPTY;
      }
    }, {
      key: "setNeedsRedraw",
      value: function setNeedsRedraw() {
        var reason = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.id;
        this.state.needsRedraw = this.state.needsRedraw || reason;
      }
    }, {
      key: "update",
      value: function update(opts) {
        this.setData(opts);
      }
    }, {
      key: "allocate",
      value: function allocate(numInstances) {
        var state = this.state,
            settings = this.settings;
  
        if (settings.noAlloc) {
          return false;
        }
  
        if (settings.update) {
          (0, _assert["default"])(Number.isFinite(numInstances));
          (0, _get2["default"])((0, _getPrototypeOf2["default"])(Attribute.prototype), "allocate", this).call(this, {
            numInstances: numInstances,
            copy: state.updateRanges !== range.FULL
          });
          return true;
        }
  
        return false;
      }
    }, {
      key: "updateBuffer",
      value: function updateBuffer(_ref2) {
        var numInstances = _ref2.numInstances,
            data = _ref2.data,
            props = _ref2.props,
            context = _ref2.context;
  
        if (!this.needsUpdate()) {
          return false;
        }
  
        var updateRanges = this.state.updateRanges,
            _this$settings = this.settings,
            update = _this$settings.update,
            noAlloc = _this$settings.noAlloc;
        var updated = true;
  
        if (update) {
          var _iteratorNormalCompletion = true;
          var _didIteratorError = false;
          var _iteratorError = undefined;
  
          try {
            for (var _iterator = updateRanges[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
              var _step$value = (0, _slicedToArray2["default"])(_step.value, 2),
                  _startRow = _step$value[0],
                  _endRow = _step$value[1];
  
              update.call(context, this, {
                data: data,
                startRow: _startRow,
                endRow: _endRow,
                props: props,
                numInstances: numInstances
              });
            }
          } catch (err) {
            _didIteratorError = true;
            _iteratorError = err;
          } finally {
            try {
              if (!_iteratorNormalCompletion && _iterator["return"] != null) {
                _iterator["return"]();
              }
            } finally {
              if (_didIteratorError) {
                throw _iteratorError;
              }
            }
          }
  
          if (!this.value) {} else if (this.constant || this.buffer.byteLength < this.value.byteLength + this.byteOffset) {
            this.setData({
              value: this.value,
              constant: this.constant
            });
          } else {
            var _iteratorNormalCompletion2 = true;
            var _didIteratorError2 = false;
            var _iteratorError2 = undefined;
  
            try {
              for (var _iterator2 = updateRanges[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
                var _step2$value = (0, _slicedToArray2["default"])(_step2.value, 2),
                    startRow = _step2$value[0],
                    endRow = _step2$value[1];
  
                var startOffset = Number.isFinite(startRow) ? this.getVertexOffset(startRow) : 0;
                var endOffset = Number.isFinite(endRow) ? this.getVertexOffset(endRow) : noAlloc || !Number.isFinite(numInstances) ? this.value.length : numInstances * this.size;
                (0, _get2["default"])((0, _getPrototypeOf2["default"])(Attribute.prototype), "updateSubBuffer", this).call(this, {
                  startOffset: startOffset,
                  endOffset: endOffset
                });
              }
            } catch (err) {
              _didIteratorError2 = true;
              _iteratorError2 = err;
            } finally {
              try {
                if (!_iteratorNormalCompletion2 && _iterator2["return"] != null) {
                  _iterator2["return"]();
                }
              } finally {
                if (_didIteratorError2) {
                  throw _iteratorError2;
                }
              }
            }
          }
  
          this._checkAttributeArray();
        } else {
          updated = false;
        }
  
        this.clearNeedsUpdate();
        this.setNeedsRedraw();
        return updated;
      }
    }, {
      key: "setConstantValue",
      value: function setConstantValue(value) {
        if (value === undefined || typeof value === 'function') {
          return false;
        }
  
        var hasChanged = this.setData({
          constant: true,
          value: value
        });
  
        if (hasChanged) {
          this.setNeedsRedraw();
        }
  
        this.clearNeedsUpdate();
        return true;
      }
    }, {
      key: "setExternalBuffer",
      value: function setExternalBuffer(buffer) {
        var state = this.state;
  
        if (!buffer) {
          state.lastExternalBuffer = null;
          return false;
        }
  
        this.clearNeedsUpdate();
  
        if (state.lastExternalBuffer === buffer) {
          return true;
        }
  
        state.lastExternalBuffer = buffer;
        this.setNeedsRedraw();
        this.setData(buffer);
        return true;
      }
    }, {
      key: "setBinaryValue",
      value: function setBinaryValue(buffer) {
        var startIndices = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
        var state = this.state,
            settings = this.settings;
  
        if (!buffer) {
          state.binaryValue = null;
          state.binaryAccessor = null;
          return false;
        }
  
        if (settings.noAlloc) {
          return false;
        }
  
        if (state.binaryValue === buffer) {
          this.clearNeedsUpdate();
          return true;
        }
  
        state.binaryValue = buffer;
        this.setNeedsRedraw();
  
        if (ArrayBuffer.isView(buffer)) {
          buffer = {
            value: buffer
          };
        }
  
        var needsUpdate = settings.transform || startIndices !== this.startIndices;
  
        if (needsUpdate) {
          (0, _assert["default"])(ArrayBuffer.isView(buffer.value), "invalid ".concat(settings.accessor));
          var needsNormalize = buffer.size && buffer.size !== this.size;
          state.binaryAccessor = (0, _iterableUtils.getAccessorFromBuffer)(buffer.value, {
            size: buffer.size || this.size,
            stride: buffer.stride,
            offset: buffer.offset,
            startIndices: startIndices,
            nested: needsNormalize
          });
          return false;
        }
  
        this.clearNeedsUpdate();
        this.setData(buffer);
        return true;
      }
    }, {
      key: "getVertexOffset",
      value: function getVertexOffset(row) {
        var startIndices = this.startIndices;
        var vertexIndex = startIndices ? startIndices[row] : row;
        return vertexIndex * this.size;
      }
    }, {
      key: "getShaderAttributes",
      value: function getShaderAttributes() {
        var shaderAttributeDefs = this.settings.shaderAttributes || (0, _defineProperty2["default"])({}, this.id, null);
        var shaderAttributes = {};
  
        for (var shaderAttributeName in shaderAttributeDefs) {
          Object.assign(shaderAttributes, (0, _get2["default"])((0, _getPrototypeOf2["default"])(Attribute.prototype), "getShaderAttributes", this).call(this, shaderAttributeName, shaderAttributeDefs[shaderAttributeName]));
        }
  
        return shaderAttributes;
      }
    }, {
      key: "_autoUpdater",
      value: function _autoUpdater(attribute, _ref4) {
        var data = _ref4.data,
            startRow = _ref4.startRow,
            endRow = _ref4.endRow,
            props = _ref4.props,
            numInstances = _ref4.numInstances;
        var settings = attribute.settings,
            state = attribute.state,
            value = attribute.value,
            size = attribute.size,
            startIndices = attribute.startIndices;
        var accessor = settings.accessor,
            transform = settings.transform;
        var accessorFunc = state.binaryAccessor || (typeof accessor === 'function' ? accessor : props[accessor]);
        (0, _assert["default"])(typeof accessorFunc === 'function', "accessor \"".concat(accessor, "\" is not a function"));
        var i = attribute.getVertexOffset(startRow);
  
        var _createIterable = (0, _iterableUtils.createIterable)(data, startRow, endRow),
            iterable = _createIterable.iterable,
            objectInfo = _createIterable.objectInfo;
  
        var _iteratorNormalCompletion3 = true;
        var _didIteratorError3 = false;
        var _iteratorError3 = undefined;
  
        try {
          for (var _iterator3 = iterable[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
            var object = _step3.value;
            objectInfo.index++;
            var objectValue = accessorFunc(object, objectInfo);
  
            if (transform) {
              objectValue = transform.call(this, objectValue);
            }
  
            if (startIndices) {
              var numVertices = (objectInfo.index < startIndices.length - 1 ? startIndices[objectInfo.index + 1] : numInstances) - startIndices[objectInfo.index];
  
              if (objectValue && Array.isArray(objectValue[0])) {
                var startIndex = i;
                var _iteratorNormalCompletion4 = true;
                var _didIteratorError4 = false;
                var _iteratorError4 = undefined;
  
                try {
                  for (var _iterator4 = objectValue[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
                    var item = _step4.value;
  
                    attribute._normalizeValue(item, value, startIndex);
  
                    startIndex += size;
                  }
                } catch (err) {
                  _didIteratorError4 = true;
                  _iteratorError4 = err;
                } finally {
                  try {
                    if (!_iteratorNormalCompletion4 && _iterator4["return"] != null) {
                      _iterator4["return"]();
                    }
                  } finally {
                    if (_didIteratorError4) {
                      throw _iteratorError4;
                    }
                  }
                }
              } else if (objectValue && objectValue.length > size) {
                value.set(objectValue, i);
              } else {
                attribute._normalizeValue(objectValue, objectInfo.target, 0);
  
                (0, _flatten.fillArray)({
                  target: value,
                  source: objectInfo.target,
                  start: i,
                  count: numVertices
                });
              }
  
              i += numVertices * size;
            } else {
              attribute._normalizeValue(objectValue, value, i);
  
              i += size;
            }
          }
        } catch (err) {
          _didIteratorError3 = true;
          _iteratorError3 = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion3 && _iterator3["return"] != null) {
              _iterator3["return"]();
            }
          } finally {
            if (_didIteratorError3) {
              throw _iteratorError3;
            }
          }
        }
  
        attribute.constant = false;
      }
    }, {
      key: "_validateAttributeUpdaters",
      value: function _validateAttributeUpdaters() {
        var settings = this.settings;
        var hasUpdater = settings.noAlloc || typeof settings.update === 'function';
  
        if (!hasUpdater) {
          throw new Error("Attribute ".concat(this.id, " missing update or accessor"));
        }
      }
    }, {
      key: "_checkAttributeArray",
      value: function _checkAttributeArray() {
        var value = this.value;
        var limit = Math.min(4, this.size);
  
        if (value && value.length >= limit) {
          var valid = true;
  
          switch (limit) {
            case 4:
              valid = valid && Number.isFinite(value[3]);
  
            case 3:
              valid = valid && Number.isFinite(value[2]);
  
            case 2:
              valid = valid && Number.isFinite(value[1]);
  
            case 1:
              valid = valid && Number.isFinite(value[0]);
              break;
  
            default:
              valid = false;
          }
  
          if (!valid) {
            throw new Error("Illegal attribute generated for ".concat(this.id));
          }
        }
      }
    }, {
      key: "startIndices",
      get: function get() {
        return this.state.startIndices;
      },
      set: function set(layout) {
        this.state.startIndices = layout;
      }
    }]);
    return Attribute;
  }(_dataColumn["default"]);
  
  exports["default"] = Attribute;
  //# sourceMappingURL=attribute.js.map