@mapless/core 1.0.23 → 1.0.25

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 (35) hide show
  1. package/dist/index.js +573 -190
  2. package/dist/types/Mapless/Base.d.ts +2 -0
  3. package/dist/types/Mapless/Base.d.ts.map +1 -1
  4. package/dist/types/Mapless/draw/index.d.ts +1 -0
  5. package/dist/types/Mapless/draw/index.d.ts.map +1 -1
  6. package/dist/types/Mapless/extensions/MapboxResizeFixer.d.ts +8 -0
  7. package/dist/types/Mapless/extensions/MapboxResizeFixer.d.ts.map +1 -0
  8. package/dist/types/Mapless/icons/Singleton.d.ts.map +1 -1
  9. package/dist/types/Mapless/lang/MapboxLanguage.d.ts +1 -0
  10. package/dist/types/Mapless/lang/MapboxLanguage.d.ts.map +1 -1
  11. package/dist/types/Mapless/layer/FixedRectangleLayer.d.ts +2 -0
  12. package/dist/types/Mapless/layer/FixedRectangleLayer.d.ts.map +1 -1
  13. package/dist/types/Mapless/layer/RectangleLayer.d.ts +1 -0
  14. package/dist/types/Mapless/layer/RectangleLayer.d.ts.map +1 -1
  15. package/dist/types/Mapless/mana-3d/mapModel.d.ts.map +1 -1
  16. package/dist/types/Mapless/mana-three/airspace3.d.ts +8 -0
  17. package/dist/types/Mapless/mana-three/airspace3.d.ts.map +1 -1
  18. package/dist/types/Mapless/mana-three/basicObject.d.ts.map +1 -1
  19. package/dist/types/Mapless/mana-three/curve3d.d.ts.map +1 -1
  20. package/dist/types/Mapless/mana-three/index.d.ts +1 -1
  21. package/dist/types/Mapless/mana-three/index.d.ts.map +1 -1
  22. package/dist/types/Mapless/mana-three/instancedModel.d.ts +75 -9
  23. package/dist/types/Mapless/mana-three/instancedModel.d.ts.map +1 -1
  24. package/dist/types/Mapless/mana-three/line2Manager.d.ts +1 -0
  25. package/dist/types/Mapless/mana-three/line2Manager.d.ts.map +1 -1
  26. package/dist/types/Mapless/mana-three/model.d.ts +1 -0
  27. package/dist/types/Mapless/mana-three/model.d.ts.map +1 -1
  28. package/dist/types/Mapless/mana-three/three.d.ts +2 -0
  29. package/dist/types/Mapless/mana-three/three.d.ts.map +1 -1
  30. package/dist/types/Mapless/preset/types.d.ts +20 -4
  31. package/dist/types/Mapless/preset/types.d.ts.map +1 -1
  32. package/dist/types/Mapless/theme/lite.d.ts +2 -2
  33. package/dist/types/Mapless/theme/lite.d.ts.map +1 -1
  34. package/dist/types/Mapless/themeSources.d.ts.map +1 -1
  35. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import mapbox_gl, { LngLat, MapMouseEvent, Marker, MercatorCoordinate, Point, Po
3
3
  import gcoord from "gcoord";
4
4
  import mapbox_gl_draw from "@mapbox/mapbox-gl-draw";
5
5
  import "@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css";
6
- import { GLTFLoader, Line2, LineGeometry, LineMaterial } from "three-stdlib";
6
+ import { DRACOLoader, GLTFLoader, Line2, LineGeometry, LineMaterial } from "three-stdlib";
7
7
  import * as __rspack_external_three from "three";
8
8
  function buildTransformMatrix(transform) {
9
9
  if (transform.matrix) return transform.matrix.clone();
@@ -743,7 +743,7 @@ class Base {
743
743
  return this;
744
744
  };
745
745
  onManaRemove = (handler)=>{
746
- this.emitter.off('managerRemove', handler);
746
+ this.emitter.on('managerRemove', handler);
747
747
  return this;
748
748
  };
749
749
  use(Manager, name, options) {
@@ -824,6 +824,25 @@ class MapboxRequestHandler {
824
824
  });
825
825
  }
826
826
  }
