mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
228 lines
7.2 KiB
TypeScript
228 lines
7.2 KiB
TypeScript
import { LatLng, LatLngExpression, Map, Point, Polygon, PolylineOptions, DivIcon, Marker } from "leaflet";
|
|
import { getApp } from "../../olympusapp";
|
|
import { DraggableHandle } from "./coalitionareahandle";
|
|
import { CoalitionAreaMiddleHandle } from "./coalitionareamiddlehandle";
|
|
import { BLUE_COMMANDER, colors, RED_COMMANDER } from "../../constants/constants";
|
|
import { Coalition } from "../../types/types";
|
|
import { polyCenter } from "../../other/utils";
|
|
import { CoalitionAreaChangedEvent, CoalitionAreaSelectedEvent } from "../../events";
|
|
|
|
let totalPolygons = 0;
|
|
|
|
export class CoalitionPolygon extends Polygon {
|
|
#coalition: Coalition = "blue";
|
|
#selected: boolean = true;
|
|
#creating: boolean = false;
|
|
#handles: DraggableHandle[] = [];
|
|
#middleHandles: CoalitionAreaMiddleHandle[] = [];
|
|
#activeIndex: number = 0;
|
|
#labelText: string;
|
|
#label: Marker;
|
|
#updateTimeout: number | null = null;
|
|
|
|
constructor(latlngs: LatLngExpression[] | LatLngExpression[][] | LatLngExpression[][][], options?: PolylineOptions, creating = true) {
|
|
if (options === undefined) options = {};
|
|
|
|
totalPolygons++;
|
|
|
|
options.bubblingMouseEvents = false;
|
|
options.interactive = false;
|
|
//@ts-ignore draggable option added by leaflet-path-drag
|
|
options.draggable = true;
|
|
|
|
super(latlngs, options);
|
|
this.#setColors();
|
|
|
|
this.#labelText = `Polygon ${totalPolygons}`;
|
|
this.#creating = creating;
|
|
|
|
if ([BLUE_COMMANDER, RED_COMMANDER].includes(getApp().getMissionManager().getCommandModeOptions().commandMode))
|
|
this.setCoalition(getApp().getMissionManager().getCommandedCoalition());
|
|
|
|
this.on("drag", () => {
|
|
this.#setHandles();
|
|
this.#setMiddleHandles();
|
|
this.#drawLabel();
|
|
|
|
if (this.#updateTimeout) window.clearTimeout(this.#updateTimeout);
|
|
this.#updateTimeout = window.setTimeout(() => {
|
|
CoalitionAreaChangedEvent.dispatch(this);
|
|
this.#updateTimeout = null;
|
|
}, 500);
|
|
});
|
|
|
|
getApp().getMap().addLayer(this);
|
|
}
|
|
|
|
setCoalition(coalition: Coalition) {
|
|
this.#coalition = coalition;
|
|
this.#setColors();
|
|
CoalitionAreaChangedEvent.dispatch(this);
|
|
}
|
|
|
|
getCoalition() {
|
|
return this.#coalition;
|
|
}
|
|
|
|
setSelected(selected: boolean) {
|
|
this.#selected = selected;
|
|
this.#setColors();
|
|
this.#setHandles();
|
|
this.#drawLabel();
|
|
this.setOpacity(selected ? 1 : 0.5);
|
|
if (!this.getSelected() && this.getCreating()) {
|
|
/* Remove the vertex we were working on */
|
|
var latlngs = this.getLatLngs()[0] as LatLng[];
|
|
latlngs.splice(this.#activeIndex, 1);
|
|
this.setLatLngs(latlngs);
|
|
this.setCreating(false);
|
|
}
|
|
|
|
if (selected) CoalitionAreaSelectedEvent.dispatch(this);
|
|
|
|
//@ts-ignore draggable option added by leaflet-path-drag
|
|
selected ? this.dragging.enable() : this.dragging.disable();
|
|
}
|
|
|
|
getSelected() {
|
|
return this.#selected;
|
|
}
|
|
|
|
setCreating(creating: boolean) {
|
|
this.#creating = creating;
|
|
this.#setHandles();
|
|
var latlngs = this.getLatLngs()[0] as LatLng[];
|
|
|
|
/* Remove areas with less than 2 vertexes */
|
|
if (latlngs.length <= 2) getApp().getCoalitionAreasManager().deleteCoalitionArea(this);
|
|
}
|
|
|
|
getCreating() {
|
|
return this.#creating;
|
|
}
|
|
|
|
addTemporaryLatLng(latlng: LatLng) {
|
|
this.#activeIndex++;
|
|
var latlngs = this.getLatLngs()[0] as LatLng[];
|
|
latlngs.splice(this.#activeIndex, 0, latlng);
|
|
this.setLatLngs(latlngs);
|
|
this.#setHandles();
|
|
}
|
|
|
|
setOpacity(opacity: number) {
|
|
this.setStyle({ opacity: opacity, fillOpacity: opacity * 0.25 });
|
|
}
|
|
|
|
getLabelText() {
|
|
return this.#labelText;
|
|
}
|
|
|
|
setLabelText(labelText: string) {
|
|
this.#labelText = labelText;
|
|
this.#drawLabel();
|
|
CoalitionAreaChangedEvent.dispatch(this);
|
|
}
|
|
|
|
onAdd(map: Map): this {
|
|
super.onAdd(map);
|
|
this.#drawLabel();
|
|
return this;
|
|
}
|
|
|
|
onRemove(map: Map): this {
|
|
super.onRemove(map);
|
|
this.#label?.removeFrom(map);
|
|
this.#handles.concat(this.#middleHandles).forEach((handle: DraggableHandle | CoalitionAreaMiddleHandle) => handle.removeFrom(map));
|
|
return this;
|
|
}
|
|
|
|
setLatLngs(latlngs: LatLngExpression[] | LatLngExpression[][] | LatLngExpression[][][]) {
|
|
super.setLatLngs(latlngs);
|
|
this.#drawLabel();
|
|
|
|
if (this.#updateTimeout) window.clearTimeout(this.#updateTimeout);
|
|
this.#updateTimeout = window.setTimeout(() => {
|
|
CoalitionAreaChangedEvent.dispatch(this);
|
|
this.#updateTimeout = null;
|
|
}, 500);
|
|
|
|
return this;
|
|
}
|
|
|
|
#setColors() {
|
|
let coalitionColor = colors.NEUTRAL_COALITION;
|
|
if (this.getCoalition() === "blue") coalitionColor = colors.BLUE_COALITION;
|
|
else if (this.getCoalition() === "red") coalitionColor = colors.RED_COALITION;
|
|
|
|
this.setStyle({
|
|
color: this.getSelected() ? "white" : coalitionColor,
|
|
fillColor: coalitionColor,
|
|
});
|
|
}
|
|
|
|
#setHandles() {
|
|
this.#handles.forEach((handle: DraggableHandle) => handle.removeFrom(getApp().getMap()));
|
|
this.#handles = [];
|
|
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 DraggableHandle(latlng);
|
|
handle.addTo(getApp().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.#setMiddleHandles();
|
|
}
|
|
|
|
#setMiddleHandles() {
|
|
this.#middleHandles.forEach((handle: CoalitionAreaMiddleHandle) => handle.removeFrom(getApp().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 = getApp().getMap().latLngToLayerPoint(latlng);
|
|
const handle2Point = getApp().getMap().latLngToLayerPoint(lastLatLng);
|
|
const middlePoint = new Point((handle1Point.x + handle2Point.x) / 2, (handle1Point.y + handle2Point.y) / 2);
|
|
const middleLatLng = getApp().getMap().layerPointToLatLng(middlePoint);
|
|
|
|
const middleHandle = new CoalitionAreaMiddleHandle(middleLatLng);
|
|
middleHandle.addTo(getApp().getMap());
|
|
middleHandle.on("click", (e: any) => {
|
|
this.#activeIndex = idx - 1;
|
|
this.addTemporaryLatLng(middleLatLng);
|
|
});
|
|
this.#middleHandles.push(middleHandle);
|
|
}
|
|
lastLatLng = latlng;
|
|
});
|
|
}
|
|
}
|
|
|
|
#drawLabel() {
|
|
if (this.#label) {
|
|
this.#label.removeFrom(this._map);
|
|
}
|
|
if ((this.getLatLngs()[0] as LatLng[]).length > 2) {
|
|
this.#label = new Marker(polyCenter(this), {
|
|
icon: new DivIcon({
|
|
className: "label",
|
|
html: this.#labelText,
|
|
iconSize: [100, 40],
|
|
}),
|
|
interactive: false,
|
|
}).addTo(this._map);
|
|
this.#label.getElement()?.classList.add(`ol-coalitionarea-label`, `${this.#selected ? "selected" : `${this.#coalition}`}`);
|
|
}
|
|
}
|
|
}
|