"use strict";

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

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

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 _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));

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

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

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

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

var _constants = require("@luma.gl/constants");

var _webgl = require("@luma.gl/webgl");

var _constants2 = require("./constants");

var _attributeManager = _interopRequireDefault(require("./attribute/attribute-manager"));

var _uniformTransitionManager = _interopRequireDefault(require("./uniform-transition-manager"));

var _props = require("../lifecycle/props");

var _constants3 = require("../lifecycle/constants");

var _count = require("../utils/count");

var _log = _interopRequireDefault(require("../utils/log"));

var _debug = _interopRequireDefault(require("../debug"));

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

var _memoize = _interopRequireDefault(require("../utils/memoize"));

var _shader = require("../utils/shader");

var _projectFunctions = require("../shaderlib/project/project-functions");

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

var _component = _interopRequireDefault(require("../lifecycle/component"));

var _layerState = _interopRequireDefault(require("./layer-state"));

var _webMercator = require("@math.gl/web-mercator");

var _core2 = require("@loaders.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; }

function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }

function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

var TRACE_CHANGE_FLAG = 'layer.changeFlag';
var TRACE_INITIALIZE = 'layer.initialize';
var TRACE_UPDATE = 'layer.update';
var TRACE_FINALIZE = 'layer.finalize';
var TRACE_MATCHED = 'layer.matched';
var MAX_PICKING_COLOR_CACHE_SIZE = Math.pow(2, 24) - 1;
var EMPTY_ARRAY = Object.freeze([]);
var areViewportsEqual = (0, _memoize.default)(function (_ref) {
  var oldViewport = _ref.oldViewport,
      viewport = _ref.viewport;
  return oldViewport.equals(viewport);
});
var pickingColorCache = new Uint8ClampedArray(0);
var defaultProps = {
  data: {
    type: 'data',
    value: EMPTY_ARRAY,
    async: true
  },
  dataComparator: {
    type: 'function',
    value: null,
    optional: true
  },
  _dataDiff: {
    type: 'function',
    value: function value(data) {
      return data && data.__diff;
    },
    optional: true
  },
  dataTransform: {
    type: 'function',
    value: null,
    optional: true
  },
  onDataLoad: {
    type: 'function',
    value: null,
    optional: true
  },
  onError: {
    type: 'function',
    value: null,
    optional: true
  },
  fetch: {
    type: 'function',
    value: function value(url, _ref2) {
      var propName = _ref2.propName,
          layer = _ref2.layer,
          loaders = _ref2.loaders,
          loadOptions = _ref2.loadOptions,
          signal = _ref2.signal;
      var resourceManager = layer.context.resourceManager;
      loadOptions = loadOptions || layer.getLoadOptions();
      loaders = loaders || layer.props.loaders;

      if (signal) {
        var _loadOptions;

        loadOptions = _objectSpread(_objectSpread({}, loadOptions), {}, {
          fetch: _objectSpread(_objectSpread({}, (_loadOptions = loadOptions) === null || _loadOptions === void 0 ? void 0 : _loadOptions.fetch), {}, {
            signal: signal
          })
        });
      }

      var inResourceManager = resourceManager.contains(url);

      if (!inResourceManager && !loadOptions) {
        resourceManager.add({
          resourceId: url,
          data: (0, _core2.load)(url, loaders),
          persistent: false
        });
        inResourceManager = true;
      }

      if (inResourceManager) {
        return resourceManager.subscribe({
          resourceId: url,
          onChange: function onChange(data) {
            var _layer$internalState;

            return (_layer$internalState = layer.internalState) === null || _layer$internalState === void 0 ? void 0 : _layer$internalState.reloadAsyncProp(propName, data);
          },
          consumerId: layer.id,
          requestId: propName
        });
      }

      return (0, _core2.load)(url, loaders, loadOptions);
    }
  },
  updateTriggers: {},
  visible: true,
  pickable: false,
  opacity: {
    type: 'number',
    min: 0,
    max: 1,
    value: 1
  },
  operation: 'draw',
  onHover: {
    type: 'function',
    value: null,
    optional: true
  },
  onClick: {
    type: 'function',
    value: null,
    optional: true
  },
  onDragStart: {
    type: 'function',
    value: null,
    optional: true
  },
  onDrag: {
    type: 'function',
    value: null,
    optional: true
  },
  onDragEnd: {
    type: 'function',
    value: null,
    optional: true
  },
  coordinateSystem: _constants2.COORDINATE_SYSTEM.DEFAULT,
  coordinateOrigin: {
    type: 'array',
    value: [0, 0, 0],
    compare: true
  },
  modelMatrix: {
    type: 'array',
    value: null,
    compare: true,
    optional: true
  },
  wrapLongitude: false,
  positionFormat: 'XYZ',
  colorFormat: 'RGBA',
  parameters: {
    type: 'object',
    value: {},
    optional: true,
    compare: 2
  },
  loadOptions: {
    type: 'object',
    value: null,
    optional: true,
    ignore: true
  },
  transitions: null,
  extensions: [],
  loaders: {
    type: 'array',
    value: [],
    optional: true,
    ignore: true
  },
  getPolygonOffset: {
    type: 'function',
    value: function value(_ref3) {
      var layerIndex = _ref3.layerIndex;
      return [0, -layerIndex * 100];
    }
  },
  highlightedObjectIndex: null,
  autoHighlight: false,
  highlightColor: {
    type: 'accessor',
    value: [0, 0, 128, 128]
  }
};

