Improved and generalized DCS maps handling

This commit is contained in:
Pax1601 2024-03-13 15:01:35 +01:00
parent a53cca8dda
commit 0bdf362174
5 changed files with 91 additions and 32 deletions

View File

@ -33,7 +33,7 @@
<div class="ol-group">
<div id="map-type" class="ol-select">
<div class="ol-select-value"><img src="resources/theme/images/icons/map-source.svg" inject-svg /><span
class="ol-select-value-text">ArcGIS Satellite</span></div>
class="ol-select-value-text">DCS Map</span></div>
<div class="ol-select-options">
<!-- Here the available map sources will be listed-->
</div>

View File

@ -154,6 +154,17 @@ export const mapBounds = {
"SinaiMap": { bounds: new LatLngBounds([34.312222, 28.523333], [25.946944, 36.897778]), zoom: 4 },
}
export const DCSMapsZoomLevelsByTheatre: { [key: string]: { minNativeZoom?: number, maxNativeZoom?: number, minZoom?: number }[] } = {
"Syria": [],
"MarianaIslands": [{ minNativeZoom: 1, maxNativeZoom: 13, }, { minNativeZoom: 14, maxNativeZoom: 18, minZoom: 14 }],
"Nevada": [],
"PersianGulf": [],
"Caucasus": [],
"Falklands": [],
"Normandy": [],
"SinaiMap": [],
}
export const defaultMapLayers = {
"ArcGIS Satellite": {
urlTemplate: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
@ -166,29 +177,7 @@ export const defaultMapLayers = {
minZoom: 1,
maxZoom: 20,
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
},
"DCS Marianas Modern": [
{
urlTemplate: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
minZoom: 1,
maxZoom: 19
},
{
urlTemplate: 'http://maps.dcsolympus.com/maps/marianas-modern/{z}/{x}/{y}.png',
minNativeZoom: 1,
maxNativeZoom: 13,
minZoom: 1,
maxZoom: 20
},
{
urlTemplate: 'http://maps.dcsolympus.com/maps/marianas-modern/{z}/{x}/{y}.png',
minNativeZoom: 14,
maxNativeZoom: 16,
minZoom: 14,
maxZoom: 20,
attribution: 'Map extracted by OzDeaDMeaT (DCS Olympus Team)'
}
]
}
}
/* Map constants */

View File

@ -0,0 +1,49 @@
import * as L from "leaflet"
export class DCSLayer extends L.TileLayer {
createTile(coords: L.Coords, done: L.DoneCallback) {
let newDone = (error?: Error, tile?: HTMLElement) => {
if (error === null && tile !== undefined && !tile.classList.contains('filtered')) {
// Create a canvas and set its width and height.
var canvas = document.createElement('canvas');
canvas.setAttribute('width', '256px');
canvas.setAttribute('height', '256px');
// Get the canvas drawing context, and draw the image to it.
var context = canvas.getContext('2d');
if (context) {
context.drawImage(tile as CanvasImageSource, 0, 0, canvas.width, canvas.height);
// Get the canvas image data.
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
// Create a function for preserving a specified colour.
var makeTransparent = function(imageData: ImageData, color: {r: number, g: number, b: number}) {
// Get the pixel data from the source.
var data = imageData.data;
// Iterate through all the pixels.
for (var i = 0; i < data.length; i += 4) {
// Check if the current pixel should have preserved transparency. This simply compares whether the color we passed in is equivalent to our pixel data.
var convert = data[i] > color.r - 5 && data[i] < color.r + 5
&& data[i + 1] > color.g - 5 && data[i + 1] < color.g + 5
&& data[i + 2] > color.b - 5 && data[i + 2] < color.b + 5;
// Either preserve the initial transparency or set the transparency to 0.
data[i + 3] = convert ? 100: data[i + 3];
}
return imageData;
};
// Get the new pixel data and set it to the canvas context.
var newData = makeTransparent(imageData, {r: 26, g: 109, b: 127});
context.putImageData(newData, 0, 0);
(tile as HTMLImageElement).src = canvas.toDataURL();
tile.classList.add('filtered');
}
} else {
return done(error, tile);
}
}
return super.createTile(coords, newDone);
}
}

View File

