From a7a41e60c45c5db7be1c9812a2318ed4d9dc4919 Mon Sep 17 00:00:00 2001 From: dpassoni Date: Mon, 6 Mar 2023 17:45:50 +0100 Subject: [PATCH] Incorporated unit info panel into unit control panel Converted callbacks to events Mouse info drawing moved to mouseinfopanel.ts --- client/public/stylesheets/layout.css | 16 +-- client/public/stylesheets/olympus.css | 32 +++++- client/src/@types/dom.d.ts | 5 +- client/src/map/map.ts | 92 +---------------- client/src/panels/mouseinfopanel.ts | 136 +++++++++++++++++++++----- client/src/panels/panel.ts | 7 ++ client/src/panels/unitinfopanel.ts | 22 ++++- client/src/server/server.ts | 10 +- client/src/units/unit.ts | 6 +- client/src/units/unitsmanager.ts | 63 ++++++------ client/views/index.ejs | 1 - client/views/mouseinfopanel.ejs | 4 +- client/views/unitcontrolpanel.ejs | 29 +++++- client/views/unitinfopanel.ejs | 28 ------ 14 files changed, 250 insertions(+), 201 deletions(-) delete mode 100644 client/views/unitinfopanel.ejs diff --git a/client/public/stylesheets/layout.css b/client/public/stylesheets/layout.css index 2fea9002..3809990c 100644 --- a/client/public/stylesheets/layout.css +++ b/client/public/stylesheets/layout.css @@ -29,18 +29,6 @@ body { min-width: 820px; } -#unit-info-panel { - position: fixed; - left: 10px; - bottom: 10px; - z-index: 1000; -} - -.content #unit-info-panel { - position: static; - margin: 50px; -} - #primary-toolbar { position: absolute; left: 10px; @@ -54,10 +42,10 @@ body { #unit-control-panel { position: absolute; - top: 10px; + top: 80px; height: fit-content; width: 250px; - right: 10px; + left: 10px; z-index: 1000; } diff --git a/client/public/stylesheets/olympus.css b/client/public/stylesheets/olympus.css index 08485192..09600ab6 100644 --- a/client/public/stylesheets/olympus.css +++ b/client/public/stylesheets/olympus.css @@ -226,6 +226,14 @@ button[disabled="disabled"] { font-size:14px; } +h1, +h2, +h3, +h4, +h5, +h6 { + margin: 0px; +} nav.ol-panel { column-gap: 20px; @@ -296,7 +304,7 @@ nav.ol-panel > :last-child { } .hide { - display: none; + display: none !important; } .icon-small { @@ -382,4 +390,26 @@ nav.ol-panel > :last-child { .main-logo { width: 40px; height: 40px; +} + +.ol-measure-box { + position: absolute; + padding-left: 0.5em; + padding-right: 0.5em; + padding-top: 0.2em; + padding-bottom: 0.2em; + background-color: var(--background-steel); + border-radius: 999px; + width: fit-content; + height: fit-content; + text-align: center; + color: var(--primary-grey); + font-size: 12px; + z-index: 2000; + font-weight: var(--font-weight-bolder); +} + +#unit-info-panel { + display: flex; + flex-direction: column; } \ No newline at end of file diff --git a/client/src/@types/dom.d.ts b/client/src/@types/dom.d.ts index ddeaba8d..094d3444 100644 --- a/client/src/@types/dom.d.ts +++ b/client/src/@types/dom.d.ts @@ -1,6 +1,8 @@ interface CustomEventMap { "unitSelection": CustomEvent, + "unitDeselection": CustomEvent, "unitsSelection": CustomEvent, + "unitsDeselection": CustomEvent, "clearSelection": CustomEvent<>, "unitCreation": CustomEvent, "unitDeletion": CustomEvent, @@ -10,8 +12,7 @@ interface CustomEventMap { "unitLandCommand": CustomEvent, "unitSetAltitudeCommand": CustomEvent, "unitSetSpeedCommand": CustomEvent, - "unitSetROECommand": CustomEvent, - "unitSetReactionToThreatCommand": CustomEvent, + "unitSetOption": CustomEvent, "groupCreation": CustomEvent, "groupDeletion": CustomEvent, "mapStateChanged": CustomEvent, diff --git a/client/src/map/map.ts b/client/src/map/map.ts index 01955e35..cc24b02d 100644 --- a/client/src/map/map.ts +++ b/client/src/map/map.ts @@ -1,7 +1,6 @@ import * as L from "leaflet" -import { getContextMenu, getUnitsManager, getActiveCoalition, getMouseInfoPanel } from ".."; +import { getContextMenu, getUnitsManager, getActiveCoalition } from ".."; import { spawnAircraft, spawnGroundUnit, spawnSmoke } from "../server/server"; -import { bearing, distance, zeroAppend } from "../other/utils"; import { aircraftDatabase } from "../units/aircraftdatabase"; import { unitTypes } from "../units/unittypes"; import { BoxSelect } from "./boxselect"; @@ -28,11 +27,6 @@ export class Map extends L.Map { #layer: L.TileLayer | null = null; #preventLeftClick: boolean = false; #leftClickTimer: number = 0; - #measurePoint: L.LatLng | null; - #measureIcon: L.Icon; - #measureMarker: L.Marker; - #measureLine: L.Polyline = new L.Polyline([], { color: '#2d3e50', weight: 3, opacity: 0.5, smoothFactor: 1, interactive: false }); - #measureLineDiv: HTMLElement; #lastMousePosition: L.Point = new L.Point(0, 0); constructor(ID: string) { @@ -45,15 +39,7 @@ export class Map extends L.Map { /* Init the state machine */ this.#state = IDLE; - this.#measurePoint = null; - - this.#measureIcon = new L.Icon({ iconUrl: 'images/pin.png', iconAnchor: [16, 32]}); - this.#measureMarker = new L.Marker([0, 0], {icon: this.#measureIcon, interactive: false}); - this.#measureLineDiv = document.createElement("div"); - this.#measureLineDiv.classList.add("ol-measure-box"); - this.#measureLineDiv.style.display = 'none'; - - document.body.appendChild(this.#measureLineDiv); + /* Register event handles */ this.on("click", (e: any) => this.#onClick(e)); @@ -63,7 +49,6 @@ export class Map extends L.Map { this.on('mousedown', (e: any) => this.#onMouseDown(e)); this.on('mouseup', (e: any) => this.#onMouseUp(e)); this.on('mousemove', (e: any) => this.#onMouseMove(e)); - this.on('zoom', (e: any) => this.#onZoom(e)); } setLayer(layerName: string) { @@ -162,19 +147,7 @@ export class Map extends L.Map { if (!this.#preventLeftClick) { this.hideContextMenu(); if (this.#state === IDLE) { - if (e.originalEvent.ctrlKey) - if (!this.#measurePoint) - { - this.#measurePoint = e.latlng; - this.#measureMarker.setLatLng(e.latlng); - this.#measureMarker.addTo(this); - } - else - { - this.#measurePoint = null; - if (this.hasLayer(this.#measureMarker)) - this.removeLayer(this.#measureMarker); - } + } else if (this.#state === MOVE_UNIT) { this.setState(IDLE); @@ -223,17 +196,13 @@ export class Map extends L.Map { #onMouseDown(e: any) { if ((e.originalEvent.which == 1) && (e.originalEvent.button == 0)) - { this.dragging.disable(); - } } #onMouseUp(e: any) { if ((e.originalEvent.which == 1) && (e.originalEvent.button == 0)) - { this.dragging.enable(); - } } #onMouseMove(e: any) @@ -241,26 +210,10 @@ export class Map extends L.Map { var selectedUnitPosition = null; var selectedUnits = getUnitsManager().getSelectedUnits(); if (selectedUnits && selectedUnits.length == 1) - { selectedUnitPosition = new L.LatLng(selectedUnits[0].getFlightData().latitude, selectedUnits[0].getFlightData().longitude); - } - getMouseInfoPanel()?.update(e.latlng, this.#measurePoint, selectedUnitPosition); this.#lastMousePosition.x = e.originalEvent.x; this.#lastMousePosition.y = e.originalEvent.y; - - if ( this.#measurePoint) - this.#drawMeasureLine(); - else - this.#hideMeasureLine(); - } - - #onZoom(e: any) - { - if (this.#measurePoint) - this.#drawMeasureLine(); - else - this.#hideMeasureLine(); } /* Spawning menus */ @@ -357,43 +310,4 @@ export class Map extends L.Map { spawnGroundUnit(unitType, e.latlng, getActiveCoalition()); }}}), true); } - - #drawMeasureLine() - { - var mouseLatLng = this.containerPointToLatLng(this.#lastMousePosition); - if (this.#measurePoint != null) - { - var points = [this.#measurePoint, mouseLatLng]; - this.#measureLine.setLatLngs(points); - var dist = distance(this.#measurePoint.lat, this.#measurePoint.lng, mouseLatLng.lat, mouseLatLng.lng); - var bear = bearing(this.#measurePoint.lat, this.#measurePoint.lng, mouseLatLng.lat, mouseLatLng.lng); - var startXY = this.latLngToContainerPoint(this.#measurePoint); - var dx = (this.#lastMousePosition.x - startXY.x); - var dy = (this.#lastMousePosition.y - startXY.y); - - var angle = Math.atan2(dy, dx); - if (angle > Math.PI / 2) - angle = angle - Math.PI; - - if (angle < -Math.PI / 2) - angle = angle + Math.PI; - - this.#measureLineDiv.innerHTML = `${zeroAppend(Math.floor(bear), 3)}° / ${zeroAppend(Math.floor(dist*0.000539957), 3)} NM` - this.#measureLineDiv.style.left = (this.#lastMousePosition.x + startXY.x) / 2 - this.#measureLineDiv.offsetWidth / 2 + "px"; - this.#measureLineDiv.style.top = (this.#lastMousePosition.y + startXY.y) / 2 - this.#measureLineDiv.offsetHeight / 2 + "px"; - this.#measureLineDiv.style.rotate = angle + "rad"; - this.#measureLineDiv.style.display = ""; - } - - if (!this.hasLayer(this.#measureLine)) - this.#measureLine.addTo(this); - } - - #hideMeasureLine() - { - this.#measureLineDiv.style.display = "none"; - - if (this.hasLayer(this.#measureLine)) - this.removeLayer(this.#measureLine) - } } diff --git a/client/src/panels/mouseinfopanel.ts b/client/src/panels/mouseinfopanel.ts index 230fc7fa..528ee645 100644 --- a/client/src/panels/mouseinfopanel.ts +++ b/client/src/panels/mouseinfopanel.ts @@ -1,14 +1,35 @@ -import { LatLng } from "leaflet"; -import { getMissionData } from ".."; +import { Icon, LatLng, Marker, Polyline } from "leaflet"; +import { getMap, getMissionData, getUnitsManager } from ".."; import { distance, bearing, zeroPad, zeroAppend } from "../other/utils"; +import { Unit } from "../units/unit"; import { Panel } from "./panel"; export class MouseInfoPanel extends Panel { + #measureMarker: Marker; + #measurePoint: LatLng | null = null; + #measureIcon: Icon; + #measureLine: Polyline = new Polyline([], { color: '#2d3e50', weight: 3, opacity: 0.5, smoothFactor: 1, interactive: false }); + #measureBox: HTMLElement; + constructor(ID: string) { super(ID); + + this.#measureIcon = new Icon({ iconUrl: 'images/pin.png', iconAnchor: [16, 32]}); + this.#measureMarker = new Marker([0, 0], {icon: this.#measureIcon, interactive: false}); + + this.#measureBox = document.createElement("div"); + this.#measureBox.classList.add("ol-measure-box"); + document.body.appendChild(this.#measureBox); + + getMap()?.on("click", (e: any) => this.#onMapClick(e)); + getMap()?.on('zoom', (e: any) => this.#onZoom(e)); + getMap()?.on('mousemove', (e: any) => this.#onMouseMove(e)); + + document.addEventListener('unitsSelection', (e: CustomEvent) => this.#onUnitsSelection(e.detail)); + document.addEventListener('clearSelection', () => this.#onClearSelection()); } - update(mousePosition: LatLng, measurePosition: LatLng | null, unitPosition: LatLng | null) { + #update(mousePosition: LatLng, measurePosition: LatLng | null, unitPosition: LatLng | null) { var bullseyes = getMissionData().getBullseyes(); for (let idx in bullseyes) { @@ -16,7 +37,7 @@ export class MouseInfoPanel extends Panel { var bear = bearing(bullseyes[idx].lat, bullseyes[idx].lng, mousePosition.lat, mousePosition.lng); var el = this.getElement().querySelector(`#bullseye-${idx}`); if (el != null) - el.innerHTML = `${zeroAppend(Math.floor(bear), 3)}° / ${zeroAppend(Math.floor(dist*0.000539957), 3)} NM` + el.innerText = `${zeroAppend(Math.floor(bear), 3)}° / ${zeroAppend(Math.floor(dist*0.000539957), 3)} NM` } if (measurePosition) { @@ -24,33 +45,100 @@ export class MouseInfoPanel extends Panel { var bear = bearing(measurePosition.lat, measurePosition.lng, mousePosition.lat, mousePosition.lng); var el = this.getElement().querySelector(`#measure-position`); if (el != null) - { - el.innerHTML = `${zeroAppend(Math.floor(bear), 3)}° / ${zeroAppend(Math.floor(dist*0.000539957), 3)} NM` - if (el.parentElement != null) - el.parentElement.style.display = 'flex'; //TODO: don't like that it's hardcoded - } - } - else { - var el = this.getElement().querySelector(`#measure-position`); - if (el != null && el.parentElement != null) - el.parentElement.style.display = 'none'; + el.innerText = `${zeroAppend(Math.floor(bear), 3)}° / ${zeroAppend(Math.floor(dist*0.000539957), 3)} NM` } + if (unitPosition) { var dist = distance(unitPosition.lat, unitPosition.lng, mousePosition.lat, mousePosition.lng); var bear = bearing(unitPosition.lat, unitPosition.lng, mousePosition.lat, mousePosition.lng); var el = this.getElement().querySelector(`#unit-position`); if (el != null) - { - el.innerHTML = `${zeroAppend(Math.floor(bear), 3)}° / ${zeroAppend(Math.floor(dist*0.000539957), 3)} NM` - if (el.parentElement != null) - el.parentElement.style.display = 'flex'; //TODO: don't like that its hardcoded - } - } - else { - var el = this.getElement().querySelector(`#unit-position`); - if (el != null && el.parentElement != null) - el.parentElement.style.display = 'none'; + el.innerText = `${zeroAppend(Math.floor(bear), 3)}° / ${zeroAppend(Math.floor(dist*0.000539957), 3)} NM` } } + + #onMapClick(e: any) + { + if (e.originalEvent.ctrlKey) + { + if (!this.#measurePoint) + { + this.#measureBox.classList.toggle("hide", false); + this.getElement().querySelector(`#measure-position`)?.classList.toggle("hide", false); + this.#measurePoint = e.latlng; + this.#measureMarker.setLatLng(e.latlng); + this.#measureMarker.addTo(getMap()); + if (!getMap().hasLayer(this.#measureLine)) + this.#measureLine.addTo(getMap()); + } + else + { + this.#measureBox.classList.toggle("hide", true); + this.getElement().querySelector(`#measure-position`)?.classList.toggle("hide", true); + this.#measurePoint = null; + if (getMap().hasLayer(this.#measureMarker)) + getMap().removeLayer(this.#measureMarker); + + this.#measureLine.setLatLngs([]); + if (getMap().hasLayer(this.#measureLine)) + getMap().removeLayer(this.#measureLine); + } + } + } + + #drawMeasureLine() + { + var mouseLatLng = getMap().containerPointToLatLng(getMap().getMousePosition()); + if (this.#measurePoint != null) + { + var points = [this.#measurePoint, mouseLatLng]; + this.#measureLine.setLatLngs(points); + var dist = distance(this.#measurePoint.lat, this.#measurePoint.lng, mouseLatLng.lat, mouseLatLng.lng); + var bear = bearing(this.#measurePoint.lat, this.#measurePoint.lng, mouseLatLng.lat, mouseLatLng.lng); + var startXY = getMap().latLngToContainerPoint(this.#measurePoint); + var dx = (getMap().getMousePosition().x - startXY.x); + var dy = (getMap().getMousePosition().y - startXY.y); + + var angle = Math.atan2(dy, dx); + if (angle > Math.PI / 2) + angle = angle - Math.PI; + + if (angle < -Math.PI / 2) + angle = angle + Math.PI; + + this.#measureBox.innerText = `${zeroAppend(Math.floor(bear), 3)}° / ${zeroAppend(Math.floor(dist*0.000539957), 3)} NM` + this.#measureBox.style.left = (getMap().getMousePosition().x + startXY.x) / 2 - this.#measureBox.offsetWidth / 2 + "px"; + this.#measureBox.style.top = (getMap().getMousePosition().y + startXY.y) / 2 - this.#measureBox.offsetHeight / 2 + "px"; + this.#measureBox.style.rotate = angle + "rad"; + } + } + + #onMouseMove(e: any) + { + var selectedUnitPosition = null; + var selectedUnits = getUnitsManager().getSelectedUnits(); + if (selectedUnits && selectedUnits.length == 1) + selectedUnitPosition = new LatLng(selectedUnits[0].getFlightData().latitude, selectedUnits[0].getFlightData().longitude); + + this.#update(e.latlng, this.#measurePoint, selectedUnitPosition); + this.#drawMeasureLine(); + } + + #onZoom(e: any) + { + this.#drawMeasureLine(); + } + + #onUnitsSelection(units: Unit[]) + { + if (units.length == 1) + this.getElement().querySelector(`#unit-position`)?.classList.toggle("hide", false); + } + + #onClearSelection() + { + this.#measureBox.classList.toggle("hide", true); + this.getElement().querySelector(`#unit-position`)?.classList.toggle("hide", true); + } } diff --git a/client/src/panels/panel.ts b/client/src/panels/panel.ts index c88c5ad0..1b803870 100644 --- a/client/src/panels/panel.ts +++ b/client/src/panels/panel.ts @@ -1,5 +1,6 @@ export class Panel { #element: HTMLElement + #visible: boolean = true; constructor(ID: string) { this.#element = document.getElementById(ID); @@ -7,13 +8,19 @@ export class Panel { show() { this.#element.classList.toggle("hide", false); + this.#visible = true; } hide() { this.#element.classList.toggle("hide", true); + this.#visible = false; } getElement() { return this.#element; } + + getVisible(){ + return this.#visible; + } } \ No newline at end of file diff --git a/client/src/panels/unitinfopanel.ts b/client/src/panels/unitinfopanel.ts index b6024861..25ac7c66 100644 --- a/client/src/panels/unitinfopanel.ts +++ b/client/src/panels/unitinfopanel.ts @@ -30,11 +30,15 @@ export class UnitInfoPanel extends Panel { this.#task = (this.getElement().querySelector("#task")); this.#loadoutContainer = (this.getElement().querySelector("#loadout-container")); + document.addEventListener("unitsSelection", (e: CustomEvent) => this.#onUnitsSelection(e.detail)); + document.addEventListener("unitsDeselection", (e: CustomEvent) => this.#onUnitsDeselection(e.detail)); + document.addEventListener("unitUpdated", (e: CustomEvent) => this.#onUnitUpdate(e.detail)); + this.hide(); } - update(unit: Unit) { - if (this.getElement() != null) { + #onUnitUpdate(unit: Unit) { + if (this.getElement() != null && this.getVisible()) { /* Set the unit info */ this.#unitName.innerText = unit.getData().unitName; this.#groupName.innerText = unit.getData().groupName; @@ -72,4 +76,18 @@ export class UnitInfoPanel extends Panel { el.innerText = amount + "x" + displayName; this.#loadoutContainer.appendChild(el); } + + #onUnitsSelection(units: Unit[]){ + if (units.length == 1) + this.show(); + else + this.hide(); + } + + #onUnitsDeselection(units: Unit[]){ + if (units.length == 1) + this.show(); + else + this.hide(); + } } \ No newline at end of file diff --git a/client/src/server/server.ts b/client/src/server/server.ts index e69a68d2..46d27ed7 100644 --- a/client/src/server/server.ts +++ b/client/src/server/server.ts @@ -49,7 +49,7 @@ export function getUnits(callback: CallableFunction, refresh: boolean = false) { if (!DEMO) GET(callback, `${UNITS_URI}/${refresh? REFRESH_URI: UPDATE_URI}}`); else - callback(refresh? generateRandomUnitsDemoData(1000): {units:{}}); + callback(refresh? generateRandomUnitsDemoData(100): {units:{}}); } export function addDestination(ID: number, path: any) { @@ -149,8 +149,8 @@ function generateRandomUnitsDemoData(unitsNumber: number) for (let i = 0; i < unitsNumber; i++) { units[String(i)] = structuredClone(DEMO_UNIT_DATA); - units[String(i)].flightData.latitude += (Math.random() - 0.5) * 0.1; - units[String(i)].flightData.longitude += (Math.random() - 0.5) * 0.1; + units[String(i)].flightData.latitude += (Math.random() - 0.5) * 0.3; + units[String(i)].flightData.longitude += (Math.random() - 0.5) * 0.3; } return {"units": units}; } @@ -163,8 +163,8 @@ const DEMO_UNIT_DATA = { alive: true, category: "Aircraft", flightData: { - latitude: 37.3, - longitude: -116, + latitude: 37.2, + longitude: -115.8, altitude: 2000, heading: 0.5, speed: 300 diff --git a/client/src/units/unit.ts b/client/src/units/unit.ts index 40206e2a..79b115ab 100644 --- a/client/src/units/unit.ts +++ b/client/src/units/unit.ts @@ -87,6 +87,7 @@ export class Unit extends Marker { } setData(data: UnitData) { + document.dispatchEvent(new CustomEvent("unitUpdated", { detail: this })); var updateMarker = true; //if (this.getFlightData().latitude != response.flightData.latitude || // this.getFlightData().longitude != response.flightData.longitude || @@ -141,7 +142,10 @@ export class Unit extends Marker { if ((this.getData().alive || !selected) && this.#selectable && this.#selected != selected) { this.#selected = selected; this.getElement()?.querySelector(".unit")?.setAttribute("data-is-selected", String(this.getSelected())); - document.dispatchEvent(new CustomEvent("unitSelection", { detail: this })); + if (selected) + document.dispatchEvent(new CustomEvent("unitSelection", { detail: this })); + else + document.dispatchEvent(new CustomEvent("unitDeselection", { detail: this })); } } diff --git a/client/src/units/unitsmanager.ts b/client/src/units/unitsmanager.ts index 5b0549f9..cd5eb90f 100644 --- a/client/src/units/unitsmanager.ts +++ b/client/src/units/unitsmanager.ts @@ -1,6 +1,6 @@ import { LatLng, LatLngBounds } from "leaflet"; -import { getMap, getUnitControlPanel, getUnitInfoPanel } from ".."; -import { Unit, GroundUnit } from "./unit"; +import { getMap } from ".."; +import { Unit } from "./unit"; import { cloneUnit } from "../server/server"; import { IDLE, MOVE_UNIT } from "../map/map"; @@ -15,7 +15,8 @@ export class UnitsManager { document.addEventListener('copy', () => this.copyUnits()); document.addEventListener('paste', () => this.pasteUnits()); - document.addEventListener('unitSelection', (e: CustomEvent) => this.onUnitSelection(e.detail)); + document.addEventListener('unitSelection', (e: CustomEvent) => this.#onUnitSelection(e.detail)); + document.addEventListener('unitDeselection', (e: CustomEvent) => this.#onUnitDeselection(e.detail)); document.addEventListener('keydown', (event) => this.#onKeyDown(event)); } @@ -56,15 +57,6 @@ export class UnitsManager { Object.keys(data.units) .filter((ID: string) => ID in this.#units) .forEach((ID: string) => this.#units[parseInt(ID)].setData(data.units[ID])); - - /* Update the unit info panel */ - if (this.getSelectedUnits().length == 1) { - getUnitInfoPanel()?.show(); - getUnitInfoPanel()?.update(this.getSelectedUnits()[0]); - } - else { - getUnitInfoPanel()?.hide(); - } } forceUpdate() { @@ -80,25 +72,6 @@ export class UnitsManager { this.#units[ID]?.setSelected(true); } - onUnitSelection(unit: Unit) { - if (this.getSelectedUnits().length > 0) { - getMap().setState(MOVE_UNIT); - /* 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) - { - setTimeout(() => { - document.dispatchEvent(new CustomEvent("unitsSelection", {detail: this.getSelectedUnits()})); - this.#selectionEventDisabled = false; - }, 300); - this.#selectionEventDisabled = true; - } - } - else { - getMap().setState(IDLE); - document.dispatchEvent(new CustomEvent("clearSelection")); - } - } - selectFromBounds(bounds: LatLngBounds) { this.deselectAllUnits(); @@ -359,4 +332,32 @@ export class UnitsManager { this.selectedUnitsDelete(); } } + + #onUnitSelection(unit: Unit) { + if (this.getSelectedUnits().length > 0) { + getMap().setState(MOVE_UNIT); + /* 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) + { + setTimeout(() => { + document.dispatchEvent(new CustomEvent("unitsSelection", {detail: this.getSelectedUnits()})); + this.#selectionEventDisabled = false; + }, 300); + this.#selectionEventDisabled = true; + } + } + else { + getMap().setState(IDLE); + document.dispatchEvent(new CustomEvent("clearSelection")); + } + } + + #onUnitDeselection(unit: Unit) { + if (this.getSelectedUnits().length == 0) { + getMap().setState(IDLE); + document.dispatchEvent(new CustomEvent("clearSelection")); + } + else + document.dispatchEvent(new CustomEvent("unitsDeselection", {detail: this.getSelectedUnits()})); + } } \ No newline at end of file diff --git a/client/views/index.ejs b/client/views/index.ejs index c4b7d71a..d68e004f 100644 --- a/client/views/index.ejs +++ b/client/views/index.ejs @@ -27,7 +27,6 @@ <%- include('contextmenu.ejs') %> <%- include('unitcontrolpanel.ejs') %> - <%- include('unitinfopanel.ejs') %> <%- include('mouseinfopanel.ejs') %> <%- include('navbar.ejs') %> <%- include('connectionstatuspanel.ejs') %> diff --git a/client/views/mouseinfopanel.ejs b/client/views/mouseinfopanel.ejs index 3b029240..32f2d8ae 100644 --- a/client/views/mouseinfopanel.ejs +++ b/client/views/mouseinfopanel.ejs @@ -1,6 +1,6 @@
-
---° / --- NM
-
---° / --- NM
+
---° / --- NM
+
---° / --- NM
---° / --- NM
---° / --- NM
\ No newline at end of file diff --git a/client/views/unitcontrolpanel.ejs b/client/views/unitcontrolpanel.ejs index 36fd7324..00230b50 100644 --- a/client/views/unitcontrolpanel.ejs +++ b/client/views/unitcontrolpanel.ejs @@ -1,9 +1,36 @@ -
+

Selected units

+
+
+

Olympus 1-1

+
Name
+
Group
+
Task
+
+
+

Flight data

+
+
+
+
Ground Speed

12

+
Altitude

+
Heading

+
+
+
+

Loadout

+
+
Fuel

+
+
+
+
+
+

Controls

diff --git a/client/views/unitinfopanel.ejs b/client/views/unitinfopanel.ejs deleted file mode 100644 index 0fa4849e..00000000 --- a/client/views/unitinfopanel.ejs +++ /dev/null @@ -1,28 +0,0 @@ -
-
-
-

Olympus 1-1

-
Name
-
Group
-
Task
-
-
-

Flight data

-
-
-
-
Ground Speed

12

-
Altitude

-
Heading

-
-
-
-

Loadout

-
-
Fuel

-
-
-
-
-
-
\ No newline at end of file