mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Added box selection for mobiles and ability to drag markers, units can be moved only via context action
This commit is contained in:
parent
61e52efc07
commit
fbc22676c5
@ -257,7 +257,6 @@ export const defaultMapLayers = {};
|
||||
|
||||
/* Map constants */
|
||||
export const IDLE = "Idle";
|
||||
export const MOVE_UNIT = "Move unit";
|
||||
export const SPAWN_UNIT = "Spawn unit";
|
||||
export const CONTEXT_ACTION = "Context action";
|
||||
export const COALITIONAREA_DRAW_POLYGON = "Draw Coalition Area";
|
||||
|
||||
2
frontend/react/src/dom.d.ts
vendored
2
frontend/react/src/dom.d.ts
vendored
@ -14,11 +14,13 @@ interface CustomEventMap {
|
||||
mapOptionChanged: CustomEvent<any>;
|
||||
mapSourceChanged: CustomEvent<string>;
|
||||
mapOptionsChanged: CustomEvent<any>; // TODO not very clear, why the two options?
|
||||
mapSelectionEnd: CustomEvent<any>;
|
||||
configLoaded: CustomEvent<any>;
|
||||
commandModeOptionsChanged: CustomEvent<any>;
|
||||
contactsUpdated: CustomEvent<Unit>;
|
||||
activeCoalitionChanged: CustomEvent<any>;
|
||||
serverStatusUpdated: CustomEvent<ServerStatus>;
|
||||
mapForceBoxSelect: CustomEvent<any>
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
@ -75,8 +75,8 @@ export interface UnitSpawnTable {
|
||||
location: LatLng;
|
||||
skill: string;
|
||||
liveryID: string;
|
||||
altitude: number;
|
||||
loadout: string;
|
||||
altitude?: number;
|
||||
loadout?: string;
|
||||
}
|
||||
|
||||
export interface ObjectIconOptions {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { Map } from "leaflet";
|
||||
import { Handler } from "leaflet";
|
||||
import { Util } from "leaflet";
|
||||
import { DomUtil } from "leaflet";
|
||||
@ -12,15 +11,22 @@ export var BoxSelect = Handler.extend({
|
||||
this._container = map.getContainer();
|
||||
this._pane = map.getPanes().overlayPane;
|
||||
this._resetStateTimeout = 0;
|
||||
this._forceBoxSelect = false;
|
||||
map.on("unload", this._destroy, this);
|
||||
|
||||
document.addEventListener("mapForceBoxSelect", () => {
|
||||
this._forceBoxSelect = true;
|
||||
});
|
||||
},
|
||||
|
||||
addHooks: function () {
|
||||
DomEvent.on(this._container, "mousedown", this._onMouseDown, this);
|
||||
DomEvent.on(this._container, "touchstart", this._onMouseDown, this);
|
||||
},
|
||||
|
||||
removeHooks: function () {
|
||||
DomEvent.off(this._container, "mousedown", this._onMouseDown, this);
|
||||
DomEvent.off(this._container, "touchstart", this._onMouseDown, this);
|
||||
},
|
||||
|
||||
moved: function () {
|
||||
@ -45,7 +51,10 @@ export var BoxSelect = Handler.extend({
|
||||
},
|
||||
|
||||
_onMouseDown: function (e: any) {
|
||||
if (e.which == 1 && e.button == 0 && e.shiftKey) {
|
||||
if (
|
||||
(e.which == 1 && e.button == 0 && (e.shiftKey || this._forceBoxSelect)) ||
|
||||
(e.type === "touchstart" && this._forceBoxSelect)
|
||||
) {
|
||||
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.
|
||||
@ -54,14 +63,21 @@ export var BoxSelect = Handler.extend({
|
||||
|
||||
DomUtil.disableTextSelection();
|
||||
DomUtil.disableImageDrag();
|
||||
this._map.dragging.disable();
|
||||
|
||||
this._startPoint = this._map.mouseEventToContainerPoint(e);
|
||||
if (e.type === "touchstart")
|
||||
this._startPoint = this._map.mouseEventToContainerPoint(e.touches[0]);
|
||||
else
|
||||
this._startPoint = this._map.mouseEventToContainerPoint(e);
|
||||
|
||||
//@ts-ignore
|
||||
DomEvent.on(
|
||||
//@ts-ignore
|
||||
document,
|
||||
{
|
||||
contextmenu: DomEvent.stop,
|
||||
touchmove: this._onMouseMove,
|
||||
touchend: this._onMouseUp,
|
||||
touchstart: this._onKeyDown,
|
||||
mousemove: this._onMouseMove,
|
||||
mouseup: this._onMouseUp,
|
||||
keydown: this._onKeyDown,
|
||||
@ -83,7 +99,10 @@ export var BoxSelect = Handler.extend({
|
||||
this._map.fire("boxzoomstart");
|
||||
}
|
||||
|
||||
this._point = this._map.mouseEventToContainerPoint(e);
|
||||
if (e.type === "touchmove")
|
||||
this._point = this._map.mouseEventToContainerPoint(e.touches[0]);
|
||||
else
|
||||
this._point = this._map.mouseEventToContainerPoint(e);
|
||||
|
||||
var bounds = new Bounds(this._point, this._startPoint),
|
||||
size = bounds.getSize();
|
||||
@ -102,12 +121,16 @@ export var BoxSelect = Handler.extend({
|
||||
|
||||
DomUtil.enableTextSelection();
|
||||
DomUtil.enableImageDrag();
|
||||
this._map.dragging.enable();
|
||||
|
||||
//@ts-ignore
|
||||
DomEvent.off(
|
||||
//@ts-ignore
|
||||
document,
|
||||
{
|
||||
contextmenu: DomEvent.stop,
|
||||
touchmove: this._onMouseMove,
|
||||
touchend: this._onMouseUp,
|
||||
touchstart: this._onKeyDown,
|
||||
mousemove: this._onMouseMove,
|
||||
mouseup: this._onMouseUp,
|
||||
keydown: this._onKeyDown,
|
||||
@ -117,7 +140,7 @@ export var BoxSelect = Handler.extend({
|
||||
},
|
||||
|
||||
_onMouseUp: function (e: any) {
|
||||
if (e.which !== 1 && e.button !== 0) {
|
||||
if (e.which !== 1 && e.button !== 0 && e.type !== "touchend") {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -134,6 +157,7 @@ export var BoxSelect = Handler.extend({
|
||||
this._map.containerPointToLatLng(this._point)
|
||||
);
|
||||
|
||||
this._forceBoxSelect = false;
|
||||
this._map.fire("selectionend", { selectionBounds: bounds });
|
||||
},
|
||||
|
||||
|
||||
@ -18,7 +18,6 @@ import {
|
||||
minimapBoundaries,
|
||||
IDLE,
|
||||
COALITIONAREA_DRAW_POLYGON,
|
||||
MOVE_UNIT,
|
||||
defaultMapMirrors,
|
||||
SPAWN_UNIT,
|
||||
CONTEXT_ACTION,
|
||||
@ -26,7 +25,6 @@ import {
|
||||
MAP_HIDDEN_TYPES_DEFAULTS,
|
||||
} from "../constants/constants";
|
||||
import { CoalitionArea } from "./coalitionarea/coalitionarea";
|
||||
import { DrawingCursor } from "./coalitionarea/drawingcursor";
|
||||
import { TouchBoxSelect } from "./touchboxselect";
|
||||
import { DestinationPreviewHandle } from "./markers/destinationpreviewHandle";
|
||||
|
||||
@ -40,16 +38,7 @@ import { MapHiddenTypes, MapOptions } from "../types/types";
|
||||
import { SpawnRequestTable } from "../interfaces";
|
||||
import { ContextAction } from "../unit/contextaction";
|
||||
|
||||
// Touch screen support temporarily disabled
|
||||
var hasTouchScreen = false;
|
||||
//if ("maxTouchPoints" in navigator)
|
||||
// hasTouchScreen = navigator.maxTouchPoints > 0;
|
||||
|
||||
if (hasTouchScreen)
|
||||
L.Map.addInitHook("addHandler", "boxSelect", TouchBoxSelect);
|
||||
else L.Map.addInitHook("addHandler", "boxSelect", BoxSelect);
|
||||
|
||||
//L.Map.addInitHook("addHandler", "gestureHandling", GestureHandling);
|
||||
L.Map.addInitHook("addHandler", "boxSelect", BoxSelect);
|
||||
|
||||
export class Map extends L.Map {
|
||||
/* Options */
|
||||
@ -95,9 +84,6 @@ export class Map extends L.Map {
|
||||
|
||||
#coalitionAreas: CoalitionArea[] = [];
|
||||
|
||||
#drawingCursor: DrawingCursor = new DrawingCursor();
|
||||
#spawnCursor: TemporaryUnitMarker | null = null;
|
||||
|
||||
#mapLayers: any = defaultMapLayers;
|
||||
#mapMirrors: any = defaultMapMirrors;
|
||||
#layerName: string = "";
|
||||
@ -127,8 +113,7 @@ export class Map extends L.Map {
|
||||
maxBoundsViscosity: 1.0,
|
||||
minZoom: 7,
|
||||
keyboard: true,
|
||||
keyboardPanDelta: 0,
|
||||
gestureHandling: hasTouchScreen,
|
||||
keyboardPanDelta: 0
|
||||
});
|
||||
this.setView([37.23, -115.8], 10);
|
||||
|
||||
@ -373,12 +358,6 @@ export class Map extends L.Map {
|
||||
getApp().getUnitsManager().deselectAllUnits();
|
||||
} else if (this.#state === SPAWN_UNIT) {
|
||||
this.#spawnRequestTable = options?.spawnRequestTable ?? null;
|
||||
this.#spawnCursor?.removeFrom(this);
|
||||
this.#spawnCursor = new TemporaryUnitMarker(
|
||||
new L.LatLng(0, 0),
|
||||
this.#spawnRequestTable?.unit.unitType ?? "unknown",
|
||||
this.#spawnRequestTable?.coalition ?? "blue"
|
||||
);
|
||||
} else if (this.#state === CONTEXT_ACTION) {
|
||||
this.#contextAction = options?.contextAction ?? null;
|
||||
} else if (this.#state === COALITIONAREA_DRAW_POLYGON) {
|
||||
@ -386,8 +365,6 @@ export class Map extends L.Map {
|
||||
this.#coalitionAreas[this.#coalitionAreas.length - 1].addTo(this);
|
||||
}
|
||||
|
||||
this.#updateCursor();
|
||||
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("mapStateChanged", { detail: this.#state })
|
||||
);
|
||||
@ -535,7 +512,6 @@ export class Map extends L.Map {
|
||||
this.options.scrollWheelZoom = undefined;
|
||||
this.#centerUnit = null;
|
||||
}
|
||||
this.#updateCursor();
|
||||
}
|
||||
|
||||
getCenteredOnUnit() {
|
||||
@ -762,9 +738,6 @@ export class Map extends L.Map {
|
||||
this.hideAllContextMenus();
|
||||
if (this.#state === IDLE) {
|
||||
this.deselectAllCoalitionAreas();
|
||||
} else if (this.#state === MOVE_UNIT) {
|
||||
getApp().getUnitsManager().clearDestinations();
|
||||
getApp().getUnitsManager().addDestination(e.latlng, false, 0);
|
||||
} else if (this.#state === SPAWN_UNIT) {
|
||||
if (this.#spawnRequestTable !== null) {
|
||||
const location = e.latlng;
|
||||
@ -820,7 +793,6 @@ export class Map extends L.Map {
|
||||
|
||||
#onSelectionStart(e: any) {
|
||||
this.#selecting = true;
|
||||
this.#updateCursor();
|
||||
}
|
||||
|
||||
#onSelectionEnd(e: any) {
|
||||
@ -831,7 +803,7 @@ export class Map extends L.Map {
|
||||
this.#preventLeftClick = false;
|
||||
}, 200);
|
||||
getApp().getUnitsManager().selectFromBounds(e.selectionBounds);
|
||||
this.#updateCursor();
|
||||
document.dispatchEvent(new CustomEvent("mapSelectionEnd"));
|
||||
}
|
||||
|
||||
#onMouseDown(e: any) {}
|
||||
@ -841,15 +813,10 @@ export class Map extends L.Map {
|
||||
this.#lastMousePosition.y = e.originalEvent.y;
|
||||
this.#lastMouseCoordinates = this.mouseEventToLatLng(e.originalEvent);
|
||||
|
||||
this.#updateCursor();
|
||||
|
||||
if (this.#state === SPAWN_UNIT) {
|
||||
this.#updateSpawnCursor();
|
||||
} else if (
|
||||
if (
|
||||
this.#state === COALITIONAREA_DRAW_POLYGON &&
|
||||
e.latlng !== undefined
|
||||
) {
|
||||
this.#drawingCursor.setLatLng(e.latlng);
|
||||
/* Update the polygon being drawn with the current position of the mouse cursor */
|
||||
this.getSelectedCoalitionArea()?.moveActiveVertex(e.latlng);
|
||||
}
|
||||
@ -857,12 +824,10 @@ export class Map extends L.Map {
|
||||
|
||||
#onKeyDown(e: any) {
|
||||
this.#shiftKey = e.originalEvent.shiftKey;
|
||||
this.#updateCursor();
|
||||
}
|
||||
|
||||
#onKeyUp(e: any) {
|
||||
this.#shiftKey = e.originalEvent.shiftKey;
|
||||
this.#updateCursor();
|
||||
}
|
||||
|
||||
#onZoomStart(e: any) {
|
||||
@ -927,7 +892,6 @@ export class Map extends L.Map {
|
||||
unit.getPosition().lng
|
||||
);
|
||||
this.setView(unitPosition, this.getZoom(), { animate: false });
|
||||
this.#updateCursor();
|
||||
}
|
||||
|
||||
#getMinimapBoundaries() {
|
||||
@ -939,60 +903,6 @@ export class Map extends L.Map {
|
||||
this.getSelectedCoalitionArea()?.setSelected(false);
|
||||
}
|
||||
|
||||
/* Cursors */
|
||||
#updateCursor() {
|
||||
/* If we are performing an area selection, show the default cursor */
|
||||
if (this.#selecting) {
|
||||
/* Hide all non default cursors */
|
||||
this.#hideDrawingCursor();
|
||||
this.#hideSpawnCursor();
|
||||
|
||||
this.#showDefaultCursor();
|
||||
} else {
|
||||
/* Hide all the unnecessary cursors depending on the active state */
|
||||
if (this.#state !== IDLE) this.#hideDefaultCursor();
|
||||
if (this.#state !== SPAWN_UNIT) this.#hideSpawnCursor();
|
||||
if (this.#state !== COALITIONAREA_DRAW_POLYGON) this.#hideDrawingCursor();
|
||||
|
||||
/* Show the active cursor depending on the active state */
|
||||
if (this.#state === IDLE) this.#showDefaultCursor();
|
||||
else if (this.#state === SPAWN_UNIT) this.#showSpawnCursor();
|
||||
else if (this.#state === COALITIONAREA_DRAW_POLYGON)
|
||||
this.#showDrawingCursor();
|
||||
}
|
||||
}
|
||||
|
||||
#showDefaultCursor() {
|
||||
document.getElementById(this.#ID)?.classList.remove("hidden-cursor");
|
||||
}
|
||||
|
||||
#hideDefaultCursor() {
|
||||
document.getElementById(this.#ID)?.classList.add("hidden-cursor");
|
||||
}
|
||||
|
||||
#showDrawingCursor() {
|
||||
this.#hideDefaultCursor();
|
||||
if (!this.hasLayer(this.#drawingCursor)) this.#drawingCursor.addTo(this);
|
||||
}
|
||||
|
||||
#hideDrawingCursor() {
|
||||
this.#drawingCursor.setLatLng(new L.LatLng(0, 0));
|
||||
if (this.hasLayer(this.#drawingCursor))
|
||||
this.#drawingCursor.removeFrom(this);
|
||||
}
|
||||
|
||||
#showSpawnCursor() {
|
||||
this.#spawnCursor?.addTo(this);
|
||||
}
|
||||
|
||||
#updateSpawnCursor() {
|
||||
this.#spawnCursor?.setLatLng(this.getMouseCoordinates());
|
||||
}
|
||||
|
||||
#hideSpawnCursor() {
|
||||
this.#spawnCursor?.removeFrom(this);
|
||||
}
|
||||
|
||||
#setSlaveDCSCameraAvailable(newSlaveDCSCameraAvailable: boolean) {
|
||||
this.#slaveDCSCameraAvailable = newSlaveDCSCameraAvailable;
|
||||
let linkButton = document.getElementById("camera-link-control");
|
||||
|
||||
@ -15,6 +15,7 @@ export const StateContext = createContext({
|
||||
mapOptions: MAP_OPTIONS_DEFAULTS,
|
||||
mapSources: [] as string[],
|
||||
activeMapSource: "",
|
||||
mapBoxSelection: false
|
||||
});
|
||||
|
||||
export const StateProvider = StateContext.Provider;
|
||||
|
||||
@ -34,14 +34,14 @@ export function OlCoalitionToggle(props: {
|
||||
></div>
|
||||
<span
|
||||
className={`
|
||||
ms-3 text-gray-900
|
||||
ms-3 overflow-hidden text-ellipsis text-nowrap text-gray-900
|
||||
dark:text-white
|
||||
data-[flash='true']:after:animate-pulse
|
||||
`}
|
||||
>
|
||||
{props.coalition
|
||||
? `Coalition (${props.coalition[0].toLocaleUpperCase() + props.coalition.substring(1)})`
|
||||
: "Different values"}
|
||||
? `${props.coalition[0].toLocaleUpperCase() + props.coalition.substring(1)}`
|
||||
: "Diff. values"}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -19,7 +19,21 @@ export function OlDropdown(props: {
|
||||
content.style.top = "0px";
|
||||
content.style.height = "";
|
||||
|
||||
/* Get the position and size of the button and the content elements */
|
||||
/* Get the position and size of the button */
|
||||
var [bxl, byt, bxr, byb, bw, bh] = [
|
||||
button.getBoundingClientRect().x,
|
||||
button.getBoundingClientRect().y,
|
||||
button.getBoundingClientRect().x + button.clientWidth,
|
||||
button.getBoundingClientRect().y + button.clientHeight,
|
||||
button.clientWidth,
|
||||
button.clientHeight,
|
||||
];
|
||||
|
||||
/* Set the minimum and maximum width to be equal to the button width */
|
||||
content.style.minWidth = `${bw}px`;
|
||||
content.style.maxWidth = `${bw}px`;
|
||||
|
||||
/* Get the position and size of the content element */
|
||||
var [cxl, cyt, cxr, cyb, cw, ch] = [
|
||||
content.getBoundingClientRect().x,
|
||||
content.getBoundingClientRect().y,
|
||||
@ -28,14 +42,6 @@ export function OlDropdown(props: {
|
||||
content.clientWidth,
|
||||
content.clientHeight,
|
||||
];
|
||||
var [bxl, byt, bxr, byb, bbw, bh] = [
|
||||
button.getBoundingClientRect().x,
|
||||
button.getBoundingClientRect().y,
|
||||
button.getBoundingClientRect().x + button.clientWidth,
|
||||
button.getBoundingClientRect().y + button.clientHeight,
|
||||
button.clientWidth,
|
||||
button.clientHeight,
|
||||
];
|
||||
|
||||
/* Limit the maximum height */
|
||||
if (ch > 400) {
|
||||
@ -134,8 +140,8 @@ export function OlDropdown(props: {
|
||||
ref={contentRef}
|
||||
data-open={open}
|
||||
className={`
|
||||
absolute z-ui-4 divide-y divide-gray-100 overflow-y-scroll rounded-lg
|
||||
bg-white p-2 shadow
|
||||
absolute z-ui-4 divide-y divide-gray-100 overflow-y-scroll
|
||||
no-scrollbar rounded-lg bg-white p-2 shadow
|
||||
dark:bg-gray-700
|
||||
data-[open='false']:hidden
|
||||
`}
|
||||
|
||||
@ -31,7 +31,7 @@ export function OlLabelToggle(props: {
|
||||
<span
|
||||
data-active={!(props.toggled ?? false)}
|
||||
className={`
|
||||
my-auto pl-3 font-normal transition-colors z-ui-2
|
||||
my-auto pl-3 font-normal transition-colors z-ui-1
|
||||
dark:data-[active='false']:text-gray-400
|
||||
dark:data-[active='true']:text-white
|
||||
`}
|
||||
@ -41,7 +41,7 @@ export function OlLabelToggle(props: {
|
||||
<span
|
||||
data-active={props.toggled ?? false}
|
||||
className={`
|
||||
my-auto pr-3.5 font-normal transition-colors z-ui-2
|
||||
my-auto pr-3.5 font-normal transition-colors z-ui-1
|
||||
dark:data-[active='false']:text-gray-400
|
||||
dark:data-[active='true']:text-white
|
||||
`}
|
||||
|
||||
@ -9,7 +9,7 @@ export function OlNumberInput(props: {
|
||||
onChange: (e: ChangeEvent<HTMLInputElement>) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="w-fit">
|
||||
<div className="min-w-32">
|
||||
<div className="relative flex max-w-[8rem] items-center">
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@ -19,20 +19,24 @@ export function Menu(props: {
|
||||
return (
|
||||
<div
|
||||
data-open={props.open}
|
||||
data-hide={hide}
|
||||
className={`
|
||||
absolute left-16 right-0 top-[58px] bg-gray-200 backdrop-grayscale
|
||||
z-ui-3 h-[calc(100vh-58px)] backdrop-blur-lg transition-transform
|
||||
dark:bg-olympus-800/90
|
||||
data-[hide='true']:-translate-y-[calc(100vh-1.5rem-58px)]
|
||||
absolute left-16 right-0 top-[58px] bg-transparent z-ui-3
|
||||
pointer-events-none h-[calc(100vh-58px)] transition-transform
|
||||
data-[open='false']:-translate-x-full
|
||||
sm:w-[400px]
|
||||
`}
|
||||
tabIndex={-1}
|
||||
>
|
||||
<div className={`
|
||||
h-[calc(100vh-58px-1.5rem)] overflow-y-auto overflow-x-hidden
|
||||
`}>
|
||||
<div
|
||||
data-hide={hide}
|
||||
className={`
|
||||
pointer-events-auto h-[calc(100vh-58px-2rem)] overflow-y-auto
|
||||
overflow-x-hidden no-scrollbar backdrop-blur-lg backdrop-grayscale
|
||||
transition-transform
|
||||
dark:bg-olympus-800/90
|
||||
data-[hide='true']:translate-y-[calc(100vh-58px)]
|
||||
`}
|
||||
>
|
||||
<h5
|
||||
className={`
|
||||
inline-flex w-full items-center px-5 py-3 pb-2 font-semibold
|
||||
@ -65,11 +69,15 @@ export function Menu(props: {
|
||||
{props.children}
|
||||
</div>
|
||||
{props.canBeHidden == true && (
|
||||
<div className="flex h-6 justify-center" onClick={() => setHide(!hide)}>
|
||||
<div className={`
|
||||
flex h-8 justify-center z-ui-6 pointer-events-auto backdrop-blur-lg
|
||||
backdrop-grayscale
|
||||
dark:bg-olympus-800/90
|
||||
`} onClick={() => setHide(!hide)}>
|
||||
{hide ? (
|
||||
<FaChevronDown className="mx-auto my-auto text-gray-400" />
|
||||
) : (
|
||||
<FaChevronUp className="mx-auto my-auto text-gray-400" />
|
||||
) : (
|
||||
<FaChevronDown className="mx-auto my-auto text-gray-400" />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -29,8 +29,24 @@ import {
|
||||
olButtonsVisibilityNavyunit,
|
||||
olButtonsVisibilityOlympus,
|
||||
} from "../components/olicons";
|
||||
import { FaChevronLeft, FaChevronRight } from "react-icons/fa6";
|
||||
|
||||
export function Header() {
|
||||
const [scrolledLeft, setScrolledLeft] = useState(true);
|
||||
const [scrolledRight, setScrolledRight] = useState(false);
|
||||
|
||||
function onScroll(ev) {
|
||||
const sl = ev.target.scrollLeft;
|
||||
const sr =
|
||||
ev.target.scrollWidth - ev.target.scrollLeft - ev.target.clientWidth;
|
||||
|
||||
sl < 1 && !scrolledLeft && setScrolledLeft(true);
|
||||
sl > 1 && scrolledLeft && setScrolledLeft(false);
|
||||
|
||||
sr < 1 && !scrolledRight && setScrolledRight(true);
|
||||
sr > 1 && scrolledRight && setScrolledRight(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<StateConsumer>
|
||||
{(appState) => (
|
||||
@ -47,11 +63,21 @@ export function Header() {
|
||||
src="images/icon.png"
|
||||
className="my-auto h-10 w-10 rounded-md p-0"
|
||||
></img>
|
||||
{!scrolledLeft && (
|
||||
<FaChevronLeft
|
||||
className={`
|
||||
absolute left-14 h-full w-6 rounded-lg px-2 py-3.5
|
||||
text-gray-200 z-ui-1
|
||||
dark:bg-olympus-900
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
className={`
|
||||
my-2 flex w-full items-center gap-3 overflow-x-scroll
|
||||
no-scrollbar
|
||||
`}
|
||||
onScroll={(ev) => onScroll(ev)}
|
||||
>
|
||||
<div
|
||||
className={`
|
||||
@ -228,6 +254,15 @@ export function Header() {
|
||||
})}
|
||||
</OlDropdown>
|
||||
</div>
|
||||
{!scrolledRight && (
|
||||
<FaChevronRight
|
||||
className={`
|
||||
absolute right-0 h-full w-6 rounded-lg px-2 py-3.5
|
||||
text-gray-200 z-ui-1
|
||||
dark:bg-olympus-900
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
</nav>
|
||||
)}
|
||||
</EventsConsumer>
|
||||
|
||||
@ -72,7 +72,7 @@ export function MiniMapPanel(props: {}) {
|
||||
onClick={() => setShowMissionTime(!showMissionTime)}
|
||||
className={`
|
||||
absolute right-[10px]
|
||||
${showMinimap ? `top-[232px]` : `top-[90px]`}
|
||||
${showMinimap ? `top-[232px]` : `top-[70px]`}
|
||||
w-[288px] z-ui-0 flex items-center justify-between
|
||||
${showMinimap ? `rounded-b-lg` : `rounded-lg`}
|
||||
bg-gray-200 p-3 text-sm backdrop-blur-lg backdrop-grayscale
|
||||
@ -114,13 +114,13 @@ export function MiniMapPanel(props: {}) {
|
||||
onClick={() => {
|
||||
getApp().getMap().setOption("showMinimap", false);
|
||||
}}
|
||||
/>
|
||||
></FaChevronUp>
|
||||
) : (
|
||||
<FaChevronDown
|
||||
onClick={() => {
|
||||
getApp().getMap().setOption("showMinimap", true);
|
||||
}}
|
||||
/>
|
||||
></FaChevronDown>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -8,6 +8,8 @@ import {
|
||||
faCog,
|
||||
faQuestionCircle,
|
||||
faPlusSquare,
|
||||
faBox,
|
||||
faObjectGroup,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { EventsConsumer } from "../../eventscontext";
|
||||
import { StateConsumer } from "../../statecontext";
|
||||
@ -17,7 +19,7 @@ export function SideBar() {
|
||||
const [mapState, setMapState] = useState(IDLE);
|
||||
|
||||
document.addEventListener("mapStateChanged", (ev) => {
|
||||
setMapState((ev as CustomEvent).detail)
|
||||
setMapState((ev as CustomEvent).detail);
|
||||
});
|
||||
|
||||
return (
|
||||
@ -71,6 +73,16 @@ export function SideBar() {
|
||||
icon={faPencil}
|
||||
tooltip="Hide/show drawing menu"
|
||||
></OlStateButton>
|
||||
<OlStateButton
|
||||
onClick={() => {
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("mapForceBoxSelect")
|
||||
);
|
||||
}}
|
||||
checked={appState.mapBoxSelection}
|
||||
icon={faObjectGroup}
|
||||
tooltip="Enable box selection on the map"
|
||||
></OlStateButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex w-16 flex-wrap content-end justify-center p-4">
|
||||
|
||||
@ -98,7 +98,9 @@ export function SpawnMenu(props: {
|
||||
<div className="p-5">
|
||||
<OlSearchBar onChange={(ev) => setFilterString(ev.target.value)} />
|
||||
<OlAccordion title={`Aircraft`}>
|
||||
<div className="flex max-h-80 flex-col gap-1 overflow-y-scroll">
|
||||
<div className={`
|
||||
flex max-h-80 flex-col gap-1 overflow-y-scroll no-scrollbar
|
||||
`}>
|
||||
{Object.keys(filteredAircraft).map((key) => {
|
||||
const blueprint =
|
||||
getApp().getAircraftDatabase().blueprints[key];
|
||||
@ -114,7 +116,9 @@ export function SpawnMenu(props: {
|
||||
</div>
|
||||
</OlAccordion>
|
||||
<OlAccordion title={`Helicopters`}>
|
||||
<div className="flex max-h-80 flex-col gap-1 overflow-y-scroll">
|
||||
<div className={`
|
||||
flex max-h-80 flex-col gap-1 overflow-y-scroll no-scrollbar
|
||||
`}>
|
||||
{Object.keys(filteredHelicopters).map((key) => {
|
||||
const blueprint =
|
||||
getApp().getHelicopterDatabase().blueprints[key];
|
||||
@ -130,7 +134,9 @@ export function SpawnMenu(props: {
|
||||
</div>
|
||||
</OlAccordion>
|
||||
<OlAccordion title={`SAM & AAA`}>
|
||||
<div className="flex max-h-80 flex-col gap-1 overflow-y-scroll">
|
||||
<div className={`
|
||||
flex max-h-80 flex-col gap-1 overflow-y-scroll no-scrollbar
|
||||
`}>
|
||||
{Object.keys(filteredAirDefense).map((key) => {
|
||||
const blueprint =
|
||||
getApp().getGroundUnitDatabase().blueprints[key];
|
||||
@ -146,7 +152,9 @@ export function SpawnMenu(props: {
|
||||
</div>
|
||||
</OlAccordion>
|
||||
<OlAccordion title={`Ground Units`}>
|
||||
<div className="flex max-h-80 flex-col gap-1 overflow-y-scroll">
|
||||
<div className={`
|
||||
flex max-h-80 flex-col gap-1 overflow-y-scroll no-scrollbar
|
||||
`}>
|
||||
{Object.keys(filteredGroundUnits).map((key) => {
|
||||
const blueprint =
|
||||
getApp().getGroundUnitDatabase().blueprints[key];
|
||||
@ -162,7 +170,9 @@ export function SpawnMenu(props: {
|
||||
</div>
|
||||
</OlAccordion>
|
||||
<OlAccordion title={`Ships and submarines`}>
|
||||
<div className="flex max-h-80 flex-col gap-1 overflow-y-scroll">
|
||||
<div className={`
|
||||
flex max-h-80 flex-col gap-1 overflow-y-scroll no-scrollbar
|
||||
`}>
|
||||
{Object.keys(filteredNavyUnits).map((key) => {
|
||||
const blueprint =
|
||||
getApp().getNavyUnitDatabase().blueprints[key];
|
||||
|
||||
@ -4,8 +4,9 @@ import { ContextActionSet } from "../../unit/contextactionset";
|
||||
import { OlStateButton } from "../components/olstatebutton";
|
||||
import { getApp } from "../../olympusapp";
|
||||
import { ContextAction } from "../../unit/contextaction";
|
||||
import { CONTEXT_ACTION, MOVE_UNIT } from "../../constants/constants";
|
||||
import { CONTEXT_ACTION } from "../../constants/constants";
|
||||
import { FaInfoCircle } from "react-icons/fa";
|
||||
import { FaChevronLeft, FaChevronRight } from "react-icons/fa6";
|
||||
|
||||
export function UnitMouseControlBar(props: {}) {
|
||||
var [open, setOpen] = useState(false);
|
||||
@ -16,6 +17,8 @@ export function UnitMouseControlBar(props: {}) {
|
||||
var [activeContextAction, setActiveContextAction] = useState(
|
||||
null as null | ContextAction
|
||||
);
|
||||
const [scrolledLeft, setScrolledLeft] = useState(true);
|
||||
const [scrolledRight, setScrolledRight] = useState(false);
|
||||
|
||||
/* When a unit is selected, open the menu */
|
||||
document.addEventListener("unitsSelection", (ev: CustomEventInit) => {
|
||||
@ -40,7 +43,7 @@ export function UnitMouseControlBar(props: {}) {
|
||||
|
||||
/* Deselect the context action when exiting state */
|
||||
document.addEventListener("mapStateChanged", (ev) => {
|
||||
setOpen((ev as CustomEvent).detail === CONTEXT_ACTION || (ev as CustomEvent).detail === MOVE_UNIT);
|
||||
setOpen((ev as CustomEvent).detail === CONTEXT_ACTION);
|
||||
});
|
||||
|
||||
/* Update the current values of the shown data */
|
||||
@ -58,6 +61,18 @@ export function UnitMouseControlBar(props: {}) {
|
||||
setActiveContextAction(null);
|
||||
}
|
||||
|
||||
function onScroll(ev) {
|
||||
const sl = ev.target.scrollLeft;
|
||||
const sr =
|
||||
ev.target.scrollWidth - ev.target.scrollLeft - ev.target.clientWidth;
|
||||
|
||||
sl < 1 && !scrolledLeft && setScrolledLeft(true);
|
||||
sl > 1 && scrolledLeft && setScrolledLeft(false);
|
||||
|
||||
sr < 1 && !scrolledRight && setScrolledRight(true);
|
||||
sr > 1 && scrolledRight && setScrolledRight(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{" "}
|
||||
@ -65,39 +80,59 @@ export function UnitMouseControlBar(props: {}) {
|
||||
<>
|
||||
<div
|
||||
className={`
|
||||
absolute left-[50%] top-16 flex translate-x-[calc(-50%+2rem)]
|
||||
gap-2 rounded-md bg-gray-200 p-2 z-ui-2
|
||||
absolute left-[50%] top-16 flex max-w-[80%]
|
||||
translate-x-[calc(-50%+2rem)] gap-2 rounded-md bg-gray-200 z-ui-2
|
||||
dark:bg-olympus-900
|
||||
`}
|
||||
>
|
||||
{Object.values(contextActionsSet.getContextActions()).map(
|
||||
(contextAction) => {
|
||||
return (
|
||||
<OlStateButton
|
||||
checked={contextAction === activeContextAction}
|
||||
icon={contextAction.getIcon()}
|
||||
tooltip={contextAction.getLabel()}
|
||||
onClick={() => {
|
||||
if (contextAction.getOptions().executeImmediately) {
|
||||
setActiveContextAction(null);
|
||||
contextAction.executeCallback(null, null);
|
||||
} else {
|
||||
if (activeContextAction != contextAction) {
|
||||
setActiveContextAction(contextAction);
|
||||
getApp().getMap().setState(CONTEXT_ACTION, {
|
||||
contextAction: contextAction,
|
||||
});
|
||||
} else {
|
||||
{!scrolledLeft && (
|
||||
<FaChevronLeft
|
||||
className={`
|
||||
absolute left-0 h-full w-6 rounded-lg px-2 py-3.5
|
||||
text-gray-200
|
||||
dark:bg-olympus-900
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
className="flex gap-2 overflow-x-auto no-scrollbar p-2"
|
||||
onScroll={(ev) => onScroll(ev)}
|
||||
>
|
||||
{Object.values(contextActionsSet.getContextActions()).map(
|
||||
(contextAction) => {
|
||||
return (
|
||||
<OlStateButton
|
||||
checked={contextAction === activeContextAction}
|
||||
icon={contextAction.getIcon()}
|
||||
tooltip={contextAction.getLabel()}
|
||||
onClick={() => {
|
||||
if (contextAction.getOptions().executeImmediately) {
|
||||
setActiveContextAction(null);
|
||||
getApp()
|
||||
.getMap()
|
||||
.setState(MOVE_UNIT);
|
||||
contextAction.executeCallback(null, null);
|
||||
} else {
|
||||
if (activeContextAction != contextAction) {
|
||||
setActiveContextAction(contextAction);
|
||||
getApp().getMap().setState(CONTEXT_ACTION, {
|
||||
contextAction: contextAction,
|
||||
});
|
||||
} else {
|
||||
setActiveContextAction(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
{!scrolledRight && (
|
||||
<FaChevronRight
|
||||
className={`
|
||||
absolute right-0 h-full w-6 rounded-lg px-2 py-3.5
|
||||
text-gray-200
|
||||
dark:bg-olympus-900
|
||||
`}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{activeContextAction && (
|
||||
@ -109,10 +144,12 @@ export function UnitMouseControlBar(props: {}) {
|
||||
dark:bg-olympus-800
|
||||
`}
|
||||
>
|
||||
<FaInfoCircle className={`
|
||||
mr-2 hidden min-w-8 text-sm text-blue-500
|
||||
md:block
|
||||
`} />
|
||||
<FaInfoCircle
|
||||
className={`
|
||||
mr-2 hidden min-w-8 text-sm text-blue-500
|
||||
md:block
|
||||
`}
|
||||
/>
|
||||
<div
|
||||
className={`
|
||||
px-2
|
||||
|
||||
@ -87,7 +87,11 @@ export function UnitSpawnMenu(props: { blueprint: UnitBlueprint }) {
|
||||
<div className="flex flex-col">
|
||||
<OlUnitSummary blueprint={props.blueprint} coalition={spawnCoalition} />
|
||||
<div className="flex h-fit flex-col gap-5 px-5 pb-8 pt-6">
|
||||
<div className="flex w-full flex-row content-center justify-between">
|
||||
<div
|
||||
className={`
|
||||
inline-flex w-full flex-row content-center justify-between
|
||||
`}
|
||||
>
|
||||
<OlCoalitionToggle
|
||||
coalition={spawnCoalition}
|
||||
onClick={() => {
|
||||
@ -192,10 +196,7 @@ export function UnitSpawnMenu(props: { blueprint: UnitBlueprint }) {
|
||||
Weapons
|
||||
</span>
|
||||
</div>
|
||||
<OlDropdown
|
||||
label={spawnLoadoutName}
|
||||
className={`w-full w-max-full`}
|
||||
>
|
||||
<OlDropdown label={spawnLoadoutName} className={`w-full w-max-full`}>
|
||||
{loadouts.map((loadout) => {
|
||||
return (
|
||||
<OlDropdownItem
|
||||
@ -230,7 +231,7 @@ export function UnitSpawnMenu(props: { blueprint: UnitBlueprint }) {
|
||||
<div className="flex content-center gap-2">
|
||||
<div
|
||||
className={`
|
||||
my-auto w-6 rounded-full py-0.5 text-center text-sm
|
||||
my-auto w-6 min-w-6 rounded-full py-0.5 text-center text-sm
|
||||
font-bold text-gray-500
|
||||
dark:bg-[#17212D]
|
||||
`}
|
||||
@ -239,7 +240,7 @@ export function UnitSpawnMenu(props: { blueprint: UnitBlueprint }) {
|
||||
</div>
|
||||
<div
|
||||
className={`
|
||||
my-auto text-sm
|
||||
my-auto overflow-hidden text-ellipsis text-nowrap text-sm
|
||||
dark:text-gray-300
|
||||
`}
|
||||
>
|
||||
|
||||
@ -51,6 +51,7 @@ export function UI() {
|
||||
var [commandMode, setCommandMode] = useState(null as null | string);
|
||||
var [mapSources, setMapSources] = useState([] as string[]);
|
||||
var [activeMapSource, setActiveMapSource] = useState("");
|
||||
var [mapBoxSelection, setMapBoxSelection] = useState(false);
|
||||
|
||||
document.addEventListener("hiddenTypesChanged", (ev) => {
|
||||
setMapHiddenTypes({ ...getApp().getMap().getHiddenTypes() });
|
||||
@ -60,11 +61,11 @@ export function UI() {
|
||||
setMapOptions({ ...getApp().getMap().getOptions() });
|
||||
});
|
||||
|
||||
//document.addEventListener("mapStateChanged", (ev) => {
|
||||
// if ((ev as CustomEvent).detail == IDLE) {
|
||||
// hideAllMenus();
|
||||
// }
|
||||
//});
|
||||
document.addEventListener("mapStateChanged", (ev) => {
|
||||
if ((ev as CustomEvent).detail == IDLE) {
|
||||
hideAllMenus();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("mapSourceChanged", (ev) => {
|
||||
var source = (ev as CustomEvent).detail;
|
||||
@ -80,6 +81,14 @@ export function UI() {
|
||||
setActiveMapSource(sources[0]);
|
||||
});
|
||||
|
||||
document.addEventListener("mapForceBoxSelect", (ev) => {
|
||||
setMapBoxSelection(true);
|
||||
});
|
||||
|
||||
document.addEventListener("mapSelectionEnd", (ev) => {
|
||||
setMapBoxSelection(false);
|
||||
});
|
||||
|
||||
function hideAllMenus() {
|
||||
setMainMenuVisible(false);
|
||||
setSpawnMenuVisible(false);
|
||||
@ -147,6 +156,7 @@ export function UI() {
|
||||
mapHiddenTypes: mapHiddenTypes,
|
||||
mapSources: mapSources,
|
||||
activeMapSource: activeMapSource,
|
||||
mapBoxSelection: mapBoxSelection,
|
||||
}}
|
||||
>
|
||||
<EventsProvider
|
||||
|
||||
@ -38,7 +38,6 @@ import {
|
||||
GAME_MASTER,
|
||||
IDLE,
|
||||
IRST,
|
||||
MOVE_UNIT,
|
||||
OPTIC,
|
||||
RADAR,
|
||||
ROEs,
|
||||
@ -93,9 +92,11 @@ import {
|
||||
faArrowDown,
|
||||
faExclamation,
|
||||
faLocationCrosshairs,
|
||||
faLocationDot,
|
||||
faMapLocation,
|
||||
faPeopleGroup,
|
||||
faQuestionCircle,
|
||||
faRoute,
|
||||
faXmarksLines,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FaXmarksLines } from "react-icons/fa6";
|
||||
@ -430,11 +431,6 @@ export abstract class Unit extends CustomMarker {
|
||||
*/
|
||||
abstract getIconOptions(): ObjectIconOptions;
|
||||
|
||||
/** Get the actions that this unit can perform
|
||||
*
|
||||
*/
|
||||
abstract appendContextActions(contextActionSet: ContextActionSet): void;
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns string containing the marker category
|
||||
@ -889,6 +885,38 @@ export abstract class Unit extends CustomMarker {
|
||||
this.#group = group;
|
||||
}
|
||||
|
||||
/** Get the actions that this unit can perform
|
||||
*
|
||||
*/
|
||||
appendContextActions(contextActionSet: ContextActionSet) {
|
||||
contextActionSet.addContextAction(
|
||||
this,
|
||||
"move",
|
||||
"Move",
|
||||
"Click on the map to move the units there",
|
||||
faLocationDot,
|
||||
(units: Unit[], _, targetPosition) => {
|
||||
getApp().getUnitsManager().clearDestinations(units);
|
||||
if (targetPosition)
|
||||
getApp().getUnitsManager().addDestination(targetPosition, false, 0);
|
||||
}
|
||||
);
|
||||
|
||||
contextActionSet.addContextAction(
|
||||
this,
|
||||
"path",
|
||||
"Path",
|
||||
"Click on the map to add a destination to the path",
|
||||
faRoute,
|
||||
(units: Unit[], _, targetPosition) => {
|
||||
if (targetPosition)
|
||||
getApp()
|
||||
.getUnitsManager()
|
||||
.addDestination(targetPosition, false, 0, units);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
drawLines() {
|
||||
/* Leaflet does not like it when you change coordinates when the map is zooming */
|
||||
if (!getApp().getMap().isZooming()) {
|
||||
@ -1189,6 +1217,15 @@ export abstract class Unit extends CustomMarker {
|
||||
if (!this.#human) this.#activePath = [];
|
||||
}
|
||||
|
||||
updatePathFromMarkers() {
|
||||
var path: any = {};
|
||||
this.#pathMarkers.forEach((marker) => {
|
||||
path[Object.keys(path).length.toString()] = marker.getLatLng();
|
||||
console.log(marker.getLatLng());
|
||||
});
|
||||
getApp().getServerManager().addDestination(this.ID, path);
|
||||
}
|
||||
|
||||
attackUnit(targetID: number) {
|
||||
/* Units can't attack themselves */
|
||||
if (!this.#human)
|
||||
@ -1521,11 +1558,7 @@ export abstract class Unit extends CustomMarker {
|
||||
this.#doubleClickTimer = window.setTimeout(() => {
|
||||
/* Still waiting so no doubleclick; do the click action */
|
||||
if (this.#waitingForDoubleClick) {
|
||||
if (
|
||||
getApp().getMap().getState() === IDLE ||
|
||||
getApp().getMap().getState() === MOVE_UNIT ||
|
||||
e.originalEvent.ctrlKey
|
||||
) {
|
||||
if (getApp().getMap().getState() === IDLE || e.originalEvent.ctrlKey) {
|
||||
if (!e.originalEvent.ctrlKey)
|
||||
getApp().getUnitsManager().deselectAllUnits();
|
||||
|
||||
@ -1781,9 +1814,13 @@ export abstract class Unit extends CustomMarker {
|
||||
|
||||
/* Add markers if missing */
|
||||
while (this.#pathMarkers.length < Object.keys(this.#activePath).length) {
|
||||
var marker = new Marker([0, 0], { icon: pathIcon }).addTo(
|
||||
getApp().getMap()
|
||||
);
|
||||
var marker = new Marker([0, 0], {
|
||||
icon: pathIcon,
|
||||
draggable: true,
|
||||
}).addTo(getApp().getMap());
|
||||
marker.on("dragend", (event) => {
|
||||
this.updatePathFromMarkers();
|
||||
});
|
||||
this.#pathMarkers.push(marker);
|
||||
}
|
||||
|
||||
@ -2144,6 +2181,8 @@ export abstract class AirUnit extends Unit {
|
||||
}
|
||||
|
||||
appendContextActions(contextActionSet: ContextActionSet) {
|
||||
super.appendContextActions(contextActionSet);
|
||||
|
||||
/* Context actions to be executed immediately */
|
||||
contextActionSet.addContextAction(
|
||||
this,
|
||||
@ -2319,6 +2358,8 @@ export class GroundUnit extends Unit {
|
||||
}
|
||||
|
||||
appendContextActions(contextActionSet: ContextActionSet) {
|
||||
super.appendContextActions(contextActionSet);
|
||||
|
||||
/* Context actions to be executed immediately */
|
||||
contextActionSet.addContextAction(
|
||||
this,
|
||||
@ -2522,6 +2563,8 @@ export class NavyUnit extends Unit {
|
||||
}
|
||||
|
||||
appendContextActions(contextActionSet: ContextActionSet) {
|
||||
super.appendContextActions(contextActionSet);
|
||||
|
||||
/* Context actions to be executed immediately */
|
||||
contextActionSet.addContextAction(
|
||||
this,
|
||||
|
||||
@ -24,8 +24,7 @@ import {
|
||||
DataIndexes,
|
||||
GAME_MASTER,
|
||||
IADSDensities,
|
||||
IDLE,
|
||||
MOVE_UNIT,
|
||||
IDLE
|
||||
} from "../constants/constants";
|
||||
import { DataExtractor } from "../server/dataextractor";
|
||||
import { citiesDatabase } from "./databases/citiesdatabase";
|
||||
@ -1954,7 +1953,6 @@ export class UnitsManager {
|
||||
if (this.getSelectedUnits().length > 0) {
|
||||
/* Disable the firing of the selection event for a certain amount of time. This avoids firing many events if many units are selected */
|
||||
if (!this.#selectionEventDisabled) {
|
||||
getApp().getMap().setState(MOVE_UNIT);
|
||||
window.setTimeout(() => {
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("unitsSelection", {
|
||||
|
||||
@ -62,7 +62,9 @@ module.exports = function (configLocation) {
|
||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
||||
ammo: [],
|
||||
contacts: [],
|
||||
activePath: [],
|
||||
activePath: [
|
||||
{lat: 37.1, lng: -116.1}
|
||||
],
|
||||
isLeader: true
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user