Follow feature completed

This commit is contained in:
Pax1601 2023-04-19 10:19:56 +02:00
parent cfd98e74ea
commit f24c57cc18
10 changed files with 117 additions and 77 deletions

View File

@ -7,7 +7,7 @@
@import url("unitdatatable.css");
@import url("unitcontrolpanel.css");
@import url("unitinfopanel.css");
@import url("popup.css");
* {
@ -441,8 +441,6 @@ nav.ol-panel> :last-child {
font-weight: var(--font-weight-bolder);
}
.hide {
display: none !important;
}

View File

@ -0,0 +1,23 @@
#info-popup {
position: absolute;
width: fit-content;
height: fit-content;
top: 100px;
left: 50%;
translate: -50% 0%;
z-index: 9999;
}
.ol-popup > div {
padding-left: 15px;
padding-right: 15px;
}
.visible {
opacity: 1;
}
.invisible {
opacity: 0;
transition: opacity 2s linear;
}

View File

@ -1,7 +1,9 @@
import { getUnitsManager } from "..";
import { deg2rad } from "../other/utils";
import { ContextMenu } from "./contextmenu";
export class UnitContextMenu extends ContextMenu {
#callback: CallableFunction | null = null;
#customFormationCallback: CallableFunction | null = null;
constructor(id: string) {
super(id);
@ -19,17 +21,28 @@ export class UnitContextMenu extends ContextMenu {
clock++;
}
var angleDeg = 360 - (clock - 1) * 45;
var distance = parseInt((<HTMLInputElement> dialog.querySelector(`#distance`)?.querySelector("input")).value);
var upDown = parseInt((<HTMLInputElement> dialog.querySelector(`#up-down`)?.querySelector("input")).value);
var asd= 1;
var angleRad = deg2rad(angleDeg);
var distance = parseInt((<HTMLInputElement> dialog.querySelector(`#distance`)?.querySelector("input")).value) * 0.3048;
var upDown = parseInt((<HTMLInputElement> dialog.querySelector(`#up-down`)?.querySelector("input")).value) * 0.3048;
}
// X: front-rear, positive front
// Y: top-bottom, positive top
// Z: left-right, positive right
if (this.#callback)
this.#callback()
var x = distance * Math.cos(angleRad);
var y = upDown;
var z = distance * Math.sin(angleRad);
if (this.#customFormationCallback)
this.#customFormationCallback({"x": x, "y": y, "z": z})
}
})
}
setCustomFormationCallback(callback: CallableFunction) {
this.#customFormationCallback = callback;
}
setOptions(options: {[key: string]: string}, callback: CallableFunction)
{
this.getContainer()?.replaceChildren(...Object.keys(options).map((option: string, idx: number) =>

View File

@ -12,6 +12,7 @@ import { LogPanel } from "./panels/logpanel";
import { getAirbases, getBullseye as getBullseyes, getConfig, getMission, getUnits, setAddress, toggleDemoEnabled } from "./server/server";
import { UnitDataTable } from "./units/unitdatatable";
import { keyEventWasInInput } from "./other/utils";
import { Popup } from "./popups/popup";
var map: Map;
@ -27,6 +28,8 @@ var unitControlPanel: UnitControlPanel;
var mouseInfoPanel: MouseInfoPanel;
var logPanel: LogPanel;
var infoPopup: Popup;
var connected: boolean = false;
var paused: boolean = false;
var activeCoalition: string = "blue";
@ -52,6 +55,9 @@ function setup() {
mouseInfoPanel = new MouseInfoPanel("mouse-info-panel");
//logPanel = new LogPanel("log-panel");
/* Popups */
infoPopup = new Popup("info-popup");
unitDataTable = new UnitDataTable("unit-data-table");
/* AIC */
@ -269,7 +275,9 @@ export function getActiveCoalition() {
}
export function setConnected(newConnected: boolean) {
connected = newConnected
if (connected != newConnected)
newConnected? getInfoPopup().setText("Connected to DCS Olympus server"): getInfoPopup().setText("Disconnected from DCS Olympus server");
connected = newConnected;
}
export function getConnected() {
@ -278,10 +286,15 @@ export function getConnected() {
export function setPaused(newPaused: boolean) {
paused = newPaused;
paused? getInfoPopup().setText("Paused"): getInfoPopup().setText("Unpaused");
}
export function getPaused() {
return paused;
}
export function getInfoPopup() {
return infoPopup;
}
window.onload = setup;

View File

@ -0,0 +1,26 @@
import { Panel } from "../panels/panel";
export class Popup extends Panel {
#fadeTime: number = 2000; // Milliseconds
#hideTimer: number | undefined = undefined;
#visibilityTimer: number | undefined = undefined;
setFadeTime(fadeTime: number) {
this.#fadeTime = fadeTime;
}
setText(text: string) {
(<HTMLElement> this.getElement().querySelector("div")).innerText = text;
this.show();
this.getElement().classList.remove("invisible");
this.getElement().classList.add("visible");
clearTimeout(this.#visibilityTimer);
clearTimeout(this.#hideTimer);
this.#visibilityTimer = setTimeout(() => {
this.getElement().classList.remove("visible");
this.getElement().classList.add("invisible");
this.#hideTimer = setTimeout(() => this.hide(), 2000);
}, this.#fadeTime);
}
}

View File

@ -476,6 +476,9 @@ export class Unit extends Marker {
if (action === "Custom")
{
document.getElementById("custom-formation-dialog")?.classList.remove("hide");
getMap().getUnitContextMenu().setCustomFormationCallback((offset: {x: number, y: number, z: number}) => {
getUnitsManager().selectedUnitsFollowUnit(this.ID, offset);
})
}
else {
// X: front-rear, positive front

View File

@ -1,5 +1,5 @@
import { LatLng, LatLngBounds } from "leaflet";
import { getMap, getUnitDataTable } from "..";
import { getInfoPopup, getMap, getUnitDataTable } from "..";
import { Unit } from "./unit";
import { cloneUnit } from "../server/server";
import { IDLE, MOVE_UNIT } from "../map/map";
@ -176,6 +176,7 @@ export class UnitsManager {
var commandedUnit = selectedUnits[idx];
commandedUnit.addDestination(latlng);
}
this.#showActionMessage(selectedUnits, " new destination added");
}
selectedUnitsClearDestinations() {
@ -193,6 +194,7 @@ export class UnitsManager {
{
selectedUnits[idx].landAt(latlng);
}
this.#showActionMessage(selectedUnits, " landing");
}
selectedUnitsChangeSpeed(speedChange: string)
@ -220,6 +222,8 @@ export class UnitsManager {
{
selectedUnits[idx].setSpeed(speed);
}
this.#showActionMessage(selectedUnits, `setting speed to ${speed * 1.94384} kts`);
}
selectedUnitsSetAltitude(altitude: number)
@ -229,6 +233,7 @@ export class UnitsManager {
{
selectedUnits[idx].setAltitude(altitude);
}
this.#showActionMessage(selectedUnits, `setting altitude to ${altitude / 0.3048} ft`);
}
selectedUnitsSetROE(ROE: string)
@ -238,6 +243,7 @@ export class UnitsManager {
{
selectedUnits[idx].setROE(ROE);
}
this.#showActionMessage(selectedUnits, `ROE set to ${ROE}`);
}
selectedUnitsSetReactionToThreat(reactionToThreat: string)
@ -247,73 +253,15 @@ export class UnitsManager {
{
selectedUnits[idx].setReactionToThreat(reactionToThreat);
}
this.#showActionMessage(selectedUnits, `reaction to threat set to ${reactionToThreat}`);
}
selectedUnitsAttackUnit(ID: number) {
var selectedUnits = this.getSelectedUnits();
for (let idx in selectedUnits) {
/* If a unit is a wingman, send the command to its leader */
var commandedUnit = selectedUnits[idx];
//if (selectedUnits[idx].wingman)
//{
// commandedUnit = this.getLeader(selectedUnits[idx].ID);
//}
commandedUnit.attackUnit(ID);
}
}
selectedUnitsCreateFormation(ID: number | null = null)
{
var selectedUnits = this.getSelectedUnits();
if (selectedUnits.length >= 2)
{
if (ID == null)
ID = selectedUnits[0].ID
var wingmenIDs = [];
for (let idx in selectedUnits)
{
if (selectedUnits[idx].getFormationData().isWingman)
{
//console.log(selectedUnits[idx].unitName + " is already in a formation.");
return;
}
else if (selectedUnits[idx].getFormationData().isLeader)
{
//console.log(selectedUnits[idx].unitName + " is already in a formation.");
return;
}
else
{
/* TODO
if (selectedUnits[idx].category !== this.getUnitByID(ID).category)
{
showMessage("All units must be of the same category to create a formation.");
}
*/
if (selectedUnits[idx].ID != ID)
{
wingmenIDs.push(selectedUnits[idx].ID);
}
}
}
if (wingmenIDs.length > 0)
{
this.getUnitByID(ID)?.setLeader(true, wingmenIDs);
}
else
{
//console.log("At least 2 units must be selected to create a formation.");
}
}
}
selectedUnitsUndoFormation()
{
for (let leader of this.getSelectedLeaders())
{
leader.setLeader(false);
selectedUnits[idx].attackUnit(ID);
}
this.#showActionMessage(selectedUnits, `attacking unit ${this.getUnitByID(ID)?.getBaseData().unitName}`);
}
selectedUnitsDelete()
@ -323,6 +271,7 @@ export class UnitsManager {
{
selectedUnits[idx].delete();
}
this.#showActionMessage(selectedUnits, `deleted`);
}
selectedUnitsRefuel()
@ -332,6 +281,7 @@ export class UnitsManager {
{
selectedUnits[idx].refuel();
}
this.#showActionMessage(selectedUnits, `sent to nearest tanker`);
}
selectedUnitsFollowUnit(ID: number, offset: {"x": number, "y": number, "z": number}) {
@ -342,11 +292,13 @@ export class UnitsManager {
commandedUnit.followUnit(ID, {"x": offset.x * count, "y": offset.y * count, "z": offset.z * count} );
count++;
}
this.#showActionMessage(selectedUnits, `following unit ${this.getUnitByID(ID)?.getBaseData().unitName}`);
}
copyUnits()
{
this.#copiedUnits = this.getSelectedUnits();
this.#showActionMessage(this.#copiedUnits, `copied`);
}
pasteUnits()
@ -357,6 +309,7 @@ export class UnitsManager {
{
var unit = this.#copiedUnits[idx];
cloneUnit(unit.ID, getMap().getMouseCoordinates());
this.#showActionMessage(this.#copiedUnits, `pasted`);
}
this.#pasteDisabled = true;
setTimeout(() => this.#pasteDisabled = false, 250);
@ -398,4 +351,11 @@ export class UnitsManager {
else
document.dispatchEvent(new CustomEvent("unitsDeselection", {detail: this.getSelectedUnits()}));
}
#showActionMessage(units: Unit[], message: string) {
if (units.length == 1)
getInfoPopup().setText(`${units[0].getBaseData().unitName} ${message}`);
else
getInfoPopup().setText(`${units[0].getBaseData().unitName} and ${units.length - 1} other units ${message}`);
}
}

View File

@ -17,8 +17,6 @@
</div>
<div id="advanced-settings-dialog" class="ol-panel ol-dialog hide">
<div class="ol-dialog-close" data-on-click="closeDialog"></div>
@ -143,7 +141,7 @@
</div>
<div id="custom-formation-dialog" class="ol-panel ol-dialog">
<div id="custom-formation-dialog" class="ol-panel ol-dialog hide">
<div class="ol-dialog-close" data-on-click="closeDialog"></div>
<div class="ol-dialog-header">
@ -168,7 +166,7 @@
<div class="ol-group">
<div id="distance" class="ol-text-input">
<input type="number" min="0" max="99999" step="1" value="150">
<input type="number" min="0" max="999999" step="1" value="150">
</div>
<label>ft</label>
</div>

View File

@ -33,6 +33,7 @@
<%- include('connectionstatuspanel.ejs') %>
<%- include('dialogs.ejs') %>
<%- include('unitdatatable.ejs') %>
<%- include('popups.ejs') %>
<% /* %>
<%- include('log.ejs') %>

5
client/views/popups.ejs Normal file
View File

@ -0,0 +1,5 @@
<div id="info-popup" class="ol-panel ol-popup hide">
<div>
<!-- Here the content of the popup will be shown -->
</div>
</div>