827
+ class MapboxResizeFixer {
828
+ _map;
829
+ _interval = null;
830
+ constructor(map){
831
+ this._map = map;
832
+ this._map?.on('load', this.mapLoad);
833
+ this.startFix();
834
+ }
835
+ mapLoad() {
836
+ this._interval && clearInterval(this._interval);
837
+ }
838
+ startFix() {
839
+ this._interval = setInterval(()=>{
840
+ this._map?.resize();
841
+ const { clientWidth, clientHeight } = this._map?._canvas || {};
842
+ if (clientWidth && clientHeight) this._map?._resizeCanvas(clientWidth, clientHeight);
843
+ }, 20);
844
+ }
845
+ }
827
846
  const COLOR_PRESETS = (()=>{
828
847
  const keys = Object.keys(maplessPreset.STATUS_COLORS);
829
848
  const ret = {};
@@ -11208,33 +11227,36 @@ const lightFog = {
11208
11227
  0
11209
11228
  ]
11210
11229
  };
11211
- const lite = ()=>({
11230
+ const lite = (urlCount = 1, rasterOpacity)=>({
11212
11231
  version: 8,
11213
11232
  sprite: `${maplessPreset.mapboxAssets}/style/sprite`,
11214
11233
  glyphs: `${maplessPreset.mapboxAssets}/glyphs/mapbox/{fontstack}/{range}.pbf`,
11215
11234
  projection: {
11216
11235
  name: 'globe'
11217
11236
  },
11218
- sources: {
11219
- lite_world: {
11220
- type: 'raster',
11221
- tiles: [
11222
- `${maplessPreset.geoServer}/{MAP_ID}/{z}/{x}/{y}`
11223
- ],
11224
- tileSize: 256,
11225
- volatile: true
11226
- }
11227
- },
11228
- layers: [
11229
- {
11230
- id: 'lite_world_layer',
11237
+ sources: Object.fromEntries(Array.from({
11238
+ length: urlCount
11239
+ }, (_, i)=>[
11240
+ `lite_world_${i + 1}`,
11241
+ {
11242
+ type: 'raster',
11243
+ tiles: [
11244
+ `${maplessPreset.geoServer}/{MAP_ID}/{z}/{x}/{y}`
11245
+ ],
11246
+ tileSize: 256,
11247
+ volatile: true
11248
+ }
11249
+ ])),
11250
+ layers: Array.from({
11251
+ length: urlCount
11252
+ }, (_, i)=>({
11253
+ id: `lite_world_layer_${i + 1}`,
11231
11254
  type: 'raster',
11232
- source: 'lite_world',
11255
+ source: `lite_world_${i + 1}`,
11233
11256
  paint: {
11234
- 'raster-opacity': 1
11257
+ 'raster-opacity': rasterOpacity?.[i] ?? 1
11235
11258
  }
11236
- }
11237
- ]
11259
+ }))
11238
11260
  });
11239
11261
  const buildTileUrl = (url)=>{
11240
11262
  if (url.startsWith('http://') || url.startsWith('https://')) if (url.includes('/{z}/{x}/{y}')) return url;
@@ -11264,10 +11286,18 @@ const transformMapCenter = (center, fromCoord, toCoord)=>{
11264
11286
  });
11265
11287
  };
11266
11288
  const sourcesMap = ()=>maplessPreset.MAP_THEME_SOURCES?.reduce((prev, item)=>{
11267
- const copy = adjustMapConfigByCoord(lite(), item.coord);
11268
- copy.sources.lite_world.tiles = [
11269
- buildTileUrl(item.url)
11289
+ const urls = Array.isArray(item.url) ? item.url : [
11290
+ item.url
11270
11291
  ];
11292
+ const opacities = null != item.rasterOpacity ? Array.isArray(item.rasterOpacity) ? item.rasterOpacity : [
11293
+ item.rasterOpacity
11294
+ ] : [];
11295
+ const copy = adjustMapConfigByCoord(lite(urls.length, opacities), item.coord);
11296
+ urls.forEach((url, i)=>{
11297
+ copy.sources[`lite_world_${i + 1}`].tiles = [
11298
+ buildTileUrl(url)
11299
+ ];
11300
+ });
11271
11301
  if (!maplessPreset.globe) copy.projection = {
11272
11302
  name: 'mercator'
11273
11303
  };
@@ -11327,6 +11357,10 @@ class Mapless extends Base {
11327
11357
  _mapMode = '2d';
11328
11358
  _mapStyle = null;
11329
11359
  _debug = false;
11360
+ enableThree = true;
11361
+ styleImageMissingHandler = (e)=>{
11362
+ if (this.map) icons_Singleton.handleMissingImage(this.map, e.id);
11363
+ };
11330
11364
  constructor(container, options){
11331
11365
  super();
11332
11366
  this.onInit = options.onMapInit;
@@ -11342,6 +11376,7 @@ class Mapless extends Base {
11342
11376
  initializeMap(container, options) {
11343
11377
  mapbox_gl.accessToken = options.accessToken || Mapless.accessToken;
11344
11378
  this._debug = options.debug || false;
11379
+ this.enableThree = false !== options.enableThree;
11345
11380
  if (!this._debug) {
11346
11381
  mapbox_gl.config.REQUIRE_ACCESS_TOKEN = false;
11347
11382
  mapbox_gl.config.MAX_PARALLEL_IMAGE_REQUESTS = 256;
@@ -11366,13 +11401,12 @@ class Mapless extends Base {
11366
11401
  preserveDrawingBuffer: true,
11367
11402
  transformRequest: maplessPreset.transformRequest
11368
11403
  });
11404
+ new MapboxResizeFixer(this.map);
11369
11405
  const reqHandler = new MapboxRequestHandler();
11370
11406
  reqHandler.setupMapboxInterceptor(this.map);
11371
11407
  this.map.on('zoom', this.mapZoomHandler);
11372
11408
  this.map.on('load', this.initCtrls);
11373
- this.map.on('styleimagemissing', (e)=>{
11374
- if (this.map) icons_Singleton.handleMissingImage(this.map, e.id);
11375
- });
11409
+ this.map.on('styleimagemissing', this.styleImageMissingHandler);
11376
11410
  Promise.resolve().then(()=>{
11377
11411
  this.map && this.onInit?.(this.map);
11378
11412
  });
@@ -11395,7 +11429,7 @@ class Mapless extends Base {
11395
11429
  if (logo) logo.style.display = 'none';
11396
11430
  const attributions = this.map.getContainer().querySelector('.mapboxgl-ctrl-attrib');
11397
11431
  if (attributions) attributions.style.display = 'none';
11398
- this.initMapThree();
11432
+ if (this.enableThree) this.initMapThree();
11399
11433
  }
11400
11434
  };
11401
11435
  mapZoomHandler = ()=>{
@@ -11568,18 +11602,19 @@ class Mapless extends Base {
11568
11602
  if (!this.map) return;
11569
11603
  this.map.flyTo({
11570
11604
  center: this.coordTrans('dataToTile', options.center),
11571
- zoom: options.zoom || this.map.getZoom(),
11572
- bearing: options.bearing || 0,
11573
- pitch: options.pitch || 0,
11574
- speed: options.speed || 1.2,
11575
- curve: options.curve || 1.42,
11576
- duration: options.duration || 2000,
11577
- essential: options.essential || true
11605
+ zoom: options.zoom ?? this.map.getZoom(),
11606
+ bearing: options.bearing ?? 0,
11607
+ pitch: options.pitch ?? 0,
11608
+ speed: options.speed ?? 1.2,
11609
+ curve: options.curve ?? 1.42,
11610
+ duration: options.duration ?? 2000,
11611
+ essential: options.essential ?? true
11578
11612
  });
11579
11613
  }
11580
11614
  toggleLayer(layerId, visible) {
11581
11615
  if (!this.map?.getLayer(layerId)) return;
11582
- const isVisible = void 0 !== visible ? visible : this.map?.getLayoutProperty(layerId, 'visibility') !== 'none';
11616
+ const currentVisible = this.map?.getLayoutProperty(layerId, 'visibility') !== 'none';
11617
+ const isVisible = visible ?? !currentVisible;
11583
11618
  this.map?.setLayoutProperty(layerId, 'visibility', isVisible ? 'visible' : 'none');
11584
11619
  }
11585
11620
  interactionLayers(interaction) {
@@ -11628,7 +11663,12 @@ class Mapless extends Base {
11628
11663
  }
11629
11664
  destroy() {
11630
11665
  if (!this.map) return;
11666
+ this.map?.off('zoom', this.mapZoomHandler);
11667
+ this.map?.off('load', this.initCtrls);
11668
+ this.map?.off('styleimagemissing', this.styleImageMissingHandler);
11631
11669
  this.clear();
11670
+ this.mapThree?.dispose();
11671
+ this.mapThree = null;
11632
11672
  this.map.remove();
11633
11673
  this.map = null;
11634
11674
  }
@@ -12424,7 +12464,7 @@ class PositionTool extends ShapeTool {
12424
12464
  }
12425
12465
  clearLayers = ()=>{
12426
12466
  if (this.draw?.map?.getLayer(this.pointMarkersLayer)) this.draw?.map?.removeLayer(this.pointMarkersLayer);
12427
- if (this.draw?.map?.getLayer(this.pointMarkersSource)) this.draw?.map?.removeLayer(this.pointMarkersSource);
12467
+ if (this.draw?.map?.getSource(this.pointMarkersSource)) this.draw?.map?.removeSource(this.pointMarkersSource);
12428
12468
  };
12429
12469
  }
12430
12470
  const blue = '#3bb2d0';
@@ -12696,6 +12736,10 @@ class Draw {
12696
12736
  areaTool;
12697
12737
  angleTool;
12698
12738
  positionTool;
12739
+ modeChangeHandler = (e)=>{
12740
+ const em = e;
12741
+ if (em?.mode === 'simple_select') this.onDrawOver?.();
12742
+ };
12699
12743
  constructor(mapless){
12700
12744
  this.mapless = mapless;
12701
12745
  this.map = this.mapless.map;
@@ -12709,10 +12753,7 @@ class Draw {
12709
12753
  this.map.addControl(this.drawControl);
12710
12754
  this.map.on('draw.create', this.createMeasure);
12711
12755
  this.map.on('draw.update', this.updateMeasure);
12712
- this.map.on('draw.modechange', (e)=>{
12713
- const em = e;
12714
- if (em?.mode === 'simple_select') this.onDrawOver?.();
12715
- });
12756
+ this.map.on('draw.modechange', this.modeChangeHandler);
12716
12757
  this.map.on('draw.delete', this.deleteMeasure);
12717
12758
  this.pointTool = new PointTool(this);
12718
12759
  this.lineTool = new LineTool(this);
@@ -12824,6 +12865,10 @@ class Draw {
12824
12865
  }
12825
12866
  destroy() {
12826
12867
  try {
12868
+ this.map?.off('draw.create', this.createMeasure);
12869
+ this.map?.off('draw.update', this.updateMeasure);
12870
+ this.map?.off('draw.modechange', this.modeChangeHandler);
12871
+ this.map?.off('draw.delete', this.deleteMeasure);
12827
12872
  this.drawControl && this.map?.removeControl(this.drawControl);
12828
12873
  this.drawControl = void 0;
12829
12874
  } catch (_error) {}
@@ -12868,6 +12913,7 @@ class MapboxLanguage {
12868
12913
  isTokenField = /^\{name/;
12869
12914
  map;
12870
12915
  container;
12916
+ initialStyleUpdateHandler = ()=>this._initialStyleUpdate();
12871
12917
  _current = '';
12872
12918
  get current() {
12873
12919
  return this._current;
@@ -12954,12 +13000,12 @@ class MapboxLanguage {
12954
13000
  }
12955
13001
  onAdd = (map)=>{
12956
13002
  this.map = map;
12957
- this.map.on('style.load', this._initialStyleUpdate.bind(this));
13003
+ this.map.on('style.load', this.initialStyleUpdateHandler);
12958
13004
  this.container = document.createElement('div');
12959
13005
  return this.container;
12960
13006
  };
12961
13007
  onRemove = (_map)=>{
12962
- this.map?.off('style.load', this._initialStyleUpdate);
13008
+ this.map?.off('style.load', this.initialStyleUpdateHandler);
12963
13009
  this.map = void 0;
12964
13010
  };
12965
13011
  getDefaultPosition;
@@ -13107,6 +13153,7 @@ class IdHub {
13107
13153
  const core_IdHub = IdHub;
13108
13154
  class FixedRectangleLayerManager extends EmitManager {
13109
13155
  rectangles = [];
13156
+ redrawFrame = null;
13110
13157
  constructor(mapless, options){
13111
13158
  super(mapless, options, 'fixed-rectangle');
13112
13159
  this.onInitialized();
@@ -13154,6 +13201,13 @@ class FixedRectangleLayerManager extends EmitManager {
13154
13201
  this.map.on('rotate', this.mapMoveHandler);
13155
13202
  this.map.on('zoom', this.mapZoomHandler);
13156
13203
  }
13204
+ scheduleDrawRectangles() {
13205
+ if (null !== this.redrawFrame) return;
13206
+ this.redrawFrame = requestAnimationFrame(()=>{
13207
+ this.redrawFrame = null;
13208
+ this.drawRectangles();
13209
+ });
13210
+ }
13157
13211
  setData(data) {
13158
13212
  this.rectangles = data;
13159
13213
  this.drawRectangles();
@@ -13261,10 +13315,10 @@ class FixedRectangleLayerManager extends EmitManager {
13261
13315
  this.mapless?.setData(this.idHub?.rectangleSourceId, data);
13262
13316
  }
13263
13317
  mapZoomHandler = ()=>{
13264
- if (this.rectangles.length > 0) this.drawRectangles();
13318
+ if (this.rectangles.length > 0) this.scheduleDrawRectangles();
13265
13319
  };
13266
13320
  mapMoveHandler = ()=>{
13267
- if (this.rectangles.length > 0) this.drawRectangles();
13321
+ if (this.rectangles.length > 0) this.scheduleDrawRectangles();
13268
13322
  };
13269
13323
  destroy = ()=>{
13270
13324
  if (this.map) {
@@ -13273,6 +13327,10 @@ class FixedRectangleLayerManager extends EmitManager {
13273
13327
  this.map.off('rotate', this.mapMoveHandler);
13274
13328
  this.map.off('zoom', this.mapZoomHandler);
13275
13329
  }
13330
+ if (null !== this.redrawFrame) {
13331
+ cancelAnimationFrame(this.redrawFrame);
13332
+ this.redrawFrame = null;
13333
+ }
13276
13334
  super.destroy();
13277
13335
  this.rectangles = [];
13278
13336
  };
@@ -13312,6 +13370,7 @@ class RectangleLayerManager extends EmitManager {
13312
13370
  program = null;
13313
13371
  positionBuffer = null;
13314
13372
  colorBuffer = null;
13373
+ clickHandler = null;
13315
13374
  vertexShaderSource = `
13316
13375
  attribute vec2 a_position;
13317
13376
  uniform vec2 u_resolution;
@@ -13533,6 +13592,10 @@ class RectangleLayerManager extends EmitManager {
13533
13592
  this.map?.triggerRepaint();
13534
13593
  }
13535
13594
  destroy = ()=>{
13595
+ if (this.map && this.clickHandler) {
13596
+ this.map.off('click', this.clickHandler);
13597
+ this.clickHandler = null;
13598
+ }
13536
13599
  if (this.map && this.customLayer) this.map.removeLayer(this.customLayer.id);
13537
13600
  this.customLayer = null;
13538
13601
  this.rectangles = [];
@@ -13552,8 +13615,8 @@ class RectangleLayerManager extends EmitManager {
13552
13615
  });
13553
13616
  }
13554
13617
  setupClickHandler() {
13555
- if (!this.map) return;
13556
- this.map.on('click', (e)=>{
13618
+ if (!this.map || this.clickHandler) return;
13619
+ this.clickHandler = (e)=>{
13557
13620
  if (!this.map || !e.point) return;
13558
13621
  for (const rect of this.rectangles){
13559
13622
  const centerPoint = this.map.project(new mapbox_gl.LngLat(rect.lng, rect.lat));
@@ -13574,7 +13637,8 @@ class RectangleLayerManager extends EmitManager {
13574
13637
  break;
13575
13638
  }
13576
13639
  }
13577
- });
13640
+ };
13641
+ this.map.on('click', this.clickHandler);
13578
13642
  }
13579
13643
  }
13580
13644
  const RectangleLayer = RectangleLayerManager;
@@ -18193,6 +18257,7 @@ class MapModelManager extends EmitManager {
18193
18257
  this.themeColorModels.clear();
18194
18258
  this.modelOptions.clear();
18195
18259
  this.clearModels();
18260
+ super.destroy();
18196
18261
  }
18197
18262
  }
18198
18263
  const mapModel = MapModelManager;
@@ -18617,6 +18682,19 @@ class Airspace3Manager extends manager_Manager {
18617
18682
  if (zone.edgeMesh) mapThree.setRenderableObjectVisible(`${zone.id}-edge`, visible);
18618
18683
  });
18619
18684
  }
18685
+ setFill2DVisible(visible) {
18686
+ if (!this.map) return;
18687
+ const visibility = visible ? 'visible' : 'none';
18688
+ if (this.map.getLayer(this.fill2DLayerId)) this.map.setLayoutProperty(this.fill2DLayerId, 'visibility', visibility);
18689
+ if (this.map.getLayer(this.lineLayerId)) this.map.setLayoutProperty(this.lineLayerId, 'visibility', visibility);
18690
+ }
18691
+ setAllEdgesVisible(visible) {
18692
+ const mapThree = this.getMapThree();
18693
+ if (!mapThree) return;
18694
+ this.zones.forEach((zone)=>{
18695
+ if (zone.edgeMesh) mapThree.setRenderableObjectVisible(`${zone.id}-edge`, visible);
18696
+ });
18697
+ }
18620
18698
  }
18621
18699
  const airspace3 = Airspace3Manager;
18622
18700
  const attachAirspace3 = (mapless, name, options)=>mapless?.use(Airspace3Manager, name, options);
@@ -18886,6 +18964,7 @@ class BasicThreeObjectManager extends manager_Manager {
18886
18964
  }
18887
18965
  destroy() {
18888
18966
  this.clearObjects();
18967
+ super.destroy();
18889
18968
  }
18890
18969
  }
18891
18970
  const basicObject = BasicThreeObjectManager;
@@ -19088,26 +19167,30 @@ class Curve3DManager extends manager_Manager {
19088
19167
  }
19089
19168
  destroy() {
19090
19169
  this.clearCurves();
19170
+ super.destroy();
19091
19171
  }
19092
19172
  }
19093
19173
  const curve3d = Curve3DManager;
19094
19174
  const attachCurve3D = (mapless, name, options)=>mapless?.use(Curve3DManager, name, options);
19095
19175
  const getCurve3D = (mapless, name)=>mapless?.get(Curve3DManager, name);
19096
19176
  const detachCurve3D = (mapless, name)=>mapless?.unuse(Curve3DManager, name);
19177
+ const DEFAULT_MODEL_TYPE = '__default__';
19097
19178
  class InstancedModelManager extends manager_Manager {
19098
19179
  scene = null;
19099
19180
  camera = null;
19100
19181
  renderer = null;
19101
19182
  customLayerId;
19102
19183
  isInitialized = false;
19103
- instancedMeshes = new Map();
19184
+ instancedModels = new Map();
19104
19185
  instanceDataMap = new Map();
19105
19186
  rotationAngles = new Map();
19106
19187
  autoRotateEnabled = new Map();
19107
19188
  rotationSpeeds = new Map();
19108
19189
  originalConfigs = new Map();
19109
19190
  clickCallback = null;
19191
+ canvasClickHandler = null;
19110
19192
  lastProjectionMatrix = null;
19193
+ zoomCleanup = null;
19111
19194
  constructor(mapless){
19112
19195
  super(mapless);
19113
19196
  this.map = mapless.map;
@@ -19127,6 +19210,14 @@ class InstancedModelManager extends manager_Manager {
19127
19210
  });
19128
19211
  this.renderer.autoClear = false;
19129
19212
  this.renderer.setPixelRatio(window.devicePixelRatio);
19213
+ const ambientLight = new __rspack_external_three.AmbientLight(0xffffff, 0.8);
19214
+ this.scene.add(ambientLight);
19215
+ const directionalLight1 = new __rspack_external_three.DirectionalLight(0xffffff, 1.5);
19216
+ directionalLight1.position.set(0, -70, 100);
19217
+ this.scene.add(directionalLight1);
19218
+ const directionalLight2 = new __rspack_external_three.DirectionalLight(0xffffff, 1.5);
19219
+ directionalLight2.position.set(0, 70, 100);
19220
+ this.scene.add(directionalLight2);
19130
19221
  this.setupCustomLayer();
19131
19222
  this.isInitialized = true;
19132
19223
  console.log('InstancedModelManager: Initialized');
@@ -19143,25 +19234,40 @@ class InstancedModelManager extends manager_Manager {
19143
19234
  },
19144
19235
  render: (_gl, matrix)=>{
19145
19236
  if (!this.camera || !this.renderer || !this.scene) return;
19146
- if (0 === this.instancedMeshes.size) return;
19147
- this.updateAutoRotate();
19237
+ if (0 === this.instancedModels.size) return;
19148
19238
  const projMatrix = new __rspack_external_three.Matrix4().fromArray(matrix);
19149
- this.camera.projectionMatrix = projMatrix;
19150
- this.lastProjectionMatrix = projMatrix.clone();
19151
- this.instancedMeshes.forEach((mesh)=>{
19152
- mesh.visible = true;
19239
+ this.updateAutoRotate();
19240
+ const camera = this.camera;
19241
+ const renderer = this.renderer;
19242
+ const scene = this.scene;
19243
+ const originalVisibilities = new Map();
19244
+ this.instancedModels.forEach((model)=>{
19245
+ originalVisibilities.set(model.group, model.group.visible);
19246
+ model.group.visible = false;
19247
+ });
19248
+ renderer.resetState();
19249
+ this.instancedModels.forEach((model)=>{
19250
+ if (!model.visible) return;
19251
+ const transformMatrix = this.buildMapboxTransform(model);
19252
+ camera.projectionMatrix = projMatrix.clone().multiply(transformMatrix);
19253
+ this.lastProjectionMatrix = camera.projectionMatrix.clone();
19254
+ model.group.visible = true;
19255
+ renderer.render(scene, camera);
19256
+ model.group.visible = false;
19257
+ });
19258
+ this.instancedModels.forEach((model)=>{
19259
+ const visible = originalVisibilities.get(model.group);
19260
+ if (void 0 !== visible) model.group.visible = visible;
19153
19261
  });
19154
- this.renderer.resetState();
19155
- this.renderer.render(this.scene, this.camera);
19156
19262
  if (this.map) this.map.triggerRepaint();
19157
19263
  }
19158
19264
  };
19159
19265
  this.map.addLayer(customLayer);
19160
19266
  }
19161
19267
  setupClickHandler() {
19162
- if (!this.map) return;
19268
+ if (!this.map || this.canvasClickHandler) return;
19163
19269
  const canvas = this.map.getCanvas();
19164
- const handleClick = (e)=>{
19270
+ this.canvasClickHandler = (e)=>{
19165
19271
  if (!this.camera || !this.scene || !this.lastProjectionMatrix) return;
19166
19272
  const rect = canvas.getBoundingClientRect();
19167
19273
  const ndcX = (e.clientX - rect.left) / rect.width * 2 - 1;
@@ -19171,21 +19277,24 @@ class InstancedModelManager extends manager_Manager {
19171
19277
  nearPoint.divideScalar(nearPoint.w);
19172
19278
  const farPoint = new __rspack_external_three.Vector4(ndcX, ndcY, 1, 1).applyMatrix4(inverseProj);
19173
19279
  farPoint.divideScalar(farPoint.w);
19174
- const origin = new __rspack_external_three.Vector3(0, 0, 0);
19280
+ const origin = new __rspack_external_three.Vector3(nearPoint.x, nearPoint.y, nearPoint.z);
19175
19281
  const direction = new __rspack_external_three.Vector3(farPoint.x - nearPoint.x, farPoint.y - nearPoint.y, farPoint.z - nearPoint.z).normalize();
19176
19282
  const raycaster = new __rspack_external_three.Raycaster(origin, direction);
19177
19283
  let closestHit = null;
19178
19284
  let minDistance = 1 / 0;
19179
- for (const [groupId, instancedMesh] of this.instancedMeshes){
19285
+ for (const [groupId, model] of this.instancedModels)for (const modelMesh of model.meshes){
19286
+ const instancedMesh = modelMesh.mesh;
19180
19287
  const intersects = raycaster.intersectObject(instancedMesh, false);
19181
19288
  if (intersects.length > 0 && intersects[0].distance < minDistance) {
19182
19289
  const intersection = intersects[0];
19183
19290
  const instanceId = intersection.instanceId;
19184
19291
  if (void 0 !== instanceId) {
19292
+ const instanceIndex = modelMesh.instanceIndexes[instanceId];
19293
+ if (void 0 === instanceIndex) continue;
19185
19294
  minDistance = intersection.distance;
19186
19295
  closestHit = {
19187
19296
  groupId,
19188
- instanceIndex: instanceId,
19297
+ instanceIndex,
19189
19298
  point: intersection.point,
19190
19299
  distance: intersection.distance
19191
19300
  };
@@ -19203,7 +19312,7 @@ class InstancedModelManager extends manager_Manager {
19203
19312
  });
19204
19313
  }
19205
19314
  };
19206
- canvas.addEventListener('click', handleClick);
19315
+ canvas.addEventListener('click', this.canvasClickHandler);
19207
19316
  }
19208
19317
  onClick(callback) {
19209
19318
  this.clickCallback = callback;
@@ -19213,121 +19322,226 @@ class InstancedModelManager extends manager_Manager {
19213
19322
  if (!enabled) return;
19214
19323
  const angles = this.rotationAngles.get(id);
19215
19324
  const speed = this.rotationSpeeds.get(id) || 0.01;
19216
- const instancedMesh = this.instancedMeshes.get(id);
19217
- if (!angles || !instancedMesh) return;
19325
+ const model = this.instancedModels.get(id);
19326
+ const instances = this.instanceDataMap.get(id);
19327
+ if (!angles || !model || !instances) return;
19218
19328
  const dummy = new __rspack_external_three.Object3D();
19219
- for(let i = 0; i < instancedMesh.count; i++){
19220
- instancedMesh.getMatrixAt(i, dummy.matrix);
19221
- const pos = new __rspack_external_three.Vector3();
19222
- const quat = new __rspack_external_three.Quaternion();
19223
- const scl = new __rspack_external_three.Vector3();
19224
- dummy.matrix.decompose(pos, quat, scl);
19225
- angles[i] += speed;
19226
- quat.setFromAxisAngle(new __rspack_external_three.Vector3(0, 0, 1), angles[i]);
19227
- dummy.matrix.compose(pos, quat, scl);
19228
- instancedMesh.setMatrixAt(i, dummy.matrix);
19329
+ const instanceMatrix = new __rspack_external_three.Matrix4();
19330
+ for(let i = 0; i < instances.length; i++)angles[i] += speed;
19331
+ for (const modelMesh of model.meshes){
19332
+ modelMesh.instanceIndexes.forEach((instanceIndex, localIndex)=>{
19333
+ const instance = instances[instanceIndex];
19334
+ if (!instance) return;
19335
+ const rotation = [
19336
+ instance.rotation[0],
19337
+ instance.rotation[1],
19338
+ instance.rotation[2] + angles[instanceIndex]
19339
+ ];
19340
+ this._setInstanceMatrixWithZoom(model, modelMesh, localIndex, instance, rotation, dummy, instanceMatrix, model.scaleFollowZoom ? 2 ** (model.referenceZoom - (this.map?.getZoom() ?? 16)) : 1);
19341
+ });
19342
+ modelMesh.mesh.instanceMatrix.needsUpdate = true;
19343
+ if (modelMesh.mesh.instanceColor) modelMesh.mesh.instanceColor.needsUpdate = true;
19229
19344
  }
19230
- instancedMesh.instanceMatrix.needsUpdate = true;
19231
19345
  });
19232
19346
  }
19233
- generateInstances(config) {
19347
+ buildMapboxTransform(model) {
19348
+ return new __rspack_external_three.Matrix4().makeTranslation(model.centerMercator.x, model.centerMercator.y, model.centerMercator.z).scale(new __rspack_external_three.Vector3(model.meterInMercator, -model.meterInMercator, model.meterInMercator));
19349
+ }
19350
+ toTileLngLat(lngLat) {
19351
+ return this.mapless?.coordTrans('dataToTile', lngLat) ?? lngLat;
19352
+ }
19353
+ resolveConfig(config) {
19354
+ const firstInstance = config.instances?.[0];
19355
+ const center = config.center || firstInstance?.lngLat;
19356
+ if (!center) throw new Error('InstancedModelConfig requires center or instances[0].lngLat');
19357
+ return {
19358
+ count: config.count ?? config.instances?.length ?? 0,
19359
+ center,
19360
+ spread: config.spread ?? 0
19361
+ };
19362
+ }
19363
+ generateInstances(config, resolved) {
19234
19364
  const instances = [];
19235
- for(let i = 0; i < config.count; i++){
19236
- const lngOffset = (Math.random() - 0.5) * config.spread * 2;
19237
- const latOffset = (Math.random() - 0.5) * config.spread * 2;
19238
- const altitude = 200 + 100 * Math.random();
19239
- const rotation = Math.random() * Math.PI * 2;
19240
- const scaleVariation = 0.8 + 0.4 * Math.random();
19365
+ for(let i = 0; i < resolved.count; i++){
19366
+ const lngOffset = (Math.random() - 0.5) * resolved.spread * 2;
19367
+ const latOffset = (Math.random() - 0.5) * resolved.spread * 2;
19368
+ const externalInstance = config.instances?.[i];
19241
19369
  instances.push({
19242
- lngLat: [
19243
- config.center[0] + lngOffset,
19244
- config.center[1] + latOffset
19370
+ lngLat: externalInstance?.lngLat || [
19371
+ resolved.center[0] + lngOffset,
19372
+ resolved.center[1] + latOffset
19245
19373
  ],
19246
- altitude,
19247
- rotation,
19248
- scale: scaleVariation
19374
+ type: externalInstance?.type ?? DEFAULT_MODEL_TYPE,
19375
+ altitude: externalInstance?.altitude ?? 80,
19376
+ rotation: externalInstance?.rotation || [
19377
+ 0,
19378
+ 0,
19379
+ 0
19380
+ ],
19381
+ scale: externalInstance?.scale ?? 1,
19382
+ color: externalInstance?.color
19249
19383
  });
19250
19384
  }
19251
19385
  return instances;
19252
19386
  }
19253
19387
  prepareGeometryForInstancing(geometry) {
19254
- const clonedGeometry = geometry.clone();
19255
- if (!(clonedGeometry instanceof __rspack_external_three.BufferGeometry)) {
19256
- console.error('几何体不是 BufferGeometry 类型');
19257
- return clonedGeometry;
19258
- }
19259
- if (!clonedGeometry.getAttribute('normal')) clonedGeometry.computeVertexNormals();
19260
- return clonedGeometry;
19388
+ return geometry.clone();
19261
19389
  }
19262
- prepareMaterialForInstancing(originalMaterial) {
19390
+ prepareMaterialForInstancing(originalMaterial, standardMaterialColor) {
19391
+ if (void 0 !== standardMaterialColor) return new __rspack_external_three.MeshStandardMaterial({
19392
+ color: new __rspack_external_three.Color(standardMaterialColor),
19393
+ roughness: 0.6,
19394
+ metalness: 0,
19395
+ vertexColors: true
19396
+ });
19263
19397
  if (Array.isArray(originalMaterial)) return originalMaterial.map((mat)=>this.cloneMaterialForInstancing(mat));
19264
19398
  return this.cloneMaterialForInstancing(originalMaterial);
19265
19399
  }
19266
19400
  cloneMaterialForInstancing(material) {
19267
19401
  const cloned = material.clone();
19268
- if (cloned instanceof __rspack_external_three.MeshStandardMaterial || cloned instanceof __rspack_external_three.MeshPhysicalMaterial || cloned instanceof __rspack_external_three.MeshPhongMaterial) {
19269
- cloned.toneMapped = false;
19270
- cloned.side = __rspack_external_three.DoubleSide;
19271
- }
19402
+ const supportedTypes = [
19403
+ __rspack_external_three.MeshStandardMaterial,
19404
+ __rspack_external_three.MeshPhysicalMaterial,
19405
+ __rspack_external_three.MeshPhongMaterial,
19406
+ __rspack_external_three.MeshBasicMaterial,
19407
+ __rspack_external_three.MeshLambertMaterial,
19408
+ __rspack_external_three.MeshToonMaterial
19409
+ ];
19410
+ const isSupported = supportedTypes.some((Type)=>cloned instanceof Type);
19411
+ if (isSupported) {
19412
+ const mat = cloned;
19413
+ mat.vertexColors = true;
19414
+ if (mat.map) {
19415
+ mat.emissive = new __rspack_external_three.Color(0xffffff);
19416
+ mat.emissiveIntensity = 0.4;
19417
+ mat.emissiveMap = mat.map;
19418
+ }
19419
+ cloned.needsUpdate = true;
19420
+ } else console.warn(`InstancedModel: Unsupported material type "${cloned.type}" for vertex colors`);
19272
19421
  return cloned;
19273
19422
  }
19423
+ resolveModelTypes(config) {
19424
+ if (config.modelTypes) return config.modelTypes;
19425
+ if (config.url) return {
19426
+ [DEFAULT_MODEL_TYPE]: {
19427
+ url: config.url,
19428
+ scale: config.scale,
19429
+ baseRotation: config.baseRotation,
19430
+ standardMaterialColor: config.standardMaterialColor
19431
+ }
19432
+ };
19433
+ throw new Error('InstancedModelConfig requires url or modelTypes');
19434
+ }
19435
+ groupInstanceIndexesByType(instances) {
19436
+ const grouped = new Map();
19437
+ instances.forEach((instance, index)=>{
19438
+ const indexes = grouped.get(instance.type) || [];
19439
+ indexes.push(index);
19440
+ grouped.set(instance.type, indexes);
19441
+ });
19442
+ return grouped;
19443
+ }
19274
19444
  async load(id, config) {
19275
19445
  this.initThree();
19276
- if (!this.scene || !this.map) throw new Error('Three.js scene not initialized');
19446
+ const scene = this.scene;
19447
+ if (!scene || !this.map) throw new Error('Three.js scene not initialized');
19277
19448
  this.remove(id);
19278
19449
  const loader = new GLTFLoader();
19450
+ const dracoLoader = new DRACOLoader();
19451
+ dracoLoader.setDecoderPath('/draco/gltf/');
19452
+ loader.setDRACOLoader(dracoLoader);
19279
19453
  try {
19280
- console.log('InstancedModel: Loading model', config.url);
19281
- const gltf = await new Promise((resolve, reject)=>{
19282
- loader.load(config.url, resolve, void 0, reject);
19283
- });
19284
- console.log('InstancedModel: Model loaded successfully');
19285
- let mesh;
19286
- gltf.scene.traverse((object)=>{
19287
- if (object instanceof __rspack_external_three.Mesh && !mesh) mesh = object;
19288
- });
19289
- if (!mesh) throw new Error('No mesh found in model');
19290
- const geometry = this.prepareGeometryForInstancing(mesh.geometry);
19291
- const material = this.prepareMaterialForInstancing(mesh.material);
19292
- const instances = this.generateInstances(config);
19293
- const angles = new Float32Array(config.count);
19294
- const centerMercator = mapbox_gl.MercatorCoordinate.fromLngLat(config.center, 0);
19454
+ const resolved = this.resolveConfig(config);
19455
+ const instances = this.generateInstances(config, resolved);
19456
+ const modelTypes = this.resolveModelTypes(config);
19457
+ const groupedInstanceIndexes = this.groupInstanceIndexesByType(instances);
19458
+ const angles = new Float32Array(resolved.count);
19459
+ const centerMercator = mapbox_gl.MercatorCoordinate.fromLngLat(this.toTileLngLat(resolved.center), 0);
19295
19460
  const meterInMercator = centerMercator.meterInMercatorCoordinateUnits();
19296
- const instancedMesh = new __rspack_external_three.InstancedMesh(geometry, material, config.count);
19297
- instancedMesh.instanceMatrix.setUsage(__rspack_external_three.DynamicDrawUsage);
19298
- instancedMesh.frustumCulled = false;
19299
- instancedMesh.position.set(centerMercator.x, centerMercator.y, centerMercator.z);
19300
- instancedMesh.updateMatrix();
19461
+ const group = new __rspack_external_three.Group();
19462
+ const instancedModelMeshes = [];
19463
+ const typeScales = new Map();
19464
+ const baseRotationMatrices = new Map();
19465
+ const modelEntry = {
19466
+ group,
19467
+ meshes: instancedModelMeshes,
19468
+ centerMercator,
19469
+ meterInMercator,
19470
+ typeScales,
19471
+ baseRotationMatrices,
19472
+ visible: true,
19473
+ scaleFollowZoom: false,
19474
+ referenceZoom: 16
19475
+ };
19301
19476
  const dummy = new __rspack_external_three.Object3D();
19302
- for(let i = 0; i < config.count; i++){
19303
- const instance = instances[i];
19304
- const mercator = mapbox_gl.MercatorCoordinate.fromLngLat(instance.lngLat, instance.altitude);
19305
- const dx = mercator.x - centerMercator.x;
19306
- const dy = mercator.y - centerMercator.y;
19307
- const dz = mercator.z - centerMercator.z;
19308
- dummy.position.set(dx, dy, dz);
19309
- const s = meterInMercator * config.scale * instance.scale;
19310
- dummy.scale.set(s, -s, s);
19311
- dummy.updateMatrix();
19312
- instancedMesh.setMatrixAt(i, dummy.matrix);
19313
- angles[i] = instance.rotation;
19314
- }
19315
- instancedMesh.instanceMatrix.needsUpdate = true;
19316
- if (!instancedMesh.geometry.boundingSphere) instancedMesh.geometry.computeBoundingSphere();
19317
- instancedMesh.computeBoundingSphere();
19318
- this.scene.add(instancedMesh);
19319
- console.log(`InstancedModel "${id}" loaded: ${config.count} instances`, {
19477
+ const instanceMatrix = new __rspack_external_three.Matrix4();
19478
+ for (const [type, instanceIndexes] of groupedInstanceIndexes){
19479
+ const typeConfig = modelTypes[type];
19480
+ if (!typeConfig) throw new Error(`Missing modelTypes config for instance type "${type}"`);
19481
+ console.log('InstancedModel: Loading model', type, typeConfig.url);
19482
+ const gltf = await new Promise((resolve, reject)=>{
19483
+ loader.load(typeConfig.url, resolve, void 0, reject);
19484
+ });
19485
+ if (this.scene !== scene || !this.isInitialized) return;
19486
+ console.log('InstancedModel: Model loaded successfully', type);
19487
+ const sourceMeshes = [];
19488
+ gltf.scene.updateMatrixWorld(true);
19489
+ gltf.scene.traverse((object)=>{
19490
+ if (object instanceof __rspack_external_three.Mesh) {
19491
+ const mat = object.material;
19492
+ const matInfo = Array.isArray(mat) ? mat.map((m)=>m.type) : mat.type;
19493
+ console.log(` Mesh found: ${object.name || 'unnamed'}, material:`, matInfo);
19494
+ sourceMeshes.push(object);
19495
+ }
19496
+ });
19497
+ if (0 === sourceMeshes.length) throw new Error(`No mesh found in model type "${type}"`);
19498
+ typeScales.set(type, typeConfig.scale ?? config.scale);
19499
+ baseRotationMatrices.set(type, new __rspack_external_three.Matrix4().makeRotationFromEuler(new __rspack_external_three.Euler(...typeConfig.baseRotation || config.baseRotation || [
19500
+ 0,
19501
+ 0,
19502
+ 0
19503
+ ], 'XYZ')));
19504
+ for (const sourceMesh of sourceMeshes){
19505
+ sourceMesh.updateWorldMatrix(true, false);
19506
+ const geometry = this.prepareGeometryForInstancing(sourceMesh.geometry);
19507
+ const material = this.prepareMaterialForInstancing(sourceMesh.material, typeConfig.standardMaterialColor ?? config.standardMaterialColor);
19508
+ const instancedMesh = new __rspack_external_three.InstancedMesh(geometry, material, instanceIndexes.length);
19509
+ instancedMesh.instanceMatrix.setUsage(__rspack_external_three.DynamicDrawUsage);
19510
+ instancedMesh.frustumCulled = false;
19511
+ const modelMesh = {
19512
+ mesh: instancedMesh,
19513
+ baseMatrix: sourceMesh.matrixWorld.clone(),
19514
+ instanceIndexes
19515
+ };
19516
+ instanceIndexes.forEach((instanceIndex, localIndex)=>{
19517
+ const instance = instances[instanceIndex];
19518
+ this._setInstanceMatrixWithZoom(modelEntry, modelMesh, localIndex, instance, instance.rotation, dummy, instanceMatrix);
19519
+ angles[instanceIndex] = 0;
19520
+ });
19521
+ instancedMesh.instanceMatrix.needsUpdate = true;
19522
+ if (instancedMesh.instanceColor) instancedMesh.instanceColor.needsUpdate = true;
19523
+ if (!instancedMesh.geometry.boundingSphere) instancedMesh.geometry.computeBoundingSphere();
19524
+ instancedMesh.computeBoundingSphere();
19525
+ group.add(instancedMesh);
19526
+ instancedModelMeshes.push(modelMesh);
19527
+ }
19528
+ }
19529
+ if (this.scene !== scene || !this.isInitialized) return;
19530
+ scene.add(group);
19531
+ console.log(`InstancedModel "${id}" loaded: ${resolved.count} instances`, {
19320
19532
  center: {
19321
19533
  x: centerMercator.x,
19322
19534
  y: centerMercator.y,
19323
19535
  z: centerMercator.z
19324
19536
  },
19537
+ meshCount: instancedModelMeshes.length,
19538
+ typeCount: groupedInstanceIndexes.size,
19325
19539
  meterInMercator,
19326
19540
  firstInstanceOffset: {
19327
- x: instances[0] ? mapbox_gl.MercatorCoordinate.fromLngLat(instances[0].lngLat, instances[0].altitude).x - centerMercator.x : 0
19541
+ x: instances[0] ? mapbox_gl.MercatorCoordinate.fromLngLat(this.toTileLngLat(instances[0].lngLat), instances[0].altitude).x - centerMercator.x : 0
19328
19542
  }
19329
19543
  });
19330
- this.instancedMeshes.set(id, instancedMesh);
19544
+ this.instancedModels.set(id, modelEntry);
19331
19545
  this.instanceDataMap.set(id, instances);
19332
19546
  this.rotationAngles.set(id, angles);
19333
19547
  this.autoRotateEnabled.set(id, config.autoRotate || false);
@@ -19336,6 +19550,8 @@ class InstancedModelManager extends manager_Manager {
19336
19550
  } catch (error) {
19337
19551
  console.error(`Failed to load instanced model "${id}":`, error);
19338
19552
  throw error;
19553
+ } finally{
19554
+ dracoLoader.dispose();
19339
19555
  }
19340
19556
  }
19341
19557
  enableAutoRotate(id, speed = 0.01) {
@@ -19345,74 +19561,230 @@ class InstancedModelManager extends manager_Manager {
19345
19561
  disableAutoRotate(id) {
19346
19562
  this.autoRotateEnabled.set(id, false);
19347
19563
  }
19348
- updateInstance(id, index, lngLat, altitude) {
19349
- const instancedMesh = this.instancedMeshes.get(id);
19350
- if (!instancedMesh) return;
19351
- const mercator = mapbox_gl.MercatorCoordinate.fromLngLat(lngLat, altitude);
19564
+ setScaleFollowZoom(id, enabled, referenceZoom = 16) {
19565
+ const model = this.instancedModels.get(id);
19566
+ if (!model) return;
19567
+ model.scaleFollowZoom = enabled;
19568
+ model.referenceZoom = referenceZoom;
19569
+ this._updateZoomListener();
19570
+ if (enabled) this._updateModelScaleWithZoom(id);
19571
+ else this._rebuildAllInstanceMatrices(id);
19572
+ }
19573
+ _updateZoomListener() {
19574
+ const hasScaleFollowZoom = Array.from(this.instancedModels.values()).some((m)=>m.scaleFollowZoom);
19575
+ if (hasScaleFollowZoom && !this.zoomCleanup) {
19576
+ const handleZoom = ()=>{
19577
+ this.instancedModels.forEach((model, id)=>{
19578
+ if (model.scaleFollowZoom) this._updateModelScaleWithZoom(id);
19579
+ });
19580
+ };
19581
+ this.map?.on('zoom', handleZoom);
19582
+ this.zoomCleanup = ()=>{
19583
+ this.map?.off('zoom', handleZoom);
19584
+ };
19585
+ } else if (!hasScaleFollowZoom && this.zoomCleanup) {
19586
+ this.zoomCleanup();
19587
+ this.zoomCleanup = null;
19588
+ }
19589
+ }
19590
+ _updateModelScaleWithZoom(id) {
19591
+ const model = this.instancedModels.get(id);
19592
+ if (!model || !this.map) return;
19593
+ const currentZoom = this.map.getZoom();
19594
+ const zoomScaleFactor = 2 ** (model.referenceZoom - currentZoom);
19595
+ this._rebuildAllInstanceMatrices(id, zoomScaleFactor);
19596
+ }
19597
+ _rebuildAllInstanceMatrices(id, zoomScaleFactor = 1) {
19598
+ const model = this.instancedModels.get(id);
19599
+ const instances = this.instanceDataMap.get(id);
19600
+ if (!model || !instances) return;
19352
19601
  const dummy = new __rspack_external_three.Object3D();
19353
- const pos = new __rspack_external_three.Vector3();
19354
- const quat = new __rspack_external_three.Quaternion();
19355
- const scl = new __rspack_external_three.Vector3();
19356
- instancedMesh.getMatrixAt(index, dummy.matrix);
19357
- dummy.matrix.decompose(pos, quat, scl);
19358
- dummy.position.set(mercator.x, mercator.y, mercator.z);
19602
+ const instanceMatrix = new __rspack_external_three.Matrix4();
19603
+ for (const modelMesh of model.meshes){
19604
+ modelMesh.instanceIndexes.forEach((instanceIndex, localIndex)=>{
19605
+ const instance = instances[instanceIndex];
19606
+ if (!instance) return;
19607
+ const rotationAngle = this.rotationAngles.get(id)?.[instanceIndex] ?? 0;
19608
+ const rotation = [
19609
+ instance.rotation[0],
19610
+ instance.rotation[1],
19611
+ instance.rotation[2] + rotationAngle
19612
+ ];
19613
+ this._setInstanceMatrixWithZoom(model, modelMesh, localIndex, instance, rotation, dummy, instanceMatrix, zoomScaleFactor);
19614
+ });
19615
+ modelMesh.mesh.instanceMatrix.needsUpdate = true;
19616
+ }
19617
+ }
19618
+ _setInstanceMatrixWithZoom(model, modelMesh, index, instance, rotation, dummy, instanceMatrix, zoomScaleFactor = 1) {
19619
+ const mercator = mapbox_gl.MercatorCoordinate.fromLngLat(this.toTileLngLat(instance.lngLat), instance.altitude);
19620
+ const dx = (mercator.x - model.centerMercator.x) / model.meterInMercator;
19621
+ const dy = -(mercator.y - model.centerMercator.y) / model.meterInMercator;
19622
+ const dz = (mercator.z - model.centerMercator.z) / model.meterInMercator;
19623
+ const typeScale = model.typeScales.get(instance.type) ?? 1;
19624
+ const baseRotationMatrix = model.baseRotationMatrices.get(instance.type) ?? new __rspack_external_three.Matrix4();
19625
+ dummy.position.set(dx, dy, dz);
19626
+ dummy.rotation.set(...rotation);
19627
+ dummy.scale.setScalar(typeScale * instance.scale * zoomScaleFactor);
19359
19628
  dummy.updateMatrix();
19360
- instancedMesh.setMatrixAt(index, dummy.matrix);
19361
- instancedMesh.instanceMatrix.needsUpdate = true;
19629
+ instanceMatrix.copy(dummy.matrix).multiply(baseRotationMatrix).multiply(modelMesh.baseMatrix);
19630
+ modelMesh.mesh.setMatrixAt(index, instanceMatrix);
19631
+ if (void 0 !== instance.color) modelMesh.mesh.setColorAt(index, new __rspack_external_three.Color(instance.color));
19632
+ }
19633
+ updateInstance(id, index, lngLat, altitude) {
19634
+ const model = this.instancedModels.get(id);
19635
+ if (!model) return;
19636
+ const instances = this.instanceDataMap.get(id);
19637
+ const instance = instances?.[index];
19638
+ if (!instance) return;
19639
+ instance.lngLat = lngLat;
19640
+ instance.altitude = altitude;
19641
+ const dummy = new __rspack_external_three.Object3D();
19642
+ const instanceMatrix = new __rspack_external_three.Matrix4();
19643
+ const rotationAngle = this.rotationAngles.get(id)?.[index] ?? 0;
19644
+ const rotation = [
19645
+ instance.rotation[0],
19646
+ instance.rotation[1],
19647
+ instance.rotation[2] + rotationAngle
19648
+ ];
19649
+ for (const modelMesh of model.meshes){
19650
+ const localIndex = modelMesh.instanceIndexes.indexOf(index);
19651
+ if (-1 !== localIndex) {
19652
+ this._setInstanceMatrixWithZoom(model, modelMesh, localIndex, instance, rotation, dummy, instanceMatrix, model.scaleFollowZoom ? 2 ** (model.referenceZoom - (this.map?.getZoom() ?? 16)) : 1);
19653
+ modelMesh.mesh.instanceMatrix.needsUpdate = true;
19654
+ }
19655
+ }
19656
+ }
19657
+ updateInstanceScale(id, index, scale) {
19658
+ const model = this.instancedModels.get(id);
19659
+ if (!model) return;
19660
+ const instances = this.instanceDataMap.get(id);
19661
+ const instance = instances?.[index];
19662
+ if (!instance) return;
19663
+ instance.scale = scale;
19664
+ const dummy = new __rspack_external_three.Object3D();
19665
+ const instanceMatrix = new __rspack_external_three.Matrix4();
19666
+ const rotationAngle = this.rotationAngles.get(id)?.[index] ?? 0;
19667
+ const rotation = [
19668
+ instance.rotation[0],
19669
+ instance.rotation[1],
19670
+ instance.rotation[2] + rotationAngle
19671
+ ];
19672
+ for (const modelMesh of model.meshes){
19673
+ const localIndex = modelMesh.instanceIndexes.indexOf(index);
19674
+ if (-1 !== localIndex) {
19675
+ this._setInstanceMatrixWithZoom(model, modelMesh, localIndex, instance, rotation, dummy, instanceMatrix, model.scaleFollowZoom ? 2 ** (model.referenceZoom - (this.map?.getZoom() ?? 16)) : 1);
19676
+ modelMesh.mesh.instanceMatrix.needsUpdate = true;
19677
+ }
19678
+ }
19679
+ }
19680
+ updateInstanceColor(id, index, color) {
19681
+ const model = this.instancedModels.get(id);
19682
+ if (!model) return;
19362
19683
  const instances = this.instanceDataMap.get(id);
19363
- if (instances?.[index]) {
19364
- instances[index].lngLat = lngLat;
19365
- instances[index].altitude = altitude;
19684
+ const instance = instances?.[index];
19685
+ if (!instance) return;
19686
+ instance.color = color;
19687
+ const colorObj = new __rspack_external_three.Color(color);
19688
+ for (const modelMesh of model.meshes){
19689
+ const localIndex = modelMesh.instanceIndexes.indexOf(index);
19690
+ if (-1 !== localIndex) modelMesh.mesh.setColorAt(localIndex, colorObj);
19366
19691
  }
19692
+ for (const modelMesh of model.meshes)if (modelMesh.mesh.instanceColor) modelMesh.mesh.instanceColor.needsUpdate = true;
19693
+ }
19694
+ handleCoordSystemChange(_system) {
19695
+ const dummy = new __rspack_external_three.Object3D();
19696
+ const instanceMatrix = new __rspack_external_three.Matrix4();
19697
+ this.instancedModels.forEach((model, id)=>{
19698
+ const instances = this.instanceDataMap.get(id);
19699
+ const config = this.originalConfigs.get(id);
19700
+ const center = config?.center ?? instances?.[0]?.lngLat;
19701
+ if (!instances || !center) return;
19702
+ model.centerMercator = mapbox_gl.MercatorCoordinate.fromLngLat(this.toTileLngLat(center), 0);
19703
+ model.meterInMercator = model.centerMercator.meterInMercatorCoordinateUnits();
19704
+ for (const modelMesh of model.meshes){
19705
+ modelMesh.instanceIndexes.forEach((instanceIndex, localIndex)=>{
19706
+ const instance = instances[instanceIndex];
19707
+ if (!instance) return;
19708
+ const rotationAngle = this.rotationAngles.get(id)?.[instanceIndex] ?? 0;
19709
+ const rotation = [
19710
+ instance.rotation[0],
19711
+ instance.rotation[1],
19712
+ instance.rotation[2] + rotationAngle
19713
+ ];
19714
+ this._setInstanceMatrixWithZoom(model, modelMesh, localIndex, instance, rotation, dummy, instanceMatrix, model.scaleFollowZoom ? 2 ** (model.referenceZoom - (this.map?.getZoom() ?? 16)) : 1);
19715
+ });
19716
+ modelMesh.mesh.instanceMatrix.needsUpdate = true;
19717
+ }
19718
+ });
19367
19719
  }
19368
19720
  setInstanceVisible(id, visible) {
19369
- const instancedMesh = this.instancedMeshes.get(id);
19370
- if (instancedMesh) instancedMesh.visible = visible;
19721
+ const model = this.instancedModels.get(id);
19722
+ if (model) {
19723
+ model.visible = visible;
19724
+ model.group.visible = visible;
19725
+ }
19371
19726
  }
19372
19727
  setVisible(visible) {
19373
19728
  this.IsVisible = visible;
19374
- this.instancedMeshes.forEach((mesh)=>{
19375
- mesh.visible = visible;
19729
+ this.instancedModels.forEach((model)=>{
19730
+ model.visible = visible;
19731
+ model.group.visible = visible;
19376
19732
  });
19377
19733
  }
19378
19734
  getInstanceCount(id) {
19379
- return this.instancedMeshes.get(id)?.count || 0;
19735
+ return this.instanceDataMap.get(id)?.length || 0;
19736
+ }
19737
+ getMeshCount(id) {
19738
+ return this.instancedModels.get(id)?.meshes.length || 0;
19380
19739
  }
19381
19740
  getIds() {
19382
- return Array.from(this.instancedMeshes.keys());
19741
+ return Array.from(this.instancedModels.keys());
19383
19742
  }
19384
19743
  remove(id) {
19385
- const instancedMesh = this.instancedMeshes.get(id);
19386
- if (instancedMesh && this.scene) {
19387
- this.scene.remove(instancedMesh);
19388
- instancedMesh.geometry.dispose();
19389
- if (Array.isArray(instancedMesh.material)) for (const m of instancedMesh.material)m.dispose();
19390
- else instancedMesh.material.dispose();
19391
- }
19392
- this.instancedMeshes.delete(id);
19744
+ const model = this.instancedModels.get(id);
19745
+ if (model && this.scene) {
19746
+ this.scene.remove(model.group);
19747
+ for (const modelMesh of model.meshes){
19748
+ modelMesh.mesh.geometry.dispose();
19749
+ if (Array.isArray(modelMesh.mesh.material)) for (const m of modelMesh.mesh.material)m.dispose();
19750
+ else modelMesh.mesh.material.dispose();
19751
+ }
19752
+ }
19753
+ this.instancedModels.delete(id);
19393
19754
  this.instanceDataMap.delete(id);
19394
19755
  this.rotationAngles.delete(id);
19395
19756
  this.autoRotateEnabled.delete(id);
19396
19757
  this.rotationSpeeds.delete(id);
19397
19758
  this.originalConfigs.delete(id);
19759
+ this._updateZoomListener();
19398
19760
  }
19399
19761
  clear() {
19400
19762
  const ids = this.getIds();
19401
19763
  for (const id of ids)this.remove(id);
19402
19764
  }
19403
19765
  setColor(id, color) {
19404
- const instancedMesh = this.instancedMeshes.get(id);
19405
- if (!instancedMesh) return;
19766
+ const model = this.instancedModels.get(id);
19767
+ if (!model) return;
19406
19768
  const meshColor = 'string' == typeof color ? new __rspack_external_three.Color(color) : color;
19407
- if (Array.isArray(instancedMesh.material)) {
19408
- for (const m of instancedMesh.material)if ('color' in m) m.color.set(meshColor);
19409
- } else if ('color' in instancedMesh.material) instancedMesh.material.color.set(meshColor);
19769
+ for (const modelMesh of model.meshes)if (Array.isArray(modelMesh.mesh.material)) {
19770
+ for (const m of modelMesh.mesh.material)if ('color' in m) m.color.set(meshColor);
19771
+ } else if ('color' in modelMesh.mesh.material) modelMesh.mesh.material.color.set(meshColor);
19410
19772
  }
19411
19773
  destroy() {
19412
19774
  this.clear();
19413
- if (this.map && this.customLayerId) try {
19414
- this.map.removeLayer(this.customLayerId);
19415
- } catch {}
19775
+ if (this.zoomCleanup) {
19776
+ this.zoomCleanup();
19777
+ this.zoomCleanup = null;
19778
+ }
19779
+ if (this.map) {
19780
+ if (this.canvasClickHandler) {
19781
+ this.map.getCanvas().removeEventListener('click', this.canvasClickHandler);
19782
+ this.canvasClickHandler = null;
19783
+ }
19784
+ if (this.customLayerId && this.map.getLayer(this.customLayerId)) try {
19785
+ this.map.removeLayer(this.customLayerId);
19786
+ } catch {}
19787
+ }
19416
19788
  if (this.renderer) {
19417
19789
  this.renderer.dispose();
19418
19790
  this.renderer = null;
@@ -19421,6 +19793,7 @@ class InstancedModelManager extends manager_Manager {
19421
19793
  this.camera = null;
19422
19794
  this.isInitialized = false;
19423
19795
  this.originalConfigs.clear();
19796
+ super.destroy();
19424
19797
  }
19425
19798
  }
19426
19799
  const instancedModel = InstancedModelManager;
@@ -19658,6 +20031,14 @@ class Line2Manager extends manager_Manager {
19658
20031
  });
19659
20032
  this.lines.clear();
19660
20033
  }
20034
+ setVisible(visible) {
20035
+ super.setVisible(visible);
20036
+ const mapThree = this.getMapThree();
20037
+ if (!mapThree) return;
20038
+ this.lines.forEach((lineData)=>{
20039
+ mapThree.setRenderableObjectVisible(lineData.id, visible);
20040
+ });
20041
+ }
19661
20042
  getLineCount() {
19662
20043
  return this.lines.size;
19663
20044
  }
@@ -19815,6 +20196,7 @@ class Line2Manager extends manager_Manager {
19815
20196
  this.renderCallback = null;
19816
20197
  }
19817
20198
  this.clearLines();
20199
+ super.destroy();
19818
20200
  }
19819
20201
  }
19820
20202
  const line2Manager = Line2Manager;
@@ -19923,6 +20305,7 @@ class ModelManager extends manager_Manager {
19923
20305
  actions = new Map();
19924
20306
  clock = new Timer();
19925
20307
  modelConfigs = new Map();
20308
+ animationCallback = ()=>this.updateAnimations();
19926
20309
  constructor(mapless){
19927
20310
  super(mapless);
19928
20311
  this.map = mapless.map;
@@ -19936,9 +20319,7 @@ class ModelManager extends manager_Manager {
19936
20319
  if (!this.mapless) return;
19937
20320
  this.mapThree = this.mapless.getMapThree();
19938
20321
  if (!this.mapThree) return void console.warn('ModelManager: MapThree not initialized');
19939
- this.mapThree.addAnimationCallback(()=>{
19940
- this.updateAnimations();
19941
- });
20322
+ this.mapThree.addAnimationCallback(this.animationCallback);
19942
20323
  }
19943
20324
  updateAnimations() {
19944
20325
  const delta = this.clock.getDelta();
@@ -20215,12 +20596,11 @@ class ModelManager extends manager_Manager {
20215
20596
  });
20216
20597
  this.mixers.clear();
20217
20598
  this.actions.clear();
20218
- if (this.mapThree) this.mapThree.removeAnimationCallback(()=>{
20219
- this.updateAnimations();
20220
- });
20599
+ if (this.mapThree) this.mapThree.removeAnimationCallback(this.animationCallback);
20221
20600
  }
20222
20601
  destroy() {
20223
20602
  this.dispose();
20603
+ super.destroy();
20224
20604
  }
20225
20605
  }
20226
20606
  const mana_three_model = ModelManager;
@@ -20262,6 +20642,7 @@ class ThreeManager extends manager_Manager {
20262
20642
  isSelected = false;
20263
20643
  clickCleanup = null;
20264
20644
  zoomCleanup = null;
20645
+ animationCallback = ()=>this.updateAnimation();
20265
20646
  originalModelConfig = null;
20266
20647
  constructor(mapless){
20267
20648
  super(mapless);
@@ -20273,9 +20654,7 @@ class ThreeManager extends manager_Manager {
20273
20654
  if (!this.mapless) return;
20274
20655
  this.mapThree = this.mapless.getMapThree();
20275
20656
  if (!this.mapThree) return void console.warn('ThreeManager: MapThree not initialized');
20276
- this.mapThree.addAnimationCallback(()=>{
20277
- this.updateAnimation();
20278
- });
20657
+ this.mapThree.addAnimationCallback(this.animationCallback);
20279
20658
  }
20280
20659
  updateAnimation() {
20281
20660
  const delta = this.clock.getDelta();
@@ -20575,6 +20954,11 @@ class ThreeManager extends manager_Manager {
20575
20954
  this.clickCleanup = cleanup;
20576
20955
  return cleanup;
20577
20956
  }
20957
+ setVisible(visible) {
20958
+ super.setVisible(visible);
20959
+ const mapThree = this.getMapThree();
20960
+ if (mapThree && this.modelId) mapThree.setRenderableObjectVisible(this.modelId, visible);
20961
+ }
20578
20962
  unregisterClick() {
20579
20963
  if (this.clickCleanup) {
20580
20964
  this.clickCleanup();
@@ -20598,9 +20982,7 @@ class ThreeManager extends manager_Manager {
20598
20982
  this.mixer.stopAllAction();
20599
20983
  this.mixer = null;
20600
20984
  }
20601
- if (this.mapThree) this.mapThree.removeAnimationCallback(()=>{
20602
- this.updateAnimation();
20603
- });
20985
+ if (this.mapThree) this.mapThree.removeAnimationCallback(this.animationCallback);
20604
20986
  }
20605
20987
  handleCoordSystemChange(_system) {
20606
20988
  if (!this.originalModelConfig) return;
@@ -20625,6 +21007,7 @@ class ThreeManager extends manager_Manager {
20625
21007
  };
20626
21008
  destroy() {
20627
21009
  this.dispose();
21010
+ super.destroy();
20628
21011
  }
20629
21012
  }
20630
21013
  const three = ThreeManager;