示例#1
0
 def onManage(self):
     self.edition_menu = QGroundObjectMenu(self.window(),
                                           self.ground_object,
                                           self.buildings, self.cp,
                                           self.game)
     self.edition_menu.show()
     self.edition_menu.changed.connect(self.onEdition)
 def on_click(self) -> None:
     self.ground_object_dialog = QGroundObjectMenu(self.window(),
                                                   self.ground_object,
                                                   self.buildings,
                                                   self.control_point,
                                                   self.game)
     self.ground_object_dialog.show()
示例#3
0
 def showInfoDialog(self) -> None:
     if self.dialog is None:
         self.dialog = QGroundObjectMenu(
             None,
             self.tgo,
             self.buildings,
             self.tgo.control_point,
             self.game,
         )
     self.dialog.show()
示例#4
0
class QBaseDefenseGroupInfo(QGroupBox):
    def __init__(self, cp: ControlPoint, ground_object: TheaterGroundObject,
                 game):
        super(QBaseDefenseGroupInfo,
              self).__init__("Group : " + ground_object.obj_name)
        self.ground_object = ground_object
        self.cp = cp
        self.game = game
        self.buildings = game.theater.find_ground_objects_by_obj_name(
            self.ground_object.obj_name)
        self.init_ui()

    def init_ui(self):
        unit_dict = {}
        layout = QGridLayout()
        for g in self.ground_object.groups:
            for u in g.units:
                if u.type in unit_dict.keys():
                    unit_dict[u.type] = unit_dict[u.type] + 1
                else:
                    unit_dict[u.type] = 1
        i = 0
        for k, v in unit_dict.items():
            #icon = QLabel()
            #if k in VEHICLES_ICONS.keys():
            #    icon.setPixmap(VEHICLES_ICONS[k])
            #else:
            #    icon.setText("<b>" + k[:6] + "</b>")
            #icon.setProperty("style", "icon-plane")
            #layout.addWidget(icon, i, 0)
            layout.addWidget(
                QLabel(str(v) + " x " + "<strong>" + k + "</strong>"), i, 0)
            i = i + 1

        manage_button = QPushButton("Manage")
        manage_button.setProperty("style", "btn-success")
        manage_button.setMaximumWidth(180)
        manage_button.clicked.connect(self.onManage)
        layout.addWidget(manage_button, i + 1, 0)
        self.setLayout(layout)

    def onManage(self):
        self.editionMenu = QGroundObjectMenu(self.window(), self.ground_object,
                                             self.buildings, self.cp,
                                             self.game)
        self.editionMenu.show()
 def open_tgo_info_dialog(self, tgo: TheaterGroundObject) -> None:
     QGroundObjectMenu(self, tgo, tgo.control_point, self.game).show()
示例#6
0
class QBaseDefenseGroupInfo(QGroupBox):
    def __init__(self, cp: ControlPoint, ground_object: TheaterGroundObject,
                 game):
        super(QBaseDefenseGroupInfo,
              self).__init__("Group : " + ground_object.obj_name)
        self.ground_object = ground_object
        self.cp = cp
        self.game = game
        self.buildings = game.theater.find_ground_objects_by_obj_name(
            self.ground_object.obj_name)

        self.main_layout = QVBoxLayout()
        self.unit_layout = QGridLayout()

        self.init_ui()

    def init_ui(self):

        self.buildLayout()
        self.main_layout.addLayout(self.unit_layout)
        if not self.cp.captured and not self.ground_object.is_dead:
            attack_button = QPushButton("Attack")
            attack_button.setProperty("style", "btn-danger")
            attack_button.setMaximumWidth(180)
            attack_button.clicked.connect(self.onAttack)
            self.main_layout.addWidget(attack_button, 0, Qt.AlignLeft)

        if self.cp.captured:
            manage_button = QPushButton("Manage")
            manage_button.setProperty("style", "btn-success")
            manage_button.setMaximumWidth(180)
            manage_button.clicked.connect(self.onManage)
            self.main_layout.addWidget(manage_button, 0, Qt.AlignLeft)

        self.setLayout(self.main_layout)

    def buildLayout(self):
        unit_dict = {}
        for i in range(self.unit_layout.rowCount()):
            for j in range(self.unit_layout.columnCount()):
                item = self.unit_layout.itemAtPosition(i, j)
                if item is not None and item.widget() is not None:
                    item.widget().setParent(None)
                    print("Remove " + str(i) + ", " + str(j))

        for g in self.ground_object.groups:
            for u in g.units:
                if u.type in unit_dict.keys():
                    unit_dict[u.type] = unit_dict[u.type] + 1
                else:
                    unit_dict[u.type] = 1
        i = 0
        for k, v in unit_dict.items():
            icon = QLabel()
            if k in VEHICLES_ICONS.keys():
                icon.setPixmap(VEHICLES_ICONS[k])
            else:
                icon.setText("<b>" + k[:8] + "</b>")
            icon.setProperty("style", "icon-armor")
            self.unit_layout.addWidget(icon, i, 0)
            unit_display_name = k
            unit_type = vehicles.vehicle_map.get(k)
            if unit_type is not None:
                unit_display_name = db.unit_get_expanded_info(
                    self.game.enemy_country, unit_type, 'name')
            self.unit_layout.addWidget(
                QLabel(
                    str(v) + " x " + "<strong>" + unit_display_name +
                    "</strong>"), i, 1)
            i = i + 1

        if len(unit_dict.items()) == 0:
            self.unit_layout.addWidget(QLabel("/"), 0, 0)

        self.setLayout(self.main_layout)

    def onAttack(self):
        Dialog.open_new_package_dialog(self.ground_object,
                                       parent=self.window())

    def onManage(self):
        self.edition_menu = QGroundObjectMenu(self.window(),
                                              self.ground_object,
                                              self.buildings, self.cp,
                                              self.game)
        self.edition_menu.show()
        self.edition_menu.changed.connect(self.onEdition)

    def onEdition(self):
        self.buildLayout()
