mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Started event handling
This commit is contained in:
@@ -1,102 +0,0 @@
|
|||||||
.ol-selection-wheel {
|
|
||||||
margin: 0;
|
|
||||||
position: fixed;
|
|
||||||
z-index: 1000;
|
|
||||||
width: 220px;
|
|
||||||
height: 220px;
|
|
||||||
overflow: visible;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ol-wheel {
|
|
||||||
width: 100%;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: var(--background-color-dark);
|
|
||||||
-webkit-mask: radial-gradient(transparent 30%, #000 31%);
|
|
||||||
mask: radial-gradient(transparent 30%, #000 31%);
|
|
||||||
transition: background-color 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ol-wheel:before {
|
|
||||||
content: "";
|
|
||||||
display: block;
|
|
||||||
padding-top: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.selection-wheel-button {
|
|
||||||
position: fixed;
|
|
||||||
z-index: 1000;
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
opacity: 0;
|
|
||||||
/*transition: opacity var(--animation_duration), left var(--animation_duration), top var(--animation_duration);*/
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.selection-wheel-image {
|
|
||||||
width: 45px;
|
|
||||||
height: 45px;
|
|
||||||
/*filter: invert(100%);*/
|
|
||||||
transition: width var(--animation_duration), height var(--animation_duration);
|
|
||||||
filter: invert(100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.selection-wheel-button:hover {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.selection-wheel-button:hover .selection-wheel-image {
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
/*filter: invert(21%) sepia(23%) saturate(775%) hue-rotate(170deg) brightness(92%) contrast(90%);*/
|
|
||||||
}
|
|
||||||
|
|
||||||
.ol-selection-wheel label {
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ol-selection-wheel input {
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ol-selection-wheel-switch {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
display: inline-block;
|
|
||||||
width: 60px;
|
|
||||||
height: 34px;
|
|
||||||
background-color: var(--active-coalition-color);
|
|
||||||
border-radius: 17px;
|
|
||||||
margin-left: -30px;
|
|
||||||
margin-top: -17px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ol-selection-wheel-switch:before {
|
|
||||||
position: absolute;
|
|
||||||
content: "";
|
|
||||||
height: 26px;
|
|
||||||
width: 26px;
|
|
||||||
left: 4px;
|
|
||||||
bottom: 4px;
|
|
||||||
background-color: white;
|
|
||||||
-webkit-transition: 0.2s;
|
|
||||||
transition: 0.2s;
|
|
||||||
border-radius: 50%;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
input:checked+.ol-selection-wheel-switch:before {
|
|
||||||
-webkit-transform: translateX(26px);
|
|
||||||
-ms-transform: translateX(26px);
|
|
||||||
transform: translateX(26px);
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
@import url("dropdown.css");
|
@import url("dropdown.css");
|
||||||
|
|
||||||
@import url("selectionwheel.css");
|
@import url("selectionwheel.css");
|
||||||
@import url("selectionscroll.css");
|
@import url("contextmenu.css");
|
||||||
|
|
||||||
@import url("unitmarker.css");
|
@import url("unitmarker.css");
|
||||||
@import url("airbasemarker.css");
|
@import url("airbasemarker.css");
|
||||||
|
|||||||
29
client/src/@types/dom.d.ts
vendored
Normal file
29
client/src/@types/dom.d.ts
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
interface CustomEventMap {
|
||||||
|
"unitSelection": CustomEvent<Unit>,
|
||||||
|
"unitsSelection": CustomEvent<Unit[]>,
|
||||||
|
"clearSelection": CustomEvent<>,
|
||||||
|
"unitCreation": CustomEvent<Unit>,
|
||||||
|
"unitDeletion": CustomEvent<Unit>,
|
||||||
|
"unitUpdated": CustomEvent<Unit>,
|
||||||
|
"unitMoveCommand": CustomEvent<Unit>,
|
||||||
|
"unitAttackCommand": CustomEvent<Unit>,
|
||||||
|
"unitLandCommand": CustomEvent<Unit>,
|
||||||
|
"unitSetAltitudeCommand": CustomEvent<Unit>,
|
||||||
|
"unitSetSpeedCommand": CustomEvent<Unit>,
|
||||||
|
"unitSetROECommand": CustomEvent<Unit>,
|
||||||
|
"unitSetReactionToThreatCommand": CustomEvent<Unit>,
|
||||||
|
"groupCreation": CustomEvent<Unit[]>,
|
||||||
|
"groupDeletion": CustomEvent<Unit[]>,
|
||||||
|
"mapStateChanged": CustomEvent<string>,
|
||||||
|
"mapContextMenu": CustomEvent<>
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Document {
|
||||||
|
addEventListener<K extends keyof CustomEventMap>(type: K,
|
||||||
|
listener: (this: Document, ev: CustomEventMap[K]) => void): void;
|
||||||
|
dispatchEvent<K extends keyof CustomEventMap>(ev: CustomEventMap[K]): void;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { };
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { LatLng } from "leaflet";
|
import { LatLng } from "leaflet";
|
||||||
import { getActiveCoalition, setActiveCoalition } from "..";
|
import { getActiveCoalition, setActiveCoalition } from "..";
|
||||||
|
|
||||||
export class SelectionScroll {
|
export class ContextMenu {
|
||||||
#container: HTMLElement | null;
|
#container: HTMLElement | null;
|
||||||
#display: string;
|
#display: string;
|
||||||
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
import { getActiveCoalition, setActiveCoalition } from "..";
|
|
||||||
import { deg2rad } from "../other/utils";
|
|
||||||
|
|
||||||
export class SelectionWheel {
|
|
||||||
#container: HTMLElement | null;
|
|
||||||
#display: string;
|
|
||||||
|
|
||||||
constructor(id: string) {
|
|
||||||
this.#container = document.getElementById(id);
|
|
||||||
this.#display = '';
|
|
||||||
if (this.#container != null) {
|
|
||||||
this.#container.querySelector("#coalition-switch")?.addEventListener('change', (e) => this.#onSwitch(e))
|
|
||||||
this.#display = this.#container.style.display;
|
|
||||||
this.hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
show(x: number, y: number, options: any, showCoalition: boolean) {
|
|
||||||
/* Hide to remove buttons, if present */
|
|
||||||
this.hide();
|
|
||||||
|
|
||||||
if (this.#container != null) {
|
|
||||||
this.#container.style.display = this.#display;
|
|
||||||
this.#container.style.left = x - 110 + "px";
|
|
||||||
this.#container.style.top = y - 110 + "px";
|
|
||||||
|
|
||||||
var angularSize = 360 / options.length;
|
|
||||||
var r = 80;
|
|
||||||
|
|
||||||
/* Create the buttons */
|
|
||||||
for (let id in options) {
|
|
||||||
var button = document.createElement("div");
|
|
||||||
button.classList.add("selection-wheel-button");
|
|
||||||
button.style.left = x - 25 + "px";
|
|
||||||
button.style.top = y - 25 + "px";
|
|
||||||
button.addEventListener('click', (e) => options[id].callback(e));
|
|
||||||
this.#container.appendChild(button);
|
|
||||||
var angle = parseInt(id) * angularSize;
|
|
||||||
button.style.opacity = "1";
|
|
||||||
button.style.left = x + r * Math.sin(deg2rad(angle)) - 25 + "px";
|
|
||||||
button.style.top = y - r * Math.cos(deg2rad(angle)) - 25 + "px";
|
|
||||||
|
|
||||||
var image = document.createElement("img");
|
|
||||||
image.classList.add("selection-wheel-image");
|
|
||||||
image.src = `images/buttons/${options[id].src}`
|
|
||||||
image.title = options[id].tooltip;
|
|
||||||
if ('tint' in options[id]) {
|
|
||||||
button.style.setProperty('background-color', options[id].tint);
|
|
||||||
image.style.opacity = "0";
|
|
||||||
}
|
|
||||||
button.appendChild(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hide the coalition switch if required */
|
|
||||||
var switchContainer = <HTMLElement>this.#container.querySelector("#coalition-switch-container");
|
|
||||||
if (showCoalition == false) {
|
|
||||||
switchContainer.style.display = "none";
|
|
||||||
document.documentElement.style.setProperty('--active-coalition-color', getComputedStyle(this.#container).getPropertyValue("--neutral-coalition-color"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
switchContainer.style.display = "block";
|
|
||||||
if (getActiveCoalition() == "blue")
|
|
||||||
document.documentElement.style.setProperty('--active-coalition-color', getComputedStyle(this.#container).getPropertyValue("--blue-coalition-color"));
|
|
||||||
else
|
|
||||||
document.documentElement.style.setProperty('--active-coalition-color', getComputedStyle(this.#container).getPropertyValue("--red-coalition-color"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hide() {
|
|
||||||
if (this.#container != null) {
|
|
||||||
this.#container.style.display = "none";
|
|
||||||
var buttons = this.#container.querySelectorAll(".selection-wheel-button");
|
|
||||||
for (let child of buttons) {
|
|
||||||
this.#container.removeChild(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#onSwitch(e: any) {
|
|
||||||
if (this.#container != null) {
|
|
||||||
if (e.currentTarget.checked) {
|
|
||||||
document.documentElement.style.setProperty('--active-coalition-color', getComputedStyle(this.#container).getPropertyValue("--red-coalition-color"));
|
|
||||||
setActiveCoalition("red");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
document.documentElement.style.setProperty('--active-coalition-color', getComputedStyle(this.#container).getPropertyValue("--blue-coalition-color"));
|
|
||||||
setActiveCoalition("blue");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
import { Map } from "./map/map"
|
import { Map } from "./map/map"
|
||||||
import { getDataFromDCS } from "./dcs/dcs"
|
import { getDataFromDCS } from "./dcs/dcs"
|
||||||
import { SelectionWheel } from "./controls/selectionwheel";
|
|
||||||
import { UnitsManager } from "./units/unitsmanager";
|
import { UnitsManager } from "./units/unitsmanager";
|
||||||
import { UnitInfoPanel } from "./panels/unitinfopanel";
|
import { UnitInfoPanel } from "./panels/unitinfopanel";
|
||||||
import { SelectionScroll } from "./controls/selectionscroll";
|
import { ContextMenu } from "./controls/contextmenu";
|
||||||
import { Dropdown } from "./controls/dropdown";
|
import { Dropdown } from "./controls/dropdown";
|
||||||
import { ConnectionStatusPanel } from "./panels/connectionstatuspanel";
|
import { ConnectionStatusPanel } from "./panels/connectionstatuspanel";
|
||||||
import { MissionData } from "./missiondata/missiondata";
|
import { MissionData } from "./missiondata/missiondata";
|
||||||
@@ -14,8 +13,7 @@ import { LogPanel } from "./panels/logpanel";
|
|||||||
|
|
||||||
/* TODO: should this be a class? */
|
/* TODO: should this be a class? */
|
||||||
var map: Map;
|
var map: Map;
|
||||||
var selectionWheel: SelectionWheel;
|
var contextMenu: ContextMenu;
|
||||||
var selectionScroll: SelectionScroll;
|
|
||||||
|
|
||||||
var unitsManager: UnitsManager;
|
var unitsManager: UnitsManager;
|
||||||
var missionData: MissionData;
|
var missionData: MissionData;
|
||||||
@@ -38,8 +36,7 @@ function setup() {
|
|||||||
unitsManager = new UnitsManager();
|
unitsManager = new UnitsManager();
|
||||||
missionData = new MissionData();
|
missionData = new MissionData();
|
||||||
|
|
||||||
selectionWheel = new SelectionWheel("selection-wheel");
|
contextMenu = new ContextMenu("selection-scroll");
|
||||||
selectionScroll = new SelectionScroll("selection-scroll");
|
|
||||||
|
|
||||||
unitInfoPanel = new UnitInfoPanel("unit-info-panel");
|
unitInfoPanel = new UnitInfoPanel("unit-info-panel");
|
||||||
unitControlPanel = new UnitControlPanel("unit-control-panel");
|
unitControlPanel = new UnitControlPanel("unit-control-panel");
|
||||||
@@ -78,12 +75,8 @@ export function getMissionData() {
|
|||||||
return missionData;
|
return missionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSelectionWheel() {
|
export function getContextMenu() {
|
||||||
return selectionWheel;
|
return contextMenu;
|
||||||
}
|
|
||||||
|
|
||||||
export function getSelectionScroll() {
|
|
||||||
return selectionScroll;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUnitsManager() {
|
export function getUnitsManager() {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import * as L from "leaflet"
|
import * as L from "leaflet"
|
||||||
import { getSelectionWheel, getSelectionScroll, getUnitsManager, getActiveCoalition, getMouseInfoPanel } from "..";
|
import { getContextMenu, getUnitsManager, getActiveCoalition, getMouseInfoPanel } from "..";
|
||||||
import { spawnAircraft, spawnGroundUnit, spawnSmoke } from "../dcs/dcs";
|
import { spawnAircraft, spawnGroundUnit, spawnSmoke } from "../dcs/dcs";
|
||||||
import { bearing, distance, zeroAppend } from "../other/utils";
|
import { bearing, distance, zeroAppend } from "../other/utils";
|
||||||
import { aircraftDatabase, getAircraftLabelsByRole, getLoadoutsByName, getLoadoutNamesByRole, getAircraftNameByLabel } from "../units/aircraftDatabase";
|
import { getAircraftLabelsByRole, getLoadoutsByName, getLoadoutNamesByRole, getAircraftNameByLabel } from "../units/aircraftDatabase";
|
||||||
import { unitTypes } from "../units/unitTypes";
|
import { unitTypes } from "../units/unitTypes";
|
||||||
import { BoxSelect } from "./boxselect";
|
import { BoxSelect } from "./boxselect";
|
||||||
|
|
||||||
@@ -14,14 +14,14 @@ export interface ClickEvent {
|
|||||||
latlng: L.LatLng;
|
latlng: L.LatLng;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SpawnEvent extends ClickEvent{
|
export interface SpawnEvent extends ClickEvent {
|
||||||
airbaseName: string | null;
|
airbaseName: string | null;
|
||||||
coalitionID: number | null;
|
coalitionID: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Map extends L.Map {
|
export class Map extends L.Map {
|
||||||
#state: string;
|
#state: string;
|
||||||
#layer?: L.TileLayer;
|
#layer: L.TileLayer | null = null;
|
||||||
#preventLeftClick: boolean = false;
|
#preventLeftClick: boolean = false;
|
||||||
#leftClickTimer: number = 0;
|
#leftClickTimer: number = 0;
|
||||||
#measurePoint: L.LatLng | null;
|
#measurePoint: L.LatLng | null;
|
||||||
@@ -113,39 +113,30 @@ export class Map extends L.Map {
|
|||||||
/* State machine */
|
/* State machine */
|
||||||
setState(state: string) {
|
setState(state: string) {
|
||||||
this.#state = state;
|
this.#state = state;
|
||||||
|
|
||||||
if (this.#state === "IDLE") {
|
if (this.#state === "IDLE") {
|
||||||
L.DomUtil.removeClass(this.getContainer(),'crosshair-cursor-enabled');
|
L.DomUtil.removeClass(this.getContainer(),'crosshair-cursor-enabled');
|
||||||
}
|
}
|
||||||
else if (this.#state === "MOVE_UNIT") {
|
else if (this.#state === "MOVE_UNIT") {
|
||||||
L.DomUtil.addClass(this.getContainer(),'crosshair-cursor-enabled');
|
L.DomUtil.addClass(this.getContainer(),'crosshair-cursor-enabled');
|
||||||
}
|
}
|
||||||
|
document.dispatchEvent(new CustomEvent("mapStateChanged"));
|
||||||
}
|
}
|
||||||
|
|
||||||
getState() {
|
getState() {
|
||||||
return this.#state;
|
return this.#state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Selection wheel */
|
|
||||||
showSelectionWheel(e: ClickEvent | SpawnEvent, options: any, showCoalition: boolean) {
|
|
||||||
var x = e.x;
|
|
||||||
var y = e.y;
|
|
||||||
getSelectionWheel().show(x, y, options, showCoalition);
|
|
||||||
}
|
|
||||||
|
|
||||||
hideSelectionWheel() {
|
|
||||||
getSelectionWheel().hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Selection scroll */
|
/* Selection scroll */
|
||||||
showSelectionScroll(e: ClickEvent | SpawnEvent, title: string, options: any, callback: CallableFunction, showCoalition: boolean = false) {
|
showContextMenu(e: ClickEvent | SpawnEvent, title: string, options: any, callback: CallableFunction, showCoalition: boolean = false) {
|
||||||
var x = e.x;
|
var x = e.x;
|
||||||
var y = e.y;
|
var y = e.y;
|
||||||
getSelectionScroll().show(x, y, title, options, callback, showCoalition);
|
getContextMenu().show(x, y, title, options, callback, showCoalition);
|
||||||
|
document.dispatchEvent(new CustomEvent("mapContextMenu"));
|
||||||
}
|
}
|
||||||
|
|
||||||
hideSelectionScroll() {
|
hideContextMenu() {
|
||||||
getSelectionScroll().hide();
|
getContextMenu().hide();
|
||||||
|
document.dispatchEvent(new CustomEvent("mapContextMenu"));
|
||||||
}
|
}
|
||||||
|
|
||||||
getMousePosition() {
|
getMousePosition() {
|
||||||
@@ -156,11 +147,16 @@ export class Map extends L.Map {
|
|||||||
return this.containerPointToLatLng(this.#lastMousePosition);
|
return this.containerPointToLatLng(this.#lastMousePosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Spawn from air base */
|
||||||
|
spawnFromAirbase(e: SpawnEvent)
|
||||||
|
{
|
||||||
|
this.#aircraftSpawnMenu(e);
|
||||||
|
}
|
||||||
|
|
||||||
/* Event handlers */
|
/* Event handlers */
|
||||||
#onClick(e: any) {
|
#onClick(e: any) {
|
||||||
if (!this.#preventLeftClick) {
|
if (!this.#preventLeftClick) {
|
||||||
this.hideSelectionWheel();
|
this.hideContextMenu();
|
||||||
this.hideSelectionScroll();
|
|
||||||
if (this.#state === "IDLE") {
|
if (this.#state === "IDLE") {
|
||||||
if (e.originalEvent.ctrlKey)
|
if (e.originalEvent.ctrlKey)
|
||||||
if (!this.#measurePoint)
|
if (!this.#measurePoint)
|
||||||
@@ -179,8 +175,7 @@ export class Map extends L.Map {
|
|||||||
else if (this.#state === "MOVE_UNIT") {
|
else if (this.#state === "MOVE_UNIT") {
|
||||||
this.setState("IDLE");
|
this.setState("IDLE");
|
||||||
getUnitsManager().deselectAllUnits();
|
getUnitsManager().deselectAllUnits();
|
||||||
this.hideSelectionWheel();
|
this.hideContextMenu();
|
||||||
this.hideSelectionScroll();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,8 +185,7 @@ export class Map extends L.Map {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#onContextMenu(e: any) {
|
#onContextMenu(e: any) {
|
||||||
this.hideSelectionWheel();
|
this.hideContextMenu();
|
||||||
this.hideSelectionScroll();
|
|
||||||
if (this.#state === "IDLE") {
|
if (this.#state === "IDLE") {
|
||||||
var spawnEvent: SpawnEvent = {x: e.originalEvent.x, y: e.originalEvent.y, latlng: e.latlng, airbaseName: null, coalitionID: null};
|
var spawnEvent: SpawnEvent = {x: e.originalEvent.x, y: e.originalEvent.y, latlng: e.latlng, airbaseName: null, coalitionID: null};
|
||||||
if (this.#state == "IDLE") {
|
if (this.#state == "IDLE") {
|
||||||
@@ -201,7 +195,7 @@ export class Map extends L.Map {
|
|||||||
{ "tooltip": "Smoke", "src": "spawnSmoke.png", "callback": () => this.#smokeSpawnMenu(spawnEvent) },
|
{ "tooltip": "Smoke", "src": "spawnSmoke.png", "callback": () => this.#smokeSpawnMenu(spawnEvent) },
|
||||||
//{ "tooltip": "Explosion", "src": "spawnExplosion.png", "callback": () => this.#explosionSpawnMenu(e) }
|
//{ "tooltip": "Explosion", "src": "spawnExplosion.png", "callback": () => this.#explosionSpawnMenu(e) }
|
||||||
]
|
]
|
||||||
this.showSelectionScroll(spawnEvent, "Action", options, () => {}, false);
|
this.showContextMenu(spawnEvent, "Action", options, () => {}, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (this.#state === "MOVE_UNIT") {
|
else if (this.#state === "MOVE_UNIT") {
|
||||||
@@ -265,12 +259,6 @@ export class Map extends L.Map {
|
|||||||
this.#hideMeasureLine();
|
this.#hideMeasureLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Spawn from air base */
|
|
||||||
spawnFromAirbase(e: SpawnEvent)
|
|
||||||
{
|
|
||||||
this.#aircraftSpawnMenu(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Spawning menus */
|
/* Spawning menus */
|
||||||
#aircraftSpawnMenu(e: SpawnEvent) {
|
#aircraftSpawnMenu(e: SpawnEvent) {
|
||||||
var options = [
|
var options = [
|
||||||
@@ -284,9 +272,9 @@ export class Map extends L.Map {
|
|||||||
{ 'coalition': true, 'tooltip': 'Transport', 'src': 'spawnTransport.png', 'callback': () => this.#selectAircraft(e, "transport") },
|
{ 'coalition': true, 'tooltip': 'Transport', 'src': 'spawnTransport.png', 'callback': () => this.#selectAircraft(e, "transport") },
|
||||||
]
|
]
|
||||||
if (e.airbaseName != null)
|
if (e.airbaseName != null)
|
||||||
this.showSelectionScroll(e, "Spawn at " + e.airbaseName, options, () => {}, true);
|
this.showContextMenu(e, "Spawn at " + e.airbaseName, options, () => {}, true);
|
||||||
else
|
else
|
||||||
this.showSelectionScroll(e, "Spawn air unit", options, () => {}, true);
|
this.showContextMenu(e, "Spawn air unit", options, () => {}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#groundUnitSpawnMenu(e: SpawnEvent) {
|
#groundUnitSpawnMenu(e: SpawnEvent) {
|
||||||
@@ -299,20 +287,19 @@ export class Map extends L.Map {
|
|||||||
{'coalition': true, 'tooltip': 'Radar', 'src': 'spawnRadar.png', 'callback': () => this.#selectGroundUnit(e, "Radar")},
|
{'coalition': true, 'tooltip': 'Radar', 'src': 'spawnRadar.png', 'callback': () => this.#selectGroundUnit(e, "Radar")},
|
||||||
{'coalition': true, 'tooltip': 'Unarmed', 'src': 'spawnUnarmed.png', 'callback': () => this.#selectGroundUnit(e, "Unarmed")}
|
{'coalition': true, 'tooltip': 'Unarmed', 'src': 'spawnUnarmed.png', 'callback': () => this.#selectGroundUnit(e, "Unarmed")}
|
||||||
]
|
]
|
||||||
this.showSelectionScroll(e, "Spawn ground unit", options, () => {}, true);
|
this.showContextMenu(e, "Spawn ground unit", options, () => {}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#smokeSpawnMenu(e: SpawnEvent) {
|
#smokeSpawnMenu(e: SpawnEvent) {
|
||||||
this.hideSelectionWheel();
|
this.hideContextMenu();
|
||||||
this.hideSelectionScroll();
|
|
||||||
var options = [
|
var options = [
|
||||||
{'tooltip': 'Red smoke', 'src': 'spawnSmoke.png', 'callback': () => {this.hideSelectionWheel(); this.hideSelectionScroll(); spawnSmoke('red', e.latlng)}, 'tint': 'red'},
|
{'tooltip': 'Red smoke', 'src': 'spawnSmoke.png', 'callback': () => {this.hideContextMenu(); spawnSmoke('red', e.latlng)}, 'tint': 'red'},
|
||||||
{'tooltip': 'White smoke', 'src': 'spawnSmoke.png', 'callback': () => {this.hideSelectionWheel(); this.hideSelectionScroll(); spawnSmoke('white', e.latlng)}, 'tint': 'white'},
|
{'tooltip': 'White smoke', 'src': 'spawnSmoke.png', 'callback': () => {this.hideContextMenu(); spawnSmoke('white', e.latlng)}, 'tint': 'white'},
|
||||||
{'tooltip': 'Blue smoke', 'src': 'spawnSmoke.png', 'callback': () => {this.hideSelectionWheel(); this.hideSelectionScroll(); spawnSmoke('blue', e.latlng)}, 'tint': 'blue'},
|
{'tooltip': 'Blue smoke', 'src': 'spawnSmoke.png', 'callback': () => {this.hideContextMenu(); spawnSmoke('blue', e.latlng)}, 'tint': 'blue'},
|
||||||
{'tooltip': 'Green smoke', 'src': 'spawnSmoke.png', 'callback': () => {this.hideSelectionWheel(); this.hideSelectionScroll(); spawnSmoke('green', e.latlng)}, 'tint': 'green'},
|
{'tooltip': 'Green smoke', 'src': 'spawnSmoke.png', 'callback': () => {this.hideContextMenu(); spawnSmoke('green', e.latlng)}, 'tint': 'green'},
|
||||||
{'tooltip': 'Orange smoke', 'src': 'spawnSmoke.png', 'callback': () => {this.hideSelectionWheel(); this.hideSelectionScroll(); spawnSmoke('orange', e.latlng)}, 'tint': 'orange'},
|
{'tooltip': 'Orange smoke', 'src': 'spawnSmoke.png', 'callback': () => {this.hideContextMenu(); spawnSmoke('orange', e.latlng)}, 'tint': 'orange'},
|
||||||
]
|
]
|
||||||
this.showSelectionScroll(e, "Spawn smoke", options, () => {}, false);
|
this.showContextMenu(e, "Spawn smoke", options, () => {}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#explosionSpawnMenu(e: SpawnEvent) {
|
#explosionSpawnMenu(e: SpawnEvent) {
|
||||||
@@ -321,12 +308,10 @@ export class Map extends L.Map {
|
|||||||
|
|
||||||
/* Show unit selection for air units */
|
/* Show unit selection for air units */
|
||||||
#selectAircraft(e: SpawnEvent, role: string) {
|
#selectAircraft(e: SpawnEvent, role: string) {
|
||||||
this.hideSelectionWheel();
|
this.hideContextMenu();
|
||||||
this.hideSelectionScroll();
|
|
||||||
var options = getAircraftLabelsByRole(role);
|
var options = getAircraftLabelsByRole(role);
|
||||||
this.showSelectionScroll(e, "Select aircraft", options, (label: string) => {
|
this.showContextMenu(e, "Select aircraft", options, (label: string) => {
|
||||||
this.hideSelectionWheel();
|
this.hideContextMenu();
|
||||||
this.hideSelectionScroll();
|
|
||||||
var name = getAircraftNameByLabel(label);
|
var name = getAircraftNameByLabel(label);
|
||||||
if (name != null)
|
if (name != null)
|
||||||
this.#unitSelectPayload(e, name, role);
|
this.#unitSelectPayload(e, name, role);
|
||||||
@@ -335,15 +320,13 @@ export class Map extends L.Map {
|
|||||||
|
|
||||||
/* Show weapon selection for air units */
|
/* Show weapon selection for air units */
|
||||||
#unitSelectPayload(e: SpawnEvent, unitType: string, role: string) {
|
#unitSelectPayload(e: SpawnEvent, unitType: string, role: string) {
|
||||||
this.hideSelectionWheel();
|
this.hideContextMenu();
|
||||||
this.hideSelectionScroll();
|
|
||||||
var options = getLoadoutNamesByRole(unitType, role);
|
var options = getLoadoutNamesByRole(unitType, role);
|
||||||
//options = payloadNames[unitType]
|
//options = payloadNames[unitType]
|
||||||
if (options != undefined && options.length > 0) {
|
if (options != undefined && options.length > 0) {
|
||||||
options.sort();
|
options.sort();
|
||||||
this.showSelectionScroll({x: e.x, y: e.y, latlng: e.latlng}, "Select loadout", options, (loadoutName: string) => {
|
this.showContextMenu({x: e.x, y: e.y, latlng: e.latlng}, "Select loadout", options, (loadoutName: string) => {
|
||||||
this.hideSelectionWheel();
|
this.hideContextMenu();
|
||||||
this.hideSelectionScroll();
|
|
||||||
var loadout = getLoadoutsByName(unitType, loadoutName);
|
var loadout = getLoadoutsByName(unitType, loadoutName);
|
||||||
spawnAircraft(unitType, e.latlng, getActiveCoalition(), loadout.code, e.airbaseName);
|
spawnAircraft(unitType, e.latlng, getActiveCoalition(), loadout.code, e.airbaseName);
|
||||||
}, true);
|
}, true);
|
||||||
@@ -356,13 +339,11 @@ export class Map extends L.Map {
|
|||||||
/* Show unit selection for ground units */
|
/* Show unit selection for ground units */
|
||||||
#selectGroundUnit(e: any, group: string)
|
#selectGroundUnit(e: any, group: string)
|
||||||
{
|
{
|
||||||
this.hideSelectionWheel();
|
this.hideContextMenu();
|
||||||
this.hideSelectionScroll();
|
|
||||||
var options = unitTypes.vehicles[group];
|
var options = unitTypes.vehicles[group];
|
||||||
options.sort();
|
options.sort();
|
||||||
this.showSelectionScroll(e, "Select ground unit", options, (unitType: string) => {
|
this.showContextMenu(e, "Select ground unit", options, (unitType: string) => {
|
||||||
this.hideSelectionWheel();
|
this.hideContextMenu();
|
||||||
this.hideSelectionScroll();
|
|
||||||
spawnGroundUnit(unitType, e.latlng, getActiveCoalition());
|
spawnGroundUnit(unitType, e.latlng, getActiveCoalition());
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ export class MissionData
|
|||||||
options = ["Spawn unit", "Land here"];
|
options = ["Spawn unit", "Land here"];
|
||||||
else
|
else
|
||||||
options = ["Spawn unit"];
|
options = ["Spawn unit"];
|
||||||
getMap().showSelectionScroll(e.originalEvent, e.sourceTarget.getName(), options, (option: string) => this.#onAirbaseOptionSelection(e, option), false);
|
getMap().showContextMenu(e.originalEvent, e.sourceTarget.getName(), options, (option: string) => this.#onAirbaseOptionSelection(e, option), false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,8 +90,7 @@ export class MissionData
|
|||||||
}
|
}
|
||||||
else if (option === "Land here")
|
else if (option === "Land here")
|
||||||
{
|
{
|
||||||
getMap().hideSelectionWheel();
|
getMap().hideContextMenu();
|
||||||
getMap().hideSelectionScroll();
|
|
||||||
getUnitsManager().selectedUnitsLandAt(e.latlng);
|
getUnitsManager().selectedUnitsLandAt(e.latlng);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,8 +118,7 @@ export class Unit {
|
|||||||
if ((this.alive || !selected) && this.#selectable && this.#selected != selected) {
|
if ((this.alive || !selected) && this.#selectable && this.#selected != selected) {
|
||||||
this.#selected = selected;
|
this.#selected = selected;
|
||||||
this.#marker.setSelected(selected);
|
this.#marker.setSelected(selected);
|
||||||
getUnitsManager().onUnitSelection();
|
document.dispatchEvent(new CustomEvent("unitSelection", {detail: this}));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,11 +206,11 @@ export class Unit {
|
|||||||
'Follow'
|
'Follow'
|
||||||
]
|
]
|
||||||
|
|
||||||
getMap().showSelectionScroll(e.originalEvent, "Action: " + this.unitName, options, (action: string) => this.#executeAction(action));
|
getMap().showContextMenu(e.originalEvent, "Action: " + this.unitName, options, (action: string) => this.#executeAction(action));
|
||||||
}
|
}
|
||||||
|
|
||||||
#executeAction(action: string) {
|
#executeAction(action: string) {
|
||||||
getMap().hideSelectionScroll();
|
getMap().hideContextMenu();
|
||||||
if (action === "Attack")
|
if (action === "Attack")
|
||||||
getUnitsManager().selectedUnitsAttackUnit(this.ID);
|
getUnitsManager().selectedUnitsAttackUnit(this.ID);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export class UnitsManager {
|
|||||||
|
|
||||||
document.addEventListener('copy', () => this.copyUnits());
|
document.addEventListener('copy', () => this.copyUnits());
|
||||||
document.addEventListener('paste', () => this.pasteUnits());
|
document.addEventListener('paste', () => this.pasteUnits());
|
||||||
|
document.addEventListener('unitSelection', () => this.onUnitSelection());
|
||||||
}
|
}
|
||||||
|
|
||||||
#updateUnitControlPanel() {
|
#updateUnitControlPanel() {
|
||||||
@@ -98,13 +99,12 @@ export class UnitsManager {
|
|||||||
onUnitSelection() {
|
onUnitSelection() {
|
||||||
if (this.getSelectedUnits().length > 0) {
|
if (this.getSelectedUnits().length > 0) {
|
||||||
getMap().setState("MOVE_UNIT");
|
getMap().setState("MOVE_UNIT");
|
||||||
//unitControlPanel.setEnabled(true);
|
document.dispatchEvent(new CustomEvent("unitsSelection", {detail: this.getSelectedUnits()}));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
getMap().setState("IDLE");
|
getMap().setState("IDLE");
|
||||||
//unitControlPanel.setEnabled(false);
|
document.dispatchEvent(new CustomEvent("clearSelection"));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#updateUnitControlPanel();
|
this.#updateUnitControlPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,7 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="map-container"></div>
|
<div id="map-container"></div>
|
||||||
<%- include('selectionwheel.ejs') %>
|
<%- include('contextmenu.ejs') %>
|
||||||
<%- include('selectionscroll.ejs') %>
|
|
||||||
<div class="ol-dropdown" id="map-source-dropdown"></div>
|
<div class="ol-dropdown" id="map-source-dropdown"></div>
|
||||||
<!-- <div class="ol-dropdown" id="scenario-dropdown"></div> -->
|
<!-- <div class="ol-dropdown" id="scenario-dropdown"></div> -->
|
||||||
<%- include('unitinfopanel.ejs') %>
|
<%- include('unitinfopanel.ejs') %>
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
<div class="ol-selection-wheel" id="selection-wheel">
|
|
||||||
<div class="ol-wheel">
|
|
||||||
</div>
|
|
||||||
<label id="coalition-switch-container">
|
|
||||||
<input type="checkbox" id="coalition-switch"> <span
|
|
||||||
class="ol-selection-wheel-slider ol-selection-wheel-switch"></span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
@@ -12,10 +12,13 @@ class Server
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Server(lua_State* L);
|
Server(lua_State* L);
|
||||||
~Server();
|
|
||||||
|
void start(lua_State* L);
|
||||||
|
void stop(lua_State* L);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::thread* serverThread;
|
std::thread* serverThread;
|
||||||
|
json::value answer;
|
||||||
|
|
||||||
void handle_options(http_request request);
|
void handle_options(http_request request);
|
||||||
void handle_get(http_request request);
|
void handle_get(http_request request);
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ extern "C" DllExport int coreDeinit(lua_State* L)
|
|||||||
|
|
||||||
log("Olympus coreDeinit called successfully");
|
log("Olympus coreDeinit called successfully");
|
||||||
|
|
||||||
|
server->stop(L);
|
||||||
|
|
||||||
delete unitsManager;
|
delete unitsManager;
|
||||||
delete server;
|
delete server;
|
||||||
delete scheduler;
|
delete scheduler;
|
||||||
@@ -42,6 +44,8 @@ extern "C" DllExport int coreInit(lua_State* L)
|
|||||||
|
|
||||||
registerLuaFunctions(L);
|
registerLuaFunctions(L);
|
||||||
|
|
||||||
|
server->start(L);
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,15 +26,25 @@ void handle_eptr(std::exception_ptr eptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Server::Server(lua_State* L):
|
Server::Server(lua_State* L):
|
||||||
|
serverThread(nullptr),
|
||||||
runListener(true)
|
runListener(true)
|
||||||
{
|
{
|
||||||
LogInfo(L, "Starting RESTServer");
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Server::start(lua_State* L)
|
||||||
|
{
|
||||||
|
log("Starting RESTServer");
|
||||||
serverThread = new thread(&Server::task, this);
|
serverThread = new thread(&Server::task, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Server::~Server()
|
void Server::stop(lua_State* L)
|
||||||
{
|
{
|
||||||
|
log("Stopping RESTServer");
|
||||||
runListener = false;
|
runListener = false;
|
||||||
|
if (serverThread != nullptr)
|
||||||
|
serverThread->join();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::handle_options(http_request request)
|
void Server::handle_options(http_request request)
|
||||||
@@ -59,18 +69,18 @@ void Server::handle_get(http_request request)
|
|||||||
response.headers().add(U("Access-Control-Allow-Methods"), U("GET, POST, PUT, OPTIONS"));
|
response.headers().add(U("Access-Control-Allow-Methods"), U("GET, POST, PUT, OPTIONS"));
|
||||||
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type"));
|
response.headers().add(U("Access-Control-Allow-Headers"), U("Content-Type"));
|
||||||
|
|
||||||
auto answer = json::value::object();
|
|
||||||
std::exception_ptr eptr;
|
std::exception_ptr eptr;
|
||||||
try {
|
try {
|
||||||
unitsManager->updateAnswer(answer);
|
unitsManager->updateAnswer(answer);
|
||||||
|
|
||||||
|
/* Get the logs from the logger */
|
||||||
|
auto logs = json::value::object();
|
||||||
|
logsToJSON(logs); // By reference, for thread safety
|
||||||
|
|
||||||
answer[L"airbases"] = airbasesData;
|
answer[L"airbases"] = airbasesData;
|
||||||
answer[L"bullseye"] = bullseyeData;
|
answer[L"bullseye"] = bullseyeData;
|
||||||
answer[L"logs"] = json::value::object();
|
answer[L"logs"] = logs;
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (auto log : getLogs())
|
|
||||||
answer[L"logs"][to_wstring(i++)] = json::value::string(to_wstring(log));
|
|
||||||
|
|
||||||
response.set_body(answer);
|
response.set_body(answer);
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
@@ -156,7 +166,10 @@ void Server::task()
|
|||||||
|
|
||||||
while (runListener);
|
while (runListener);
|
||||||
|
|
||||||
listener.close();
|
listener.close()
|
||||||
|
.then([&listener]() {log("RESTServer stopping connections"); })
|
||||||
|
.wait();
|
||||||
|
|
||||||
log("RESTServer stopped listening");
|
log("RESTServer stopped listening");
|
||||||
}
|
}
|
||||||
catch (exception const& e)
|
catch (exception const& e)
|
||||||
|
|||||||
@@ -3,4 +3,4 @@
|
|||||||
|
|
||||||
void DllExport log(const std::string& sMessage);
|
void DllExport log(const std::string& sMessage);
|
||||||
void DllExport log(const std::wstring& sMessage);
|
void DllExport log(const std::wstring& sMessage);
|
||||||
std::list<std::string> DllExport getLogs();
|
void DllExport logsToJSON(json::value& json);
|
||||||
|
|||||||
@@ -5,11 +5,12 @@
|
|||||||
class Logger
|
class Logger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void Log(const string& sMessage);
|
void log(const string& sMessage);
|
||||||
void Log(const wstring& sMessage);
|
void log(const wstring& sMessage);
|
||||||
std::list<std::string> getLogs() { return m_logs; };
|
void toJSON(json::value& json);
|
||||||
|
|
||||||
static Logger* GetLogger();
|
static Logger* GetLogger();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Logger();
|
Logger();
|
||||||
Logger(const Logger&) {}; // copy constructor is private
|
Logger(const Logger&) {}; // copy constructor is private
|
||||||
@@ -20,6 +21,8 @@ private:
|
|||||||
static ofstream m_Logfile;
|
static ofstream m_Logfile;
|
||||||
static std::list<std::string> m_logs;
|
static std::list<std::string> m_logs;
|
||||||
|
|
||||||
|
mutex mutexLock;
|
||||||
|
|
||||||
void Open();
|
void Open();
|
||||||
void Close();
|
void Close();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,15 +6,15 @@
|
|||||||
|
|
||||||
void log(const string& message)
|
void log(const string& message)
|
||||||
{
|
{
|
||||||
LOGGER->Log(message);
|
LOGGER->log(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void log(const wstring& message)
|
void log(const wstring& message)
|
||||||
{
|
{
|
||||||
LOGGER->Log(message);
|
LOGGER->log(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::list<std::string> getLogs()
|
void logsToJSON(json::value& json)
|
||||||
{
|
{
|
||||||
return LOGGER->getLogs();
|
LOGGER->toJSON(json);
|
||||||
}
|
}
|
||||||
@@ -16,8 +16,7 @@ Logger* Logger::GetLogger()
|
|||||||
if (m_pThis == NULL) {
|
if (m_pThis == NULL) {
|
||||||
m_pThis = new Logger();
|
m_pThis = new Logger();
|
||||||
std::filesystem::path dirPath = std::filesystem::temp_directory_path();
|
std::filesystem::path dirPath = std::filesystem::temp_directory_path();
|
||||||
m_Logfile.open((dirPath.string() + m_sFileName).c_str(), ios::out | ios::app);
|
m_Logfile.open((dirPath.string() + m_sFileName).c_str(), ios::out);
|
||||||
m_pThis->Log("**************************************************");
|
|
||||||
}
|
}
|
||||||
return m_pThis;
|
return m_pThis;
|
||||||
}
|
}
|
||||||
@@ -33,8 +32,17 @@ void Logger::Close()
|
|||||||
m_Logfile.close();
|
m_Logfile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::Log(const string& message)
|
void Logger::toJSON(json::value& json)
|
||||||
{
|
{
|
||||||
|
lock_guard<mutex> guard(mutexLock);
|
||||||
|
int i = 0;
|
||||||
|
for (auto log : m_logs)
|
||||||
|
json[to_wstring(i++)] = json::value::string(to_wstring(log));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Logger::log(const string& message)
|
||||||
|
{
|
||||||
|
lock_guard<mutex> guard(mutexLock);
|
||||||
Open();
|
Open();
|
||||||
m_Logfile << CurrentDateTime() << ":\t";
|
m_Logfile << CurrentDateTime() << ":\t";
|
||||||
m_Logfile << message << "\n";
|
m_Logfile << message << "\n";
|
||||||
@@ -42,8 +50,9 @@ void Logger::Log(const string& message)
|
|||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::Log(const wstring& message)
|
void Logger::log(const wstring& message)
|
||||||
{
|
{
|
||||||
|
lock_guard<mutex> guard(mutexLock);
|
||||||
Open();
|
Open();
|
||||||
m_Logfile << CurrentDateTime() << ":\t";
|
m_Logfile << CurrentDateTime() << ":\t";
|
||||||
m_Logfile << to_string(message) << "\n";
|
m_Logfile << to_string(message) << "\n";
|
||||||
|
|||||||
Reference in New Issue
Block a user