More work on units spawn menu and started to add documentation

This commit is contained in:
Pax1601
2023-09-01 16:13:15 +02:00
parent fab7d26191
commit 695adc8acb
255 changed files with 105653 additions and 483 deletions

View File

@@ -0,0 +1,174 @@
import { getMap, getMissionHandler, getUnitsManager, setActiveCoalition } from "..";
import { GAME_MASTER } from "../constants/constants";
import { Airbase } from "../mission/airbase";
import { dataPointMap } from "../other/utils";
import { ContextMenu } from "./contextmenu";
/** This context menu is shown to the user when the airbase marker is right clicked on the map.
* It allows the user to inspect information about the airbase, as well as allowing to spawn units from the airbase itself and land units on it. */
export class AirbaseContextMenu extends ContextMenu {
#airbase: Airbase | null = null;
/**
*
* @param ID - the ID of the HTML element which will contain the context menu
*/
constructor(ID: string){
super(ID);
document.addEventListener("contextMenuSpawnAirbase", (e: any) => {
this.#showSpawnMenu();
})
document.addEventListener("contextMenuLandAirbase", (e: any) => {
if (this.#airbase)
getUnitsManager().selectedUnitsLandAt(this.#airbase.getLatLng());
this.hide();
})
}
/** Sets the airbase for which data will be shown in the context menu
*
* @param airbase The airbase for which data will be shown in the context menu. Note: the airbase must be present in the public/databases/airbases/<theatre>.json database.
*/
setAirbase(airbase: Airbase) {
this.#airbase = airbase;
this.#setName(this.#airbase.getName());
this.#setProperties(this.#airbase.getProperties());
this.#setParkings(this.#airbase.getParkings());
this.#setCoalition(this.#airbase.getCoalition());
this.#showLandButton(getUnitsManager().getSelectedUnitsTypes().length == 1 && ["Aircraft", "Helicopter"].includes(getUnitsManager().getSelectedUnitsTypes()[0]) && (getUnitsManager().getSelectedUnitsCoalition() === this.#airbase.getCoalition() || this.#airbase.getCoalition() === "neutral"))
this.#showSpawnButton(getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER || this.#airbase.getCoalition() == getMissionHandler().getCommandedCoalition());
this.#setAirbaseData();
this.clip();
}
/**
*
* @param airbaseName The name of the airbase
*/
#setName(airbaseName: string) {
var nameDiv = <HTMLElement>this.getContainer()?.querySelector("#airbase-name");
if (nameDiv != null)
nameDiv.innerText = airbaseName;
}
/**
*
* @param airbaseProperties The properties of the airbase
*/
#setProperties(airbaseProperties: string[]) {
this.getContainer()?.querySelector("#airbase-properties")?.replaceChildren(...airbaseProperties.map((property: string) => {
var div = document.createElement("div");
div.innerText = property;
return div;
}),);
}
/**
*
* @param airbaseParkings List of available parkings at the airbase
*/
#setParkings(airbaseParkings: string[]) {
this.getContainer()?.querySelector("#airbase-parking")?.replaceChildren(...airbaseParkings.map((parking: string) => {
var div = document.createElement("div");
div.innerText = parking;
return div;
}));
}
/**
*
* @param coalition Coalition to which the airbase belongs
*/
#setCoalition(coalition: string) {
(this.getContainer()?.querySelector("#spawn-airbase-aircraft-button") as HTMLElement).dataset.coalition = coalition;
}
/**
*
* @param showSpawnButton If true, the spawn button will be visibile
*/
#showSpawnButton(showSpawnButton: boolean) {
this.getContainer()?.querySelector("#spawn-airbase-aircraft-button")?.classList.toggle("hide", !showSpawnButton);
}
/**
*
* @param showLandButton If true, the land button will be visible
*/
#showLandButton(showLandButton: boolean) {
this.getContainer()?.querySelector("#land-here-button")?.classList.toggle("hide", !showLandButton);
}
/** Shows the spawn context menu which allows the user to select a unit to ground spawn at the airbase
*
*/
#showSpawnMenu() {
if (this.#airbase != null) {
setActiveCoalition(this.#airbase.getCoalition());
getMap().showAirbaseSpawnMenu(this.getX(), this.getY(), this.getLatLng(), this.#airbase);
}
}
/** @todo needs commenting
*
*/
#setAirbaseData() {
if (this.#airbase && this.getContainer()) {
dataPointMap(this.getContainer() as HTMLElement, {
"coalition": this.#airbase.getCoalition(),
"airbaseName": this.#airbase.getName()
});
dataPointMap( this.getContainer() as HTMLElement, this.#airbase.getChartData() );
const runwaysContainer = this.getContainer()?.querySelector( "#airbase-runways" ) as HTMLElement;
runwaysContainer.innerHTML = "";
if ( runwaysContainer instanceof HTMLElement ) {
const runways = this.#airbase.getChartData().runways;
if ( runways.length === 0 ) {
runwaysContainer.innerText = "No data";
} else {
runways.forEach( runway => {
let runwayDiv = document.createElement( "div" );
runwayDiv.classList.add( "runway" );
runway.headings.forEach( headings => {
for ( const [ heading, data ] of Object.entries( headings ) ) {
let headingDiv = document.createElement( "div" );
headingDiv.classList.add( "heading" );
let abbr = document.createElement( "abbr" );
abbr.title = `Mag heading: ${data.magHeading}`;
abbr.innerText = heading;
headingDiv.appendChild( abbr );
runwayDiv.appendChild( headingDiv );
if ( data.ILS ) {
let ilsDiv = document.createElement( "div" );
ilsDiv.classList.add( "ils" );
abbr = document.createElement( "abbr" );
abbr.title = data.ILS;
abbr.innerText = "ILS";
ilsDiv.appendChild( abbr );
headingDiv.appendChild( ilsDiv );
}
}
});
runwaysContainer.appendChild( runwayDiv );
});
}
}
}
}
}

