mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Completed creation of areas
This commit is contained in:
@@ -4,6 +4,10 @@ import { CustomMarker } from "../markers/custommarker";
|
||||
export class CoalitionAreaHandle extends CustomMarker {
|
||||
constructor(latlng: LatLng) {
|
||||
super(latlng, { interactive: true, draggable: true });
|
||||
|
||||
this.on("add", (e) => {
|
||||
this.getElement()?.addEventListener("touchstart", (e) => e.stopPropagation());
|
||||
})
|
||||
}
|
||||
|
||||
createIcon() {
|
||||
|
||||
@@ -49,6 +49,10 @@ export class CoalitionCircle extends Circle {
|
||||
this.#setRadiusHandle();
|
||||
this.#drawLabel();
|
||||
});
|
||||
|
||||
this.on("remove", () => {
|
||||
this.#label.removeFrom(this._map);
|
||||
});
|
||||
}
|
||||
|
||||
setCoalition(coalition: Coalition) {
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
Polygon,
|
||||
PolylineOptions,
|
||||
DivIcon,
|
||||
Marker,
|
||||
Marker
|
||||
} from "leaflet";
|
||||
import { getApp } from "../../olympusapp";
|
||||
import { CoalitionAreaHandle } from "./coalitionareahandle";
|
||||
@@ -57,6 +57,10 @@ export class CoalitionPolygon extends Polygon {
|
||||
this.#setMiddleHandles();
|
||||
this.#drawLabel();
|
||||
});
|
||||
|
||||
this.on("remove", () => {
|
||||
this.#label.removeFrom(this._map);
|
||||
});
|
||||
}
|
||||
|
||||
setCoalition(coalition: Coalition) {
|
||||
|
||||
179
frontend/react/src/map/coalitionarea/draggablepath.ts
Normal file
179
frontend/react/src/map/coalitionarea/draggablepath.ts
Normal file
@@ -0,0 +1,179 @@
|
||||
import * as L from "leaflet";
|
||||
|
||||
export const initDraggablePath = () => {
|
||||
//@ts-ignore
|
||||
L.PathDraggable = L.Draggable.extend({
|
||||
initialize: function (path) {
|
||||
this._path = path;
|
||||
|
||||
this._canvas = path._map.getRenderer(path) instanceof L.Canvas;
|
||||
|
||||
var element = this._canvas
|
||||
? this._path._map.getRenderer(this._path)._container
|
||||
: this._path._path;
|
||||
|
||||
//@ts-ignore
|
||||
L.Draggable.prototype.initialize.call(this, element, element, true);
|
||||
},
|
||||
|
||||
_updatePosition: function () {
|
||||
var e = { originalEvent: this._lastEvent };
|
||||
|
||||
this.fire("drag", e);
|
||||
},
|
||||
|
||||
_onDown: function (e) {
|
||||
var first = e.touches ? e.touches[0] : e;
|
||||
|
||||
this._startPoint = new L.Point(first.clientX, first.clientY);
|
||||
|
||||
if (
|
||||
this._canvas &&
|
||||
!this._path._containsPoint(
|
||||
this._path._map.mouseEventToLayerPoint(first)
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
L.Draggable.prototype._onDown.call(this, e);
|
||||
e.stopPropagation();
|
||||
},
|
||||
});
|
||||
|
||||
//@ts-ignore
|
||||
L.Handler.PathDrag = L.Handler.extend({
|
||||
initialize: function (path) {
|
||||
this._path = path;
|
||||
},
|
||||
|
||||
getEvents: function () {
|
||||
return {
|
||||
dragstart: this._onDragStart,
|
||||
|
||||
drag: this._onDrag,
|
||||
|
||||
dragend: this._onDragEnd,
|
||||
};
|
||||
},
|
||||
|
||||
addHooks: function () {
|
||||
if (!this._draggable) {
|
||||
//@ts-ignore
|
||||
this._draggable = new L.PathDraggable(this._path);
|
||||
}
|
||||
|
||||
this._draggable.on(this.getEvents(), this).enable();
|
||||
|
||||
L.DomUtil.addClass(this._draggable._element, "leaflet-path-draggable");
|
||||
},
|
||||
|
||||
removeHooks: function () {
|
||||
this._draggable.off(this.getEvents(), this).disable();
|
||||
|
||||
L.DomUtil.removeClass(this._draggable._element, "leaflet-path-draggable");
|
||||
},
|
||||
|
||||
moved: function () {
|
||||
return this._draggable && this._draggable._moved;
|
||||
},
|
||||
|
||||
_onDragStart: function () {
|
||||
this._startPoint = this._draggable._startPoint;
|
||||
|
||||
this._path.closePopup().fire("movestart").fire("dragstart");
|
||||
},
|
||||
|
||||
_onDrag: function (e) {
|
||||
var path = this._path,
|
||||
event =
|
||||
e.originalEvent.touches && e.originalEvent.touches.length === 1
|
||||
? e.originalEvent.touches[0]
|
||||
: e.originalEvent,
|
||||
newPoint = L.point(event.clientX, event.clientY),
|
||||
latlng = path._map.layerPointToLatLng(newPoint);
|
||||
|
||||
this._offset = newPoint.subtract(this._startPoint);
|
||||
|
||||
this._startPoint = newPoint;
|
||||
|
||||
this._path.eachLatLng(this.updateLatLng, this);
|
||||
|
||||
path.redraw();
|
||||
|
||||
e.latlng = latlng;
|
||||
|
||||
e.offset = this._offset;
|
||||
|
||||
path.fire("drag", e);
|
||||
|
||||
e.latlng = this._path.getCenter
|
||||
? this._path.getCenter()
|
||||
: this._path.getLatLng();
|
||||
|
||||
path.fire("move", e);
|
||||
},
|
||||
|
||||
_onDragEnd: function (e) {
|
||||
if (this._path._bounds) this.resetBounds();
|
||||
|
||||
this._path.fire("moveend").fire("dragend", e);
|
||||
},
|
||||
|
||||
latLngToLayerPoint: function (latlng) {
|
||||
// Same as map.latLngToLayerPoint, but without the round().
|
||||
|
||||
var projectedPoint = this._path._map.project(L.latLng(latlng));
|
||||
|
||||
return projectedPoint._subtract(this._path._map.getPixelOrigin());
|
||||
},
|
||||
|
||||
updateLatLng: function (latlng) {
|
||||
var oldPoint = this.latLngToLayerPoint(latlng);
|
||||
|
||||
oldPoint._add(this._offset);
|
||||
|
||||
var newLatLng = this._path._map.layerPointToLatLng(oldPoint);
|
||||
|
||||
latlng.lat = newLatLng.lat;
|
||||
|
||||
latlng.lng = newLatLng.lng;
|
||||
},
|
||||
|
||||
resetBounds: function () {
|
||||
//@ts-ignore
|
||||
this._path._bounds = new L.LatLngBounds();
|
||||
|
||||
this._path.eachLatLng(function (latlng) {
|
||||
this._bounds.extend(latlng);
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
L.Path.include({
|
||||
eachLatLng: function (callback, context) {
|
||||
context = context || this;
|
||||
|
||||
var loop = function (latlngs) {
|
||||
for (var i = 0; i < latlngs.length; i++) {
|
||||
if (L.Util.isArray(latlngs[i])) loop(latlngs[i]);
|
||||
else callback.call(context, latlngs[i]);
|
||||
}
|
||||
};
|
||||
|
||||
loop(this.getLatLngs ? this.getLatLngs() : [this.getLatLng()]);
|
||||
},
|
||||
});
|
||||
|
||||
L.Path.addInitHook(function () {
|
||||
//@ts-ignore
|
||||
this.dragging = new L.Handler.PathDrag(this);
|
||||
|
||||
if (this.options.draggable) {
|
||||
this.once("add", function () {
|
||||
this.dragging.enable();
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -3,13 +3,7 @@ import { getApp } from "../olympusapp";
|
||||
import { BoxSelect } from "./boxselect";
|
||||
import { Airbase } from "../mission/airbase";
|
||||
import { Unit } from "../unit/unit";
|
||||
import {
|
||||
areaContains,
|
||||
circleContains,
|
||||
deg2rad,
|
||||
getGroundElevation,
|
||||
polyContains,
|
||||
} from "../other/utils";
|
||||
import { areaContains, deg2rad, getFunctionArguments, getGroundElevation } from "../other/utils";
|
||||
import { TemporaryUnitMarker } from "./markers/temporaryunitmarker";
|
||||
import { ClickableMiniMap } from "./clickableminimap";
|
||||
import {
|
||||
@@ -38,12 +32,14 @@ import "./markers/stylesheets/units.css";
|
||||
import "./map.css";
|
||||
import { CoalitionCircle } from "./coalitionarea/coalitioncircle";
|
||||
|
||||
import "leaflet-path-drag";
|
||||
import { faLeftLong } from "@fortawesome/free-solid-svg-icons";
|
||||
import { initDraggablePath } from "./coalitionarea/draggablepath";
|
||||
import { faDrawPolygon, faJetFighter, faMap } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
/* Register the handler for the box selection */
|
||||
L.Map.addInitHook("addHandler", "boxSelect", BoxSelect);
|
||||
|
||||
initDraggablePath();
|
||||
|
||||
export class Map extends L.Map {
|
||||
/* Options */
|
||||
#options: MapOptions = MAP_OPTIONS_DEFAULTS;
|
||||
@@ -413,63 +409,83 @@ export class Map extends L.Map {
|
||||
return [
|
||||
{
|
||||
actions: ["Tap"],
|
||||
target: faJetFighter,
|
||||
text: "Select unit",
|
||||
},
|
||||
{
|
||||
actions: ["Shift", "Drag"],
|
||||
target: faMap,
|
||||
text: "Box selection",
|
||||
},
|
||||
{
|
||||
actions: ["Press", "Drag"],
|
||||
target: faMap,
|
||||
text: "Box selection",
|
||||
},
|
||||
{
|
||||
actions: ["Drag"],
|
||||
target: faMap,
|
||||
text: "Move map location",
|
||||
},
|
||||
{
|
||||
actions: ["Long tap", "Drag"],
|
||||
text: "Box selection",
|
||||
},
|
||||
];
|
||||
} else if (this.#state === SPAWN_UNIT) {
|
||||
return [
|
||||
{
|
||||
actions: ["Tap"],
|
||||
target: faMap,
|
||||
text: "Spawn unit",
|
||||
},
|
||||
{
|
||||
actions: ["Double tap"],
|
||||
target: faMap,
|
||||
text: "Exit spawn mode",
|
||||
},
|
||||
{
|
||||
actions: ["Drag"],
|
||||
target: faMap,
|
||||
text: "Move map location",
|
||||
},
|
||||
];
|
||||
} else if (this.#state === CONTEXT_ACTION) {
|
||||
return [
|
||||
{
|
||||
actions: ["Tap"],
|
||||
text: this.#contextAction?.getLabel() ?? "",
|
||||
},
|
||||
let controls = [
|
||||
{
|
||||
actions: ["Double tap"],
|
||||
text: "Exit action mode",
|
||||
target: faMap,
|
||||
text: "Deselect units",
|
||||
},
|
||||
{
|
||||
actions: ["Drag"],
|
||||
target: faMap,
|
||||
text: "Move map location",
|
||||
},
|
||||
];
|
||||
|
||||
if (this.#contextAction) {
|
||||
/* TODO: I don't like this approach, it relies on the arguments names of the callback. We should find a better method */
|
||||
const args = getFunctionArguments(this.#contextAction.getCallback());
|
||||
controls.push({
|
||||
actions: ["Tap"],
|
||||
target: args.includes("targetUnit")? faJetFighter: faMap,
|
||||
text: this.#contextAction?.getLabel() ?? "",
|
||||
});
|
||||
}
|
||||
|
||||
return controls;
|
||||
} else if (this.#state === COALITIONAREA_EDIT) {
|
||||
return [
|
||||
{
|
||||
actions: ["Tap"],
|
||||
target: faDrawPolygon,
|
||||
text: "Select shape",
|
||||
},
|
||||
{
|
||||
actions: ["Double tap"],
|
||||
target: faMap,
|
||||
text: "Exit drawing mode",
|
||||
},
|
||||
{
|
||||
actions: ["Drag"],
|
||||
target: faMap,
|
||||
text: "Move map location",
|
||||
},
|
||||
];
|
||||
@@ -477,14 +493,17 @@ export class Map extends L.Map {
|
||||
return [
|
||||
{
|
||||
actions: ["Tap"],
|
||||
target: faMap,
|
||||
text: "Add vertex to polygon",
|
||||
},
|
||||
{
|
||||
actions: ["Double tap"],
|
||||
target: faMap,
|
||||
text: "Finalize polygon",
|
||||
},
|
||||
{
|
||||
actions: ["Drag"],
|
||||
target: faMap,
|
||||
text: "Move map location",
|
||||
},
|
||||
];
|
||||
@@ -492,10 +511,12 @@ export class Map extends L.Map {
|
||||
return [
|
||||
{
|
||||
actions: ["Tap"],
|
||||
target: faMap,
|
||||
text: "Add circle",
|
||||
},
|
||||
{
|
||||
actions: ["Drag"],
|
||||
target: faMap,
|
||||
text: "Move map location",
|
||||
},
|
||||
];
|
||||
@@ -801,7 +822,8 @@ export class Map extends L.Map {
|
||||
|
||||
this.#longPressTimer = window.setTimeout(() => {
|
||||
/* If the mouse is still being pressed, execute the long press action */
|
||||
if (this.#isMouseDown) this.#onLongPress(e);
|
||||
if (this.#isMouseDown && !this.#isDragging && !this.#isZooming)
|
||||
this.#onLongPress(e);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
@@ -822,15 +844,20 @@ export class Map extends L.Map {
|
||||
}
|
||||
|
||||
#onShortPress(e: any) {
|
||||
console.log(`Short press at ${e.latlng}`);
|
||||
let touchLocation: L.LatLng;
|
||||
if (e.type === "touchstart")
|
||||
touchLocation = this.containerPointToLatLng(
|
||||
this.mouseEventToContainerPoint(e.touches[0])
|
||||
);
|
||||
else touchLocation = new L.LatLng(e.latlng.lat, e.latlng.lng);
|
||||
|
||||
const location = new L.LatLng(e.latlng.lat, e.latlng.lng);
|
||||
console.log(`Short press at ${touchLocation}`);
|
||||
|
||||
/* Execute the short click action */
|
||||
if (this.#state === IDLE) {
|
||||
} else if (this.#state === SPAWN_UNIT) {
|
||||
if (this.#spawnRequestTable !== null) {
|
||||
this.#spawnRequestTable.unit.location = location;
|
||||
this.#spawnRequestTable.unit.location = touchLocation;
|
||||
getApp()
|
||||
.getUnitsManager()
|
||||
.spawnUnits(
|
||||
@@ -842,7 +869,7 @@ export class Map extends L.Map {
|
||||
undefined,
|
||||
(hash) => {
|
||||
this.addTemporaryMarker(
|
||||
location,
|
||||
touchLocation,
|
||||
this.#spawnRequestTable?.unit.unitType ?? "unknown",
|
||||
this.#spawnRequestTable?.coalition ?? "blue",
|
||||
hash
|
||||
@@ -853,7 +880,7 @@ export class Map extends L.Map {
|
||||
} else if (this.#state === COALITIONAREA_DRAW_POLYGON) {
|
||||
const selectedArea = this.getSelectedCoalitionArea();
|
||||
if (selectedArea && selectedArea instanceof CoalitionPolygon) {
|
||||
selectedArea.addTemporaryLatLng(location);
|
||||
selectedArea.addTemporaryLatLng(touchLocation);
|
||||
}
|
||||
} else if (this.#state === COALITIONAREA_DRAW_CIRCLE) {
|
||||
const selectedArea = this.getSelectedCoalitionArea();
|
||||
@@ -862,13 +889,13 @@ export class Map extends L.Map {
|
||||
selectedArea.getLatLng().lat == 0 &&
|
||||
selectedArea.getLatLng().lng == 0
|
||||
)
|
||||
selectedArea.setLatLng(location);
|
||||
selectedArea.setLatLng(touchLocation);
|
||||
this.setState(COALITIONAREA_EDIT);
|
||||
}
|
||||
} else if (this.#state == COALITIONAREA_EDIT) {
|
||||
this.deselectAllCoalitionAreas();
|
||||
for (let idx = 0; idx < this.#coalitionAreas.length; idx++) {
|
||||
if (areaContains(e.latlng, this.#coalitionAreas[idx])) {
|
||||
if (areaContains(touchLocation, this.#coalitionAreas[idx])) {
|
||||
this.#coalitionAreas[idx].setSelected(true);
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("coalitionAreaSelected", {
|
||||
@@ -879,18 +906,24 @@ export class Map extends L.Map {
|
||||
}
|
||||
}
|
||||
} else if (this.#state === CONTEXT_ACTION) {
|
||||
this.executeContextAction(null, e.latlng);
|
||||
this.executeContextAction(null, touchLocation);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
#onLongPress(e: any) {
|
||||
console.log(`Long press at ${e.latlng}`);
|
||||
let touchLocation: L.LatLng;
|
||||
if (e.type === "touchstart")
|
||||
touchLocation = this.containerPointToLatLng(
|
||||
this.mouseEventToContainerPoint(e.touches[0])
|
||||
);
|
||||
else touchLocation = new L.LatLng(e.latlng.lat, e.latlng.lng);
|
||||
|
||||
this.deselectAllCoalitionAreas();
|
||||
console.log(`Long press at ${touchLocation}`);
|
||||
|
||||
if (!this.#isDragging && !this.#isZooming) {
|
||||
if (this.#state == IDLE) {
|
||||
this.deselectAllCoalitionAreas();
|
||||
if (this.#state === IDLE) {
|
||||
if (e.type === "touchstart")
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("mapForceBoxSelect", { detail: e })
|
||||
@@ -908,7 +941,7 @@ export class Map extends L.Map {
|
||||
|
||||
this.#lastMousePosition.x = e.originalEvent.x;
|
||||
this.#lastMousePosition.y = e.originalEvent.y;
|
||||
this.#lastMouseCoordinates = this.mouseEventToLatLng(e.originalEvent);
|
||||
this.#lastMouseCoordinates = e.latlng;
|
||||
}
|
||||
|
||||
#onMapMove(e: any) {
|
||||
|
||||
Reference in New Issue
Block a user