Make units selectable in faction overview during campaign gen

Resolves #35
Resolves #40
This commit is contained in:
Raffson 2022-12-31 23:25:26 +01:00
parent cd4ace4ad5
commit 192741af36
No known key found for this signature in database
GPG Key ID: B0402B2C9B764D99
6 changed files with 145 additions and 120 deletions

View File

@ -4,6 +4,7 @@
* **[Mission Generation]** Given a CAS flight was planned, delay ground force attack until first CAS flight is on station
* **[Mission Generation]** Add option to switch ATFLIR to LITENING automatically for ground based F-18C flights
* **[Cheat Menu]** Option to instantly transfer squadrons across bases.
* **[UI]** Add selectable units in faction overview during campaign generation.
## Fixes
* **[UI]** Removed deprecated options

View File

@ -60,7 +60,7 @@ class Faction:
description: str = field(default="")
# Available aircraft
aircrafts: List[AircraftType] = field(default_factory=list)
aircraft: List[AircraftType] = field(default_factory=list)
# Available awacs aircraft
awacs: List[AircraftType] = field(default_factory=list)
@ -178,6 +178,10 @@ class Faction:
)
return sorted(air_defenses)
@cached_property
def aircrafts(self) -> list[UnitType[Any]]:
return list(self.aircraft + self.awacs + self.tankers)
@classmethod
def from_json(cls: Type[Faction], json: Dict[str, Any]) -> Faction:
faction = Faction(locales=json.get("locales"))
@ -206,14 +210,10 @@ class Faction:
faction.authors = json.get("authors", "")
faction.description = json.get("description", "")
faction.aircrafts = [AircraftType.named(n) for n in json.get("aircrafts", [])]
faction.aircraft = [AircraftType.named(n) for n in json.get("aircrafts", [])]
faction.awacs = [AircraftType.named(n) for n in json.get("awacs", [])]
faction.tankers = [AircraftType.named(n) for n in json.get("tankers", [])]
faction.aircrafts = list(
set(faction.aircrafts + faction.awacs + faction.tankers)
)
faction.frontline_units = [
GroundUnitType.named(n) for n in json.get("frontline_units", [])
]

View File