var Layer = function (_Component) {
  (0, _inherits2.default)(Layer, _Component);

  var _super = _createSuper(Layer);

  function Layer() {
    var _this;

    (0, _classCallCheck2.default)(this, Layer);

    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    _this = _super.call.apply(_super, [this].concat(args));
    _this.internalState = null;
    _this.lifecycle = _constants3.LIFECYCLE.NO_STATE;
    _this.context = void 0;
    _this.state = void 0;
    _this.parent = null;
    return _this;
  }

  var _proto = Layer.prototype;

  _proto.toString = function toString() {
    var className = this.constructor.layerName || this.constructor.name;
    return "".concat(className, "({id: '").concat(this.props.id, "'})");
  };

  _proto.project = function project(xyz) {
    (0, _assert.default)(this.internalState);
    var viewport = this.internalState.viewport || this.context.viewport;
    var worldPosition = (0, _projectFunctions.getWorldPosition)(xyz, {
      viewport: viewport,
      modelMatrix: this.props.modelMatrix,
      coordinateOrigin: this.props.coordinateOrigin,
      coordinateSystem: this.props.coordinateSystem
    });

    var _worldToPixels = (0, _webMercator.worldToPixels)(worldPosition, viewport.pixelProjectionMatrix),
        _worldToPixels2 = (0, _slicedToArray2.default)(_worldToPixels, 3),
        x = _worldToPixels2[0],
        y = _worldToPixels2[1],
        z = _worldToPixels2[2];

    return xyz.length === 2 ? [x, y] : [x, y, z];
  };

  _proto.unproject = function unproject(xy) {
    (0, _assert.default)(this.internalState);
    var viewport = this.internalState.viewport || this.context.viewport;
    return viewport.unproject(xy);
  };

  _proto.projectPosition = function projectPosition(xyz, params) {
    (0, _assert.default)(this.internalState);
    var viewport = this.internalState.viewport || this.context.viewport;
    return (0, _projectFunctions.projectPosition)(xyz, _objectSpread({
      viewport: viewport,
      modelMatrix: this.props.modelMatrix,
      coordinateOrigin: this.props.coordinateOrigin,
      coordinateSystem: this.props.coordinateSystem
    }, params));
  };

  _proto.setState = function setState(partialState) {
    this.setChangeFlags({
      stateChanged: true
    });
    Object.assign(this.state, partialState);
    this.setNeedsRedraw();
  };

  _proto.setNeedsRedraw = function setNeedsRedraw() {
    if (this.internalState) {
      this.internalState.needsRedraw = true;
    }
  };

  _proto.setNeedsUpdate = function setNeedsUpdate() {
    if (this.internalState) {
      this.context.layerManager.setNeedsUpdate(String(this));
      this.internalState.needsUpdate = true;
    }
  };

  _proto.isPickable = function isPickable() {
    return this.props.pickable && this.props.visible;
  };

  _proto.getModels = function getModels() {
    var state = this.state;
    return state && (state.models || state.model && [state.model]) || [];
  };

  _proto.setModuleParameters = function setModuleParameters(moduleParameters) {
    var _iterator = _createForOfIteratorHelper(this.getModels()),
        _step;

    try {
      for (_iterator.s(); !(_step = _iterator.n()).done;) {
        var model = _step.value;
        model.updateModuleSettings(moduleParameters);
      }
    } catch (err) {
      _iterator.e(err);
    } finally {
      _iterator.f();
    }
  };

  _proto.setShaderModuleProps = function setShaderModuleProps() {
    var _iterator2 = _createForOfIteratorHelper(this.getModels()),
        _step2;

    try {
      for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
        var _model$shaderInputs;

        var model = _step2.value;

        (_model$shaderInputs = model.shaderInputs).setProps.apply(_model$shaderInputs, arguments);
      }
    } catch (err) {
      _iterator2.e(err);
    } finally {
      _iterator2.f();
    }
  };

  _proto.getAttributeManager = function getAttributeManager() {
    return this.internalState && this.internalState.attributeManager;
  };

  _proto.getCurrentLayer = function getCurrentLayer() {
    return this.internalState && this.internalState.layer;
  };

  _proto.getLoadOptions = function getLoadOptions() {
    return this.props.loadOptions;
  };

  _proto.use64bitPositions = function use64bitPositions() {
    var coordinateSystem = this.props.coordinateSystem;
    return coordinateSystem === _constants2.COORDINATE_SYSTEM.DEFAULT || coordinateSystem === _constants2.COORDINATE_SYSTEM.LNGLAT || coordinateSystem === _constants2.COORDINATE_SYSTEM.CARTESIAN;
  };

  _proto.onHover = function onHover(info, pickingEvent) {
    if (this.props.onHover) {
      return this.props.onHover(info, pickingEvent) || false;
    }

    return false;
  };

  _proto.onClick = function onClick(info, pickingEvent) {
    if (this.props.onClick) {
      return this.props.onClick(info, pickingEvent) || false;
    }

    return false;
  };

  _proto.nullPickingColor = function nullPickingColor() {
    return [0, 0, 0];
  };

  _proto.encodePickingColor = function encodePickingColor(i) {
    var target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
    target[0] = i + 1 & 255;
    target[1] = i + 1 >> 8 & 255;
    target[2] = i + 1 >> 8 >> 8 & 255;
    return target;
  };

  _proto.decodePickingColor = function decodePickingColor(color) {
    (0, _assert.default)(color instanceof Uint8Array);

    var _color = (0, _slicedToArray2.default)(color, 3),
        i1 = _color[0],
        i2 = _color[1],
        i3 = _color[2];

    var index = i1 + i2 * 256 + i3 * 65536 - 1;
    return index;
  };

  _proto.getNumInstances = function getNumInstances() {
    if (Number.isFinite(this.props.numInstances)) {
      return this.props.numInstances;
    }

    if (this.state && this.state.numInstances !== undefined) {
      return this.state.numInstances;
    }

    return (0, _count.count)(this.props.data);
  };

  _proto.getStartIndices = function getStartIndices() {
    if (this.props.startIndices) {
      return this.props.startIndices;
    }

    if (this.state && this.state.startIndices) {
      return this.state.startIndices;
    }

    return null;
  };

  _proto.getBounds = function getBounds() {
    var _this$getAttributeMan;

    return (_this$getAttributeMan = this.getAttributeManager()) === null || _this$getAttributeMan === void 0 ? void 0 : _this$getAttributeMan.getBounds(['positions', 'instancePositions']);
  };

  _proto.getShaders = function getShaders(shaders) {
    var _iterator3 = _createForOfIteratorHelper(this.props.extensions),
        _step3;

    try {
      for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
        var extension = _step3.value;
        shaders = (0, _shader.mergeShaders)(shaders, extension.getShaders.call(this, extension));
      }
    } catch (err) {
      _iterator3.e(err);
    } finally {
      _iterator3.f();
    }

    return shaders;
  };

  _proto.shouldUpdateState = function shouldUpdateState(params) {
    return params.changeFlags.propsOrDataChanged;
  };

  _proto.updateState = function updateState(params) {
    var _this2 = this;

    var attributeManager = this.getAttributeManager();
    var dataChanged = params.changeFlags.dataChanged;

    if (dataChanged && attributeManager) {
      if (Array.isArray(dataChanged)) {
        var _iterator4 = _createForOfIteratorHelper(dataChanged),
            _step4;

        try {
          for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
            var dataRange = _step4.value;
            attributeManager.invalidateAll(dataRange);
          }
        } catch (err) {
          _iterator4.e(err);
        } finally {
          _iterator4.f();
        }
      } else {
        attributeManager.invalidateAll();
      }
    }

    if (attributeManager) {
      var props = params.props;
      var hasPickingBuffer = this.internalState.hasPickingBuffer;
      var needsPickingBuffer = Number.isInteger(props.highlightedObjectIndex) || props.pickable || props.extensions.some(function (extension) {
        return extension.getNeedsPickingBuffer.call(_this2, extension);
      });

      if (hasPickingBuffer !== needsPickingBuffer) {
        this.internalState.hasPickingBuffer = needsPickingBuffer;
        var _attributeManager$att = attributeManager.attributes,
            pickingColors = _attributeManager$att.pickingColors,
            instancePickingColors = _attributeManager$att.instancePickingColors;
        var pickingColorsAttribute = pickingColors || instancePickingColors;

        if (pickingColorsAttribute) {
          if (needsPickingBuffer && pickingColorsAttribute.constant) {
            pickingColorsAttribute.constant = false;
            attributeManager.invalidate(pickingColorsAttribute.id);
          }

          if (!pickingColorsAttribute.value && !needsPickingBuffer) {
            pickingColorsAttribute.constant = true;
            pickingColorsAttribute.value = [0, 0, 0];
          }
        }
      }
    }
  };

  _proto.finalizeState = function finalizeState(context) {
    var _iterator5 = _createForOfIteratorHelper(this.getModels()),
        _step5;

    try {
      for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
        var model = _step5.value;
        model.destroy();
      }
    } catch (err) {
      _iterator5.e(err);
    } finally {
      _iterator5.f();
    }

    var attributeManager = this.getAttributeManager();

    if (attributeManager) {
      attributeManager.finalize();
    }

    if (this.context) {
      this.context.resourceManager.unsubscribe({
        consumerId: this.id
      });
    }

    if (this.internalState) {
      this.internalState.uniformTransitions.clear();
      this.internalState.finalize();
    }
  };

  _proto.draw = function draw(opts) {
    var _iterator6 = _createForOfIteratorHelper(this.getModels()),
        _step6;

    try {
      for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
        var model = _step6.value;
        model.draw(opts);
      }
    } catch (err) {
      _iterator6.e(err);
    } finally {
      _iterator6.f();
    }
  };

  _proto.getPickingInfo = function getPickingInfo(_ref4) {
    var info = _ref4.info,
        mode = _ref4.mode,
        sourceLayer = _ref4.sourceLayer;
    var index = info.index;

    if (index >= 0) {
      if (Array.isArray(this.props.data)) {
        info.object = this.props.data[index];
      }
    }

    return info;
  };

  _proto.raiseError = function raiseError(error, message) {
    var _this$props$onError, _this$props;

    if (message) {
      error = new Error("".concat(message, ": ").concat(error.message), {
        cause: error
      });
    }

    if (!((_this$props$onError = (_this$props = this.props).onError) !== null && _this$props$onError !== void 0 && _this$props$onError.call(_this$props, error))) {
      var _this$context, _this$context$onError;

      (_this$context = this.context) === null || _this$context === void 0 ? void 0 : (_this$context$onError = _this$context.onError) === null || _this$context$onError === void 0 ? void 0 : _this$context$onError.call(_this$context, error, this);
    }
  };

  _proto.getNeedsRedraw = function getNeedsRedraw() {
    var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
      clearRedrawFlags: false
    };
    return this._getNeedsRedraw(opts);
  };

  _proto.needsUpdate = function needsUpdate() {
    if (!this.internalState) {
      return false;
    }

    return this.internalState.needsUpdate || this.hasUniformTransition() || this.shouldUpdateState(this._getUpdateParams());
  };

  _proto.hasUniformTransition = function hasUniformTransition() {
    var _this$internalState;

    return ((_this$internalState = this.internalState) === null || _this$internalState === void 0 ? void 0 : _this$internalState.uniformTransitions.active) || false;
  };

  _proto.activateViewport = function activateViewport(viewport) {
    if (!this.internalState) {
      return;
    }

    var oldViewport = this.internalState.viewport;
    this.internalState.viewport = viewport;

    if (!oldViewport || !areViewportsEqual({
      oldViewport: oldViewport,
      viewport: viewport
    })) {
      this.setChangeFlags({
        viewportChanged: true
      });

      if (this.isComposite) {
        if (this.needsUpdate()) {
          this.setNeedsUpdate();
        }
      } else {
        this._update();
      }
    }
  };

  _proto.invalidateAttribute = function invalidateAttribute() {
    var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'all';
    var attributeManager = this.getAttributeManager();

    if (!attributeManager) {
      return;
    }

    if (name === 'all') {
      attributeManager.invalidateAll();
    } else {
      attributeManager.invalidate(name);
    }
  };

  _proto.updateAttributes = function updateAttributes(changedAttributes) {
    var bufferLayoutChanged = false;

    for (var _id in changedAttributes) {
      if (changedAttributes[_id].layoutChanged()) {
        bufferLayoutChanged = true;
      }
    }

    var _iterator7 = _createForOfIteratorHelper(this.getModels()),
        _step7;

    try {
      for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
        var model = _step7.value;

        this._setModelAttributes(model, changedAttributes, bufferLayoutChanged);
      }
    } catch (err) {
      _iterator7.e(err);
    } finally {
      _iterator7.f();
    }
  };

  _proto._updateAttributes = function _updateAttributes() {
    var attributeManager = this.getAttributeManager();

    if (!attributeManager) {
      return;
    }

    var props = this.props;
    var numInstances = this.getNumInstances();
    var startIndices = this.getStartIndices();
    attributeManager.update({
      data: props.data,
      numInstances: numInstances,
      startIndices: startIndices,
      props: props,
      transitions: props.transitions,
      buffers: props.data.attributes,
      context: this
    });
    var changedAttributes = attributeManager.getChangedAttributes({
      clearChangedFlags: true
    });
    this.updateAttributes(changedAttributes);
  };

  _proto._updateAttributeTransition = function _updateAttributeTransition() {
    var attributeManager = this.getAttributeManager();

    if (attributeManager) {
      attributeManager.updateTransition();
    }
  };

  _proto._updateUniformTransition = function _updateUniformTransition() {
    var uniformTransitions = this.internalState.uniformTransitions;

    if (uniformTransitions.active) {
      var propsInTransition = uniformTransitions.update();
      var props = Object.create(this.props);

      for (var _key2 in propsInTransition) {
        Object.defineProperty(props, _key2, {
          value: propsInTransition[_key2]
        });
      }

      return props;
    }

    return this.props;
  };

  _proto.calculateInstancePickingColors = function calculateInstancePickingColors(attribute, _ref5) {
    var numInstances = _ref5.numInstances;

    if (attribute.constant) {
      return;
    }

    var cacheSize = Math.floor(pickingColorCache.length / 4);
    this.internalState.usesPickingColorCache = true;

    if (cacheSize < numInstances) {
      if (numInstances > MAX_PICKING_COLOR_CACHE_SIZE) {
        _log.default.warn('Layer has too many data objects. Picking might not be able to distinguish all objects.')();
      }

      pickingColorCache = _typedArrayManager.default.allocate(pickingColorCache, numInstances, {
        size: 4,
        copy: true,
        maxCount: Math.max(numInstances, MAX_PICKING_COLOR_CACHE_SIZE)
      });
      var newCacheSize = Math.floor(pickingColorCache.length / 4);
      var pickingColor = [];

      for (var i = cacheSize; i < newCacheSize; i++) {
        this.encodePickingColor(i, pickingColor);
        pickingColorCache[i * 4 + 0] = pickingColor[0];
        pickingColorCache[i * 4 + 1] = pickingColor[1];
        pickingColorCache[i * 4 + 2] = pickingColor[2];
      }
    }

    attribute.value = pickingColorCache.subarray(0, numInstances * 4);
  };

  _proto._setModelAttributes = function _setModelAttributes(model, changedAttributes) {
    var _model$userData;

    var bufferLayoutChanged = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;

    if (!Object.keys(changedAttributes).length) {
      return;
    }

    if (bufferLayoutChanged) {
      var attributeManager = this.getAttributeManager();
      model.setBufferLayout(attributeManager.getBufferLayouts());
      changedAttributes = attributeManager.getAttributes();
    }

    var excludeAttributes = ((_model$userData = model.userData) === null || _model$userData === void 0 ? void 0 : _model$userData.excludeAttributes) || {};
    var attributeBuffers = {};
    var constantAttributes = {};

    for (var name in changedAttributes) {
      if (excludeAttributes[name]) {
        continue;
      }

      var values = changedAttributes[name].getValue();

      for (var attributeName in values) {
        var value = values[attributeName];

        if (value instanceof _core.Buffer) {
          if (changedAttributes[name].settings.isIndexed) {
            model.setIndexBuffer(value);
          } else {
            attributeBuffers[attributeName] = value;
          }
        } else if (value) {
          constantAttributes[attributeName] = value;
        }
      }
    }

    model.setAttributes(attributeBuffers);
    model.setConstantAttributes(constantAttributes);
  };

  _proto.disablePickingIndex = function disablePickingIndex(objectIndex) {
    var data = this.props.data;

    if (!('attributes' in data)) {
      this._disablePickingIndex(objectIndex);

      return;
    }

    var _this$getAttributeMan2 = this.getAttributeManager().attributes,
        pickingColors = _this$getAttributeMan2.pickingColors,
        instancePickingColors = _this$getAttributeMan2.instancePickingColors;
    var colors = pickingColors || instancePickingColors;
    var externalColorAttribute = colors && data.attributes && data.attributes[colors.id];

    if (externalColorAttribute && externalColorAttribute.value) {
      var values = externalColorAttribute.value;
      var objectColor = this.encodePickingColor(objectIndex);

      for (var index = 0; index < data.length; index++) {
        var i = colors.getVertexOffset(index);

        if (values[i] === objectColor[0] && values[i + 1] === objectColor[1] && values[i + 2] === objectColor[2]) {
          this._disablePickingIndex(index);
        }
      }
    } else {
      this._disablePickingIndex(objectIndex);
    }
  };

  _proto._disablePickingIndex = function _disablePickingIndex(objectIndex) {
    var _this$getAttributeMan3 = this.getAttributeManager().attributes,
        pickingColors = _this$getAttributeMan3.pickingColors,
        instancePickingColors = _this$getAttributeMan3.instancePickingColors;
    var colors = pickingColors || instancePickingColors;

    if (!colors) {
      return;
    }

    var start = colors.getVertexOffset(objectIndex);
    var end = colors.getVertexOffset(objectIndex + 1);
    colors.buffer.write(new Uint8Array(end - start), start);
  };

  _proto.restorePickingColors = function restorePickingColors() {
    var _this$getAttributeMan4 = this.getAttributeManager().attributes,
        pickingColors = _this$getAttributeMan4.pickingColors,
        instancePickingColors = _this$getAttributeMan4.instancePickingColors;
    var colors = pickingColors || instancePickingColors;

    if (!colors) {
      return;
    }

    if (this.internalState.usesPickingColorCache && colors.value.buffer !== pickingColorCache.buffer) {
      colors.value = pickingColorCache.subarray(0, colors.value.length);
    }

    colors.updateSubBuffer({
      startOffset: 0
    });
  };

  _proto._initialize = function _initialize() {
    (0, _assert.default)(!this.internalState);
    (0, _assert.default)(Number.isFinite(this.props.coordinateSystem));
    (0, _debug.default)(TRACE_INITIALIZE, this);

    var attributeManager = this._getAttributeManager();

    if (attributeManager) {
      attributeManager.addInstanced({
        instancePickingColors: {
          type: 5121,
          size: 4,
          noAlloc: true,
          update: this.calculateInstancePickingColors
        }
      });
    }

    this.internalState = new _layerState.default({
      attributeManager: attributeManager,
      layer: this
    });

    this._clearChangeFlags();

    this.state = {};
    Object.defineProperty(this.state, 'attributeManager', {
      get: function get() {
        _log.default.deprecated('layer.state.attributeManager', 'layer.getAttributeManager()')();

        return attributeManager;
      }
    });
    this.internalState.uniformTransitions = new _uniformTransitionManager.default(this.context.timeline);
    this.internalState.onAsyncPropUpdated = this._onAsyncPropUpdated.bind(this);
    this.internalState.setAsyncProps(this.props);
    this.initializeState(this.context);

    var _iterator8 = _createForOfIteratorHelper(this.props.extensions),
        _step8;

    try {
      for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {
        var extension = _step8.value;
        extension.initializeState.call(this, this.context, extension);
      }
    } catch (err) {
      _iterator8.e(err);
    } finally {
      _iterator8.f();
    }

    this.setChangeFlags({
      dataChanged: 'init',
      propsChanged: 'init',
      viewportChanged: true,
      extensionsChanged: true
    });

    this._update();
  };

  _proto._transferState = function _transferState(oldLayer) {
    (0, _debug.default)(TRACE_MATCHED, this, this === oldLayer);
    var state = oldLayer.state,
        internalState = oldLayer.internalState;

    if (this === oldLayer) {
      return;
    }

    this.internalState = internalState;
    this.state = state;
    this.internalState.setAsyncProps(this.props);

    this._diffProps(this.props, this.internalState.getOldProps());
  };

  _proto._update = function _update() {
    var stateNeedsUpdate = this.needsUpdate();
    (0, _debug.default)(TRACE_UPDATE, this, stateNeedsUpdate);

    if (!stateNeedsUpdate) {
      return;
    }

    var currentProps = this.props;
    var context = this.context;
    var internalState = this.internalState;
    var currentViewport = context.viewport;

    var propsInTransition = this._updateUniformTransition();

    internalState.propsInTransition = propsInTransition;
    context.viewport = internalState.viewport || currentViewport;
    this.props = propsInTransition;

    try {
      var updateParams = this._getUpdateParams();

      var oldModels = this.getModels();

      if (context.device) {
        this.updateState(updateParams);
      } else {
        try {
          this.updateState(updateParams);
        } catch (error) {}
      }

      var _iterator9 = _createForOfIteratorHelper(this.props.extensions),
          _step9;

      try {
        for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {
          var extension = _step9.value;
          extension.updateState.call(this, updateParams, extension);
        }
      } catch (err) {
        _iterator9.e(err);
      } finally {
        _iterator9.f();
      }

      var modelChanged = this.getModels()[0] !== oldModels[0];

      this._postUpdate(updateParams, modelChanged);
    } finally {
      context.viewport = currentViewport;
      this.props = currentProps;

      this._clearChangeFlags();

      internalState.needsUpdate = false;
      internalState.resetOldProps();
    }
  };

  _proto._finalize = function _finalize() {
    (0, _debug.default)(TRACE_FINALIZE, this);
    this.finalizeState(this.context);

    var _iterator10 = _createForOfIteratorHelper(this.props.extensions),
        _step10;

    try {
      for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {
        var extension = _step10.value;
        extension.finalizeState.call(this, this.context, extension);
      }
    } catch (err) {
      _iterator10.e(err);
    } finally {
      _iterator10.f();
    }
  };

  _proto._drawLayer = function _drawLayer(_ref6) {
    var _this3 = this;

    var renderPass = _ref6.renderPass,
        _ref6$moduleParameter = _ref6.moduleParameters,
        moduleParameters = _ref6$moduleParameter === void 0 ? null : _ref6$moduleParameter,
        _ref6$uniforms = _ref6.uniforms,
        uniforms = _ref6$uniforms === void 0 ? {} : _ref6$uniforms,
        _ref6$parameters = _ref6.parameters,
        parameters = _ref6$parameters === void 0 ? {} : _ref6$parameters;

    this._updateAttributeTransition();

    var currentProps = this.props;
    var context = this.context;
    this.props = this.internalState.propsInTransition || currentProps;
    var opacity = this.props.opacity;
    uniforms.opacity = Math.pow(opacity, 1 / 2.2);

    try {
      if (moduleParameters) {
        var _moduleParameters$pic = moduleParameters.picking,
            isActive = _moduleParameters$pic.isActive,
            isAttribute = _moduleParameters$pic.isAttribute;
        this.setModuleParameters(moduleParameters);
        this.setShaderModuleProps({
          picking: {
            isActive: isActive,
            isAttribute: isAttribute
          }
        });
      }

      var getPolygonOffset = this.props.getPolygonOffset;
      var offsets = getPolygonOffset && getPolygonOffset(uniforms) || [0, 0];
      (0, _webgl.setGLParameters)(context.device, {
        polygonOffset: offsets
      });
      (0, _webgl.withGLParameters)(context.gl, parameters, function () {
        var opts = {
          renderPass: renderPass,
          moduleParameters: moduleParameters,
          uniforms: uniforms,
          parameters: parameters,
          context: context
        };

        var _iterator11 = _createForOfIteratorHelper(_this3.props.extensions),
            _step11;

        try {
          for (_iterator11.s(); !(_step11 = _iterator11.n()).done;) {
            var extension = _step11.value;
            extension.draw.call(_this3, opts, extension);
          }
        } catch (err) {
          _iterator11.e(err);
        } finally {
          _iterator11.f();
        }

        _this3.draw(opts);
      });
    } finally {
      this.props = currentProps;
    }
  };

  _proto.getChangeFlags = function getChangeFlags() {
    var _this$internalState2;

    return (_this$internalState2 = this.internalState) === null || _this$internalState2 === void 0 ? void 0 : _this$internalState2.changeFlags;
  };

  _proto.setChangeFlags = function setChangeFlags(flags) {
    if (!this.internalState) {
      return;
    }

    var changeFlags = this.internalState.changeFlags;

    for (var _key3 in flags) {
      if (flags[_key3]) {
        var flagChanged = false;

        switch (_key3) {
          case 'dataChanged':
            var dataChangedReason = flags[_key3];
            var prevDataChangedReason = changeFlags[_key3];

            if (dataChangedReason && Array.isArray(prevDataChangedReason)) {
              changeFlags.dataChanged = Array.isArray(dataChangedReason) ? prevDataChangedReason.concat(dataChangedReason) : dataChangedReason;
              flagChanged = true;
            }

          default:
            if (!changeFlags[_key3]) {
              changeFlags[_key3] = flags[_key3];
              flagChanged = true;
            }

        }

        if (flagChanged) {
          (0, _debug.default)(TRACE_CHANGE_FLAG, this, _key3, flags);
        }
      }
    }

    var propsOrDataChanged = Boolean(changeFlags.dataChanged || changeFlags.updateTriggersChanged || changeFlags.propsChanged || changeFlags.extensionsChanged);
    changeFlags.propsOrDataChanged = propsOrDataChanged;
    changeFlags.somethingChanged = propsOrDataChanged || changeFlags.viewportChanged || changeFlags.stateChanged;
  };

  _proto._clearChangeFlags = function _clearChangeFlags() {
    this.internalState.changeFlags = {
      dataChanged: false,
      propsChanged: false,
      updateTriggersChanged: false,
      viewportChanged: false,
      stateChanged: false,
      extensionsChanged: false,
      propsOrDataChanged: false,
      somethingChanged: false
    };
  };

  _proto._diffProps = function _diffProps(newProps, oldProps) {
    var changeFlags = (0, _props.diffProps)(newProps, oldProps);

    if (changeFlags.updateTriggersChanged) {
      for (var _key4 in changeFlags.updateTriggersChanged) {
        if (changeFlags.updateTriggersChanged[_key4]) {
          this.invalidateAttribute(_key4);
        }
      }
    }

    if (changeFlags.transitionsChanged) {
      for (var _key5 in changeFlags.transitionsChanged) {
        var _newProps$transitions;

        this.internalState.uniformTransitions.add(_key5, oldProps[_key5], newProps[_key5], (_newProps$transitions = newProps.transitions) === null || _newProps$transitions === void 0 ? void 0 : _newProps$transitions[_key5]);
      }
    }

    return this.setChangeFlags(changeFlags);
  };

  _proto.validateProps = function validateProps() {
    (0, _props.validateProps)(this.props);
  };

  _proto.updateAutoHighlight = function updateAutoHighlight(info) {
    if (this.props.autoHighlight && !Number.isInteger(this.props.highlightedObjectIndex)) {
      this._updateAutoHighlight(info);
    }
  };

  _proto._updateAutoHighlight = function _updateAutoHighlight(info) {
    var picking = {
      highlightedObjectColor: info.picked ? info.color : null
    };
    var highlightColor = this.props.highlightColor;

    if (info.picked && typeof highlightColor === 'function') {
      picking.highlightColor = highlightColor(info);
    }

    this.setShaderModuleProps({
      picking: picking
    });
    this.setNeedsRedraw();
  };

  _proto._getAttributeManager = function _getAttributeManager() {
    var context = this.context;
    return new _attributeManager.default(context.device, {
      id: this.props.id,
      stats: context.stats,
      timeline: context.timeline
    });
  };

  _proto._postUpdate = function _postUpdate(updateParams, forceUpdate) {
    var props = updateParams.props,
        oldProps = updateParams.oldProps;
    this.setNeedsRedraw();

    this._updateAttributes();

    var model = this.state.model;
    model === null || model === void 0 ? void 0 : model.setInstanceCount(this.getNumInstances());
    var autoHighlight = props.autoHighlight,
        highlightedObjectIndex = props.highlightedObjectIndex,
        highlightColor = props.highlightColor;

    if (forceUpdate || oldProps.autoHighlight !== autoHighlight || oldProps.highlightedObjectIndex !== highlightedObjectIndex || oldProps.highlightColor !== highlightColor) {
      var picking = {};

      if (!autoHighlight) {
        picking.highlightedObjectColor = null;
      }

      if (Array.isArray(highlightColor)) {
        picking.highlightColor = highlightColor;
      }

      if (forceUpdate || highlightedObjectIndex !== oldProps.highlightedObjectIndex) {
        picking.highlightedObjectColor = Number.isFinite(highlightedObjectIndex) && highlightedObjectIndex >= 0 ? this.encodePickingColor(highlightedObjectIndex) : null;
      }

      this.setShaderModuleProps({
        picking: picking
      });
    }
  };

  _proto._getUpdateParams = function _getUpdateParams() {
    return {
      props: this.props,
      oldProps: this.internalState.getOldProps(),
      context: this.context,
      changeFlags: this.internalState.changeFlags
    };
  };

  _proto._getNeedsRedraw = function _getNeedsRedraw(opts) {
    if (!this.internalState) {
      return false;
    }

    var redraw = false;
    redraw = redraw || this.internalState.needsRedraw && this.id;
    var attributeManager = this.getAttributeManager();
    var attributeManagerNeedsRedraw = attributeManager ? attributeManager.getNeedsRedraw(opts) : false;
    redraw = redraw || attributeManagerNeedsRedraw;

    if (redraw) {
      var _iterator12 = _createForOfIteratorHelper(this.props.extensions),
          _step12;

      try {
        for (_iterator12.s(); !(_step12 = _iterator12.n()).done;) {
          var extension = _step12.value;
          extension.onNeedsRedraw.call(this, extension);
        }
      } catch (err) {
        _iterator12.e(err);
      } finally {
        _iterator12.f();
      }
    }

    this.internalState.needsRedraw = this.internalState.needsRedraw && !opts.clearRedrawFlags;
    return redraw;
  };

  _proto._onAsyncPropUpdated = function _onAsyncPropUpdated() {
    this._diffProps(this.props, this.internalState.getOldProps());

    this.setNeedsUpdate();
  };

  (0, _createClass2.default)(Layer, [{
    key: "root",
    get: function get() {
      var layer = this;

      while (layer.parent) {
        layer = layer.parent;
      }

      return layer;
    }
  }, {
    key: "isComposite",
    get: function get() {
      return false;
    }
  }, {
    key: "isLoaded",
    get: function get() {
      return this.internalState ? !this.internalState.isAsyncPropLoading() : false;
    }
  }, {
    key: "wrapLongitude",
    get: function get() {
      return this.props.wrapLongitude;
    }
  }], [{
    key: "componentName",
    get: function get() {
      return Object.prototype.hasOwnProperty.call(this, 'layerName') ? this.layerName : '';
    }
  }]);
  return Layer;
}(_component.default);

exports.default = Layer;
Layer.defaultProps = defaultProps;
Layer.layerName = 'Layer';
//# sourceMappingURL=layer.js.map