Add waypoint info tooltip to the new map.

This commit is contained in:
Dan Albert 2021-05-12 23:03:53 -07:00
parent d9d68cd37c
commit 4e498e6932
2 changed files with 91 additions and 14 deletions

View File

@ -1,4 +1,5 @@
import logging import logging
from datetime import timedelta
from typing import List, Optional, Tuple from typing import List, Optional, Tuple
from PySide2.QtCore import Property, QObject, Signal, Slot from PySide2.QtCore import Property, QObject, Signal, Slot
@ -11,8 +12,10 @@ from game.theater import (
ControlPoint, ControlPoint,
TheaterGroundObject, TheaterGroundObject,
) )
from game.utils import meters
from gen.ato import AirTaskingOrder from gen.ato import AirTaskingOrder
from gen.flights.flight import Flight, FlightWaypoint from gen.flights.flight import Flight, FlightWaypoint, FlightWaypointType
from gen.flights.flightplan import FlightPlan
from qt_ui.models import GameModel from qt_ui.models import GameModel
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
from qt_ui.windows.basemenu.QBaseMenu2 import QBaseMenu2 from qt_ui.windows.basemenu.QBaseMenu2 import QBaseMenu2
@ -102,16 +105,55 @@ class SupplyRouteJs(QObject):
class WaypointJs(QObject): class WaypointJs(QObject):
def __init__(self, waypoint: FlightWaypoint, theater: ConflictTheater) -> None: def __init__(
self,
waypoint: FlightWaypoint,
number: int,
flight_plan: FlightPlan,
theater: ConflictTheater,
) -> None:
super().__init__() super().__init__()
self.waypoint = waypoint self.waypoint = waypoint
self._number = number
self.flight_plan = flight_plan
self.theater = theater self.theater = theater
@Property(int)
def number(self) -> int:
return self._number
@Property(list) @Property(list)
def position(self) -> LeafletLatLon: def position(self) -> LeafletLatLon:
ll = self.theater.point_to_ll(self.waypoint.position) ll = self.theater.point_to_ll(self.waypoint.position)
return [ll.latitude, ll.longitude] return [ll.latitude, ll.longitude]
@Property(int)
def altitudeFt(self) -> int:
return int(self.waypoint.alt.feet)
@Property(str)
def altitudeReference(self) -> str:
return "AGL" if self.waypoint.alt_type == "RADIO" else "MSL"
@Property(str)
def name(self) -> str:
return self.waypoint.name
@Property(str)
def timing(self) -> str:
prefix = "TOT"
time = self.flight_plan.tot_for_waypoint(self.waypoint)
if time is None:
prefix = "Depart"
time = self.flight_plan.depart_time_for_waypoint(self.waypoint)
if time is None:
return ""
return f"{prefix} T+{timedelta(seconds=int(time.total_seconds()))}"
@Property(bool)
def isDivert(self) -> bool:
return self.waypoint.waypoint_type is FlightWaypointType.DIVERT
class FlightJs(QObject): class FlightJs(QObject):
flightPlanChanged = Signal() flightPlanChanged = Signal()
@ -127,7 +169,17 @@ class FlightJs(QObject):
self.reset_waypoints() self.reset_waypoints()
def reset_waypoints(self) -> None: def reset_waypoints(self) -> None:
self._waypoints = [WaypointJs(p, self.theater) for p in self.flight.points] departure = FlightWaypoint(
FlightWaypointType.TAKEOFF,
self.flight.departure.position.x,
self.flight.departure.position.y,
meters(0),
)
departure.alt_type = "RADIO"
self._waypoints = [
WaypointJs(p, i, self.flight.flight_plan, self.theater)
for i, p in enumerate([departure] + self.flight.points)
]
self.flightPlanChanged.emit() self.flightPlanChanged.emit()
@Property(list, notify=flightPlanChanged) @Property(list, notify=flightPlanChanged)

View File

@ -8,7 +8,6 @@
* - Time of day/weather themeing * - Time of day/weather themeing
* - Exclusion zones * - Exclusion zones
* - Commit ranges * - Commit ranges
* - Waypoint info
* - Supply route status * - Supply route status
* - Front line * - Front line
* - Debug flight plan drawing * - Debug flight plan drawing
@ -61,7 +60,7 @@ L.control
"Enemy SAM detection range": redSamDetectionLayer, "Enemy SAM detection range": redSamDetectionLayer,
}, },
"Flight Plans": { "Flight Plans": {
"Hide": L.layerGroup(), Hide: L.layerGroup(),
"Show selected blue": selectedFlightPlansLayer, "Show selected blue": selectedFlightPlansLayer,
"Show all blue": blueFlightPlansLayer, "Show all blue": blueFlightPlansLayer,
"Show all red": redFlightPlansLayer, "Show all red": redFlightPlansLayer,
@ -178,19 +177,32 @@ function drawFlightPlan(flight) {
var layer = flight.blue ? blueFlightPlansLayer : redFlightPlansLayer; var layer = flight.blue ? blueFlightPlansLayer : redFlightPlansLayer;
var color = flight.blue ? Colors.Blue : Colors.Red; var color = flight.blue ? Colors.Blue : Colors.Red;
var highlight = "#ffff00"; var highlight = "#ffff00";
var points = []; // We don't need a marker for the departure waypoint (and it's likely
flight.flightPlan.forEach((waypoint) => { // coincident with the landing waypoint, so hard to see). We do want to draw
points.push(waypoint.position); // the path from it though.
L.circle(waypoint.position, { radius: 50, color: color }).addTo(layer); var points = [flight.flightPlan[0].position];
flight.flightPlan.slice(1).forEach((waypoint) => {
if (!waypoint.isDivert) {
points.push(waypoint.position);
}
if (flight.selected) { if (flight.selected) {
L.circle(waypoint.position, { radius: 50, color: highlight }).addTo( L.marker(waypoint.position)
selectedFlightPlansLayer .bindTooltip(
); `${waypoint.number} ${waypoint.name}<br />` +
`${waypoint.altitudeFt} ft ${waypoint.altitudeReference}<br />` +
`${waypoint.timing}`,
{ permanent: true }
)
.addTo(layer)
.addTo(selectedFlightPlansLayer);
} }
}); });
L.polyline(points, { color: color }).addTo(layer);
if (flight.selected) { if (flight.selected) {
L.polyline(points, { color: highlight }).addTo(selectedFlightPlansLayer); L.polyline(points, { color: highlight }).addTo(selectedFlightPlansLayer);
L.polyline(points, { color: highlight }).addTo(layer);
} else {
L.polyline(points, { color: color }).addTo(layer);
} }
} }
@ -198,9 +210,22 @@ function drawFlightPlans() {
blueFlightPlansLayer.clearLayers(); blueFlightPlansLayer.clearLayers();
redFlightPlansLayer.clearLayers(); redFlightPlansLayer.clearLayers();
selectedFlightPlansLayer.clearLayers(); selectedFlightPlansLayer.clearLayers();
var selected = null;
game.flights.forEach((flight) => { game.flights.forEach((flight) => {
drawFlightPlan(flight); // Draw the selected waypoint last so it's on top. bringToFront only brings
// it to the front of the *extant* elements, so any flights drawn later will
// be drawn on top. We could fight with manual Z-indexes but leaflet does a
// lot of that automatically so it'd be error prone.
if (flight.selected) {
selected = flight;
} else {
drawFlightPlan(flight);
}
}); });
if (selected != null) {
drawFlightPlan(selected);
}
} }
function drawInitialMap() { function drawInitialMap() {