示例#7
0
class GroundObjectJs(QObject):
    nameChanged = Signal()
    controlPointNameChanged = Signal()
    unitsChanged = Signal()
    blueChanged = Signal()
    positionChanged = Signal()
    samThreatRangesChanged = Signal()
    samDetectionRangesChanged = Signal()
    categoryChanged = Signal()
    deadChanged = Signal()

    def __init__(self, tgo: TheaterGroundObject, game: Game) -> None:
        super().__init__()
        self.tgo = tgo
        self.game = game
        self.theater = game.theater
        self.buildings = self.theater.find_ground_objects_by_obj_name(self.tgo.obj_name)
        self.dialog: Optional[QGroundObjectMenu] = None

    @Slot()
    def showInfoDialog(self) -> None:
        if self.dialog is None:
            self.dialog = QGroundObjectMenu(
                None,
                self.tgo,
                self.buildings,
                self.tgo.control_point,
                self.game,
            )
        self.dialog.show()

    @Slot()
    def showPackageDialog(self) -> None:
        Dialog.open_new_package_dialog(self.tgo)

    @Property(str, notify=nameChanged)
    def name(self) -> str:
        return self.tgo.name

    @Property(str, notify=controlPointNameChanged)
    def controlPointName(self) -> str:
        return self.tgo.control_point.name

    @Property(str, notify=categoryChanged)
    def category(self) -> str:
        return self.tgo.category

    @staticmethod
    def make_unit_name(unit: Unit, dead: bool) -> str:
        dead_label = " [DEAD]" if dead else ""
        unit_display_name = unit.type
        dcs_unit_type = vehicle_map.get(unit.type)
        if dcs_unit_type is not None:
            # TODO: Make the TGO contain GroundUnitType instead of the pydcs Group.
            # This is a hack because we can't know which variant was used.
            try:
                unit_display_name = next(
                    GroundUnitType.for_dcs_type(dcs_unit_type)
                ).name
            except StopIteration:
                pass
        return f"Unit #{unit.id} - {unit_display_name}{dead_label}"

    @Property(list, notify=unitsChanged)
    def units(self) -> List[str]:
        units = []
        # TGOs with a non-empty group set are non-building TGOs. Building TGOs have no
        # groups set, but instead are one TGO per building "group" (DCS doesn't support
        # groups of statics) all with the same name.
        if self.tgo.groups:
            for unit in self.tgo.units:
                units.append(self.make_unit_name(unit, dead=False))
            for unit in self.tgo.dead_units:
                units.append(self.make_unit_name(unit, dead=True))
        else:
            for building in self.buildings:
                dead = " [DEAD]" if building.is_dead else ""
                units.append(f"{building.dcs_identifier}{dead}")
        return units

    @Property(bool, notify=blueChanged)
    def blue(self) -> bool:
        return self.tgo.control_point.captured

    @Property(list, notify=positionChanged)
    def position(self) -> LeafletLatLon:
        ll = self.theater.point_to_ll(self.tgo.position)
        return [ll.latitude, ll.longitude]

    @Property(bool, notify=deadChanged)
    def dead(self) -> bool:
        if not self.tgo.groups:
            return all(b.is_dead for b in self.buildings)
        return not any(g.units for g in self.tgo.groups)

    @Property(list, notify=samThreatRangesChanged)
    def samThreatRanges(self) -> List[float]:
        if not self.tgo.might_have_aa:
            return []

        ranges = []
        for group in self.tgo.groups:
            threat_range = self.tgo.threat_range(group)
            if threat_range:
                ranges.append(threat_range.meters)
        return ranges

    @Property(list, notify=samDetectionRangesChanged)
    def samDetectionRanges(self) -> List[float]:
        if not self.tgo.might_have_aa:
            return []

        ranges = []
        for group in self.tgo.groups:
            detection_range = self.tgo.detection_range(group)
            if detection_range:
                ranges.append(detection_range.meters)
        return ranges
