@mapwhit/tilerenderer 0.52.1 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/README.md +7 -0
  2. package/build/min/package.json +2 -1
  3. package/build/min/src/shaders/_prelude.fragment.glsl.js +2 -2
  4. package/build/min/src/shaders/_prelude.vertex.glsl.js +2 -2
  5. package/build/min/src/shaders/background.fragment.glsl.js +2 -2
  6. package/build/min/src/shaders/background.vertex.glsl.js +1 -1
  7. package/build/min/src/shaders/background_pattern.fragment.glsl.js +2 -2
  8. package/build/min/src/shaders/background_pattern.vertex.glsl.js +1 -1
  9. package/build/min/src/shaders/circle.fragment.glsl.js +2 -2
  10. package/build/min/src/shaders/circle.vertex.glsl.js +2 -2
  11. package/build/min/src/shaders/clipping_mask.fragment.glsl.js +1 -1
  12. package/build/min/src/shaders/clipping_mask.vertex.glsl.js +1 -1
  13. package/build/min/src/shaders/collision_box.fragment.glsl.js +1 -1
  14. package/build/min/src/shaders/collision_box.vertex.glsl.js +1 -1
  15. package/build/min/src/shaders/collision_circle.fragment.glsl.js +1 -1
  16. package/build/min/src/shaders/collision_circle.vertex.glsl.js +1 -1
  17. package/build/min/src/shaders/debug.fragment.glsl.js +1 -1
  18. package/build/min/src/shaders/debug.vertex.glsl.js +1 -1
  19. package/build/min/src/shaders/fill.fragment.glsl.js +2 -2
  20. package/build/min/src/shaders/fill.vertex.glsl.js +2 -2
  21. package/build/min/src/shaders/fill_extrusion.fragment.glsl.js +2 -2
  22. package/build/min/src/shaders/fill_extrusion.vertex.glsl.js +2 -2
  23. package/build/min/src/shaders/fill_extrusion_pattern.fragment.glsl.js +2 -2
  24. package/build/min/src/shaders/fill_extrusion_pattern.vertex.glsl.js +2 -2
  25. package/build/min/src/shaders/fill_outline.fragment.glsl.js +2 -2
  26. package/build/min/src/shaders/fill_outline.vertex.glsl.js +2 -2
  27. package/build/min/src/shaders/fill_outline_pattern.fragment.glsl.js +2 -2
  28. package/build/min/src/shaders/fill_outline_pattern.vertex.glsl.js +2 -2
  29. package/build/min/src/shaders/fill_pattern.fragment.glsl.js +2 -2
  30. package/build/min/src/shaders/fill_pattern.vertex.glsl.js +2 -2
  31. package/build/min/src/shaders/heatmap.fragment.glsl.js +2 -2
  32. package/build/min/src/shaders/heatmap.vertex.glsl.js +2 -2
  33. package/build/min/src/shaders/heatmap_texture.fragment.glsl.js +2 -2
  34. package/build/min/src/shaders/heatmap_texture.vertex.glsl.js +1 -1
  35. package/build/min/src/shaders/hillshade.fragment.glsl.js +2 -2
  36. package/build/min/src/shaders/hillshade.vertex.glsl.js +1 -1
  37. package/build/min/src/shaders/hillshade_prepare.fragment.glsl.js +2 -2
  38. package/build/min/src/shaders/hillshade_prepare.vertex.glsl.js +1 -1
  39. package/build/min/src/shaders/line.fragment.glsl.js +2 -2
  40. package/build/min/src/shaders/line.vertex.glsl.js +2 -2
  41. package/build/min/src/shaders/line_gradient.fragment.glsl.js +2 -2
  42. package/build/min/src/shaders/line_gradient.vertex.glsl.js +2 -2
  43. package/build/min/src/shaders/line_pattern.fragment.glsl.js +2 -2
  44. package/build/min/src/shaders/line_pattern.vertex.glsl.js +2 -2
  45. package/build/min/src/shaders/line_sdf.fragment.glsl.js +2 -2
  46. package/build/min/src/shaders/line_sdf.vertex.glsl.js +2 -2
  47. package/build/min/src/shaders/raster.fragment.glsl.js +2 -2
  48. package/build/min/src/shaders/raster.vertex.glsl.js +1 -1
  49. package/build/min/src/shaders/symbol_icon.fragment.glsl.js +2 -2
  50. package/build/min/src/shaders/symbol_icon.vertex.glsl.js +2 -2
  51. package/build/min/src/shaders/symbol_sdf.fragment.glsl.js +2 -2
  52. package/build/min/src/shaders/symbol_sdf.vertex.glsl.js +2 -2
  53. package/package.json +5 -4
  54. package/src/data/array_types.js +55 -117
  55. package/src/data/bucket/circle_attributes.js +2 -4
  56. package/src/data/bucket/circle_bucket.js +19 -16
  57. package/src/data/bucket/fill_attributes.js +2 -4
  58. package/src/data/bucket/fill_bucket.js +38 -27
  59. package/src/data/bucket/fill_extrusion_attributes.js +2 -4
  60. package/src/data/bucket/fill_extrusion_bucket.js +56 -37
  61. package/src/data/bucket/heatmap_bucket.js +2 -11
  62. package/src/data/bucket/line_attributes.js +2 -4
  63. package/src/data/bucket/line_bucket.js +208 -163
  64. package/src/data/bucket/pattern_attributes.js +2 -4
  65. package/src/data/bucket/pattern_bucket_features.js +7 -9
  66. package/src/data/bucket/symbol_attributes.js +12 -26
  67. package/src/data/bucket/symbol_bucket.js +174 -323
  68. package/src/data/bucket/symbol_buffers.js +62 -0
  69. package/src/data/bucket/symbol_collision_buffers.js +33 -0
  70. package/src/data/bucket.js +26 -25
  71. package/src/data/dem_data.js +11 -10
  72. package/src/data/extent.js +1 -1
  73. package/src/data/feature_index.js +38 -28
  74. package/src/data/index_array_type.js +1 -6
  75. package/src/data/load_geometry.js +6 -9
  76. package/src/data/pos_attributes.js +2 -3
  77. package/src/data/program_configuration.js +47 -38
  78. package/src/data/raster_bounds_attributes.js +2 -2
  79. package/src/data/segment.js +4 -7
  80. package/src/geo/coordinate.js +1 -1
  81. package/src/geo/lng_lat.js +3 -3
  82. package/src/geo/lng_lat_bounds.js +8 -4
  83. package/src/geo/transform.js +69 -30
  84. package/src/gl/color_mode.js +2 -2
  85. package/src/gl/context.js +28 -29
  86. package/src/gl/cull_face_mode.js +1 -1
  87. package/src/gl/depth_mode.js +1 -1
  88. package/src/gl/framebuffer.js +8 -4
  89. package/src/gl/index_buffer.js +2 -2
  90. package/src/gl/stencil_mode.js +1 -1
  91. package/src/gl/value.js +33 -68
  92. package/src/gl/vertex_buffer.js +2 -2
  93. package/src/index.js +49 -25
  94. package/src/render/draw_background.js +17 -12
  95. package/src/render/draw_circle.js +15 -12
  96. package/src/render/draw_collision_debug.js +11 -8
  97. package/src/render/draw_debug.js +16 -14
  98. package/src/render/draw_fill.js +27 -20
  99. package/src/render/draw_fill_extrusion.js +20 -17
  100. package/src/render/draw_heatmap.js +21 -16
  101. package/src/render/draw_hillshade.js +12 -9
  102. package/src/render/draw_line.js +36 -22
  103. package/src/render/draw_raster.js +22 -18
  104. package/src/render/draw_symbol.js +38 -33
  105. package/src/render/glyph_atlas.js +9 -8
  106. package/src/render/glyph_manager.js +2 -3
  107. package/src/render/image_atlas.js +4 -11
  108. package/src/render/image_manager.js +39 -28
  109. package/src/render/line_atlas.js +2 -2
  110. package/src/render/painter.js +78 -61
  111. package/src/render/program/background_program.js +6 -13
  112. package/src/render/program/circle_program.js +8 -10
  113. package/src/render/program/clipping_mask_program.js +3 -5
  114. package/src/render/program/collision_program.js +4 -6
  115. package/src/render/program/debug_program.js +3 -5
  116. package/src/render/program/fill_extrusion_program.js +9 -15
  117. package/src/render/program/fill_program.js +10 -21
  118. package/src/render/program/heatmap_program.js +9 -15
  119. package/src/render/program/hillshade_program.js +16 -22
  120. package/src/render/program/line_program.js +14 -25
  121. package/src/render/program/pattern.js +5 -7
  122. package/src/render/program/program_uniforms.js +13 -20
  123. package/src/render/program/raster_program.js +9 -11
  124. package/src/render/program/symbol_program.js +5 -7
  125. package/src/render/program.js +5 -6
  126. package/src/render/texture.js +1 -1
  127. package/src/render/tile_mask.js +6 -4
  128. package/src/render/uniform_binding.js +9 -20
  129. package/src/render/vertex_array_object.js +5 -3
  130. package/src/shaders/encode_attribute.js +2 -6
  131. package/src/shaders/index.js +103 -51
  132. package/src/source/geojson_source.js +25 -30
  133. package/src/source/geojson_worker_source.js +46 -74
  134. package/src/source/geojson_wrapper.js +13 -5
  135. package/src/source/image_source.js +17 -28
  136. package/src/source/load_tilejson.js +3 -3
  137. package/src/source/pixels_to_tile_units.js +3 -3
  138. package/src/source/query_features.js +17 -15
  139. package/src/source/raster_dem_tile_source.js +54 -71
  140. package/src/source/raster_tile_source.js +14 -15
  141. package/src/source/resources/glyphs.js +4 -5
  142. package/src/source/resources/index.js +4 -12
  143. package/src/source/rtl_text_plugin.js +62 -35
  144. package/src/source/source.js +14 -22
  145. package/src/source/source_cache.js +221 -179
  146. package/src/source/source_state.js +125 -13
  147. package/src/source/tile.js +67 -66
  148. package/src/source/tile_bounds.js +36 -29
  149. package/src/source/tile_cache.js +2 -2
  150. package/src/source/tile_id.js +30 -26
  151. package/src/source/vector_tile_source.js +23 -21
  152. package/src/source/vector_tile_worker_source.js +22 -26
  153. package/src/source/worker_tile.js +139 -134
  154. package/src/style/create_style_layer.js +11 -11
  155. package/src/style/evaluation_parameters.js +4 -6
  156. package/src/style/light.js +5 -5
  157. package/src/style/load_sprite.js +6 -6
  158. package/src/style/parse_glyph_pbf.js +21 -17
  159. package/src/style/pauseable_placement.js +7 -9
  160. package/src/style/properties.js +21 -51
  161. package/src/style/query_utils.js +7 -13
  162. package/src/style/style.js +314 -221
  163. package/src/style/style_layer/background_style_layer.js +3 -4
  164. package/src/style/style_layer/background_style_layer_properties.js +2 -2
  165. package/src/style/style_layer/circle_style_layer.js +25 -20
  166. package/src/style/style_layer/circle_style_layer_properties.js +2 -2
  167. package/src/style/style_layer/fill_extrusion_style_layer.js +55 -37
  168. package/src/style/style_layer/fill_extrusion_style_layer_properties.js +2 -2
  169. package/src/style/style_layer/fill_style_layer.js +11 -12
  170. package/src/style/style_layer/fill_style_layer_properties.js +2 -2
  171. package/src/style/style_layer/heatmap_style_layer.js +6 -7
  172. package/src/style/style_layer/heatmap_style_layer_properties.js +2 -2
  173. package/src/style/style_layer/hillshade_style_layer.js +4 -5
  174. package/src/style/style_layer/hillshade_style_layer_properties.js +2 -2
  175. package/src/style/style_layer/line_style_layer.js +33 -30
  176. package/src/style/style_layer/line_style_layer_properties.js +5 -5
  177. package/src/style/style_layer/raster_style_layer.js +3 -4
  178. package/src/style/style_layer/raster_style_layer_properties.js +2 -2
  179. package/src/style/style_layer/symbol_style_layer.js +20 -21
  180. package/src/style/style_layer/symbol_style_layer_properties.js +2 -2
  181. package/src/style/style_layer.js +66 -47
  182. package/src/style/style_layer_index.js +17 -42
  183. package/src/style/zoom_history.js +1 -1
  184. package/src/style-spec/error/parsing_error.js +1 -1
  185. package/src/style-spec/error/validation_error.js +5 -3
  186. package/src/style-spec/feature_filter/convert.js +17 -9
  187. package/src/style-spec/feature_filter/index.js +13 -9
  188. package/src/style-spec/util/eval_support.js +2 -2
  189. package/src/style-spec/util/ref_properties.js +1 -1
  190. package/src/symbol/anchor.js +2 -6
  191. package/src/symbol/check_max_angle.js +13 -5
  192. package/src/symbol/clip_line.js +2 -3
  193. package/src/symbol/collision_feature.js +8 -4
  194. package/src/symbol/collision_index.js +5 -7
  195. package/src/symbol/cross_tile_symbol_index.js +7 -10
  196. package/src/symbol/get_anchors.js +15 -8
  197. package/src/symbol/grid_index.js +5 -3
  198. package/src/symbol/mergelines.js +2 -2
  199. package/src/symbol/opacity_state.js +1 -5
  200. package/src/symbol/placement.js +28 -23
  201. package/src/symbol/projection.js +29 -28
  202. package/src/symbol/quads.js +14 -16
  203. package/src/symbol/shaping.js +27 -19
  204. package/src/symbol/symbol_layout.js +24 -28
  205. package/src/symbol/symbol_size.js +13 -12
  206. package/src/symbol/transform_text.js +4 -4
  207. package/src/ui/camera.js +34 -18
  208. package/src/ui/map.js +102 -44
  209. package/src/util/async.js +11 -5
  210. package/src/util/browser.js +1 -1
  211. package/src/util/callback.js +3 -9
  212. package/src/util/classify_rings.js +13 -8
  213. package/src/util/color_ramp.js +3 -3
  214. package/src/util/config.js +4 -4
  215. package/src/util/dictionary_coder.js +2 -3
  216. package/src/util/dom.js +7 -3
  217. package/src/util/find_pole_of_inaccessibility.js +29 -14
  218. package/src/util/group_layers.js +41 -0
  219. package/src/util/image.js +3 -13
  220. package/src/util/interpolate.js +1 -1
  221. package/src/util/intersection_tests.js +80 -42
  222. package/src/util/is_char_in_unicode_block.js +1 -1
  223. package/src/util/key.js +25 -0
  224. package/src/util/loader/image.js +1 -1
  225. package/src/util/object.js +33 -76
  226. package/src/util/script_detection.js +212 -91
  227. package/src/util/struct_array.js +8 -40
  228. package/src/util/task_queue.js +11 -7
  229. package/src/util/throttle.js +2 -2
  230. package/src/util/tile_cover.js +8 -5
  231. package/src/util/token.js +1 -1
  232. package/src/util/unique_id.js +2 -2
  233. package/src/util/util.js +21 -29
  234. package/src/util/vectortile_to_geojson.js +4 -2
  235. package/src/util/verticalize_punctuation.js +3 -7
  236. package/src/util/warn.js +4 -4
  237. package/src/util/web_worker.js +3 -3
  238. package/src/worker.js +1 -4
  239. package/src/source/resources/images.js +0 -68
  240. package/src/source/worker.js +0 -110
  241. package/src/source/worker_source.js +0 -14
  242. package/src/style-spec/deref.js +0 -51
  243. package/src/style-spec/group_by_layout.js +0 -46
  244. package/src/util/actor.js +0 -108
  245. package/src/util/dispatcher.js +0 -65
  246. package/src/util/global_worker_pool.js +0 -15
  247. package/src/util/transfer_registry.js +0 -168
  248. package/src/util/web_worker_transfer.js +0 -43
  249. package/src/util/worker_pool.js +0 -41
