From 1c543666b5e105ade813b4ff0c2b6eccd8893b0e Mon Sep 17 00:00:00 2001 From: Dan Albert Date: Tue, 22 Feb 2022 19:37:43 -0800 Subject: [PATCH] Move unculled zones out of MapModel. --- game/server/eventstream/models.py | 2 ++ game/server/mapzones/models.py | 6 +++++ game/server/mapzones/routes.py | 16 ++++++++--- game/sim/gameupdateevents.py | 5 ++++ qt_ui/models.py | 7 +++-- qt_ui/widgets/map/model/mapmodel.py | 22 --------------- qt_ui/widgets/map/model/unculledzonejs.py | 33 ----------------------- resources/ui/map/map.js | 24 ++++++++++------- 8 files changed, 45 insertions(+), 70 deletions(-) delete mode 100644 qt_ui/widgets/map/model/unculledzonejs.py diff --git a/game/server/eventstream/models.py b/game/server/eventstream/models.py index e10532e7..3db18479 100644 --- a/game/server/eventstream/models.py +++ b/game/server/eventstream/models.py @@ -18,6 +18,7 @@ class GameUpdateEventsJs(BaseModel): new_combats: list[FrozenCombatJs] = [] updated_combats: list[FrozenCombatJs] = [] navmesh_updates: set[bool] = set() + unculled_zones_updated: bool = False @classmethod def from_events(cls, events: GameUpdateEvents, game: Game) -> GameUpdateEventsJs: @@ -33,4 +34,5 @@ class GameUpdateEventsJs(BaseModel): for c in events.updated_combats ], navmesh_updates=events.navmesh_updates, + unculled_zones_updated=events.unculled_zones_updated, ) diff --git a/game/server/mapzones/models.py b/game/server/mapzones/models.py index bef8f364..44c1b41d 100644 --- a/game/server/mapzones/models.py +++ b/game/server/mapzones/models.py @@ -1,5 +1,6 @@ from __future__ import annotations +from dcs.mapping import LatLng from pydantic import BaseModel from game.server.leaflet import LeafletPoly @@ -9,3 +10,8 @@ class MapZonesJs(BaseModel): inclusion: list[LeafletPoly] exclusion: list[LeafletPoly] sea: list[LeafletPoly] + + +class UnculledZoneJs(BaseModel): + position: LatLng + radius: float diff --git a/game/server/mapzones/routes.py b/game/server/mapzones/routes.py index c66ad007..96d608b9 100644 --- a/game/server/mapzones/routes.py +++ b/game/server/mapzones/routes.py @@ -2,14 +2,14 @@ from fastapi import APIRouter, Depends, HTTPException, status from game import Game from game.server import GameContext -from .models import MapZonesJs +from .models import MapZonesJs, UnculledZoneJs from ..leaflet import ShapelyUtil router: APIRouter = APIRouter(prefix="/map-zones") -@router.get("/") -def get(game: Game = Depends(GameContext.get)) -> MapZonesJs: +@router.get("/terrain") +def get_terrain(game: Game = Depends(GameContext.get)) -> MapZonesJs: zones = game.theater.landmap if zones is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND) @@ -19,3 +19,13 @@ def get(game: Game = Depends(GameContext.get)) -> MapZonesJs: exclusion=ShapelyUtil.polys_to_leaflet(zones.exclusion_zones, game.theater), sea=ShapelyUtil.polys_to_leaflet(zones.sea_zones, game.theater), ) + + +@router.get("/unculled") +def get_unculled_zones(game: Game = Depends(GameContext.get)) -> list[UnculledZoneJs]: + return [ + UnculledZoneJs( + position=zone.latlng(), radius=game.settings.perf_culling_distance * 1000 + ) + for zone in game.get_culling_zones() + ] diff --git a/game/sim/gameupdateevents.py b/game/sim/gameupdateevents.py index 7c49182e..0c7990f5 100644 --- a/game/sim/gameupdateevents.py +++ b/game/sim/gameupdateevents.py @@ -16,6 +16,7 @@ class GameUpdateEvents: self.updated_combats: list[FrozenCombat] = [] self.updated_flights: list[tuple[Flight, Point]] = [] self.navmesh_updates: set[bool] = set() + self.unculled_zones_updated: bool = False @property def empty(self) -> bool: @@ -26,6 +27,7 @@ class GameUpdateEvents: self.updated_combats, self.updated_flights, self.navmesh_updates, + self.unculled_zones_updated, ] ) @@ -43,3 +45,6 @@ class GameUpdateEvents: def update_navmesh(self, player: bool) -> None: self.navmesh_updates.add(player) + + def update_unculled_zones(self) -> None: + self.unculled_zones_updated = True diff --git a/qt_ui/models.py b/qt_ui/models.py index 28fddf03..5e7f82e2 100644 --- a/qt_ui/models.py +++ b/qt_ui/models.py @@ -16,12 +16,13 @@ from game.ato.airtaaskingorder import AirTaskingOrder from game.ato.flight import Flight from game.ato.flighttype import FlightType from game.ato.package import Package +from game.ato.traveltime import TotEstimator from game.game import Game +from game.server import EventStream from game.sim.gameupdateevents import GameUpdateEvents from game.squadrons.squadron import Pilot, Squadron from game.theater.missiontarget import MissionTarget from game.transfers import PendingTransfers, TransferOrder -from game.ato.traveltime import TotEstimator from qt_ui.simcontroller import SimController from qt_ui.uiconstants import AIRCRAFT_ICONS @@ -279,7 +280,9 @@ class AtoModel(QAbstractListModel): def on_packages_changed(self) -> None: if self.game is not None: self.game.compute_unculled_zones() - self.packages_changed.emit() + events = GameUpdateEvents() + events.update_unculled_zones() + EventStream.put_nowait(events) def package_at_index(self, index: QModelIndex) -> Package: """Returns the package at the given index.""" diff --git a/qt_ui/widgets/map/model/mapmodel.py b/qt_ui/widgets/map/model/mapmodel.py index 0099ffc1..37c071f0 100644 --- a/qt_ui/widgets/map/model/mapmodel.py +++ b/qt_ui/widgets/map/model/mapmodel.py @@ -23,7 +23,6 @@ from .groundobjectjs import GroundObjectJs from .supplyroutejs import SupplyRouteJs from .threatzonecontainerjs import ThreatZoneContainerJs from .threatzonesjs import ThreatZonesJs -from .unculledzonejs import UnculledZone # **EVERY PROPERTY NEEDS A NOTIFY SIGNAL** @@ -53,7 +52,6 @@ class MapModel(QObject): flightsChanged = Signal() frontLinesChanged = Signal() threatZonesChanged = Signal() - unculledZonesChanged = Signal() selectedFlightChanged = Signal(str) def __init__(self, game_model: GameModel) -> None: @@ -68,7 +66,6 @@ class MapModel(QObject): self._threat_zones = ThreatZoneContainerJs( ThreatZonesJs.empty(), ThreatZonesJs.empty() ) - self._unculled_zones = [] self._selected_flight_index: Optional[Tuple[int, int]] = None GameUpdateSignal.get_instance().game_loaded.connect(self.on_game_load) @@ -79,12 +76,6 @@ class MapModel(QObject): GameUpdateSignal.get_instance().flight_selection_changed.connect( self.set_flight_selection ) - self.game_model.ato_model_for(True).packages_changed.connect( - self.on_package_change - ), - self.game_model.ato_model_for(False).packages_changed.connect( - self.on_package_change - ), self.reset() def clear(self) -> None: @@ -96,7 +87,6 @@ class MapModel(QObject): self._threat_zones = ThreatZoneContainerJs( ThreatZonesJs.empty(), ThreatZonesJs.empty() ) - self._unculled_zones = [] self.cleared.emit() def set_package_selection(self, index: int) -> None: @@ -160,7 +150,6 @@ class MapModel(QObject): self.reset_atos() self.reset_front_lines() self.reset_threat_zones() - self.reset_unculled_zones() def on_game_load(self, game: Optional[Game]) -> None: if game is not None: @@ -292,17 +281,6 @@ class MapModel(QObject): def threatZones(self) -> ThreatZoneContainerJs: return self._threat_zones - def on_package_change(self) -> None: - self.reset_unculled_zones() - - def reset_unculled_zones(self) -> None: - self._unculled_zones = list(UnculledZone.each_from_game(self.game)) - self.unculledZonesChanged.emit() - - @Property(list, notify=unculledZonesChanged) - def unculledZones(self) -> list[UnculledZone]: - return self._unculled_zones - @property def game(self) -> Game: if self.game_model.game is None: diff --git a/qt_ui/widgets/map/model/unculledzonejs.py b/qt_ui/widgets/map/model/unculledzonejs.py deleted file mode 100644 index a7a26455..00000000 --- a/qt_ui/widgets/map/model/unculledzonejs.py +++ /dev/null @@ -1,33 +0,0 @@ -from __future__ import annotations - -from typing import Iterator - -from PySide2.QtCore import Property, QObject, Signal - -from game import Game -from game.server.leaflet import LeafletLatLon - - -class UnculledZone(QObject): - positionChanged = Signal() - radiusChanged = Signal() - - def __init__(self, position: LeafletLatLon, radius: float) -> None: - super().__init__() - self._position = position - self._radius = radius - - @Property(list, notify=positionChanged) - def position(self) -> LeafletLatLon: - return self._position - - @Property(float, notify=radiusChanged) - def radius(self) -> float: - return self._radius - - @classmethod - def each_from_game(cls, game: Game) -> Iterator[UnculledZone]: - for zone in game.get_culling_zones(): - yield UnculledZone( - zone.latlng().as_list(), game.settings.perf_culling_distance * 1000 - ) diff --git a/resources/ui/map/map.js b/resources/ui/map/map.js index 3ce9626b..ca208194 100644 --- a/resources/ui/map/map.js +++ b/resources/ui/map/map.js @@ -385,7 +385,6 @@ new QWebChannel(qt.webChannelTransport, function (channel) { game.flightsChanged.connect(drawAircraft); game.threatZonesChanged.connect(drawThreatZones); game.mapZonesChanged.connect(drawMapZones); - game.unculledZonesChanged.connect(drawUnculledZones); game.selectedFlightChanged.connect(updateSelectedFlight); }); @@ -402,6 +401,9 @@ function handleStreamedEvents(events) { for (const player of events.navmesh_updates) { drawNavmesh(player); } + if (events.unculled_zones_updated) { + drawUnculledZones(); + } } function recenterMap(center) { @@ -1124,7 +1126,7 @@ function drawMapZones() { inclusionZones.clearLayers(); exclusionZones.clearLayers(); - getJson("/map-zones").then((zones) => { + getJson("/map-zones/terrain").then((zones) => { for (const zone of zones.sea) { L.polygon(zone, { color: "#344455", @@ -1157,14 +1159,16 @@ function drawMapZones() { function drawUnculledZones() { unculledZones.clearLayers(); - for (const zone of game.unculledZones) { - L.circle(zone.position, { - radius: zone.radius, - color: "#b4ff8c", - fill: false, - interactive: false, - }).addTo(unculledZones); - } + getJson("/map-zones/unculled").then((zones) => { + for (const zone of zones) { + L.circle(zone.position, { + radius: zone.radius, + color: "#b4ff8c", + fill: false, + interactive: false, + }).addTo(unculledZones); + } + }); } function drawIpZones(id) {