class QMapGroundObject(QMapObject):
    def __init__(
        self,
        parent,
        x: float,
        y: float,
        w: float,
        h: float,
        control_point: ControlPoint,
        ground_object: TheaterGroundObject,
        game: Game,
        buildings: Optional[List[TheaterGroundObject]] = None,
    ) -> None:
        super().__init__(x, y, w, h, mission_target=ground_object)
        self.ground_object = ground_object
        self.control_point = control_point
        self.parent = parent
        self.game = game
        self.setZValue(2)
        self.buildings = buildings if buildings is not None else []
        self.setFlag(QGraphicsItem.ItemIgnoresTransformations, False)
        self.ground_object_dialog: Optional[QGroundObjectMenu] = None
        self.setToolTip(self.tooltip)

    @property
    def tooltip(self) -> str:
        lines = [
            f"[{self.ground_object.obj_name}]",
            f"${self.production_per_turn} per turn",
        ]
        if self.ground_object.groups:
            units = {}
            for g in self.ground_object.groups:
                for u in g.units:
                    if u.type in units:
                        units[u.type] = units[u.type] + 1
                    else:
                        units[u.type] = 1

            for unit in units.keys():
                lines.append(f"{unit} x {units[unit]}")
        else:
            for building in self.buildings:
                if not building.is_dead:
                    lines.append(f"{building.dcs_identifier}")

        return "\n".join(lines)

    @property
    def production_per_turn(self) -> int:
        production = 0
        for building in self.buildings:
            if building.is_dead:
                continue
            if building.category in REWARDS.keys():
                production += REWARDS[building.category]
        return production

    def paint(self, painter, option, widget=None) -> None:
        player_icons = "_blue"
        enemy_icons = ""

        if DisplayOptions.ground_objects:
            painter.save()

            cat = self.ground_object.category
            if cat == "aa" and self.ground_object.sea_object:
                cat = "ship"
            if isinstance(self.ground_object, MissileSiteGroundObject):
                cat = "missile"

            rect = QRect(
                option.rect.x() + 2,
                option.rect.y(),
                option.rect.width() - 2,
                option.rect.height(),
            )

            is_dead = self.ground_object.is_dead
            for building in self.buildings:
                if not building.is_dead:
                    is_dead = False
                    break

            if cat == "aa":
                has_threat = False
                for group in self.ground_object.groups:
                    if self.ground_object.threat_range(
                            group).distance_in_meters > 0:
                        has_threat = True

            if not is_dead and not self.control_point.captured:
                if cat == "aa" and not has_threat:
                    painter.drawPixmap(rect,
                                       const.ICONS["nothreat" + enemy_icons])
                else:
                    painter.drawPixmap(rect, const.ICONS[cat + enemy_icons])
            elif not is_dead:
                if cat == "aa" and not has_threat:
                    painter.drawPixmap(rect,
                                       const.ICONS["nothreat" + player_icons])
                else:
                    painter.drawPixmap(rect, const.ICONS[cat + player_icons])
            else:
                painter.drawPixmap(rect, const.ICONS["destroyed"])

            self.draw_health_gauge(painter, option)
            painter.restore()

    def draw_health_gauge(self, painter, option) -> None:
        units_alive = 0
        units_dead = 0

        if len(self.ground_object.groups) == 0:
            for building in self.buildings:
                if building.dcs_identifier in FORTIFICATION_BUILDINGS:
                    continue
                if building.is_dead:
                    units_dead += 1
                else:
                    units_alive += 1

        for g in self.ground_object.groups:
            units_alive += len(g.units)
            if hasattr(g, "units_losts"):
                units_dead += len(g.units_losts)

        if units_dead + units_alive > 0:
            ratio = float(units_alive) / (float(units_dead) +
                                          float(units_alive))
            bar_height = ratio * option.rect.height()
            painter.fillRect(
                option.rect.x(),
                option.rect.y(),
                2,
                option.rect.height(),
                QBrush(const.COLORS["dark_red"]),
            )
            painter.fillRect(
                option.rect.x(),
                option.rect.y(),
                2,
                bar_height,
                QBrush(const.COLORS["green"]),
            )

    def on_click(self) -> None:
        self.ground_object_dialog = QGroundObjectMenu(
            self.window(),
            self.ground_object,
            self.buildings,
            self.control_point,
            self.game,
        )
        self.ground_object_dialog.show()
