Add initial version of the unit info window.
DCS features a massive range of aircraft and land vehicles, and not all of them make their role(s) clear just from the name alone. What this commit does is add an "information" button (and resultant window) to the recruitment section. This should allow new players to understand what each unit is/does. Current state - every aircraft has a country of origin and an introduction date for that variant. Some also have a small placeholder description, taken from ED's store page for that aircraft. There is also a placeholder picture (taken from a rejected image from my own personal photography) that will, in time, show a banner image of each unit. Todo - add appropriate screenshots for each aircraft's banner, replace the placeholder text for each aircraft (this will take a while...) and add more data points for each unit type, such as a unit role (i.e. "air-superiority fighter", "multirole fighter", etc) or perhaps a list of weapons carried. I also haven't made a start on the huge number of ground units yet.
@ -25,6 +25,7 @@ Saves from 2.3 are not compatible with 2.4.
|
||||
* **[UI]** Unit names are now prettier and more accurate, and can now be set per-country for added historical flavour.
|
||||
* **[UI]** Default loadout is now shown for flights with no custom loadout selected.
|
||||
* **[UI]** Aircraft for a new flight are now only selectable if they match the task type for that flight.
|
||||
* **[UI]** WIP - There is now a unit info button for each unit in the recruitment list, that should help newer players learn what each unit does.
|
||||
* **[Factions]** Added option for date-based loadout restriction. Active radar homing missiles are handled, patches welcome for the other thousand weapons.
|
||||
* **[Factions]** Added Poland 2010 faction.
|
||||
* **[Factions]** Added Greece 2005 faction.
|
||||
|
||||
42
game/db.py
@ -174,7 +174,7 @@ from pydcs_extensions.mb339.mb339 import MB_339PAN
|
||||
from pydcs_extensions.rafale.rafale import Rafale_A_S, Rafale_M, Rafale_B
|
||||
from pydcs_extensions.su57.su57 import Su_57
|
||||
|
||||
PRETTYNAMES_PATH = Path("./resources/units/pretty_unit_names.json")
|
||||
UNITINFOTEXT_PATH = Path("./resources/units/unit_info_text.json")
|
||||
|
||||
plane_map["A-4E-C"] = A_4E_C
|
||||
plane_map["MB-339PAN"] = MB_339PAN
|
||||
@ -1366,25 +1366,33 @@ def unit_type_name(unit_type) -> str:
|
||||
def unit_type_name_2(unit_type) -> str:
|
||||
return unit_type.name and unit_type.name or unit_type.id
|
||||
|
||||
def unit_pretty_name(country_name: str, unit_type) -> str:
|
||||
def unit_get_expanded_info(country_name: str, unit_type, request_type: str) -> str:
|
||||
original_name = unit_type.name and unit_type.name or unit_type.id
|
||||
default_name = None
|
||||
faction_name = None
|
||||
with PRETTYNAMES_PATH.open("r", encoding="utf-8") as fdata:
|
||||
default_value = None
|
||||
faction_value = None
|
||||
with UNITINFOTEXT_PATH.open("r", encoding="utf-8") as fdata:
|
||||
data = json.load(fdata, encoding="utf-8")
|
||||
type_exists = data.get(original_name)
|
||||
if type_exists is None:
|
||||
return original_name
|
||||
for faction in type_exists:
|
||||
if default_name is None:
|
||||
default_name = faction.get("default")
|
||||
if faction_name is None:
|
||||
faction_name = faction.get(country_name)
|
||||
if default_name is None:
|
||||
return original_name
|
||||
if faction_name is None:
|
||||
return default_name
|
||||
return faction_name
|
||||
if type_exists is not None:
|
||||
for faction in type_exists:
|
||||
if default_value is None:
|
||||
default_exists = faction.get("default")
|
||||
if default_exists is not None:
|
||||
default_value = default_exists.get(request_type)
|
||||
if faction_value is None:
|
||||
faction_exists = faction.get(country_name)
|
||||
if faction_exists is not None:
|
||||
faction_value = faction_exists.get(request_type)
|
||||
if default_value is None:
|
||||
if request_type == "text":
|
||||
return "I hate to say it, but it looks like the unit you're searching for doesn't exist. Perhaps the archives are incomplete..."
|
||||
if request_type == "name":
|
||||
return original_name
|
||||
else:
|
||||
return "Unknown"
|
||||
if faction_value is None:
|
||||
return default_value
|
||||
return faction_value
|
||||
|
||||
def unit_type_from_name(name: str) -> Optional[Type[UnitType]]:
|
||||
if name in vehicle_map:
|
||||
|
||||
@ -182,7 +182,7 @@ class Flight:
|
||||
return f"[{self.flight_type}] {self.count} x {name}"
|
||||
|
||||
def __str__(self):
|
||||
name = db.unit_pretty_name(self.country, self.unit_type)
|
||||
name = db.unit_get_expanded_info(self.country, self.unit_type, 'name')
|
||||
if self.custom_name:
|
||||
return f"{self.custom_name} {self.count} x {name}"
|
||||
return f"[{self.flight_type}] {self.count} x {name}"
|
||||
|
||||
@ -74,6 +74,7 @@ def run_ui(game: Optional[Game] = None) -> None:
|
||||
uiconstants.load_event_icons()
|
||||
uiconstants.load_aircraft_icons()
|
||||
uiconstants.load_vehicle_icons()
|
||||
uiconstants.load_aircraft_banners()
|
||||
|
||||
# Replace DCS Mission scripting file to allow DCS Liberation to work
|
||||
try:
|
||||
|
||||
@ -72,6 +72,7 @@ COLORS: Dict[str, QColor] = {
|
||||
|
||||
CP_SIZE = 12
|
||||
|
||||
AIRCRAFT_BANNERS: Dict[str, QPixmap] = {}
|
||||
AIRCRAFT_ICONS: Dict[str, QPixmap] = {}
|
||||
VEHICLES_ICONS: Dict[str, QPixmap] = {}
|
||||
ICONS: Dict[str, QPixmap] = {}
|
||||
@ -171,9 +172,9 @@ def load_event_icons():
|
||||
EVENT_ICONS[image[:-4]] = QPixmap(os.path.join("./resources/ui/events/", image))
|
||||
|
||||
def load_aircraft_icons():
|
||||
for aircraft in os.listdir("./resources/ui/units/aircrafts/"):
|
||||
for aircraft in os.listdir("./resources/ui/units/aircrafts/icons/"):
|
||||
if aircraft.endswith(".jpg"):
|
||||
AIRCRAFT_ICONS[aircraft[:-7]] = QPixmap(os.path.join("./resources/ui/units/aircrafts/", aircraft))
|
||||
AIRCRAFT_ICONS[aircraft[:-7]] = QPixmap(os.path.join("./resources/ui/units/aircrafts/icons/", aircraft))
|
||||
AIRCRAFT_ICONS["F-16C_50"] = AIRCRAFT_ICONS["F-16C"]
|
||||
AIRCRAFT_ICONS["FA-18C_hornet"] = AIRCRAFT_ICONS["FA-18C"]
|
||||
AIRCRAFT_ICONS["A-10C_2"] = AIRCRAFT_ICONS["A-10C"]
|
||||
@ -183,3 +184,8 @@ def load_vehicle_icons():
|
||||
for vehicle in os.listdir("./resources/ui/units/vehicles/"):
|
||||
if vehicle.endswith(".jpg"):
|
||||
VEHICLES_ICONS[vehicle[:-7]] = QPixmap(os.path.join("./resources/ui/units/vehicles/", vehicle))
|
||||
|
||||
def load_aircraft_banners():
|
||||
for aircraft in os.listdir("./resources/ui/units/aircrafts/banners/"):
|
||||
if aircraft.endswith(".jpg"):
|
||||
AIRCRAFT_BANNERS[aircraft[:-7]] = QPixmap(os.path.join("./resources/ui/units/aircrafts/banners/", aircraft))
|
||||
@ -28,25 +28,25 @@ class QAircraftTypeSelector(QComboBox):
|
||||
for aircraft in aircraft_types:
|
||||
if mission_type in [FlightType.BARCAP, FlightType.ESCORT, FlightType.INTERCEPTION, FlightType.SWEEP, FlightType.TARCAP]:
|
||||
if aircraft in gen.flights.ai_flight_planner_db.CAP_CAPABLE:
|
||||
self.addItem(f"{db.unit_pretty_name(self.country, aircraft)}", userData=aircraft)
|
||||
self.addItem(f"{db.unit_get_expanded_info(self.country, aircraft, 'name')}", userData=aircraft)
|
||||
elif mission_type in [FlightType.CAS, FlightType.BAI, FlightType.OCA_AIRCRAFT]:
|
||||
if aircraft in gen.flights.ai_flight_planner_db.CAS_CAPABLE or aircraft in gen.flights.ai_flight_planner_db.TRANSPORT_CAPABLE:
|
||||
self.addItem(f"{db.unit_pretty_name(self.country, aircraft)}", userData=aircraft)
|
||||
self.addItem(f"{db.unit_get_expanded_info(self.country, aircraft, 'name')}", userData=aircraft)
|
||||
elif mission_type in [FlightType.SEAD]:
|
||||
if aircraft in gen.flights.ai_flight_planner_db.SEAD_CAPABLE:
|
||||
self.addItem(f"{db.unit_pretty_name(self.country, aircraft)}", userData=aircraft)
|
||||
self.addItem(f"{db.unit_get_expanded_info(self.country, aircraft, 'name')}", userData=aircraft)
|
||||
elif mission_type in [FlightType.DEAD]:
|
||||
if aircraft in gen.flights.ai_flight_planner_db.DEAD_CAPABLE:
|
||||
self.addItem(f"{db.unit_pretty_name(self.country, aircraft)}", userData=aircraft)
|
||||
self.addItem(f"{db.unit_get_expanded_info(self.country, aircraft, 'name')}", userData=aircraft)
|
||||
elif mission_type in [FlightType.STRIKE]:
|
||||
if aircraft in gen.flights.ai_flight_planner_db.STRIKE_CAPABLE or aircraft in gen.flights.ai_flight_planner_db.TRANSPORT_CAPABLE:
|
||||
self.addItem(f"{db.unit_pretty_name(self.country, aircraft)}", userData=aircraft)
|
||||
self.addItem(f"{db.unit_get_expanded_info(self.country, aircraft, 'name')}", userData=aircraft)
|
||||
elif mission_type in [FlightType.ANTISHIP]:
|
||||
if aircraft in gen.flights.ai_flight_planner_db.ANTISHIP_CAPABLE:
|
||||
self.addItem(f"{db.unit_pretty_name(self.country, aircraft)}", userData=aircraft)
|
||||
self.addItem(f"{db.unit_get_expanded_info(self.country, aircraft, 'name')}", userData=aircraft)
|
||||
elif mission_type in [FlightType.OCA_RUNWAY]:
|
||||
if aircraft in gen.flights.ai_flight_planner_db.RUNWAY_ATTACK_CAPABLE:
|
||||
self.addItem(f"{db.unit_pretty_name(self.country, aircraft)}", userData=aircraft)
|
||||
self.addItem(f"{db.unit_get_expanded_info(self.country, aircraft, 'name')}", userData=aircraft)
|
||||
current_aircraft_index = self.findData(current_aircraft)
|
||||
if current_aircraft_index != -1:
|
||||
self.setCurrentIndex(current_aircraft_index)
|
||||
|
||||
@ -52,7 +52,7 @@ class QDebriefingWindow(QDialog):
|
||||
for unit_type, count in player_air_losses.items():
|
||||
try:
|
||||
lostUnitsLayout.addWidget(
|
||||
QLabel(db.unit_pretty_name(self.debriefing.player_country, unit_type)), row, 0)
|
||||
QLabel(db.unit_get_expanded_info(self.debriefing.player_country, unit_type, 'name')), row, 0)
|
||||
lostUnitsLayout.addWidget(QLabel(str(count)), row, 1)
|
||||
row += 1
|
||||
except AttributeError:
|
||||
@ -94,7 +94,7 @@ class QDebriefingWindow(QDialog):
|
||||
for unit_type, count in enemy_air_losses.items():
|
||||
try:
|
||||
enemylostUnitsLayout.addWidget(
|
||||
QLabel(db.unit_pretty_name(self.debriefing.enemy_country, unit_type)), row, 0)
|
||||
QLabel(db.unit_get_expanded_info(self.debriefing.enemy_country, unit_type, 'name')), row, 0)
|
||||
enemylostUnitsLayout.addWidget(QLabel(str(count)), row, 1)
|
||||
row += 1
|
||||
except AttributeError:
|
||||
|
||||
79
qt_ui/windows/QUnitInfoWindow.py
Normal file
@ -0,0 +1,79 @@
|
||||
import logging
|
||||
from typing import Type
|
||||
|
||||
from PySide2 import QtCore
|
||||
from PySide2.QtCore import Qt
|
||||
from PySide2.QtGui import QIcon, QMovie, QPixmap
|
||||
from PySide2.QtWidgets import (
|
||||
QDialog,
|
||||
QGridLayout,
|
||||
QGroupBox,
|
||||
QHBoxLayout,
|
||||
QLabel,
|
||||
QMessageBox,
|
||||
QPushButton,
|
||||
QTextBrowser,
|
||||
QFrame,
|
||||
)
|
||||
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
||||
from dcs.unittype import UnitType
|
||||
from qt_ui.uiconstants import AIRCRAFT_BANNERS
|
||||
|
||||
from game.game import Game
|
||||
from game import db
|
||||
|
||||
|
||||
class QUnitInfoWindow(QDialog):
|
||||
|
||||
def __init__(self, game: Game, unit_type: Type[UnitType]) -> None:
|
||||
super(QUnitInfoWindow, self).__init__()
|
||||
self.setModal(True)
|
||||
self.game = game
|
||||
self.unit_type = unit_type
|
||||
self.setWindowTitle(f"Unit Info: {db.unit_get_expanded_info(self.game.player_country, self.unit_type, 'name')}")
|
||||
self.setWindowIcon(QIcon("./resources/icon.png"))
|
||||
self.setMinimumHeight(570)
|
||||
self.setWindowFlags(Qt.WindowStaysOnTopHint)
|
||||
|
||||
self.initUi()
|
||||
|
||||
def initUi(self):
|
||||
self.layout = QGridLayout()
|
||||
|
||||
header = QLabel(self)
|
||||
header.setGeometry(0, 0, 720, 360)
|
||||
pixmap = AIRCRAFT_BANNERS.get(self.unit_type.id)
|
||||
if pixmap is None:
|
||||
pixmap = AIRCRAFT_BANNERS.get("Missing")
|
||||
header.setPixmap(pixmap.scaled(header.width(), header.height()))
|
||||
self.layout.addWidget(header, 0, 0)
|
||||
|
||||
self.gridLayout = QGridLayout()
|
||||
|
||||
self.details_grid = QFrame()
|
||||
self.details_grid_layout = QGridLayout()
|
||||
|
||||
self.name_box = QLabel(f"<b>Name:</b> {db.unit_get_expanded_info(self.game.player_country, self.unit_type, 'name')}")
|
||||
self.name_box.setProperty("style", "info-element")
|
||||
|
||||
self.country_box = QLabel(f"<b>Country of Origin:</b> {db.unit_get_expanded_info(self.game.player_country, self.unit_type, 'country-of-origin')}")
|
||||
self.country_box.setProperty("style", "info-element")
|
||||
|
||||
self.year_box = QLabel(f"<b>Variant Introduction:</b> {db.unit_get_expanded_info(self.game.player_country, self.unit_type, 'year-of-variant-introduction')}")
|
||||
self.year_box.setProperty("style", "info-element")
|
||||
|
||||
self.details_grid_layout.addWidget(self.name_box, 0, 0)
|
||||
self.details_grid_layout.addWidget(self.country_box, 1, 0)
|
||||
self.details_grid_layout.addWidget(self.year_box, 2, 0)
|
||||
|
||||
self.details_grid.setLayout(self.details_grid_layout)
|
||||
|
||||
self.details_text = QTextBrowser()
|
||||
self.details_text.setProperty("style", "info-desc")
|
||||
self.details_text.setText(db.unit_get_expanded_info(self.game.player_country, self.unit_type, "text"))
|
||||
|
||||
self.gridLayout.addWidget(self.details_grid, 1, 0)
|
||||
self.gridLayout.addWidget(self.details_text, 2, 0)
|
||||
|
||||
self.layout.addLayout(self.gridLayout, 1, 0)
|
||||
self.setLayout(self.layout)
|
||||
@ -1,6 +1,7 @@
|
||||
import logging
|
||||
from typing import Type
|
||||
|
||||
from PySide2.QtCore import Qt
|
||||
from PySide2.QtWidgets import (
|
||||
QGroupBox,
|
||||
QHBoxLayout,
|
||||
@ -17,6 +18,7 @@ from game.event import UnitsDeliveryEvent
|
||||
from game.theater import ControlPoint
|
||||
from qt_ui.models import GameModel
|
||||
from qt_ui.windows.GameUpdateSignal import GameUpdateSignal
|
||||
from qt_ui.windows.QUnitInfoWindow import QUnitInfoWindow
|
||||
|
||||
|
||||
class QRecruitBehaviour:
|
||||
@ -58,7 +60,7 @@ class QRecruitBehaviour:
|
||||
existing_units = self.cp.base.total_units_of_type(unit_type)
|
||||
scheduled_units = self.pending_deliveries.units.get(unit_type, 0)
|
||||
|
||||
unitName = QLabel("<b>" + db.unit_pretty_name(self.game_model.game.player_country, unit_type) + "</b>")
|
||||
unitName = QLabel("<b>" + db.unit_get_expanded_info(self.game_model.game.player_country, unit_type, 'name') + "</b>")
|
||||
unitName.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
|
||||
|
||||
existing_units = QLabel(str(existing_units))
|
||||
@ -96,6 +98,21 @@ class QRecruitBehaviour:
|
||||
sell.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
|
||||
sell.clicked.connect(lambda: self.sell(unit_type))
|
||||
|
||||
info = QGroupBox()
|
||||
info.setProperty("style", "buy-box")
|
||||
info.setMaximumHeight(36)
|
||||
info.setMinimumHeight(36)
|
||||
infolayout = QHBoxLayout()
|
||||
info.setLayout(infolayout)
|
||||
|
||||
unitInfo = QPushButton("i")
|
||||
unitInfo.setProperty("style", "btn-info")
|
||||
unitInfo.setDisabled(disabled)
|
||||
unitInfo.setMinimumSize(16, 16)
|
||||
unitInfo.setMaximumSize(16, 16)
|
||||
unitInfo.clicked.connect(lambda: self.info(unit_type))
|
||||
unitInfo.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
|
||||
|
||||
existLayout.addWidget(unitName)
|
||||
existLayout.addItem(QSpacerItem(20, 0, QSizePolicy.Minimum, QSizePolicy.Minimum))
|
||||
existLayout.addWidget(existing_units)
|
||||
@ -106,8 +123,11 @@ class QRecruitBehaviour:
|
||||
buysellayout.addWidget(amount_bought)
|
||||
buysellayout.addWidget(buy)
|
||||
|
||||
infolayout.addWidget(unitInfo)
|
||||
|
||||
layout.addWidget(exist, row, 1)
|
||||
layout.addWidget(buysell, row, 2)
|
||||
layout.addWidget(info, row, 3)
|
||||
|
||||
return row + 1
|
||||
|
||||
@ -145,6 +165,10 @@ class QRecruitBehaviour:
|
||||
self._update_count_label(unit_type)
|
||||
self.update_available_budget()
|
||||
|
||||
def info(self, unit_type):
|
||||
self.info_window = QUnitInfoWindow(self.game_model.game, unit_type)
|
||||
self.info_window.show()
|
||||
|
||||
def set_maximum_units(self, maximum_units):
|
||||
"""
|
||||
Set the maximum number of units that can be bought
|
||||
|
||||
@ -65,7 +65,7 @@ class QAircraftRecruitmentMenu(QFrame, QRecruitBehaviour):
|
||||
continue
|
||||
unit_types.add(unit)
|
||||
|
||||
sorted_units = sorted(unit_types, key=lambda u: db.unit_pretty_name(self.game_model.game.player_country, u))
|
||||
sorted_units = sorted(unit_types, key=lambda u: db.unit_get_expanded_info(self.game_model.game.player_country, u, 'name'))
|
||||
for unit_type in sorted_units:
|
||||
row = self.add_purchase_row(
|
||||
unit_type, task_box_layout, row,
|
||||
|
||||
@ -17,6 +17,7 @@ class QAirfieldCommand(QFrame):
|
||||
|
||||
def init_ui(self):
|
||||
layout = QGridLayout()
|
||||
layout.setHorizontalSpacing(1)
|
||||
layout.addWidget(QAircraftRecruitmentMenu(self.cp, self.game_model), 0, 0)
|
||||
|
||||
planned = QGroupBox("Planned Flights")
|
||||
|
||||
@ -50,7 +50,7 @@ class QIntelInfo(QFrame):
|
||||
existing_units = self.cp.base.total_units_of_type(unit_type)
|
||||
if existing_units == 0:
|
||||
continue
|
||||
groupLayout.addWidget(QLabel("<b>" + db.unit_pretty_name(self.game.enemy_country, unit_type) + "</b>"), row, 0)
|
||||
groupLayout.addWidget(QLabel("<b>" + db.unit_get_expanded_info(self.game.enemy_country, unit_type, 'name') + "</b>"), row, 0)
|
||||
groupLayout.addWidget(QLabel(str(existing_units)), row, 1)
|
||||
row += 1
|
||||
|
||||
|
||||
@ -81,7 +81,7 @@ class AircraftIntelLayout(IntelTableLayout):
|
||||
for airframe, count in base.aircraft.items():
|
||||
if not count:
|
||||
continue
|
||||
self.add_row(db.unit_pretty_name(game.enemy_country, airframe), count)
|
||||
self.add_row(db.unit_get_expanded_info(game.enemy_country, airframe, 'name'), count)
|
||||
|
||||
self.add_spacer()
|
||||
self.add_row("<b>Total</b>", total)
|
||||
|
||||
@ -179,6 +179,21 @@ QPushButton[style="btn-sell"]:hover{
|
||||
background:#D84545;
|
||||
}
|
||||
|
||||
/* Info button */
|
||||
QPushButton[style="btn-info"]{
|
||||
background-color:#329E9E;
|
||||
color: white;
|
||||
border-radius:2px;
|
||||
font-weight:bold;
|
||||
text-transform:lowercase;
|
||||
margin: 0px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
QPushButton[style="btn-info"]:hover{
|
||||
background:#45D8D8;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QPushButton[style="btn-danger"]{
|
||||
@ -300,6 +315,18 @@ QLabel[style="SEAD"]{
|
||||
padding:2px 6px;
|
||||
}
|
||||
|
||||
QLabel[style="info-element"]{
|
||||
border: 1px solid #435466;
|
||||
color:white;
|
||||
padding:2px 6px;
|
||||
}
|
||||
|
||||
QTextBrowser[style="info-desc"]{
|
||||
border: 1px solid #435466;
|
||||
color:white;
|
||||
padding:2px 6px;
|
||||
}
|
||||
|
||||
/*QGroupBox these are the sections that look like fieldsets*/
|
||||
QGroupBox {
|
||||
margin-top: 1ex; /* leave space at the top for the title */
|
||||
|
||||
BIN
resources/ui/units/aircrafts/banners/Missing_24.jpg
Normal file
|
After Width: | Height: | Size: 178 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1017 B After Width: | Height: | Size: 1017 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1010 B After Width: | Height: | Size: 1010 B |
|
Before Width: | Height: | Size: 1010 B After Width: | Height: | Size: 1010 B |
|
Before Width: | Height: | Size: 1010 B After Width: | Height: | Size: 1010 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |