mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Resolved conflicts
This commit is contained in:
@@ -8,36 +8,61 @@ export class Dropdown {
|
||||
|
||||
constructor(ID: string, callback: CallableFunction, options: string[] | null = null)
|
||||
{
|
||||
this.#element = <HTMLElement>document.getElementById(ID);
|
||||
this.#options = <HTMLElement>this.#element.querySelector(".ol-select-options");
|
||||
this.#value = <HTMLElement>this.#element.querySelector(".ol-select-value");
|
||||
this.#element = <HTMLElement>document.getElementById(ID);
|
||||
this.#options = <HTMLElement>this.#element.querySelector(".ol-select-options");
|
||||
this.#value = <HTMLElement>this.#element.querySelector(".ol-select-value");
|
||||
this.#defaultValue = this.#value.innerText;
|
||||
this.#callback = callback;
|
||||
this.#callback = callback;
|
||||
|
||||
if (options != null) {
|
||||
this.setOptions(options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Do open/close toggle
|
||||
this.#element.addEventListener("click", ev => {
|
||||
|
||||
if ( ev.target instanceof HTMLElement && ev.target.nodeName !== "A" ) {
|
||||
ev.preventDefault();
|
||||
}
|
||||
this.#value.addEventListener( "click", ev => {
|
||||
|
||||
ev.stopPropagation();
|
||||
this.#element.classList.toggle("is-open");
|
||||
this.#element.classList.toggle( "is-open" );
|
||||
this.#clip();
|
||||
|
||||
});
|
||||
|
||||
// Autoclose on mouseleave
|
||||
this.#element.addEventListener("mouseleave", ev => {
|
||||
this.#element.classList.remove("is-open");
|
||||
this.#close();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
#clip() {
|
||||
|
||||
const options = this.#options;
|
||||
const bounds = options.getBoundingClientRect();
|
||||
|
||||
this.#element.dataset.position = ( bounds.bottom > window.innerHeight ) ? "top" : "";
|
||||
|
||||
}
|
||||
|
||||
|
||||
#close() {
|
||||
this.#element.classList.remove( "is-open" );
|
||||
this.#element.dataset.position = "";
|
||||
}
|
||||
|
||||
|
||||
#open() {
|
||||
this.#element.classList.add( "is-open" );
|
||||
}
|
||||
|
||||
|
||||
#toggle() {
|
||||
|
||||
if ( this.#element.classList.contains( "is-open" ) ) {
|
||||
this.#close();
|
||||
} else {
|
||||
this.#open();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
setOptions(optionsList: string[])
|
||||
{
|
||||
this.#optionsList = optionsList;
|
||||
@@ -47,7 +72,9 @@ export class Dropdown {
|
||||
button.textContent = option;
|
||||
div.appendChild(button);
|
||||
button.addEventListener("click", (e: MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
this.#value.innerText = option;
|
||||
this.#close();
|
||||
this.#callback( option, e );
|
||||
});
|
||||
return div;
|
||||
|
||||
@@ -168,7 +168,7 @@ export class MapContextMenu extends ContextMenu {
|
||||
/********* Ground unit spawn menu *********/
|
||||
#setGroundUnitRole(role: string) {
|
||||
this.#spawnOptions.role = role;
|
||||
this.#resetGroundUnitRole();
|
||||
this.#resetGroundUnitType();
|
||||
this.#groundUnitTypeDropdown.setOptions(groundUnitsDatabase.getByRole(role).map((blueprint) => { return blueprint.label }));
|
||||
this.#groundUnitTypeDropdown.selectValue(0);
|
||||
this.clip();
|
||||
|
||||
@@ -75,7 +75,7 @@ export class Slider {
|
||||
{
|
||||
this.#value = newValue;
|
||||
if (this.#slider != null)
|
||||
this.#slider.value = String((newValue - this.#minValue) / (this.#maxValue - this.#minValue) * 100);
|
||||
this.#slider.value = String((newValue - this.#minValue) / (this.#maxValue - this.#minValue) * parseFloat(this.#slider.max));
|
||||
this.#onValue()
|
||||
}
|
||||
}
|
||||
@@ -120,7 +120,7 @@ export class Slider {
|
||||
this.#dragged = false;
|
||||
if (this.#slider != null)
|
||||
{
|
||||
this.#value = this.#minValue + parseFloat(this.#slider.value) / 100 * (this.#maxValue - this.#minValue);
|
||||
this.#value = this.#minValue + parseFloat(this.#slider.value) / parseFloat(this.#slider.max) * (this.#maxValue - this.#minValue);
|
||||
this.#callback(this.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,9 @@ import { AIC } from "./aic/aic";
|
||||
import { ATC } from "./atc/atc";
|
||||
import { FeatureSwitches } from "./featureswitches";
|
||||
import { LogPanel } from "./panels/logpanel";
|
||||
import { getAirbases, getBullseye as getBullseyes, getMission, getUnits, toggleDemoEnabled } from "./server/server";
|
||||
import { getAirbases, getBullseye as getBullseyes, getConfig, getMission, getUnits, setAddress, toggleDemoEnabled } from "./server/server";
|
||||
import { UnitDataTable } from "./units/unitdatatable";
|
||||
import { keyEventWasInInput } from "./other/utils";
|
||||
|
||||
var map: Map;
|
||||
|
||||
@@ -69,16 +70,33 @@ function setup() {
|
||||
/* Setup event handlers */
|
||||
setupEvents();
|
||||
|
||||
/* On the first connection, force request of full data */
|
||||
getAirbases((data: AirbasesData) => getMissionData()?.update(data));
|
||||
getBullseyes((data: BullseyesData) => getMissionData()?.update(data));
|
||||
getMission((data: any) => {getMissionData()?.update(data)});
|
||||
getUnits((data: UnitsData) => getUnitsManager()?.update(data), true /* Does a full refresh */);
|
||||
|
||||
/* Start periodically requesting updates */
|
||||
startPeriodicUpdate();
|
||||
getConfig(readConfig)
|
||||
}
|
||||
|
||||
function readConfig(config: any)
|
||||
{
|
||||
if (config && config["server"] != undefined && config["server"]["address"] != undefined && config["server"]["port"] != undefined)
|
||||
{
|
||||
const address = config["server"]["address"];
|
||||
const port = config["server"]["port"];
|
||||
if ((typeof address === 'string' || address instanceof String) && typeof port == 'number')
|
||||
{
|
||||
setAddress(window.location.hostname, <number>port);
|
||||
}
|
||||
|
||||
/* On the first connection, force request of full data */
|
||||
getAirbases((data: AirbasesData) => getMissionData()?.update(data));
|
||||
getBullseyes((data: BullseyesData) => getMissionData()?.update(data));
|
||||
getMission((data: any) => {getMissionData()?.update(data)});
|
||||
getUnits((data: UnitsData) => getUnitsManager()?.update(data), true /* Does a full refresh */);
|
||||
|
||||
/* Start periodically requesting updates */
|
||||
startPeriodicUpdate();
|
||||
}
|
||||
else {
|
||||
throw new Error('Could not read configuration file!');
|
||||
}
|
||||
}
|
||||
|
||||
function startPeriodicUpdate() {
|
||||
requestUpdate();
|
||||
@@ -124,14 +142,16 @@ function checkSessionHash(newSessionHash: string) {
|
||||
function setupEvents() {
|
||||
/* Generic clicks */
|
||||
document.addEventListener("click", (ev) => {
|
||||
|
||||
if (ev instanceof PointerEvent && ev.target instanceof HTMLElement) {
|
||||
if (ev instanceof MouseEvent && ev.target instanceof HTMLElement) {
|
||||
|
||||
const target = ev.target;
|
||||
|
||||
if (target.classList.contains("olympus-dialog-close")) {
|
||||
target.closest("div.olympus-dialog")?.classList.add("hide");
|
||||
}
|
||||
|
||||
const triggerElement = target.closest("[data-on-click]");
|
||||
|
||||
if (triggerElement instanceof HTMLElement) {
|
||||
const eventName: string = triggerElement.dataset.onClick || "";
|
||||
let params = JSON.parse(triggerElement.dataset.onClickParams || "{}");
|
||||
@@ -148,23 +168,22 @@ function setupEvents() {
|
||||
|
||||
/* Keyup events */
|
||||
document.addEventListener("keyup", ev => {
|
||||
|
||||
if ( keyEventWasInInput( ev ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ev.code) {
|
||||
|
||||
case "KeyL":
|
||||
document.body.toggleAttribute("data-hide-labels");
|
||||
break;
|
||||
|
||||
case "KeyD":
|
||||
toggleDemoEnabled();
|
||||
break;
|
||||
|
||||
case "Minus": // For Veltro's italian layout keyboard, which lacks a quote
|
||||
case "Quote":
|
||||
unitDataTable.toggle();
|
||||
break
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
|
||||
@@ -26,6 +26,27 @@ export function ConvertDDToDMS(D: number, lng: boolean) {
|
||||
}
|
||||
|
||||
|
||||
export function dataPointMap( container:HTMLElement, data:any) {
|
||||
|
||||
Object.keys( data ).forEach( ( key ) => {
|
||||
|
||||
const val = "" + data[ key ]; // Ensure a string
|
||||
|
||||
container.querySelectorAll( `[data-point="${key}"]`).forEach( el => {
|
||||
|
||||
// We could probably have options here
|
||||
if ( el instanceof HTMLInputElement ) {
|
||||
el.value = val;
|
||||
} else if ( el instanceof HTMLElement ) {
|
||||
el.innerText = val;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
export function deg2rad(deg: number) {
|
||||
var pi = Math.PI;
|
||||
return deg * (pi / 180);
|
||||
@@ -48,6 +69,15 @@ export function distance(lat1: number, lon1: number, lat2: number, lon2: number)
|
||||
}
|
||||
|
||||
|
||||
export function keyEventWasInInput( event:KeyboardEvent ) {
|
||||
|
||||
const target = event.target;
|
||||
|
||||
return ( target instanceof HTMLElement && ( [ "INPUT", "TEXTAREA" ].includes( target.nodeName ) ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
export function rad2deg(rad: number) {
|
||||
var pi = Math.PI;
|
||||
return rad / (pi / 180);
|
||||
|
||||
@@ -36,10 +36,17 @@ export class MouseInfoPanel extends Panel {
|
||||
var el = <HTMLElement>this.getElement().querySelector(`#bullseye-${idx}`);
|
||||
|
||||
if ( el != null ) {
|
||||
|
||||
var dist = distance(bullseyes[idx].latitude, bullseyes[idx].longitude, mousePosition.lat, mousePosition.lng);
|
||||
var bear = bearing(bullseyes[idx].latitude, bullseyes[idx].longitude, mousePosition.lat, mousePosition.lng);
|
||||
|
||||
el.dataset.bearing = zeroAppend(Math.floor(bear), 3);
|
||||
let bng = zeroAppend(Math.floor(bear), 3);
|
||||
|
||||
if ( bng === "000" ) {
|
||||
bng = "360";
|
||||
}
|
||||
|
||||
el.dataset.bearing = bng;
|
||||
el.dataset.distance = zeroAppend(Math.floor(dist*0.000539957), 3);
|
||||
el.dataset.distanceUnits = "NM";
|
||||
}
|
||||
|
||||
@@ -11,9 +11,13 @@ export class Panel {
|
||||
this.#visible = true;
|
||||
}
|
||||
|
||||
protected onHide() {}
|
||||
|
||||
hide() {
|
||||
this.#element.classList.toggle("hide", true);
|
||||
this.#visible = false;
|
||||
|
||||
this.onHide();
|
||||
}
|
||||
|
||||
toggle() {
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import { getUnitsManager } from "..";
|
||||
import { Slider } from "../controls/slider";
|
||||
import { dataPointMap } from "../other/utils";
|
||||
import { aircraftDatabase } from "../units/aircraftdatabase";
|
||||
import { groundUnitsDatabase } from "../units/groundunitsdatabase";
|
||||
import { Aircraft, GroundUnit, Unit } from "../units/unit";
|
||||
import { UnitDatabase } from "../units/unitdatabase";
|
||||
import { UnitsManager } from "../units/unitsmanager";
|
||||
import { Panel } from "./panel";
|
||||
|
||||
const ROEs: string[] = ["Free", "Designated free", "Designated", "Return", "Hold"];
|
||||
const reactionsToThreat: string[] = ["None", "Passive", "Evade", "Escape", "Abort"];
|
||||
// const ROEs: string[] = ["Free", "Designated free", "Designated", "Return", "Hold"]; // Full list
|
||||
// const reactionsToThreat: string[] = ["None", "Passive", "Evade", "Escape", "Abort"]; // Full list
|
||||
|
||||
const ROEs: string[] = [ "Hold", "Return", "Designated", "Free" ];
|
||||
const reactionsToThreat: string[] = [ "None", "Passive", "Evade" ];
|
||||
|
||||
const minSpeedValues: { [key: string]: number } = { Aircraft: 100, Helicopter: 0, NavyUnit: 0, GroundUnit: 0 };
|
||||
const maxSpeedValues: { [key: string]: number } = { Aircraft: 800, Helicopter: 300, NavyUnit: 60, GroundUnit: 60 };
|
||||
const speedIncrements: { [key: string]: number } = { Aircraft: 25, Helicopter: 10, NavyUnit: 5, GroundUnit: 5 };
|
||||
@@ -19,14 +23,23 @@ const altitudeIncrements: { [key: string]: number } = { Aircraft: 2500, Helicopt
|
||||
export class UnitControlPanel extends Panel {
|
||||
#altitudeSlider: Slider;
|
||||
#airspeedSlider: Slider;
|
||||
#expectedAltitude:number = -1;
|
||||
#expectedSpeed: number = -1;
|
||||
#optionButtons: { [key: string]: HTMLButtonElement[] } = {}
|
||||
|
||||
constructor(ID: string) {
|
||||
super(ID);
|
||||
|
||||
/* Unit control sliders */
|
||||
this.#altitudeSlider = new Slider("altitude-slider", 0, 100, "ft", (value: number) => getUnitsManager().selectedUnitsSetAltitude(value * 0.3048));
|
||||
this.#airspeedSlider = new Slider("airspeed-slider", 0, 100, "kts", (value: number) => getUnitsManager().selectedUnitsSetSpeed(value / 1.94384));
|
||||
this.#altitudeSlider = new Slider("altitude-slider", 0, 100, "ft", (value: number) => {
|
||||
this.#expectedAltitude = value;
|
||||
getUnitsManager().selectedUnitsSetAltitude(value * 0.3048)
|
||||
});
|
||||
|
||||
this.#airspeedSlider = new Slider("airspeed-slider", 0, 100, "kts", (value: number) => {
|
||||
this.#expectedSpeed = value;
|
||||
getUnitsManager().selectedUnitsSetSpeed(value / 1.94384)
|
||||
});
|
||||
|
||||
/* Option buttons */
|
||||
this.#optionButtons["ROE"] = ROEs.map((option: string, index: number) => {
|
||||
@@ -55,6 +68,39 @@ export class UnitControlPanel extends Panel {
|
||||
this.hide();
|
||||
}
|
||||
|
||||
|
||||
// Do this after panel is hidden (make sure there's a reset)
|
||||
protected onHide() {
|
||||
this.#expectedAltitude = -1;
|
||||
this.#expectedSpeed = -1;
|
||||
}
|
||||
|
||||
|
||||
// Update function will only be allowed to update the sliders once it's matched the expected value for the first time (due to lag of Ajax request)
|
||||
#updateCanSetAltitudeSlider( altitude:number ) {
|
||||
|
||||
if ( this.#expectedAltitude < 0 || altitude === this.#expectedAltitude ) {
|
||||
this.#expectedAltitude = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#updateCanSetSpeedSlider( altitude:number ) {
|
||||
|
||||
if ( this.#expectedSpeed < 0 || altitude === this.#expectedSpeed ) {
|
||||
this.#expectedSpeed = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
update() {
|
||||
var units = getUnitsManager().getSelectedUnits();
|
||||
if (this.getElement() != null && units.length > 0) {
|
||||
@@ -69,23 +115,13 @@ export class UnitControlPanel extends Panel {
|
||||
else
|
||||
database = null; // TODO add databases for other unit types
|
||||
|
||||
if (index === 0) {
|
||||
this.getElement().querySelectorAll(`[data-object|="unit"]`).forEach(marker => {
|
||||
marker.setAttribute("data-coalition", unit.getMissionData().coalition);
|
||||
const shortLabel = <HTMLElement>marker.querySelector(".unit-short-label");
|
||||
if (shortLabel)
|
||||
shortLabel.innerText = database?.getByName(unit.getBaseData().name)?.shortLabel || "";
|
||||
});
|
||||
}
|
||||
console.log( unit.getBaseData() );
|
||||
|
||||
var button = document.createElement("button");
|
||||
const unitName = <HTMLInputElement>this.getElement().querySelector("#unit-name");
|
||||
var callsign = aircraftDatabase.getByName(unit.getBaseData().unitName)?.label || "";
|
||||
var callsign = unit.getBaseData().unitName || "";
|
||||
|
||||
button.innerText = "";
|
||||
button.setAttribute("data-short-label", database?.getByName(unit.getBaseData().name)?.shortLabel || "");
|
||||
button.setAttribute("data-callsign", callsign);
|
||||
unitName.value = callsign;
|
||||
|
||||
button.setAttribute("data-coalition", unit.getMissionData().coalition);
|
||||
button.classList.add("pill", "highlight-coalition")
|
||||
@@ -104,6 +140,7 @@ export class UnitControlPanel extends Panel {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#showFlightControlSliders(units: Unit[])
|
||||
{
|
||||
if (getUnitsManager().getSelectedUnitsType() !== undefined)
|
||||
@@ -132,12 +169,24 @@ export class UnitControlPanel extends Panel {
|
||||
this.#altitudeSlider.setIncrement(altitudeIncrements[unitsType]);
|
||||
|
||||
this.#airspeedSlider.setActive(targetSpeed != undefined);
|
||||
if (targetSpeed != undefined)
|
||||
this.#airspeedSlider.setValue(targetSpeed * 1.94384);
|
||||
if (targetSpeed != undefined) {
|
||||
|
||||
targetSpeed *= 1.94384;
|
||||
|
||||
if ( this.#updateCanSetSpeedSlider( targetSpeed ) ) {
|
||||
this.#airspeedSlider.setValue( targetSpeed );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
this.#altitudeSlider.setActive(targetAltitude != undefined);
|
||||
if (targetAltitude != undefined)
|
||||
this.#altitudeSlider.setValue(targetAltitude / 0.3048);
|
||||
if (targetAltitude != undefined) {
|
||||
targetAltitude /= 0.3048;
|
||||
|
||||
if ( this.#updateCanSetAltitudeSlider( targetAltitude ) ) {
|
||||
this.#altitudeSlider.setValue( targetAltitude );
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.#airspeedSlider.setActive(false);
|
||||
|
||||
@@ -2,9 +2,8 @@ import * as L from 'leaflet'
|
||||
import { setConnected } from '..';
|
||||
import { SpawnOptions } from '../controls/mapcontextmenu';
|
||||
|
||||
/* Edit here to change server address */
|
||||
const REST_ADDRESS = "http://localhost:30000/olympus";
|
||||
const DEMO_ADDRESS = "http://localhost:3000/demo";
|
||||
var REST_ADDRESS = "http://localhost:30000/olympus";
|
||||
var DEMO_ADDRESS = window.location.href + "demo";
|
||||
const UNITS_URI = "units";
|
||||
const LOGS_URI = "logs";
|
||||
const AIRBASES_URI = "airbases";
|
||||
@@ -24,9 +23,14 @@ export function GET(callback: CallableFunction, uri: string){
|
||||
xmlHttp.open("GET", `${demoEnabled? DEMO_ADDRESS: REST_ADDRESS}/${uri}`, true);
|
||||
xmlHttp.onload = function (e) {
|
||||
var data = JSON.parse(xmlHttp.responseText);
|
||||
callback(data);
|
||||
lastUpdateTime = parseInt(data.time);
|
||||
setConnected(true);
|
||||
if (parseInt(data.time) > lastUpdateTime)
|
||||
{
|
||||
callback(data);
|
||||
lastUpdateTime = parseInt(data.time);
|
||||
if (isNaN(lastUpdateTime))
|
||||
lastUpdateTime = 0;
|
||||
setConnected(true);
|
||||
}
|
||||
};
|
||||
xmlHttp.onerror = function () {
|
||||
console.error("An error occurred during the XMLHttpRequest");
|
||||
@@ -45,6 +49,24 @@ export function POST(request: object, callback: CallableFunction){
|
||||
xhr.send(JSON.stringify(request));
|
||||
}
|
||||
|
||||
export function getConfig(callback: CallableFunction) {
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.open("GET", window.location.href + "config", true);
|
||||
xmlHttp.onload = function (e) {
|
||||
var data = JSON.parse(xmlHttp.responseText);
|
||||
callback(data);
|
||||
};
|
||||
xmlHttp.onerror = function () {
|
||||
console.error("An error occurred during the XMLHttpRequest, could not retrieve configuration file");
|
||||
};
|
||||
xmlHttp.send(null);
|
||||
}
|
||||
|
||||
export function setAddress(address: string, port: number) {
|
||||
REST_ADDRESS = `http://${address}:${port}/olympus`
|
||||
console.log(`Setting REST address to ${REST_ADDRESS}`)
|
||||
}
|
||||
|
||||
export function getAirbases(callback: CallableFunction) {
|
||||
GET(callback, AIRBASES_URI);
|
||||
}
|
||||
|
||||
@@ -573,6 +573,15 @@ export class GroundUnit extends Unit {
|
||||
super(ID, data);
|
||||
}
|
||||
|
||||
getMarkerHTML() {
|
||||
var role = groundUnitsDatabase.getByName(this.getBaseData().name)?.loadouts[0].roles[0];
|
||||
return `<div class="unit" data-object="unit-${this.getMarkerCategory()}" data-coalition="${this.getMissionData().coalition}">
|
||||
<div class="unit-selected-spotlight"></div>
|
||||
<div class="unit-marker"></div>
|
||||
<div class="unit-short-label">${role?.substring(0, 1)?.toUpperCase() || ""}</div>
|
||||
</div>`
|
||||
}
|
||||
|
||||
getMarkerCategory()
|
||||
{
|
||||
// TODO this is very messy
|
||||
|
||||
@@ -3,11 +3,13 @@ import { getMap, getUnitDataTable } from "..";
|
||||
import { Unit } from "./unit";
|
||||
import { cloneUnit } from "../server/server";
|
||||
import { IDLE, MOVE_UNIT } from "../map/map";
|
||||
import { keyEventWasInInput } from "../other/utils";
|
||||
|
||||
export class UnitsManager {
|
||||
#units: { [ID: number]: Unit };
|
||||
#copiedUnits: Unit[];
|
||||
#selectionEventDisabled: boolean = false;
|
||||
#pasteDisabled: boolean = false;
|
||||
|
||||
constructor() {
|
||||
this.#units = {};
|
||||
@@ -330,16 +332,21 @@ export class UnitsManager {
|
||||
|
||||
pasteUnits()
|
||||
{
|
||||
for (let idx in this.#copiedUnits)
|
||||
if (!this.#pasteDisabled)
|
||||
{
|
||||
var unit = this.#copiedUnits[idx];
|
||||
cloneUnit(unit.ID, getMap().getMouseCoordinates());
|
||||
for (let idx in this.#copiedUnits)
|
||||
{
|
||||
var unit = this.#copiedUnits[idx];
|
||||
cloneUnit(unit.ID, getMap().getMouseCoordinates());
|
||||
}
|
||||
this.#pasteDisabled = true;
|
||||
setTimeout(() => this.#pasteDisabled = false, 250);
|
||||
}
|
||||
}
|
||||
|
||||
#onKeyDown(event: KeyboardEvent)
|
||||
{
|
||||
if (event.key === "Delete")
|
||||
if ( !keyEventWasInInput( event ) && event.key === "Delete")
|
||||
{
|
||||
this.selectedUnitsDelete();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user