@tangram.gl/tangram-renderer 0.0.0-stage → 0.0.1

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 (321) hide show
  1. package/README.md +60 -2
  2. package/dist/core.js +36923 -0
  3. package/dist/core.js.map +6 -0
  4. package/dist/index.js +32 -0
  5. package/dist/loaders-gl-worker.js +82 -0
  6. package/dist/loaders-gl-worker.js.map +6 -0
  7. package/dist/map-logic.js +2 -0
  8. package/dist/map-logic.js.map +6 -0
  9. package/dist/projected-basemaps-worker.js +3 -0
  10. package/dist/projected-basemaps-worker.js.map +6 -0
  11. package/dist/shader-modules.js +141 -0
  12. package/dist/shader-modules.js.map +6 -0
  13. package/dist/style-schema.js +126 -0
  14. package/dist/style-schema.js.map +6 -0
  15. package/dist/tangram-style.schema.json +882 -0
  16. package/dist/tangram.debug.mjs +37139 -0
  17. package/dist/tangram.debug.mjs.map +6 -0
  18. package/dist/tangram.min.mjs +4950 -0
  19. package/dist/types/builders/earcut.d.ts +15 -0
  20. package/dist/types/core.d.ts +29 -0
  21. package/dist/types/gl/constants.d.ts +2 -0
  22. package/dist/types/gl/globe_mesh.d.ts +48 -0
  23. package/dist/types/gl/glsl.d.ts +17 -0
  24. package/dist/types/gl/vertex-constants.d.ts +4 -0
  25. package/dist/types/gl/vertex-types.d.ts +34 -0
  26. package/dist/types/gl/vertex_data.d.ts +32 -0
  27. package/dist/types/gl/vertex_elements.d.ts +8 -0
  28. package/dist/types/gl/vertex_layout.d.ts +32 -0
  29. package/dist/types/glsl.d.ts +14 -0
  30. package/dist/types/gpu/luma_device_renderer.d.ts +66 -0
  31. package/dist/types/gpu/resource_lifecycle.d.ts +4 -0
  32. package/dist/types/gpu/tangram_gpu_backend.d.ts +151 -0
  33. package/dist/types/index.d.ts +155 -0
  34. package/dist/types/lights/light-definitions.d.ts +121 -0
  35. package/dist/types/map-logic/draped-terrain-bounds.d.ts +41 -0
  36. package/dist/types/map-logic/globe-terrain-preparation.d.ts +85 -0
  37. package/dist/types/map-logic/globe-terrain.d.ts +54 -0
  38. package/dist/types/map-logic/index.d.ts +33 -0
  39. package/dist/types/map-logic/label-identity.d.ts +22 -0
  40. package/dist/types/map-logic/label-placement.d.ts +32 -0
  41. package/dist/types/map-logic/screen-bounds.d.ts +15 -0
  42. package/dist/types/map-logic/terrain-data.d.ts +55 -0
  43. package/dist/types/map-logic/terrain-error.d.ts +51 -0
  44. package/dist/types/map-logic/terrain-ground-topology.d.ts +26 -0
  45. package/dist/types/map-logic/terrain-height-field.d.ts +59 -0
  46. package/dist/types/map-logic/terrain-navigation.d.ts +27 -0
  47. package/dist/types/map-logic/terrain-neighborhood.d.ts +5 -0
  48. package/dist/types/map-logic/terrain-query.d.ts +33 -0
  49. package/dist/types/map-logic/terrain-resource-budget.d.ts +51 -0
  50. package/dist/types/map-logic/terrain-transition-topology.d.ts +23 -0
  51. package/dist/types/map-logic/tile-build-queue.d.ts +51 -0
  52. package/dist/types/map-logic/tile-cache-policy.d.ts +46 -0
  53. package/dist/types/map-logic/tile-residency.d.ts +17 -0
  54. package/dist/types/map-logic/triangle-query-index.d.ts +87 -0
  55. package/dist/types/procedures/js-yaml.d.ts +15 -0
  56. package/dist/types/procedures/mesh-projector.d.ts +107 -0
  57. package/dist/types/procedures/mvt-dependencies.d.ts +20 -0
  58. package/dist/types/procedures/projected-coordinate-transform.d.ts +27 -0
  59. package/dist/types/procedures/projection-batch-executor.d.ts +53 -0
  60. package/dist/types/procedures/scene-yaml-legacy.d.ts +6 -0
  61. package/dist/types/procedures/terrain-draping.d.ts +165 -0
  62. package/dist/types/procedures/terrain-globe.d.ts +6 -0
  63. package/dist/types/procedures/terrain-styled-topology.d.ts +34 -0
  64. package/dist/types/procedures/web-mercator-legacy.d.ts +4 -0
  65. package/dist/types/procedures/web-mercator-math.d.ts +4 -0
  66. package/dist/types/scene/globals.d.ts +11 -0
  67. package/dist/types/scene/ground_footprint.d.ts +16 -0
  68. package/dist/types/scene/host_frame.d.ts +54 -0
  69. package/dist/types/scene/projection_math.d.ts +52 -0
  70. package/dist/types/scene/scene-resource-types.d.ts +177 -0
  71. package/dist/types/scene/scene_bundle.d.ts +69 -0
  72. package/dist/types/scene/visibility_adapter.d.ts +106 -0
  73. package/dist/types/selection/draped-terrain-surface.d.ts +78 -0
  74. package/dist/types/selection/terrain_surface.d.ts +149 -0
  75. package/dist/types/shader-modules/globe-horizon.d.ts +15 -0
  76. package/dist/types/shader-modules/height-decode.d.ts +13 -0
  77. package/dist/types/shader-modules/hillshade.d.ts +13 -0
  78. package/dist/types/shader-modules/index.d.ts +6 -0
  79. package/dist/types/shader-modules/planar.d.ts +12 -0
  80. package/dist/types/shader-modules/sphere-map.d.ts +13 -0
  81. package/dist/types/shader-modules/triplanar.d.ts +15 -0
  82. package/dist/types/sources/decoded_tile_store.d.ts +95 -0
  83. package/dist/types/sources/tile_source_metadata.d.ts +32 -0
  84. package/dist/types/styles/text/fontfaceobserver.d.ts +10 -0
  85. package/dist/types/tile/tile_id.d.ts +37 -0
  86. package/dist/types/tile/tile_traversal_adapter.d.ts +63 -0
  87. package/dist/types/types.d.ts +293 -0
  88. package/dist/types/utils/geo.d.ts +57 -0
  89. package/dist/types/utils/hash.d.ts +1 -0
  90. package/dist/types/utils/log.d.ts +27 -0
  91. package/dist/types/utils/props.d.ts +6 -0
  92. package/dist/types/utils/subscribe.d.ts +10 -0
  93. package/dist/types/utils/thread.d.ts +6 -0
  94. package/dist/types/utils/urls.d.ts +26 -0
  95. package/dist/types/utils/utils.d.ts +26 -0
  96. package/dist/types/utils/version.d.ts +2 -0
  97. package/dist/types/utils/worker-types.d.ts +68 -0
  98. package/dist/types/utils/worker_broker.d.ts +3 -0
  99. package/package.json +103 -3
  100. package/src/builders/common.ts +41 -0
  101. package/src/builders/earcut.d.ts +15 -0
  102. package/src/builders/geometry-types.ts +60 -0
  103. package/src/builders/points.ts +115 -0
  104. package/src/builders/polygons.ts +225 -0
  105. package/src/builders/polylines.ts +682 -0
  106. package/src/builders/wireframe.ts +31 -0
  107. package/src/core.d.ts +29 -0
  108. package/src/core.ts +33 -0
  109. package/src/experimental/loaders-gl-worker.ts +19 -0
  110. package/src/experimental/projected-basemaps-worker.ts +13 -0
  111. package/src/experimental/projected-mesh-cache.ts +137 -0
  112. package/src/experimental/projected-mesh-domain.ts +110 -0
  113. package/src/experimental/projected-mesh-refinement.ts +193 -0
  114. package/src/experimental/projected-mesh.ts +399 -0
  115. package/src/experimental/projected-normal.ts +26 -0
  116. package/src/experimental/projected-symbol-mesh.ts +74 -0
  117. package/src/gl/constants.ts +18 -0
  118. package/src/gl/context.ts +103 -0
  119. package/src/gl/extensions.ts +30 -0
  120. package/src/gl/globe_mesh.ts +285 -0
  121. package/src/gl/glsl.ts +257 -0
  122. package/src/gl/mesh-types.ts +56 -0
  123. package/src/gl/render_state.ts +111 -0
  124. package/src/gl/shader_program.ts +1310 -0
  125. package/src/gl/texture.ts +814 -0
  126. package/src/gl/uniform_buffer.ts +340 -0
  127. package/src/gl/vao.ts +154 -0
  128. package/src/gl/vbo_mesh.ts +349 -0
  129. package/src/gl/vertex-constants.ts +19 -0
  130. package/src/gl/vertex-types.ts +35 -0
  131. package/src/gl/vertex_data.ts +126 -0
  132. package/src/gl/vertex_elements.ts +54 -0
  133. package/src/gl/vertex_layout.ts +241 -0
  134. package/src/glsl.d.ts +14 -0
  135. package/src/gpu/luma_device_renderer.ts +579 -0
  136. package/src/gpu/pixel_readback.ts +51 -0
  137. package/src/gpu/resource_lifecycle.ts +32 -0
  138. package/src/gpu/tangram_gpu_backend.ts +195 -0
  139. package/src/index.d.ts +155 -0
  140. package/src/index.ts +105 -0
  141. package/src/labels/collision-types.ts +94 -0
  142. package/src/labels/collision.ts +273 -0
  143. package/src/labels/collision_grid.ts +61 -0
  144. package/src/labels/intersect.ts +30 -0
  145. package/src/labels/label-types.ts +91 -0
  146. package/src/labels/label.ts +207 -0
  147. package/src/labels/label_line.ts +801 -0
  148. package/src/labels/label_point.ts +131 -0
  149. package/src/labels/main-pass-types.ts +73 -0
  150. package/src/labels/main_pass.ts +221 -0
  151. package/src/labels/point_anchor.ts +100 -0
  152. package/src/labels/point_placement.ts +150 -0
  153. package/src/labels/projected-pass.ts +259 -0
  154. package/src/labels/repeat_group.ts +72 -0
  155. package/src/lights/ambient_light.glsl +18 -0
  156. package/src/lights/directional_light.glsl +39 -0
  157. package/src/lights/geographic-lights.ts +21 -0
  158. package/src/lights/light-definitions.ts +285 -0
  159. package/src/lights/light.ts +590 -0
  160. package/src/lights/lighting-uniforms.ts +80 -0
  161. package/src/lights/lighting-wgsl.ts +116 -0
  162. package/src/lights/material.glsl +237 -0
  163. package/src/lights/material.ts +145 -0
  164. package/src/lights/native-falloff.ts +37 -0
  165. package/src/lights/point_light.glsl +96 -0
  166. package/src/lights/spot_light.glsl +111 -0
  167. package/src/map-logic/draped-terrain-bounds.ts +71 -0
  168. package/src/map-logic/globe-terrain-preparation.ts +217 -0
  169. package/src/map-logic/globe-terrain.ts +296 -0
  170. package/src/map-logic/index.ts +37 -0
  171. package/src/map-logic/label-identity.ts +36 -0
  172. package/src/map-logic/label-placement.ts +117 -0
  173. package/src/map-logic/screen-bounds.ts +34 -0
  174. package/src/map-logic/terrain-data.ts +107 -0
  175. package/src/map-logic/terrain-error.ts +134 -0
  176. package/src/map-logic/terrain-ground-topology.ts +164 -0
  177. package/src/map-logic/terrain-height-field.ts +254 -0
  178. package/src/map-logic/terrain-navigation.ts +50 -0
  179. package/src/map-logic/terrain-neighborhood.ts +43 -0
  180. package/src/map-logic/terrain-query.ts +51 -0
  181. package/src/map-logic/terrain-resource-budget.ts +124 -0
  182. package/src/map-logic/terrain-transition-topology.ts +164 -0
  183. package/src/map-logic/tile-build-queue.ts +110 -0
  184. package/src/map-logic/tile-cache-policy.ts +89 -0
  185. package/src/map-logic/tile-residency.ts +50 -0
  186. package/src/map-logic/triangle-query-index.ts +265 -0
  187. package/src/procedures/js-yaml.d.ts +15 -0
  188. package/src/procedures/mesh-projector.ts +191 -0
  189. package/src/procedures/mlt-loaders.ts +55 -0
  190. package/src/procedures/mvt-dependencies.d.ts +20 -0
  191. package/src/procedures/mvt-legacy.ts +150 -0
  192. package/src/procedures/mvt-loaders.ts +53 -0
  193. package/src/procedures/mvt-parser.ts +48 -0
  194. package/src/procedures/mvt-properties.ts +36 -0
  195. package/src/procedures/mvt-tile-provider.ts +72 -0
  196. package/src/procedures/pmtiles-loader.ts +75 -0
  197. package/src/procedures/projected-coordinate-transform.ts +79 -0
  198. package/src/procedures/projection-batch-executor.ts +140 -0
  199. package/src/procedures/scene-yaml-legacy.ts +16 -0
  200. package/src/procedures/scene-yaml-loaders.ts +10 -0
  201. package/src/procedures/terrain-draping.ts +713 -0
  202. package/src/procedures/terrain-globe.ts +32 -0
  203. package/src/procedures/terrain-styled-topology.ts +184 -0
  204. package/src/procedures/web-mercator-legacy.ts +24 -0
  205. package/src/procedures/web-mercator-math.ts +50 -0
  206. package/src/scene/camera.ts +298 -0
  207. package/src/scene/camera_base.ts +116 -0
  208. package/src/scene/classic_scene.ts +20 -0
  209. package/src/scene/external_camera.ts +101 -0
  210. package/src/scene/globals.ts +120 -0
  211. package/src/scene/ground_footprint.ts +139 -0
  212. package/src/scene/host_frame.ts +326 -0
  213. package/src/scene/projected_tile_lod.ts +125 -0
  214. package/src/scene/projection_math.ts +142 -0
  215. package/src/scene/projection_shaders.ts +183 -0
  216. package/src/scene/renderer.ts +516 -0
  217. package/src/scene/scene-resource-types.ts +174 -0
  218. package/src/scene/scene.ts +2378 -0
  219. package/src/scene/scene_bundle.ts +304 -0
  220. package/src/scene/scene_debug.ts +129 -0
  221. package/src/scene/scene_loader.ts +402 -0
  222. package/src/scene/scene_worker.ts +528 -0
  223. package/src/scene/view.ts +683 -0
  224. package/src/scene/visibility_adapter.ts +319 -0
  225. package/src/scene/worker_url.ts +15 -0
  226. package/src/selection/draped-terrain-surface.ts +377 -0
  227. package/src/selection/selection-types.ts +79 -0
  228. package/src/selection/selection.ts +542 -0
  229. package/src/selection/selection_fragment.glsl +18 -0
  230. package/src/selection/selection_globals.glsl +9 -0
  231. package/src/selection/selection_pixels.ts +59 -0
  232. package/src/selection/selection_vertex.glsl +15 -0
  233. package/src/selection/terrain_surface.ts +298 -0
  234. package/src/shader-modules/globe-horizon.ts +52 -0
  235. package/src/shader-modules/height-decode.ts +41 -0
  236. package/src/shader-modules/hillshade.ts +70 -0
  237. package/src/shader-modules/index.ts +10 -0
  238. package/src/shader-modules/planar.ts +24 -0
  239. package/src/shader-modules/sphere-map.ts +38 -0
  240. package/src/shader-modules/triplanar.ts +45 -0
  241. package/src/sources/aligned_tile_source.ts +122 -0
  242. package/src/sources/data_source.ts +655 -0
  243. package/src/sources/decoded_tile_store.ts +245 -0
  244. package/src/sources/geojson.ts +300 -0
  245. package/src/sources/mvt.ts +247 -0
  246. package/src/sources/raster.ts +341 -0
  247. package/src/sources/shared_tile_source_adapter.ts +117 -0
  248. package/src/sources/sources.ts +10 -0
  249. package/src/sources/tile_source_adapter.ts +84 -0
  250. package/src/sources/tile_source_metadata.ts +65 -0
  251. package/src/sources/tile_source_state.ts +112 -0
  252. package/src/sources/topojson.ts +90 -0
  253. package/src/styles/feature_annotations.ts +16 -0
  254. package/src/styles/filter.ts +190 -0
  255. package/src/styles/geometry-style-types.ts +209 -0
  256. package/src/styles/globe_visibility_wgsl.ts +22 -0
  257. package/src/styles/layer-types.ts +45 -0
  258. package/src/styles/layer.ts +586 -0
  259. package/src/styles/lines/dasharray.ts +49 -0
  260. package/src/styles/lines/lines.ts +707 -0
  261. package/src/styles/lines/lines_wgsl.ts +224 -0
  262. package/src/styles/points/point-runtime-types.ts +125 -0
  263. package/src/styles/points/points.ts +1079 -0
  264. package/src/styles/points/points_fragment.glsl +126 -0
  265. package/src/styles/points/points_vertex.glsl +230 -0
  266. package/src/styles/points/points_wgsl.ts +189 -0
  267. package/src/styles/polygons/polygons.ts +268 -0
  268. package/src/styles/polygons/polygons_fragment.glsl +173 -0
  269. package/src/styles/polygons/polygons_vertex.glsl +213 -0
  270. package/src/styles/polygons/polygons_wgsl.ts +127 -0
  271. package/src/styles/property-types.ts +125 -0
  272. package/src/styles/raster/raster.ts +33 -0
  273. package/src/styles/raster/raster_globals.glsl +46 -0
  274. package/src/styles/style-mixing-types.ts +101 -0
  275. package/src/styles/style-runtime-types.ts +220 -0
  276. package/src/styles/style-schema.ts +133 -0
  277. package/src/styles/style.ts +1033 -0
  278. package/src/styles/style_globals.glsl +69 -0
  279. package/src/styles/style_manager.ts +464 -0
  280. package/src/styles/style_parser.ts +620 -0
  281. package/src/styles/text/font_manager.ts +180 -0
  282. package/src/styles/text/fontfaceobserver.d.ts +10 -0
  283. package/src/styles/text/text-types.ts +220 -0
  284. package/src/styles/text/text.ts +378 -0
  285. package/src/styles/text/text_canvas.ts +773 -0
  286. package/src/styles/text/text_labels.ts +436 -0
  287. package/src/styles/text/text_segments.ts +142 -0
  288. package/src/styles/text/text_settings.ts +228 -0
  289. package/src/styles/text/text_wgsl.ts +159 -0
  290. package/src/styles/text/text_wrap.ts +194 -0
  291. package/src/tile/globe_tile_preload.ts +40 -0
  292. package/src/tile/tangram_tileset_2d.ts +108 -0
  293. package/src/tile/tile-build-types.ts +155 -0
  294. package/src/tile/tile.ts +807 -0
  295. package/src/tile/tile_id.ts +172 -0
  296. package/src/tile/tile_manager.ts +889 -0
  297. package/src/tile/tile_pyramid.ts +119 -0
  298. package/src/tile/tile_resource_cache.ts +91 -0
  299. package/src/tile/tile_traversal_adapter.ts +132 -0
  300. package/src/types.ts +332 -0
  301. package/src/utils/debounce.ts +17 -0
  302. package/src/utils/debug_settings.ts +43 -0
  303. package/src/utils/errors.ts +12 -0
  304. package/src/utils/functions.ts +95 -0
  305. package/src/utils/geo.ts +364 -0
  306. package/src/utils/hash.ts +14 -0
  307. package/src/utils/log.ts +108 -0
  308. package/src/utils/media_capture.ts +193 -0
  309. package/src/utils/merge.ts +44 -0
  310. package/src/utils/obb.ts +134 -0
  311. package/src/utils/props.ts +43 -0
  312. package/src/utils/slice.ts +14 -0
  313. package/src/utils/subscribe.ts +58 -0
  314. package/src/utils/task.ts +154 -0
  315. package/src/utils/thread.ts +26 -0
  316. package/src/utils/urls.ts +223 -0
  317. package/src/utils/utils.ts +310 -0
  318. package/src/utils/vector.ts +197 -0
  319. package/src/utils/version.ts +8 -0
  320. package/src/utils/worker-types.ts +79 -0
  321. package/src/utils/worker_broker.ts +523 -0
