UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

163 lines (148 loc) 5.98 kB
import mapboxgl from 'mapbox-gl'; import {Camera} from 'three'; import {PolyScene} from '../../../engine/scene/PolyScene'; import {MapboxCameraAttribute} from './MapboxCameraAttribute'; import {MapboxLayersController, LayersOptions} from './LayersController'; import {ThreejsLayerRenderFunc} from './layers/MapboxThreejsLayer'; import {MapboxViewer} from '../../../engine/viewers/Mapbox'; // import {NodeContext} from '../../../engine/poly/NodeContext'; import {JsType} from '../../../engine/poly/registers/nodes/types/Js'; import {coreObjectClassFactory} from '../../geometry/CoreObjectFactory'; interface CreateMapboxMapOptions { camera: Camera; container: HTMLElement; scene: PolyScene; renderFunc: ThreejsLayerRenderFunc; viewer: MapboxViewer; } type MapRegisterCallback = (value: mapboxgl.Map) => void; // const CAMERA_MOVE_EVENT: Event = { // type: 'cameraMove', // }; class MapboxMapsControllerClass { private static _instance: MapboxMapsControllerClass; static instance() { return (this._instance = this._instance || new MapboxMapsControllerClass()); } private constructor() {} private _scene: PolyScene | undefined; private _mapByCameraName: Map<string, mapboxgl.Map> = new Map(); private _lastCreatedMap: mapboxgl.Map | undefined; private _resolves: MapRegisterCallback[] = []; async waitForMap(): Promise<mapboxgl.Map> { if (this._lastCreatedMap) { return this._lastCreatedMap; } else { return new Promise((resolve, reject) => { this._resolves.push(resolve); }); } } private _styleFlushed = false; private _flushCallbacksWithMap(map: mapboxgl.Map) { if (this._styleFlushed) { return; } this._styleFlushed = true; const callbacks: MapRegisterCallback[] = [...this._resolves]; this._resolves.length = 0; for (const c of callbacks) { c(map); } } createMap(options: CreateMapboxMapOptions) { const {camera, container, scene, renderFunc, viewer} = options; this._scene = scene; const coreObjectClass = coreObjectClassFactory(camera); const style = coreObjectClass.attribValue(camera, MapboxCameraAttribute.STYLE) as string; const longitude = coreObjectClass.attribValue(camera, MapboxCameraAttribute.LONGITUDE) as number; const latitude = coreObjectClass.attribValue(camera, MapboxCameraAttribute.LATITUDE) as number; const zoom = coreObjectClass.attribValue(camera, MapboxCameraAttribute.ZOOM) as number; const minZoom = coreObjectClass.attribValue(camera, MapboxCameraAttribute.MIN_ZOOM) as number; const maxZoom = coreObjectClass.attribValue(camera, MapboxCameraAttribute.MAX_ZOOM) as number; const pitch = coreObjectClass.attribValue(camera, MapboxCameraAttribute.PITCH) as number; const bearing = coreObjectClass.attribValue(camera, MapboxCameraAttribute.BEARING) as number; const allowDragRotate = coreObjectClass.attribValue(camera, MapboxCameraAttribute.ALLOW_DRAG_ROTATE) as boolean; const addZoomControl = coreObjectClass.attribValue(camera, MapboxCameraAttribute.ADD_ZOOM_CONTROL) as boolean; const tlayerBuildings = coreObjectClass.attribValue(camera, MapboxCameraAttribute.LAYER_BUILDINGS) as boolean; const tlayer3D = coreObjectClass.attribValue(camera, MapboxCameraAttribute.LAYER_3D) as boolean; const tlayerSky = coreObjectClass.attribValue(camera, MapboxCameraAttribute.LAYER_SKY) as boolean; const mapOptions: mapboxgl.MapboxOptions = { style, container, center: [longitude, latitude], zoom, minZoom, maxZoom, pitch, bearing, // preserveDrawingBuffer: true, dragRotate: allowDragRotate, pitchWithRotate: allowDragRotate, antialias: true, interactive: true, // useWebGL2: true, }; // webgl2 required since three 150 addition of textureLod in common.glsl (mapOptions as any).useWebGL2 = true; const map = new mapboxgl.Map(mapOptions); const layersOptions: LayersOptions = { map, scene, camera, renderFunc, viewer, lngLat: { lng: longitude, lat: latitude, }, displayScene: scene.threejsScene(), zoomControls: addZoomControl, layer3D: tlayer3D, layerBuildings: tlayerBuildings, layerSky: tlayerSky, }; const layersController = new MapboxLayersController(layersOptions); map.on('load', () => { layersController.addLayers(); // this.mapboxEventController.camera_node_move_end(); // to update mapbox planes globalThis.dispatchEvent(new Event('resize')); // helps making sure it is resized correctly }); map.on('styledata', () => { // console.log('A styledata event occurred.', map.isStyleLoaded()); if (map.isStyleLoaded()) { if (!this._styleFlushed && this._lastCreatedMap) { this._flushCallbacksWithMap(this._lastCreatedMap); } } }); map.on('move', () => this._dispatchCameraMove(JsType.ON_MAPBOX_CAMERA_MOVE)); map.on('movestart', () => this._dispatchCameraMove(JsType.ON_MAPBOX_CAMERA_MOVE_START)); map.on('moveend', () => this._dispatchCameraMove(JsType.ON_MAPBOX_CAMERA_MOVE_END)); // map.on('styledataloading', () => { // console.log('A styledataloading event occurred.', map.isStyleLoaded()); // }); // this._updateCameraAttributes(); // this._addRemoveControls(map, container.id); // this._maps_by_container_id.set(container.id, map); // this._map_containers_by_container_id.set(container.id, container); // this._canvases_by_container_id.set(container.id, container.querySelector('canvas')!); this._mapByCameraName.set(camera.name, map); this._lastCreatedMap = map; // if (this._mapByCameraName.size == 1) { // this._flushCallbacksWithMap(map); // } return {map, layersController}; } private _dispatchCameraMove( type: JsType.ON_MAPBOX_CAMERA_MOVE | JsType.ON_MAPBOX_CAMERA_MOVE_START | JsType.ON_MAPBOX_CAMERA_MOVE_END ) { if (!this._scene) { return; } this._scene.threejsScene().traverse((object) => { this._scene?.actorsManager.triggerEventNodes(object, type); }); } } export const MapboxMapsController = MapboxMapsControllerClass.instance();