@@ -1,66 +1,76 @@
1
- const assert = require('assert');
2
-
3
- const { Event, ErrorEvent, Evented } = require('@mapwhit/events');
4
- const createStyleLayer = require('./create_style_layer');
5
- const loadSprite = require('./load_sprite');
6
- const ImageManager = require('../render/image_manager');
7
- const GlyphManager = require('../render/glyph_manager');
8
- const Light = require('./light');
9
- const LineAtlas = require('../render/line_atlas');
10
- const { clone, deepEqual, filterObject, mapObject } = require('../util/object');
11
- const browser = require('../util/browser');
12
- const dispatcher = require('../util/dispatcher');
13
- const { getType: getSourceType, setType: setSourceType } = require('../source/source');
14
- const { queryRenderedFeatures, queryRenderedSymbols, querySourceFeatures } = require('../source/query_features');
15
- const SourceCache = require('../source/source_cache');
16
- const getWorkerPool = require('../util/global_worker_pool');
17
- const deref = require('../style-spec/deref');
18
- const { registerForPluginAvailability, evented: rtlTextPluginEvented } = require('../source/rtl_text_plugin');
19
- const PauseablePlacement = require('./pauseable_placement');
20
- const ZoomHistory = require('./zoom_history');
21
- const CrossTileSymbolIndex = require('../symbol/cross_tile_symbol_index');
1
+ import { ErrorEvent, Event, Evented } from '@mapwhit/events';
2
+ import assert from 'assert';
3
+ import GlyphManager from '../render/glyph_manager.js';
4
+ import ImageManager from '../render/image_manager.js';
5
+ import LineAtlas from '../render/line_atlas.js';
6
+ import { queryRenderedFeatures, queryRenderedSymbols, querySourceFeatures } from '../source/query_features.js';
7
+ import { resources } from '../source/resources/index.js';
8
+ import plugin from '../source/rtl_text_plugin.js';
9
+ import { getType as getSourceType, setType as setSourceType } from '../source/source.js';
10
+ import SourceCache from '../source/source_cache.js';
11
+ import CrossTileSymbolIndex from '../symbol/cross_tile_symbol_index.js';
12
+ import browser from '../util/browser.js';
13
+ import { clone, deepEqual } from '../util/object.js';
14
+ import createStyleLayer from './create_style_layer.js';
15
+ import Light from './light.js';
16
+ import loadSprite from './load_sprite.js';
17
+ import PauseablePlacement from './pauseable_placement.js';
18
+ import StyleLayerIndex from './style_layer_index.js';
19
+ import ZoomHistory from './zoom_history.js';
20
+
21
+ const properties = [
22
+ 'version',
23
+ 'name',
24
+ 'metadata',
25
+ 'center',
26
+ 'zoom',
27
+ 'bearing',
28
+ 'pitch',
29
+ 'state',
30
+ 'sprite',
31
+ 'glyphs',
32
+ 'transition'
33
+ ];
22
34
 
