mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Convert front line segments to proper class.
Needed so we can add context menus to the lines.
This commit is contained in:
parent
2a5b37b9ad
commit
2b06d8a096
@ -4,7 +4,7 @@ import datetime
|
||||
import logging
|
||||
import math
|
||||
from functools import singledispatchmethod
|
||||
from typing import Iterable, Iterator, List, Optional, Set, Tuple
|
||||
from typing import Iterable, Iterator, List, Optional, Tuple
|
||||
|
||||
from PySide2 import QtCore, QtWidgets
|
||||
from PySide2.QtCore import QLineF, QPointF, QRectF, Qt
|
||||
@ -26,8 +26,8 @@ from PySide2.QtWidgets import (
|
||||
QGraphicsView,
|
||||
)
|
||||
from dcs import Point
|
||||
from dcs.planes import F_16C_50
|
||||
from dcs.mapping import point_from_heading
|
||||
from dcs.planes import F_16C_50
|
||||
from dcs.unitgroup import Group
|
||||
from shapely.geometry import (
|
||||
LineString,
|
||||
@ -44,6 +44,7 @@ from game.theater.conflicttheater import FrontLine, ReferencePoint
|
||||
from game.theater.theatergroundobject import (
|
||||
TheaterGroundObject,
|
||||
)
|
||||
from game.transfers import RoadTransferOrder
|
||||
from game.utils import Distance, meters, nautical_miles
|
||||
from game.weather import TimeOfDay
|
||||
from gen import Conflict, Package
|
||||
@ -66,6 +67,7 @@ from qt_ui.widgets.map.QFrontLine import QFrontLine
|
||||
from qt_ui.widgets.map.QLiberationScene import QLiberationScene
|
||||
from qt_ui.widgets.map.QMapControlPoint import QMapControlPoint
|
||||
from qt_ui.widgets.map.QMapGroundObject import QMapGroundObject
|
||||
from qt_ui.widgets.map.SupplyRouteSegment import SupplyRouteSegment
|
||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||
|
||||
MAX_SHIP_DISTANCE = nautical_miles(80)
|
||||
@ -824,9 +826,8 @@ class QLiberationMap(QGraphicsView):
|
||||
def draw_bezier_frontline(
|
||||
self,
|
||||
scene: QGraphicsScene,
|
||||
pen: QPen,
|
||||
frontline: FrontLine,
|
||||
convoy_size: int = 0,
|
||||
convoys: List[RoadTransferOrder],
|
||||
) -> None:
|
||||
"""
|
||||
Thanks to Alquimista for sharing a python implementation of the bezier algorithm this is adapted from.
|
||||
@ -841,18 +842,17 @@ class QLiberationMap(QGraphicsView):
|
||||
for point in bezier_curve_range(
|
||||
int(len(bezier_fixed_points) * 2), bezier_fixed_points
|
||||
):
|
||||
line = scene.addLine(
|
||||
old_point[0], old_point[1], point[0], point[1], pen=pen
|
||||
)
|
||||
if convoy_size:
|
||||
units = "units" if convoy_size > 1 else "unit"
|
||||
tooltip = (
|
||||
f"{convoy_size} {units} transferring between "
|
||||
f"{frontline.control_point_a} and {frontline.control_point_b}."
|
||||
scene.addItem(
|
||||
SupplyRouteSegment(
|
||||
old_point[0],
|
||||
old_point[1],
|
||||
point[0],
|
||||
point[1],
|
||||
frontline.control_point_a,
|
||||
frontline.control_point_b,
|
||||
convoys,
|
||||
)
|
||||
else:
|
||||
tooltip = "No convoys present on this supply route."
|
||||
line.setToolTip(tooltip)
|
||||
)
|
||||
old_point = point
|
||||
|
||||
def draw_supply_routes(self) -> None:
|
||||
@ -865,19 +865,21 @@ class QLiberationMap(QGraphicsView):
|
||||
if DisplayOptions.lines:
|
||||
self.draw_supply_route_between(cp, connected)
|
||||
|
||||
def _count_units_tranferring_between(self, a: ControlPoint, b: ControlPoint) -> int:
|
||||
def _transfers_between(
|
||||
self, a: ControlPoint, b: ControlPoint
|
||||
) -> List[RoadTransferOrder]:
|
||||
# We attempt to short circuit the expensive shortest path computation for the
|
||||
# cases where there is never a transfer, but caching might be needed.
|
||||
|
||||
if a.captured != b.captured:
|
||||
# Cannot transfer to enemy CPs.
|
||||
return 0
|
||||
return []
|
||||
|
||||
# This is only called for drawing lines between nodes and have rules out routes
|
||||
# to enemy bases, so a and b are guaranteed to be in the same supply route.
|
||||
supply_route = SupplyRoute.for_control_point(a)
|
||||
|
||||
count = 0
|
||||
transfers = []
|
||||
points = {a, b}
|
||||
for transfer in self.game.transfers:
|
||||
# No possible route from our network to this transfer.
|
||||
@ -887,55 +889,32 @@ class QLiberationMap(QGraphicsView):
|
||||
# Anything left is a transfer within our supply route.
|
||||
transfer_points = {transfer.position, transfer.next_stop()}
|
||||
if points == transfer_points:
|
||||
count += sum(transfer.units.values())
|
||||
return count
|
||||
|
||||
def supply_route_color(self, a: ControlPoint, b: ControlPoint) -> QColor:
|
||||
if a.front_is_active(b):
|
||||
return CONST.COLORS["red"]
|
||||
elif a.captured:
|
||||
return CONST.COLORS["dark_" + self.game.get_player_color()]
|
||||
else:
|
||||
return CONST.COLORS["dark_" + self.game.get_enemy_color()]
|
||||
|
||||
def supply_route_style(
|
||||
self, a: ControlPoint, b: ControlPoint, has_transfer: bool
|
||||
) -> Qt.PenStyle:
|
||||
if a.front_is_active(b) or has_transfer:
|
||||
return Qt.PenStyle.SolidLine
|
||||
return Qt.PenStyle.DotLine
|
||||
|
||||
def supply_route_pen(
|
||||
self, a: ControlPoint, b: ControlPoint, has_transfer: bool
|
||||
) -> QPen:
|
||||
color = self.supply_route_color(a, b)
|
||||
pen = QPen(brush=color)
|
||||
pen.setColor(color)
|
||||
pen.setStyle(self.supply_route_style(a, b, has_transfer))
|
||||
pen.setWidth(6)
|
||||
return pen
|
||||
transfers.append(transfer)
|
||||
return transfers
|
||||
|
||||
def draw_supply_route_between(self, a: ControlPoint, b: ControlPoint) -> None:
|
||||
scene = self.scene()
|
||||
|
||||
convoy_size = self._count_units_tranferring_between(a, b)
|
||||
pen = self.supply_route_pen(a, b, convoy_size > 0)
|
||||
convoys = self._transfers_between(a, b)
|
||||
frontline = FrontLine(a, b, self.game.theater)
|
||||
if a.front_is_active(b):
|
||||
if DisplayOptions.actual_frontline_pos:
|
||||
self.draw_actual_frontline(frontline, scene, pen)
|
||||
self.draw_actual_frontline(scene, frontline, convoys)
|
||||
else:
|
||||
self.draw_frontline_approximation(frontline, scene, pen)
|
||||
self.draw_frontline_approximation(scene, frontline, convoys)
|
||||
else:
|
||||
self.draw_bezier_frontline(scene, pen, frontline, convoy_size)
|
||||
self.draw_bezier_frontline(scene, frontline, convoys)
|
||||
|
||||
def draw_frontline_approximation(
|
||||
self, frontline: FrontLine, scene: QGraphicsScene, pen: QPen
|
||||
self,
|
||||
scene: QGraphicsScene,
|
||||
frontline: FrontLine,
|
||||
convoys: List[RoadTransferOrder],
|
||||
) -> None:
|
||||
posx = frontline.position
|
||||
h = frontline.attack_heading
|
||||
pos2 = self._transform_point(posx)
|
||||
self.draw_bezier_frontline(scene, pen, frontline)
|
||||
self.draw_bezier_frontline(scene, frontline, convoys)
|
||||
p1 = point_from_heading(pos2[0], pos2[1], h + 180, 25)
|
||||
p2 = point_from_heading(pos2[0], pos2[1], h, 25)
|
||||
scene.addItem(
|
||||
@ -943,9 +922,12 @@ class QLiberationMap(QGraphicsView):
|
||||
)
|
||||
|
||||
def draw_actual_frontline(
|
||||
self, frontline: FrontLine, scene: QGraphicsScene, pen: QPen
|
||||
self,
|
||||
scene: QGraphicsScene,
|
||||
frontline: FrontLine,
|
||||
convoys: List[RoadTransferOrder],
|
||||
) -> None:
|
||||
self.draw_bezier_frontline(scene, pen, frontline)
|
||||
self.draw_bezier_frontline(scene, frontline, convoys)
|
||||
vector = Conflict.frontline_vector(
|
||||
frontline.control_point_a, frontline.control_point_b, self.game.theater
|
||||
)
|
||||
|
||||
73
qt_ui/widgets/map/SupplyRouteSegment.py
Normal file
73
qt_ui/widgets/map/SupplyRouteSegment.py
Normal file
@ -0,0 +1,73 @@
|
||||
from functools import cached_property
|
||||
from typing import List, Optional
|
||||
|
||||
from PySide2.QtCore import Qt
|
||||
from PySide2.QtGui import QColor, QPen
|
||||
from PySide2.QtWidgets import QGraphicsItem, QGraphicsLineItem
|
||||
|
||||
from game.theater import ControlPoint
|
||||
from game.transfers import RoadTransferOrder
|
||||
from qt_ui.uiconstants import COLORS
|
||||
|
||||
|
||||
class SupplyRouteSegment(QGraphicsLineItem):
|
||||
def __init__(
|
||||
self,
|
||||
x0: float,
|
||||
y0: float,
|
||||
x1: float,
|
||||
y1: float,
|
||||
control_point_a: ControlPoint,
|
||||
control_point_b: ControlPoint,
|
||||
convoys: List[RoadTransferOrder],
|
||||
parent: Optional[QGraphicsItem] = None,
|
||||
) -> None:
|
||||
super().__init__(x0, y0, x1, y1, parent)
|
||||
self.control_point_a = control_point_a
|
||||
self.control_point_b = control_point_b
|
||||
self.convoys = convoys
|
||||
self.setPen(self.make_pen())
|
||||
self.setToolTip(self.make_tooltip())
|
||||
|
||||
@cached_property
|
||||
def convoy_size(self) -> int:
|
||||
return sum(sum(c.units.values()) for c in self.convoys)
|
||||
|
||||
def make_tooltip(self) -> str:
|
||||
if not self.convoys:
|
||||
return "No convoys present on this supply route."
|
||||
units = "units" if self.convoy_size > 1 else "unit"
|
||||
|
||||
return (
|
||||
f"{self.convoy_size} {units} transferring between {self.control_point_a} "
|
||||
f"and {self.control_point_b}."
|
||||
)
|
||||
|
||||
@property
|
||||
def line_color(self) -> QColor:
|
||||
if self.control_point_a.front_is_active(self.control_point_b):
|
||||
return COLORS["red"]
|
||||
elif self.control_point_a.captured:
|
||||
return COLORS["dark_blue"]
|
||||
else:
|
||||
return COLORS["dark_red"]
|
||||
|
||||
@property
|
||||
def line_style(self) -> Qt.PenStyle:
|
||||
if (
|
||||
self.control_point_a.front_is_active(self.control_point_b)
|
||||
or self.has_convoys
|
||||
):
|
||||
return Qt.PenStyle.SolidLine
|
||||
return Qt.PenStyle.DotLine
|
||||
|
||||
def make_pen(self) -> QPen:
|
||||
pen = QPen(brush=self.line_color)
|
||||
pen.setColor(self.line_color)
|
||||
pen.setStyle(self.line_style)
|
||||
pen.setWidth(6)
|
||||
return pen
|
||||
|
||||
@property
|
||||
def has_convoys(self) -> bool:
|
||||
return bool(self.convoys)
|
||||
Loading…
x
Reference in New Issue
Block a user