mirror of
https://github.com/BlueMap-Minecraft/BlueMapWeb.git
synced 2025-02-20 11:51:21 +01:00
Some tidying and finalizing
This commit is contained in:
parent
d16b71765f
commit
272809389b
41
package-lock.json
generated
41
package-lock.json
generated
@ -1043,6 +1043,47 @@
|
|||||||
"picomatch": "^2.2.2"
|
"picomatch": "^2.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/babel__core": {
|
||||||
|
"version": "7.1.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.12.tgz",
|
||||||
|
"integrity": "sha512-wMTHiiTiBAAPebqaPiPDLFA4LYPKr6Ph0Xq/6rq1Ur3v66HXyG+clfR9CNETkD7MQS8ZHvpQOtA53DLws5WAEQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/parser": "^7.1.0",
|
||||||
|
"@babel/types": "^7.0.0",
|
||||||
|
"@types/babel__generator": "*",
|
||||||
|
"@types/babel__template": "*",
|
||||||
|
"@types/babel__traverse": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/babel__generator": {
|
||||||
|
"version": "7.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.2.tgz",
|
||||||
|
"integrity": "sha512-MdSJnBjl+bdwkLskZ3NGFp9YcXGx5ggLpQQPqtgakVhsWK0hTtNYhjpZLlWQTviGTvF8at+Bvli3jV7faPdgeQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/types": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/babel__template": {
|
||||||
|
"version": "7.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.0.tgz",
|
||||||
|
"integrity": "sha512-NTPErx4/FiPCGScH7foPyr+/1Dkzkni+rHiYHHoTjvwou7AQzJkNeD60A9CXRy+ZEN2B1bggmkTMCDb+Mv5k+A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/parser": "^7.1.0",
|
||||||
|
"@babel/types": "^7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/babel__traverse": {
|
||||||
|
"version": "7.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.11.0.tgz",
|
||||||
|
"integrity": "sha512-kSjgDMZONiIfSH1Nxcr5JIRMwUetDki63FSQfpTCz8ogF3Ulqm8+mr5f78dUYs6vMiB6gBusQqfQmBvHZj/lwg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@babel/types": "^7.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/color-name": {
|
"@types/color-name": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
||||||
|
32
package.json
32
package.json
@ -1,9 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "bluemap",
|
"name": "bluemap",
|
||||||
"description": "A Minecraft mapping tool that creates 3D models of your Minecraft worlds and displays them in a web viewer.",
|
"version": "0.0.0",
|
||||||
|
"description": "A library to load and display Minecraft maps generated by BlueMap.",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/BlueMap-Minecraft/BlueMap.git"
|
"url": "https://github.com/BlueMap-Minecraft/BlueMap.git"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"minecraft",
|
"minecraft",
|
||||||
@ -13,27 +14,28 @@
|
|||||||
"webgl",
|
"webgl",
|
||||||
"bluemap"
|
"bluemap"
|
||||||
],
|
],
|
||||||
"author": "Blue (Lukas Rieger)",
|
"author": "Lukas Rieger <contact@bluecolored.de> (https://bluecolored.de/)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/BlueMap-Minecraft/BlueMap/issues"
|
"url": "https://github.com/BlueMap-Minecraft/BlueMap/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://bluecolo.red/bluemap",
|
"homepage": "https://bluecolo.red/bluemap",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"three": "^0.123.0",
|
"three": "~0.123.0",
|
||||||
"hammerjs": "^2.0.8"
|
"hammerjs": "~2.0.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.11.6",
|
"@babel/core": "~7.11.6",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.10.4",
|
"@babel/plugin-proposal-class-properties": "~7.10.4",
|
||||||
"@babel/polyfill": "^7.11.5",
|
"@babel/polyfill": "~7.11.5",
|
||||||
"@babel/preset-env": "^7.11.5",
|
"@babel/preset-env": "~7.11.5",
|
||||||
"@rollup/plugin-babel": "^5.2.1",
|
"@types/babel__core": "~7.1.9",
|
||||||
"concurrently": "^5.3.0",
|
"@rollup/plugin-babel": "~5.2.1",
|
||||||
"copyfiles": "^2.3.0",
|
"concurrently": "~5.3.0",
|
||||||
"http-server": "^0.12.3",
|
"copyfiles": "~2.3.0",
|
||||||
"rollup": "^2.28.2",
|
"http-server": "~0.12.3",
|
||||||
"rollup-plugin-terser": "^7.0.2"
|
"rollup": "~2.28.2",
|
||||||
|
"rollup-plugin-terser": "~7.0.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c",
|
"build": "rollup -c",
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
</head>
|
</head>
|
||||||
<body style="margin: 0; padding: 0;">
|
<body style="margin: 0; padding: 0;">
|
||||||
<div id="map-container" style="position: absolute; width: 100%; height: 100%;"></div>
|
<div id="map-container" style="position: absolute; width: 100%; height: 100%;"></div>
|
||||||
<!--<div id="debug-div" style="position: fixed; top: 10px; left: 10px; background-color: #111; opacity: 0.8; color: white; padding: 10px"></div>-->
|
|
||||||
|
|
||||||
<script type="text/javascript" src="js/three.js"></script>
|
<script type="text/javascript" src="js/three.js"></script>
|
||||||
<script type="text/javascript" src="js/hammer.js"></script>
|
<script type="text/javascript" src="js/hammer.js"></script>
|
||||||
@ -20,14 +19,53 @@
|
|||||||
// show stats panel
|
// show stats panel
|
||||||
bluemap.stats.showPanel(1);
|
bluemap.stats.showPanel(1);
|
||||||
|
|
||||||
let mapControls = bluemap.controlsManager.controls;
|
let mapControls = new BlueMap.MapControls(bluemap.rootElement);
|
||||||
let freeControls = new BlueMap.FreeFlightControls(bluemap.rootElement);
|
let freeControls = new BlueMap.FreeFlightControls(bluemap.rootElement);
|
||||||
|
bluemap.controlsManager.controls = mapControls;
|
||||||
|
|
||||||
// load map
|
// load map
|
||||||
|
const loadMaps = (dataUrl, events = null) => {
|
||||||
|
function loadSettings() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let loader = new THREE.FileLoader();
|
||||||
|
loader.setResponseType("json");
|
||||||
|
loader.load(dataUrl + "settings.json",
|
||||||
|
resolve,
|
||||||
|
() => {},
|
||||||
|
() => reject("Failed to load the settings.json!")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadSettings().then(settings => {
|
||||||
|
let maps = [];
|
||||||
|
|
||||||
|
// create maps
|
||||||
|
if (settings.maps !== undefined){
|
||||||
|
for (let mapId in settings.maps) {
|
||||||
|
if (!settings.maps.hasOwnProperty(mapId)) continue;
|
||||||
|
|
||||||
|
let mapSettings = settings.maps[mapId];
|
||||||
|
if (mapSettings.enabled)
|
||||||
|
maps.push(new BlueMap.Map(mapId, dataUrl + mapId + "/", dataUrl + "settings.json", dataUrl + "textures.json", events));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort maps
|
||||||
|
maps.sort((map1, map2) => {
|
||||||
|
let sort = settings.maps[map1.id].ordinal - settings.maps[map2.id].ordinal;
|
||||||
|
if (isNaN(sort)) return 0;
|
||||||
|
return sort;
|
||||||
|
});
|
||||||
|
|
||||||
|
return maps;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let maps = [];
|
let maps = [];
|
||||||
let markerManager = null;
|
let markerManager = null;
|
||||||
let playerManager = null;
|
let playerManager = null;
|
||||||
BlueMap.loadMaps("data/", bluemap.events).then(loadedMaps => {
|
loadMaps("data/", bluemap.events).then(loadedMaps => {
|
||||||
maps = loadedMaps;
|
maps = loadedMaps;
|
||||||
|
|
||||||
markerManager = new BlueMap.MarkerFileManager(bluemap.markerScene, "data/markers.json", maps[0].id, bluemap.events);
|
markerManager = new BlueMap.MarkerFileManager(bluemap.markerScene, "data/markers.json", maps[0].id, bluemap.events);
|
||||||
@ -38,7 +76,7 @@
|
|||||||
playerManager.update();
|
playerManager.update();
|
||||||
playerManager.setAutoUpdateInterval(1000);
|
playerManager.setAutoUpdateInterval(1000);
|
||||||
|
|
||||||
bluemap.setMap(maps[0]).then(() => {
|
bluemap.switchMap(maps[0]).then(() => {
|
||||||
playerManager.worldId = maps[0].world;
|
playerManager.worldId = maps[0].world;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,58 +1,31 @@
|
|||||||
import {FileLoader, Object3D} from "three";
|
import {Object3D} from "three";
|
||||||
import {Map} from "./map/Map";
|
|
||||||
|
|
||||||
export * from "./MapViewer";
|
export * from "./MapViewer";
|
||||||
|
|
||||||
|
export * from "./map/Map";
|
||||||
|
export * from "./map/Tile";
|
||||||
|
export * from "./map/TileLoader";
|
||||||
|
export * from "./map/TileManager";
|
||||||
|
export * from "./map/TileMap";
|
||||||
|
|
||||||
|
export * from "./markers/ExtrudeMarker";
|
||||||
|
export * from "./markers/HtmlMarker";
|
||||||
|
export * from "./markers/LineMarker";
|
||||||
|
export * from "./markers/Marker";
|
||||||
export * from "./markers/MarkerFileManager";
|
export * from "./markers/MarkerFileManager";
|
||||||
|
export * from "./markers/MarkerManager";
|
||||||
|
export * from "./markers/MarkerSet";
|
||||||
|
export * from "./markers/ObjectMarker";
|
||||||
|
export * from "./markers/PlayerMarker";
|
||||||
export * from "./markers/PlayerMarkerManager";
|
export * from "./markers/PlayerMarkerManager";
|
||||||
|
export * from "./markers/PoiMarker";
|
||||||
|
export * from "./markers/ShapeMarker";
|
||||||
|
|
||||||
export * from "./controls/map/MapControls";
|
export * from "./controls/map/MapControls";
|
||||||
export * from "./controls/freeflight/FreeFlightControls";
|
export * from "./controls/freeflight/FreeFlightControls";
|
||||||
|
|
||||||
/**
|
export * from "./util/CombinedCamera";
|
||||||
* Loads and returns a promise with an array of Maps loaded from that root-path.<br>
|
export * from "./util/Utils";
|
||||||
* <b>DONT FORGET TO dispose() ALL MAPS RETURNED BY THIS METHOD IF YOU DONT NEED THEM ANYMORE!</b>
|
|
||||||
* @param dataUrl {string}
|
|
||||||
* @param events {EventTarget}
|
|
||||||
* @returns {Promise<Map[]>}
|
|
||||||
*/
|
|
||||||
export const loadMaps = (dataUrl, events = null) => {
|
|
||||||
|
|
||||||
function loadSettings() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let loader = new FileLoader();
|
|
||||||
loader.setResponseType("json");
|
|
||||||
loader.load(dataUrl + "settings.json",
|
|
||||||
resolve,
|
|
||||||
() => {},
|
|
||||||
() => reject("Failed to load the settings.json!")
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return loadSettings().then(settings => {
|
|
||||||
let maps = [];
|
|
||||||
|
|
||||||
// create maps
|
|
||||||
if (settings.maps !== undefined){
|
|
||||||
for (let mapId in settings.maps) {
|
|
||||||
if (!settings.maps.hasOwnProperty(mapId)) continue;
|
|
||||||
|
|
||||||
let mapSettings = settings.maps[mapId];
|
|
||||||
if (mapSettings.enabled)
|
|
||||||
maps.push(new Map(mapId, dataUrl + mapId + "/", events));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort maps
|
|
||||||
maps.sort((map1, map2) => {
|
|
||||||
let sort = settings.maps[map1.id].ordinal - settings.maps[map2.id].ordinal;
|
|
||||||
if (isNaN(sort)) return 0;
|
|
||||||
return sort;
|
|
||||||
});
|
|
||||||
|
|
||||||
return maps;
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param event {object}
|
* @param event {object}
|
||||||
|
159
src/MapViewer.js
159
src/MapViewer.js
@ -1,8 +1,7 @@
|
|||||||
import {Layers, PerspectiveCamera, Raycaster, Scene, Vector2, WebGLRenderer} from "three";
|
import {PerspectiveCamera, Raycaster, Scene, Vector2, WebGLRenderer} from "three";
|
||||||
import {Map} from "./map/Map";
|
import {Map} from "./map/Map";
|
||||||
import {SkyboxScene} from "./skybox/SkyboxScene";
|
import {SkyboxScene} from "./skybox/SkyboxScene";
|
||||||
import {ControlsManager} from "./controls/ControlsManager";
|
import {ControlsManager} from "./controls/ControlsManager";
|
||||||
import {MapControls} from "./controls/map/MapControls";
|
|
||||||
import Stats from "./util/Stats";
|
import Stats from "./util/Stats";
|
||||||
import {alert, dispatchEvent, elementOffset, htmlToElement} from "./util/Utils";
|
import {alert, dispatchEvent, elementOffset, htmlToElement} from "./util/Utils";
|
||||||
import {TileManager} from "./map/TileManager";
|
import {TileManager} from "./map/TileManager";
|
||||||
@ -12,30 +11,19 @@ import {LOWRES_VERTEX_SHADER} from "./map/lowres/LowresVertexShader";
|
|||||||
import {LOWRES_FRAGMENT_SHADER} from "./map/lowres/LowresFragmentShader";
|
import {LOWRES_FRAGMENT_SHADER} from "./map/lowres/LowresFragmentShader";
|
||||||
import {CombinedCamera} from "./util/CombinedCamera";
|
import {CombinedCamera} from "./util/CombinedCamera";
|
||||||
import {CSS2DRenderer} from "./util/CSS2DRenderer";
|
import {CSS2DRenderer} from "./util/CSS2DRenderer";
|
||||||
import {FreeFlightControls} from "./controls/freeflight/FreeFlightControls";
|
|
||||||
|
|
||||||
export class MapViewer {
|
export class MapViewer {
|
||||||
|
|
||||||
static InteractionType = {
|
|
||||||
LEFTCLICK: 0,
|
|
||||||
RIGHTCLICK: 1
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param element {Element}
|
* @param element {Element}
|
||||||
* @param dataUrl {string}
|
|
||||||
* @param liveApiUrl {string}
|
|
||||||
* @param events {EventTarget}
|
* @param events {EventTarget}
|
||||||
*/
|
*/
|
||||||
constructor(element, dataUrl = "data/", liveApiUrl = "live/", events = element) {
|
constructor(element, events = element) {
|
||||||
Object.defineProperty( this, 'isMapViewer', { value: true } );
|
Object.defineProperty( this, 'isMapViewer', { value: true } );
|
||||||
|
|
||||||
this.rootElement = element;
|
this.rootElement = element;
|
||||||
this.events = events;
|
this.events = events;
|
||||||
|
|
||||||
this.dataUrl = dataUrl;
|
|
||||||
this.liveApiUrl = liveApiUrl;
|
|
||||||
|
|
||||||
this.stats = new Stats();
|
this.stats = new Stats();
|
||||||
this.stats.hide();
|
this.stats.hide();
|
||||||
|
|
||||||
@ -77,11 +65,7 @@ export class MapViewer {
|
|||||||
this.camera = new CombinedCamera(75, 1, 0.1, 10000, 0);
|
this.camera = new CombinedCamera(75, 1, 0.1, 10000, 0);
|
||||||
this.skyboxCamera = new PerspectiveCamera(75, 1, 0.1, 10000);
|
this.skyboxCamera = new PerspectiveCamera(75, 1, 0.1, 10000);
|
||||||
|
|
||||||
this.hammer = new Hammer.Manager(this.rootElement);
|
|
||||||
this.initializeHammer();
|
|
||||||
|
|
||||||
this.controlsManager = new ControlsManager(this, this.camera);
|
this.controlsManager = new ControlsManager(this, this.camera);
|
||||||
this.controlsManager.controls = new MapControls(this.rootElement);
|
|
||||||
|
|
||||||
this.raycaster = new Raycaster();
|
this.raycaster = new Raycaster();
|
||||||
this.raycaster.layers.enableAll();
|
this.raycaster.layers.enableAll();
|
||||||
@ -97,31 +81,13 @@ export class MapViewer {
|
|||||||
// initialize
|
// initialize
|
||||||
this.initializeRootElement();
|
this.initializeRootElement();
|
||||||
|
|
||||||
// handle some events
|
// handle window resizes
|
||||||
window.addEventListener("resize", this.handleContainerResize);
|
window.addEventListener("resize", this.handleContainerResize);
|
||||||
|
|
||||||
// start render-loop
|
// start render-loop
|
||||||
requestAnimationFrame(this.renderLoop);
|
requestAnimationFrame(this.renderLoop);
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeHammer() {
|
|
||||||
let touchTap = new Hammer.Tap({ event: 'tap', pointers: 1, taps: 1, threshold: 2 });
|
|
||||||
let touchMove = new Hammer.Pan({ event: 'move', direction: Hammer.DIRECTION_ALL, threshold: 0 });
|
|
||||||
let touchTilt = new Hammer.Pan({ event: 'tilt', direction: Hammer.DIRECTION_VERTICAL, pointers: 2, threshold: 0 });
|
|
||||||
let touchRotate = new Hammer.Rotate({ event: 'rotate', pointers: 2, threshold: 10 });
|
|
||||||
let touchZoom = new Hammer.Pinch({ event: 'zoom', pointers: 2, threshold: 0 });
|
|
||||||
|
|
||||||
touchTilt.recognizeWith(touchRotate);
|
|
||||||
touchTilt.recognizeWith(touchZoom);
|
|
||||||
touchRotate.recognizeWith(touchZoom);
|
|
||||||
|
|
||||||
this.hammer.add(touchTap);
|
|
||||||
this.hammer.add(touchMove);
|
|
||||||
this.hammer.add(touchTilt);
|
|
||||||
this.hammer.add(touchRotate);
|
|
||||||
this.hammer.add(touchZoom);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the root-element
|
* Initializes the root-element
|
||||||
*/
|
*/
|
||||||
@ -129,14 +95,7 @@ export class MapViewer {
|
|||||||
this.rootElement.innerHTML = "";
|
this.rootElement.innerHTML = "";
|
||||||
|
|
||||||
let outerDiv = htmlToElement(`<div style="position: relative; width: 100%; height: 100%; overflow: hidden;"></div>`);
|
let outerDiv = htmlToElement(`<div style="position: relative; width: 100%; height: 100%; overflow: hidden;"></div>`);
|
||||||
this.rootElement.appendChild(outerDiv)
|
this.rootElement.appendChild(outerDiv);
|
||||||
this.hammer.on('tap', event => {
|
|
||||||
let rootOffset = elementOffset(this.rootElement);
|
|
||||||
this.handleMapInteraction(new Vector2(
|
|
||||||
((event.center.x - rootOffset.top) / this.rootElement.clientWidth) * 2 - 1,
|
|
||||||
-((event.center.y - rootOffset.left) / this.rootElement.clientHeight) * 2 + 1
|
|
||||||
));
|
|
||||||
});
|
|
||||||
|
|
||||||
// 3d-canvas
|
// 3d-canvas
|
||||||
outerDiv.appendChild(this.renderer.domElement);
|
outerDiv.appendChild(this.renderer.domElement);
|
||||||
@ -168,46 +127,58 @@ export class MapViewer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param screenPos {{x: number, y:number}}
|
* Triggers an interaction on the screen (map), e.g. a mouse-click.
|
||||||
* @param interactionType {number}
|
*
|
||||||
|
* This will first attempt to invoke the onClick() method on the Object3D (e.g. Markers) that has been clicked.
|
||||||
|
* And if none of those consumed the event, it will fire a <code>bluemapMapInteraction</code> event.
|
||||||
|
*
|
||||||
|
* @param screenPosition {Vector2} - Clicked position on the screen (usually event.x, event.y)
|
||||||
|
* @param data {object} - Custom event data that will be added to the interaction-event
|
||||||
*/
|
*/
|
||||||
handleMapInteraction(screenPos, interactionType = MapViewer.InteractionType.LEFTCLICK) {
|
handleMapInteraction(screenPosition, data = {}) {
|
||||||
|
let rootOffset = elementOffset(this.rootElement);
|
||||||
|
let normalizedScreenPos = new Vector2(
|
||||||
|
((screenPosition.x - rootOffset.top) / this.rootElement.clientWidth) * 2 - 1,
|
||||||
|
-((screenPosition.y - rootOffset.left) / this.rootElement.clientHeight) * 2 + 1
|
||||||
|
);
|
||||||
|
|
||||||
if (this.map && this.map.isLoaded){
|
if (this.map && this.map.isLoaded){
|
||||||
this.raycaster.setFromCamera(screenPos, this.camera);
|
this.raycaster.setFromCamera(normalizedScreenPos, this.camera);
|
||||||
|
|
||||||
let lowresLayer = new Layers();
|
// check Object3D interactions
|
||||||
lowresLayer.set(2);
|
let intersects = this.raycaster.intersectObjects([this.map.hiresTileManager.scene, this.map.lowresTileManager.scene, this.markerScene], true);
|
||||||
|
|
||||||
// check marker interactions
|
|
||||||
let intersects = this.raycaster.intersectObjects([this.map.scene, this.markerScene], true);
|
|
||||||
let covered = false;
|
let covered = false;
|
||||||
for (let i = 0; i < intersects.length; i++) {
|
for (let i = 0; i < intersects.length; i++) {
|
||||||
if (intersects[i].object){
|
if (intersects[i].object){
|
||||||
let object = intersects[i].object;
|
let object = intersects[i].object;
|
||||||
|
|
||||||
if (object.visible) {
|
if (object.visible) {
|
||||||
if (!covered || (object.material && !object.material.depthTest)) {
|
if (!covered || (object.material && !object.material.depthTest)) {
|
||||||
if (object.onClick({
|
if (object.onClick({
|
||||||
interactionType: interactionType,
|
data: data,
|
||||||
intersection: intersects[i]
|
intersection: intersects[i]
|
||||||
})) return;
|
})) return;
|
||||||
covered = true;
|
}
|
||||||
} else if (!intersects[i].object.layers.test(lowresLayer)) {
|
|
||||||
|
let parentRoot = object;
|
||||||
|
while(parentRoot.parent) parentRoot = parentRoot.parent;
|
||||||
|
if (parentRoot !== this.map.lowresTileManager.scene) {
|
||||||
covered = true;
|
covered = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fire event
|
||||||
|
dispatchEvent(this.events, "bluemapMapInteraction", {
|
||||||
|
data: data,
|
||||||
|
intersections: intersects
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLoadedMapArea = () => {
|
|
||||||
if (!this.map) return;
|
|
||||||
|
|
||||||
this.map.loadMapArea(this.loadedCenter.x, this.loadedCenter.y, this.loadedHiresViewDistance, this.loadedLowresViewDistance);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @private
|
||||||
* The render-loop to update and possibly render a new frame.
|
* The render-loop to update and possibly render a new frame.
|
||||||
* @param now {number} the current time in milliseconds
|
* @param now {number} the current time in milliseconds
|
||||||
*/
|
*/
|
||||||
@ -235,6 +206,7 @@ export class MapViewer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @private
|
||||||
* Renders a frame
|
* Renders a frame
|
||||||
* @param delta {number}
|
* @param delta {number}
|
||||||
*/
|
*/
|
||||||
@ -254,25 +226,16 @@ export class MapViewer {
|
|||||||
this.renderer.render(this.skyboxScene, this.skyboxCamera);
|
this.renderer.render(this.skyboxScene, this.skyboxCamera);
|
||||||
this.renderer.clearDepth();
|
this.renderer.clearDepth();
|
||||||
|
|
||||||
/*
|
|
||||||
Layers:
|
|
||||||
0 - always visible objects
|
|
||||||
1 - hires layer
|
|
||||||
2 - lowres layer
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (this.map && this.map.isLoaded) {
|
if (this.map && this.map.isLoaded) {
|
||||||
//update uniforms
|
//update uniforms
|
||||||
this.uniforms.hiresTileMap.value.pos.copy(this.map.hiresTileManager.centerTile);
|
this.uniforms.hiresTileMap.value.pos.copy(this.map.hiresTileManager.centerTile);
|
||||||
|
|
||||||
this.camera.layers.set(2);
|
this.renderer.render(this.map.lowresTileManager.scene, this.camera);
|
||||||
this.renderer.render(this.map.scene, this.camera);
|
|
||||||
this.renderer.clearDepth();
|
this.renderer.clearDepth();
|
||||||
this.camera.layers.set(0);
|
|
||||||
if (this.controlsManager.distance < 2000) this.camera.layers.enable(1);
|
if (this.controlsManager.distance < 2000) {
|
||||||
this.renderer.render(this.map.scene, this.camera);
|
this.renderer.render(this.map.hiresTileManager.scene, this.camera);
|
||||||
//this.renderer.render(this.map.markerManager.objectMarkerScene, this.camera);
|
}
|
||||||
//this.css2dRenderer.render(this.map.markerManager.elementMarkerScene, this.camera);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// render markers
|
// render markers
|
||||||
@ -285,7 +248,7 @@ export class MapViewer {
|
|||||||
* @param map {Map}
|
* @param map {Map}
|
||||||
* @returns Promise<void>
|
* @returns Promise<void>
|
||||||
*/
|
*/
|
||||||
setMap(map = null) {
|
switchMap(map = null) {
|
||||||
if (this.map && this.map.isMap) this.map.unload();
|
if (this.map && this.map.isMap) this.map.unload();
|
||||||
|
|
||||||
this.map = map;
|
this.map = map;
|
||||||
@ -316,6 +279,7 @@ export class MapViewer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Loads the given area on the map (and unloads everything outside that area)
|
||||||
* @param centerX {number}
|
* @param centerX {number}
|
||||||
* @param centerZ {number}
|
* @param centerZ {number}
|
||||||
* @param hiresViewDistance {number}
|
* @param hiresViewDistance {number}
|
||||||
@ -329,6 +293,14 @@ export class MapViewer {
|
|||||||
this.updateLoadedMapArea();
|
this.updateLoadedMapArea();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
updateLoadedMapArea = () => {
|
||||||
|
if (!this.map) return;
|
||||||
|
this.map.loadMapArea(this.loadedCenter.x, this.loadedCenter.y, this.loadedHiresViewDistance, this.loadedLowresViewDistance);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
@ -344,35 +316,4 @@ export class MapViewer {
|
|||||||
this.handleContainerResize();
|
this.handleContainerResize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Applies a loaded settings-object (settings.json)
|
|
||||||
* @param settings {{maps: {}}}
|
|
||||||
*/
|
|
||||||
applySettings(settings) {
|
|
||||||
|
|
||||||
// reset maps
|
|
||||||
this.maps.forEach(map => map.dispose());
|
|
||||||
this.maps = [];
|
|
||||||
|
|
||||||
// create maps
|
|
||||||
if (settings.maps !== undefined){
|
|
||||||
for (let mapId in settings.maps) {
|
|
||||||
if (!settings.maps.hasOwnProperty(mapId)) continue;
|
|
||||||
|
|
||||||
let mapSettings = settings.maps[mapId];
|
|
||||||
if (mapSettings.enabled)
|
|
||||||
this.maps.push(new Map(mapId, this.dataUrl + mapId + "/", this.rootElement));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort maps
|
|
||||||
this.maps.sort((map1, map2) => {
|
|
||||||
let sort = settings.maps[map1.id].ordinal - settings.maps[map2.id].ordinal;
|
|
||||||
if (isNaN(sort)) return 0;
|
|
||||||
return sort;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ export class ControlsManager {
|
|||||||
if (this.mapViewer.map) {
|
if (this.mapViewer.map) {
|
||||||
let triggerDistance = 1;
|
let triggerDistance = 1;
|
||||||
if (valueChanged) {
|
if (valueChanged) {
|
||||||
triggerDistance = this.mapViewer.loadedLowresViewDistance * 0.8;
|
triggerDistance = this.mapViewer.loadedLowresViewDistance * 0.5;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
Math.abs(this.lastMapUpdatePosition.x - this.position.x) >= triggerDistance ||
|
Math.abs(this.lastMapUpdatePosition.x - this.position.x) >= triggerDistance ||
|
||||||
@ -128,6 +128,15 @@ export class ControlsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers an interaction on the screen (map), e.g. a mouse-click
|
||||||
|
* @param screenPosition {THREE.Vector2} - Clicked position on the screen (usually event.x, event.y)
|
||||||
|
* @param data {object} - Custom event data that will be added to the interaction-event
|
||||||
|
*/
|
||||||
|
handleMapInteraction(screenPosition, data = {}) {
|
||||||
|
this.mapViewer.handleMapInteraction(screenPosition, data);
|
||||||
|
}
|
||||||
|
|
||||||
isValueChanged() {
|
isValueChanged() {
|
||||||
return !(
|
return !(
|
||||||
this.position.equals(this.lastPosition) &&
|
this.position.equals(this.lastPosition) &&
|
||||||
|
@ -75,6 +75,11 @@ export class FreeFlightControls {
|
|||||||
this.mouseAngle.stop();
|
this.mouseAngle.stop();
|
||||||
this.touchPan.stop();
|
this.touchPan.stop();
|
||||||
|
|
||||||
|
this.target.removeEventListener("contextmenu", this.onContextMenu);
|
||||||
|
this.target.removeEventListener("mousedown", this.onMouseDown);
|
||||||
|
this.target.removeEventListener("mouseup", this.onMouseUp);
|
||||||
|
window.removeEventListener("wheel", this.onWheel);
|
||||||
|
|
||||||
this.started = false;
|
this.started = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,24 +103,8 @@ export class FreeFlightControls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initializeHammer() {
|
initializeHammer() {
|
||||||
let touchTap = new Hammer.Tap({ event: 'tap', pointers: 1, taps: 1, threshold: 2 });
|
|
||||||
let touchMove = new Hammer.Pan({ event: 'move', pointers: 1, direction: Hammer.DIRECTION_ALL, threshold: 0 });
|
let touchMove = new Hammer.Pan({ event: 'move', pointers: 1, direction: Hammer.DIRECTION_ALL, threshold: 0 });
|
||||||
let touchTilt = new Hammer.Pan({ event: 'tilt', pointers: 2, direction: Hammer.DIRECTION_VERTICAL, threshold: 0 });
|
|
||||||
let touchRotate = new Hammer.Rotate({ event: 'rotate', pointers: 2, threshold: 0 });
|
|
||||||
let touchZoom = new Hammer.Pinch({ event: 'zoom', pointers: 2, threshold: 0 });
|
|
||||||
|
|
||||||
touchMove.recognizeWith(touchRotate);
|
|
||||||
touchMove.recognizeWith(touchTilt);
|
|
||||||
touchMove.recognizeWith(touchZoom);
|
|
||||||
touchTilt.recognizeWith(touchRotate);
|
|
||||||
touchTilt.recognizeWith(touchZoom);
|
|
||||||
touchRotate.recognizeWith(touchZoom);
|
|
||||||
|
|
||||||
this.hammer.add(touchTap);
|
|
||||||
this.hammer.add(touchTilt);
|
|
||||||
this.hammer.add(touchMove);
|
this.hammer.add(touchMove);
|
||||||
this.hammer.add(touchRotate);
|
|
||||||
this.hammer.add(touchZoom);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onContextMenu = evt => {
|
onContextMenu = evt => {
|
||||||
|
@ -2,7 +2,7 @@ import {MouseMoveControls} from "./mouse/MouseMoveControls";
|
|||||||
import {MouseZoomControls} from "./mouse/MouseZoomControls";
|
import {MouseZoomControls} from "./mouse/MouseZoomControls";
|
||||||
import {MouseRotateControls} from "./mouse/MouseRotateControls";
|
import {MouseRotateControls} from "./mouse/MouseRotateControls";
|
||||||
import {MouseAngleControls} from "./mouse/MouseAngleControls";
|
import {MouseAngleControls} from "./mouse/MouseAngleControls";
|
||||||
import {MathUtils} from "three";
|
import {MathUtils, Vector2} from "three";
|
||||||
import {animate, EasingFunctions, softClamp, softMin} from "../../util/Utils";
|
import {animate, EasingFunctions, softClamp, softMin} from "../../util/Utils";
|
||||||
import {MapHeightControls} from "./MapHeightControls";
|
import {MapHeightControls} from "./MapHeightControls";
|
||||||
import {KeyMoveControls} from "./keyboard/KeyMoveControls";
|
import {KeyMoveControls} from "./keyboard/KeyMoveControls";
|
||||||
@ -23,6 +23,8 @@ export class MapControls {
|
|||||||
*/
|
*/
|
||||||
constructor(rootElement) {
|
constructor(rootElement) {
|
||||||
this.rootElement = rootElement;
|
this.rootElement = rootElement;
|
||||||
|
|
||||||
|
/** @type {ControlsManager} */
|
||||||
this.manager = null;
|
this.manager = null;
|
||||||
|
|
||||||
this.started = false;
|
this.started = false;
|
||||||
@ -58,6 +60,7 @@ export class MapControls {
|
|||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
|
|
||||||
this.rootElement.addEventListener("contextmenu", this.onContextMenu);
|
this.rootElement.addEventListener("contextmenu", this.onContextMenu);
|
||||||
|
this.hammer.on("tap", this.onTap);
|
||||||
|
|
||||||
this.mouseMove.start(manager);
|
this.mouseMove.start(manager);
|
||||||
this.mouseRotate.start(manager);
|
this.mouseRotate.start(manager);
|
||||||
@ -97,6 +100,7 @@ export class MapControls {
|
|||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
this.rootElement.removeEventListener("contextmenu", this.onContextMenu);
|
this.rootElement.removeEventListener("contextmenu", this.onContextMenu);
|
||||||
|
this.hammer.off("tap", this.onTap);
|
||||||
|
|
||||||
this.mouseMove.stop();
|
this.mouseMove.stop();
|
||||||
this.mouseRotate.stop();
|
this.mouseRotate.stop();
|
||||||
@ -238,4 +242,8 @@ export class MapControls {
|
|||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onTap = evt => {
|
||||||
|
this.manager.handleMapInteraction(new Vector2(evt.center.x, evt.center.y));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -6,9 +6,11 @@ export class KeyZoomControls {
|
|||||||
static KEYS = {
|
static KEYS = {
|
||||||
IN: [
|
IN: [
|
||||||
new KeyCombination("NumpadAdd"),
|
new KeyCombination("NumpadAdd"),
|
||||||
|
new KeyCombination("Insert"),
|
||||||
],
|
],
|
||||||
OUT: [
|
OUT: [
|
||||||
new KeyCombination("NumpadSubtract"),
|
new KeyCombination("NumpadSubtract"),
|
||||||
|
new KeyCombination("Home"),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,8 +52,8 @@ export class KeyZoomControls {
|
|||||||
* @param map {Map}
|
* @param map {Map}
|
||||||
*/
|
*/
|
||||||
update(delta, map) {
|
update(delta, map) {
|
||||||
if (this.in) this.deltaZoom += 1;
|
if (this.in) this.deltaZoom -= 1;
|
||||||
if (this.out) this.deltaZoom -= 1;
|
if (this.out) this.deltaZoom += 1;
|
||||||
|
|
||||||
if (this.deltaZoom === 0) return;
|
if (this.deltaZoom === 0) return;
|
||||||
|
|
||||||
|
@ -14,15 +14,20 @@ export class Map {
|
|||||||
/**
|
/**
|
||||||
* @param id {string}
|
* @param id {string}
|
||||||
* @param dataUrl {string}
|
* @param dataUrl {string}
|
||||||
|
* @param settingsUrl {string}
|
||||||
|
* @param texturesUrl {string}
|
||||||
* @param events {EventTarget}
|
* @param events {EventTarget}
|
||||||
*/
|
*/
|
||||||
constructor(id, dataUrl, events = null) {
|
constructor(id, dataUrl, settingsUrl, texturesUrl, events = null) {
|
||||||
Object.defineProperty( this, 'isMap', { value: true } );
|
Object.defineProperty( this, 'isMap', { value: true } );
|
||||||
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.events = events;
|
this.events = events;
|
||||||
this.dataUrl = dataUrl;
|
this.dataUrl = dataUrl;
|
||||||
|
|
||||||
|
this.settingsUrl = settingsUrl;
|
||||||
|
this.texturesUrl = texturesUrl;
|
||||||
|
|
||||||
this.name = this.id;
|
this.name = this.id;
|
||||||
this.world = "-";
|
this.world = "-";
|
||||||
|
|
||||||
@ -41,9 +46,6 @@ export class Map {
|
|||||||
translate: {x: 2, z: 2}
|
translate: {x: 2, z: 2}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.scene = new Scene();
|
|
||||||
this.scene.autoUpdate = false;
|
|
||||||
|
|
||||||
this.raycaster = new Raycaster();
|
this.raycaster = new Raycaster();
|
||||||
|
|
||||||
/** @type {ShaderMaterial[]} */
|
/** @type {ShaderMaterial[]} */
|
||||||
@ -111,8 +113,11 @@ export class Map {
|
|||||||
|
|
||||||
this.hiresMaterial = this.createHiresMaterial(hiresVertexShader, hiresFragmentShader, uniforms, textures);
|
this.hiresMaterial = this.createHiresMaterial(hiresVertexShader, hiresFragmentShader, uniforms, textures);
|
||||||
|
|
||||||
this.hiresTileManager = new TileManager(this.scene, new TileLoader(`${this.dataUrl}hires/`, this.hiresMaterial, this.hires, 1), this.onTileLoad("hires"), this.onTileUnload("hires"), this.events);
|
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(this.scene, new TileLoader(`${this.dataUrl}lowres/`, this.lowresMaterial, this.lowres, 2), this.onTileLoad("lowres"), this.onTileUnload("lowres"), 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.scene.autoUpdate = false;
|
||||||
|
this.lowresTileManager.scene.autoUpdate = false;
|
||||||
|
|
||||||
alert(this.events, `Map '${this.id}' is loaded.`, "fine");
|
alert(this.events, `Map '${this.id}' is loaded.`, "fine");
|
||||||
});
|
});
|
||||||
@ -165,7 +170,7 @@ export class Map {
|
|||||||
|
|
||||||
let loader = new FileLoader();
|
let loader = new FileLoader();
|
||||||
loader.setResponseType("json");
|
loader.setResponseType("json");
|
||||||
loader.load(this.dataUrl + "../settings.json",
|
loader.load(this.settingsUrl,
|
||||||
settings => {
|
settings => {
|
||||||
if (settings.maps && settings.maps[this.id]) {
|
if (settings.maps && settings.maps[this.id]) {
|
||||||
resolve(settings.maps[this.id]);
|
resolve(settings.maps[this.id]);
|
||||||
@ -189,7 +194,7 @@ export class Map {
|
|||||||
|
|
||||||
let loader = new FileLoader();
|
let loader = new FileLoader();
|
||||||
loader.setResponseType("json");
|
loader.setResponseType("json");
|
||||||
loader.load(this.dataUrl + "../textures.json",
|
loader.load(this.texturesUrl,
|
||||||
resolve,
|
resolve,
|
||||||
() => {},
|
() => {},
|
||||||
() => reject(`Failed to load the textures.json for map: ${this.id}`)
|
() => reject(`Failed to load the textures.json for map: ${this.id}`)
|
||||||
|
@ -45,6 +45,8 @@ export class TileLoader {
|
|||||||
object.position.set(tileX * tileSize.x + translate.x, 0, tileZ * tileSize.z + translate.z);
|
object.position.set(tileX * tileSize.x + translate.x, 0, tileZ * tileSize.z + translate.z);
|
||||||
object.scale.set(scale.x, 1, scale.z);
|
object.scale.set(scale.x, 1, scale.z);
|
||||||
|
|
||||||
|
object.userData.tileUrl = this.tilePath + pathFromCoords(tileX, tileZ) + '.json';
|
||||||
|
|
||||||
object.updateMatrixWorld(true);
|
object.updateMatrixWorld(true);
|
||||||
|
|
||||||
resolve(object);
|
resolve(object);
|
||||||
|
Loading…
Reference in New Issue
Block a user