mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Added ability to draw coalition areas (WIP)
This commit is contained in:
@@ -259,7 +259,8 @@ export const defaultMapLayers = {};
|
||||
export const IDLE = "Idle";
|
||||
export const SPAWN_UNIT = "Spawn unit";
|
||||
export const CONTEXT_ACTION = "Context action";
|
||||
export const COALITIONAREA_DRAW_POLYGON = "Draw Coalition Area";
|
||||
export const COALITIONAREA_DRAW_POLYGON = "Draw Coalition Area polygon";
|
||||
export const COALITIONAREA_EDIT = "Edit Coalition Area";
|
||||
|
||||
export const IADSTypes = ["AAA", "SAM Site", "Radar (EWR)"];
|
||||
export const IADSDensities: { [key: string]: number } = {
|
||||
|
||||
@@ -31,7 +31,6 @@ export class CoalitionArea extends Polygon {
|
||||
|
||||
super(latlngs, options);
|
||||
this.#setColors();
|
||||
this.#registerCallbacks();
|
||||
|
||||
if (
|
||||
[BLUE_COMMANDER, RED_COMMANDER].includes(
|
||||
@@ -175,20 +174,4 @@ export class CoalitionArea extends Polygon {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#registerCallbacks() {
|
||||
this.on("click", (e: any) => {
|
||||
getApp().getMap().deselectAllCoalitionAreas();
|
||||
if (!this.getSelected()) {
|
||||
this.setSelected(true);
|
||||
}
|
||||
});
|
||||
|
||||
this.on("contextmenu", (e: any) => {
|
||||
if (!this.getEditing()) {
|
||||
getApp().getMap().deselectAllCoalitionAreas();
|
||||
this.setSelected(true);
|
||||
} else this.setEditing(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -97,3 +97,24 @@
|
||||
* {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ol-coalitionarea-handle-icon {
|
||||
background-color: #FFFFFFAA;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.ol-coalitionarea-handle-icon {
|
||||
background-color: #FFFFFFAA;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.ol-coalitionarea-middle-handle-icon {
|
||||
background-color: #FFFFFFAA;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 999px;
|
||||
}
|
||||
@@ -3,13 +3,7 @@ import { getApp } from "../olympusapp";
|
||||
import { BoxSelect } from "./boxselect";
|
||||
import { Airbase } from "../mission/airbase";
|
||||
import { Unit } from "../unit/unit";
|
||||
import {
|
||||
bearing,
|
||||
deg2rad,
|
||||
getGroundElevation,
|
||||
polyContains,
|
||||
} from "../other/utils";
|
||||
import { DestinationPreviewMarker } from "./markers/destinationpreviewmarker";
|
||||
import { deg2rad, getGroundElevation, polyContains } from "../other/utils";
|
||||
import { TemporaryUnitMarker } from "./markers/temporaryunitmarker";
|
||||
import { ClickableMiniMap } from "./clickableminimap";
|
||||
import {
|
||||
@@ -23,21 +17,19 @@ import {
|
||||
CONTEXT_ACTION,
|
||||
MAP_OPTIONS_DEFAULTS,
|
||||
MAP_HIDDEN_TYPES_DEFAULTS,
|
||||
COALITIONAREA_EDIT,
|
||||
} from "../constants/constants";
|
||||
import { CoalitionArea } from "./coalitionarea/coalitionarea";
|
||||
import { TouchBoxSelect } from "./touchboxselect";
|
||||
import { DestinationPreviewHandle } from "./markers/destinationpreviewHandle";
|
||||
|
||||
import "./markers/stylesheets/airbase.css";
|
||||
import "./markers/stylesheets/bullseye.css";
|
||||
import "./markers/stylesheets/units.css";
|
||||
|
||||
// Temporary
|
||||
import "./theme.css";
|
||||
import { MapHiddenTypes, MapOptions } from "../types/types";
|
||||
import { SpawnRequestTable } from "../interfaces";
|
||||
import { ContextAction } from "../unit/contextaction";
|
||||
|
||||
/* Stylesheets */
|
||||
import "./markers/stylesheets/airbase.css";
|
||||
import "./markers/stylesheets/bullseye.css";
|
||||
import "./markers/stylesheets/units.css";
|
||||
import "./map.css";
|
||||
|
||||
L.Map.addInitHook("addHandler", "boxSelect", BoxSelect);
|
||||
|
||||
export class Map extends L.Map {
|
||||
@@ -45,58 +37,68 @@ export class Map extends L.Map {
|
||||
#options: MapOptions = MAP_OPTIONS_DEFAULTS;
|
||||
#hiddenTypes: MapHiddenTypes = MAP_HIDDEN_TYPES_DEFAULTS;
|
||||
|
||||
#ID: string;
|
||||
/* State machine */
|
||||
#state: string;
|
||||
|
||||
/* Map layers */
|
||||
#theatre: string = "";
|
||||
#layer: L.TileLayer | L.LayerGroup | null = null;
|
||||
#layerName: string = "";
|
||||
#mapLayers: any = defaultMapLayers;
|
||||
#mapMirrors: any = defaultMapMirrors;
|
||||
|
||||
#spawnRequestTable: SpawnRequestTable | null = null;
|
||||
/* Inputs timers */
|
||||
#mouseCooldownTimer: number = 0;
|
||||
#shortPressTimer: number = 0;
|
||||
#longPressTimer: number = 0;
|
||||
|
||||
#preventLeftClick: boolean = false;
|
||||
#leftClickTimer: number = 0;
|
||||
#deafultPanDelta: number = 100;
|
||||
/* Camera keyboard panning control */
|
||||
defaultPanDelta: number = 100;
|
||||
#panInterval: number | null = null;
|
||||
#panLeft: boolean = false;
|
||||
#panRight: boolean = false;
|
||||
#panUp: boolean = false;
|
||||
#panDown: boolean = false;
|
||||
|
||||
#lastMousePosition: L.Point = new L.Point(0, 0);
|
||||
#lastMouseCoordinates: L.LatLng = new L.LatLng(0, 0);
|
||||
/* Keyboard state */
|
||||
#isShiftKeyDown: boolean = false;
|
||||
|
||||
#shiftKey: boolean = false;
|
||||
#centerUnit: Unit | null = null;
|
||||
/* Center on unit target */
|
||||
#centeredUnit: Unit | null = null;
|
||||
|
||||
/* Minimap */
|
||||
#miniMap: ClickableMiniMap | null = null;
|
||||
#miniMapLayerGroup: L.LayerGroup;
|
||||
#miniMapPolyline: L.Polyline;
|
||||
|
||||
#temporaryMarkers: TemporaryUnitMarker[] = [];
|
||||
|
||||
#isSelecting: boolean = false;
|
||||
/* Other state controls */
|
||||
#isMouseOnCooldown: boolean = false;
|
||||
#isZooming: boolean = false;
|
||||
#isDragging: boolean = false;
|
||||
#isMouseDown: boolean = false;
|
||||
#lastMousePosition: L.Point = new L.Point(0, 0);
|
||||
#lastMouseCoordinates: L.LatLng = new L.LatLng(0, 0);
|
||||
#previousZoom: number = 0;
|
||||
|
||||
/* Camera control plugin */
|
||||
#slaveDCSCamera: boolean = false;
|
||||
#slaveDCSCameraAvailable: boolean = false;
|
||||
#cameraControlTimer: number = 0;
|
||||
#cameraControlPort: number = 3003;
|
||||
#cameraControlMode: string = "map";
|
||||
|
||||
#coalitionAreas: CoalitionArea[] = [];
|
||||
|
||||
#mapLayers: any = defaultMapLayers;
|
||||
#mapMirrors: any = defaultMapMirrors;
|
||||
#layerName: string = "";
|
||||
#cameraOptionsXmlHttp: XMLHttpRequest | null = null;
|
||||
#bradcastPositionXmlHttp: XMLHttpRequest | null = null;
|
||||
#cameraZoomRatio: number = 1.0;
|
||||
|
||||
/* Coalition areas drawing */
|
||||
#coalitionAreas: CoalitionArea[] = [];
|
||||
|
||||
/* Unit context actions */
|
||||
#contextAction: null | ContextAction = null;
|
||||
#theatre: string = "";
|
||||
#waitingForDoubleClick: boolean = false;
|
||||
#doubleClickTimer: number = 0;
|
||||
#longPressTimer: number = 0;
|
||||
#isDragging: boolean = false;
|
||||
|
||||
/* Unit spawning */
|
||||
#spawnRequestTable: SpawnRequestTable | null = null;
|
||||
#temporaryMarkers: TemporaryUnitMarker[] = [];
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -119,8 +121,6 @@ export class Map extends L.Map {
|
||||
});
|
||||
this.setView([37.23, -115.8], 10);
|
||||
|
||||
this.#ID = ID;
|
||||
|
||||
/* Minimap */
|
||||
var minimapLayer = new L.TileLayer(
|
||||
"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
|
||||
@@ -134,24 +134,28 @@ export class Map extends L.Map {
|
||||
this.#state = IDLE;
|
||||
|
||||
/* Register event handles */
|
||||
this.on("click", (e: any) => this.#onClick(e));
|
||||
this.on("dblclick", (e: any) => this.#onDoubleClick(e));
|
||||
this.on("zoomstart", (e: any) => this.#onZoomStart(e));
|
||||
this.on("zoom", (e: any) => this.#onZoom(e));
|
||||
this.on("zoomend", (e: any) => this.#onZoomEnd(e));
|
||||
this.on("drag", (e: any) => this.centerOnUnit(null));
|
||||
|
||||
this.on("dragstart", (e: any) => this.#onDragStart(e));
|
||||
this.on("drag", (e: any) => this.centerOnUnit(null));
|
||||
this.on("dragend", (e: any) => this.#onDragEnd(e));
|
||||
this.on("contextmenu", (e: any) => this.#onContextMenu(e));
|
||||
|
||||
this.on("selectionstart", (e: any) => this.#onSelectionStart(e));
|
||||
this.on("selectionend", (e: any) => this.#onSelectionEnd(e));
|
||||
|
||||
this.on("dblclick", (e: any) => this.#onDoubleClick(e));
|
||||
this.on("mouseup", (e: any) => this.#onMouseUp(e));
|
||||
this.on("mousedown", (e: any) => this.#onMouseDown(e));
|
||||
|
||||
this.on("mousemove", (e: any) => this.#onMouseMove(e));
|
||||
|
||||
this.on("keydown", (e: any) => this.#onKeyDown(e));
|
||||
this.on("keyup", (e: any) => this.#onKeyUp(e));
|
||||
|
||||
this.on("move", (e: any) => {
|
||||
if (this.#slaveDCSCamera) this.#broadcastPosition();
|
||||
this.#onMapMove(e);
|
||||
});
|
||||
|
||||
L.DomEvent.on(this.getContainer(), "touchstart", this.#onMouseDown, this);
|
||||
@@ -259,11 +263,11 @@ export class Map extends L.Map {
|
||||
this.panBy(
|
||||
new L.Point(
|
||||
((this.#panLeft ? -1 : 0) + (this.#panRight ? 1 : 0)) *
|
||||
this.#deafultPanDelta *
|
||||
(this.#shiftKey ? 3 : 1),
|
||||
this.defaultPanDelta *
|
||||
(this.#isShiftKeyDown ? 3 : 1),
|
||||
((this.#panUp ? -1 : 0) + (this.#panDown ? 1 : 0)) *
|
||||
this.#deafultPanDelta *
|
||||
(this.#shiftKey ? 3 : 1)
|
||||
this.defaultPanDelta *
|
||||
(this.#isShiftKeyDown ? 3 : 1)
|
||||
)
|
||||
);
|
||||
}, 20);
|
||||
@@ -368,6 +372,9 @@ export class Map extends L.Map {
|
||||
|
||||
/* Operations to perform if you are NOT in a state */
|
||||
if (this.#state !== COALITIONAREA_DRAW_POLYGON) {
|
||||
this.getSelectedCoalitionArea()?.setEditing(false);
|
||||
}
|
||||
if (this.#state !== COALITIONAREA_EDIT) {
|
||||
this.#deselectSelectedCoalitionArea();
|
||||
}
|
||||
|
||||
@@ -416,104 +423,6 @@ export class Map extends L.Map {
|
||||
return this.#hiddenTypes;
|
||||
}
|
||||
|
||||
/* Context Menus */
|
||||
hideAllContextMenus() {
|
||||
this.hideMapContextMenu();
|
||||
this.hideUnitContextMenu();
|
||||
this.hideAirbaseContextMenu();
|
||||
this.hideAirbaseSpawnMenu();
|
||||
this.hideCoalitionAreaContextMenu();
|
||||
}
|
||||
|
||||
showMapContextMenu(x: number, y: number, latlng: L.LatLng) {
|
||||
//this.hideAllContextMenus();
|
||||
//this.#mapContextMenu.show(x, y, latlng);
|
||||
//document.dispatchEvent(new CustomEvent("mapContextMenu"));
|
||||
}
|
||||
|
||||
hideMapContextMenu() {
|
||||
//this.#mapContextMenu.hide();
|
||||
//document.dispatchEvent(new CustomEvent("mapContextMenu"));
|
||||
}
|
||||
|
||||
getMapContextMenu() {
|
||||
return null; //this.#mapContextMenu;
|
||||
}
|
||||
|
||||
showUnitContextMenu(
|
||||
x: number | undefined = undefined,
|
||||
y: number | undefined = undefined,
|
||||
latlng: L.LatLng | undefined = undefined
|
||||
) {
|
||||
//this.hideAllContextMenus();
|
||||
//this.#unitContextMenu.show(x, y, latlng);
|
||||
}
|
||||
|
||||
getUnitContextMenu() {
|
||||
return null; //this.#unitContextMenu;
|
||||
}
|
||||
|
||||
hideUnitContextMenu() {
|
||||
//this.#unitContextMenu.hide();
|
||||
}
|
||||
|
||||
showAirbaseContextMenu(
|
||||
airbase: Airbase,
|
||||
x: number | undefined = undefined,
|
||||
y: number | undefined = undefined,
|
||||
latlng: L.LatLng | undefined = undefined
|
||||
) {
|
||||
//this.hideAllContextMenus();
|
||||
//this.#airbaseContextMenu.show(x, y, latlng);
|
||||
//this.#airbaseContextMenu.setAirbase(airbase);
|
||||
}
|
||||
|
||||
getAirbaseContextMenu() {
|
||||
return null; //this.#airbaseContextMenu;
|
||||
}
|
||||
|
||||
hideAirbaseContextMenu() {
|
||||
//this.#airbaseContextMenu.hide();
|
||||
}
|
||||
|
||||
showAirbaseSpawnMenu(
|
||||
airbase: Airbase,
|
||||
x: number | undefined = undefined,
|
||||
y: number | undefined = undefined,
|
||||
latlng: L.LatLng | undefined = undefined
|
||||
) {
|
||||
//this.hideAllContextMenus();
|
||||
//this.#airbaseSpawnMenu.show(x, y);
|
||||
//this.#airbaseSpawnMenu.setAirbase(airbase);
|
||||
}
|
||||
|
||||
getAirbaseSpawnMenu() {
|
||||
return null; //this.#airbaseSpawnMenu;
|
||||
}
|
||||
|
||||
hideAirbaseSpawnMenu() {
|
||||
//this.#airbaseSpawnMenu.hide();
|
||||
}
|
||||
|
||||
showCoalitionAreaContextMenu(
|
||||
x: number,
|
||||
y: number,
|
||||
latlng: L.LatLng,
|
||||
coalitionArea: CoalitionArea
|
||||
) {
|
||||
//this.hideAllContextMenus();
|
||||
//this.#coalitionAreaContextMenu.show(x, y, latlng);
|
||||
//this.#coalitionAreaContextMenu.setCoalitionArea(coalitionArea);
|
||||
}
|
||||
|
||||
getCoalitionAreaContextMenu() {
|
||||
return null; //this.#coalitionAreaContextMenu;
|
||||
}
|
||||
|
||||
hideCoalitionAreaContextMenu() {
|
||||
//this.#coalitionAreaContextMenu.hide();
|
||||
}
|
||||
|
||||
getMousePosition() {
|
||||
return this.#lastMousePosition;
|
||||
}
|
||||
@@ -525,15 +434,15 @@ export class Map extends L.Map {
|
||||
centerOnUnit(unit: Unit | null) {
|
||||
if (unit !== null) {
|
||||
this.options.scrollWheelZoom = "center";
|
||||
this.#centerUnit = unit;
|
||||
this.#centeredUnit = unit;
|
||||
} else {
|
||||
this.options.scrollWheelZoom = undefined;
|
||||
this.#centerUnit = null;
|
||||
this.#centeredUnit = null;
|
||||
}
|
||||
}
|
||||
|
||||
getCenteredOnUnit() {
|
||||
return this.#centerUnit;
|
||||
return this.#centeredUnit;
|
||||
}
|
||||
|
||||
setTheatre(theatre: string) {
|
||||
@@ -688,10 +597,6 @@ export class Map extends L.Map {
|
||||
return false;
|
||||
}
|
||||
|
||||
getMapMarkerVisibilityControls() {
|
||||
return null; //this.#mapMarkerVisibilityControls;
|
||||
}
|
||||
|
||||
setSlaveDCSCamera(newSlaveDCSCamera: boolean) {
|
||||
this.#slaveDCSCamera = newSlaveDCSCamera;
|
||||
let button = document.getElementById("camera-link-control");
|
||||
@@ -740,75 +645,6 @@ export class Map extends L.Map {
|
||||
}
|
||||
|
||||
/* Event handlers */
|
||||
#onClick(e: any) {
|
||||
/* Exit if we were waiting for a doubleclick */
|
||||
if (this.#waitingForDoubleClick) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* We'll wait for a doubleclick */
|
||||
this.#waitingForDoubleClick = true;
|
||||
|
||||
this.#doubleClickTimer = window.setTimeout(() => {
|
||||
/* Still waiting so no doubleclick; do the click action */
|
||||
if (this.#waitingForDoubleClick) {
|
||||
if (!this.#preventLeftClick) {
|
||||
/* Execute the short click action */
|
||||
if (this.#state === IDLE) {
|
||||
this.deselectAllCoalitionAreas();
|
||||
} else if (this.#state === SPAWN_UNIT) {
|
||||
if (this.#spawnRequestTable !== null) {
|
||||
const location = e.latlng;
|
||||
this.#spawnRequestTable.unit.location = e.latlng;
|
||||
getApp()
|
||||
.getUnitsManager()
|
||||
.spawnUnits(
|
||||
this.#spawnRequestTable.category,
|
||||
[this.#spawnRequestTable.unit],
|
||||
this.#spawnRequestTable.coalition,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
(hash) => {
|
||||
this.addTemporaryMarker(
|
||||
location,
|
||||
this.#spawnRequestTable?.unit.unitType ?? "unknown",
|
||||
this.#spawnRequestTable?.coalition ?? "blue",
|
||||
hash
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
} else if (this.#state === COALITIONAREA_DRAW_POLYGON) {
|
||||
if (this.getSelectedCoalitionArea()?.getEditing()) {
|
||||
this.getSelectedCoalitionArea()?.addTemporaryLatLng(e.latlng);
|
||||
} else {
|
||||
this.deselectAllCoalitionAreas();
|
||||
}
|
||||
} else if (this.#state === CONTEXT_ACTION) {
|
||||
this.executeContextAction(null, e.latlng);
|
||||
} else {
|
||||
this.setState(IDLE);
|
||||
getApp().getUnitsManager().deselectAllUnits();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No longer waiting for a doubleclick */
|
||||
this.#waitingForDoubleClick = false;
|
||||
}, 200);
|
||||
}
|
||||
|
||||
#onDoubleClick(e: any) {
|
||||
/* Let single clicks work again */
|
||||
this.#waitingForDoubleClick = false;
|
||||
clearTimeout(this.#doubleClickTimer);
|
||||
|
||||
this.setState(IDLE);
|
||||
}
|
||||
|
||||
#onContextMenu(e: any) {}
|
||||
|
||||
#onDragStart(e: any) {
|
||||
this.#isDragging = true;
|
||||
}
|
||||
@@ -818,27 +654,103 @@ export class Map extends L.Map {
|
||||
}
|
||||
|
||||
#onSelectionStart(e: any) {
|
||||
this.#isSelecting = true;
|
||||
}
|
||||
|
||||
#onSelectionEnd(e: any) {
|
||||
this.#isSelecting = false;
|
||||
clearTimeout(this.#leftClickTimer);
|
||||
this.#preventLeftClick = true;
|
||||
this.#leftClickTimer = window.setTimeout(() => {
|
||||
this.#preventLeftClick = false;
|
||||
}, 200);
|
||||
getApp().getUnitsManager().selectFromBounds(e.selectionBounds);
|
||||
document.dispatchEvent(new CustomEvent("mapSelectionEnd"));
|
||||
}
|
||||
|
||||
#onMouseUp(e: any) {
|
||||
this.#isMouseDown = false;
|
||||
window.clearTimeout(this.#longPressTimer);
|
||||
|
||||
this.#isMouseOnCooldown = true;
|
||||
this.#mouseCooldownTimer = window.setTimeout(() => {
|
||||
this.#isMouseOnCooldown = false;
|
||||
}, 200);
|
||||
}
|
||||
|
||||
#onMouseDown(e: any) {
|
||||
this.#isMouseDown = true;
|
||||
|
||||
if (this.#isMouseOnCooldown) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#shortPressTimer = window.setTimeout(() => {
|
||||
/* If the mouse is no longer being pressed, execute the short press action */
|
||||
if (!this.#isMouseDown) this.#onShortPress(e);
|
||||
}, 200);
|
||||
|
||||
this.#longPressTimer = window.setTimeout(() => {
|
||||
if (!this.#isDragging && !this.#isZooming)
|
||||
/* If the mouse is still being pressed, execute the long press action */
|
||||
if (this.#isMouseDown) this.#onLongPress(e);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
#onDoubleClick(e: any) {
|
||||
console.log(`Double click at ${e.latlng}`);
|
||||
|
||||
window.clearTimeout(this.#shortPressTimer);
|
||||
window.clearTimeout(this.#longPressTimer);
|
||||
|
||||
if (this.#state === COALITIONAREA_DRAW_POLYGON) {
|
||||
this.setState(COALITIONAREA_EDIT);
|
||||
} else {
|
||||
this.setState(IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
#onShortPress(e: any) {
|
||||
console.log(`Short press at ${e.latlng}`);
|
||||
|
||||
const location = new L.LatLng(e.latlng.lat, e.latlng.lng);
|
||||
|
||||
/* Execute the short click action */
|
||||
if (this.#state === IDLE) {
|
||||
this.deselectAllCoalitionAreas();
|
||||
} else if (this.#state === SPAWN_UNIT) {
|
||||
if (this.#spawnRequestTable !== null) {
|
||||
this.#spawnRequestTable.unit.location = location;
|
||||
getApp()
|
||||
.getUnitsManager()
|
||||
.spawnUnits(
|
||||
this.#spawnRequestTable.category,
|
||||
[this.#spawnRequestTable.unit],
|
||||
this.#spawnRequestTable.coalition,
|
||||
false,
|
||||
undefined,
|
||||
undefined,
|
||||
(hash) => {
|
||||
this.addTemporaryMarker(
|
||||
location,
|
||||
this.#spawnRequestTable?.unit.unitType ?? "unknown",
|
||||
this.#spawnRequestTable?.coalition ?? "blue",
|
||||
hash
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
} else if (this.#state === COALITIONAREA_DRAW_POLYGON) {
|
||||
if (this.getSelectedCoalitionArea()?.getEditing()) {
|
||||
this.getSelectedCoalitionArea()?.addTemporaryLatLng(location);
|
||||
} else {
|
||||
this.deselectAllCoalitionAreas();
|
||||
}
|
||||
} else if (this.#state === COALITIONAREA_EDIT) {
|
||||
this.deselectAllCoalitionAreas();
|
||||
} else if (this.#state === CONTEXT_ACTION) {
|
||||
this.executeContextAction(null, e.latlng);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
#onLongPress(e: any) {
|
||||
console.log(`Long press at ${e.latlng}`);
|
||||
|
||||
if (!this.#isDragging && !this.#isZooming) {
|
||||
if (this.getState() == IDLE) {
|
||||
if (e.type === "touchstart")
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("mapForceBoxSelect", { detail: e })
|
||||
@@ -847,36 +759,50 @@ export class Map extends L.Map {
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("mapForceBoxSelect", { detail: e.originalEvent })
|
||||
);
|
||||
}, 500);
|
||||
} else if (this.getState() == COALITIONAREA_EDIT) {
|
||||
for (let idx = 0; idx < this.#coalitionAreas.length; idx++) {
|
||||
if (polyContains(e.latlng, this.#coalitionAreas[idx])) {
|
||||
this.#coalitionAreas[idx].setSelected(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#onMouseMove(e: any) {
|
||||
window.clearTimeout(this.#longPressTimer);
|
||||
|
||||
this.#lastMousePosition.x = e.originalEvent.x;
|
||||
this.#lastMousePosition.y = e.originalEvent.y;
|
||||
this.#lastMouseCoordinates = this.mouseEventToLatLng(e.originalEvent);
|
||||
|
||||
if (this.#state === COALITIONAREA_DRAW_POLYGON && e.latlng !== undefined) {
|
||||
/* Update the polygon being drawn with the current position of the mouse cursor */
|
||||
this.getSelectedCoalitionArea()?.moveActiveVertex(e.latlng);
|
||||
//this.getSelectedCoalitionArea()?.moveActiveVertex(e.latlng);
|
||||
}
|
||||
}
|
||||
|
||||
#onMapMove(e: any) {
|
||||
if (this.#slaveDCSCamera) this.#broadcastPosition();
|
||||
}
|
||||
|
||||
#onKeyDown(e: any) {
|
||||
this.#shiftKey = e.originalEvent.shiftKey;
|
||||
this.#isShiftKeyDown = e.originalEvent.shiftKey;
|
||||
}
|
||||
|
||||
#onKeyUp(e: any) {
|
||||
this.#shiftKey = e.originalEvent.shiftKey;
|
||||
this.#isShiftKeyDown = e.originalEvent.shiftKey;
|
||||
}
|
||||
|
||||
#onZoomStart(e: any) {
|
||||
this.#previousZoom = this.getZoom();
|
||||
if (this.#centerUnit != null) this.#panToUnit(this.#centerUnit);
|
||||
if (this.#centeredUnit != null) this.#panToUnit(this.#centeredUnit);
|
||||
this.#isZooming = true;
|
||||
}
|
||||
|
||||
#onZoom(e: any) {
|
||||
if (this.#centerUnit != null) this.#panToUnit(this.#centerUnit);
|
||||
if (this.#centeredUnit != null) this.#panToUnit(this.#centeredUnit);
|
||||
}
|
||||
|
||||
#onZoomEnd(e: any) {
|
||||
|
||||
@@ -31,7 +31,7 @@ export class SmokeMarker extends CustomMarker {
|
||||
el.classList.add("ol-smoke-icon");
|
||||
el.setAttribute("data-color", this.#color);
|
||||
var img = document.createElement("img");
|
||||
img.src = "/images/markers/smoke.svg";
|
||||
img.src = "/vite/images/markers/smoke.svg";
|
||||
img.onload = () => SVGInjector(img);
|
||||
el.appendChild(img);
|
||||
this.getElement()?.appendChild(el);
|
||||
|
||||
@@ -288,15 +288,15 @@
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-state="rtb"] .unit-state {
|
||||
background-image: url("/images/states/rtb.svg");
|
||||
background-image: url("/vite/images/states/rtb.svg");
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-state="land"] .unit-state {
|
||||
background-image: url("/images/states/rtb.svg");
|
||||
background-image: url("/vite/images/states/rtb.svg");
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-state="idle"] .unit-state {
|
||||
background-image: url("/images/states/idle.svg");
|
||||
background-image: url("/vite/images/states/idle.svg");
|
||||
}
|
||||
|
||||
[data-object*="groundunit"][data-state="idle"] .unit-state,
|
||||
@@ -308,59 +308,59 @@
|
||||
[data-object|="unit"][data-state="bomb-point"] .unit-state,
|
||||
[data-object|="unit"][data-state="carpet-bombing"] .unit-state,
|
||||
[data-object|="unit"][data-state="fire-at-area"] .unit-state {
|
||||
background-image: url("/images/states/attack.svg");
|
||||
background-image: url("/vite/images/states/attack.svg");
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-state="follow"] .unit-state {
|
||||
background-image: url("/images/states/follow.svg");
|
||||
background-image: url("/vite/images/states/follow.svg");
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-state="refuel"] .unit-state {
|
||||
background-image: url("/images/states/refuel.svg");
|
||||
background-image: url("/vite/images/states/refuel.svg");
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-state="human"] .unit-state {
|
||||
background-image: url("/images/states/human.svg");
|
||||
background-image: url("/vite/images/states/human.svg");
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-state="dcs"] .unit-state {
|
||||
background-image: url("/images/states/dcs.svg");
|
||||
background-image: url("/vite/images/states/dcs.svg");
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-state="land-at-point"] .unit-state {
|
||||
background-image: url("/images/states/land-at-point.svg");
|
||||
background-image: url("/vite/images/states/land-at-point.svg");
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-state="no-task"] .unit-state {
|
||||
background-image: url("/images/states/no-task.svg");
|
||||
background-image: url("/vite/images/states/no-task.svg");
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-state="off"] .unit-state {
|
||||
background-image: url("/images/states/off.svg");
|
||||
background-image: url("/vite/images/states/off.svg");
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-state="tanker"] .unit-state {
|
||||
background-image: url("/images/states/tanker.svg");
|
||||
background-image: url("/vite/images/states/tanker.svg");
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-state="AWACS"] .unit-state {
|
||||
background-image: url("/images/states/awacs.svg");
|
||||
background-image: url("/vite/images/states/awacs.svg");
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-state="miss-on-purpose"] .unit-state {
|
||||
background-image: url("/images/states/miss-on-purpose.svg");
|
||||
background-image: url("/vite/images/states/miss-on-purpose.svg");
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-state="scenic-aaa"] .unit-state {
|
||||
background-image: url("/images/states/scenic-aaa.svg");
|
||||
background-image: url("/vite/images/states/scenic-aaa.svg");
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-state="simulate-fire-fight"] .unit-state {
|
||||
background-image: url("/images/states/simulate-fire-fight.svg");
|
||||
background-image: url("/vite/images/states/simulate-fire-fight.svg");
|
||||
}
|
||||
|
||||
[data-object|="unit"] .unit-health::before {
|
||||
background-image: url("/images/icons/health.svg");
|
||||
background-image: url("/vite/images/icons/health.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
content: " ";
|
||||
|
||||
@@ -67,7 +67,7 @@ export class TemporaryUnitMarker extends CustomMarker {
|
||||
unitIcon.classList.add("unit-icon");
|
||||
var img = document.createElement("img");
|
||||
|
||||
img.src = `/images/units/${databaseEntry?.markerFile ?? category}.svg`;
|
||||
img.src = `/vite/images/units/${databaseEntry?.markerFile ?? category}.svg`;
|
||||
img.onload = () => SVGInjector(img);
|
||||
unitIcon.appendChild(img);
|
||||
unitIcon.toggleAttribute("data-rotate-to-heading", false);
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
import { Map, Point } from "leaflet";
|
||||
import { Handler } from "leaflet";
|
||||
import { Util } from "leaflet";
|
||||
import { DomUtil } from "leaflet";
|
||||
import { DomEvent } from "leaflet";
|
||||
import { LatLngBounds } from "leaflet";
|
||||
import { Bounds } from "leaflet";
|
||||
|
||||
export var TouchBoxSelect = Handler.extend({
|
||||
initialize: function (map: Map) {
|
||||
this._map = map;
|
||||
this._container = map.getContainer();
|
||||
this._pane = map.getPanes().overlayPane;
|
||||
this._resetStateTimeout = 0;
|
||||
this._doubleClicked = false;
|
||||
map.on("unload", this._destroy, this);
|
||||
},
|
||||
|
||||
addHooks: function () {
|
||||
DomEvent.on(this._container, "touchstart", this._onMouseDown, this);
|
||||
},
|
||||
|
||||
removeHooks: function () {
|
||||
DomEvent.off(this._container, "touchstart", this._onMouseDown, this);
|
||||
},
|
||||
|
||||
moved: function () {
|
||||
return this._moved;
|
||||
},
|
||||
|
||||
_destroy: function () {
|
||||
DomUtil.remove(this._pane);
|
||||
delete this._pane;
|
||||
},
|
||||
|
||||
_resetState: function () {
|
||||
this._resetStateTimeout = 0;
|
||||
this._moved = false;
|
||||
},
|
||||
|
||||
_clearDeferredResetState: function () {
|
||||
if (this._resetStateTimeout !== 0) {
|
||||
clearTimeout(this._resetStateTimeout);
|
||||
this._resetStateTimeout = 0;
|
||||
}
|
||||
},
|
||||
|
||||
_onMouseDown: function (e: any) {
|
||||
if (e.which == 0) {
|
||||
this._map.fire("selectionstart");
|
||||
// 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();
|
||||
|
||||
this._startPoint = this._getMousePosition(e);
|
||||
|
||||
//@ts-ignore
|
||||
DomEvent.on(
|
||||
document,
|
||||
{
|
||||
contextmenu: DomEvent.stop,
|
||||
touchmove: this._onMouseMove,
|
||||
touchend: this._onMouseUp,
|
||||
},
|
||||
this
|
||||
);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
_onMouseMove: function (e: any) {
|
||||
if (!this._moved) {
|
||||
this._moved = true;
|
||||
|
||||
this._box = DomUtil.create("div", "leaflet-zoom-box", this._container);
|
||||
DomUtil.addClass(this._container, "leaflet-crosshair");
|
||||
}
|
||||
|
||||
this._point = this._getMousePosition(e);
|
||||
|
||||
var bounds = new Bounds(this._point, this._startPoint),
|
||||
size = bounds.getSize();
|
||||
|
||||
if (bounds.min != undefined) DomUtil.setPosition(this._box, bounds.min);
|
||||
|
||||
this._box.style.width = size.x + "px";
|
||||
this._box.style.height = size.y + "px";
|
||||
},
|
||||
|
||||
_finish: function () {
|
||||
if (this._moved) {
|
||||
DomUtil.remove(this._box);
|
||||
DomUtil.removeClass(this._container, "leaflet-crosshair");
|
||||
}
|
||||
|
||||
DomUtil.enableTextSelection();
|
||||
DomUtil.enableImageDrag();
|
||||
|
||||
//@ts-ignore
|
||||
DomEvent.off(
|
||||
document,
|
||||
{
|
||||
contextmenu: DomEvent.stop,
|
||||
touchmove: this._onMouseMove,
|
||||
touchend: this._onMouseUp,
|
||||
},
|
||||
this
|
||||
);
|
||||
},
|
||||
|
||||
_onMouseUp: function (e: any) {
|
||||
if (e.which !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._finish();
|
||||
|
||||
if (!this._moved) {
|
||||
return;
|
||||
}
|
||||
// Postpone to next JS tick so internal click event handling
|
||||
// still see it as "moved".
|
||||
window.setTimeout(Util.bind(this._resetState, this), 0);
|
||||
var bounds = new LatLngBounds(
|
||||
this._map.containerPointToLatLng(this._startPoint),
|
||||
this._map.containerPointToLatLng(this._point)
|
||||
);
|
||||
|
||||
this._map.fire("selectionend", { selectionBounds: bounds });
|
||||
},
|
||||
|
||||
_getMousePosition(e: any) {
|
||||
var scale = DomUtil.getScale(this._container),
|
||||
offset = scale.boundingClientRect; // left and top values are in page scale (like the event clientX/Y)
|
||||
|
||||
return new Point(
|
||||
// offset.left/top values are in page scale (like clientX/Y),
|
||||
// whereas clientLeft/Top (border width) values are the original values (before CSS scale applies).
|
||||
(e.touches[0].clientX - offset.left) / scale.x -
|
||||
this._container.clientLeft,
|
||||
(e.touches[0].clientY - offset.top) / scale.y - this._container.clientTop
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -38,7 +38,7 @@ export class Airbase extends CustomMarker {
|
||||
el.classList.add("airbase-icon");
|
||||
el.setAttribute("data-object", "airbase");
|
||||
var img = document.createElement("img");
|
||||
img.src = "/images/markers/airbase.svg";
|
||||
img.src = "/vite/images/markers/airbase.svg";
|
||||
img.onload = () => SVGInjector(img);
|
||||
el.appendChild(img);
|
||||
this.getElement()?.appendChild(el);
|
||||
|
||||
@@ -17,7 +17,7 @@ export class Bullseye extends CustomMarker {
|
||||
el.classList.add("bullseye-icon");
|
||||
el.setAttribute("data-object", "bullseye");
|
||||
var img = document.createElement("img");
|
||||
img.src = "/images/markers/bullseye.svg";
|
||||
img.src = "/vite/images/markers/bullseye.svg";
|
||||
img.onload = () => SVGInjector(img);
|
||||
el.appendChild(img);
|
||||
this.getElement()?.appendChild(el);
|
||||
|
||||
@@ -210,7 +210,7 @@ export class OlympusApp {
|
||||
|
||||
/* Load the config file from the server */
|
||||
const configRequest = new Request(
|
||||
window.location.href.split("?")[0].replace("vite/", "") +
|
||||
window.location.href.split("?")[0].replace("/vite", "/") +
|
||||
"resources/config"
|
||||
);
|
||||
fetch(configRequest)
|
||||
|
||||
@@ -175,7 +175,7 @@ export class ServerManager {
|
||||
}
|
||||
|
||||
setAddress(address: string) {
|
||||
this.#REST_ADDRESS = `${address}olympus`;
|
||||
this.#REST_ADDRESS = `${address.replace('vite', '')}olympus`;
|
||||
console.log(`Setting REST address to ${this.#REST_ADDRESS}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ export function OlStateButton(props: {
|
||||
icon: IconProp;
|
||||
tooltip: string;
|
||||
onClick: () => void;
|
||||
children?: JSX.Element | JSX.Element[];
|
||||
}) {
|
||||
var [hover, setHover] = useState(false);
|
||||
var buttonRef = useRef(null);
|
||||
@@ -47,7 +48,10 @@ export function OlStateButton(props: {
|
||||
setHover(false);
|
||||
}}
|
||||
>
|
||||
<FontAwesomeIcon icon={props.icon} />
|
||||
<div className="m-auto flex w-fit content-center justify-center gap-2">
|
||||
<FontAwesomeIcon icon={props.icon} className="m-auto"/>
|
||||
{props.children}
|
||||
</div>
|
||||
</button>
|
||||
{hover && <OlTooltip buttonRef={buttonRef} content={props.tooltip} />}
|
||||
</>
|
||||
|
||||
@@ -23,7 +23,7 @@ export function OlUnitSummary(props: {
|
||||
className={`
|
||||
absolute right-5 top-0 h-full object-cover opacity-10 invert
|
||||
`}
|
||||
src={"images/units/" + props.blueprint.filename}
|
||||
src={"vite/images/units/" + props.blueprint.filename}
|
||||
alt=""
|
||||
/>
|
||||
<div
|
||||
|
||||
@@ -45,7 +45,7 @@ export function LoginModal(props: {
|
||||
`}
|
||||
>
|
||||
<img
|
||||
src="/images/splash/1.jpg"
|
||||
src="/vite/images/splash/1.jpg"
|
||||
className={`contents-center w-full object-cover opacity-[7%]`}
|
||||
></img>
|
||||
<div
|
||||
@@ -106,7 +106,7 @@ export function LoginModal(props: {
|
||||
>
|
||||
<span className="size-[80px] min-w-14">
|
||||
<img
|
||||
src="..\images\olympus-500x500.png"
|
||||
src="..\vite\images\olympus-500x500.png"
|
||||
className={`flex w-full`}
|
||||
></img>
|
||||
</span>
|
||||
@@ -332,7 +332,7 @@ export function LoginModal(props: {
|
||||
>
|
||||
<Card className="flex">
|
||||
<img
|
||||
src="/images/splash/1.jpg"
|
||||
src="/vite/images/splash/1.jpg"
|
||||
className={`
|
||||
h-[40%] max-h-[120px] contents-center w-full rounded-md
|
||||
object-cover
|
||||
@@ -362,7 +362,7 @@ export function LoginModal(props: {
|
||||
</Card>
|
||||
<Card className="flex">
|
||||
<img
|
||||
src="/images/splash/1.jpg"
|
||||
src="/vite/images/splash/1.jpg"
|
||||
className={`
|
||||
h-[40%] max-h-[120px] contents-center w-full rounded-md
|
||||
object-cover
|
||||
|
||||
62
frontend/react/src/ui/panels/drawingmenu.tsx
Normal file
62
frontend/react/src/ui/panels/drawingmenu.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Menu } from "./components/menu";
|
||||
import { FaQuestionCircle } from "react-icons/fa";
|
||||
import { getApp } from "../../olympusapp";
|
||||
import { COALITIONAREA_DRAW_POLYGON, COALITIONAREA_EDIT, IDLE } from "../../constants/constants";
|
||||
import { OlStateButton } from "../components/olstatebutton";
|
||||
import { faDrawPolygon } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
export function DrawingMenu(props: { open: boolean; onClose: () => void }) {
|
||||
const [drawingPolygon, setDrawingPolygon] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (props.open && !drawingPolygon) {
|
||||
getApp().getMap().setState(COALITIONAREA_EDIT);
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<Menu
|
||||
open={props.open}
|
||||
title="Draw"
|
||||
onClose={props.onClose}
|
||||
canBeHidden={true}
|
||||
>
|
||||
<div className="p-4 text-sm text-gray-400">
|
||||
The draw tool allows you to quickly draw areas on the map and use these
|
||||
areas to spawn units and activate triggers.
|
||||
</div>
|
||||
<div className="mx-6 my-2 flex rounded-lg bg-olympus-400 p-4 text-sm">
|
||||
<div>
|
||||
<FaQuestionCircle className="my-4 ml-2 mr-6 text-gray-400" />
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="text-gray-100">
|
||||
Use the polygon or paint tool to draw areas on the map.
|
||||
</div>
|
||||
<div className="text-gray-400">
|
||||
After drawing a shape, select it to see the options for spawning
|
||||
units.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6 text-sm text-gray-400">
|
||||
<OlStateButton
|
||||
className="!w-full"
|
||||
icon={faDrawPolygon}
|
||||
tooltip={"Add a new polygon"}
|
||||
checked={drawingPolygon}
|
||||
onClick={() => {
|
||||
if (drawingPolygon)
|
||||
getApp().getMap().setState(COALITIONAREA_EDIT);
|
||||
else
|
||||
getApp().getMap().setState(COALITIONAREA_DRAW_POLYGON);
|
||||
setDrawingPolygon(!drawingPolygon);
|
||||
}}
|
||||
>
|
||||
<div className="text-sm">Add polygon</div>
|
||||
</OlStateButton>
|
||||
</div>
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
@@ -60,7 +60,7 @@ export function Header() {
|
||||
`}
|
||||
>
|
||||
<img
|
||||
src="images/icon.png"
|
||||
src="vite/images/icon.png"
|
||||
className="my-auto h-10 w-10 rounded-md p-0"
|
||||
></img>
|
||||
{!scrolledLeft && (
|
||||
|
||||
@@ -35,10 +35,7 @@ import {
|
||||
import { Coalition } from "../../types/types";
|
||||
import { ftToM, knotsToMs, mToFt, msToKnots } from "../../other/utils";
|
||||
|
||||
export function UnitControlMenu(props: {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
}) {
|
||||
export function UnitControlMenu(props: { open: boolean; onClose: () => void }) {
|
||||
var [selectedUnits, setSelectedUnits] = useState([] as Unit[]);
|
||||
|
||||
var [selectedUnitsData, setSelectedUnitsData] = useState({
|
||||
@@ -185,7 +182,12 @@ export function UnitControlMenu(props: {
|
||||
getApp()?.getUnitsManager()?.getSelectedUnitsCategories() ?? [];
|
||||
|
||||
return (
|
||||
<Menu open={props.open} title="Units selected (x)" onClose={props.onClose}>
|
||||
<Menu
|
||||
open={props.open}
|
||||
title="Units selected (x)"
|
||||
onClose={props.onClose}
|
||||
canBeHidden={true}
|
||||
>
|
||||
{/* Units list */}
|
||||
<div
|
||||
className={`
|
||||
|
||||
@@ -24,6 +24,7 @@ import { LoginModal } from "./modals/login";
|
||||
import { sha256 } from "js-sha256";
|
||||
import { MiniMapPanel } from "./panels/minimappanel";
|
||||
import { UnitMouseControlBar } from "./panels/unitmousecontrolbar";
|
||||
import { DrawingMenu } from "./panels/drawingmenu";
|
||||
|
||||
export type OlympusState = {
|
||||
mainMenuVisible: boolean;
|
||||
@@ -238,6 +239,10 @@ export function UI() {
|
||||
open={unitControlMenuVisible}
|
||||
onClose={() => setUnitControlMenuVisible(false)}
|
||||
/>
|
||||
<DrawingMenu
|
||||
open={drawingMenuVisible}
|
||||
onClose={() => setDrawingMenuVisible(false)}
|
||||
/>
|
||||
<div id="map-container" className="h-full w-screen" />
|
||||
<UnitMouseControlBar />
|
||||
</div>
|
||||
|
||||
@@ -102,8 +102,8 @@ import {
|
||||
import { FaXmarksLines } from "react-icons/fa6";
|
||||
|
||||
var pathIcon = new Icon({
|
||||
iconUrl: "/images/markers/marker-icon.png",
|
||||
shadowUrl: "/images/markers/marker-shadow.png",
|
||||
iconUrl: "/vite/images/markers/marker-icon.png",
|
||||
shadowUrl: "/vite/images/markers/marker-shadow.png",
|
||||
iconAnchor: [13, 41],
|
||||
});
|
||||
|
||||
@@ -991,7 +991,7 @@ export abstract class Unit extends CustomMarker {
|
||||
)
|
||||
marker = this.getDatabaseEntry()?.markerFile ?? this.getDefaultMarker();
|
||||
else marker = "aircraft";
|
||||
img.src = `/images/units/${marker}.svg`;
|
||||
img.src = `/vite/images/units/${marker}.svg`;
|
||||
img.onload = () => SVGInjector(img);
|
||||
unitIcon.appendChild(img);
|
||||
|
||||
@@ -1486,9 +1486,6 @@ export abstract class Unit extends CustomMarker {
|
||||
faExclamation,
|
||||
() => this.applyFollowOptions("custom", units)
|
||||
);
|
||||
|
||||
//getApp().getMap().getUnitContextMenu().setContextActions(contextActionSet);
|
||||
getApp().getMap().showUnitContextMenu();
|
||||
}
|
||||
|
||||
applyFollowOptions(formation: string, units: Unit[]) {
|
||||
|
||||
@@ -194,7 +194,7 @@ export class Weapon extends CustomMarker {
|
||||
var unitIcon = document.createElement("div");
|
||||
unitIcon.classList.add("unit-icon");
|
||||
var img = document.createElement("img");
|
||||
img.src = `/images/units/${this.getMarkerCategory()}.svg`;
|
||||
img.src = `/vite/images/units/${this.getMarkerCategory()}.svg`;
|
||||
img.onload = () => SVGInjector(img);
|
||||
unitIcon.appendChild(img);
|
||||
unitIcon.toggleAttribute(
|
||||
|
||||
Reference in New Issue
Block a user