Use all modeled radio-bands in freq-selector

This commit is contained in:
Raffson 2023-09-30 16:17:18 +02:00
parent d581af3b8a
commit 3b7077e593
No known key found for this signature in database
GPG Key ID: B0402B2C9B764D99
5 changed files with 110 additions and 45 deletions

View File

@ -18,6 +18,7 @@
* **[Waypoints]** Allow user to add navigation waypoints where possible without degrading to a custom flight-plan * **[Waypoints]** Allow user to add navigation waypoints where possible without degrading to a custom flight-plan
* **[Campaign Management]** Improve squadron retreat logic to account for parking-slot sizes * **[Campaign Management]** Improve squadron retreat logic to account for parking-slot sizes
* **[Autoplanner]** Support for auto-planning Air Assaults * **[Autoplanner]** Support for auto-planning Air Assaults
* **[UI]** Improved frequency selector to support all modeled bands for every aircraft's intra-flight radio
## Fixes ## Fixes
* **[Mission Generation]** Anti-ship strikes should use "group attack" in their attack-task * **[Mission Generation]** Anti-ship strikes should use "group attack" in their attack-task

View File

@ -190,8 +190,8 @@ RADIOS: List[Radio] = [
Radio( Radio(
"AN/ARC-222", "AN/ARC-222",
( (
RadioRange(MHz(30), MHz(88), kHz(25), Modulation.FM),
RadioRange(MHz(116), MHz(152), kHz(25), Modulation.AM), RadioRange(MHz(116), MHz(152), kHz(25), Modulation.AM),
RadioRange(MHz(30), MHz(88), kHz(25), Modulation.FM),
), ),
), ),
Radio("SCR-522", (RadioRange(MHz(100), MHz(156), kHz(25), Modulation.AM),)), Radio("SCR-522", (RadioRange(MHz(100), MHz(156), kHz(25), Modulation.AM),)),
@ -200,8 +200,8 @@ RADIOS: List[Radio] = [
Radio( Radio(
"TRT ERA 7000 V/UHF", "TRT ERA 7000 V/UHF",
( (
RadioRange(MHz(118), MHz(150), kHz(25), Modulation.AM),
RadioRange(MHz(225), MHz(400), kHz(25), Modulation.AM), RadioRange(MHz(225), MHz(400), kHz(25), Modulation.AM),
RadioRange(MHz(118), MHz(150), kHz(25), Modulation.AM),
), ),
), ),
Radio( Radio(
@ -247,10 +247,10 @@ RADIOS: List[Radio] = [
Radio( Radio(
"R-863", "R-863",
( (
RadioRange(MHz(100), MHz(150), kHz(25), Modulation.AM),
RadioRange(MHz(220), MHz(400), kHz(25), Modulation.AM), RadioRange(MHz(220), MHz(400), kHz(25), Modulation.AM),
RadioRange(MHz(100), MHz(150), kHz(25), Modulation.FM), RadioRange(MHz(100), MHz(150), kHz(25), Modulation.AM),
RadioRange(MHz(220), MHz(400), kHz(25), Modulation.FM), RadioRange(MHz(220), MHz(400), kHz(25), Modulation.FM),
RadioRange(MHz(100), MHz(150), kHz(25), Modulation.FM),
), ),
), ),
# UH-1H # UH-1H
@ -263,8 +263,8 @@ RADIOS: List[Radio] = [
Radio( Radio(
"V/UHF TRAP 136", "V/UHF TRAP 136",
( (
RadioRange(MHz(118), MHz(144), kHz(25), Modulation.AM),
RadioRange(MHz(225), MHz(400), kHz(25), Modulation.AM), RadioRange(MHz(225), MHz(400), kHz(25), Modulation.AM),
RadioRange(MHz(118), MHz(144), kHz(25), Modulation.AM),
), ),
), ),
Radio("UHF TRAP 137B", (RadioRange(MHz(225), MHz(400), kHz(25), Modulation.AM),)), Radio("UHF TRAP 137B", (RadioRange(MHz(225), MHz(400), kHz(25), Modulation.AM),)),
@ -272,9 +272,9 @@ RADIOS: List[Radio] = [
Radio( Radio(
"R-800", "R-800",
( (
RadioRange(MHz(30), MHz(88), kHz(25), Modulation.AM),
RadioRange(MHz(108), MHz(174), kHz(25), Modulation.AM),
RadioRange(MHz(225), MHz(400), kHz(25), Modulation.AM), RadioRange(MHz(225), MHz(400), kHz(25), Modulation.AM),
RadioRange(MHz(108), MHz(174), kHz(25), Modulation.AM),
RadioRange(MHz(30), MHz(88), kHz(25), Modulation.AM),
), ),
), ),
# MB-339A # MB-339A
@ -294,18 +294,11 @@ RADIOS: List[Radio] = [
"SRT-651/N", "SRT-651/N",
( (
RadioRange( RadioRange(
MHz(30), MHz(225),
MHz(88), MHz(400),
kHz(25), kHz(25),
Modulation.FM, Modulation.AM, # Actually AM/FM, but we can't represent that.
frozenset((MHz(40, 500),)), frozenset((MHz(243),)),
),
RadioRange(
MHz(108),
MHz(156),
kHz(25),
Modulation.AM,
frozenset((MHz(121, 500),)),
), ),
RadioRange( RadioRange(
MHz(156), MHz(156),
@ -315,11 +308,18 @@ RADIOS: List[Radio] = [
frozenset((MHz(156, 800),)), frozenset((MHz(156, 800),)),
), ),
RadioRange( RadioRange(
MHz(225), MHz(108),
MHz(400), MHz(156),
kHz(25), kHz(25),
Modulation.AM, # Actually AM/FM, but we can't represent that. Modulation.AM,
frozenset((MHz(243),)), frozenset((MHz(121, 500),)),
),
RadioRange(
MHz(30),
MHz(88),
kHz(25),
Modulation.FM,
frozenset((MHz(40, 500),)),
), ),
), ),
), ),

View File

@ -49,22 +49,18 @@ class QFrequencyWidget(QWidget):
return f"<b>FREQ: {freq}</b>" return f"<b>FREQ: {freq}</b>"
def open_freq_dialog(self) -> None: def open_freq_dialog(self) -> None:
range = RadioRange(MHz(100), MHz(400), kHz(25)) ranges = [RadioRange(MHz(30), MHz(400), kHz(25))]
if isinstance(self.ct, Flight): if isinstance(self.ct, Flight):
if self.ct.unit_type.intra_flight_radio is not None: if self.ct.unit_type.intra_flight_radio is not None:
range = self.ct.unit_type.intra_flight_radio.ranges[0] ranges = self.ct.unit_type.intra_flight_radio.ranges
self.frequency_dialog = QRadioFrequencyDialog(self, self.ct, range) self.frequency_dialog = QRadioFrequencyDialog(self, self.ct, ranges)
self.frequency_dialog.accepted.connect(self.assign_frequency) self.frequency_dialog.accepted.connect(self.assign_frequency)
self.frequency_dialog.show() self.frequency_dialog.show()
def assign_frequency(self) -> None: def assign_frequency(self) -> None:
hz = round(self.frequency_dialog.frequency_input.value() * 10**6) hz = round(self.frequency_dialog.frequency_input.value() * 10**6)
self._try_remove() self._try_remove()
mod = RadioFrequency.modulation mod = self.frequency_dialog.frequency_modulation.currentData()
if isinstance(self.ct, Flight):
if self.ct.unit_type.intra_flight_radio is not None:
range = self.ct.unit_type.intra_flight_radio.ranges[0]
mod = range.modulation
self.ct.frequency = RadioFrequency(hertz=hz, modulation=mod) self.ct.frequency = RadioFrequency(hertz=hz, modulation=mod)
self.gm.allocated_freqs.append(self.ct.frequency) self.gm.allocated_freqs.append(self.ct.frequency)
self.freq.setText(self._get_label_text()) self.freq.setText(self._get_label_text())

View File

@ -46,8 +46,8 @@ class QLink4Widget(QWidget):
return f"<b>LINK4: {freq}</b>" return f"<b>LINK4: {freq}</b>"
def open_freq_dialog(self) -> None: def open_freq_dialog(self) -> None:
range = RadioRange(MHz(225), MHz(400), kHz(25)) ranges = [RadioRange(MHz(225), MHz(400), kHz(25))]
self.frequency_dialog = QRadioFrequencyDialog(self, self.cp, range, link4=True) self.frequency_dialog = QRadioFrequencyDialog(self, self.cp, ranges, link4=True)
self.frequency_dialog.accepted.connect(self.assign_frequency) self.frequency_dialog.accepted.connect(self.assign_frequency)
self.frequency_dialog.show() self.frequency_dialog.show()

View File

@ -1,12 +1,14 @@
from typing import Optional from typing import Optional, Iterable
from PySide2.QtCore import Qt, QLocale from PySide2.QtCore import Qt, QLocale
from PySide2.QtGui import QIcon
from PySide2.QtWidgets import ( from PySide2.QtWidgets import (
QDialog, QDialog,
QPushButton, QPushButton,
QLabel, QLabel,
QHBoxLayout, QHBoxLayout,
QDoubleSpinBox, QDoubleSpinBox,
QComboBox,
) )
from game.radio.Link4Container import Link4Container from game.radio.Link4Container import Link4Container
@ -15,12 +17,80 @@ from game.radio.radios import RadioRange, kHz, MHz
from qt_ui.uiconstants import EVENT_ICONS from qt_ui.uiconstants import EVENT_ICONS
class QFrequencySpinbox(QDoubleSpinBox):
def __init__(self, ranges: Iterable[RadioRange]) -> None:
super().__init__()
self.setLocale(QLocale(QLocale.Language.English))
self.setDecimals(3)
self.ranges = list(ranges)
first = True
for r in ranges:
if r.minimum.mhz < self.minimum():
self.setMinimum(r.minimum.mhz)
if self.maximum() < r.maximum.mhz:
self.setMaximum(r.maximum.mhz)
if first:
self.setSingleStep(r.step.mhz)
self.setValue(r.minimum.mhz)
first = False
def correct_value(self, value: float) -> None:
for r in self.ranges:
if r.maximum.mhz == value:
self.setValue(value - r.step.mhz)
return
def stepBy(self, steps: int) -> None:
new_value = self.check_value(self.value() + (steps * self.singleStep()))
self.setValue(new_value)
def check_value(self, value: float) -> float:
for r in self.ranges:
if r.minimum.mhz <= value < r.maximum.mhz:
self.setSingleStep(r.step.mhz)
return value
minimums = [m for m in set(r.minimum.mhz for r in self.ranges) if m > value]
maximums = [m for m in set(r.maximum.mhz for r in self.ranges) if m <= value]
if not minimums or not maximums:
return self.value()
smallest_min = min(minimums)
largest_max = max(maximums)
if largest_max <= value < smallest_min:
if value < self.value():
rs = [r for r in self.ranges if r.maximum.mhz == largest_max]
value = largest_max - rs[0].step.mhz
else:
rs = [r for r in self.ranges if r.minimum.mhz == smallest_min]
value = smallest_min
r = rs[0]
self.setSingleStep(r.step.mhz)
return value
raise RuntimeError()
class QFrequencyModulationBox(QComboBox):
def __init__(self, ranges: Iterable[RadioRange], freq: float) -> None:
super().__init__()
self.setMaximumWidth(60)
self.ranges = list(ranges)
self.update_modulations(freq)
def update_modulations(self, freq: float) -> None:
self.modulations = set(
r.modulation for r in self.ranges if r.minimum.mhz <= freq < r.maximum.mhz
)
self.setEnabled(len(self.modulations) > 1)
self.clear()
for i, m in enumerate(sorted(self.modulations, key=lambda x: x.name)):
self.addItem(QIcon(), m.name, m)
class QRadioFrequencyDialog(QDialog): class QRadioFrequencyDialog(QDialog):
def __init__( def __init__(
self, self,
parent=None, parent=None,
container: Optional[RadioFrequencyContainer] = None, container: Optional[RadioFrequencyContainer] = None,
range: RadioRange = RadioRange(MHz(225), MHz(400), kHz(25)), ranges: Iterable[RadioRange] = tuple([RadioRange(MHz(225), MHz(400), kHz(25))]),
link4: bool = False, link4: bool = False,
) -> None: ) -> None:
super().__init__(parent=parent) super().__init__(parent=parent)
@ -36,20 +106,18 @@ class QRadioFrequencyDialog(QDialog):
layout = QHBoxLayout() layout = QHBoxLayout()
self.frequency_label = QLabel("FREQ (MHz):") self.frequency_label = QLabel("FREQ (MHz):")
self.frequency_input = QDoubleSpinBox() self.frequency_input = QFrequencySpinbox(ranges)
self.frequency_input.setRange( self.frequency_modulation = QFrequencyModulationBox(
range.minimum.mhz, range.maximum.mhz - range.step.mhz ranges, self.frequency_input.value()
) )
self.frequency_input.setSingleStep(range.step.mhz) self.frequency_input.valueChanged.connect(
self.frequency_input.setDecimals(3) self.frequency_modulation.update_modulations
self.frequency_input.setLocale(QLocale(QLocale.Language.English)) )
if range.minimum.mhz <= 225.0 < range.maximum.mhz: self.frequency_input.valueChanged.connect(self.frequency_input.correct_value)
self.frequency_input.setValue(225.0)
else:
mid = range.minimum.mhz + (range.maximum.mhz - range.minimum.mhz) / 2
self.frequency_input.setValue(mid)
layout.addWidget(self.frequency_label) layout.addWidget(self.frequency_label)
layout.addWidget(self.frequency_input) layout.addWidget(self.frequency_input)
layout.addWidget(self.frequency_modulation)
self.create_button = QPushButton("Save") self.create_button = QPushButton("Save")
self.create_button.clicked.connect(self.accept) self.create_button.clicked.connect(self.accept)