mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Update the UI to show sim state.
https://github.com/dcs-liberation/dcs_liberation/issues/1704
This commit is contained in:
parent
87bf3110c8
commit
03430a4df5
@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Callable, TYPE_CHECKING
|
||||
|
||||
@ -22,6 +23,10 @@ class GameLoop:
|
||||
self.started = False
|
||||
self.completed = False
|
||||
|
||||
@property
|
||||
def current_time_in_sim(self) -> datetime:
|
||||
return self.sim.time
|
||||
|
||||
def start(self) -> None:
|
||||
if self.started:
|
||||
raise RuntimeError("Cannot start game loop because it has already started")
|
||||
@ -67,7 +72,5 @@ class GameLoop:
|
||||
self.pause()
|
||||
logging.info(f"Simulation completed at {self.sim.time}")
|
||||
self.on_complete()
|
||||
else:
|
||||
logging.info(f"Simulation continued at {self.sim.time}")
|
||||
except SimulationAlreadyCompletedError:
|
||||
logging.exception("Attempted to tick already completed sim")
|
||||
|
||||
@ -32,6 +32,7 @@ class MissionSimulation:
|
||||
self.time = self.game.conditions.start_time
|
||||
|
||||
def begin_simulation(self) -> None:
|
||||
self.time = self.game.conditions.start_time
|
||||
self.aircraft_simulation.begin_simulation()
|
||||
|
||||
def tick(self) -> bool:
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Callable, Optional, TYPE_CHECKING
|
||||
|
||||
from PySide2.QtCore import QObject, Signal
|
||||
|
||||
from game.polldebriefingfilethread import PollDebriefingFileThread
|
||||
from game.sim.gameloop import GameLoop
|
||||
from game.sim.simspeedsetting import SimSpeedSetting
|
||||
from game.polldebriefingfilethread import PollDebriefingFileThread
|
||||
from qt_ui.simupdatethread import SimUpdateThread
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from game import Game
|
||||
@ -16,6 +18,7 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
class SimController(QObject):
|
||||
sim_update = Signal()
|
||||
sim_speed_reset = Signal(SimSpeedSetting)
|
||||
simulation_complete = Signal()
|
||||
|
||||
@ -24,18 +27,28 @@ class SimController(QObject):
|
||||
self.game_loop: Optional[GameLoop] = None
|
||||
self.recreate_game_loop(game)
|
||||
self.started = False
|
||||
self._sim_update_thread = SimUpdateThread(self.sim_update.emit)
|
||||
self._sim_update_thread.start()
|
||||
|
||||
@property
|
||||
def completed(self) -> bool:
|
||||
return self.game_loop.completed
|
||||
|
||||
@property
|
||||
def current_time_in_sim(self) -> Optional[datetime]:
|
||||
if self.game_loop is None:
|
||||
return None
|
||||
return self.game_loop.current_time_in_sim
|
||||
|
||||
def set_game(self, game: Optional[Game]) -> None:
|
||||
self.recreate_game_loop(game)
|
||||
self.sim_speed_reset.emit(SimSpeedSetting.PAUSED)
|
||||
|
||||
def recreate_game_loop(self, game: Optional[Game]) -> None:
|
||||
if self.game_loop is not None:
|
||||
self._sim_update_thread.on_sim_pause()
|
||||
self.game_loop.pause()
|
||||
self.game_loop = None
|
||||
if game is not None:
|
||||
self.game_loop = GameLoop(game, self.on_simulation_complete)
|
||||
self.started = False
|
||||
@ -48,11 +61,17 @@ class SimController(QObject):
|
||||
self.game_loop.start()
|
||||
self.started = True
|
||||
self.game_loop.set_simulation_speed(simulation_speed)
|
||||
if simulation_speed is SimSpeedSetting.PAUSED:
|
||||
self._sim_update_thread.on_sim_pause()
|
||||
else:
|
||||
self._sim_update_thread.on_sim_unpause()
|
||||
|
||||
def run_to_first_contact(self) -> None:
|
||||
self.game_loop.run_to_first_contact()
|
||||
self.sim_update.emit()
|
||||
|
||||
def generate_miz(self, output: Path) -> None:
|
||||
self._sim_update_thread.on_sim_pause()
|
||||
self.game_loop.pause_and_generate_miz(output)
|
||||
|
||||
def wait_for_debriefing(
|
||||
@ -65,11 +84,14 @@ class SimController(QObject):
|
||||
def debrief_current_state(
|
||||
self, state_path: Path, force_end: bool = False
|
||||
) -> Debriefing:
|
||||
self._sim_update_thread.on_sim_pause()
|
||||
return self.game_loop.pause_and_debrief(state_path, force_end)
|
||||
|
||||
def process_results(self, debriefing: Debriefing) -> None:
|
||||
self._sim_update_thread.on_sim_pause()
|
||||
return self.game_loop.complete_with_results(debriefing)
|
||||
|
||||
def on_simulation_complete(self) -> None:
|
||||
logging.debug("Simulation complete")
|
||||
self._sim_update_thread.on_sim_pause()
|
||||
self.simulation_complete.emit()
|
||||
|
||||
45
qt_ui/simupdatethread.py
Normal file
45
qt_ui/simupdatethread.py
Normal file
@ -0,0 +1,45 @@
|
||||
from threading import Event, Thread, Timer
|
||||
from typing import Callable
|
||||
|
||||
|
||||
class SimUpdateThread(Thread):
|
||||
def __init__(self, update_callback: Callable[[], None]) -> None:
|
||||
super().__init__()
|
||||
self.update_callback = update_callback
|
||||
self.running = False
|
||||
self.should_shutdown = False
|
||||
self._interrupt = Event()
|
||||
self._timer = self._make_timer()
|
||||
|
||||
def run(self) -> None:
|
||||
while True:
|
||||
self._interrupt.wait()
|
||||
self._interrupt.clear()
|
||||
if self.should_shutdown:
|
||||
return
|
||||
if self.running:
|
||||
self.update_callback()
|
||||
self._timer = self._make_timer()
|
||||
self._timer.start()
|
||||
|
||||
def on_sim_pause(self) -> None:
|
||||
self._timer.cancel()
|
||||
self._timer = self._make_timer()
|
||||
self.running = False
|
||||
|
||||
def on_sim_unpause(self) -> None:
|
||||
if not self.running:
|
||||
self.running = True
|
||||
self._timer.start()
|
||||
|
||||
def stop(self) -> None:
|
||||
self.should_shutdown = True
|
||||
self._interrupt.set()
|
||||
|
||||
def on_timer_elapsed(self) -> None:
|
||||
self._timer = self._make_timer()
|
||||
self._timer.start()
|
||||
self._interrupt.set()
|
||||
|
||||
def _make_timer(self) -> Timer:
|
||||
return Timer(1 / 60, lambda: self._interrupt.set())
|
||||
@ -1,3 +1,5 @@
|
||||
from datetime import datetime
|
||||
|
||||
from PySide2.QtGui import QPixmap
|
||||
from PySide2.QtWidgets import (
|
||||
QFrame,
|
||||
@ -12,6 +14,7 @@ from dcs.weather import CloudPreset, Weather as PydcsWeather
|
||||
import qt_ui.uiconstants as CONST
|
||||
from game.utils import mps
|
||||
from game.weather import Conditions, TimeOfDay
|
||||
from qt_ui.simcontroller import SimController
|
||||
|
||||
|
||||
class QTimeTurnWidget(QGroupBox):
|
||||
@ -19,8 +22,9 @@ class QTimeTurnWidget(QGroupBox):
|
||||
UI Component to display current turn and time info
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, sim_controller: SimController) -> None:
|
||||
super(QTimeTurnWidget, self).__init__("Turn")
|
||||
self.sim_controller = sim_controller
|
||||
self.setStyleSheet(
|
||||
"padding: 0px; margin-left: 5px; margin-right: 0px; margin-top: 1ex; margin-bottom: 5px; border-right: 0px"
|
||||
)
|
||||
@ -49,17 +53,30 @@ class QTimeTurnWidget(QGroupBox):
|
||||
self.time_display = QLabel()
|
||||
self.time_column.addWidget(self.time_display)
|
||||
|
||||
def setCurrentTurn(self, turn: int, conditions: Conditions) -> None:
|
||||
sim_controller.sim_update.connect(self.on_sim_update)
|
||||
|
||||
def on_sim_update(self) -> None:
|
||||
time = self.sim_controller.current_time_in_sim
|
||||
if time is None:
|
||||
self.date_display.setText("")
|
||||
self.time_display.setText("")
|
||||
else:
|
||||
self.set_date_and_time(time)
|
||||
|
||||
def set_current_turn(self, turn: int, conditions: Conditions) -> None:
|
||||
"""Sets the turn information display.
|
||||
|
||||
:arg turn Current turn number.
|
||||
:arg conditions Current time and weather conditions.
|
||||
"""
|
||||
self.daytime_icon.setPixmap(self.icons[conditions.time_of_day])
|
||||
self.date_display.setText(conditions.start_time.strftime("%d %b %Y"))
|
||||
self.time_display.setText(conditions.start_time.strftime("%H:%M:%S Local"))
|
||||
self.set_date_and_time(conditions.start_time)
|
||||
self.setTitle(f"Turn {turn}")
|
||||
|
||||
def set_date_and_time(self, time: datetime) -> None:
|
||||
self.date_display.setText(time.strftime("%d %b %Y"))
|
||||
self.time_display.setText(time.strftime("%H:%M:%S Local"))
|
||||
|
||||
|
||||
class QWeatherWidget(QGroupBox):
|
||||
"""
|
||||
@ -265,7 +282,7 @@ class QConditionsWidget(QFrame):
|
||||
UI Component to display Turn Number, Day Time & Hour and weather combined.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, sim_controller: SimController) -> None:
|
||||
super(QConditionsWidget, self).__init__()
|
||||
self.setProperty("style", "QConditionsWidget")
|
||||
|
||||
@ -275,7 +292,7 @@ class QConditionsWidget(QFrame):
|
||||
self.layout.setVerticalSpacing(0)
|
||||
self.setLayout(self.layout)
|
||||
|
||||
self.time_turn_widget = QTimeTurnWidget()
|
||||
self.time_turn_widget = QTimeTurnWidget(sim_controller)
|
||||
self.time_turn_widget.setStyleSheet("QGroupBox { margin-right: 0px; }")
|
||||
self.layout.addWidget(self.time_turn_widget, 0, 0)
|
||||
|
||||
@ -292,6 +309,6 @@ class QConditionsWidget(QFrame):
|
||||
:arg turn Current turn number.
|
||||
:arg conditions Current time and weather conditions.
|
||||
"""
|
||||
self.time_turn_widget.setCurrentTurn(turn, conditions)
|
||||
self.time_turn_widget.set_current_turn(turn, conditions)
|
||||
self.weather_widget.setCurrentTurn(turn, conditions)
|
||||
self.weather_widget.show()
|
||||
|
||||
@ -38,7 +38,7 @@ class QTopPanel(QFrame):
|
||||
|
||||
self.setMaximumHeight(70)
|
||||
|
||||
self.conditionsWidget = QConditionsWidget()
|
||||
self.conditionsWidget = QConditionsWidget(sim_controller)
|
||||
self.budgetBox = QBudgetBox(self.game)
|
||||
|
||||
pass_turn_text = "Pass Turn"
|
||||
|
||||
@ -15,6 +15,7 @@ from PySide2.QtWebEngineWidgets import (
|
||||
|
||||
from game import Game
|
||||
from qt_ui.models import GameModel
|
||||
from qt_ui.simcontroller import SimController
|
||||
from qt_ui.widgets.map.mapmodel import MapModel
|
||||
|
||||
|
||||
@ -35,11 +36,13 @@ class LoggingWebPage(QWebEnginePage):
|
||||
|
||||
|
||||
class QLiberationMap(QWebEngineView):
|
||||
def __init__(self, game_model: GameModel, parent) -> None:
|
||||
def __init__(
|
||||
self, game_model: GameModel, sim_controller: SimController, parent
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
self.game_model = game_model
|
||||
self.setMinimumSize(800, 600)
|
||||
self.map_model = MapModel(game_model)
|
||||
self.map_model = MapModel(game_model, sim_controller)
|
||||
|
||||
self.channel = QWebChannel()
|
||||
self.channel.registerObject("game", self.map_model)
|
||||
|
||||
@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
from typing import List, Optional, Tuple, Union, Iterator
|
||||
from typing import Iterator, List, Optional, Tuple, Union
|
||||
|
||||
from PySide2.QtCore import Property, QObject, Signal, Slot
|
||||
from dcs import Point
|
||||
@ -10,40 +10,38 @@ from dcs.unit import Unit
|
||||
from dcs.vehicles import vehicle_map
|
||||
from shapely.geometry import (
|
||||
LineString,
|
||||
MultiLineString,
|
||||
MultiPolygon,
|
||||
Point as ShapelyPoint,
|
||||
Polygon,
|
||||
MultiPolygon,
|
||||
MultiLineString,
|
||||
)
|
||||
|
||||
from game import Game
|
||||
from game.ato.airtaaskingorder import AirTaskingOrder
|
||||
from game.ato.flight import Flight
|
||||
from game.ato.flightstate import InFlight
|
||||
from game.ato.flightwaypoint import FlightWaypoint
|
||||
from game.ato.flightwaypointtype import FlightWaypointType
|
||||
from game.dcs.groundunittype import GroundUnitType
|
||||
from game.flightplan import JoinZoneGeometry, HoldZoneGeometry
|
||||
from game.flightplan import HoldZoneGeometry, JoinZoneGeometry
|
||||
from game.flightplan.ipzonegeometry import IpZoneGeometry
|
||||
from game.navmesh import NavMesh, NavMeshPoly
|
||||
from game.profiling import logged_duration
|
||||
from game.theater import (
|
||||
ConflictTheater,
|
||||
ControlPoint,
|
||||
TheaterGroundObject,
|
||||
ControlPointStatus,
|
||||
FrontLine,
|
||||
LatLon,
|
||||
ControlPointStatus,
|
||||
TheaterGroundObject,
|
||||
)
|
||||
from game.threatzones import ThreatZones
|
||||
from game.transfers import MultiGroupTransport, TransportMap
|
||||
from game.utils import meters, nautical_miles
|
||||
from game.ato.airtaaskingorder import AirTaskingOrder
|
||||
from game.ato.flightwaypointtype import FlightWaypointType
|
||||
from game.ato.flightwaypoint import FlightWaypoint
|
||||
from game.ato.flight import Flight
|
||||
from gen.flights.flightplan import (
|
||||
FlightPlan,
|
||||
PatrollingFlightPlan,
|
||||
CasFlightPlan,
|
||||
)
|
||||
from game.flightplan.ipzonegeometry import IpZoneGeometry
|
||||
from gen.flights.flightplan import CasFlightPlan, FlightPlan, PatrollingFlightPlan
|
||||
from qt_ui.dialogs import Dialog
|
||||
from qt_ui.models import GameModel, AtoModel
|
||||
from qt_ui.models import AtoModel, GameModel
|
||||
from qt_ui.simcontroller import SimController
|
||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||
from qt_ui.windows.basemenu.QBaseMenu2 import QBaseMenu2
|
||||
from qt_ui.windows.groundobject.QGroundObjectMenu import QGroundObjectMenu
|
||||
@ -537,6 +535,7 @@ class WaypointJs(QObject):
|
||||
|
||||
|
||||
class FlightJs(QObject):
|
||||
positionChanged = Signal()
|
||||
flightPlanChanged = Signal()
|
||||
blueChanged = Signal()
|
||||
selectedChanged = Signal()
|
||||
@ -588,6 +587,13 @@ class FlightJs(QObject):
|
||||
waypoints.append(waypoint)
|
||||
return waypoints
|
||||
|
||||
@Property(list, notify=positionChanged)
|
||||
def position(self) -> LeafletLatLon:
|
||||
if isinstance(self.flight.state, InFlight):
|
||||
ll = self.theater.point_to_ll(self.flight.state.estimate_position())
|
||||
return [ll.latitude, ll.longitude]
|
||||
return []
|
||||
|
||||
@Property(list, notify=flightPlanChanged)
|
||||
def flightPlan(self) -> List[WaypointJs]:
|
||||
return self._waypoints
|
||||
@ -1032,7 +1038,7 @@ class MapModel(QObject):
|
||||
joinZonesChanged = Signal()
|
||||
holdZonesChanged = Signal()
|
||||
|
||||
def __init__(self, game_model: GameModel) -> None:
|
||||
def __init__(self, game_model: GameModel, sim_controller: SimController) -> None:
|
||||
super().__init__()
|
||||
self.game_model = game_model
|
||||
self._map_center = [0, 0]
|
||||
@ -1059,6 +1065,7 @@ class MapModel(QObject):
|
||||
GameUpdateSignal.get_instance().flight_selection_changed.connect(
|
||||
self.set_flight_selection
|
||||
)
|
||||
sim_controller.sim_update.connect(self.on_sim_update)
|
||||
self.reset()
|
||||
|
||||
def clear(self) -> None:
|
||||
@ -1076,6 +1083,10 @@ class MapModel(QObject):
|
||||
self._ip_zones = IpZonesJs.empty()
|
||||
self.cleared.emit()
|
||||
|
||||
def on_sim_update(self) -> None:
|
||||
for flight in self._flights:
|
||||
flight.positionChanged.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.
|
||||
|
||||
@ -54,7 +54,7 @@ class QLiberationWindow(QMainWindow):
|
||||
self.sim_controller = SimController(self.game)
|
||||
self.ato_panel = QAirTaskingOrderPanel(self.game_model)
|
||||
self.info_panel = QInfoPanel(self.game)
|
||||
self.liberation_map = QLiberationMap(self.game_model, self)
|
||||
self.liberation_map = QLiberationMap(self.game_model, self.sim_controller, self)
|
||||
|
||||
self.setGeometry(300, 100, 270, 100)
|
||||
self.updateWindowTitle()
|
||||
|
||||
1
resources/ui/air_assets/unspecified_blue.svg
Normal file
1
resources/ui/air_assets/unspecified_blue.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" width="118" height="128" viewBox="41 26 118 128"><path d="M 155,150 C 155,50 115,30 100,30 85,30 45,50 45,150" stroke-width="4" stroke="black" fill="rgb(128,224,255)" fill-opacity="1" ></path></svg>
|
||||
|
After Width: | Height: | Size: 271 B |
1
resources/ui/air_assets/unspecified_red.svg
Normal file
1
resources/ui/air_assets/unspecified_red.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" width="118" height="138" viewBox="41 16 118 138"><path d="M 45,150 L45,70 100,20 155,70 155,150" stroke-width="4" stroke="black" fill="rgb(255,128,128)" fill-opacity="1" ></path></svg>
|
||||
|
After Width: | Height: | Size: 257 B |
@ -104,9 +104,31 @@ class TgoIcons {
|
||||
}
|
||||
}
|
||||
|
||||
class AirIcons {
|
||||
constructor() {
|
||||
this.icons = {};
|
||||
for (const player of [true, false]) {
|
||||
this.icons[player] = this.loadIcon("unspecified", player);
|
||||
}
|
||||
}
|
||||
|
||||
icon(_category, player, _state) {
|
||||
return this.icons[player];
|
||||
}
|
||||
|
||||
loadIcon(category, player) {
|
||||
const color = player ? "blue" : "red";
|
||||
return new L.Icon({
|
||||
iconUrl: `../air_assets/${category}_${color}.svg`,
|
||||
iconSize: [24, 24],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const Icons = Object.freeze({
|
||||
ControlPoints: new CpIcons(),
|
||||
Objectives: new TgoIcons(),
|
||||
AirIcons: new AirIcons(),
|
||||
});
|
||||
|
||||
function metersToNauticalMiles(meters) {
|
||||
@ -163,6 +185,7 @@ defaultBaseMap.addTo(map);
|
||||
|
||||
// Enabled by default, so addTo(map).
|
||||
const controlPointsLayer = L.layerGroup().addTo(map);
|
||||
const aircraftLayer = L.layerGroup().addTo(map);
|
||||
const airDefensesLayer = L.layerGroup().addTo(map);
|
||||
const factoriesLayer = L.layerGroup().addTo(map);
|
||||
const shipsLayer = L.layerGroup().addTo(map);
|
||||
@ -249,8 +272,9 @@ L.control
|
||||
.groupedLayers(
|
||||
baseLayers,
|
||||
{
|
||||
"Points of Interest": {
|
||||
"Units and locations": {
|
||||
"Control points": controlPointsLayer,
|
||||
Aircraft: aircraftLayer,
|
||||
"Air defenses": airDefensesLayer,
|
||||
Factories: factoriesLayer,
|
||||
Ships: shipsLayer,
|
||||
@ -307,7 +331,7 @@ new QWebChannel(qt.webChannelTransport, function (channel) {
|
||||
game.groundObjectsChanged.connect(drawGroundObjects);
|
||||
game.supplyRoutesChanged.connect(drawSupplyRoutes);
|
||||
game.frontLinesChanged.connect(drawFrontLines);
|
||||
game.flightsChanged.connect(drawFlightPlans);
|
||||
game.flightsChanged.connect(drawAircraft);
|
||||
game.threatZonesChanged.connect(drawThreatZones);
|
||||
game.navmeshesChanged.connect(drawNavmeshes);
|
||||
game.mapZonesChanged.connect(drawMapZones);
|
||||
@ -770,9 +794,11 @@ class Flight {
|
||||
constructor(flight) {
|
||||
this.flight = flight;
|
||||
this.flightPlan = this.flight.flightPlan.map((p) => new Waypoint(p, this));
|
||||
this.aircraft = null;
|
||||
this.path = null;
|
||||
this.commitBoundary = null;
|
||||
this.flight.flightPlanChanged.connect(() => this.draw());
|
||||
this.flight.positionChanged.connect(() => this.drawAircraftLocation());
|
||||
this.flight.flightPlanChanged.connect(() => this.drawFlightPlan());
|
||||
this.flight.commitBoundaryChanged.connect(() => this.drawCommitBoundary());
|
||||
}
|
||||
|
||||
@ -808,6 +834,25 @@ class Flight {
|
||||
}
|
||||
}
|
||||
|
||||
draw() {
|
||||
this.drawAircraftLocation();
|
||||
this.drawFlightPlan();
|
||||
this.drawCommitBoundary();
|
||||
}
|
||||
|
||||
drawAircraftLocation() {
|
||||
if (this.aircraft != null) {
|
||||
this.aircraft.removeFrom(aircraftLayer);
|
||||
this.aircraft = null;
|
||||
}
|
||||
const position = this.flight.position;
|
||||
if (position.length > 0) {
|
||||
this.aircraft = L.marker(position, {
|
||||
icon: Icons.AirIcons.icon("fighter", this.flight.blue),
|
||||
}).addTo(aircraftLayer);
|
||||
}
|
||||
}
|
||||
|
||||
drawCommitBoundary() {
|
||||
if (this.commitBoundary != null) {
|
||||
this.commitBoundary
|
||||
@ -829,7 +874,7 @@ class Flight {
|
||||
}
|
||||
}
|
||||
|
||||
draw() {
|
||||
drawFlightPlan() {
|
||||
const path = [];
|
||||
this.flightPlan.forEach((waypoint) => {
|
||||
if (waypoint.includeInPath()) {
|
||||
@ -844,11 +889,11 @@ class Flight {
|
||||
});
|
||||
|
||||
this.drawPath(path);
|
||||
this.drawCommitBoundary();
|
||||
}
|
||||
}
|
||||
|
||||
function drawFlightPlans() {
|
||||
function drawAircraft() {
|
||||
aircraftLayer.clearLayers();
|
||||
blueFlightPlansLayer.clearLayers();
|
||||
redFlightPlansLayer.clearLayers();
|
||||
selectedFlightPlansLayer.clearLayers();
|
||||
@ -1136,7 +1181,7 @@ function drawInitialMap() {
|
||||
drawGroundObjects();
|
||||
drawSupplyRoutes();
|
||||
drawFrontLines();
|
||||
drawFlightPlans();
|
||||
drawAircraft();
|
||||
drawThreatZones();
|
||||
drawNavmeshes();
|
||||
drawMapZones();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user