示例#9
0
 def openEditionMenu(self):
     self.editionMenu = QGroundObjectMenu(self.window(), self.model, self.buildings, self.cp, self.game)
     self.editionMenu.show()
示例#10
0
class QMapGroundObject(QGraphicsRectItem):

    def __init__(self, parent, x: float, y: float, w: float, h: float, cp: ControlPoint, model: TheaterGroundObject, game:Game, buildings=[]):
        super(QMapGroundObject, self).__init__(x, y, w, h)
        self.model = model
        self.cp = cp
        self.parent = parent
        self.game = game
        self.setAcceptHoverEvents(True)
        self.setZValue(2)
        self.buildings = buildings
        self.setFlag(QGraphicsItem.ItemIgnoresTransformations, False)

        if len(self.model.groups) > 0:
            units = {}
            for g in self.model.groups:
                print(g)
                for u in g.units:
                    if u.type in units.keys():
                        units[u.type] = units[u.type]+1
                    else:
                        units[u.type] = 1
            tooltip = "[" + self.model.obj_name + "]" + "\n"
            for unit in units.keys():
                tooltip = tooltip + str(unit) + "x" + str(units[unit]) + "\n"
            self.setToolTip(tooltip[:-1])
        else:
            tooltip = "[" + self.model.obj_name + "]" + "\n"
            for building in buildings:
                if not building.is_dead:
                    tooltip = tooltip + str(building.dcs_identifier) + "\n"
            self.setToolTip(tooltip[:-1])

    def mousePressEvent(self, event:QGraphicsSceneMouseEvent):
        self.openEditionMenu()

    def paint(self, painter, option, widget=None):
        #super(QMapControlPoint, self).paint(painter, option, widget)

        playerIcons = "_blue"
        enemyIcons = ""

        if self.parent.get_display_rule("go"):
            painter.save()

            cat = self.model.category
            if cat == "aa" and self.model.sea_object:
                cat = "ship"

            rect = QRect(option.rect.x()+2,option.rect.y(),option.rect.width()-2,option.rect.height())

            is_dead = self.model.is_dead
            for building in self.buildings:
                if not building.is_dead:
                    is_dead = False
                    break

            if not is_dead and not self.cp.captured:
                painter.drawPixmap(rect, CONST.ICONS[cat + enemyIcons])
            elif not is_dead:
                painter.drawPixmap(rect, CONST.ICONS[cat + playerIcons])
            else:
                painter.drawPixmap(rect, CONST.ICONS["destroyed"])

            self.drawHealthGauge(painter, option)
            painter.restore()

    def drawHealthGauge(self, painter, option):
        units_alive = 0
        units_dead = 0

        if len(self.model.groups) == 0:
            for building in self.buildings:
                if building.dcs_identifier in FORTIFICATION_BUILDINGS:
                    continue
                if building.is_dead:
                    units_dead += 1
                else:
                    units_alive += 1

        for g in self.model.groups:
            units_alive += len(g.units)
            if hasattr(g, "units_losts"):
                units_dead += len(g.units_losts)

        if units_dead + units_alive > 0:
            ratio = float(units_alive)/(float(units_dead) + float(units_alive))
            bar_height = ratio * option.rect.height()
            painter.fillRect(option.rect.x(), option.rect.y(), 2, option.rect.height(), QBrush(CONST.COLORS["dark_red"]))
            painter.fillRect(option.rect.x(), option.rect.y(), 2, bar_height, QBrush(CONST.COLORS["green"]))


    def hoverEnterEvent(self, event: QGraphicsSceneHoverEvent):
        self.update()
        self.setCursor(Qt.PointingHandCursor)

    def mouseMoveEvent(self, event:QGraphicsSceneMouseEvent):
        self.update()
        self.setCursor(Qt.PointingHandCursor)

    def hoverLeaveEvent(self, event: QGraphicsSceneHoverEvent):
        self.update()

    def openEditionMenu(self):
        self.editionMenu = QGroundObjectMenu(self.window(), self.model, self.buildings, self.cp, self.game)
        self.editionMenu.show()
示例#11
0
 def onManage(self):
     self.editionMenu = QGroundObjectMenu(self.window(), self.ground_object,
                                          self.buildings, self.cp,
                                          self.game)
     self.editionMenu.show()