@ -1,16 +1,28 @@
from __future__ import unicode_literals
import logging
import math
from datetime import datetime, timedelta
from typing import List
from PySide2 import QtGui, QtWidgets
from PySide2.QtCore import QDate, QItemSelectionModel, QPoint, Qt, Signal
from PySide2.QtWidgets import QCheckBox, QLabel, QTextEdit, QVBoxLayout, QTextBrowser
from PySide2.QtWidgets import (
QCheckBox,
QLabel,
QTextEdit,
QVBoxLayout,
QTextBrowser,
QWidget,
QGridLayout,
QScrollArea,
QSizePolicy,
)
from jinja2 import Environment, FileSystemLoader, select_autoescape
from game.campaignloader.campaign import Campaign, DEFAULT_BUDGET
from game.dcs.aircrafttype import AircraftType
from game.dcs.unittype import UnitType
from game.factions import FACTIONS, Faction
from game.settings import Settings
from game.theater.start_generator import GameGenerator, GeneratorSettings, ModSettings
@ -236,6 +248,87 @@ class IntroPage(QtWidgets.QWizardPage):
self.setLayout(layout)
class QFactionUnits(QScrollArea):
def __init__(self, faction: Faction, parent=None):
super().__init__()
self.setWidgetResizable(True)
self.content = QWidget()
self.setWidget(self.content)
self.parent = parent
self.faction = faction
self._create_checkboxes()
def _add_checkboxes(self, units: list, counter: int, grid: QGridLayout) -> int:
counter += 1
for i, v in enumerate(sorted(units, key=lambda x: x.name), counter):
cb = QCheckBox(v.name)
cb.setCheckState(Qt.CheckState.Checked)
self.checkboxes[v.name] = cb
grid.addWidget(cb, i, 1)
counter += 1
counter += 1
return counter
def _create_checkboxes(self):
counter = 0
self.checkboxes: dict[str, QCheckBox] = {}
grid = QGridLayout()
if len(self.faction.aircraft) > 0:
grid.addWidget(QLabel("<strong>Aircraft:</strong>"), counter, 0)
counter = self._add_checkboxes(self.faction.aircraft, counter, grid)
if len(self.faction.awacs) > 0:
grid.addWidget(QLabel("<strong>AWACS:</strong>"), counter, 0)
counter = self._add_checkboxes(self.faction.awacs, counter, grid)
if len(self.faction.tankers) > 0:
grid.addWidget(QLabel("<strong>Tankers:</strong>"), counter, 0)
counter = self._add_checkboxes(self.faction.tankers, counter, grid)
if len(self.faction.frontline_units) > 0:
grid.addWidget(QLabel("<strong>Frontlines vehicles:</strong>"), counter, 0)
counter = self._add_checkboxes(self.faction.frontline_units, counter, grid)
if len(self.faction.artillery_units) > 0:
grid.addWidget(QLabel("<strong>Artillery units:</strong>"), counter, 0)
counter = self._add_checkboxes(self.faction.artillery_units, counter, grid)
if len(self.faction.logistics_units) > 0:
grid.addWidget(QLabel("<strong>Logistics units:</strong>"), counter, 0)
counter = self._add_checkboxes(self.faction.logistics_units, counter, grid)
if len(self.faction.infantry_units) > 0:
grid.addWidget(QLabel("<strong>Infantry units:</strong>"), counter, 0)
counter = self._add_checkboxes(self.faction.infantry_units, counter, grid)
if len(self.faction.preset_groups) > 0:
grid.addWidget(QLabel("<strong>Preset groups:</strong>"), counter, 0)
counter = self._add_checkboxes(self.faction.preset_groups, counter, grid)
if len(self.faction.air_defense_units) > 0:
grid.addWidget(QLabel("<strong>Air defenses:</strong>"), counter, 0)
counter = self._add_checkboxes(
self.faction.air_defense_units, counter, grid
)
if len(self.faction.naval_units) > 0:
grid.addWidget(QLabel("<strong>Naval units:</strong>"), counter, 0)
counter = self._add_checkboxes(self.faction.naval_units, counter, grid)
if len(self.faction.missiles) > 0:
grid.addWidget(QLabel("<strong>Missile units:</strong>"), counter, 0)
self._add_checkboxes(self.faction.missiles, counter, grid)
self.content.setLayout(grid)
def updateFaction(self, faction: Faction):
self.faction = faction
self.content = QWidget()
self.setWidget(self.content)
self._create_checkboxes()
self.update()
if self.parent:
self.parent.update()
def updateFactionUnits(self, units: list):
deletes = []
for a in units:
if not self.checkboxes[a.name].isChecked():
deletes.append(a)
for d in deletes:
units.remove(d)
class FactionSelection(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super(FactionSelection, self).__init__(parent)
@ -259,8 +352,6 @@ class FactionSelection(QtWidgets.QWizardPage):
blueFaction = QtWidgets.QLabel("<b>Player Faction :</b>")
self.blueFactionSelect = QtWidgets.QComboBox()
for f in FACTIONS:
self.blueFactionSelect.addItem(f)
blueFaction.setBuddy(self.blueFactionSelect)
redFaction = QtWidgets.QLabel("<b>Enemy Faction :</b>")
@ -271,26 +362,41 @@ class FactionSelection(QtWidgets.QWizardPage):
self.blueFactionDescription = QTextBrowser()
self.blueFactionDescription.setReadOnly(True)
self.blueFactionDescription.setOpenExternalLinks(True)
self.blueFactionDescription.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.blueFactionDescription.setMaximumHeight(120)
self.redFactionDescription = QTextBrowser()
self.redFactionDescription.setReadOnly(True)
self.redFactionDescription.setOpenExternalLinks(True)
self.redFactionDescription.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.redFactionDescription.setMaximumHeight(120)
# Setup default selected factions
for i, r in enumerate(FACTIONS):
self.redFactionSelect.addItem(r)
self.blueFactionSelect.addItem(r, FACTIONS[r])
self.redFactionSelect.addItem(r, FACTIONS[r])
if r == "Russia 1990":
self.redFactionSelect.setCurrentIndex(i)
if r == "USA 2005":
self.blueFactionSelect.setCurrentIndex(i)
# Faction units
self.blueFactionUnits = QFactionUnits(
self.blueFactionSelect.currentData(), self.blueGroupLayout
)
self.redFactionUnits = QFactionUnits(
self.redFactionSelect.currentData(), self.redGroupLayout
)
self.blueGroupLayout.addWidget(blueFaction, 0, 0)
self.blueGroupLayout.addWidget(self.blueFactionSelect, 0, 1)
self.blueGroupLayout.addWidget(self.blueFactionDescription, 1, 0, 1, 2)
self.blueGroupLayout.addWidget(self.blueFactionUnits, 2, 0, 1, 2)
self.redGroupLayout.addWidget(redFaction, 0, 0)
self.redGroupLayout.addWidget(self.redFactionSelect, 0, 1)
self.redGroupLayout.addWidget(self.redFactionDescription, 1, 0, 1, 2)
self.redGroupLayout.addWidget(self.redFactionUnits, 2, 0, 1, 2)
self.factionsGroupLayout.addLayout(self.blueGroupLayout)
self.factionsGroupLayout.addLayout(self.redGroupLayout)
@ -348,13 +454,35 @@ class FactionSelection(QtWidgets.QWizardPage):
self.blueFactionDescription.setText(blue_faction_txt)
self.redFactionDescription.setText(red_faction_txt)
self.blueGroupLayout.removeWidget(self.blueFactionUnits)
self.blueFactionUnits.updateFaction(blue_faction)
self.blueGroupLayout.addWidget(self.blueFactionUnits, 2, 0, 1, 2)
self.redGroupLayout.removeWidget(self.redFactionUnits)
self.redFactionUnits.updateFaction(red_faction)
self.redGroupLayout.addWidget(self.redFactionUnits, 2, 0, 1, 2)
@staticmethod
def _filter_selected_units(qfu: QFactionUnits) -> Faction:
qfu.updateFactionUnits(qfu.faction.aircrafts)
qfu.updateFactionUnits(qfu.faction.awacs)
qfu.updateFactionUnits(qfu.faction.tankers)
qfu.updateFactionUnits(qfu.faction.frontline_units)
qfu.updateFactionUnits(qfu.faction.artillery_units)
qfu.updateFactionUnits(qfu.faction.logistics_units)
qfu.updateFactionUnits(qfu.faction.infantry_units)
qfu.updateFactionUnits(qfu.faction.preset_groups)
qfu.updateFactionUnits(qfu.faction.air_defense_units)
qfu.updateFactionUnits(qfu.faction.naval_units)
qfu.updateFactionUnits(qfu.faction.missiles)
return qfu.faction
@property
def selected_blue_faction(self) -> Faction:
return FACTIONS[self.blueFactionSelect.currentText()]
return self._filter_selected_units(self.blueFactionUnits)
@property
def selected_red_faction(self) -> Faction:
return FACTIONS[self.redFactionSelect.currentText()]
return self._filter_selected_units(self.redFactionUnits)
class TheaterConfiguration(QtWidgets.QWizardPage):

View File

@ -1,62 +1,4 @@
{{ faction.description|safe }}
<strong>Description:</strong> {{ faction.description|safe }}
<br/>
<strong>Author(s):</strong> {{ faction.authors }}
<br/><br/>
<strong>Potential aircraft:</strong>
<p>
The aircraft that will be present in the game are specified by the campaign.
Only aircraft in this list will be allowed, but not all aircraft in this
list will necessarily be available.
</p>
<p>
If the campaign you chose doesn't include the aircraft you want to fly, you
can mod the campaign by following the squadron section of the
<a style="color: #ffffff"
href="https://github.com/dcs-liberation/dcs_liberation/wiki/Custom-Campaigns#squadron-configuration">
custom campaigns guide</a>.
</p>
<ul>
{% for aircraft in faction.aircrafts | sort(attribute="name") %}
<li>{{aircraft.name}}</li>
{% endfor %}
</ul>
<br/>
<strong>Frontlines vehicles:</strong>
<ul>
{% for vehicle in faction.frontline_units | sort(attribute="name") %}
<li>
{% if vehicle.name is not none %}
{{ vehicle.name }}
{% else %}
{{ vehicle.id }}
{%endif %}
</li>
{% endfor %}
</ul>
<br/>
<strong>Artillery units:</strong>
<ul>
{% for arty in faction.artillery_units | sort(attribute="name") %}
<li>
{% if arty.name is not none %}
{{ arty.name }}
{% else %}
{{ arty.id }}
{%endif %}
</li>
{% endfor %}
</ul>
<br/>
<strong>Air defenses:</strong>
<ul>
{% for air_defense in faction.air_defenses | sort() %}
<li>{{air_defense}}</li>
{% endfor %}
</ul>
<br/>

View File

@ -1,50 +1,4 @@
{{ faction.description|safe }}
<strong>Description:</strong> {{ faction.description|safe }}
<br/>
<strong>Auteur(s):</strong> {{ faction.authors }}
<br/><br/>
<strong>Aéronefs disponibles :</strong>
<ul>
{% for aircraft in faction.aircrafts | sort(attribute="name") %}
<li>{{aircraft.name}}</li>
{% endfor %}
</ul>
<br/>
<strong>Véhicules disponibles :</strong>
<ul>
{% for vehicle in faction.frontline_units | sort(attribute="name") %}
<li>
{% if vehicle.name is not none %}
{{ vehicle.name }}
{% else %}
{{ vehicle.id }}
{%endif %}
</li>
{% endfor %}
</ul>
<br/>
<strong>Pièces d'artillerie :</strong>
<ul>
{% for arty in faction.artillery_units | sort(attribute="name") %}
<li>
{% if arty.name is not none %}
{{ arty.name }}
{% else %}
{{ arty.id }}
{%endif %}
</li>
{% endfor %}
</ul>
<br/>
<strong>Défense Sol-Air:</strong>
<ul>
{% for air_defense in faction.air_defenses | sort() %}
<li>{{air_defense}}</li>
{% endfor %}
</ul>
<br/>