View File

@@ -0,0 +1,102 @@
import { LatLng } from "leaflet";
import { getActiveCoalition } from "..";
import { ContextMenu } from "./contextmenu";
import { AircraftSpawnMenu, HelicopterSpawnMenu } from "../controls/unitspawnmenu";
import { Airbase } from "../mission/airbase";
/** This context menu is shown when the user wants to spawn a new aircraft or helicopter from the ground at an airbase.
* It is shown by clicking on the "spawn" button of a AirbaseContextMenu. */
export class AirbaseSpawnContextMenu extends ContextMenu {
#aircraftSpawnMenu: AircraftSpawnMenu;
#helicopterSpawnMenu: HelicopterSpawnMenu;
/**
*
* @param ID - the ID of the HTML element which will contain the context menu
*/
constructor(ID: string){
super(ID);
/* Create the spawn menus for the different unit types */
this.#aircraftSpawnMenu = new AircraftSpawnMenu("airbase-aircraft-spawn-menu");
this.#helicopterSpawnMenu = new HelicopterSpawnMenu("airbase-helicopter-spawn-menu");
this.#aircraftSpawnMenu.getAltitudeSlider().hide();
this.#helicopterSpawnMenu.getAltitudeSlider().hide();
/* Event listeners */
document.addEventListener("mapContextMenuShow", (e: any) => {
if (this.getVisibleSubMenu() !== e.detail.type)
this.#showSubMenu(e.detail.type);
else
this.#hideSubMenus();
});
this.#aircraftSpawnMenu.getContainer().addEventListener("resize", () => this.clip());
this.#helicopterSpawnMenu.getContainer().addEventListener("resize", () => this.clip());
this.hide();
}
/** Show the context menu
*
* @param x X screen coordinate of the top left corner of the context menu
* @param y Y screen coordinate of the top left corner of the context menu
*/
show(x: number, y: number) {
super.show(x, y, new LatLng(0, 0));
this.#aircraftSpawnMenu.setAirbase(undefined);
this.#helicopterSpawnMenu.setAirbase(undefined);
this.#aircraftSpawnMenu.setCountries();
this.#helicopterSpawnMenu.setCountries();
this.getContainer()?.querySelectorAll('[data-coalition]').forEach((element: any) => { element.setAttribute("data-coalition", getActiveCoalition()) });
}
/** Sets the airbase at which the new unit will be spawned
*
* @param airbase The airbase at which the new unit will be spawned. Note: if the airbase has no suitable parking spots, the airplane may be spawned on the runway, or spawning may fail.
*/
setAirbase(airbase: Airbase) {
this.#aircraftSpawnMenu.setAirbase(airbase);
this.#helicopterSpawnMenu.setAirbase(airbase);
}
/** Shows the submenu depending on unit selection
*
* @param type Submenu type, either "aircraft" or "helicopter"
*/
#showSubMenu(type: string) {
this.getContainer()?.querySelector("#airbase-aircraft-spawn-menu")?.classList.toggle("hide", type !== "aircraft");
this.getContainer()?.querySelector("#airbase-aircraft-spawn-button")?.classList.toggle("is-open", type === "aircraft");
this.getContainer()?.querySelector("#airbase-helicopter-spawn-menu")?.classList.toggle("hide", type !== "helicopter");
this.getContainer()?.querySelector("#airbase-helicopter-spawn-button")?.classList.toggle("is-open", type === "helicopter");
(this.getContainer()?.querySelectorAll(".deploy-unit-button"))?.forEach((element: Node) => { (element as HTMLButtonElement).disabled = true; })
this.#aircraftSpawnMenu.reset();
this.#aircraftSpawnMenu.setCountries();
this.#helicopterSpawnMenu.reset();
this.#helicopterSpawnMenu.setCountries();
this.setVisibleSubMenu(type);
this.clip();
}
/** Hide all the open submenus
*
*/
#hideSubMenus() {
this.getContainer()?.querySelector("#airbase-aircraft-spawn-menu")?.classList.toggle("hide", true);
this.getContainer()?.querySelector("#airbase-aircraft-spawn-button")?.classList.toggle("is-open", false);
this.getContainer()?.querySelector("#airbase-helicopter-spawn-menu")?.classList.toggle("hide", true);
this.getContainer()?.querySelector("#airbase-helicopter-spawn-button")?.classList.toggle("is-open", false);
this.#aircraftSpawnMenu.reset();
this.#helicopterSpawnMenu.reset();
this.setVisibleSubMenu(null);
this.clip();
}
}

