From 48f962ca4b9670783b293416cd945c39ae3ee3dc Mon Sep 17 00:00:00 2001 From: PeekabooSteam Date: Mon, 18 Dec 2023 12:57:44 +0000 Subject: [PATCH] Spawn history is functional --- client/public/stylesheets/leaflet/leaflet.css | 7 +- .../public/stylesheets/other/contextmenus.css | 136 +++++++++++++----- .../images/buttons/other/arrow-down-solid.svg | 1 + .../buttons/other/clock-rotate-left-solid.svg | 1 + client/src/contextmenus/mapcontextmenu.ts | 61 ++++++++ client/src/unit/unitsmanager.ts | 10 ++ client/views/contextmenus/map.ejs | 115 ++++++++------- 7 files changed, 238 insertions(+), 93 deletions(-) create mode 100644 client/public/themes/olympus/images/buttons/other/arrow-down-solid.svg create mode 100644 client/public/themes/olympus/images/buttons/other/clock-rotate-left-solid.svg diff --git a/client/public/stylesheets/leaflet/leaflet.css b/client/public/stylesheets/leaflet/leaflet.css index 9ade8dc4..1981009f 100644 --- a/client/public/stylesheets/leaflet/leaflet.css +++ b/client/public/stylesheets/leaflet/leaflet.css @@ -60,11 +60,6 @@ padding: 0; } -.leaflet-container img.leaflet-tile { - /* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */ - mix-blend-mode: plus-lighter; -} - .leaflet-container.leaflet-touch-zoom { -ms-touch-action: pan-x pan-y; touch-action: pan-x pan-y; @@ -651,7 +646,7 @@ svg.leaflet-image-layer.leaflet-interactive path { } /* Printing */ - + @media print { /* Prevent printers from removing background-images of controls. */ .leaflet-control { diff --git a/client/public/stylesheets/other/contextmenus.css b/client/public/stylesheets/other/contextmenus.css index 172afdac..9aa269a8 100644 --- a/client/public/stylesheets/other/contextmenus.css +++ b/client/public/stylesheets/other/contextmenus.css @@ -8,24 +8,20 @@ z-index: 9999; } -#map-contextmenu>div:nth-child(2) { - align-items: center; + + +/* #map-contextmenu>div:nth-child(n+4)>div { + width: 100%; +} */ + +#map-contextmenu .spawn-mode { display: flex; - flex-direction: row; + flex-direction: column; justify-content: space-between; - padding-right: 0px; + row-gap: 5px; } -#map-contextmenu>div:nth-child(3) { - align-items: center; - display: flex; - flex-direction: row; - justify-content: space-between; - padding-right: 0px; -} - -#map-contextmenu>div:nth-child(n+4) { - align-items: center; +.ol-context-menu-panel { display: flex; flex-direction: column; justify-content: space-between; @@ -33,10 +29,6 @@ padding: 20px; } -#map-contextmenu>div:nth-child(n+4)>div { - width: 100%; -} - .contextmenu-advanced-options, .contextmenu-metadata { align-items: center; @@ -143,20 +135,6 @@ padding: 2px 5px; } -/* -.ol-tag-CA { - background-color: #FF000022; -} - -.ol-tag-Radar { - background-color: #00FF0022; -} - -.ol-tag-IR { - background-color: #0000FF22; -} -*/ - .unit-loadout-list { min-width: 0; } @@ -187,7 +165,65 @@ content: " (" attr(data-points) " points)"; } -.upper-bar svg>* { +#spawn-mode-tabs { + align-items: center; + column-gap: 6px; + display: flex; + position: absolute; + right: 0; + top:0; + translate: -6px -100%; + z-index: 9998; +} + +#spawn-mode-tabs button { + align-items: center; + border-bottom:2px solid transparent; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border-top-left-radius: var(--border-radius-sm); + border-top-right-radius: var(--border-radius-sm); + display: flex; + height:32px; + justify-content: center; + margin:0; + width:32px; +} + +#spawn-mode-tabs button:hover { + background-color: var(--background-steel); +} + +[data-coalition="blue"] + #spawn-mode-tabs button { + border-bottom-color: var(--primary-blue); +} + + +[data-coalition="red"] + #spawn-mode-tabs button { + border-bottom-color: var(--primary-red); +} + + +[data-coalition="neutral"] + #spawn-mode-tabs button { + border-bottom-color: var(--primary-neutral); +} + +#spawn-mode-tabs button svg { + height:24px; + margin:3px; + width:24px; +} + +.upper-bar { + align-items: center; + display: flex; + flex-direction: row; + justify-content: space-between; + padding-right: 0px; +} + +.upper-bar svg>*, +#spawn-mode-tabs button svg * { fill: white; } @@ -200,24 +236,52 @@ margin-left: auto; } +#spawn-history-menu { + display:flex; + flex-direction: column; + max-height: 300px; + row-gap: 6px; +} + +#spawn-history-menu button { + border-radius: 0; + height:32px; + width:100%; +} + +#spawn-history-menu button[data-spawned-coalition="blue"] { + border-left:4px solid var(--primary-blue); +} + +#spawn-history-menu button[data-spawned-coalition="red"] { + border-left:4px solid var(--primary-red); +} + +#spawn-history-menu button[data-spawned-coalition="neutral"] { + border-left:4px solid var(--primary-neutral); +} + [data-coalition="blue"]#active-coalition-label, [data-coalition="blue"].deploy-unit-button, [data-coalition="blue"]#spawn-airbase-aircraft-button, -[data-coalition="blue"].create-iads-button { +[data-coalition="blue"].create-iads-button, +[data-coalition="blue"] + .upper-bar .spawn-mode-tabs button.active { background-color: var(--primary-blue) } [data-coalition="red"]#active-coalition-label, [data-coalition="red"].deploy-unit-button, [data-coalition="red"]#spawn-airbase-aircraft-button, -[data-coalition="red"].create-iads-button { +[data-coalition="red"].create-iads-button, +[data-coalition="red"] + .upper-bar .spawn-mode-tabs button.active { background-color: var(--primary-red) } [data-coalition="neutral"]#active-coalition-label, [data-coalition="neutral"].deploy-unit-button, [data-coalition="neutral"]#spawn-airbase-aircraft-button, -[data-coalition="neutral"].create-iads-button { +[data-coalition="neutral"].create-iads-button, +[data-coalition="neutral"] + .upper-bar .spawn-mode-tabs button.active { background-color: var(--primary-neutral) } diff --git a/client/public/themes/olympus/images/buttons/other/arrow-down-solid.svg b/client/public/themes/olympus/images/buttons/other/arrow-down-solid.svg new file mode 100644 index 00000000..a31ed4b6 --- /dev/null +++ b/client/public/themes/olympus/images/buttons/other/arrow-down-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/public/themes/olympus/images/buttons/other/clock-rotate-left-solid.svg b/client/public/themes/olympus/images/buttons/other/clock-rotate-left-solid.svg new file mode 100644 index 00000000..50966792 --- /dev/null +++ b/client/public/themes/olympus/images/buttons/other/clock-rotate-left-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/src/contextmenus/mapcontextmenu.ts b/client/src/contextmenus/mapcontextmenu.ts index d7619c99..38ece85c 100644 --- a/client/src/contextmenus/mapcontextmenu.ts +++ b/client/src/contextmenus/mapcontextmenu.ts @@ -7,6 +7,7 @@ import { CoalitionArea } from "../map/coalitionarea/coalitionarea"; import { AirDefenceUnitSpawnMenu, AircraftSpawnMenu, GroundUnitSpawnMenu, HelicopterSpawnMenu, NavyUnitSpawnMenu } from "../controls/unitspawnmenu"; import { Airbase } from "../mission/airbase"; import { SmokeMarker } from "../map/markers/smokemarker"; +import { UnitSpawnTable } from "../interfaces"; /** 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. @@ -96,6 +97,8 @@ export class MapContextMenu extends ContextMenu { this.getContainer()?.addEventListener("hide", () => this.#airDefenceUnitSpawnMenu.clearCirclesPreviews()); this.getContainer()?.addEventListener("hide", () => this.#groundUnitSpawnMenu.clearCirclesPreviews()); this.getContainer()?.addEventListener("hide", () => this.#navyUnitSpawnMenu.clearCirclesPreviews()); + + this.#setupHistory(); } /** Show the contextmenu on top of the map, usually at the location where the user has clicked on it. @@ -257,4 +260,62 @@ export class MapContextMenu extends ContextMenu { this.#groundUnitSpawnMenu.setCountries(); this.#navyUnitSpawnMenu.setCountries(); } + + + /** Handles all of the logic for historal logging. + * + */ + #setupHistory() { + const spawnModes = this.getContainer()?.querySelectorAll(".spawn-mode"); + const activeCoalitionLabel = document.getElementById("active-coalition-label"); + this.getContainer()?.querySelectorAll(".spawn-mode-tab").forEach((btn:Element) => { + btn.addEventListener("click", (ev:MouseEventInit) => { + spawnModes?.forEach(div => div.classList.add("hide")); + + const prevSiblings = []; + let prev = btn.previousElementSibling; + + while ( prev ) { + prevSiblings.push(prev); + prev = prev.previousElementSibling; + } + + if (spawnModes && spawnModes[prevSiblings.length]) { + spawnModes[prevSiblings.length].classList.remove("hide"); + } + + if (activeCoalitionLabel) activeCoalitionLabel.classList.toggle("hide", !btn.hasAttribute("data-show-label")); + }); + }); + + const history = document.getElementById("spawn-history-menu"); + document.addEventListener( "unitSpawned", (ev:CustomEventInit) => { + const buttons = history.querySelectorAll("button"); + const detail:any = ev.detail; + if (buttons.length === 0) history.innerHTML = ""; // Take out any "no data" messages + const button = document.createElement("button"); + button.setAttribute("data-spawned-coalition", detail.coalition); + button.setAttribute("data-unit-type", detail.unitSpawnTable[0].unitType); + button.setAttribute("data-unit-qty", detail.unitSpawnTable.length); + button.innerHTML = `${detail.unitSpawnTable[0].unitType} (${detail.unitSpawnTable.length})`; + + // Remove a previous instance to save clogging up the list + const previous:any = [].slice.call(buttons).find( (button:Element) => ( + detail.coalition === button.getAttribute("data-spawned-coalition") && + detail.unitSpawnTable[0].unitType === button.getAttribute("data-unit-type") && + detail.unitSpawnTable.length === parseInt(button.getAttribute("data-unit-qty") || "-1"))); + + if (previous instanceof HTMLElement) previous.remove(); + + button.addEventListener("click", (ev:MouseEventInit) => { + detail.unitSpawnTable.forEach((table:UnitSpawnTable, i:number) => { + table.location = this.getLatLng(); // Set to new menu location + table.location.lat += 0.00015 * i; + }); + getApp().getUnitsManager().spawnUnits(detail.category, detail.unitSpawnTable, detail.coalition, detail.immediate, detail.airbase, detail.country); + }); + + history.prepend(button); + }); + } } \ No newline at end of file diff --git a/client/src/unit/unitsmanager.ts b/client/src/unit/unitsmanager.ts index da455dc1..28556b46 100644 --- a/client/src/unit/unitsmanager.ts +++ b/client/src/unit/unitsmanager.ts @@ -1427,6 +1427,16 @@ export class UnitsManager { if (spawnPoints <= getApp().getMissionManager().getAvailableSpawnPoints()) { getApp().getMissionManager().setSpentSpawnPoints(spawnPoints); spawnFunction(); + document.dispatchEvent( new CustomEvent( "unitSpawned", { + "detail": { + "airbase": airbase, + "category": category, + "coalition": coalition, + "country": country, + "immediate": immediate, + "unitSpawnTable": units + } + })); return true; } else { (getApp().getPopupsManager().get("infoPopup") as Popup).setText("Not enough spawn points available!"); diff --git a/client/views/contextmenus/map.ejs b/client/views/contextmenus/map.ejs index a3b87b49..4f375786 100644 --- a/client/views/contextmenus/map.ejs +++ b/client/views/contextmenus/map.ejs @@ -1,58 +1,71 @@
-
-
- - - - - - +
+ +
-
- - - - +
+

Spawn history

+
+

You do not have any units to show.

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