From d73ceb374c66f01fad5b275a626418df1e3a8309 Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Thu, 13 May 2021 01:48:12 -0700 Subject: [PATCH] Add front lines to new map UI. Only shows an approximate front line. Still need support for "actual". --- qt_ui/widgets/map/mapmodel.py | 56 ++++++++++++++++++++++++++++++----- resources/ui/map/map.js | 17 ++++++++++- 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/qt_ui/widgets/map/mapmodel.py b/qt_ui/widgets/map/mapmodel.py index 24e5e317..4d2800d0 100644 --- a/qt_ui/widgets/map/mapmodel.py +++ b/qt_ui/widgets/map/mapmodel.py @@ -4,8 +4,8 @@ from typing import List, Optional, Tuple from PySide2.QtCore import Property, QObject, Signal, Slot from dcs import Point -from dcs.vehicles import vehicle_map from dcs.unit import Unit +from dcs.vehicles import vehicle_map from game import Game, db from game.profiling import logged_duration @@ -13,8 +13,9 @@ from game.theater import ( ConflictTheater, ControlPoint, TheaterGroundObject, + FrontLine, ) -from game.utils import meters +from game.utils import meters, nautical_miles from gen.ato import AirTaskingOrder from gen.flights.flight import Flight, FlightWaypoint, FlightWaypointType from gen.flights.flightplan import FlightPlan @@ -190,6 +191,31 @@ class SupplyRouteJs(QObject): return self.control_point_a.captured +class FrontLineJs(QObject): + def __init__(self, front_line: FrontLine, theater: ConflictTheater) -> None: + super().__init__() + self.front_line = front_line + self.theater = theater + + @Property(list) + def extents(self) -> List[LeafletLatLon]: + a = self.theater.point_to_ll( + self.front_line.position.point_from_heading( + self.front_line.attack_heading + 90, nautical_miles(2).meters + ) + ) + b = self.theater.point_to_ll( + self.front_line.position.point_from_heading( + self.front_line.attack_heading + 270, nautical_miles(2).meters + ) + ) + return [[a.latitude, a.longitude], [b.latitude, b.longitude]] + + @Slot() + def showPackageDialog(self) -> None: + Dialog.open_new_package_dialog(self.front_line) + + class WaypointJs(QObject): def __init__( self, @@ -289,6 +315,7 @@ class MapModel(QObject): groundObjectsChanged = Signal() supplyRoutesChanged = Signal() flightsChanged = Signal() + frontLinesChanged = Signal() def __init__(self, game_model: GameModel) -> None: super().__init__() @@ -298,6 +325,7 @@ class MapModel(QObject): self._ground_objects = [] self._supply_routes = [] self._flights = [] + self._front_lines = [] self._selected_flight_index: Optional[Tuple[int, int]] = None GameUpdateSignal.get_instance().game_loaded.connect(self.on_game_load) GameUpdateSignal.get_instance().flight_paths_changed.connect(self.reset_atos) @@ -309,6 +337,14 @@ class MapModel(QObject): ) self.reset() + def clear(self) -> None: + self._control_points = [] + self._supply_routes = [] + self._ground_objects = [] + self._flights = [] + self._front_lines = [] + self.cleared.emit() + def set_package_selection(self, index: int) -> None: # Optional[int] isn't a valid type for a Qt signal. None will be converted to # zero automatically. We use -1 to indicate no selection. @@ -349,6 +385,7 @@ class MapModel(QObject): self.reset_ground_objects() self.reset_routes() self.reset_atos() + self.reset_front_lines() def on_game_load(self, game: Optional[Game]) -> None: if game is not None: @@ -453,12 +490,15 @@ class MapModel(QObject): def supplyRoutes(self) -> List[SupplyRouteJs]: return self._supply_routes - def clear(self) -> None: - self._control_points = [] - self._supply_routes = [] - self._ground_objects = [] - self._flights = [] - self.cleared.emit() + def reset_front_lines(self) -> None: + self._front_lines = [ + FrontLineJs(f, self.game.theater) for f in self.game.theater.conflicts() + ] + self.frontLinesChanged.emit() + + @Property(list, notify=frontLinesChanged) + def frontLines(self) -> List[FrontLineJs]: + return self._front_lines @property def game(self) -> Game: diff --git a/resources/ui/map/map.js b/resources/ui/map/map.js index bbc08a86..da054f79 100644 --- a/resources/ui/map/map.js +++ b/resources/ui/map/map.js @@ -9,7 +9,7 @@ * - Exclusion zones * - Commit ranges * - Supply route status - * - Front line + * - "Actual" front line * - Debug flight plan drawing * - Icon variety */ @@ -35,6 +35,7 @@ defaultBaseMap.addTo(map); var controlPointsLayer = L.layerGroup().addTo(map); var groundObjectsLayer = L.markerClusterGroup().addTo(map); var supplyRoutesLayer = L.layerGroup().addTo(map); +var frontLinesLayer = L.layerGroup().addTo(map); var redSamThreatLayer = L.layerGroup().addTo(map); var blueFlightPlansLayer = L.layerGroup().addTo(map); @@ -53,6 +54,7 @@ L.control "Control points": controlPointsLayer, "Ground objects": groundObjectsLayer, "Supply routes": supplyRoutesLayer, + "Front lines": frontLinesLayer, }, "Air Defenses": { "Ally SAM threat range": blueSamThreatLayer, @@ -102,6 +104,7 @@ new QWebChannel(qt.webChannelTransport, function (channel) { game.controlPointsChanged.connect(drawControlPoints); game.groundObjectsChanged.connect(drawGroundObjects); game.supplyRoutesChanged.connect(drawSupplyRoutes); + game.frontLinesChanged.connect(drawFrontLines); game.flightsChanged.connect(drawFlightPlans); }); @@ -200,6 +203,17 @@ function drawSupplyRoutes() { }); } +function drawFrontLines() { + frontLinesLayer.clearLayers(); + game.frontLines.forEach((front) => { + L.polyline(front.extents, { weight: 8, color: "#fe7d0a" }) + .on("contextmenu", function () { + front.showPackageDialog(); + }) + .addTo(frontLinesLayer); + }); +} + const SHOW_WAYPOINT_INFO_AT_ZOOM = 9; function drawFlightPlan(flight) { @@ -264,6 +278,7 @@ function drawInitialMap() { drawControlPoints(); drawGroundObjects(); drawSupplyRoutes(); + drawFrontLines(); drawFlightPlans(); }