View File

@@ -0,0 +1,159 @@
import { LatLng } from "leaflet";
import { getMap, getMissionHandler, getUnitsManager } from "..";
import { GAME_MASTER, IADSTypes } from "../constants/constants";
import { CoalitionArea } from "../map/coalitionarea";
import { ContextMenu } from "./contextmenu";
import { Dropdown } from "../controls/dropdown";
import { Slider } from "../controls/slider";
import { Switch } from "../controls/switch";
import { groundUnitDatabase } from "../unit/groundunitdatabase";
import { createCheckboxOption, getCheckboxOptions } from "../other/utils";
/** This context menu allows the user to edit or delete a CoalitionArea. Moreover, it allows the user to create a IADS automatically using the CoalitionArea as bounds. */
export class CoalitionAreaContextMenu extends ContextMenu {
#coalitionSwitch: Switch;
#coalitionArea: CoalitionArea | null = null;
#iadsDensitySlider: Slider;
#iadsDistributionSlider: Slider;
#iadsTypesDropdown: Dropdown;
#iadsErasDropdown: Dropdown;
#iadsRangesDropdown: Dropdown;
/**
*
* @param ID - the ID of the HTML element which will contain the context menu
*/
constructor(ID: string){
super(ID);
/* Create the coalition switch */
this.#coalitionSwitch = new Switch("coalition-area-switch", (value: boolean) => this.#onSwitchClick(value));
this.#coalitionSwitch.setValue(false);
/* Create the controls of the IADS creation submenu */
this.#iadsTypesDropdown = new Dropdown("iads-units-type-options", () => { });
this.#iadsErasDropdown = new Dropdown("iads-era-options", () => {});
this.#iadsRangesDropdown = new Dropdown("iads-range-options", () => {});
this.#iadsDensitySlider = new Slider("iads-density-slider", 5, 100, "%", (value: number) => { });
this.#iadsDistributionSlider = new Slider("iads-distribution-slider", 5, 100, "%", (value: number) => { });
/* Set the default parameters of the sliders */
this.#iadsDensitySlider.setIncrement(5);
this.#iadsDensitySlider.setValue(50);
this.#iadsDensitySlider.setActive(true);
this.#iadsDistributionSlider.setIncrement(5);
this.#iadsDistributionSlider.setValue(50);
this.#iadsDistributionSlider.setActive(true);
document.addEventListener("coalitionAreaContextMenuShow", (e: any) => {
if (this.getVisibleSubMenu() !== e.detail.type)
this.#showSubMenu(e.detail.type);
else
this.#hideSubMenus();
});
document.addEventListener("coalitionAreaBringToBack", (e: any) => {
if (this.#coalitionArea)
getMap().bringCoalitionAreaToBack(this.#coalitionArea);
getMap().hideCoalitionAreaContextMenu();
});
document.addEventListener("coalitionAreaDelete", (e: any) => {
if (this.#coalitionArea)
getMap().deleteCoalitionArea(this.#coalitionArea);
getMap().hideCoalitionAreaContextMenu();
});
document.addEventListener("contextMenuCreateIads", (e: any) => {
const area = this.getCoalitionArea();
if (area)
getUnitsManager().createIADS(area, getCheckboxOptions(this.#iadsTypesDropdown), getCheckboxOptions(this.#iadsErasDropdown), getCheckboxOptions(this.#iadsRangesDropdown), this.#iadsDensitySlider.getValue(), this.#iadsDistributionSlider.getValue());
})
this.hide();
}
/**
*
* @param x X screen coordinate of the top left corner of the context menu
* @param y Y screen coordinate of the top left corner of the context menu
* @param latlng Leaflet latlng object of the mouse click
*/
show(x: number, y: number, latlng: LatLng) {
super.show(x, y, latlng);
/* Create the checkboxes to select the unit roles */
this.#iadsTypesDropdown.setOptionsElements(IADSTypes.map((role: string) => {
return createCheckboxOption(role, `Add ${role}s to the IADS` );
}));
/* Create the checkboxes to select the unit periods */
this.#iadsErasDropdown.setOptionsElements(groundUnitDatabase.getEras().map((era: string) => {
return createCheckboxOption(era, `Add ${era} era units to the IADS`);
}));
/* Create the checkboxes to select the unit ranges */
this.#iadsRangesDropdown.setOptionsElements(groundUnitDatabase.getRanges().map((range: string) => {
return createCheckboxOption(range, `Add ${range} units to the IADS`);
}));
if (getMissionHandler().getCommandModeOptions().commandMode !== GAME_MASTER)
this.#coalitionSwitch.hide()
}
/** Set the CoalitionArea object the user will be able to edit using this menu
*
* @param coalitionArea The CoalitionArea object to edit
*/
setCoalitionArea(coalitionArea: CoalitionArea) {
this.#coalitionArea = coalitionArea;
this.getContainer()?.querySelectorAll('[data-coalition]').forEach((element: any) => {
element.setAttribute("data-coalition", this.getCoalitionArea()?.getCoalition())
});
this.#coalitionSwitch.setValue(this.getCoalitionArea()?.getCoalition() === "red");
}
/** Get the CoalitionArea object the contextmenu is editing
*
* @returns The CoalitionArea the contextmenu is editing
*/
getCoalitionArea() {
return this.#coalitionArea;
}
/** Show a submenu of the contextmenu
*
* @param type The submenu type, currently only "iads"
*/
#showSubMenu(type: string) {
this.getContainer()?.querySelector("#iads-menu")?.classList.toggle("hide", type !== "iads");
this.getContainer()?.querySelector("#iads-button")?.classList.toggle("is-open", type === "iads");
this.clip();
this.setVisibleSubMenu(type);
}
/** Hide all submenus
*
*/
#hideSubMenus() {
this.getContainer()?.querySelector("#iads-menu")?.classList.toggle("hide", true);
this.getContainer()?.querySelector("#iads-button")?.classList.toggle("is-open", false);
this.clip();
this.setVisibleSubMenu(null);
}
/** Callback event called when the coalition switch is clicked to change the coalition of the CoalitionArea
*
* @param value Switch position (false: blue, true: red)
*/
#onSwitchClick(value: boolean) {
if (getMissionHandler().getCommandModeOptions().commandMode == GAME_MASTER) {
this.getCoalitionArea()?.setCoalition(value ? "red" : "blue");
this.getContainer()?.querySelectorAll('[data-coalition]').forEach((element: any) => {
element.setAttribute("data-coalition", this.getCoalitionArea()?.getCoalition())
});
}
}
}

