diff --git a/client/public/images/icon-temporary.png b/client/public/images/icon-temporary.png new file mode 100644 index 00000000..712221a0 Binary files /dev/null and b/client/public/images/icon-temporary.png differ diff --git a/client/src/controls/mapcontextmenu.ts b/client/src/controls/mapcontextmenu.ts index 8faeddef..bde299e5 100644 --- a/client/src/controls/mapcontextmenu.ts +++ b/client/src/controls/mapcontextmenu.ts @@ -1,5 +1,5 @@ import { LatLng } from "leaflet"; -import { getActiveCoalition, setActiveCoalition } from ".."; +import { getActiveCoalition, getMap, setActiveCoalition } from ".."; import { spawnAircraft, spawnGroundUnit, spawnSmoke } from "../server/server"; import { aircraftDatabase } from "../units/aircraftdatabase"; import { groundUnitsDatabase } from "../units/groundunitsdatabase"; @@ -41,14 +41,20 @@ export class MapContextMenu extends ContextMenu { this.hide(); this.#spawnOptions.coalition = getActiveCoalition(); if (this.#spawnOptions) + { + getMap().addTemporaryMarker(this.#spawnOptions.latlng); spawnAircraft(this.#spawnOptions); + } }); document.addEventListener("contextMenuDeployGroundUnit", () => { this.hide(); this.#spawnOptions.coalition = getActiveCoalition(); if (this.#spawnOptions) + { + getMap().addTemporaryMarker(this.#spawnOptions.latlng); spawnGroundUnit(this.#spawnOptions); + } }); document.addEventListener("contextMenuDeploySmoke", (e: any) => { diff --git a/client/src/map/boxselect.ts b/client/src/map/boxselect.ts index 6161fa88..b285c10a 100644 --- a/client/src/map/boxselect.ts +++ b/client/src/map/boxselect.ts @@ -45,25 +45,28 @@ export var BoxSelect = Handler.extend({ }, _onMouseDown: function (e: any) { - if ((e.which !== 1 && e.button !== 0) || !e.shiftKey) { return false; } + if ((e.which == 1 && e.button == 0 && e.shiftKey)) { - // Clear the deferred resetState if it hasn't executed yet, otherwise it - // will interrupt the interaction and orphan a box element in the container. - this._clearDeferredResetState(); - this._resetState(); + // Clear the deferred resetState if it hasn't executed yet, otherwise it + // will interrupt the interaction and orphan a box element in the container. + this._clearDeferredResetState(); + this._resetState(); - DomUtil.disableTextSelection(); - DomUtil.disableImageDrag(); + DomUtil.disableTextSelection(); + DomUtil.disableImageDrag(); - this._startPoint = this._map.mouseEventToContainerPoint(e); + this._startPoint = this._map.mouseEventToContainerPoint(e); - //@ts-ignore - DomEvent.on(document, { - contextmenu: DomEvent.stop, - mousemove: this._onMouseMove, - mouseup: this._onMouseUp, - keydown: this._onKeyDown - }, this); + //@ts-ignore + DomEvent.on(document, { + contextmenu: DomEvent.stop, + mousemove: this._onMouseMove, + mouseup: this._onMouseUp, + keydown: this._onKeyDown + }, this); + } else { + return false; + } }, _onMouseMove: function (e: any) { diff --git a/client/src/map/map.ts b/client/src/map/map.ts index bac70981..c7bfd727 100644 --- a/client/src/map/map.ts +++ b/client/src/map/map.ts @@ -3,7 +3,7 @@ import { MiniMap, MiniMapOptions } from "leaflet-control-mini-map"; import { getUnitsManager } from ".."; import { BoxSelect } from "./boxselect"; -import { MapContextMenu } from "../controls/mapcontextmenu"; +import { MapContextMenu, SpawnOptions } from "../controls/mapcontextmenu"; import { UnitContextMenu } from "../controls/unitcontextmenu"; import { AirbaseContextMenu } from "../controls/airbasecontextmenu"; import { Dropdown } from "../controls/dropdown"; @@ -18,6 +18,12 @@ export const MOVE_UNIT = "MOVE_UNIT"; L.Map.addInitHook('addHandler', 'boxSelect', BoxSelect); +var temporaryIcon = new L.Icon({ + iconUrl: 'images/icon-temporary.png', + iconSize: [52, 52], + iconAnchor: [26, 26] +}); + export class ClickableMiniMap extends MiniMap { constructor(layer: L.TileLayer | L.LayerGroup, options?: MiniMapOptions) { super(layer, options); @@ -44,6 +50,7 @@ export class Map extends L.Map { #centerUnit: Unit | null = null; #miniMap: ClickableMiniMap | null = null; #miniMapLayerGroup: L.LayerGroup; + #temporaryMarkers: L.Marker[] = []; #mapContextMenu: MapContextMenu = new MapContextMenu("map-contextmenu"); #unitContextMenu: UnitContextMenu = new UnitContextMenu("unit-contextmenu"); @@ -372,6 +379,31 @@ export class Map extends L.Map { } } + addTemporaryMarker(latlng: L.LatLng) { + var marker = new L.Marker(latlng, {icon: temporaryIcon}); + marker.addTo(this); + this.#temporaryMarkers.push(marker); + } + + removeTemporaryMarker(latlng: L.LatLng) { + var d: number | null = null; + var closest: L.Marker | null = null; + var i: number = 0; + this.#temporaryMarkers.forEach((marker: L.Marker, idx: number) => { + var t = latlng.distanceTo(marker.getLatLng()); + if (d == null || t < d) { + d = t; + closest = marker; + i = idx; + } + }); + if (closest) + { + this.removeLayer(closest); + delete this.#temporaryMarkers[i]; + } + } + /* Event handlers */ #onClick(e: any) { if (!this.#preventLeftClick) { diff --git a/client/src/units/unit.ts b/client/src/units/unit.ts index d3ee4338..946a0d47 100644 --- a/client/src/units/unit.ts +++ b/client/src/units/unit.ts @@ -1,4 +1,4 @@ -import { Marker, LatLng, Polyline, Icon, DivIcon, CircleMarker } from 'leaflet'; +import { Marker, LatLng, Polyline, Icon, DivIcon, CircleMarker, Map } from 'leaflet'; import { getMap, getUnitsManager } from '..'; import { rad2deg } from '../other/utils'; import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, deleteUnit, getUnits, landAt, setAltitude, setReactionToThreat, setROE, setSpeed, refuel, setAdvacedOptions, followUnit } from '../server/server'; @@ -383,6 +383,12 @@ export class Unit extends Marker { }, 200); } + onAdd(map: Map): this { + super.onAdd(map); + getMap().removeTemporaryMarker(new LatLng(this.getFlightData().latitude, this.getFlightData().longitude)); + return this; + } + #onDoubleClick(e: any) { clearTimeout(this.#timer); this.#preventClick = true; @@ -438,6 +444,7 @@ export class Unit extends Marker { 'Line abreast (LH)': `