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]** 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 * **[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. * **[Cheat Menu]** Option to instantly transfer squadrons across bases.
* **[UI]** Add selectable units in faction overview during campaign generation.
## Fixes ## Fixes
* **[UI]** Removed deprecated options * **[UI]** Removed deprecated options

View File

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

View File

@ -1,16 +1,28 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import logging import logging
import math
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import List from typing import List
from PySide2 import QtGui, QtWidgets from PySide2 import QtGui, QtWidgets
from PySide2.QtCore import QDate, QItemSelectionModel, QPoint, Qt, Signal 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 jinja2 import Environment, FileSystemLoader, select_autoescape
from game.campaignloader.campaign import Campaign, DEFAULT_BUDGET from game.campaignloader.campaign import Campaign, DEFAULT_BUDGET
from game.dcs.aircrafttype import AircraftType from game.dcs.aircrafttype import AircraftType
from game.dcs.unittype import UnitType
from game.factions import FACTIONS, Faction from game.factions import FACTIONS, Faction
from game.settings import Settings from game.settings import Settings
from game.theater.start_generator import GameGenerator, GeneratorSettings, ModSettings from game.theater.start_generator import GameGenerator, GeneratorSettings, ModSettings
@ -236,6 +248,87 @@ class IntroPage(QtWidgets.QWizardPage):
self.setLayout(layout) 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): class FactionSelection(QtWidgets.QWizardPage):
def __init__(self, parent=None): def __init__(self, parent=None):
super(FactionSelection, self).__init__(parent) super(FactionSelection, self).__init__(parent)
@ -259,8 +352,6 @@ class FactionSelection(QtWidgets.QWizardPage):
blueFaction = QtWidgets.QLabel("<b>Player Faction :</b>") blueFaction = QtWidgets.QLabel("<b>Player Faction :</b>")
self.blueFactionSelect = QtWidgets.QComboBox() self.blueFactionSelect = QtWidgets.QComboBox()
for f in FACTIONS:
self.blueFactionSelect.addItem(f)
blueFaction.setBuddy(self.blueFactionSelect) blueFaction.setBuddy(self.blueFactionSelect)
redFaction = QtWidgets.QLabel("<b>Enemy Faction :</b>") redFaction = QtWidgets.QLabel("<b>Enemy Faction :</b>")
@ -271,26 +362,41 @@ class FactionSelection(QtWidgets.QWizardPage):
self.blueFactionDescription = QTextBrowser() self.blueFactionDescription = QTextBrowser()
self.blueFactionDescription.setReadOnly(True) self.blueFactionDescription.setReadOnly(True)
self.blueFactionDescription.setOpenExternalLinks(True) self.blueFactionDescription.setOpenExternalLinks(True)
self.blueFactionDescription.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.blueFactionDescription.setMaximumHeight(120)
self.redFactionDescription = QTextBrowser() self.redFactionDescription = QTextBrowser()
self.redFactionDescription.setReadOnly(True) self.redFactionDescription.setReadOnly(True)
self.redFactionDescription.setOpenExternalLinks(True) self.redFactionDescription.setOpenExternalLinks(True)
self.redFactionDescription.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.redFactionDescription.setMaximumHeight(120)
# Setup default selected factions # Setup default selected factions
for i, r in enumerate(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": if r == "Russia 1990":
self.redFactionSelect.setCurrentIndex(i) self.redFactionSelect.setCurrentIndex(i)
if r == "USA 2005": if r == "USA 2005":
self.blueFactionSelect.setCurrentIndex(i) 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(blueFaction, 0, 0)
self.blueGroupLayout.addWidget(self.blueFactionSelect, 0, 1) self.blueGroupLayout.addWidget(self.blueFactionSelect, 0, 1)
self.blueGroupLayout.addWidget(self.blueFactionDescription, 1, 0, 1, 2) 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(redFaction, 0, 0)
self.redGroupLayout.addWidget(self.redFactionSelect, 0, 1) self.redGroupLayout.addWidget(self.redFactionSelect, 0, 1)
self.redGroupLayout.addWidget(self.redFactionDescription, 1, 0, 1, 2) 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.blueGroupLayout)
self.factionsGroupLayout.addLayout(self.redGroupLayout) self.factionsGroupLayout.addLayout(self.redGroupLayout)
@ -348,13 +454,35 @@ class FactionSelection(QtWidgets.QWizardPage):
self.blueFactionDescription.setText(blue_faction_txt) self.blueFactionDescription.setText(blue_faction_txt)
self.redFactionDescription.setText(red_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 @property
def selected_blue_faction(self) -> Faction: def selected_blue_faction(self) -> Faction:
return FACTIONS[self.blueFactionSelect.currentText()] return self._filter_selected_units(self.blueFactionUnits)
@property @property
def selected_red_faction(self) -> Faction: def selected_red_faction(self) -> Faction:
return FACTIONS[self.redFactionSelect.currentText()] return self._filter_selected_units(self.redFactionUnits)
class TheaterConfiguration(QtWidgets.QWizardPage): class TheaterConfiguration(QtWidgets.QWizardPage):

View File

@ -76,7 +76,7 @@
"Paratrooper AKS", "Paratrooper AKS",
"Paratrooper RPG-16" "Paratrooper RPG-16"
], ],
"missiles": [ "missiles": [
"SSM SS-1C Scud-B" "SSM SS-1C Scud-B"
], ],
"preset_groups": [ "preset_groups": [

View File

@ -1,62 +1,4 @@
{{ faction.description|safe }} <strong>Description:</strong> {{ faction.description|safe }}
<br/> <br/>
<strong>Author(s):</strong> {{ faction.authors }} <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/> <br/>
<strong>Auteur(s):</strong> {{ faction.authors }} <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/>