diff --git a/package-lock.json b/package-lock.json index 0760d72..12956a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,7 +1,8 @@ { "name": "bluemap", - "requires": true, + "version": "0.1.0", "lockfileVersion": 1, + "requires": true, "dependencies": { "@babel/code-frame": { "version": "7.10.4", diff --git a/public/index.html b/public/index.html index 518913f..aa441c2 100644 --- a/public/index.html +++ b/public/index.html @@ -68,16 +68,16 @@ loadMaps("data/", bluemap.events).then(loadedMaps => { maps = loadedMaps; - markerManager = new BlueMap.MarkerFileManager(bluemap.markerScene, "data/markers.json", maps[0].id, bluemap.events); + markerManager = new BlueMap.MarkerFileManager(bluemap.markers, "data/markers.json", maps[0].data.id, bluemap.events); markerManager.update(); markerManager.setAutoUpdateInterval(1000 * 10); - playerManager = new BlueMap.PlayerMarkerManager(bluemap.markerScene, "live/players", "", bluemap.events); + playerManager = new BlueMap.PlayerMarkerManager(bluemap.markers, "live/players", "", bluemap.events); playerManager.update(); playerManager.setAutoUpdateInterval(1000); bluemap.switchMap(maps[0]).then(() => { - playerManager.worldId = maps[0].world; + playerManager.worldId = maps[0].data.world; }); }); diff --git a/src/MapViewer.js b/src/MapViewer.js index ec403c7..f69cecd 100644 --- a/src/MapViewer.js +++ b/src/MapViewer.js @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -import {PerspectiveCamera, Raycaster, Scene, Vector2, WebGLRenderer} from "three"; +import {Color, PerspectiveCamera, Raycaster, Scene, Vector2, Vector3, WebGLRenderer} from "three"; import {Map} from "./map/Map"; import {SkyboxScene} from "./skybox/SkyboxScene"; import {ControlsManager} from "./controls/ControlsManager"; @@ -35,6 +35,7 @@ import {LOWRES_VERTEX_SHADER} from "./map/lowres/LowresVertexShader"; import {LOWRES_FRAGMENT_SHADER} from "./map/lowres/LowresFragmentShader"; import {CombinedCamera} from "./util/CombinedCamera"; import {CSS2DRenderer} from "./util/CSS2DRenderer"; +import {MarkerSet} from "./markers/MarkerSet"; export class MapViewer { @@ -48,29 +49,33 @@ export class MapViewer { this.rootElement = element; this.events = events; + this.data = { + map: null, + camera: null, + controlsManager: null, + uniforms: { + sunlightStrength: { value: 1 }, + ambientLight: { value: 0 }, + skyColor: { value: new Color(0.5, 0.5, 1) }, + hiresTileMap: { + value: { + map: null, + size: TileManager.tileMapSize, + scale: new Vector2(1, 1), + translate: new Vector2(), + pos: new Vector2(), + } + } + }, + superSampling: 1, + loadedCenter: new Vector2(0, 0), + loadedHiresViewDistance: 200, + loadedLowresViewDistance: 2000, + } + this.stats = new Stats(); this.stats.hide(); - this.superSamplingValue = 1; - this.loadedCenter = new Vector2(0, 0); - this.loadedHiresViewDistance = 200; - this.loadedLowresViewDistance = 2000; - - // uniforms - this.uniforms = { - sunlightStrength: { value: 1 }, - ambientLight: { value: 0 }, - hiresTileMap: { - value: { - map: null, - size: TileManager.tileMapSize, - scale: new Vector2(1, 1), - translate: new Vector2(), - pos: new Vector2(), - } - } - }; - // renderer this.renderer = new WebGLRenderer({ antialias: true, @@ -79,12 +84,12 @@ export class MapViewer { logarithmicDepthBuffer: true, }); this.renderer.autoClear = false; - this.renderer.uniforms = this.uniforms; + this.renderer.uniforms = this.data.uniforms; // CSS2D renderer this.css2dRenderer = new CSS2DRenderer(); - this.skyboxScene = new SkyboxScene(); + this.skyboxScene = new SkyboxScene(this.data.uniforms); this.camera = new CombinedCamera(75, 1, 0.1, 10000, 0); this.skyboxCamera = new PerspectiveCamera(75, 1, 0.1, 10000); @@ -98,7 +103,7 @@ export class MapViewer { /** @type {Map} */ this.map = null; - this.markerScene = new Scene(); + this.markers = new MarkerSet("bm-root"); this.lastFrame = 0; @@ -142,7 +147,7 @@ export class MapViewer { */ handleContainerResize = () => { this.renderer.setSize(this.rootElement.clientWidth, this.rootElement.clientHeight); - this.renderer.setPixelRatio(window.devicePixelRatio * this.superSamplingValue); + this.renderer.setPixelRatio(window.devicePixelRatio * this.superSampling); this.css2dRenderer.setSize(this.rootElement.clientWidth, this.rootElement.clientHeight); @@ -170,7 +175,7 @@ export class MapViewer { this.raycaster.setFromCamera(normalizedScreenPos, this.camera); // check Object3D interactions - let intersects = this.raycaster.intersectObjects([this.map.hiresTileManager.scene, this.map.lowresTileManager.scene, this.markerScene], true); + let intersects = this.raycaster.intersectObjects([this.map.hiresTileManager.scene, this.map.lowresTileManager.scene, this.markers], true); let covered = false; for (let i = 0; i < intersects.length; i++) { if (intersects[i].object){ @@ -252,7 +257,7 @@ export class MapViewer { if (this.map && this.map.isLoaded) { //update uniforms - this.uniforms.hiresTileMap.value.pos.copy(this.map.hiresTileManager.centerTile); + this.data.uniforms.hiresTileMap.value.pos.copy(this.map.hiresTileManager.centerTile); this.renderer.render(this.map.lowresTileManager.scene, this.camera); this.renderer.clearDepth(); @@ -263,8 +268,8 @@ export class MapViewer { } // render markers - this.renderer.render(this.markerScene, this.camera); - this.css2dRenderer.render(this.markerScene, this.camera); + this.renderer.render(this.markers, this.camera); + this.css2dRenderer.render(this.markers, this.camera); } /** @@ -278,15 +283,13 @@ export class MapViewer { this.map = map; if (this.map && this.map.isMap) { - return map.load(HIRES_VERTEX_SHADER, HIRES_FRAGMENT_SHADER, LOWRES_VERTEX_SHADER, LOWRES_FRAGMENT_SHADER, this.uniforms) + return map.load(HIRES_VERTEX_SHADER, HIRES_FRAGMENT_SHADER, LOWRES_VERTEX_SHADER, LOWRES_FRAGMENT_SHADER, this.data.uniforms) .then(() => { - this.skyboxScene.ambientLight = map.ambientLight; - this.skyboxScene.skyColor = map.skyColor; - - this.uniforms.ambientLight.value = map.ambientLight; - this.uniforms.hiresTileMap.value.map = map.hiresTileManager.tileMap.texture; - this.uniforms.hiresTileMap.value.scale.set(map.hires.tileSize.x, map.hires.tileSize.z); - this.uniforms.hiresTileMap.value.translate.set(map.hires.translate.x, map.hires.translate.z); + this.data.uniforms.skyColor.value = map.data.skyColor; + this.data.uniforms.ambientLight.value = map.data.ambientLight; + this.data.uniforms.hiresTileMap.value.map = map.hiresTileManager.tileMap.texture; + this.data.uniforms.hiresTileMap.value.scale.set(map.data.hires.tileSize.x, map.data.hires.tileSize.z); + this.data.uniforms.hiresTileMap.value.translate.set(map.data.hires.translate.x, map.data.hires.translate.z); setTimeout(this.updateLoadedMapArea); @@ -306,13 +309,13 @@ export class MapViewer { * Loads the given area on the map (and unloads everything outside that area) * @param centerX {number} * @param centerZ {number} - * @param hiresViewDistance {number} - * @param lowresViewDistance {number} + * @param hiresViewDistance {number?} + * @param lowresViewDistance {number?} */ loadMapArea(centerX, centerZ, hiresViewDistance = -1, lowresViewDistance = -1) { - this.loadedCenter.set(centerX, centerZ); - if (hiresViewDistance >= 0) this.loadedHiresViewDistance = hiresViewDistance; - if (lowresViewDistance >= 0) this.loadedLowresViewDistance = lowresViewDistance; + this.data.loadedCenter.set(centerX, centerZ); + if (hiresViewDistance >= 0) this.data.loadedHiresViewDistance = hiresViewDistance; + if (lowresViewDistance >= 0) this.data.loadedLowresViewDistance = lowresViewDistance; this.updateLoadedMapArea(); } @@ -322,22 +325,67 @@ export class MapViewer { */ updateLoadedMapArea = () => { if (!this.map) return; - this.map.loadMapArea(this.loadedCenter.x, this.loadedCenter.y, this.loadedHiresViewDistance, this.loadedLowresViewDistance); + this.map.loadMapArea(this.data.loadedCenter.x, this.data.loadedCenter.y, this.data.loadedHiresViewDistance, this.data.loadedLowresViewDistance); } /** * @returns {number} */ get superSampling() { - return this.superSamplingValue; + return this.data.superSampling; } /** * @param value {number} */ set superSampling(value) { - this.superSamplingValue = value; + this.data.superSampling = value; this.handleContainerResize(); } + /** + * @returns {CombinedCamera} + */ + get camera() { + return this._camera; + } + + /** + * @param value {CombinedCamera} + */ + set camera(value) { + this._camera = value; + this.data.camera = value.data; + } + + /** + * @returns {ControlsManager} + */ + get controlsManager() { + return this._controlsManager; + } + + /** + * @param value {ControlsManager} + */ + set controlsManager(value) { + this._controlsManager = value; + this.data.controlsManager = value.data; + } + + /** + * @returns {Map} + */ + get map() { + return this._map; + } + + /** + * @param value {Map} + */ + set map(value) { + this._map = value; + if (value) this.data.map = value.data; + } + } diff --git a/src/controls/ControlsManager.js b/src/controls/ControlsManager.js index d2be6e2..71869fd 100644 --- a/src/controls/ControlsManager.js +++ b/src/controls/ControlsManager.js @@ -36,14 +36,20 @@ export class ControlsManager { constructor(mapViewer, camera) { Object.defineProperty( this, 'isControlsManager', { value: true } ); + this.data = { + mapViewer: null, + camera: null, + controls: null, + position: new Vector3(0, 0, 0), + rotation: 0, + angle: 0, + tilt: 0, + }; + this.mapViewer = mapViewer; this.camera = camera; - this.position = new Vector3(0, 0, 0); - this.rotation = 0; - this.angle = 0; - this.tilt = 0; - + /** @type {Vector3} */ this.lastPosition = this.position.clone(); this.lastRotation = this.rotation; this.lastAngle = this.angle; @@ -164,22 +170,22 @@ export class ControlsManager { isValueChanged() { return !( - this.position.equals(this.lastPosition) && - this.rotation === this.lastRotation && - this.angle === this.lastAngle && + this.data.position.equals(this.lastPosition) && + this.data.rotation === this.lastRotation && + this.data.angle === this.lastAngle && this.distance === this.lastDistance && this.ortho === this.lastOrtho && - this.tilt === this.lastTilt + this.data.tilt === this.lastTilt ); } resetValueChanged() { - this.lastPosition.copy(this.position); - this.lastRotation = this.rotation; - this.lastAngle = this.angle; + this.lastPosition.copy(this.data.position); + this.lastRotation = this.data.rotation; + this.lastAngle = this.data.angle; this.lastDistance = this.distance; this.lastOrtho = this.ortho; - this.lastTilt = this.tilt; + this.lastTilt = this.data.tilt; } /** @@ -218,6 +224,7 @@ export class ControlsManager { this._controls.stop(); this._controls = controls; + if (controls) this.data.controls = controls.data || null if (this._controls && this._controls.start) this._controls.start(this); @@ -230,4 +237,89 @@ export class ControlsManager { return this._controls; } + /** + * @returns {MapViewer} + */ + get mapViewer() { + return this._mapViewer; + } + + /** + * @param value {MapViewer} + */ + set mapViewer(value) { + this._mapViewer = value; + this.data.mapViewer = value.data; + } + + /** + * @returns {CombinedCamera} + */ + get camera() { + return this._camera; + } + + /** + * @param value {CombinedCamera} + */ + set camera(value) { + this._camera = value; + this.data.camera = value.data; + } + + /** + * @returns {Vector3} + */ + get position() { + return this.data.position; + } + + /** + * @param value {Vector3} + */ + set position(value) { + this.data.position = value; + } + + /** + * @returns {number} + */ + get rotation() { + return this.data.rotation; + } + + /** + * @param value {number} + */ + set rotation(value) { + this.data.rotation = value; + } + + /** + * @returns {number} + */ + get angle() { + return this.data.angle; + } + + /** + * @param value {number} + */ + set angle(value) { + this.data.angle = value; + } + + /** + * @returns {number} + */ + get tilt() { + return this.data.tilt; + } + + /** + * @param value {number} + */ + set tilt(value) { + this.data.tilt = value; + } } \ No newline at end of file diff --git a/src/controls/map/MapHeightControls.js b/src/controls/map/MapHeightControls.js index 956d80a..9a36a37 100644 --- a/src/controls/map/MapHeightControls.js +++ b/src/controls/map/MapHeightControls.js @@ -41,9 +41,6 @@ export class MapHeightControls { this.targetHeight = 0; this.cameraHeight = 0; - this.lastTarget = new Vector2(); - this.lastTargetTerrainHeight = 0; - this.minCameraHeight = 0; this.distanceTagretHeight = 0; } @@ -73,12 +70,7 @@ export class MapHeightControls { let targetSmoothing = this.targetHeightStiffness / (16.666 / delta); targetSmoothing = MathUtils.clamp(targetSmoothing, 0, 1); - let targetTerrainHeight = this.lastTargetTerrainHeight; - if (this.lastTarget.x !== this.manager.position.x || this.lastTarget.y !== this.manager.position.z){ - targetTerrainHeight = map.terrainHeightAt(this.manager.position.x, this.manager.position.z) || 0; - this.lastTargetTerrainHeight = targetTerrainHeight; - this.lastTarget.set(this.manager.position.x, this.manager.position.z); - } + let targetTerrainHeight = map.terrainHeightAt(this.manager.position.x, this.manager.position.z) + 3 || 0; let targetDelta = targetTerrainHeight - this.targetHeight; this.targetHeight += targetDelta * targetSmoothing; diff --git a/src/map/Map.js b/src/map/Map.js index 40805c2..c807afd 100644 --- a/src/map/Map.js +++ b/src/map/Map.js @@ -45,29 +45,28 @@ export class Map { constructor(id, dataUrl, settingsUrl, texturesUrl, events = null) { Object.defineProperty( this, 'isMap', { value: true } ); - this.id = id; this.events = events; - this.dataUrl = dataUrl; - this.settingsUrl = settingsUrl; - this.texturesUrl = texturesUrl; - - this.name = this.id; - this.world = "-"; - - this.startPos = {x: 0, z: 0}; - this.skyColor = new Color(); - this.ambientLight = 0; - - this.hires = { - tileSize: {x: 32, z: 32}, - scale: {x: 1, z: 1}, - translate: {x: 2, z: 2} - }; - this.lowres = { - tileSize: {x: 32, z: 32}, - scale: {x: 1, z: 1}, - translate: {x: 2, z: 2} + this.data = { + id: id, + dataUrl: dataUrl, + settingsUrl: settingsUrl, + texturesUrl: texturesUrl, + name: id, + world: "-", + startPos: {x: 0, z: 0}, + skyColor: new Color(), + ambientLight: 0, + hires: { + tileSize: {x: 32, z: 32}, + scale: {x: 1, z: 1}, + translate: {x: 2, z: 2} + }, + lowres: { + tileSize: {x: 32, z: 32}, + scale: {x: 1, z: 1}, + translate: {x: 2, z: 2} + } }; this.raycaster = new Raycaster(); @@ -104,29 +103,29 @@ export class Map { let settingsPromise = settingsFilePromise .then(worldSettings => { - this.name = worldSettings.name ? worldSettings.name : this.name; - this.world = worldSettings.world ? worldSettings.world : this.world; + this.data.name = worldSettings.name ? worldSettings.name : this.data.name; + this.data.world = worldSettings.world ? worldSettings.world : this.data.world; - this.startPos = {...this.startPos, ...worldSettings.startPos}; - this.skyColor.setRGB( - worldSettings.skyColor.r || this.skyColor.r, - worldSettings.skyColor.g || this.skyColor.g, - worldSettings.skyColor.b || this.skyColor.b, + this.data.startPos = {...this.data.startPos, ...worldSettings.startPos}; + this.data.skyColor.setRGB( + worldSettings.skyColor.r || this.data.skyColor.r, + worldSettings.skyColor.g || this.data.skyColor.g, + worldSettings.skyColor.b || this.data.skyColor.b, ); - this.ambientLight = worldSettings.ambientLight ? worldSettings.ambientLight : 0; + this.data.ambientLight = worldSettings.ambientLight ? worldSettings.ambientLight : this.data.ambientLight; if (worldSettings.hires === undefined) worldSettings.hires = {}; if (worldSettings.lowres === undefined) worldSettings.lowres = {}; - this.hires = { - tileSize: {...this.hires.tileSize, ...worldSettings.hires.tileSize}, - scale: {...this.hires.scale, ...worldSettings.hires.scale}, - translate: {...this.hires.translate, ...worldSettings.hires.translate} + this.data.hires = { + tileSize: {...this.data.hires.tileSize, ...worldSettings.hires.tileSize}, + scale: {...this.data.hires.scale, ...worldSettings.hires.scale}, + translate: {...this.data.hires.translate, ...worldSettings.hires.translate} }; - this.lowres = { - tileSize: {...this.lowres.tileSize, ...worldSettings.lowres.tileSize}, - scale: {...this.lowres.scale, ...worldSettings.lowres.scale}, - translate: {...this.lowres.translate, ...worldSettings.lowres.translate} + this.data.lowres = { + tileSize: {...this.data.lowres.tileSize, ...worldSettings.lowres.tileSize}, + scale: {...this.data.lowres.scale, ...worldSettings.lowres.scale}, + translate: {...this.data.lowres.translate, ...worldSettings.lowres.translate} }; }); @@ -137,13 +136,13 @@ export class Map { this.hiresMaterial = this.createHiresMaterial(hiresVertexShader, hiresFragmentShader, uniforms, textures); - this.hiresTileManager = new TileManager(new Scene(), new TileLoader(`${this.dataUrl}hires/`, this.hiresMaterial, this.hires), this.onTileLoad("hires"), this.onTileUnload("hires"), this.events); - this.lowresTileManager = new TileManager(new Scene(), new TileLoader(`${this.dataUrl}lowres/`, this.lowresMaterial, this.lowres), this.onTileLoad("lowres"), this.onTileUnload("lowres"), this.events); + this.hiresTileManager = new TileManager(new Scene(), new TileLoader(`${this.data.dataUrl}hires/`, this.hiresMaterial, this.data.hires), this.onTileLoad("hires"), this.onTileUnload("hires"), this.events); + this.lowresTileManager = new TileManager(new Scene(), new TileLoader(`${this.data.dataUrl}lowres/`, this.lowresMaterial, this.data.lowres), this.onTileLoad("lowres"), this.onTileUnload("lowres"), this.events); this.hiresTileManager.scene.autoUpdate = false; this.lowresTileManager.scene.autoUpdate = false; - alert(this.events, `Map '${this.id}' is loaded.`, "fine"); + alert(this.events, `Map '${this.data.id}' is loaded.`, "fine"); }); } @@ -170,15 +169,15 @@ export class Map { loadMapArea(x, z, hiresViewDistance, lowresViewDistance) { if (!this.isLoaded) return; - let hiresX = Math.floor((x - this.hires.translate.x) / this.hires.tileSize.x); - let hiresZ = Math.floor((z - this.hires.translate.z) / this.hires.tileSize.z); - let hiresViewX = Math.floor(hiresViewDistance / this.hires.tileSize.x); - let hiresViewZ = Math.floor(hiresViewDistance / this.hires.tileSize.z); + let hiresX = Math.floor((x - this.data.hires.translate.x) / this.data.hires.tileSize.x); + let hiresZ = Math.floor((z - this.data.hires.translate.z) / this.data.hires.tileSize.z); + let hiresViewX = Math.floor(hiresViewDistance / this.data.hires.tileSize.x); + let hiresViewZ = Math.floor(hiresViewDistance / this.data.hires.tileSize.z); - let lowresX = Math.floor((x - this.lowres.translate.x) / this.lowres.tileSize.x); - let lowresZ = Math.floor((z - this.lowres.translate.z) / this.lowres.tileSize.z); - let lowresViewX = Math.floor(lowresViewDistance / this.lowres.tileSize.x); - let lowresViewZ = Math.floor(lowresViewDistance / this.lowres.tileSize.z); + let lowresX = Math.floor((x - this.data.lowres.translate.x) / this.data.lowres.tileSize.x); + let lowresZ = Math.floor((z - this.data.lowres.translate.z) / this.data.lowres.tileSize.z); + let lowresViewX = Math.floor(lowresViewDistance / this.data.lowres.tileSize.x); + let lowresViewZ = Math.floor(lowresViewDistance / this.data.lowres.tileSize.z); this.hiresTileManager.loadAroundTile(hiresX, hiresZ, hiresViewX, hiresViewZ); this.lowresTileManager.loadAroundTile(lowresX, lowresZ, lowresViewX, lowresViewZ); @@ -190,20 +189,20 @@ export class Map { */ loadSettingsFile() { return new Promise((resolve, reject) => { - alert(this.events, `Loading settings for map '${this.id}'...`, "fine"); + alert(this.events, `Loading settings for map '${this.data.id}'...`, "fine"); let loader = new FileLoader(); loader.setResponseType("json"); - loader.load(this.settingsUrl, + loader.load(this.data.settingsUrl, settings => { - if (settings.maps && settings.maps[this.id]) { - resolve(settings.maps[this.id]); + if (settings.maps && settings.maps[this.data.id]) { + resolve(settings.maps[this.data.id]); } else { - reject(`the settings.json does not contain informations for map: ${this.id}`); + reject(`the settings.json does not contain informations for map: ${this.data.id}`); } }, () => {}, - () => reject(`Failed to load the settings.json for map: ${this.id}`) + () => reject(`Failed to load the settings.json for map: ${this.data.id}`) ) }); } @@ -214,14 +213,14 @@ export class Map { */ loadTexturesFile() { return new Promise((resolve, reject) => { - alert(this.events, `Loading textures for map '${this.id}'...`, "fine"); + alert(this.events, `Loading textures for map '${this.data.id}'...`, "fine"); let loader = new FileLoader(); loader.setResponseType("json"); - loader.load(this.texturesUrl, + loader.load(this.data.texturesUrl, resolve, () => {}, - () => reject(`Failed to load the textures.json for map: ${this.id}`) + () => reject(`Failed to load the textures.json for map: ${this.data.id}`) ) }); } @@ -343,10 +342,10 @@ export class Map { this.raycaster.far = 300; this.raycaster.layers.enableAll(); - let hiresTileHash = hashTile(Math.floor((x - this.hires.translate.x) / this.hires.tileSize.x), Math.floor((z - this.hires.translate.z) / this.hires.tileSize.z)); + let hiresTileHash = hashTile(Math.floor((x - this.data.hires.translate.x) / this.data.hires.tileSize.x), Math.floor((z - this.data.hires.translate.z) / this.data.hires.tileSize.z)); let tile = this.hiresTileManager.tiles.get(hiresTileHash); if (!tile || !tile.model) { - let lowresTileHash = hashTile(Math.floor((x - this.lowres.translate.x) / this.lowres.tileSize.x), Math.floor((z - this.lowres.translate.z) / this.lowres.tileSize.z)); + let lowresTileHash = hashTile(Math.floor((x - this.data.lowres.translate.x) / this.data.lowres.tileSize.x), Math.floor((z - this.data.lowres.translate.z) / this.data.lowres.tileSize.z)); tile = this.lowresTileManager.tiles.get(lowresTileHash); } diff --git a/src/markers/ExtrudeMarker.js b/src/markers/ExtrudeMarker.js index d12f1b3..3f81111 100644 --- a/src/markers/ExtrudeMarker.js +++ b/src/markers/ExtrudeMarker.js @@ -39,7 +39,7 @@ export class ExtrudeMarker extends ObjectMarker { constructor(markerId) { super(markerId); Object.defineProperty(this, 'isExtrudeMarker', {value: true}); - this.markerType = "extrude"; + this.data.type = "extrude"; let zero = new Vector2(); let shape = new Shape([zero, zero, zero]); diff --git a/src/markers/HtmlMarker.js b/src/markers/HtmlMarker.js index caccca7..ae347a5 100644 --- a/src/markers/HtmlMarker.js +++ b/src/markers/HtmlMarker.js @@ -34,9 +34,9 @@ export class HtmlMarker extends Marker { constructor(markerId) { super(markerId); Object.defineProperty(this, 'isHtmlMarker', {value: true}); - this.markerType = "html"; + this.data.type = "html"; - this.elementObject = new CSS2DObject(htmlToElement(`
`)); + this.elementObject = new CSS2DObject(htmlToElement(`
`)); this.elementObject.onBeforeRender = (renderer, scene, camera) => this.onBeforeRender(renderer, scene, camera); this.fadeDistanceMin = 0; diff --git a/src/markers/LineMarker.js b/src/markers/LineMarker.js index 7419c53..b111408 100644 --- a/src/markers/LineMarker.js +++ b/src/markers/LineMarker.js @@ -37,7 +37,7 @@ export class LineMarker extends ObjectMarker { constructor(markerId) { super(markerId); Object.defineProperty(this, 'isLineMarker', {value: true}); - this.markerType = "line"; + this.data.type = "line"; this.line = new LineMarkerLine([0, 0, 0]); diff --git a/src/markers/Marker.js b/src/markers/Marker.js index 4cedf7f..2524286 100644 --- a/src/markers/Marker.js +++ b/src/markers/Marker.js @@ -33,12 +33,20 @@ export class Marker extends Object3D { super(); Object.defineProperty(this, 'isMarker', {value: true}); - this.markerId = markerId; - this.markerType = "marker"; + this.data = { + id: markerId, + type: "marker", + position: this.position + }; + // redirect parent properties + Object.defineProperty(this, "position", { + get() { return this.data.position }, + set(value) { this.data.position = value } + }); } - dispose() {}; + dispose() {} /** * Updates this marker from the provided data object, usually parsed form json from a markers.json diff --git a/src/markers/MarkerFileManager.js b/src/markers/MarkerFileManager.js index 47c598d..52a6440 100644 --- a/src/markers/MarkerFileManager.js +++ b/src/markers/MarkerFileManager.js @@ -136,7 +136,7 @@ export class MarkerFileManager extends MarkerManager { let marker = this.markers.get(markerData.id); // create new if not existent of wrong type - if (!marker || marker.markerType !== markerData.type) { + if (!marker || marker.data.type !== markerData.type) { switch (markerData.type) { case "shape" : marker = new ShapeMarker(markerData.id); break; case "extrude" : marker = new ExtrudeMarker(markerData.id); break; diff --git a/src/markers/MarkerManager.js b/src/markers/MarkerManager.js index 3a05f61..634da54 100644 --- a/src/markers/MarkerManager.js +++ b/src/markers/MarkerManager.js @@ -95,7 +95,7 @@ export class MarkerManager { * Removes all markers managed by this marker-manager */ clear() { - this.markerSets.forEach(markerSet => this.removeMarkerSet(markerSet.markerSetId)); + this.markerSets.forEach(markerSet => this.removeMarkerSet(markerSet.data.id)); } /** @@ -104,10 +104,10 @@ export class MarkerManager { * @param markerSet {MarkerSet} */ addMarkerSet(markerSet) { - this.removeMarkerSet(markerSet.markerSetId); + this.removeMarkerSet(markerSet.data.id); - this.markerSets.set(markerSet.markerSetId, markerSet); - this.markerScene.add(markerSet) + this.markerSets.set(markerSet.data.id, markerSet); + this.markerScene.add(markerSet); } /** @@ -132,9 +132,9 @@ export class MarkerManager { * @param marker {Marker} */ addMarker(markerSet, marker) { - this.removeMarker(marker.markerId); + this.removeMarker(marker.data.id); - this.markers.set(marker.markerId, marker); + this.markers.set(marker.data.id, marker); markerSet.add(marker); } diff --git a/src/markers/MarkerSet.js b/src/markers/MarkerSet.js index 9d7d4a9..a73af37 100644 --- a/src/markers/MarkerSet.js +++ b/src/markers/MarkerSet.js @@ -22,22 +22,55 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -import {Object3D} from "three"; +import {Scene} from "three"; -export class MarkerSet extends Object3D { +export class MarkerSet extends Scene { /** - * @param markerSetId {string} + * @param id {string} */ - constructor(markerSetId) { + constructor(id) { super(); Object.defineProperty(this, 'isMarkerSet', {value: true}); - this.markerSetId = markerSetId; - this.label = markerSetId; + this.data = { + id: id, + label: id, + toggleable: true, + defaultHide: false, + markerSets: [], + markers: [], + }; + } - this.toggleable = true; - this.defaultHide = false; + add(...object) { + if (object.length === 1) { //super.add() will re-invoke this method for each array-entry if its more than one + let o = object[0]; + if (o.isMarkerSet) { + this.data.markerSets.push(o.data); + } + if (o.isMarker) { + this.data.markers.push(o.data); + } + } + + return super.add(...object); + } + + remove(...object) { + if (object.length === 1) { //super.remove() will re-invoke this method for each array-entry if its more than one + let o = object[0]; + if (o.isMarkerSet) { + let i = this.data.markerSets.indexOf(o.data); + if (i > -1) this.data.markerSets.splice(i, 1); + } + if (o.isMarker) { + let i = this.data.markers.indexOf(o.data); + if (i > -1) this.data.markers.splice(i, 1); + } + } + + return super.remove(...object); } dispose() { diff --git a/src/markers/ObjectMarker.js b/src/markers/ObjectMarker.js index e5d4e2a..2070507 100644 --- a/src/markers/ObjectMarker.js +++ b/src/markers/ObjectMarker.js @@ -35,11 +35,11 @@ export class ObjectMarker extends Marker { constructor(markerId) { super(markerId); Object.defineProperty(this, 'isObjectMarker', {value: true}); - this.markerType = "object"; + this.data.type = "object"; - this.label = null; - this.link = null; - this.newTab = true; + this.data.label = null; + this.data.link = null; + this.data.newTab = true; } onClick(event) { @@ -49,13 +49,17 @@ export class ObjectMarker extends Marker { pos.sub(this.position); } - if (this.label) { - let popup = new LabelPopup(this.label); + if (this.data.label) { + let popup = new LabelPopup(this.data.label); popup.position.copy(pos); this.add(popup); popup.open(); } + if (this.data.link){ + window.open(this.data.link, this.data.newTab ? '_blank' : '_self'); + } + return true; } diff --git a/src/markers/PlayerMarker.js b/src/markers/PlayerMarker.js index e7040ba..671f1aa 100644 --- a/src/markers/PlayerMarker.js +++ b/src/markers/PlayerMarker.js @@ -35,12 +35,12 @@ export class PlayerMarker extends Marker { constructor(markerId, playerUuid) { super(markerId); Object.defineProperty(this, 'isPlayerMarker', {value: true}); - this.markerType = "player"; + this.data.type = "player"; this.playerUuid = playerUuid; this.elementObject = new CSS2DObject(htmlToElement(` -
+
playerhead
diff --git a/src/markers/PoiMarker.js b/src/markers/PoiMarker.js index d8ce187..12cb79b 100644 --- a/src/markers/PoiMarker.js +++ b/src/markers/PoiMarker.js @@ -32,9 +32,9 @@ export class PoiMarker extends HtmlMarker { constructor(markerId) { super(markerId); Object.defineProperty(this, 'isPoiMarker', {value: true}); - this.markerType = "poi"; + this.data.type = "poi"; - this.html = `POI Icon (${this.markerId})
`; + this.html = `POI Icon (${this.data.id})
`; this.iconElement = this.element.getElementsByTagName("img").item(0); this.labelElement = this.element.getElementsByTagName("div").item(0); @@ -43,13 +43,13 @@ export class PoiMarker extends HtmlMarker { } onClick(event) { - if (this.hightlight) return; - this.hightlight = true; + if (this.highlight) return; + this.highlight = true; let eventHandler = evt => { if (evt.path.includes(this.element)) return; - this.hightlight = false; + this.highlight = false; window.removeEventListener("mousedown", eventHandler); window.removeEventListener("touchstart", eventHandler); @@ -67,7 +67,7 @@ export class PoiMarker extends HtmlMarker { return true; } - set hightlight(highlight) { + set highlight(highlight) { if (highlight) { this.element.classList.add("bm-marker-highlight"); } else { @@ -75,7 +75,7 @@ export class PoiMarker extends HtmlMarker { } } - get hightlight() { + get highlight() { return this.element.classList.contains("bm-marker-highlight"); } @@ -122,5 +122,4 @@ export class PoiMarker extends HtmlMarker { } - } \ No newline at end of file diff --git a/src/markers/ShapeMarker.js b/src/markers/ShapeMarker.js index 4f1eb00..f22ba28 100644 --- a/src/markers/ShapeMarker.js +++ b/src/markers/ShapeMarker.js @@ -39,7 +39,7 @@ export class ShapeMarker extends ObjectMarker { constructor(markerId) { super(markerId); Object.defineProperty(this, 'isShapeMarker', {value: true}); - this.markerType = "shape"; + this.data.type = "shape"; let zero = new Vector2(); let shape = new Shape([zero, zero, zero]); diff --git a/src/skybox/SkyFragmentShader.js b/src/skybox/SkyFragmentShader.js index 720c098..be59e76 100644 --- a/src/skybox/SkyFragmentShader.js +++ b/src/skybox/SkyFragmentShader.js @@ -23,7 +23,7 @@ * THE SOFTWARE. */ export const SKY_FRAGMENT_SHADER = ` -uniform float sunlight; +uniform float sunlightStrength; uniform float ambientLight; uniform vec3 skyColor; @@ -33,7 +33,7 @@ void main() { float horizonWidth = 0.005; float horizonHeight = 0.0; - vec4 color = vec4(skyColor * max(sunlight, ambientLight), 1.0); + vec4 color = vec4(skyColor * max(sunlightStrength, ambientLight), 1.0); float voidMultiplier = (clamp(vPosition.y - horizonHeight, -horizonWidth, horizonWidth) + horizonWidth) / (horizonWidth * 2.0); color.rgb *= voidMultiplier; diff --git a/src/skybox/SkyboxScene.js b/src/skybox/SkyboxScene.js index ef1f193..d8f6236 100644 --- a/src/skybox/SkyboxScene.js +++ b/src/skybox/SkyboxScene.js @@ -22,39 +22,23 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -import {BackSide, Color, Mesh, Scene, ShaderMaterial, SphereGeometry} from 'three'; +import {BackSide, Mesh, Scene, ShaderMaterial, SphereGeometry} from 'three'; import {SKY_FRAGMENT_SHADER} from './SkyFragmentShader'; import {SKY_VERTEX_SHADER} from './SkyVertexShader'; export class SkyboxScene extends Scene { - constructor() { + constructor(uniforms) { super(); this.autoUpdate = false; - Object.defineProperty( this, 'isSkyboxScene', { value: true } ); - - this.UNIFORM_sunlight = { - value: 1 - }; - - this.UNIFORM_skyColor = { - value: new Color(0.5, 0.5, 1) - }; - - this.UNIFORM_ambientLight = { - value: 0 - }; + Object.defineProperty(this, 'isSkyboxScene', {value: true}); let geometry = new SphereGeometry(1, 40, 5); let material = new ShaderMaterial({ - uniforms: { - sunlight: this.UNIFORM_sunlight, - skyColor: this.UNIFORM_skyColor, - ambientLight: this.UNIFORM_ambientLight, - }, + uniforms: uniforms, vertexShader: SKY_VERTEX_SHADER, fragmentShader: SKY_FRAGMENT_SHADER, side: BackSide @@ -64,46 +48,4 @@ export class SkyboxScene extends Scene { this.add(skybox); } - /** - * @returns {number} - */ - get sunlight() { - return this.UNIFORM_sunlight.value; - } - - /** - * @param strength {number} - */ - set sunlight(strength) { - this.UNIFORM_sunlight.value = strength; - } - - /** - * @returns {Color} - */ - get skyColor() { - return this.UNIFORM_skyColor.value; - } - - /** - * @param color {Color} - */ - set skyColor(color) { - this.UNIFORM_skyColor.value.set(color); - } - - /** - * @returns {number} - */ - get ambientLight() { - return this.UNIFORM_ambientLight.value; - } - - /** - * @param strength {number} - */ - set ambientLight(strength) { - this.UNIFORM_ambientLight.value = strength; - } - } \ No newline at end of file diff --git a/src/util/CombinedCamera.js b/src/util/CombinedCamera.js index 3b85e0a..fb4f81f 100644 --- a/src/util/CombinedCamera.js +++ b/src/util/CombinedCamera.js @@ -36,8 +36,39 @@ export class CombinedCamera extends PerspectiveCamera { constructor(fov, aspect, near, far, ortho) { super(fov, aspect, near, far); - this.ortho = ortho; - this.distance = 1; + this.data = { + fov: this.fov, + aspect: this.aspect, + near: this.near, + far: this.far, + zoom: this.zoom, + ortho: ortho, + distance: 1, + }; + + // redirect parent properties + Object.defineProperty(this, "fov", { + get() { return this.data.fov }, + set(value) { this.data.fov = value } + }); + Object.defineProperty(this, "aspect", { + get() { return this.data.aspect }, + set(value) { this.data.aspect = value } + }); + Object.defineProperty(this, "near", { + get() { return this.data.near }, + set(value) { this.data.near = value } + }); + Object.defineProperty(this, "far", { + get() { return this.data.far }, + set(value) { this.data.far = value } + }); + Object.defineProperty(this, "zoom", { + get() { return this.data.zoom }, + set(value) { this.data.zoom = value } + }); + + this.updateProjectionMatrix(); } updateProjectionMatrix() { @@ -47,6 +78,9 @@ export class CombinedCamera extends PerspectiveCamera { if (!this.perspectiveProjection) this.perspectiveProjection = new Matrix4(); + if (!this.data) + this.data = {}; + //copied from PerspectiveCamera const near = this.near; let top = near * Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov ) / this.zoom; @@ -117,4 +151,31 @@ export class CombinedCamera extends PerspectiveCamera { //ignore } + /** + * @returns {number} + */ + get ortho() { + return this.data.ortho; + } + + /** + * @param value {number} + */ + set ortho(value) { + this.data.ortho = value; + } + + /** + * @returns {number} + */ + get distance() { + return this.data.distance; + } + + /** + * @param value {number} + */ + set distance(value) { + this.data.distance = value; + } } \ No newline at end of file