@ -12,7 +12,7 @@ import { DestinationPreviewMarker } from "./markers/destinationpreviewmarker";
import { TemporaryUnitMarker } from "./markers/temporaryunitmarker";
import { ClickableMiniMap } from "./clickableminimap";
import { SVGInjector } from '@tanem/svg-injector'
import { defaultMapLayers, mapBounds, minimapBoundaries, IDLE, COALITIONAREA_DRAW_POLYGON, MOVE_UNIT, SHOW_UNIT_CONTACTS, HIDE_GROUP_MEMBERS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, SHOW_UNIT_LABELS, SHOW_UNITS_ENGAGEMENT_RINGS, SHOW_UNITS_ACQUISITION_RINGS, HIDE_UNITS_SHORT_RANGE_RINGS, FILL_SELECTED_RING, MAP_MARKER_CONTROLS, DCS_LINK_PORT } from "../constants/constants";
import { defaultMapLayers, mapBounds, minimapBoundaries, IDLE, COALITIONAREA_DRAW_POLYGON, MOVE_UNIT, SHOW_UNIT_CONTACTS, HIDE_GROUP_MEMBERS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, SHOW_UNIT_LABELS, SHOW_UNITS_ENGAGEMENT_RINGS, SHOW_UNITS_ACQUISITION_RINGS, HIDE_UNITS_SHORT_RANGE_RINGS, FILL_SELECTED_RING, MAP_MARKER_CONTROLS, DCS_LINK_PORT, DCSMapsZoomLevelsByTheatre } from "../constants/constants";
import { CoalitionArea } from "./coalitionarea/coalitionarea";
import { CoalitionAreaContextMenu } from "../contextmenus/coalitionareacontextmenu";
import { DrawingCursor } from "./coalitionarea/drawingcursor";
@ -21,6 +21,7 @@ import { GestureHandling } from "leaflet-gesture-handling";
import { TouchBoxSelect } from "./touchboxselect";
import { DestinationPreviewHandle } from "./markers/destinationpreviewHandle";
import { ContextActionSet } from "../unit/contextactionset";
import { DCSLayer } from "./dcslayer";
var hasTouchScreen = false;
//if ("maxTouchPoints" in navigator)
@ -46,7 +47,7 @@ export type MapMarkerVisibilityControl = {
"toggles": string[],
"tooltip": string
}
export class Map extends L.Map {
#ID: string;
#state: string;
@ -101,6 +102,7 @@ export class Map extends L.Map {
#optionButtons: { [key: string]: HTMLButtonElement[] } = {}
#visibilityOptions: { [key: string]: boolean | string | number } = {}
#hiddenTypes: string[] = [];
#layerName: string = "";
/**
*
@ -126,7 +128,7 @@ export class Map extends L.Map {
this.#ID = ID;
this.setLayer(Object.keys(this.#mapLayers)[0]);
this.setLayer("DCS Map");
/* Minimap */
var minimapLayer = new L.TileLayer(this.#mapLayers[Object.keys(this.#mapLayers)[0]].urlTemplate, { minZoom: 0, maxZoom: 13 });
@ -139,7 +141,8 @@ export class Map extends L.Map {
//L.control.scalenautic({ position: "topright", maxWidth: 300, nautic: true, metric: true, imperial: false }).addTo(this);
/* Map source dropdown */
this.#mapSourceDropdown = new Dropdown("map-type", (layerName: string) => this.setLayer(layerName), this.getLayers());
this.#mapSourceDropdown = new Dropdown("map-type", (layerName: string) => this.setLayer(layerName));
this.#mapSourceDropdown.setOptions(this.getLayers(), null);
/* Visibility options dropdown */
this.#mapVisibilityOptionsDropdown = new Dropdown("map-visibility-options", (value: string) => { });
@ -218,7 +221,7 @@ export class Map extends L.Map {
...this.#mapLayers,
...additionalMaps
}
this.#mapSourceDropdown.setOptions(this.getLayers());
this.#mapSourceDropdown.setOptions(this.getLayers(), null);
}
})
@ -279,23 +282,40 @@ export class Map extends L.Map {
if (this.#layer != null)
this.removeLayer(this.#layer)
let theatre = getApp().getMissionManager()?.getTheatre() ?? "Nevada";
/* Normal or custom layers are handled here */
if (layerName in this.#mapLayers) {
const layerData = this.#mapLayers[layerName];
if (layerData instanceof Array) {
let layers = layerData.map((layer: any) => {
return new L.TileLayer(layer.urlTemplate, layer);
return new L.TileLayer(layer.urlTemplate.replace("{theatre}", theatre.toLowerCase()), layer);
})
this.#layer = new L.LayerGroup(layers);
} else {
this.#layer = new L.TileLayer(layerData.urlTemplate, layerData);
}
/* DCS core layers are handled here */
} else if (["DCS Map", "DCS Satellite"].includes(layerName) ) {
let layerData = this.#mapLayers["ArcGIS Satellite"];
let layers = [new L.TileLayer(layerData.urlTemplate, layerData)];
let template = `https://maps.dcsolympus.com/maps/${layerName === "DCS Map"? "alt": "sat"}-{theatre}-modern/{z}/{x}/{y}.png`;
layers.push(...DCSMapsZoomLevelsByTheatre[theatre].map((nativeZoomLevels: any) => {
return new L.TileLayer(template.replace("{theatre}", theatre.toLowerCase()), {...nativeZoomLevels, maxZoom: 20, crossOrigin: ""});
}));
this.#layer = new L.LayerGroup(layers);
}
this.#layer?.addTo(this);
this.#layerName = layerName;
}
getLayers() {
return Object.keys(this.#mapLayers);
let layers = ["DCS Map", "DCS Satellite"]
layers.push(...Object.keys(this.#mapLayers));
return layers;
}
/* State machine */
@ -471,6 +491,8 @@ export class Map extends L.Map {
const boundaries = this.#getMinimapBoundaries();
this.#miniMapPolyline.setLatLngs(boundaries[theatre as keyof typeof boundaries]);
this.setLayer(this.#layerName);
}
getMiniMapLayerGroup() {

View File

@ -180,7 +180,6 @@ export class MissionManager {
return this.#theatre;
}
getAvailableSpawnPoints() {
if (this.getCommandModeOptions().commandMode === GAME_MASTER)
return Infinity;