@@ -0,0 +1,402 @@
1
+ // Tangram
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (c) 2013-2016 Brett Camper and Mapzen
4
+ // Copyright (c) 2026 vis.gl contributors
5
+
6
+ import log from '../utils/log';
7
+ import GLSL from '../gl/glsl';
8
+ import * as URLs from '../utils/urls';
9
+ import mergeObjects from '../utils/merge';
10
+ import subscribeMixin from '../utils/subscribe';
11
+ import { getPropertyPath, setPropertyPath } from '../utils/props';
12
+ import { flattenGlobalProperties, applyGlobalProperties, isGlobalSubstitution } from './globals';
13
+ import { createSceneBundle } from './scene_bundle';
14
+ import { isReserved } from '../styles/layer';
15
+ import {normalizeSceneLights} from '../lights/light-definitions';
16
+ import type {SubscriptionMethods} from '../utils/subscribe';
17
+ import type {SceneBundle} from './scene_bundle';
18
+ import type {
19
+ SceneDefinition, SceneInput, SceneImportError, SceneLoadOptions, SceneLoadResult,
20
+ SceneResourceDescriptor, SceneSourceDefinition, SceneTextureNodes, LoadedScene,
21
+ SceneLayerDefinition, SceneMaterialChannel, SceneLoaderAPI, SceneStyleDefinition,
22
+ FinalizedSceneDefinition, SceneNamedLights
23
+ } from './scene-resource-types';
24
+
25
+ const SceneLoader = subscribeMixin<Omit<SceneLoaderAPI, keyof SubscriptionMethods>>({
26
+
27
+ // Load scenes definitions from URL & proprocess
28
+ async loadScene(this: SceneLoaderAPI, url: SceneInput,
29
+ { path, type, cameraMode }: SceneLoadOptions = {}): Promise<LoadedScene & {texture_nodes: SceneTextureNodes}> {
30
+ const errors: SceneImportError[] = [];
31
+ const texture_nodes: SceneTextureNodes = {};
32
+ const scene = await this.loadSceneRecursive({ url, path, type }, null, texture_nodes, errors);
33
+ const {config, bundle} = this.finalize(scene, { cameraMode });
34
+ if (!config) {
35
+ // root scene failed to load, reject with first error
36
+ throw errors[0];
37
+ }
38
+ else if (errors.length > 0) {
39
+ // scene loaded, but some imports had errors
40
+ errors.forEach(error => {
41
+ const message = `Failed to import scene: ${error.url}`;
42
+ log('error', message, error);
43
+ this.trigger('error', { type: 'scene_import', message, error, url: error.url });
44
+ });
45
+ }
46
+ return { config, bundle, texture_nodes };
47
+ },
48
+
49
+ // Loads scene files from URL, recursively loading 'import' scenes
50
+ // Optional *initial* path only (won't be passed to recursive 'import' calls)
51
+ // Useful for loading resources in base scene file from a separate location
52
+ // (e.g. in Tangram Play, when modified local scene should still refer to original resource URLs)
53
+ async loadSceneRecursive({ url, path, type }: SceneResourceDescriptor, parent: SceneBundle | null,
54
+ texture_nodes: SceneTextureNodes = {}, errors: SceneImportError[] = []): Promise<SceneLoadResult> {
55
+ if (!url) {
56
+ return {};
57
+ }
58
+
59
+ const bundle = createSceneBundle(url, path, parent, type);
60
+
61
+ try {
62
+ let config = await bundle.load();
63
+ if (config.import == null) {
64
+ this.normalize(config, bundle, texture_nodes);
65
+ return { config, bundle };
66
+ }
67
+
68
+ // accept single entry or array
69
+ if (!Array.isArray(config.import)) {
70
+ config.import = [config.import]; // convert to array
71
+ }
72
+
73
+ // Collect URLs of scenes to import
74
+ const imports: SceneResourceDescriptor[] = [];
75
+ (config.import as SceneInput[]).forEach(url => {
76
+ // Inline scene objects inherit this scene's resource directory.
77
+ // Keep them as objects so functions survive and no blob URL
78
+ // obscures their base (or leaks for each editor reload).
79
+ if (typeof url === 'object') {
80
+ imports.push({url, path: bundle.container || bundle.isContainer() ? '' : bundle.path});
81
+ }
82
+ else {
83
+ const resource = bundle.resourceFor(url);
84
+ if (resource.url == null) {
85
+ const error: SceneImportError = new Error(`Scene import not found: ${url}`);
86
+ error.url = url; // Keep the authored archive path, not an undefined blob URL.
87
+ errors.push(error);
88
+ }
89
+ else {
90
+ imports.push(resource);
91
+ }
92
+ }
93
+ });
94
+ delete config.import; // don't want to merge this property
95
+
96
+ // load and normalize imports
97
+ // Each subtree owns its texture provenance. Recursive loads already
98
+ // normalize their local config; re-normalizing a merged import would
99
+ // resolve descendant textures against the wrong bundle. Merge nodes
100
+ // in authored order, never asynchronous completion order.
101
+ const imported_nodes = imports.map((): SceneTextureNodes => ({}));
102
+ const queue = imports.map((resource, index) =>
103
+ this.loadSceneRecursive(resource, bundle, imported_nodes[index], errors));
104
+ const scenes = await Promise.all(queue);
105
+ const configs = scenes.filter(scene => scene.config).map(scene => scene.config);
106
+ scenes.forEach((scene, index) => {
107
+ if (scene.config) Object.assign(texture_nodes, imported_nodes[index]);
108
+ });
109
+
110
+ this.normalize(config, bundle, texture_nodes); // last normalize parent
111
+ config = mergeObjects<SceneDefinition>({}, ...configs, config);
112
+ return { config, bundle, texture_nodes };
113
+ }
114
+ catch (caught) {
115
+ const error = caught as SceneImportError;
116
+ // Collect scene load errors as we go
117
+ error.url = url;
118
+ errors.push(error);
119
+ return {};
120
+ }
121
+ },
122
+
123
+ // Normalize properties that should be adjust within each local scene file (usually by path)
124
+ normalize(config: SceneDefinition, bundle: SceneBundle, texture_nodes: SceneTextureNodes = {}): LoadedScene {
125
+ this.normalizeDataSources(config, bundle);
126
+ this.normalizeFonts(config, bundle);
127
+ this.normalizeTextures(config, bundle);
128
+ this.collectTextures(config, bundle, texture_nodes);
129
+ return { config, bundle, texture_nodes };
130
+ },
131
+
132
+ // Expand paths for data source
133
+ normalizeDataSources(config: SceneDefinition, bundle: SceneBundle): SceneDefinition {
134
+ config.sources = config.sources || {};
135
+
136
+ for (const sn in config.sources) {
137
+ this.normalizeDataSource(config.sources[sn], bundle);
138
+ }
139
+
140
+ return config;
141
+ },
142
+
143
+ normalizeDataSource(source: SceneSourceDefinition, bundle: SceneBundle): SceneSourceDefinition {
144
+ source.url = bundle.urlFor(source.url);
145
+ // Inline TileJSON is already a descriptor, not a resource URL.
146
+ if (typeof source.tilejson !== 'object') source.tilejson = bundle.urlFor(source.tilejson);
147
+
148
+ // composite untiled raster sources
149
+ if (Array.isArray(source.composite)) {
150
+ source.composite.forEach(c => c.url = bundle.urlFor(c.url));
151
+ }
152
+
153
+ // custom scripts
154
+ if (source.scripts) {
155
+ // convert legacy array-style scripts to object format (script URL is used as both key and value)
156
+ if (Array.isArray(source.scripts)) {
157
+ source.scripts = source.scripts.reduce<Record<string, string | undefined>>((val, cur) => { val[cur] = cur; return val; }, {});
158
+ }
159
+
160
+ // resolve URLs for external scripts
161
+ for (const s in source.scripts) {
162
+ source.scripts[s] = bundle.urlFor(source.scripts[s]);
163
+ }
164
+ }
165
+
166
+ return source;
167
+ },
168
+
169
+ // Expand paths for fonts
170
+ normalizeFonts(config: SceneDefinition, bundle: SceneBundle): SceneDefinition {
171
+ config.fonts = config.fonts || {};
172
+
173
+ // Add scene base path for URL-based fonts (skip "external" fonts referencing CSS-loaded resources)
174
+ const fonts = Object.values(config.fonts).filter(face => face !== 'external');
175
+ for (const face of fonts) {
176
+ const faces = (Array.isArray(face) ? face : [face]); // can be single value or array
177
+ faces.forEach(face => face.url = bundle.urlFor(face.url));
178
+ }
179
+
180
+ return config;
181
+ },
182
+
183
+ // Expand paths and centralize texture definitions for a scene object
184
+ normalizeTextures(config: SceneDefinition, bundle: SceneBundle): void {
185
+ config.textures = config.textures || {};
186
+
187
+ // Add current scene's base path to globally defined textures
188
+ // Only adds path for textures with relative URLs, so textures in imported scenes get the base
189
+ // path of their immediate scene file
190
+ if (config.textures) {
191
+ for (const tn in config.textures) {
192
+ const texture = config.textures[tn];
193
+ if (texture.url) {
194
+ texture.url = bundle.urlFor(texture.url);
195
+ }
196
+ }
197
+ }
198
+ },
199
+
200
+ // Move inline (URL string) textures to the scene's top-level set of textures (config.textures).
201
+ // There are 4 such cases of textures:
202
+ // - in a style's `texture` property
203
+ // - in a style's `material` properties
204
+ // - in a style's custom uniforms (`shaders.uniforms`)
205
+ // - in a draw groups `texture` property
206
+ collectTextures(config: SceneDefinition, bundle: SceneBundle, texture_nodes: SceneTextureNodes): void {
207
+ const textures = config.textures!; // normalizeTextures runs before collection.
208
+ // Inline textures in styles
209
+ if (config.styles) {
210
+ for (const sn in config.styles) {
211
+ const style: SceneStyleDefinition = config.styles[sn];
212
+
213
+ // Style `texture`
214
+ const tex = style.texture;
215
+ if (typeof tex === 'string' && !textures[tex]) {
216
+ const path = ['styles', sn, 'texture'];
217
+ this.addTextureNode(path, bundle, texture_nodes);
218
+ }
219
+
220
+ // Material
221
+ if (style.material) {
222
+ ['emission', 'ambient', 'diffuse', 'specular', 'normal'].forEach(prop => {
223
+ // Material property has a texture
224
+ const tex = style.material![prop] != null &&
225
+ (style.material![prop] as Exclude<SceneMaterialChannel, number | string | number[]>).texture;
226
+ if (typeof tex === 'string' && !textures[tex]) {
227
+ const path = ['styles', sn, 'material', prop, 'texture'];
228
+ this.addTextureNode(path, bundle, texture_nodes);
229
+ }
230
+ });
231
+ }
232
+ }
233
+ }
234
+
235
+ // Inline textures in shader uniforms
236
+ if (config.styles) {
237
+ for (const sn in config.styles) {
238
+ const style = config.styles[sn];
239
+
240
+ if (style.shaders && style.shaders.uniforms) {
241
+ GLSL.parseUniforms(style.shaders.uniforms).forEach(({ type, value, path }) => {
242
+ // Texture by URL (string-named texture not referencing existing texture definition)
243
+ if (type === 'sampler2D' && typeof value === 'string' && !textures[value]) {
244
+ const texture_path = ['styles', sn, 'shaders', 'uniforms', ...path];
245
+ this.addTextureNode(texture_path, bundle, texture_nodes);
246
+ }
247
+ });
248
+ }
249
+ }
250
+ }
251
+
252
+ // Inline textures in draw blocks
253
+ if (config.layers) {
254
+ const stack: unknown[] = [config.layers];
255
+ const path_stack = [['layers']];
256
+ while (stack.length > 0) {
257
+ const layer = stack.pop();
258
+ const layer_path = path_stack.pop()!;
259
+
260
+ // only recurse into objects
261
+ if (typeof layer !== 'object' || Array.isArray(layer)) {
262
+ continue;
263
+ }
264
+
265
+ const definition = layer as SceneLayerDefinition;
266
+ for (const prop in definition) {
267
+ if (prop === 'draw') { // process draw groups for current layer
268
+ const draws = definition.draw!;
269
+ for (const group in draws) {
270
+ if (draws[group].texture) {
271
+ const tex = draws[group].texture;
272
+ if (typeof tex === 'string' && !textures[tex]) {
273
+ const path = [...layer_path, prop, group, 'texture'];
274
+ this.addTextureNode(path, bundle, texture_nodes);
275
+ }
276
+ }
277
+
278
+ // special handling for outlines :(
279
+ if (draws[group].outline && draws[group].outline.texture) {
280
+ const tex = draws[group].outline.texture;
281
+ if (typeof tex === 'string' && !textures[tex]) {
282
+ const path = [...layer_path, prop, group, 'outline', 'texture'];
283
+ this.addTextureNode(path, bundle, texture_nodes);
284
+ }
285
+ }
286
+ }
287
+
288
+ }
289
+ else if (isReserved(prop)) {
290
+ continue; // skip reserved keyword
291
+ }
292
+ else {
293
+ stack.push(definition[prop]); // traverse sublayer
294
+ path_stack.push([...layer_path, prop]);
295
+ }
296
+ }
297
+ }
298
+ }
299
+ },
300
+
301
+ addTextureNode (path: (string | number)[], bundle: SceneBundle, texture_nodes: SceneTextureNodes): void {
302
+ const pathKey = JSON.stringify(path);
303
+ texture_nodes[pathKey] = {
304
+ path,
305
+ bundle
306
+ };
307
+ },
308
+
309
+ // Hoist any remaining inline texture nodes that don't have a corresponding named texture
310
+ // base_bundle is the bundle for the root scene, for resolving textures from global properties
311
+ hoistTextureNodes (config: SceneDefinition, base_bundle: SceneBundle, texture_nodes: SceneTextureNodes = {}): void {
312
+ const textures = config.textures!; // Normalized scene owns the texture registry.
313
+ for(const { path, bundle } of Object.values(texture_nodes)) {
314
+ const curValue = getPropertyPath(config, path);
315
+
316
+ // Make sure current property values is a string to account for global property substitutions
317
+ // e.g. shader uniforms are ambiguous, could be replaced with string value indicating texture,
318
+ // but could also be a float, an array indicating vector, etc.
319
+ if (typeof curValue === 'string' && textures[curValue] == null) {
320
+ if (isGlobalSubstitution(config, path)) {
321
+ // global substituions are resolved against the base scene path, not the import they came from
322
+ const url = base_bundle.urlFor(curValue);
323
+ textures[curValue] = { url };
324
+ }
325
+ else {
326
+ // non-global textures are resolved against the import they came from
327
+ const url = bundle.urlFor(curValue);
328
+ textures[String(url)] = { url }; // Preserve legacy key coercion for a missing archive resource.
329
+ setPropertyPath(config, path, url);
330
+ }
331
+ }
332
+ }
333
+ },
334
+
335
+ // Substitutes global scene properties (those defined in the `config.global` object) for any style values
336
+ // of the form `global.`, for example `color: global.park_color` would be replaced with the value (if any)
337
+ // defined for the `park_color` property in `config.global.park_color`.
338
+ applyGlobalProperties<Config extends SceneDefinition>(config: Config): Config {
339
+ if (!config.global || Object.keys(config.global).length === 0) {
340
+ return config; // no global properties to transform
341
+ }
342
+
343
+ const globals = flattenGlobalProperties(config.global); // flatten nested globals for simpler string look-ups
344
+ return applyGlobalProperties(globals, config);
345
+ },
346
+
347
+ // Normalize some scene-wide settings that apply to the final, merged scene
348
+ finalize: finalizeScene
349
+ });
350
+
351
+ /** Normalize a known scene while preserving the caller's resource resolver identity. */
352
+ function finalizeScene<Bundle>(scene: {config: SceneDefinition; bundle: Bundle}, options?: SceneLoadOptions):
353
+ {config: FinalizedSceneDefinition; bundle: Bundle};
354
+ /** Preserve an empty result when the root or import subtree failed to load. */
355
+ function finalizeScene(scene: SceneLoadResult, options?: SceneLoadOptions): SceneLoadResult;
356
+ function finalizeScene({config, bundle}: {config?: SceneDefinition; bundle?: unknown},
357
+ {cameraMode}: SceneLoadOptions = {}): {config?: SceneDefinition; bundle?: unknown} {
358
+ if (!config) {
359
+ return {};
360
+ }
361
+
362
+ // Ensure top-level properties
363
+ config.global = config.global || {};
364
+ config.scene = config.scene || {};
365
+ // Internal worker policy: host cameras, not tile zoom, own billboard collision.
366
+ config.scene._host_screen_space_labels = cameraMode === 'external';
367
+ config.cameras = config.cameras || {};
368
+ const native_lights = Array.isArray(config.lights);
369
+ const lights = normalizeSceneLights(config.lights || {}) as SceneNamedLights;
370
+ config.lights = lights;
371
+ if (native_lights && Object.keys(lights).length === 0) {
372
+ config.scene.lighting = 'configured'; // Explicit empty arrays still select the configurable WGSL path.
373
+ }
374
+ config.styles = config.styles || {};
375
+ config.layers = config.layers || {};
376
+
377
+ // Host-driven scenes do not need Tangram camera configuration. Keep
378
+ // authored cameras intact, but do not synthesize a default camera.
379
+ if (cameraMode !== 'external') {
380
+ // If only one camera specified, set it as default
381
+ if (config.camera) {
382
+ config.cameras.default = config.camera;
383
+ }
384
+
385
+ // If no cameras specified, create one
386
+ if (Object.keys(config.cameras).length === 0) {
387
+ config.cameras.default = {};
388
+ }
389
+ }
390
+
391
+ // If no lights specified, create default
392
+ if (!native_lights && (Object.keys(lights).length === 0 ||
393
+ Object.keys(lights).every(i => lights[i].visible === false))) {
394
+ lights.default_light = {
395
+ type: 'directional'
396
+ };
397
+ }
398
+
399
+ return { config: config as FinalizedSceneDefinition, bundle };
400
+ }
401
+
402
+ export default SceneLoader;