mirror of
https://github.com/dcs-liberation/dcs_liberation.git
synced 2025-11-10 14:22:26 +00:00
Qt Map drawn with line and frontline
This commit is contained in:
parent
67910bce61
commit
b66bf4cc36
@ -4,23 +4,29 @@ from time import sleep
|
||||
from PySide2.QtGui import QPixmap
|
||||
from PySide2.QtWidgets import QApplication, QLabel, QSplashScreen
|
||||
|
||||
from qt_ui import uiconstants
|
||||
from qt_ui.windows.QLiberationWindow import QLiberationWindow
|
||||
from userdata import persistency
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
# Splash screen setup
|
||||
pixmap = QPixmap("../resources/ui/splash_screen.png")
|
||||
splash = QSplashScreen(pixmap)
|
||||
splash.show()
|
||||
|
||||
# Load stuff
|
||||
persistency.setup(sys.argv[1])
|
||||
sleep(2)
|
||||
sleep(0.5)
|
||||
uiconstants.load_icons()
|
||||
app.processEvents()
|
||||
|
||||
# Start window
|
||||
window = QLiberationWindow()
|
||||
window.show()
|
||||
|
||||
splash.finish(window)
|
||||
|
||||
sys.exit(app.exec_())
|
||||
@ -1,7 +1,11 @@
|
||||
# URL for UI links
|
||||
from typing import Dict
|
||||
|
||||
from PySide2.QtGui import QColor, QFont, QPixmap
|
||||
|
||||
URLS = {
|
||||
from theater.theatergroundobject import CATEGORY_MAP
|
||||
|
||||
URLS : Dict[str, str] = {
|
||||
"Manual": "https://github.com/shdwp/dcs_liberation/wiki/Manual",
|
||||
"Troubleshooting": "https://github.com/shdwp/dcs_liberation/wiki/Troubleshooting",
|
||||
"Modding": "https://github.com/shdwp/dcs_liberation/wiki/Modding-tutorial",
|
||||
@ -10,7 +14,7 @@ URLS = {
|
||||
"Issues": "https://github.com/shdwp/dcs_liberation/issues"
|
||||
}
|
||||
|
||||
COLORS = {
|
||||
COLORS: Dict[str, QColor] = {
|
||||
"red": QColor(255, 125, 125),
|
||||
"bright_red": QColor(200, 64, 64),
|
||||
"blue": QColor(164, 164, 255),
|
||||
@ -18,7 +22,8 @@ COLORS = {
|
||||
"white": QColor(255, 255, 255),
|
||||
"green": QColor(128, 186, 128),
|
||||
"bright_green": QColor(64, 200, 64),
|
||||
"black": QColor(0, 0, 0)
|
||||
"black": QColor(0, 0, 0),
|
||||
"black_transparent": QColor(0, 0, 0, 64)
|
||||
}
|
||||
|
||||
|
||||
@ -27,13 +32,22 @@ CP_SIZE = 25
|
||||
|
||||
FONT = QFont("Arial", 12, weight=5, italic=True)
|
||||
|
||||
"""
|
||||
ICONS = {
|
||||
"Dawn": QPixmap("../resources/ui/daytime/dawn.png"),
|
||||
"Day": QPixmap("../resources/ui/daytime/day.png"),
|
||||
"Dusk": QPixmap("../resources/ui/daytime/dusk.png"),
|
||||
"Night": QPixmap("../resources/ui/daytime/night.png"),
|
||||
"Money": QPixmap("../resources/ui/misc/money_icon.png"),
|
||||
"Ordnance": QPixmap("../resources/ui/misc/ordnance_icon.png"),
|
||||
}
|
||||
"""
|
||||
ICONS: Dict[str, QPixmap] = {}
|
||||
|
||||
def load_icons():
|
||||
|
||||
ICONS["New"] = QPixmap("../resources/ui/misc/new.png")
|
||||
ICONS["Open"] = QPixmap("../resources/ui/misc/open.png")
|
||||
ICONS["Save"] = QPixmap("../resources/ui/misc/save.png")
|
||||
|
||||
ICONS["Dawn"] = QPixmap("../resources/ui/daytime/dawn.png")
|
||||
ICONS["Day"] = QPixmap("../resources/ui/daytime/day.png")
|
||||
ICONS["Dusk"] = QPixmap("../resources/ui/daytime/dusk.png")
|
||||
ICONS["Night"] = QPixmap("../resources/ui/daytime/night.png")
|
||||
ICONS["Money"] = QPixmap("../resources/ui/misc/money_icon.png")
|
||||
ICONS["Ordnance"] = QPixmap("../resources/ui/misc/ordnance_icon.png")
|
||||
|
||||
ICONS["target"] = QPixmap("../resources/ui/ground_assets/target.png")
|
||||
ICONS["cleared"] = QPixmap("../resources/ui/ground_assets/cleared.png")
|
||||
for category in CATEGORY_MAP.keys():
|
||||
ICONS[category] = QPixmap("../resources/ui/ground_assets/" + category + ".png")
|
||||
|
||||
@ -14,11 +14,13 @@ class QMapControlPoint(QGraphicsRectItem):
|
||||
self.parent = parent
|
||||
self.setAcceptHoverEvents(True)
|
||||
self.setZValue(1)
|
||||
self.setToolTip(self.model.base)
|
||||
self.setToolTip(self.model.name)
|
||||
|
||||
|
||||
def paint(self, painter, option, widget=None):
|
||||
#super(QMapControlPoint, self).paint(painter, option, widget)
|
||||
|
||||
if self.parent.get_display_rule("cp"):
|
||||
painter.save()
|
||||
painter.setRenderHint(QPainter.Antialiasing)
|
||||
painter.setBrush(self.brush_color)
|
||||
@ -33,7 +35,9 @@ class QMapControlPoint(QGraphicsRectItem):
|
||||
r = option.rect
|
||||
painter.setPen(QPen(CONST.COLORS["white"], CONST.CP_SIZE/5))
|
||||
painter.setBrush(CONST.COLORS["white"])
|
||||
painter.drawLine(QLine(r.x(), r.y(), r.x()+r.width(), r.y()+r.height()))
|
||||
painter.drawLine(QLine(r.x()+CONST.CP_SIZE/5, r.y()+CONST.CP_SIZE/5,
|
||||
r.x()+r.width()-CONST.CP_SIZE/5,
|
||||
r.y()+r.height()-CONST.CP_SIZE/5))
|
||||
|
||||
painter.restore()
|
||||
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
from PySide2.QtWidgets import QGraphicsRectItem
|
||||
|
||||
import qt_ui.uiconstants as CONST
|
||||
from theater import TheaterGroundObject, ControlPoint
|
||||
|
||||
|
||||
class QMapGroundObject(QGraphicsRectItem):
|
||||
|
||||
def __init__(self, parent, x: float, y: float, w: float, h: float, cp: ControlPoint, model: TheaterGroundObject):
|
||||
super(QMapGroundObject, self).__init__(x, y, w, h)
|
||||
self.model = model
|
||||
self.cp = cp
|
||||
self.parent = parent
|
||||
self.setAcceptHoverEvents(True)
|
||||
self.setZValue(2)
|
||||
self.setToolTip(cp.name + "'s " + self.model.category)
|
||||
|
||||
|
||||
def paint(self, painter, option, widget=None):
|
||||
#super(QMapControlPoint, self).paint(painter, option, widget)
|
||||
|
||||
if self.parent.get_display_rule("go"):
|
||||
painter.save()
|
||||
if not self.model.is_dead and not self.cp.captured:
|
||||
painter.drawPixmap(option.rect, CONST.ICONS[self.model.category])
|
||||
else:
|
||||
painter.drawPixmap(option.rect, CONST.ICONS["cleared"])
|
||||
painter.restore()
|
||||
@ -1,10 +1,16 @@
|
||||
from typing import Dict
|
||||
|
||||
from PySide2.QtCore import Qt
|
||||
from PySide2.QtGui import QPixmap, QBrush, QColor, QWheelEvent, QPen, QFont
|
||||
from PySide2.QtWidgets import QWidget, QGraphicsWidget, QGraphicsView, QFrame, QGraphicsTextItem
|
||||
|
||||
from gen import Conflict
|
||||
from qt_ui.widgets.QMapControlPoint import QMapControlPoint
|
||||
from qt_ui.widgets.QMapGroundObject import QMapGroundObject
|
||||
from qt_ui.windows.QLiberationScene import QLiberationScene
|
||||
from dcs import Point
|
||||
|
||||
from theater import ControlPoint
|
||||
from userdata import persistency
|
||||
from game import Game
|
||||
import qt_ui.uiconstants as CONST
|
||||
@ -12,18 +18,28 @@ 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):
|
||||
super(QLiberationMap, self).__init__()
|
||||
QLiberationMap.instance = self
|
||||
|
||||
self.frontline_vector_cache = {}
|
||||
|
||||
self.setMinimumSize(800,600)
|
||||
self.setMaximumHeight(2160)
|
||||
self._zoom = 0
|
||||
|
||||
self.init_scene()
|
||||
|
||||
game = persistency.restore_game()
|
||||
self.loadGame(game)
|
||||
|
||||
|
||||
|
||||
def init_scene(self):
|
||||
scene = QLiberationScene(self)
|
||||
scene.addText("Hello World")
|
||||
@ -39,26 +55,80 @@ class QLiberationMap(QGraphicsView):
|
||||
|
||||
def loadGame(self, game: Game):
|
||||
self.game = game
|
||||
scene = self.scene()
|
||||
self.reload_scene()
|
||||
|
||||
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))
|
||||
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 go in cp.ground_objects:
|
||||
pos = self._transform_point(go.position)
|
||||
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=CONST.COLORS["green"]), width=5), brush=CONST.COLORS["green"])
|
||||
|
||||
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):
|
||||
|
||||
@ -101,3 +171,17 @@ class QLiberationMap(QGraphicsView):
|
||||
#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]
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
from PySide2.QtGui import QIcon
|
||||
from PySide2.QtWidgets import QWidget, QPushButton, QHBoxLayout, QVBoxLayout, QMenuBar, QMainWindow
|
||||
from PySide2.QtWidgets import QWidget, QPushButton, QHBoxLayout, QVBoxLayout, QMenuBar, QMainWindow, QAction, QToolBar
|
||||
import webbrowser
|
||||
|
||||
from qt_ui.uiconstants import URLS
|
||||
from qt_ui.windows.QLiberationMap import QLiberationMap
|
||||
|
||||
import qt_ui.uiconstants as CONST
|
||||
|
||||
class QLiberationWindow(QMainWindow):
|
||||
|
||||
@ -19,16 +19,18 @@ class QLiberationWindow(QMainWindow):
|
||||
self.setWindowIcon(QIcon("../resources/icon.png"))
|
||||
self.statusBar().showMessage('Ready')
|
||||
self.init_menubar()
|
||||
self.init_toolbar()
|
||||
|
||||
okButton = QPushButton("OK")
|
||||
cancelButton = QPushButton("Cancel")
|
||||
|
||||
hbox = QHBoxLayout()
|
||||
hbox.addStretch(1)
|
||||
hbox.addWidget(okButton)
|
||||
hbox.addWidget(cancelButton)
|
||||
"""hbox.addWidget(okButton)
|
||||
hbox.addWidget(cancelButton)"""
|
||||
|
||||
self.liberation_map = QLiberationMap()
|
||||
|
||||
hbox.addWidget(self.liberation_map)
|
||||
|
||||
vbox = QVBoxLayout()
|
||||
@ -40,13 +42,20 @@ class QLiberationWindow(QMainWindow):
|
||||
self.setCentralWidget(central_widget)
|
||||
|
||||
|
||||
def init_toolbar(self):
|
||||
self.tool_bar = self.addToolBar("File")
|
||||
self.tool_bar.addAction(QIcon(CONST.ICONS["New"]), "New")
|
||||
self.tool_bar.addAction(QIcon(CONST.ICONS["Open"]), "Open")
|
||||
self.tool_bar.addAction(QIcon(CONST.ICONS["Save"]), "Save")
|
||||
|
||||
|
||||
def init_menubar(self):
|
||||
self.menu = self.menuBar()
|
||||
|
||||
file_menu = self.menu.addMenu("File")
|
||||
file_menu.addAction("New Game")
|
||||
file_menu.addAction("Open")
|
||||
file_menu.addAction("Save")
|
||||
file_menu.addAction(QIcon(CONST.ICONS["New"]), "New Game")
|
||||
file_menu.addAction(QIcon(CONST.ICONS["Open"]), "Open")
|
||||
file_menu.addAction(QIcon(CONST.ICONS["Save"]), "Save")
|
||||
file_menu.addAction("Save As")
|
||||
|
||||
help_menu = self.menu.addMenu("Help")
|
||||
@ -57,3 +66,24 @@ class QLiberationWindow(QMainWindow):
|
||||
help_menu.addAction("Contribute", lambda: webbrowser.open_new_tab(URLS["Repository"]))
|
||||
help_menu.addAction("Forum Thread", lambda: webbrowser.open_new_tab(URLS["ForumThread"]))
|
||||
help_menu.addAction("Report an issue", lambda: webbrowser.open_new_tab(URLS["Issues"]))
|
||||
|
||||
displayMenu = self.menu.addMenu("Display")
|
||||
|
||||
tg_cp_visibility = QAction('Control Point', displayMenu)
|
||||
tg_cp_visibility.setCheckable(True)
|
||||
tg_cp_visibility.setChecked(True)
|
||||
tg_cp_visibility.toggled.connect(lambda: QLiberationMap.set_display_rule("cp", tg_cp_visibility.isChecked()))
|
||||
|
||||
tg_go_visibility = QAction('Ground Objects', displayMenu)
|
||||
tg_go_visibility.setCheckable(True)
|
||||
tg_go_visibility.setChecked(True)
|
||||
tg_go_visibility.toggled.connect(lambda: QLiberationMap.set_display_rule("go", tg_go_visibility.isChecked()))
|
||||
|
||||
tg_line_visibility = QAction('Lines', displayMenu)
|
||||
tg_line_visibility.setCheckable(True)
|
||||
tg_line_visibility.setChecked(True)
|
||||
tg_line_visibility.toggled.connect(lambda: QLiberationMap.set_display_rule("lines", tg_line_visibility.isChecked()))
|
||||
|
||||
displayMenu.addAction(tg_go_visibility)
|
||||
displayMenu.addAction(tg_cp_visibility)
|
||||
displayMenu.addAction(tg_line_visibility)
|
||||
|
||||
BIN
resources/ui/misc/new.png
Normal file
BIN
resources/ui/misc/new.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 852 B |
BIN
resources/ui/misc/open.png
Normal file
BIN
resources/ui/misc/open.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
BIN
resources/ui/misc/save.png
Normal file
BIN
resources/ui/misc/save.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
Loading…
x
Reference in New Issue
Block a user