11import { bindAll } from '../util/util' ;
22import { Event , Evented } from '../util/evented' ;
33import LngLat from '../geo/lng_lat' ;
4- import IndoorControl from '../ui/control/indoor_control' ;
54
65import type { IndoorBuilding , IndoorData , IndoorEvents , IndoorState , IndoorTileOptions } from './indoor_data' ;
76import type Style from './style' ;
87import type { LngLatBounds } from '../geo/lng_lat' ;
9-
108export default class IndoorManager extends Evented < IndoorEvents > {
119 _style : Style ;
1210 _selectedFloorId : string | null ;
1311 _closestBuildingId : string | null ;
1412 _buildings : Record < string , IndoorBuilding > | null ;
15- _indoorControl : IndoorControl | null ;
16-
1713 _activeFloors : Set < string > | null ;
1814 _indoorState : IndoorState | null ;
1915 _activeFloorsVisible : boolean ;
20-
2116 constructor ( style : Style ) {
2217 super ( ) ;
2318 this . _style = style ;
2419 this . _buildings = { } ;
25- this . _indoorControl = null ;
20+
2621 this . _activeFloors = new Set ( ) ;
2722 this . _activeFloorsVisible = true ;
2823 this . _indoorState = { selectedFloorId : null , lastActiveFloors : null , activeFloorsVisible : true } ;
2924 bindAll ( [ '_updateUI' ] , this ) ;
30-
3125 const setupObservers = ( ) => {
3226 if ( this . _style . isIndoorEnabled ( ) ) {
3327 this . _style . map . on ( 'load' , this . _updateUI ) ;
@@ -36,33 +30,26 @@ export default class IndoorManager extends Evented<IndoorEvents> {
3630 this . _updateUI ( ) ;
3731 }
3832 } ;
39-
4033 this . _style . on ( 'style.load' , setupObservers ) ;
4134 }
42-
4335 destroy ( ) {
4436 this . _buildings = { } ;
4537 this . _activeFloors = new Set ( ) ;
4638 this . _indoorState = null ;
47- this . _removeIndoorControl ( ) ;
4839 }
49-
5040 selectFloor ( floorId : string | null ) {
5141 if ( floorId === this . _selectedFloorId && this . _activeFloorsVisible ) {
5242 return ;
5343 }
54-
5544 this . _selectedFloorId = floorId ;
5645 this . _activeFloorsVisible = true ;
5746 this . _updateActiveFloors ( ) ;
5847 }
59-
6048 setActiveFloorsVisibility ( activeFloorsVisible : boolean ) {
6149 this . _activeFloorsVisible = activeFloorsVisible ;
6250 this . _updateActiveFloors ( ) ;
6351 this . _updateIndoorSelector ( ) ;
6452 }
65-
6653 /// Fan in data sent from different tiles and sources and merge it into the one state
6754 /// Both buildings and active floors updates are additive-only
6855 setIndoorData ( indoorData : IndoorData ) {
@@ -78,42 +65,22 @@ export default class IndoorManager extends Evented<IndoorEvents> {
7865 this . _buildings [ id ] = building ;
7966 }
8067 }
81-
8268 for ( const floorId of indoorData . activeFloors ) {
8369 this . _activeFloors . add ( floorId ) ;
8470 }
85-
8671 // Next step: Add debouncing to prevent excessive selector updates, though not visible
8772 this . _updateIndoorSelector ( ) ;
8873 }
89-
9074 getIndoorTileOptions ( sourceId : string , scope : string ) : IndoorTileOptions | null {
9175 const sourceLayers = this . _style . getIndoorSourceLayers ( sourceId , scope ) ;
9276 if ( ! sourceLayers || ! this . _indoorState ) {
9377 return null ;
9478 }
95-
9679 return {
9780 sourceLayers,
9881 indoorState : this . _indoorState
9982 } ;
10083 }
101-
102- _addIndoorControl ( ) {
103- if ( ! this . _indoorControl ) {
104- this . _indoorControl = new IndoorControl ( ) ;
105- this . _style . map . addControl ( this . _indoorControl , 'right' ) ;
106- }
107- }
108-
109- _removeIndoorControl ( ) {
110- if ( ! this . _indoorControl ) {
111- return ;
112- }
113- this . _indoorControl . onRemove ( ) ;
114- this . _indoorControl = null ;
115- }
116-
11784 _updateUI ( ) {
11885 const transform = this . _style . map . transform ;
11986 const closestBuildingId = findClosestBuildingId ( this . _buildings , transform . center , transform . getBounds ( ) , transform . zoom ) ;
@@ -122,31 +89,24 @@ export default class IndoorManager extends Evented<IndoorEvents> {
12289 this . _updateIndoorSelector ( ) ;
12390 }
12491 }
125-
126- _updateIndoorSelector ( ) {
92+ getControlState ( ) {
12793 const buildings = this . _buildings ;
12894 const closestBuildingId = this . _closestBuildingId ;
12995 const closestBuilding = ( closestBuildingId && buildings ) ? buildings [ closestBuildingId ] : undefined ;
130-
13196 if ( ! closestBuilding ) {
132- this . _removeIndoorControl ( ) ;
133- this . fire ( new Event ( 'selector-update' , {
97+ return {
13498 selectedFloorId : null ,
13599 activeFloorsVisible : this . _activeFloorsVisible ,
136100 floors : [ ]
137- } ) ) ;
138- return ;
101+ } ;
139102 }
140-
141- this . _addIndoorControl ( ) ;
142103 let buildingActiveFloorId : string | null = null ;
143104 for ( const floorId of closestBuilding . floorIds ) {
144105 if ( this . _activeFloors && this . _activeFloors . has ( floorId ) ) {
145106 buildingActiveFloorId = floorId ;
146107 break ;
147108 }
148109 }
149-
150110 // Dedupe floors by zIndex before sending to the control:
151111 // we should only show one floor per zIndex for a given building.
152112 const floors = Array . from ( closestBuilding . floorIds )
@@ -157,14 +117,15 @@ export default class IndoorManager extends Evented<IndoorEvents> {
157117 } ) )
158118 . sort ( ( a , b ) => b . zIndex - a . zIndex )
159119 . filter ( ( floor , idx , arr ) => idx === 0 || floor . zIndex !== arr [ idx - 1 ] . zIndex ) ;
160-
161- this . fire ( new Event ( 'selector-update' , {
120+ return {
162121 selectedFloorId : buildingActiveFloorId ,
163122 activeFloorsVisible : this . _activeFloorsVisible ,
164123 floors
165- } ) ) ;
124+ } ;
125+ }
126+ _updateIndoorSelector ( ) {
127+ this . fire ( new Event ( 'selector-update' , this . getControlState ( ) ) ) ;
166128 }
167-
168129 // Update previous state and pass it to tiles
169130 // Resolve active floors to construct new set based on data from tiles
170131 // Tiles will resolve individual subsets of activeFloors and send it in setIndoorData
@@ -175,16 +136,13 @@ export default class IndoorManager extends Evented<IndoorEvents> {
175136 this . _style . updateIndoorDependentLayers ( ) ;
176137 }
177138}
178-
179139function findClosestBuildingId ( buildings : Record < string , IndoorBuilding > , mapCenter : LngLat , mapBounds : LngLatBounds , zoom : number ) : string | null {
180140 const indoorMinimumZoom : number = 16.0 ;
181141 let closestBuildingId : string | null = null ;
182142 let minDistance = Number . MAX_SAFE_INTEGER ;
183-
184143 if ( zoom < indoorMinimumZoom ) {
185144 return null ;
186145 }
187-
188146 for ( const [ id , building ] of Object . entries ( buildings ) ) {
189147 const buildingCenter = building . center ;
190148 if ( buildingCenter ) {
@@ -195,6 +153,5 @@ function findClosestBuildingId(buildings: Record<string, IndoorBuilding>, mapCen
195153 }
196154 }
197155 }
198-
199156 return closestBuildingId ;
200157}
0 commit comments