mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Added area editing functions
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { getUnitsManager } from "..";
|
||||
import { getMap, getUnitsManager } from "..";
|
||||
import { CoalitionArea } from "../map/coalitionarea";
|
||||
import { ContextMenu } from "./contextmenu";
|
||||
import { Dropdown } from "./dropdown";
|
||||
@@ -9,29 +9,39 @@ const unitRole = ["AAA", "MANPADS", "SAM Sites", "Radar"];
|
||||
|
||||
export class CoalitionAreaContextMenu extends ContextMenu {
|
||||
#coalitionSwitch: Switch;
|
||||
#coalitionArea: CoalitionArea|null = null;
|
||||
#coalitionArea: CoalitionArea | null = null;
|
||||
#iadsDensitySlider: Slider;
|
||||
#iadsRoleDropdown: Dropdown;
|
||||
|
||||
//#iadsPeriodDropdown: Dropdown;
|
||||
|
||||
|
||||
constructor(id: string) {
|
||||
super(id);
|
||||
|
||||
this.#coalitionSwitch = new Switch("coalition-area-switch", (value: boolean) => this.#onSwitchClick(value));
|
||||
this.#coalitionSwitch.setValue(false);
|
||||
this.#iadsRoleDropdown = new Dropdown("iads-units-role-options", () => {});
|
||||
this.#iadsRoleDropdown = new Dropdown("iads-units-role-options", () => { });
|
||||
//this.#iadsPeriodDropdown = new Dropdown("iads-period-options", () => {});
|
||||
this.#iadsDensitySlider = new Slider("iads-density-slider", 5, 100, "%", (value: number) => {});
|
||||
this.#iadsDensitySlider = new Slider("iads-density-slider", 5, 100, "%", (value: number) => { });
|
||||
this.#iadsDensitySlider.setIncrement(5);
|
||||
this.#iadsDensitySlider.setValue(50);
|
||||
this.#iadsDensitySlider.setActive(true);
|
||||
|
||||
document.addEventListener("coalitionAreaContextMenuShow", (e: any) => {
|
||||
this.showSubMenu(e.detail.type);
|
||||
if (this.getVisibleSubMenu() !== e.detail.type)
|
||||
this.showSubMenu(e.detail.type);
|
||||
else
|
||||
this.hideSubMenus();
|
||||
});
|
||||
|
||||
document.addEventListener("coalitionAreaDelete", (e: any) => {
|
||||
if (this.#coalitionArea)
|
||||
getMap().deleteCoalitionArea(this.#coalitionArea);
|
||||
getMap().hideCoalitionAreaContextMenu();
|
||||
});
|
||||
|
||||
document.addEventListener("contextMenuCreateIads", (e: any) => {
|
||||
const values: {[key: string]: boolean} = {};
|
||||
const values: { [key: string]: boolean } = {};
|
||||
const element = this.#iadsRoleDropdown.getOptionElements();
|
||||
for (let idx = 0; idx < element.length; idx++) {
|
||||
const option = element.item(idx) as HTMLElement;
|
||||
@@ -70,6 +80,16 @@ export class CoalitionAreaContextMenu extends ContextMenu {
|
||||
this.getContainer()?.querySelector("#iads-menu")?.classList.toggle("hide", type !== "iads");
|
||||
this.getContainer()?.querySelector("#iads-button")?.classList.toggle("is-open", type === "iads");
|
||||
this.clip();
|
||||
|
||||
this.setVisibleSubMenu(type);
|
||||
}
|
||||
|
||||
hideSubMenus() {
|
||||
this.getContainer()?.querySelector("#iads-menu")?.classList.toggle("hide", true);
|
||||
this.getContainer()?.querySelector("#iads-button")?.classList.toggle("is-open", false);
|
||||
this.clip();
|
||||
|
||||
this.setVisibleSubMenu(null);
|
||||
}
|
||||
|
||||
getCoalitionArea() {
|
||||
@@ -78,9 +98,16 @@ export class CoalitionAreaContextMenu extends ContextMenu {
|
||||
|
||||
setCoalitionArea(coalitionArea: CoalitionArea) {
|
||||
this.#coalitionArea = coalitionArea;
|
||||
this.getContainer()?.querySelectorAll('[data-coalition]').forEach((element: any) => {
|
||||
element.setAttribute("data-coalition", this.getCoalitionArea()?.getCoalition())
|
||||
});
|
||||
this.#coalitionSwitch.setValue(this.getCoalitionArea()?.getCoalition() === "red");
|
||||
}
|
||||
|
||||
#onSwitchClick(value: boolean) {
|
||||
this.getCoalitionArea()?.setCoalition(value? "red": "blue");
|
||||
this.getCoalitionArea()?.setCoalition(value ? "red" : "blue");
|
||||
this.getContainer()?.querySelectorAll('[data-coalition]').forEach((element: any) => {
|
||||
element.setAttribute("data-coalition", this.getCoalitionArea()?.getCoalition())
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ export class ContextMenu {
|
||||
#latlng: LatLng = new LatLng(0, 0);
|
||||
#x: number = 0;
|
||||
#y: number = 0;
|
||||
#visibleSubMenu: string | null = null;
|
||||
|
||||
constructor(id: string) {
|
||||
this.#container = document.getElementById(id);
|
||||
@@ -52,4 +53,12 @@ export class ContextMenu {
|
||||
this.#container.style.top = window.innerHeight - this.#container.offsetHeight - 10 + "px";
|
||||
}
|
||||
}
|
||||
|
||||
setVisibleSubMenu(menu: string | null) {
|
||||
this.#visibleSubMenu = menu;
|
||||
}
|
||||
|
||||
getVisibleSubMenu() {
|
||||
return this.#visibleSubMenu;
|
||||
}
|
||||
}
|
||||
@@ -29,11 +29,11 @@ export class MapContextMenu extends ContextMenu {
|
||||
#groundUnitRoleDropdown: Dropdown;
|
||||
#groundUnitTypeDropdown: Dropdown;
|
||||
#spawnOptions: SpawnOptions = { role: "", type: "", latlng: new LatLng(0, 0), loadout: null, coalition: "blue", airbaseName: null, altitude: ftToM(20000) };
|
||||
|
||||
|
||||
constructor(id: string) {
|
||||
super(id);
|
||||
|
||||
this.#coalitionSwitch = new Switch("coalition-switch", this.#onSwitchClick);
|
||||
this.#coalitionSwitch = new Switch("coalition-switch", (value: boolean) => this.#onSwitchClick(value));
|
||||
this.#coalitionSwitch.setValue(false);
|
||||
this.#coalitionSwitch.getContainer()?.addEventListener("contextmenu", (e) => this.#onSwitchRightClick(e));
|
||||
this.#aircraftRoleDropdown = new Dropdown("aircraft-role-options", (role: string) => this.#setAircraftRole(role));
|
||||
@@ -47,7 +47,10 @@ export class MapContextMenu extends ContextMenu {
|
||||
this.#groundUnitTypeDropdown = new Dropdown("ground-unit-type-options", (type: string) => this.#setGroundUnitType(type));
|
||||
|
||||
document.addEventListener("mapContextMenuShow", (e: any) => {
|
||||
this.showSubMenu(e.detail.type);
|
||||
if (this.getVisibleSubMenu() !== e.detail.type)
|
||||
this.showSubMenu(e.detail.type);
|
||||
else
|
||||
this.hideSubMenus();
|
||||
});
|
||||
|
||||
document.addEventListener("contextMenuDeployAircraft", () => {
|
||||
@@ -104,8 +107,30 @@ export class MapContextMenu extends ContextMenu {
|
||||
this.#resetGroundUnitRole();
|
||||
this.#resetGroundUnitType();
|
||||
this.clip();
|
||||
|
||||
this.setVisibleSubMenu(type);
|
||||
}
|
||||
|
||||
hideSubMenus() {
|
||||
this.getContainer()?.querySelector("#aircraft-spawn-menu")?.classList.toggle("hide", true);
|
||||
this.getContainer()?.querySelector("#aircraft-spawn-button")?.classList.toggle("is-open", false);
|
||||
this.getContainer()?.querySelector("#ground-unit-spawn-menu")?.classList.toggle("hide", true);
|
||||
this.getContainer()?.querySelector("#ground-ol-contexmenu-button")?.classList.toggle("is-open", false);
|
||||
this.getContainer()?.querySelector("#smoke-spawn-menu")?.classList.toggle("hide", true);
|
||||
this.getContainer()?.querySelector("#smoke-spawn-button")?.classList.toggle("is-open", false);
|
||||
this.getContainer()?.querySelector("#explosion-menu")?.classList.toggle("hide", true);
|
||||
this.getContainer()?.querySelector("#explosion-spawn-button")?.classList.toggle("is-open", false);
|
||||
|
||||
this.#resetAircraftRole();
|
||||
this.#resetAircraftType();
|
||||
this.#resetGroundUnitRole();
|
||||
this.#resetGroundUnitType();
|
||||
this.clip();
|
||||
|
||||
this.setVisibleSubMenu(null);
|
||||
}
|
||||
|
||||
|
||||
showUpperBar() {
|
||||
this.getContainer()?.querySelector("#upper-bar")?.classList.toggle("hide", false);
|
||||
}
|
||||
@@ -124,6 +149,7 @@ export class MapContextMenu extends ContextMenu {
|
||||
|
||||
#onSwitchClick(value: boolean) {
|
||||
value? setActiveCoalition("red"): setActiveCoalition("blue");
|
||||
this.getContainer()?.querySelectorAll('[data-coalition]').forEach((element: any) => { element.setAttribute("data-coalition", getActiveCoalition()) });
|
||||
}
|
||||
|
||||
#onSwitchRightClick(e: any) {
|
||||
|
||||
@@ -253,7 +253,6 @@ export function getHotgroupPanel() {
|
||||
|
||||
export function setActiveCoalition(newActiveCoalition: string) {
|
||||
activeCoalition = newActiveCoalition;
|
||||
document.querySelectorAll('[data-active-coalition]').forEach((element: any) => { element.setAttribute("data-active-coalition", activeCoalition) });
|
||||
}
|
||||
|
||||
export function getActiveCoalition() {
|
||||
|
||||
@@ -1,40 +1,24 @@
|
||||
import { LatLng, LatLngExpression, Polygon, PolylineOptions } from "leaflet";
|
||||
import { LatLng, LatLngExpression, Map, Point, Polygon, PolylineOptions } from "leaflet";
|
||||
import { getMap } from "..";
|
||||
import { DRAW_POLYGON } from "./map";
|
||||
import { CoalitionAreaHandle } from "./coalitionareahandle";
|
||||
import { CoalitionAreaMiddleHandle } from "./coalitionareamiddlehandle";
|
||||
|
||||
export class CoalitionArea extends Polygon {
|
||||
#coalition: string = "blue";
|
||||
#selected: boolean = true;
|
||||
#editing: boolean = true;
|
||||
#handles: CoalitionAreaHandle[] = [];
|
||||
#middleHandles: CoalitionAreaMiddleHandle[] = [];
|
||||
#activeIndex: number = 0;
|
||||
|
||||
constructor(latlngs: LatLngExpression[] | LatLngExpression[][] | LatLngExpression[][][], options?: PolylineOptions) {
|
||||
if (options === undefined)
|
||||
if (options === undefined)
|
||||
options = {};
|
||||
|
||||
|
||||
options.bubblingMouseEvents = false;
|
||||
super(latlngs, options);
|
||||
|
||||
this.on("click", (e: any) => {
|
||||
if (!this.getSelected()) {
|
||||
this.setSelected(true);
|
||||
getMap().setState(DRAW_POLYGON);
|
||||
}
|
||||
else if (this.getEditing()) {
|
||||
this.addLatLng(e.latlng);
|
||||
this.addTemporaryLatLng(e.latlng);
|
||||
}
|
||||
});
|
||||
|
||||
this.on("contextmenu", (e: any) => {
|
||||
if (!this.#editing)
|
||||
getMap().showCoalitionAreaContextMenu(e, this);
|
||||
else
|
||||
this.setEditing(false);
|
||||
});
|
||||
|
||||
this.#setColors();
|
||||
this.#registerCallbacks();
|
||||
}
|
||||
|
||||
setCoalition(coalition: string) {
|
||||
@@ -50,10 +34,15 @@ export class CoalitionArea extends Polygon {
|
||||
this.#selected = selected;
|
||||
this.#setColors();
|
||||
this.#setHandles();
|
||||
if (!selected)
|
||||
if (!this.getSelected() && this.getEditing()) {
|
||||
/* Remove the vertex we were working on */
|
||||
var latlngs = this.getLatLngs()[0] as LatLng[];
|
||||
latlngs.splice(this.#activeIndex, 1);
|
||||
this.setLatLngs(latlngs);
|
||||
this.setEditing(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
getSelected() {
|
||||
return this.#selected;
|
||||
}
|
||||
@@ -61,6 +50,11 @@ export class CoalitionArea extends Polygon {
|
||||
setEditing(editing: boolean) {
|
||||
this.#editing = editing;
|
||||
this.#setHandles();
|
||||
var latlngs = this.getLatLngs()[0] as LatLng[];
|
||||
|
||||
/* Remove areas with less than 2 vertexes */
|
||||
if (latlngs.length <= 2)
|
||||
getMap().deleteCoalitionArea(this);
|
||||
}
|
||||
|
||||
getEditing() {
|
||||
@@ -68,38 +62,92 @@ export class CoalitionArea extends Polygon {
|
||||
}
|
||||
|
||||
addTemporaryLatLng(latlng: LatLng) {
|
||||
this.addLatLng(latlng);
|
||||
this.#activeIndex++;
|
||||
var latlngs = this.getLatLngs()[0] as LatLng[];
|
||||
latlngs.splice(this.#activeIndex, 0, latlng);
|
||||
this.setLatLngs(latlngs);
|
||||
this.#setHandles();
|
||||
}
|
||||
|
||||
moveTemporaryLatLng(latlng: LatLng) {
|
||||
var latlngs = this.getLatLngs()[0] as LatLng[];
|
||||
latlngs[latlngs.length - 1] = latlng;
|
||||
latlngs[this.#activeIndex] = latlng;
|
||||
this.setLatLngs(latlngs);
|
||||
}
|
||||
|
||||
addLatLng(latlng: LatLngExpression | LatLngExpression[], latlngs?: LatLng[] | undefined): this {
|
||||
super.addLatLng(latlng, latlngs)
|
||||
this.#setHandles();
|
||||
return this;
|
||||
}
|
||||
|
||||
#setColors() {
|
||||
this.setStyle({color: this.getSelected()? "white": this.#coalition, fillColor: this.#coalition});
|
||||
const coalitionColor = this.getCoalition() === "blue" ? "#247be2" : "#ff5858";
|
||||
this.setStyle({ color: this.getSelected() ? "white" : coalitionColor, fillColor: coalitionColor });
|
||||
}
|
||||
|
||||
#setHandles() {
|
||||
this.#handles.forEach((handle: CoalitionAreaHandle) => handle.removeFrom(getMap()));
|
||||
this.#handles = [];
|
||||
var latlngs = this.getLatLngs()[0] as LatLng[];
|
||||
latlngs.forEach((latlng: LatLng, idx: number) => {
|
||||
const handle = new CoalitionAreaHandle(latlng);
|
||||
handle.addTo(getMap());
|
||||
handle.on("dragend", (e: any) => {
|
||||
var latlngs = this.getLatLngs()[0] as LatLng[];
|
||||
latlngs[idx] = e.latlng;
|
||||
this.setLatLngs(latlngs);
|
||||
if (this.getSelected()) {
|
||||
var latlngs = this.getLatLngs()[0] as LatLng[];
|
||||
latlngs.forEach((latlng: LatLng, idx: number) => {
|
||||
/* Add the polygon vertex handle (for moving the vertex) */
|
||||
const handle = new CoalitionAreaHandle(latlng);
|
||||
handle.addTo(getMap());
|
||||
handle.on("drag", (e: any) => {
|
||||
var latlngs = this.getLatLngs()[0] as LatLng[];
|
||||
latlngs[idx] = e.target.getLatLng();
|
||||
this.setLatLngs(latlngs);
|
||||
this.#setMiddleHandles();
|
||||
});
|
||||
this.#handles.push(handle);
|
||||
});
|
||||
this.#handles.push(handle);
|
||||
}
|
||||
this.#setMiddleHandles();
|
||||
}
|
||||
|
||||
#setMiddleHandles() {
|
||||
this.#middleHandles.forEach((handle: CoalitionAreaMiddleHandle) => handle.removeFrom(getMap()));
|
||||
this.#middleHandles = [];
|
||||
var latlngs = this.getLatLngs()[0] as LatLng[];
|
||||
if (this.getSelected() && latlngs.length >= 2) {
|
||||
var lastLatLng: LatLng | null = null;
|
||||
latlngs.concat([latlngs[0]]).forEach((latlng: LatLng, idx: number) => {
|
||||
/* Add the polygon middle point handle (for adding new vertexes) */
|
||||
if (lastLatLng != null) {
|
||||
const handle1Point = getMap().latLngToLayerPoint(latlng);
|
||||
const handle2Point = getMap().latLngToLayerPoint(lastLatLng);
|
||||
const middlePoint = new Point((handle1Point.x + handle2Point.x) / 2, (handle1Point.y + handle2Point.y) / 2);
|
||||
const middleLatLng = getMap().layerPointToLatLng(middlePoint);
|
||||
|
||||
const middleHandle = new CoalitionAreaMiddleHandle(middleLatLng);
|
||||
middleHandle.addTo(getMap());
|
||||
middleHandle.on("click", (e: any) => {
|
||||
this.#activeIndex = idx - 1;
|
||||
this.addTemporaryLatLng(middleLatLng);
|
||||
});
|
||||
this.#middleHandles.push(middleHandle);
|
||||
}
|
||||
lastLatLng = latlng;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#registerCallbacks() {
|
||||
this.on("click", (e: any) => {
|
||||
getMap().deselectAllCoalitionAreas();
|
||||
if (!this.getSelected()) {
|
||||
this.setSelected(true);
|
||||
}
|
||||
});
|
||||
|
||||
this.on("contextmenu", (e: any) => {
|
||||
if (this.getSelected() && !this.getEditing())
|
||||
getMap().showCoalitionAreaContextMenu(e, this);
|
||||
else
|
||||
this.setEditing(false);
|
||||
});
|
||||
}
|
||||
|
||||
onRemove(map: Map): this {
|
||||
super.onRemove(map);
|
||||
this.#handles.concat(this.#middleHandles).forEach((handle: CoalitionAreaHandle | CoalitionAreaMiddleHandle) => handle.removeFrom(getMap()));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -8,12 +8,12 @@ export class CoalitionAreaHandle extends CustomMarker {
|
||||
|
||||
createIcon() {
|
||||
this.setIcon(new DivIcon({
|
||||
iconSize: [52, 52],
|
||||
iconAnchor: [26, 26],
|
||||
className: "leaflet-target-marker",
|
||||
iconSize: [24, 24],
|
||||
iconAnchor: [12, 12],
|
||||
className: "leaflet-coalitionarea-handle-marker",
|
||||
}));
|
||||
var el = document.createElement("div");
|
||||
el.classList.add("ol-target-icon");
|
||||
el.classList.add("ol-coalitionarea-handle-icon");
|
||||
this.getElement()?.appendChild(el);
|
||||
}
|
||||
}
|
||||
19
client/src/map/coalitionareamiddlehandle.ts
Normal file
19
client/src/map/coalitionareamiddlehandle.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { DivIcon, LatLng } from "leaflet";
|
||||
import { CustomMarker } from "./custommarker";
|
||||
|
||||
export class CoalitionAreaMiddleHandle extends CustomMarker {
|
||||
constructor(latlng: LatLng) {
|
||||
super(latlng, {interactive: true, draggable: false});
|
||||
}
|
||||
|
||||
createIcon() {
|
||||
this.setIcon(new DivIcon({
|
||||
iconSize: [16, 16],
|
||||
iconAnchor: [8, 8],
|
||||
className: "leaflet-coalitionarea-middle-handle-marker",
|
||||
}));
|
||||
var el = document.createElement("div");
|
||||
el.classList.add("ol-coalitionarea-middle-handle-icon");
|
||||
this.getElement()?.appendChild(el);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,12 @@
|
||||
import { DivIcon } from "leaflet";
|
||||
import { DivIcon, LatLngExpression, MarkerOptions } from "leaflet";
|
||||
import { CustomMarker } from "./custommarker";
|
||||
|
||||
export class DestinationPreviewMarker extends CustomMarker {
|
||||
constructor(latlng: LatLngExpression, options?: MarkerOptions) {
|
||||
super(latlng, options);
|
||||
this.setZIndexOffset(9999);
|
||||
}
|
||||
|
||||
createIcon() {
|
||||
this.setIcon(new DivIcon({
|
||||
iconSize: [52, 52],
|
||||
|
||||
20
client/src/map/drawingmarker.ts
Normal file
20
client/src/map/drawingmarker.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { DivIcon, LatLng } from "leaflet";
|
||||
import { CustomMarker } from "./custommarker";
|
||||
|
||||
export class DrawingCursor extends CustomMarker {
|
||||
constructor() {
|
||||
super(new LatLng(0, 0), {interactive: false})
|
||||
this.setZIndexOffset(9999);
|
||||
}
|
||||
|
||||
createIcon() {
|
||||
this.setIcon(new DivIcon({
|
||||
iconSize: [24, 24],
|
||||
iconAnchor: [0, 24],
|
||||
className: "leaflet-draw-marker",
|
||||
}));
|
||||
var el = document.createElement("div");
|
||||
el.classList.add("ol-draw-icon");
|
||||
this.getElement()?.appendChild(el);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import { layers as mapLayers, mapBounds, minimapBoundaries } from "../constants/
|
||||
import { TargetMarker } from "./targetmarker";
|
||||
import { CoalitionArea } from "./coalitionarea";
|
||||
import { CoalitionAreaContextMenu } from "../controls/coalitionareacontextmenu";
|
||||
import { DrawingCursor } from "./drawingmarker";
|
||||
|
||||
L.Map.addInitHook('addHandler', 'boxSelect', BoxSelect);
|
||||
|
||||
@@ -29,7 +30,7 @@ export const MOVE_UNIT = "Move unit";
|
||||
export const BOMBING = "Bombing";
|
||||
export const CARPET_BOMBING = "Carpet bombing";
|
||||
export const FIRE_AT_AREA = "Fire at area";
|
||||
export const DRAW_POLYGON = "Draw polygon";
|
||||
export const DRAW_COALITIONAREA_POLYGON = "Draw Coalition Area";
|
||||
export const visibilityControls: string[] = ["human", "dcs", "aircraft", "groundunit-sam", "groundunit-other", "navyunit", "airbase"];
|
||||
export const visibilityControlsTootlips: string[] = ["Toggle human players visibility", "Toggle DCS controlled units visibility", "Toggle aircrafts visibility", "Toggle SAM units visibility", "Toggle ground units (not SAM) visibility", "Toggle navy units visibility", "Toggle airbases visibility"];
|
||||
|
||||
@@ -50,12 +51,15 @@ export class Map extends L.Map {
|
||||
#miniMap: ClickableMiniMap | null = null;
|
||||
#miniMapLayerGroup: L.LayerGroup;
|
||||
#temporaryMarkers: TemporaryUnitMarker[] = [];
|
||||
#destinationPreviewMarkers: DestinationPreviewMarker[] = [];
|
||||
#targetMarker: TargetMarker;
|
||||
|
||||
#destinationGroupRotation: number = 0;
|
||||
#computeDestinationRotation: boolean = false;
|
||||
#destinationRotationCenter: L.LatLng | null = null;
|
||||
#coalitionAreas: CoalitionArea[] = [];
|
||||
|
||||
#targetCursor: TargetMarker = new TargetMarker(new L.LatLng(0, 0), {interactive: false});
|
||||
#destinationPreviewCursors: DestinationPreviewMarker[] = [];
|
||||
#drawingCursor: DrawingCursor = new DrawingCursor();
|
||||
|
||||
#mapContextMenu: MapContextMenu = new MapContextMenu("map-contextmenu");
|
||||
#unitContextMenu: UnitContextMenu = new UnitContextMenu("unit-contextmenu");
|
||||
@@ -102,8 +106,8 @@ export class Map extends L.Map {
|
||||
this.on('mousedown', (e: any) => this.#onMouseDown(e));
|
||||
this.on('mouseup', (e: any) => this.#onMouseUp(e));
|
||||
this.on('mousemove', (e: any) => this.#onMouseMove(e));
|
||||
this.on('keydown', (e: any) => this.#updateDestinationPreview(e));
|
||||
this.on('keyup', (e: any) => this.#updateDestinationPreview(e));
|
||||
this.on('keydown', (e: any) => this.#onKeyDown(e));
|
||||
this.on('keyup', (e: any) => this.#onKeyUp(e));
|
||||
|
||||
/* Event listeners */
|
||||
document.addEventListener("toggleCoalitionVisibility", (ev: CustomEventInit) => {
|
||||
@@ -120,9 +124,14 @@ export class Map extends L.Map {
|
||||
Object.values(getUnitsManager().getUnits()).forEach((unit: Unit) => unit.updateVisibility());
|
||||
});
|
||||
|
||||
document.addEventListener("toggleMapDraw", (ev: CustomEventInit) => {
|
||||
document.addEventListener("toggleCoalitionAreaDraw", (ev: CustomEventInit) => {
|
||||
const el = ev.detail._element;
|
||||
document.addEventListener("mapStateChanged", () => el?.classList.toggle("off", !(this.getState() === DRAW_COALITIONAREA_POLYGON)));
|
||||
if (ev.detail?.type == "polygon") {
|
||||
this.setState(DRAW_POLYGON);
|
||||
if (this.getState() !== DRAW_COALITIONAREA_POLYGON)
|
||||
this.setState(DRAW_COALITIONAREA_POLYGON);
|
||||
else
|
||||
this.setState(IDLE);
|
||||
}
|
||||
})
|
||||
|
||||
@@ -143,9 +152,6 @@ export class Map extends L.Map {
|
||||
return this.#createOptionButton(option, `visibility/${option.toLowerCase()}.svg`, visibilityControlsTootlips[index], "toggleUnitVisibility", `{"type": "${option}"}`);
|
||||
});
|
||||
document.querySelector("#unit-visibility-control")?.append(...this.#optionButtons["visibility"]);
|
||||
|
||||
/* Markers */
|
||||
this.#targetMarker = new TargetMarker(new L.LatLng(0, 0), {interactive: false});
|
||||
}
|
||||
|
||||
setLayer(layerName: string) {
|
||||
@@ -172,30 +178,17 @@ export class Map extends L.Map {
|
||||
/* State machine */
|
||||
setState(state: string) {
|
||||
this.#state = state;
|
||||
this.#showCursor();
|
||||
if (this.#state === IDLE) {
|
||||
this.#resetDestinationMarkers();
|
||||
this.#resetTargetMarker();
|
||||
this.#deselectCoalitionAreas();
|
||||
this.#showCursor();
|
||||
}
|
||||
else if (this.#state === MOVE_UNIT) {
|
||||
this.#resetTargetMarker();
|
||||
this.#deselectCoalitionAreas();
|
||||
this.#createDestinationMarkers();
|
||||
if (this.#destinationPreviewMarkers.length > 0)
|
||||
this.#hideCursor();
|
||||
}
|
||||
else if ([BOMBING, CARPET_BOMBING, FIRE_AT_AREA].includes(this.#state)) {
|
||||
this.#resetDestinationMarkers();
|
||||
this.#deselectCoalitionAreas();
|
||||
this.#createTargetMarker();
|
||||
this.#hideCursor();
|
||||
}
|
||||
else if (this.#state === DRAW_POLYGON) {
|
||||
this.#resetDestinationMarkers();
|
||||
this.#resetTargetMarker();
|
||||
this.#showCursor();
|
||||
//@ts-ignore draggable option added by plugin
|
||||
else if (this.#state === DRAW_COALITIONAREA_POLYGON) {
|
||||
this.#coalitionAreas.push(new CoalitionArea([]));
|
||||
this.#coalitionAreas[this.#coalitionAreas.length - 1].addTo(this);
|
||||
}
|
||||
@@ -206,6 +199,17 @@ export class Map extends L.Map {
|
||||
return this.#state;
|
||||
}
|
||||
|
||||
deselectAllCoalitionAreas() {
|
||||
this.#coalitionAreas.forEach((coalitionArea: CoalitionArea) => coalitionArea.setSelected(false));
|
||||
}
|
||||
|
||||
deleteCoalitionArea(coalitionArea: CoalitionArea) {
|
||||
if (this.#coalitionAreas.includes(coalitionArea))
|
||||
this.#coalitionAreas.splice(this.#coalitionAreas.indexOf(coalitionArea), 1);
|
||||
if (this.hasLayer(coalitionArea))
|
||||
this.removeLayer(coalitionArea);
|
||||
}
|
||||
|
||||
/* Context Menus */
|
||||
hideAllContextMenus() {
|
||||
this.hideMapContextMenu();
|
||||
@@ -393,7 +397,7 @@ export class Map extends L.Map {
|
||||
});
|
||||
if (closest) {
|
||||
this.removeLayer(closest);
|
||||
delete this.#temporaryMarkers[i];
|
||||
this.#temporaryMarkers.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,16 +410,14 @@ export class Map extends L.Map {
|
||||
if (!this.#preventLeftClick) {
|
||||
this.hideAllContextMenus();
|
||||
if (this.#state === IDLE) {
|
||||
|
||||
this.deselectAllCoalitionAreas();
|
||||
}
|
||||
else if (this.#state === DRAW_POLYGON) {
|
||||
/* This gets only called to create the first point of the area. All other points are added by the area itself */
|
||||
else if (this.#state === DRAW_COALITIONAREA_POLYGON) {
|
||||
if (this.getSelectedCoalitionArea()?.getEditing()) {
|
||||
this.getSelectedCoalitionArea()?.addLatLng(e.latlng);
|
||||
this.getSelectedCoalitionArea()?.addTemporaryLatLng(e.latlng);
|
||||
}
|
||||
else {
|
||||
this.getSelectedCoalitionArea()?.setSelected(false);
|
||||
this.deselectAllCoalitionAreas();
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -426,7 +428,7 @@ export class Map extends L.Map {
|
||||
}
|
||||
|
||||
#onDoubleClick(e: any) {
|
||||
|
||||
this.deselectAllCoalitionAreas();
|
||||
}
|
||||
|
||||
#onContextMenu(e: any) {
|
||||
@@ -492,20 +494,34 @@ export class Map extends L.Map {
|
||||
this.#lastMousePosition.x = e.originalEvent.x;
|
||||
this.#lastMousePosition.y = e.originalEvent.y;
|
||||
|
||||
this.#showCursor(e);
|
||||
|
||||
if (this.#state === MOVE_UNIT){
|
||||
if (this.#computeDestinationRotation && this.#destinationRotationCenter != null)
|
||||
this.#destinationGroupRotation = -bearing(this.#destinationRotationCenter.lat, this.#destinationRotationCenter.lng, this.getMouseCoordinates().lat, this.getMouseCoordinates().lng);
|
||||
this.#updateDestinationPreview(e);
|
||||
}
|
||||
else if ([BOMBING, CARPET_BOMBING, FIRE_AT_AREA].includes(this.#state)) {
|
||||
this.#targetMarker.setLatLng(this.getMouseCoordinates());
|
||||
this.#targetCursor.setLatLng(this.getMouseCoordinates());
|
||||
}
|
||||
else if (this.#state === DRAW_POLYGON) {
|
||||
if (this.getSelectedCoalitionArea()?.getEditing())
|
||||
else if (this.#state === DRAW_COALITIONAREA_POLYGON) {
|
||||
if (this.getSelectedCoalitionArea()?.getEditing() && !e.originalEvent.ctrlKey){
|
||||
this.#drawingCursor.setLatLng(e.latlng);
|
||||
this.getSelectedCoalitionArea()?.moveTemporaryLatLng(e.latlng);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#onKeyDown(e: any) {
|
||||
this.#updateDestinationPreview(e);
|
||||
this.#showCursor(e);
|
||||
}
|
||||
|
||||
#onKeyUp(e: any) {
|
||||
this.#updateDestinationPreview(e);
|
||||
this.#showCursor(e);
|
||||
}
|
||||
|
||||
#onZoom(e: any) {
|
||||
if (this.#centerUnit != null)
|
||||
this.#panToUnit(this.#centerUnit);
|
||||
@@ -523,8 +539,8 @@ export class Map extends L.Map {
|
||||
|
||||
#updateDestinationPreview(e: any) {
|
||||
Object.values(getUnitsManager().selectedUnitsComputeGroupDestination(this.#computeDestinationRotation && this.#destinationRotationCenter != null ? this.#destinationRotationCenter : this.getMouseCoordinates(), this.#destinationGroupRotation)).forEach((latlng: L.LatLng, idx: number) => {
|
||||
if (idx < this.#destinationPreviewMarkers.length)
|
||||
this.#destinationPreviewMarkers[idx].setLatLng(e.originalEvent.shiftKey ? latlng : this.getMouseCoordinates());
|
||||
if (idx < this.#destinationPreviewCursors.length)
|
||||
this.#destinationPreviewCursors[idx].setLatLng(e.originalEvent.shiftKey ? latlng : this.getMouseCoordinates());
|
||||
})
|
||||
}
|
||||
|
||||
@@ -541,12 +557,12 @@ export class Map extends L.Map {
|
||||
return button;
|
||||
}
|
||||
|
||||
#createDestinationMarkers() {
|
||||
this.#resetDestinationMarkers();
|
||||
#showDestinationCursors() {
|
||||
this.#hideDestinationCursors();
|
||||
|
||||
if (getUnitsManager().getSelectedUnits({ excludeHumans: true }).length > 0) {
|
||||
/* Create the unit destination preview markers */
|
||||
this.#destinationPreviewMarkers = getUnitsManager().getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true }).map((unit: Unit) => {
|
||||
this.#destinationPreviewCursors = getUnitsManager().getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true }).map((unit: Unit) => {
|
||||
var marker = new DestinationPreviewMarker(this.getMouseCoordinates(), {interactive: false});
|
||||
marker.addTo(this);
|
||||
return marker;
|
||||
@@ -554,38 +570,79 @@ export class Map extends L.Map {
|
||||
}
|
||||
}
|
||||
|
||||
#resetDestinationMarkers() {
|
||||
#hideDestinationCursors() {
|
||||
/* Remove all the destination preview markers */
|
||||
this.#destinationPreviewMarkers.forEach((marker: L.Marker) => {
|
||||
this.#destinationPreviewCursors.forEach((marker: L.Marker) => {
|
||||
this.removeLayer(marker);
|
||||
})
|
||||
this.#destinationPreviewMarkers = [];
|
||||
this.#destinationPreviewCursors = [];
|
||||
|
||||
this.#destinationGroupRotation = 0;
|
||||
this.#computeDestinationRotation = false;
|
||||
this.#destinationRotationCenter = null;
|
||||
}
|
||||
|
||||
#createTargetMarker(){
|
||||
this.#resetTargetMarker();
|
||||
this.#targetMarker.addTo(this);
|
||||
#showTargetCursor(){
|
||||
this.#hideTargetCursor();
|
||||
this.#targetCursor.addTo(this);
|
||||
}
|
||||
|
||||
#resetTargetMarker() {
|
||||
this.#targetMarker.setLatLng(new L.LatLng(0, 0));
|
||||
this.removeLayer(this.#targetMarker);
|
||||
#hideTargetCursor() {
|
||||
this.#targetCursor.setLatLng(new L.LatLng(0, 0));
|
||||
this.removeLayer(this.#targetCursor);
|
||||
}
|
||||
|
||||
#deselectCoalitionAreas() {
|
||||
this.getSelectedCoalitionArea()?.setSelected(false);
|
||||
}
|
||||
|
||||
#showCursor() {
|
||||
#showDefaultCursor() {
|
||||
document.getElementById(this.#ID)?.classList.remove("hidden-cursor");
|
||||
}
|
||||
|
||||
#hideCursor() {
|
||||
#hideDefaultCursor() {
|
||||
document.getElementById(this.#ID)?.classList.add("hidden-cursor");
|
||||
}
|
||||
|
||||
#showDrawingCursor() {
|
||||
this.#hideDefaultCursor();
|
||||
if (!this.hasLayer(this.#drawingCursor))
|
||||
this.#drawingCursor.addTo(this);
|
||||
}
|
||||
|
||||
#hideDrawingCursor() {
|
||||
if (this.hasLayer(this.#drawingCursor))
|
||||
this.#drawingCursor.removeFrom(this);
|
||||
}
|
||||
|
||||
#showCursor(e?: any) {
|
||||
if (e?.originalEvent.ctrlKey) {
|
||||
this.#hideDefaultCursor();
|
||||
this.#hideDestinationCursors();
|
||||
this.#hideTargetCursor();
|
||||
this.#hideDrawingCursor();
|
||||
this.#showDefaultCursor();
|
||||
} else {
|
||||
if (this.#state !== IDLE) this.#hideDefaultCursor();
|
||||
if (this.#state !== MOVE_UNIT) this.#hideDestinationCursors();
|
||||
if (![BOMBING, CARPET_BOMBING, FIRE_AT_AREA].includes(this.#state)) this.#hideTargetCursor();
|
||||
if (this.#state !== DRAW_COALITIONAREA_POLYGON) this.#hideDrawingCursor();
|
||||
|
||||
if (this.#state === IDLE) this.#showDefaultCursor();
|
||||
else if (this.#state === MOVE_UNIT) this.#showDestinationCursors();
|
||||
else if ([BOMBING, CARPET_BOMBING, FIRE_AT_AREA].includes(this.#state)) this.#showTargetCursor();
|
||||
else if (this.#state === DRAW_COALITIONAREA_POLYGON) {
|
||||
if (this.getSelectedCoalitionArea()?.getEditing())
|
||||
{
|
||||
this.#hideDefaultCursor();
|
||||
this.#showDrawingCursor();
|
||||
}
|
||||
else {
|
||||
this.#hideDrawingCursor();
|
||||
this.#showDefaultCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { DivIcon } from "leaflet";
|
||||
import { DivIcon, LatLngExpression, MarkerOptions } from "leaflet";
|
||||
import { CustomMarker } from "./custommarker";
|
||||
|
||||
export class TargetMarker extends CustomMarker {
|
||||
#interactive: boolean = false;
|
||||
constructor(latlng: LatLngExpression, options?: MarkerOptions) {
|
||||
super(latlng, options);
|
||||
this.setZIndexOffset(9999);
|
||||
}
|
||||
|
||||
createIcon() {
|
||||
this.setIcon(new DivIcon({
|
||||
@@ -12,7 +15,6 @@ export class TargetMarker extends CustomMarker {
|
||||
}));
|
||||
var el = document.createElement("div");
|
||||
el.classList.add("ol-target-icon");
|
||||
el.classList.toggle("ol-target-icon-interactive", this.#interactive)
|
||||
this.getElement()?.appendChild(el);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ export class MissionHandler {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ("airbases" in data) {
|
||||
for (let idx in data.airbases) {
|
||||
var airbase = data.airbases[idx]
|
||||
|
||||
@@ -526,7 +526,8 @@ export class UnitsManager {
|
||||
type: unitBlueprint.name,
|
||||
coalition: coalitionArea.getCoalition(),
|
||||
immediate: true
|
||||
})
|
||||
});
|
||||
getMap().addTemporaryMarker(latlng);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user