Added hotgroups ui and basic functions

User interaction still TBD
This commit is contained in:
Pax1601 2023-05-15 17:37:20 +02:00
parent 1ca2c66b45
commit 493c75b6e7
8 changed files with 167 additions and 69 deletions

View File

@ -856,4 +856,37 @@ body[data-hide-navyunit] #unit-visibility-control-navyunit {
50% {
opacity: 0;
}
}
#hotgroup-panel {
position: absolute;
bottom: 40px;
left: 50%;
translate: -50%;
z-index: 9999;
display: flex;
column-gap: 10px;
}
#hotgroup-panel>div {
width: 50px;
height: 50px;
background-color: var(--background-steel);
border-radius: var(--border-radius-sm);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
border: 0px solid transparent;
}
#hotgroup-panel>div:hover {
cursor: pointer;
border: 2px solid white;
}
.hotgroup-selector>.unit-hotgroup {
display: flex;
translate: 0% -300%;
}

View File

@ -3,7 +3,7 @@
--unit-centre-x: calc(var(--unit-width) / 2);
--unit-centre-y: calc(var(--unit-height) / 2);
--unit-hotgroup-height: 10px;
--unit-hotgroup-height: 15px;
--unit-hotgroup-width: var(--unit-hotgroup-height);
@ -23,7 +23,7 @@
width: 100%;
}
[data-object|="unit"] .unit-selected-spotlight {
.unit-selected-spotlight {
background-color: var(--unit-spotlight-fill);
border-radius: 50%;
display: none;
@ -32,8 +32,7 @@
z-index: 1;
}
[data-object|="unit"] .unit-vvi {
.unit-vvi {
align-self: center;
background: var(--secondary-gunmetal-grey);
display: flex;
@ -46,30 +45,7 @@
z-index: 3;
}
[data-object|="unit"] .unit-hotgroup {
align-content: center;
background-color: black;
border-radius: var(--border-radius-xs);
display: none;
height: var(--unit-hotgroup-height);
justify-content: center;
position: absolute;
transform: rotate(-45deg);
translate: 0 -275%;
width: var(--unit-hotgroup-width);
z-index: 5;
}
[data-object|="unit"] .unit-hotgroup-id {
background-color: transparent;
color: white;
font-size: 9px;
font-weight: bolder;
transform: rotate(45deg);
}
[data-object|="unit"] .unit-marker-border {
.unit-marker-border {
border-radius: var(--border-radius-sm);
display: none;
height: calc(var(--unit-aircraft-height) + (var(--unit-label-border-width) * 2));
@ -78,6 +54,29 @@
z-index: 2;
}
.unit-hotgroup {
align-content: center;
background-color: var(--background-steel);
border-radius: var(--border-radius-xs);
display: none;
height: var(--unit-hotgroup-height);
justify-content: center;
position: absolute;
transform: rotate(-45deg);
translate: 0 -200%;
width: var(--unit-hotgroup-width);
z-index: 5;
}
.unit-hotgroup-id {
background-color: transparent;
color: white;
font-size: 9px;
font-weight: bolder;
transform: rotate(45deg);
translate: -1px 1px;
}
/******************************
Marker
@ -92,8 +91,6 @@
z-index: 3;
}
/* Air */
[data-object|="unit-aircraft"] .unit-marker {
@ -110,7 +107,6 @@
background-image: var(--unit-aircraft-marker-neutral-selected-url);
}
[data-object|="unit-aircraft"][data-coalition="blue"] .unit-marker {
background-image: var(--unit-aircraft-marker-blue-url);
}
@ -136,9 +132,6 @@
background-image: var(--unit-aircraft-marker-red-selected-url);
}
/* Ground vehicles (not SAMs) */
[data-object|="unit-groundunit"] .unit-marker {
@ -279,7 +272,6 @@
/* Building */
[data-object|="unit-building"] .unit-marker {
background-image: var(--unit-building-marker-neutral-url);
height: var(--unit-building-marker-height);
@ -296,8 +288,6 @@
background-image: var(--unit-building-marker-red-url);
}
/* Weapons */
[data-object|="unit-missile"],
@ -439,8 +429,6 @@
overflow: visible;
}
[data-object|="unit"]:hover .unit-ammo,
[data-object|="unit"]:hover .unit-fuel {
display: flex;
@ -460,9 +448,6 @@
background-color: var(--secondary-gunmetal-grey);
}
[data-object|="unit"][data-coalition="blue"][data-is-selected] .unit-short-label {
color: var(--secondary-blue-text);
}
@ -496,8 +481,6 @@
background-color: var(--secondary-red-outline);
}
@keyframes pulse {
50% {
opacity: 0;
@ -508,7 +491,6 @@
animation: pulse 1.5s linear infinite;
}
[data-object|="unit"] .unit-state {
background-repeat: no-repeat;
position: absolute;
@ -569,20 +551,19 @@
}
[data-object|="unit-aircraft"][ data-is-dead] .unit-selected-spotlight,
[data-object|="unit-aircraft"][ data-is-dead] .unit-short-label,
[data-object|="unit-aircraft"][ data-is-dead] .unit-vvi,
[data-object|="unit-aircraft"][ data-is-dead] .unit-hotgroup,
[data-object|="unit-aircraft"][ data-is-dead] .unit-hotgroup-id,
[data-object|="unit-aircraft"][ data-is-dead] .unit-state,
[data-object|="unit-aircraft"][ data-is-dead] .unit-fuel,
[data-object|="unit-aircraft"][ data-is-dead] .unit-ammo,
[data-object|="unit-aircraft"][ data-is-dead]:hover .unit-fuel,
[data-object|="unit-aircraft"][ data-is-dead]:hover .unit-ammo {
[data-object|="unit-aircraft"][data-is-dead] .unit-selected-spotlight,
[data-object|="unit-aircraft"][data-is-dead] .unit-short-label,
[data-object|="unit-aircraft"][data-is-dead] .unit-vvi,
[data-object|="unit-aircraft"][data-is-dead] .unit-hotgroup,
[data-object|="unit-aircraft"][data-is-dead] .unit-hotgroup-id,
[data-object|="unit-aircraft"][data-is-dead] .unit-state,
[data-object|="unit-aircraft"][data-is-dead] .unit-fuel,
[data-object|="unit-aircraft"][data-is-dead] .unit-ammo,
[data-object|="unit-aircraft"][data-is-dead]:hover .unit-fuel,
[data-object|="unit-aircraft"][data-is-dead]:hover .unit-ammo {
display: none !important;
}
[data-object|="unit-aircraft"][ data-is-dead] .unit-summary>* {
display: none;
}

View File

@ -9,11 +9,12 @@ import { AIC } from "./aic/aic";
import { ATC } from "./atc/atc";
import { FeatureSwitches } from "./featureswitches";
import { LogPanel } from "./panels/logpanel";
import { getAirbases, getBullseye, getConfig, getFreezed, getMission, getUnits, setAddress, setCredentials, setFreezed, startUpdate, toggleDemoEnabled } from "./server/server";
import { getConfig, getFreezed, setAddress, setCredentials, setFreezed, startUpdate, toggleDemoEnabled } from "./server/server";
import { UnitDataTable } from "./units/unitdatatable";
import { keyEventWasInInput } from "./other/utils";
import { Popup } from "./popups/popup";
import { Dropdown } from "./controls/dropdown";
import { HotgroupPanel } from "./panels/hotgrouppanel";
var map: Map;
@ -28,6 +29,7 @@ var connectionStatusPanel: ConnectionStatusPanel;
var unitControlPanel: UnitControlPanel;
var mouseInfoPanel: MouseInfoPanel;
var logPanel: LogPanel;
var hotgroupPanel: HotgroupPanel;
var infoPopup: Popup;
@ -50,6 +52,7 @@ function setup() {
unitControlPanel = new UnitControlPanel("unit-control-panel");
connectionStatusPanel = new ConnectionStatusPanel("connection-status-panel");
mouseInfoPanel = new MouseInfoPanel("mouse-info-panel");
hotgroupPanel = new HotgroupPanel("hotgroup-panel");
//logPanel = new LogPanel("log-panel");
/* Popups */
@ -147,6 +150,20 @@ function setupEvents() {
case "ArrowDown":
getMap().handleMapPanning(ev);
break;
case "Digit1":
case "Digit2":
case "Digit3":
case "Digit4":
case "Digit5":
case "Digit6":
case "Digit7":
case "Digit8":
case "Digit9":
if (ev.ctrlKey)
getUnitsManager().selectedUnitsAddToHotgroup(parseInt(ev.key));
else
getUnitsManager().selectUnitsByHotgroup(parseInt(ev.key));
break;
}
});
@ -232,6 +249,10 @@ export function getConnectionStatusPanel() {
return connectionStatusPanel;
}
export function getHotgroupPanel() {
return hotgroupPanel;
}
export function setActiveCoalition(newActiveCoalition: string) {
activeCoalition = newActiveCoalition;
document.querySelectorAll('[data-active-coalition]').forEach((element: any) => { element.setAttribute("data-active-coalition", activeCoalition) });

View File

@ -0,0 +1,25 @@
import { getUnitsManager } from "..";
import { Panel } from "./panel";
export class HotgroupPanel extends Panel {
addHotgroup(hotgroup: number) {
this.removeHotgroup(hotgroup);
const hotgroupHtml = `<div class="unit-hotgroup">
<div class="unit-hotgroup-id">${hotgroup}</div>
</div>
x${getUnitsManager().getUnitsByHotgroup(hotgroup).length}`
var el = document.createElement("div");
el.classList.add("hotgroup-selector");
el.innerHTML = hotgroupHtml;
el.toggleAttribute(`data-hotgroup-${hotgroup}`, true)
this.getElement().appendChild(el);
el.addEventListener("click", () => {
getUnitsManager().selectUnitsByHotgroup(hotgroup);
});
}
removeHotgroup(hotgroup: number) {
const el = this.getElement().querySelector(`[data-hotgroup-${hotgroup}]`) as HTMLElement;
if (el) el.remove();
}
}

View File

@ -77,6 +77,8 @@ export class Unit extends Marker {
#timer: number = 0;
#hotgroup: number | null = null;
static getConstructor(type: string) {
if (type === "GroundUnit") return GroundUnit;
if (type === "Aircraft") return Aircraft;
@ -265,6 +267,14 @@ export class Unit extends Marker {
return this.#selectable;
}
setHotgroup(hotgroup: number | null) {
this.#hotgroup = hotgroup;
}
getHotgroup() {
return this.#hotgroup;
}
/********************** Visibility *************************/
updateVisibility()
{
@ -556,7 +566,6 @@ export class Unit extends Marker {
});
/* Turn on ordnance indicators */
var hasFox1 = element.querySelector(".unit")?.hasAttribute("data-has-fox-1");
var hasFox2 = element.querySelector(".unit")?.hasAttribute("data-has-fox-2");
var hasFox3 = element.querySelector(".unit")?.hasAttribute("data-has-fox-3");
@ -568,25 +577,30 @@ export class Unit extends Marker {
var newHasOtherAmmo = false;
Object.values(this.getMissionData().ammo).forEach((ammo: any) => {
if (ammo.desc.category == 1 && ammo.desc.missileCategory == 1) {
if (ammo.desc.guidance == 4 || ammo.desc.guidance == 5) {
if (ammo.desc.guidance == 4 || ammo.desc.guidance == 5)
newHasFox1 = true;
}
else if (ammo.desc.guidance == 2) {
else if (ammo.desc.guidance == 2)
newHasFox2 = true;
}
else if (ammo.desc.guidance == 3) {
else if (ammo.desc.guidance == 3)
newHasFox3 = true;
}
}
else {
else
newHasOtherAmmo = true;
}
});
if (hasFox1 != newHasFox1) element.querySelector(".unit")?.toggleAttribute("data-has-fox-1", newHasFox1);
if (hasFox2 != newHasFox2) element.querySelector(".unit")?.toggleAttribute("data-has-fox-2", newHasFox2);
if (hasFox3 != newHasFox3) element.querySelector(".unit")?.toggleAttribute("data-has-fox-3", newHasFox3);
if (hasOtherAmmo != newHasOtherAmmo) element.querySelector(".unit")?.toggleAttribute("data-has-other-ammo", newHasOtherAmmo);
/* Draw the hotgroup element */
if (this.#hotgroup) {
element.querySelector(".unit")?.toggleAttribute("data-is-in-hotgroup", this.#hotgroup != null);
const hotgroupEl = element.querySelector(".unit-hotgroup-id") as HTMLElement;
if (hotgroupEl)
hotgroupEl.innerText = String(this.#hotgroup);
}
}
/* Set vertical offset for altitude stacking */
@ -732,6 +746,9 @@ export class GroundUnit extends Unit {
<div class="unit-selected-spotlight"></div>
<div class="unit-marker"></div>
<div class="unit-short-label">${role?.substring(0, 1)?.toUpperCase() || ""}</div>
<div class="unit-hotgroup">
<div class="unit-hotgroup-id"></div>
</div>
</div>`
}

View File

@ -1,5 +1,5 @@
import { LatLng, LatLngBounds } from "leaflet";
import { getInfoPopup, getMap, getUnitDataTable } from "..";
import { getHotgroupPanel, getInfoPopup, getMap, getUnitDataTable } from "..";
import { Unit } from "./unit";
import { cloneUnit } from "../server/server";
import { IDLE, MOVE_UNIT } from "../map/map";
@ -45,6 +45,10 @@ export class UnitsManager {
return null;
}
getUnitsByHotgroup(hotgroup: number) {
return Object.values(this.#units).filter((unit: Unit) => {return unit.getHotgroup() == hotgroup});
}
addUnit(ID: number, data: UnitData) {
/* The name of the unit category is exactly the same as the constructor name */
var constructor = Unit.getConstructor(data.baseData.category);
@ -112,6 +116,10 @@ export class UnitsManager {
}
}
selectUnitsByHotgroup(hotgroup: number) {
this.getUnitsByHotgroup(hotgroup).forEach((unit: Unit) => unit.setSelected(true))
}
getSelectedUnitsType() {
if (this.getSelectedUnits().length == 0)
return undefined;
@ -259,7 +267,7 @@ export class UnitsManager {
}
selectedUnitsRefuel() {
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
for (let idx in selectedUnits) {
selectedUnits[idx].refuel();
}
@ -309,6 +317,16 @@ export class UnitsManager {
this.#showActionMessage(selectedUnits, `following unit ${this.getUnitByID(ID)?.getBaseData().unitName}`);
}
selectedUnitsAddToHotgroup(hotgroup: number)
{
var selectedUnits = this.getSelectedUnits();
for (let idx in selectedUnits) {
selectedUnits[idx].setHotgroup(hotgroup);
}
this.#showActionMessage(selectedUnits, `added to hotgroup ${hotgroup}`);
getHotgroupPanel().addHotgroup(hotgroup);
}
/***********************************************/
copyUnits() {
this.#copiedUnits = this.getSelectedUnits(); /* Can be applied to humans too */

View File

@ -0,0 +1,3 @@
<div id="hotgroup-panel">
</div>

View File

@ -24,7 +24,6 @@
<div id="map-container"></div>
<%- include('aic.ejs') %>
<%- include('atc.ejs') %>
<%- include('contextmenus.ejs') %>
<%- include('unitcontrolpanel.ejs') %>
<%- include('unitinfopanel.ejs') %>
@ -34,6 +33,7 @@
<%- include('dialogs.ejs') %>
<%- include('unitdatatable.ejs') %>
<%- include('popups.ejs') %>
<%- include('hotgrouppanel.ejs') %>
<div id="gray-out"></div>