View File

@@ -0,0 +1,105 @@
import { LatLng } from "leaflet";
/** Base class for map contextmenus. By default it is empty and requires to be extended. */
export class ContextMenu {
#container: HTMLElement | null;
#latlng: LatLng = new LatLng(0, 0);
#x: number = 0;
#y: number = 0;
#visibleSubMenu: string | null = null;
/**
*
* @param ID - the ID of the HTML element which will contain the context menu
*/
constructor(ID: string){
this.#container = document.getElementById(ID);
this.hide();
}
/** Show the contextmenu on top of the map, usually at the location where the user has clicked on it.
*
* @param x X screen coordinate of the top left corner of the context menu
* @param y Y screen coordinate of the top left corner of the context menu
* @param latlng Leaflet latlng object of the mouse click
*/
show(x: number, y: number, latlng: LatLng) {
this.#latlng = latlng;
this.#container?.classList.toggle("hide", false);
this.#x = x;
this.#y = y;
this.clip();
}
/** Hide the contextmenu
*
*/
hide() {
this.#container?.classList.toggle("hide", true);
}
/**
*
* @returns The HTMLElement that contains the contextmenu
*/
getContainer() {
return this.#container;
}
/**
*
* @returns The Leaflet latlng object associated to the click that caused the contextmenu to be shown
*/
getLatLng() {
return this.#latlng;
}
/**
*
* @returns The x coordinate of the top left corner of the menu
*/
getX() {
return this.#x;
}
/**
*
* @returns The y coordinate of the top left corner of the menu
*/
getY() {
return this.#y;
}
/** Clips the contextmenu, meaning it moves it on the screen to make sure it does not overflow the window.
*
*/
clip() {
if (this.#container != null) {
if (this.#x + this.#container.offsetWidth < window.innerWidth)
this.#container.style.left = this.#x + "px";
else
this.#container.style.left = window.innerWidth - this.#container.offsetWidth - 10 + "px";
if (this.#y + this.#container.offsetHeight < window.innerHeight)
this.#container.style.top = this.#y + "px";
else
this.#container.style.top = window.innerHeight - this.#container.offsetHeight - 10 + "px";
}
}
/** Sets the currently visible submenu
*
* @param menu The name of the currently visibile submenu, or null if no submenu is visible
*/
setVisibleSubMenu(menu: string | null) {
this.#visibleSubMenu = menu;
}
/**
*
* @returns The name of the currently visible submenu
*/
getVisibleSubMenu() {
return this.#visibleSubMenu;
}
}

View File

@@ -0,0 +1,215 @@
import { LatLng } from "leaflet";
import { getActiveCoalition, getMap, getMissionHandler, setActiveCoalition } from "..";
import { spawnExplosion, spawnSmoke } from "../server/server";
import { ContextMenu } from "./contextmenu";
import { Switch } from "../controls/switch";
import { GAME_MASTER } from "../constants/constants";
import { CoalitionArea } from "../map/coalitionarea";
import { AircraftSpawnMenu, GroundUnitSpawnMenu, HelicopterSpawnMenu, NavyUnitSpawnMenu } from "../controls/unitspawnmenu";
import { Airbase } from "../mission/airbase";
/** The MapContextMenu is the main contextmenu shown to the user whenever it rightclicks on the map. It is the primary interaction method for the user.
* It allows to spawn units, create explosions and smoke, and edit CoalitionAreas.
*/
export class MapContextMenu extends ContextMenu {
#coalitionSwitch: Switch;
#aircraftSpawnMenu: AircraftSpawnMenu;
#helicopterSpawnMenu: HelicopterSpawnMenu;
#groundUnitSpawnMenu: GroundUnitSpawnMenu;
#navyUnitSpawnMenu: NavyUnitSpawnMenu;
#coalitionArea: CoalitionArea | null = null;
/**
*
* @param ID - the ID of the HTML element which will contain the context menu
*/
constructor(ID: string){
super(ID);
/* Create the coalition switch */
this.#coalitionSwitch = new Switch("coalition-switch", (value: boolean) => this.#onSwitchClick(value));
this.#coalitionSwitch.setValue(false);
this.#coalitionSwitch.getContainer()?.addEventListener("contextmenu", (e) => this.#onSwitchRightClick());
/* Create the spawn menus for the different unit types */
this.#aircraftSpawnMenu = new AircraftSpawnMenu("aircraft-spawn-menu");
this.#helicopterSpawnMenu = new HelicopterSpawnMenu("helicopter-spawn-menu");
this.#groundUnitSpawnMenu = new GroundUnitSpawnMenu("groundunit-spawn-menu");
this.#navyUnitSpawnMenu = new NavyUnitSpawnMenu("navyunit-spawn-menu");
/* Event listeners */
document.addEventListener("mapContextMenuShow", (e: any) => {
if (this.getVisibleSubMenu() !== e.detail.type)
this.#showSubMenu(e.detail.type);
else
this.#hideSubMenus(e.detail.type);
});
document.addEventListener("contextMenuDeploySmoke", (e: any) => {
this.hide();
spawnSmoke(e.detail.color, this.getLatLng());
});
document.addEventListener("contextMenuExplosion", (e: any) => {
this.hide();
spawnExplosion(e.detail.strength, this.getLatLng());
});
document.addEventListener("editCoalitionArea", (e: any) => {
this.hide();
if (this.#coalitionArea) {
getMap().deselectAllCoalitionAreas();
this.#coalitionArea.setSelected(true);
}
});
document.addEventListener("commandModeOptionsChanged", (e: any) => {
//this.#refreshOptions();
});
this.#aircraftSpawnMenu.getContainer().addEventListener("resize", () => this.clip());
this.#helicopterSpawnMenu.getContainer().addEventListener("resize", () => this.clip());
this.#groundUnitSpawnMenu.getContainer().addEventListener("resize", () => this.clip());
this.#navyUnitSpawnMenu.getContainer().addEventListener("resize", () => this.clip());
this.hide();
}
/** Show the contextmenu on top of the map, usually at the location where the user has clicked on it.
*
* @param x X screen coordinate of the top left corner of the context menu
* @param y Y screen coordinate of the top left corner of the context menu
* @param latlng Leaflet latlng object of the mouse click
*/
show(x: number, y: number, latlng: LatLng) {
super.show(x, y, latlng);
this.#aircraftSpawnMenu.setLatLng(latlng);
this.#helicopterSpawnMenu.setLatLng(latlng);
this.#groundUnitSpawnMenu.setLatLng(latlng);
this.#navyUnitSpawnMenu.setLatLng(latlng);
this.#aircraftSpawnMenu.setCountries();
this.#helicopterSpawnMenu.setCountries();
this.#groundUnitSpawnMenu.setCountries();
this.#navyUnitSpawnMenu.setCountries();
/* Only a Game Master can choose the coalition of a new unit */
if (getMissionHandler().getCommandModeOptions().commandMode !== GAME_MASTER) {
this.#coalitionSwitch.hide()
} else {
this.getContainer()?.querySelectorAll('[data-coalition]').forEach((element: any) => { element.setAttribute("data-coalition", getActiveCoalition()) });
if (getActiveCoalition() == "blue")
this.#coalitionSwitch.setValue(false);
else if (getActiveCoalition() == "red")
this.#coalitionSwitch.setValue(true);
else
this.#coalitionSwitch.setValue(undefined);
}
/* Hide the coalition area button. It will be visible if a coalition area is set */
this.getContainer()?.querySelector("#coalition-area-button")?.classList.toggle("hide", true);
}
/** If the user rightclicked on a CoalitionArea, it will be given the ability to edit it.
*
* @param coalitionArea The CoalitionArea the user can edit
*/
setCoalitionArea(coalitionArea: CoalitionArea) {
this.#coalitionArea = coalitionArea;
this.getContainer()?.querySelector("#coalition-area-button")?.classList.toggle("hide", false);
}
/** Shows the submenu depending on unit selection
*
* @param type Submenu type, either "aircraft", "helicopter", "groundunit", "navyunit", "smoke", or "explosion"
*/
#showSubMenu(type: string) {
if (type === "more")
this.getContainer()?.querySelector("#more-options-button-bar")?.classList.toggle("hide");
else if (["aircraft", "helicopter", "groundunit"].includes(type))
this.getContainer()?.querySelector("#more-options-button-bar")?.classList.toggle("hide", true);
this.getContainer()?.querySelector("#aircraft-spawn-menu")?.classList.toggle("hide", type !== "aircraft");
this.getContainer()?.querySelector("#aircraft-spawn-button")?.classList.toggle("is-open", type === "aircraft");
this.getContainer()?.querySelector("#helicopter-spawn-menu")?.classList.toggle("hide", type !== "helicopter");
this.getContainer()?.querySelector("#helicopter-spawn-button")?.classList.toggle("is-open", type === "helicopter");
this.getContainer()?.querySelector("#groundunit-spawn-menu")?.classList.toggle("hide", type !== "groundunit");
this.getContainer()?.querySelector("#groundunit-spawn-button")?.classList.toggle("is-open", type === "groundunit");
this.getContainer()?.querySelector("#navyunit-spawn-menu")?.classList.toggle("hide", type !== "navyunit");
this.getContainer()?.querySelector("#navyunit-spawn-button")?.classList.toggle("is-open", type === "navyunit");
this.getContainer()?.querySelector("#smoke-spawn-menu")?.classList.toggle("hide", type !== "smoke");
this.getContainer()?.querySelector("#smoke-spawn-button")?.classList.toggle("is-open", type === "smoke");
this.getContainer()?.querySelector("#explosion-menu")?.classList.toggle("hide", type !== "explosion");
this.getContainer()?.querySelector("#explosion-spawn-button")?.classList.toggle("is-open", type === "explosion");
(this.getContainer()?.querySelectorAll(".deploy-unit-button"))?.forEach((element: Node) => { (element as HTMLButtonElement).disabled = true; })
this.#aircraftSpawnMenu.reset();
this.#aircraftSpawnMenu.setCountries();
this.#helicopterSpawnMenu.reset();
this.#helicopterSpawnMenu.setCountries();
this.#groundUnitSpawnMenu.reset();
this.#groundUnitSpawnMenu.setCountries();
this.#navyUnitSpawnMenu.reset();
this.#navyUnitSpawnMenu.setCountries();
this.setVisibleSubMenu(type);
this.clip();
}
/** Hide all the submenus
*
* @param type The type of the currenlt open submenu.
*/
#hideSubMenus(type: string) {
/* Close the lower options bar if the currently open submenu does not required it */
this.getContainer()?.querySelector("#more-options-button-bar")?.classList.toggle("hide", ["aircraft", "helicopter", "groundunit"].includes(type));
this.getContainer()?.querySelector("#aircraft-spawn-menu")?.classList.toggle("hide", true);
this.getContainer()?.querySelector("#aircraft-spawn-button")?.classList.toggle("is-open", false);
this.getContainer()?.querySelector("#helicopter-spawn-menu")?.classList.toggle("hide", true);
this.getContainer()?.querySelector("#helicopter-spawn-button")?.classList.toggle("is-open", false);
this.getContainer()?.querySelector("#groundunit-spawn-menu")?.classList.toggle("hide", true);
this.getContainer()?.querySelector("#groundunit-spawn-button")?.classList.toggle("is-open", false);
this.getContainer()?.querySelector("#navyunit-spawn-menu")?.classList.toggle("hide", true);
this.getContainer()?.querySelector("#navyunit-spawn-button")?.classList.toggle("is-open", false);
this.getContainer()?.querySelector("#smoke-spawn-menu")?.classList.toggle("hide", true);
this.getContainer()?.querySelector("#smoke-spawn-button")?.classList.toggle("is-open", false);
this.getContainer()?.querySelector("#explosion-menu")?.classList.toggle("hide", true);
this.getContainer()?.querySelector("#explosion-spawn-button")?.classList.toggle("is-open", false);
this.#aircraftSpawnMenu.reset();
this.#helicopterSpawnMenu.reset();
this.#groundUnitSpawnMenu.reset();
this.#navyUnitSpawnMenu.reset();
this.setVisibleSubMenu(null);
this.clip();
}
/** Callback called when the user left clicks on the coalition switch
*
* @param value Switch position (false: "blue", true: "red")
*/
#onSwitchClick(value: boolean) {
value ? setActiveCoalition("red") : setActiveCoalition("blue");
this.getContainer()?.querySelectorAll('[data-coalition]').forEach((element: any) => { element.setAttribute("data-coalition", getActiveCoalition()) });
this.#aircraftSpawnMenu.setCountries();
this.#helicopterSpawnMenu.setCountries();
this.#groundUnitSpawnMenu.setCountries();
this.#navyUnitSpawnMenu.setCountries();
}
/** Callback called when the user rightclicks on the coalition switch. This will select the "neutral" coalition.
*
*/
#onSwitchRightClick() {
this.#coalitionSwitch.setValue(undefined);
setActiveCoalition("neutral");
this.getContainer()?.querySelectorAll('[data-coalition]').forEach((element: any) => { element.setAttribute("data-coalition", getActiveCoalition()) });
this.#aircraftSpawnMenu.setCountries();
this.#helicopterSpawnMenu.setCountries();
this.#groundUnitSpawnMenu.setCountries();
this.#navyUnitSpawnMenu.setCountries();
}
}

View File

@@ -0,0 +1,32 @@
import { deg2rad, ftToM } from "../other/utils";
import { ContextMenu } from "./contextmenu";
/** The UnitContextMenu is shown when the user rightclicks on a unit. It dynamically presents the user with possible actions to perform on the unit. */
export class UnitContextMenu extends ContextMenu {
/**
*
* @param ID - the ID of the HTML element which will contain the context menu
*/
constructor(ID: string){
super(ID);
}
/** Set the options that will be presented to the user in the contextmenu
*
* @param options Dictionary element containing the text and tooltip of the options shown in the menu
* @param callback Callback that will be called when the user clicks on one of the options
*/
setOptions(options: { [key: string]: {text: string, tooltip: string }}, callback: CallableFunction) {
this.getContainer()?.replaceChildren(...Object.keys(options).map((key: string, idx: number) => {
const option = options[key];
var button = document.createElement("button");
var el = document.createElement("div");
el.title = option.tooltip;
el.innerText = option.text;
el.id = key;
button.addEventListener("click", () => callback(key));
button.appendChild(el);
return (button);
}));
}
}