mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Implemented top bar with turn counter and budget info. Added CSS stylesheet.
This commit is contained in:
188
qt_ui/widgets/map/QLiberationMap.py
Normal file
188
qt_ui/widgets/map/QLiberationMap.py
Normal file
@@ -0,0 +1,188 @@
|
||||
from typing import Dict
|
||||
|
||||
from PySide2.QtCore import Qt
|
||||
from PySide2.QtGui import QPixmap, QBrush, QColor, QWheelEvent, QPen, QFont
|
||||
from PySide2.QtWidgets import QGraphicsView, QFrame
|
||||
|
||||
from gen import Conflict
|
||||
from qt_ui.widgets.map.QMapControlPoint import QMapControlPoint
|
||||
from qt_ui.widgets.map.QMapGroundObject import QMapGroundObject
|
||||
from qt_ui.widgets.map.QLiberationScene import QLiberationScene
|
||||
from dcs import Point
|
||||
|
||||
from theater import ControlPoint
|
||||
from game import Game
|
||||
import qt_ui.uiconstants as CONST
|
||||
|
||||
|
||||
class QLiberationMap(QGraphicsView):
|
||||
|
||||
instance = None
|
||||
display_rules: Dict[str, bool] = {
|
||||
"cp": True,
|
||||
"go": True,
|
||||
"lines": True,
|
||||
"ennemy_sam_ranges": True,
|
||||
"ally_sam_ranges": True
|
||||
}
|
||||
|
||||
def __init__(self, game: Game):
|
||||
super(QLiberationMap, self).__init__()
|
||||
QLiberationMap.instance = self
|
||||
|
||||
self.frontline_vector_cache = {}
|
||||
|
||||
self.setMinimumSize(800,600)
|
||||
self.setMaximumHeight(2160)
|
||||
self._zoom = 0
|
||||
self.init_scene()
|
||||
self.loadGame(game)
|
||||
|
||||
def init_scene(self):
|
||||
scene = QLiberationScene(self)
|
||||
scene.addText("Hello World")
|
||||
|
||||
self.setScene(scene)
|
||||
self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
|
||||
self.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
|
||||
#self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
#self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
self.setBackgroundBrush(QBrush(QColor(30, 30, 30)))
|
||||
self.setFrameShape(QFrame.NoFrame)
|
||||
self.setDragMode(QGraphicsView.ScrollHandDrag)
|
||||
|
||||
def loadGame(self, game: Game):
|
||||
self.game = game
|
||||
scene = self.scene()
|
||||
self.reload_scene()
|
||||
|
||||
def setGame(self, game: Game):
|
||||
self.loadGame(game)
|
||||
|
||||
def reload_scene(self):
|
||||
scene = self.scene()
|
||||
scene.clear()
|
||||
scene.addPixmap(QPixmap("./resources/" + self.game.theater.overview_image))
|
||||
for cp in self.game.theater.controlpoints:
|
||||
|
||||
pos = self._transform_point(cp.position)
|
||||
scene.addItem(QMapControlPoint(self, pos[0] - CONST.CP_SIZE / 2, pos[1] - CONST.CP_SIZE / 2, CONST.CP_SIZE,
|
||||
CONST.CP_SIZE, cp))
|
||||
|
||||
# e = scene.addEllipse(pos[0]-CONST.CP_SIZE/2, pos[1]-CONST.CP_SIZE/2, CONST.CP_SIZE, CONST.CP_SIZE, QPen(brush=QBrush(color=color), width=5), brush=color)
|
||||
|
||||
text = scene.addText(cp.name, font=QFont("Trebuchet MS", 10, weight=5, italic=False))
|
||||
text.setPos(pos[0] + CONST.CP_SIZE, pos[1] - CONST.CP_SIZE / 2)
|
||||
|
||||
for ground_object in cp.ground_objects:
|
||||
go_pos = self._transform_point(ground_object.position)
|
||||
scene.addItem(QMapGroundObject(self, go_pos[0], go_pos[1], 16, 16, cp, ground_object))
|
||||
|
||||
if self.get_display_rule("lines"):
|
||||
self.scene_create_lines_for_cp(cp)
|
||||
|
||||
def scene_create_lines_for_cp(self, cp: ControlPoint):
|
||||
scene = self.scene()
|
||||
pos = self._transform_point(cp.position)
|
||||
for connected_cp in cp.connected_points:
|
||||
pos2 = self._transform_point(connected_cp.position)
|
||||
if connected_cp.captured != cp.captured:
|
||||
color = CONST.COLORS["red"]
|
||||
elif connected_cp.captured and cp.captured:
|
||||
color = CONST.COLORS["blue"]
|
||||
else:
|
||||
color = CONST.COLORS["black_transparent"]
|
||||
|
||||
pen = QPen(brush=color)
|
||||
pen.setColor(color)
|
||||
pen.setWidth(4)
|
||||
scene.addLine(pos[0], pos[1], pos2[0], pos2[1], pen=pen)
|
||||
|
||||
if cp.captured and not connected_cp.captured and Conflict.has_frontline_between(cp, connected_cp):
|
||||
frontline = self._frontline_vector(cp, connected_cp)
|
||||
if not frontline:
|
||||
continue
|
||||
|
||||
frontline_pos, heading, distance = frontline
|
||||
|
||||
if distance < 10000:
|
||||
frontline_pos = frontline_pos.point_from_heading(heading + 180, 5000)
|
||||
distance = 10000
|
||||
|
||||
start_coords = self._transform_point(frontline_pos, treshold=10)
|
||||
end_coords = self._transform_point(frontline_pos.point_from_heading(heading, distance),
|
||||
treshold=60)
|
||||
|
||||
frontline_pen = QPen(brush=CONST.COLORS["bright_red"])
|
||||
frontline_pen.setColor(CONST.COLORS["bright_red"])
|
||||
frontline_pen.setWidth(4)
|
||||
frontline_pen.setStyle(Qt.DashDotLine)
|
||||
# frontline_pen.setDashPattern([0,1])
|
||||
scene.addLine(start_coords[0], start_coords[1], end_coords[0], end_coords[1], pen=frontline_pen)
|
||||
|
||||
|
||||
def _frontline_vector(self, from_cp: ControlPoint, to_cp: ControlPoint):
|
||||
# Cache mechanism to avoid performing frontline vector computation on every frame
|
||||
key = str(from_cp.id) + "_" + str(to_cp.id)
|
||||
if key in self.frontline_vector_cache:
|
||||
return self.frontline_vector_cache[key]
|
||||
else:
|
||||
frontline = Conflict.frontline_vector(from_cp, to_cp, self.game.theater)
|
||||
self.frontline_vector_cache[key] = frontline
|
||||
return frontline
|
||||
|
||||
def wheelEvent(self, event: QWheelEvent):
|
||||
|
||||
if event.angleDelta().y() > 0:
|
||||
factor = 1.25
|
||||
self._zoom += 1
|
||||
else:
|
||||
factor = 0.8
|
||||
self._zoom -= 1
|
||||
|
||||
if self._zoom > -5:
|
||||
self.scale(factor, factor)
|
||||
else:
|
||||
self._zoom = -5
|
||||
|
||||
def _transform_point(self, p: Point, treshold=30) -> (int, int):
|
||||
point_a = list(self.game.theater.reference_points.keys())[0]
|
||||
point_a_img = self.game.theater.reference_points[point_a]
|
||||
|
||||
point_b = list(self.game.theater.reference_points.keys())[1]
|
||||
point_b_img = self.game.theater.reference_points[point_b]
|
||||
|
||||
Y_dist = point_a_img[0] - point_b_img[0]
|
||||
lon_dist = point_a[1] - point_b[1]
|
||||
|
||||
X_dist = point_a_img[1] - point_b_img[1]
|
||||
lat_dist = point_b[0] - point_a[0]
|
||||
|
||||
Y_scale = float(Y_dist) / float(lon_dist)
|
||||
X_scale = float(X_dist) / float(lat_dist)
|
||||
|
||||
# ---
|
||||
Y_offset = p.x - point_a[0]
|
||||
X_offset = p.y - point_a[1]
|
||||
|
||||
X = point_b_img[1] + X_offset * X_scale
|
||||
Y = point_a_img[0] - Y_offset * Y_scale
|
||||
|
||||
#X += 5
|
||||
#Y += 5
|
||||
|
||||
return X > treshold and X or treshold, Y > treshold and Y or treshold
|
||||
|
||||
@staticmethod
|
||||
def set_display_rule(rule: str, value: bool):
|
||||
QLiberationMap.display_rules[rule] = value
|
||||
QLiberationMap.instance.reload_scene()
|
||||
QLiberationMap.instance.update()
|
||||
|
||||
@staticmethod
|
||||
def get_display_rules() -> Dict[str, bool]:
|
||||
return QLiberationMap.display_rules
|
||||
|
||||
@staticmethod
|
||||
def get_display_rule(rule) -> bool:
|
||||
return QLiberationMap.display_rules[rule]
|
||||
Reference in New Issue
Block a user