23
35
  /**
24
36
  * @private
25
37
  */
26
38
  class Style extends Evented {
27
- // exposed to allow stubbing by unit tests
39
+ #resources = resources({
40
+ getImages: this.getImages.bind(this),
41
+ loadGlyphRange: this.loadGlyphRange.bind(this)
42
+ });
43
+ #layerIndex = new StyleLayerIndex();
28
44
 
29
45
  constructor(map, options = {}) {
30
46
  super();
31
47
 
32
48
  this.map = map;
33
- this.dispatcher = dispatcher(getWorkerPool(), this);
34
49
  this.imageManager = new ImageManager();
35
50
  this.glyphManager = new GlyphManager();
51
+
36
52
  this.lineAtlas = new LineAtlas(256, 512);
37
53
  this.crossTileSymbolIndex = new CrossTileSymbolIndex();
38
54
 
39
- this._layers = {};
40
- this._order = [];
41
- this.sourceCaches = {};
55
+ // insertion operations are done in the order of the layers in the style
56
+ this._layers = new Map();
57
+ this._sources = {};
42
58
  this.zoomHistory = new ZoomHistory();
43
59
  this._loaded = false;
44
60
  this._globalState = {};
45
61
 
62
+ this._updatedLayers = new Map();
63
+ this._removedLayers = new Map();
46
64
  this._resetUpdates();
47
65
 
48
- const self = this;
49
- this._rtlTextPluginCallback = Style.registerForPluginAvailability(args => {
50
- self.dispatcher
51
- .broadcast('loadRTLTextPlugin', args.pluginURL)
52
- .then(_ => args.completionCallback(), args.completionCallback);
53
- for (const id in self.sourceCaches) {
54
- self.sourceCaches[id].reload(); // Should be a no-op if the plugin loads before any tiles load
55
- }
56
- });
66
+ this._rtlTextPluginCallbackUnregister = plugin.registerForPluginAvailability(this._reloadSources.bind(this));
57
67
 
58
68
  this.on('data', event => {
59
69
  if (event.dataType !== 'source' || event.sourceDataType !== 'metadata') {
60
70
  return;
61
71
  }
62
72
 
63
- const sourceCache = this.sourceCaches[event.sourceId];
73
+ const sourceCache = this._sources[event.sourceId];
64
74
  if (!sourceCache) {
65
75
  return;
66
76
  }
@@ -70,8 +80,7 @@ class Style extends Evented {
70
80
  return;
71
81
  }
72
82
 
73
- for (const layerId in this._layers) {
74
- const layer = this._layers[layerId];
83
+ for (const layer of this._layers.values()) {
75
84
  if (layer.source === source.id) {
76
85
  this._validateLayer(layer);
77
86
  }
@@ -126,8 +135,7 @@ class Style extends Evented {
126
135
 
127
136
  const sourceIdsToReload = new Set();
128
137
 
129
- for (const layerId in this._layers) {
130
- const layer = this._layers[layerId];
138
+ for (const layer of this._layers.values()) {
131
139
  const layoutAffectingGlobalStateRefs = layer.getLayoutAffectingGlobalStateRefs();
132
140
  const paintAffectingGlobalStateRefs = layer.getPaintAffectingGlobalStateRefs();
133
141
 
@@ -143,7 +151,7 @@ class Style extends Evented {
143
151
  }
144
152
  }
145
153
 
146
- for (const id in this.sourceCaches) {
154
+ for (const id in this._sources) {
147
155
  if (sourceIdsToReload.has(id)) {
148
156
  this._reloadSource(id);
149
157
  this._changed = true;
@@ -162,7 +170,9 @@ class Style extends Evented {
162
170
  _load(json) {
163
171
  this._loaded = true;
164
172
  this.stylesheet = json;
173
+ properties.forEach(prop => (this[prop] = json[prop]));
165
174
 
175
+ this.sources = {};
166
176
  for (const id in json.sources) {
167
177
  this.addSource(id, json.sources[id]);
168
178
  }
@@ -186,20 +196,22 @@ class Style extends Evented {
186
196
 
187
197
  this.glyphManager.setGlyphsLoader(json.glyphs);
188
198
 
189
- const layers = deref(this.stylesheet.layers);
190
-
191
- this._order = layers.map(layer => layer.id);
199
+ const layers = this.stylesheet.layers;
192
200
 
193
- this._layers = {};
201
+ this._layers.clear();
194
202
  for (let layer of layers) {
203
+ if (layer.ref) {
204
+ continue; // just ignore layers that reference other layers
205
+ }
195
206
  layer = createStyleLayer(layer);
196
207
  layer.setEventedParent(this, { layer: { id: layer.id } });
197
- this._layers[layer.id] = layer;
208
+ this._layers.set(layer.id, layer);
198
209
  }
199
210
 
200
- this.dispatcher.broadcast('setLayers', this._serializeLayers(this._order));
211
+ this.#layerIndex.replace(this._layers);
201
212
 
202
- this.light = new Light(this.stylesheet.light);
213
+ this.light = this.stylesheet.light;
214
+ this._light = new Light(this.light);
203
215
 
204
216
  this.setGlobalState(this.stylesheet.state ?? null);
205
217
 
@@ -208,7 +220,7 @@ class Style extends Evented {
208
220
  }
209
221
 
210
222
  _validateLayer(layer) {
211
- const sourceCache = this.sourceCaches[layer.source];
223
+ const sourceCache = this._sources[layer.source];
212
224
  if (!sourceCache) {
213
225
  return;
214
226
  }
@@ -233,34 +245,40 @@ class Style extends Evented {
233
245
  }
234
246
 
235
247
  loaded() {
236
- if (!this._loaded) return false;
248
+ if (!this._loaded) {
249
+ return false;
250
+ }
237
251
 
238
- if (Object.keys(this._updatedSources).length) return false;
252
+ if (Object.keys(this._updatedSources).length) {
253
+ return false;
254
+ }
239
255
 
240
- for (const id in this.sourceCaches) if (!this.sourceCaches[id].loaded()) return false;
256
+ for (const id in this._sources) {
257
+ if (!this._sources[id].loaded()) {
258
+ return false;
259
+ }
260
+ }
241
261
 
242
- if (!this.imageManager.isLoaded()) return false;
262
+ if (!this.imageManager.isLoaded()) {
263
+ return false;
264
+ }
243
265
 
244
266
  return true;
245
267
  }
246
268
 
247
- _serializeLayers(ids) {
248
- return ids.map(id => this._layers[id].serialize());
249
- }
250
-
251
269
  hasTransitions() {
252
- if (this.light?.hasTransition()) {
270
+ if (this._light?.hasTransition()) {
253
271
  return true;
254
272
  }
255
273
 
256
- for (const id in this.sourceCaches) {
257
- if (this.sourceCaches[id].hasTransition()) {
274
+ for (const id in this._sources) {
275
+ if (this._sources[id].hasTransition()) {
258
276
  return true;
259
277
  }
260
278
  }
261
279
 
262
- for (const id in this._layers) {
263
- if (this._layers[id].hasTransition()) {
280
+ for (const layer of this._layers.values()) {
281
+ if (layer.hasTransition()) {
264
282
  return true;
265
283
  }
266
284
  }
@@ -283,11 +301,8 @@ class Style extends Evented {
283
301
  }
284
302
 
285
303
  if (this._changed) {
286
- const updatedIds = Object.keys(this._updatedLayers);
287
- const removedIds = Object.keys(this._removedLayers);
288
-
289
- if (updatedIds.length || removedIds.length) {
290
- this._updateWorkerLayers(updatedIds, removedIds);
304
+ if (this._updatedLayers.size || this._removedLayers.size) {
305
+ this._updateWorkerLayers();
291
306
  }
292
307
  for (const id in this._updatedSources) {
293
308
  const action = this._updatedSources[id];
@@ -300,45 +315,40 @@ class Style extends Evented {
300
315
  }
301
316
 
302
317
  for (const id in this._updatedPaintProps) {
303
- this._layers[id].updateTransitions(parameters);
318
+ this._layers.get(id).updateTransitions(parameters);
304
319
  }
305
320
 
306
- this.light.updateTransitions(parameters);
321
+ this._light.updateTransitions(parameters);
307
322
 
308
323
  this._resetUpdates();
309
324
 
310
325
  this.fire(new Event('data', { dataType: 'style' }));
311
326
  }
312
327
 
313
- for (const sourceId in this.sourceCaches) {
314
- this.sourceCaches[sourceId].used = false;
328
+ for (const sourceId in this._sources) {
329
+ this._sources[sourceId].used = false;
315
330
  }
316
331
 
317
- for (const layerId of this._order) {
318
- const layer = this._layers[layerId];
319
-
332
+ for (const layer of this._layers.values()) {
320
333
  layer.recalculate(parameters);
321
334
  if (!layer.isHidden(parameters.zoom) && layer.source) {
322
- this.sourceCaches[layer.source].used = true;
335
+ this._sources[layer.source].used = true;
323
336
  }
324
337
  }
325
338
 
326
- this.light.recalculate(parameters);
339
+ this._light.recalculate(parameters);
327
340
  this.z = parameters.zoom;
328
341
  }
329
342
 
330
- _updateWorkerLayers(updatedIds, removedIds) {
331
- this.dispatcher.broadcast('updateLayers', {
332
- layers: this._serializeLayers(updatedIds),
333
- removedIds: removedIds
334
- });
343
+ _updateWorkerLayers() {
344
+ this.#layerIndex.update();
335
345
  }
336
346
 
337
347
  _resetUpdates() {
338
348
  this._changed = false;
339
349
 
340
- this._updatedLayers = {};
341
- this._removedLayers = {};
350
+ this._updatedLayers.clear();
351
+ this._removedLayers.clear();
342
352
 
343
353
  this._updatedSources = {};
344
354
  this._updatedPaintProps = {};
@@ -373,7 +383,7 @@ class Style extends Evented {
373
383
  addSource(id, source) {
374
384
  this._checkLoaded();
375
385
 
376
- if (this.sourceCaches[id] !== undefined) {
386
+ if (this._sources[id] !== undefined) {
377
387
  throw new Error('There is already a source with this ID');
378
388
  }
379
389
 
@@ -383,11 +393,17 @@ class Style extends Evented {
383
393
  );
384
394
  }
385
395
 
386
- const sourceCache = (this.sourceCaches[id] = new SourceCache(id, source, this.dispatcher));
396
+ this.sources[id] = source;
397
+
398
+ const sourceCache = (this._sources[id] = new SourceCache(id, source, {
399
+ resources: this.#resources,
400
+ layerIndex: this.#layerIndex,
401
+ showTileBoundaries: this.map.showTileBoundaries
402
+ }));
387
403
  sourceCache.style = this;
388
404
  sourceCache.setEventedParent(this, () => ({
389
405
  isSourceLoaded: this.loaded(),
390
- source: sourceCache.serialize(),
406
+ source: sourceCache,
391
407
  sourceId: id
392
408
  }));
393
409
 
@@ -403,25 +419,27 @@ class Style extends Evented {
403
419
  removeSource(id) {
404
420
  this._checkLoaded();
405
421
 
406
- if (this.sourceCaches[id] === undefined) {
422
+ if (this._sources[id] === undefined) {
407
423
  throw new Error('There is no source with this ID');
408
424
  }
409
- for (const layerId in this._layers) {
410
- if (this._layers[layerId].source === id) {
425
+ for (const [layerId, layer] of this._layers) {
426
+ if (layer.source === id) {
411
427
  return this.fire(
412
428
  new ErrorEvent(new Error(`Source "${id}" cannot be removed while layer "${layerId}" is using it.`))
413
429
  );
414
430
  }
415
431
  }
416
432
 
417
- const sourceCache = this.sourceCaches[id];
418
- delete this.sourceCaches[id];
433
+ const sourceCache = this._sources[id];
434
+ delete this._sources[id];
419
435
  delete this._updatedSources[id];
420
436
  sourceCache.fire(new Event('data', { sourceDataType: 'metadata', dataType: 'source', sourceId: id }));
421
437
  sourceCache.setEventedParent(null);
422
438
  sourceCache.clearTiles();
423
439
 
424
- if (sourceCache.onRemove) sourceCache.onRemove(this.map);
440
+ if (sourceCache.onRemove) {
441
+ sourceCache.onRemove(this.map);
442
+ }
425
443
  this._changed = true;
426
444
  }
427
445
 
@@ -433,10 +451,11 @@ class Style extends Evented {
433
451
  setGeoJSONSourceData(id, data) {
434
452
  this._checkLoaded();
435
453
 
436
- assert(this.sourceCaches[id] !== undefined, 'There is no source with this ID');
437
- const geojsonSource = this.sourceCaches[id].getSource();
454
+ assert(this._sources[id] !== undefined, 'There is no source with this ID');
455
+ const geojsonSource = this._sources[id].getSource();
438
456
  assert(geojsonSource.type === 'geojson');
439
457
 
458
+ this.sources[id].data = data;
440
459
  geojsonSource.setData(data);
441
460
  this._changed = true;
442
461
  }
@@ -447,7 +466,36 @@ class Style extends Evented {
447
466
  * @returns {Object} source
448
467
  */
449
468
  getSource(id) {
450
- return this.sourceCaches[id]?.getSource();
469
+ return this._sources[id]?.getSource();
470
+ }
471
+
472
+ _insertLayer(id, layer, before, move) {
473
+ if (!before) {
474
+ if (move) {
475
+ this._layers.delete(id);
476
+ }
477
+ this._layers.set(id, layer);
478
+ this._layerOrderChanged = true;
479
+ return;
480
+ }
481
+ let beforeFound;
482
+ const _layers = new Map();
483
+ for (const [key, value] of this._layers.entries()) {
484
+ if (key === before) {
485
+ _layers.set(id, layer);
486
+ beforeFound = true;
487
+ }
488
+ if (move && key === id) {
489
+ continue;
490
+ }
491
+ _layers.set(key, value);
492
+ }
493
+ if (!beforeFound) {
494
+ this.fire(new ErrorEvent(new Error(`Layer with id "${before}" does not exist on this map.`)));
495
+ return;
496
+ }
497
+ this._layers = _layers;
498
+ this._layerOrderChanged = true;
451
499
  }
452
500
 
453
501
  /**
@@ -476,18 +524,9 @@ class Style extends Evented {
476
524
 
477
525
  layer.setEventedParent(this, { layer: { id: id } });
478
526
 
479
- const index = before ? this._order.indexOf(before) : this._order.length;
480
- if (before && index === -1) {
481
- this.fire(new ErrorEvent(new Error(`Layer with id "${before}" does not exist on this map.`)));
482
- return;
483
- }
484
-
485
- this._order.splice(index, 0, id);
486
- this._layerOrderChanged = true;
527
+ this._insertLayer(id, layer, before);
487
528
 
488
- this._layers[id] = layer;
489
-
490
- if (this._removedLayers[id] && layer.source) {
529
+ if (this._removedLayers.has(id) && layer.source) {
491
530
  // If, in the current batch, we have already removed this layer
492
531
  // and we are now re-adding it with a different `type`, then we
493
532
  // need to clear (rather than just reload) the underyling source's
@@ -495,13 +534,13 @@ class Style extends Evented {
495
534
  // buffers that are set up for the _previous_ version of this
496
535
  // layer, causing, e.g.:
497
536
  // https://github.com/mapbox/mapbox-gl-js/issues/3633
498
- const removed = this._removedLayers[id];
499
- delete this._removedLayers[id];
537
+ const removed = this._removedLayers.get(id);
538
+ this._removedLayers.delete(id);
500
539
  if (removed.type !== layer.type) {
501
540
  this._updatedSources[layer.source] = 'clear';
502
541
  } else {
503
542
  this._updatedSources[layer.source] = 'reload';
504
- this.sourceCaches[layer.source].pause();
543
+ this._sources[layer.source].pause();
505
544
  }
506
545
  }
507
546
  this._updateLayer(layer);
@@ -517,7 +556,7 @@ class Style extends Evented {
517
556
  this._checkLoaded();
518
557
  this._changed = true;
519
558
 
520
- const layer = this._layers[id];
559
+ const layer = this._layers.get(id);
521
560
  if (!layer) {
522
561
  this.fire(new ErrorEvent(new Error(`The layer '${id}' does not exist in the map's style and cannot be moved.`)));
523
562
  return;
@@ -527,17 +566,7 @@ class Style extends Evented {
527
566
  return;
528
567
  }
529
568
 
530
- const index = this._order.indexOf(id);
531
- this._order.splice(index, 1);
532
-
533
- const newIndex = before ? this._order.indexOf(before) : this._order.length;
534
- if (before && newIndex === -1) {
535
- this.fire(new ErrorEvent(new Error(`Layer with id "${before}" does not exist on this map.`)));
536
- return;
537
- }
538
- this._order.splice(newIndex, 0, id);
539
-
540
- this._layerOrderChanged = true;
569
+ this._insertLayer(id, layer, before, true);
541
570
  }
542
571
 
543
572
  /**
@@ -551,7 +580,7 @@ class Style extends Evented {
551
580
  removeLayer(id) {
552
581
  this._checkLoaded();
553
582
 
554
- const layer = this._layers[id];
583
+ const layer = this._layers.get(id);
555
584
  if (!layer) {
556
585
  this.fire(
557
586
  new ErrorEvent(new Error(`The layer '${id}' does not exist in the map's style and cannot be removed.`))
@@ -561,14 +590,11 @@ class Style extends Evented {
561
590
 
562
591
  layer.setEventedParent(null);
563
592
 
564
- const index = this._order.indexOf(id);
565
- this._order.splice(index, 1);
566
-
567
593
  this._layerOrderChanged = true;
568
594
  this._changed = true;
569
- this._removedLayers[id] = layer;
570
- delete this._layers[id];
571
- delete this._updatedLayers[id];
595
+ this._removedLayers.set(id, layer);
596
+ this._layers.delete(id);
597
+ this._updatedLayers.delete(id);
572
598
  delete this._updatedPaintProps[id];
573
599
  }
574
600
 
@@ -579,7 +605,7 @@ class Style extends Evented {
579
605
  * @returns {?Object} a layer, if one with the given `id` exists
580
606
  */
581
607
  getLayer(id) {
582
- return this._layers[id];
608
+ return this._layers.get(id);
583
609
  }
584
610
 
585
611
  setLayerZoomRange(layerId, minzoom, maxzoom) {
@@ -595,15 +621,13 @@ class Style extends Evented {
595
621
  return;
596
622
  }
597
623
 
598
- if (layer.minzoom === minzoom && layer.maxzoom === maxzoom) return;
599
-
600
- if (minzoom != null) {
601
- layer.minzoom = minzoom;
602
- }
603
- if (maxzoom != null) {
604
- layer.maxzoom = maxzoom;
624
+ if (layer._setZoomRange(minzoom, maxzoom)) {
625
+ this._updateLayer(layer);
605
626
  }
606
- this._updateLayer(layer);
627
+ }
628
+
629
+ get layers() {
630
+ return Array.from(this._layers.values());
607
631
  }
608
632
 
609
633
  setFilter(layerId, filter) {
@@ -651,9 +675,15 @@ class Style extends Evented {
651
675
  return;
652
676
  }
653
677
 
654
- if (deepEqual(layer.getLayoutProperty(name), value)) return;
678
+ if (deepEqual(layer.getLayoutProperty(name), value)) {
679
+ return;
680
+ }
655
681
 
656
682
  layer.setLayoutProperty(name, value);
683
+ const layerObject = this.layers.find(({ id }) => id === layerId);
684
+ layerObject.layout ??= {};
685
+ layerObject.layout[name] = value;
686
+
657
687
  this._updateLayer(layer);
658
688
  }
659
689
 
@@ -678,7 +708,13 @@ class Style extends Evented {
678
708
  return;
679
709
  }
680
710
 
681
- if (deepEqual(layer.getPaintProperty(name), value)) return;
711
+ if (deepEqual(layer.getPaintProperty(name), value)) {
712
+ return;
713
+ }
714
+
715
+ const layerObject = this.layers.find(({ id }) => id === layerId);
716
+ layerObject.paint ??= {};
717
+ layerObject.paint[name] = value;
682
718
 
683
719
  this._updatePaintProperty(layer, name, value);
684
720
  }
@@ -701,13 +737,17 @@ class Style extends Evented {
701
737
  this._checkLoaded();
702
738
  const sourceId = feature.source;
703
739
  const sourceLayer = feature.sourceLayer;
704
- const sourceCache = this.sourceCaches[sourceId];
740
+ const sourceCache = this._sources[sourceId];
705
741
 
706
742
  if (sourceCache === undefined) {
707
743
  this.fire(new ErrorEvent(new Error(`The source '${sourceId}' does not exist in the map's style.`)));
708
744
  return;
709
745
  }
710
746
  const sourceType = sourceCache.getSource().type;
747
+ if (sourceType === 'geojson' && sourceLayer) {
748
+ this.fire(new ErrorEvent(new Error('GeoJSON sources cannot have a sourceLayer parameter.')));
749
+ return;
750
+ }
711
751
  if (sourceType === 'vector' && !sourceLayer) {
712
752
  this.fire(new ErrorEvent(new Error('The sourceLayer parameter must be provided for vector source types.')));
713
753
  return;
@@ -720,11 +760,37 @@ class Style extends Evented {
720
760
  sourceCache.setFeatureState(sourceLayer, feature.id, state);
721
761
  }
722
762
 
763
+ removeFeatureState(target, key) {
764
+ this._checkLoaded();
765
+ const sourceId = target.source;
766
+ const sourceCache = this._sources[sourceId];
767
+
768
+ if (sourceCache === undefined) {
769
+ this.fire(new ErrorEvent(new Error(`The source '${sourceId}' does not exist in the map's style.`)));
770
+ return;
771
+ }
772
+
773
+ const sourceType = sourceCache.getSource().type;
774
+ const sourceLayer = sourceType === 'vector' ? target.sourceLayer : undefined;
775
+
776
+ if (sourceType === 'vector' && !sourceLayer) {
777
+ this.fire(new ErrorEvent(new Error('The sourceLayer parameter must be provided for vector source types.')));
778
+ return;
779
+ }
780
+
781
+ if (key && typeof target.id !== 'string' && typeof target.id !== 'number') {
782
+ this.fire(new ErrorEvent(new Error('A feature id is required to remove its specific state property.')));
783
+ return;
784
+ }
785
+
786
+ sourceCache.removeFeatureState(sourceLayer, target.id, key);
787
+ }
788
+
723
789
  getFeatureState(feature) {
724
790
  this._checkLoaded();
725
791
  const sourceId = feature.source;
726
792
  const sourceLayer = feature.sourceLayer;
727
- const sourceCache = this.sourceCaches[sourceId];
793
+ const sourceCache = this._sources[sourceId];
728
794
 
729
795
  if (sourceCache === undefined) {
730
796
  this.fire(new ErrorEvent(new Error(`The source '${sourceId}' does not exist in the map's style.`)));
@@ -743,63 +809,81 @@ class Style extends Evented {
743
809
  return Object.assign({ duration: 300, delay: 0 }, this.stylesheet?.transition);
744
810
  }
745
811
 
746
- serialize() {
747
- return filterObject(
748
- {
749
- version: this.stylesheet.version,
750
- name: this.stylesheet.name,
751
- metadata: this.stylesheet.metadata,
752
- light: this.stylesheet.light,
753
- center: this.stylesheet.center,
754
- zoom: this.stylesheet.zoom,
755
- bearing: this.stylesheet.bearing,
756
- pitch: this.stylesheet.pitch,
757
- sprite: this.stylesheet.sprite,
758
- glyphs: this.stylesheet.glyphs,
759
- transition: this.stylesheet.transition,
760
- sources: mapObject(this.sourceCaches, source => source.serialize()),
761
- layers: this._order.map(id => this._layers[id].serialize())
762
- },
763
- value => value !== undefined
764
- );
765
- }
766
-
767
812
  _updateLayer(layer) {
768
- this._updatedLayers[layer.id] = true;
813
+ this._updatedLayers.set(layer.id, layer);
769
814
  if (layer.source && !this._updatedSources[layer.source]) {
770
815
  this._updatedSources[layer.source] = 'reload';
771
- this.sourceCaches[layer.source].pause();
816
+ this._sources[layer.source].pause();
772
817
  }
773
818
  this._changed = true;
774
819
  }
775
820
 
776
821
  _flattenAndSortRenderedFeatures(sourceResults) {
777
- const features = [];
822
+ // Feature order is complicated.
823
+ // The order between features in two 2D layers is always determined by layer order.
824
+ // The order between features in two 3D layers is always determined by depth.
825
+ // The order between a feature in a 2D layer and a 3D layer is tricky:
826
+ // Most often layer order determines the feature order in this case. If
827
+ // a line layer is above a extrusion layer the line feature will be rendered
828
+ // above the extrusion. If the line layer is below the extrusion layer,
829
+ // it will be rendered below it.
830
+ //
831
+ // There is a weird case though.
832
+ // You have layers in this order: extrusion_layer_a, line_layer, extrusion_layer_b
833
+ // Each layer has a feature that overlaps the other features.
834
+ // The feature in extrusion_layer_a is closer than the feature in extrusion_layer_b so it is rendered above.
835
+ // The feature in line_layer is rendered above extrusion_layer_a.
836
+ // This means that that the line_layer feature is above the extrusion_layer_b feature despite
837
+ // it being in an earlier layer.
838
+
839
+ const isLayer3D = layer => layer.type === 'fill-extrusion';
840
+
841
+ const layerIndex = new Map();
778
842
  const features3D = [];
779
- for (let l = this._order.length - 1; l >= 0; l--) {
780
- const layerId = this._order[l];
781
- for (const sourceResult of sourceResults) {
782
- const layerFeatures = sourceResult[layerId];
783
- if (layerFeatures) {
784
- if (this._layers[layerId].type === 'fill-extrusion') {
843
+ const layers = Array.from(this._layers.values());
844
+ for (let l = layers.length - 1; l >= 0; l--) {
845
+ const layer = layers[l];
846
+ if (isLayer3D(layer)) {
847
+ layerIndex.set(layer.id, l);
848
+ for (const sourceResult of sourceResults) {
849
+ const layerFeatures = sourceResult[layer.id];
850
+ if (layerFeatures) {
785
851
  for (const featureWrapper of layerFeatures) {
786
852
  features3D.push(featureWrapper);
787
853
  }
788
- } else {
789
- for (const featureWrapper of layerFeatures) {
790
- features.push(featureWrapper.feature);
791
- }
792
854
  }
793
855
  }
794
856
  }
795
857
  }
796
858
 
797
859
  features3D.sort((a, b) => {
798
- return a.intersectionZ - b.intersectionZ;
860
+ return b.intersectionZ - a.intersectionZ;
799
861
  });
800
862
 
801
- for (const featureWrapper of features3D) {
802
- features.push(featureWrapper.feature);
863
+ const features = [];
864
+ for (let l = layers.length - 1; l >= 0; l--) {
865
+ const layer = layers[l];
866
+
867
+ if (isLayer3D(layer)) {
868
+ // add all 3D features that are in or above the current layer
869
+ for (let i = features3D.length - 1; i >= 0; i--) {
870
+ const topmost3D = features3D[i].feature;
871
+ if (layerIndex.get(topmost3D.layer.id) < l) {
872
+ break;
873
+ }
874
+ features.push(topmost3D);
875
+ features3D.pop();
876
+ }
877
+ } else {
878
+ for (const sourceResult of sourceResults) {
879
+ const layerFeatures = sourceResult[layer.id];
880
+ if (layerFeatures) {
881
+ for (const featureWrapper of layerFeatures) {
882
+ features.push(featureWrapper.feature);
883
+ }
884
+ }
885
+ }
886
+ }
803
887
  }
804
888
 
805
889
  return features;
@@ -813,7 +897,7 @@ class Style extends Evented {
813
897
  return [];
814
898
  }
815
899
  for (const layerId of params.layers) {
816
- const layer = this._layers[layerId];
900
+ const layer = this._layers.get(layerId);
817
901
  if (layer) {
818
902
  includedSources[layer.source] = true;
819
903
  }
@@ -821,10 +905,12 @@ class Style extends Evented {
821
905
  }
822
906
 
823
907
  const sourceResults = [];
824
- for (const id in this.sourceCaches) {
825
- if (params.layers && !includedSources[id]) continue;
908
+ for (const id in this._sources) {
909
+ if (params.layers && !includedSources[id]) {
910
+ continue;
911
+ }
826
912
  sourceResults.push(
827
- queryRenderedFeatures(this.sourceCaches[id], this._layers, queryGeometry.viewport, params, transform)
913
+ queryRenderedFeatures(this._sources[id], this._layers, queryGeometry.viewport, params, transform)
828
914
  );
829
915
  }
830
916
 
@@ -834,7 +920,7 @@ class Style extends Evented {
834
920
  sourceResults.push(
835
921
  queryRenderedSymbols(
836
922
  this._layers,
837
- this.sourceCaches,
923
+ this._sources,
838
924
  queryGeometry.viewport,
839
925
  params,
840
926
  this.placement.collisionIndex,
@@ -846,18 +932,18 @@ class Style extends Evented {
846
932
  }
847
933
 
848
934
  querySourceFeatures(sourceID, params) {
849
- const sourceCache = this.sourceCaches[sourceID];
935
+ const sourceCache = this._sources[sourceID];
850
936
  return sourceCache ? querySourceFeatures(sourceCache, params) : [];
851
937
  }
852
938
 
853
939
  getLight() {
854
- return this.light.getLight();
940
+ return this._light.getLight();
855
941
  }
856
942
 
857
943
  setLight(lightOptions) {
858
944
  this._checkLoaded();
859
945
 
860
- const light = this.light.getLight();
946
+ const light = this._light.getLight();
861
947
  let _update = false;
862
948
  for (const key in lightOptions) {
863
949
  if (!deepEqual(lightOptions[key], light[key])) {
@@ -865,7 +951,9 @@ class Style extends Evented {
865
951
  break;
866
952
  }
867
953
  }
868
- if (!_update) return;
954
+ if (!_update) {
955
+ return;
956
+ }
869
957
 
870
958
  const parameters = {
871
959
  now: browser.now(),
@@ -878,35 +966,40 @@ class Style extends Evented {
878
966
  )
879
967
  };
880
968
 
881
- this.light.setLight(lightOptions);
882
- this.light.updateTransitions(parameters);
969
+ this._light.setLight(lightOptions);
970
+ this._light.updateTransitions(parameters);
883
971
  }
884
972
 
885
973
  _remove() {
886
- rtlTextPluginEvented.off('pluginAvailable', this._rtlTextPluginCallback);
887
- for (const id in this.sourceCaches) {
888
- this.sourceCaches[id].clearTiles();
974
+ this._rtlTextPluginCallbackUnregister?.();
975
+ for (const id in this._sources) {
976
+ this._sources[id].clearTiles();
889
977
  }
890
- this.dispatcher.remove();
891
978
  }
892
979
 
893
980
  _clearSource(id) {
894
- this.sourceCaches[id].clearTiles();
981
+ this._sources[id].clearTiles();
895
982
  }
896
983
 
897
984
  _reloadSource(id) {
898
- this.sourceCaches[id].resume();
899
- this.sourceCaches[id].reload();
985
+ this._sources[id].resume();
986
+ this._sources[id].reload();
900
987
  }
901
988
 
902
989
  _updateSources(transform) {
903
- for (const id in this.sourceCaches) {
904
- this.sourceCaches[id].update(transform);
990
+ for (const id in this._sources) {
991
+ this._sources[id].update(transform);
992
+ }
993
+ }
994
+
995
+ _reloadSources() {
996
+ for (const sourceCache of Object.values(this._sources)) {
997
+ sourceCache.reload(); // Should be a no-op if called before any tiles load
905
998
  }
906
999
  }
907
1000
 
908
1001
  _generateCollisionBoxes() {
909
- for (const id in this.sourceCaches) {
1002
+ for (const id in this._sources) {
910
1003
  this._reloadSource(id);
911
1004
  }
912
1005
  }
@@ -917,26 +1010,27 @@ class Style extends Evented {
917
1010
 
918
1011
  const layerTiles = {};
919
1012
 
920
- for (const layerID of this._order) {
921
- const styleLayer = this._layers[layerID];
922
- if (styleLayer.type !== 'symbol') continue;
1013
+ for (const layer of this._layers.values()) {
1014
+ if (layer.type !== 'symbol') {
1015
+ continue;
1016
+ }
923
1017
 
924
- if (!layerTiles[styleLayer.source]) {
925
- const sourceCache = this.sourceCaches[styleLayer.source];
926
- layerTiles[styleLayer.source] = sourceCache
1018
+ if (!layerTiles[layer.source]) {
1019
+ const sourceCache = this._sources[layer.source];
1020
+ layerTiles[layer.source] = sourceCache
927
1021
  .getRenderableIds(true)
928
1022
  .map(id => sourceCache.getTileByID(id))
929
1023
  .sort((a, b) => b.tileID.overscaledZ - a.tileID.overscaledZ || (a.tileID.isLessThan(b.tileID) ? -1 : 1));
930
1024
  }
931
1025
 
932
1026
  const layerBucketsChanged = this.crossTileSymbolIndex.addLayer(
933
- styleLayer,
934
- layerTiles[styleLayer.source],
1027
+ layer,
1028
+ layerTiles[layer.source],
935
1029
  transform.center.lng
936
1030
  );
937
1031
  symbolBucketsChanged = symbolBucketsChanged || layerBucketsChanged;
938
1032
  }
939
- this.crossTileSymbolIndex.pruneUnusedLayers(this._order);
1033
+ this.crossTileSymbolIndex.pruneUnusedLayers(this._layers.keys());
940
1034
 
941
1035
  // Anything that changes our "in progress" layer and tile indices requires us
942
1036
  // to start over. When we start over, we do a full placement instead of incremental
@@ -951,7 +1045,7 @@ class Style extends Evented {
951
1045
  ) {
952
1046
  this.pauseablePlacement = new PauseablePlacement(
953
1047
  transform,
954
- this._order,
1048
+ this._layers.size - 1,
955
1049
  forceFullPlacement,
956
1050
  showCollisionBoxes,
957
1051
  fadeDuration,
@@ -967,7 +1061,7 @@ class Style extends Evented {
967
1061
  // render frame
968
1062
  this.placement.setStale();
969
1063
  } else {
970
- this.pauseablePlacement.continuePlacement(this._order, this._layers, layerTiles);
1064
+ this.pauseablePlacement.continuePlacement(Array.from(this._layers.values()), layerTiles);
971
1065
 
972
1066
  if (this.pauseablePlacement.isDone()) {
973
1067
  this.placement = this.pauseablePlacement.commit(this.placement, browser.now());
@@ -983,10 +1077,11 @@ class Style extends Evented {
983
1077
  }
984
1078
 
985
1079
  if (placementCommitted || symbolBucketsChanged) {
986
- for (const layerID of this._order) {
987
- const styleLayer = this._layers[layerID];
988
- if (styleLayer.type !== 'symbol') continue;
989
- this.placement.updateLayerOpacities(styleLayer, layerTiles[styleLayer.source]);
1080
+ for (const layer of this._layers.values()) {
1081
+ if (layer.type !== 'symbol') {
1082
+ continue;
1083
+ }
1084
+ this.placement.updateLayerOpacities(layer, layerTiles[layer.source]);
990
1085
  }
991
1086
  }
992
1087
 
@@ -996,24 +1091,22 @@ class Style extends Evented {
996
1091
  }
997
1092
 
998
1093
  _releaseSymbolFadeTiles() {
999
- for (const id in this.sourceCaches) {
1000
- this.sourceCaches[id].releaseSymbolFadeTiles();
1094
+ for (const id in this._sources) {
1095
+ this._sources[id].releaseSymbolFadeTiles();
1001
1096
  }
1002
1097
  }
1003
1098
 
1004
1099
  // Callbacks from web workers
1005
-
1006
- getImages(_mapId, { icons }) {
1100
+ getImages({ icons }) {
1007
1101
  return this.imageManager.getImages(icons);
1008
1102
  }
1009
1103
 
1010
- loadGlyphRange(_mapId, { stack, range }) {
1104
+ loadGlyphRange({ stack, range }) {
1011
1105
  return this.glyphManager.loadGlyphRange(stack, range);
1012
1106
  }
1013
1107
  }
1014
1108
 
1015
1109
  Style.getSourceType = getSourceType;
1016
1110
  Style.setSourceType = setSourceType;
1017
- Style.registerForPluginAvailability = registerForPluginAvailability;
1018
1111
 
1019
- module.exports = Style;
1112
+ export default Style;