1
0
Fork 0

Codechange: Move GUI parts of badges to a separate file. (#14023)

pull/14034/head
Peter Nelson 2025-04-18 17:20:31 +01:00 committed by GitHub
parent 67d6089f39
commit 394adb654e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 344 additions and 276 deletions

View File

@ -279,6 +279,8 @@ add_files(
newgrf_animation_type.h
newgrf_badge.cpp
newgrf_badge.h
newgrf_badge_gui.cpp
newgrf_badge_gui.h
newgrf_badge_type.h
newgrf_callbacks.h
newgrf_canal.cpp

View File

@ -21,7 +21,7 @@
#include "company_base.h"
#include "station_type.h"
#include "newgrf_airport.h"
#include "newgrf_badge.h"
#include "newgrf_badge_gui.h"
#include "newgrf_callbacks.h"
#include "dropdown_type.h"
#include "dropdown_func.h"

View File

@ -18,6 +18,7 @@
#include "company_func.h"
#include "vehicle_gui.h"
#include "newgrf_badge.h"
#include "newgrf_badge_gui.h"
#include "newgrf_engine.h"
#include "newgrf_text.h"
#include "group.h"

View File

@ -12,7 +12,7 @@
#include "engine_type.h"
#include "group_type.h"
#include "newgrf_badge.h"
#include "newgrf_badge_gui.h"
#include "sortlist_type.h"
#include "gfx_type.h"
#include "vehicle_type.h"

View File

@ -21,6 +21,7 @@
#include "town.h"
#include "cheat_type.h"
#include "newgrf_badge.h"
#include "newgrf_badge_gui.h"
#include "newgrf_industries.h"
#include "newgrf_text.h"
#include "newgrf_debug.h"

View File

@ -8,7 +8,6 @@
/** @file newgrf_badge.cpp Functionality for NewGRF badges. */
#include "stdafx.h"
#include "dropdown_type.h"
#include "newgrf.h"
#include "newgrf_badge.h"
#include "newgrf_badge_type.h"
@ -16,13 +15,9 @@
#include "stringfilter_type.h"
#include "strings_func.h"
#include "timer/timer_game_calendar.h"
#include "window_gui.h"
#include "zoom_func.h"
#include "table/strings.h"
#include "dropdown_common_type.h"
#include "safeguards.h"
/** Separator to identify badge classes from a label. */
@ -38,6 +33,15 @@ public:
/** Static instance of badge state. */
static Badges _badges = {};
/**
* Get a read-only view of badges.
* @return Span of badges.
*/
std::span<const Badge> GetBadges()
{
return _badges.specs;
}
/**
* Assign a BadgeClassID to the given badge.
* @param index Badge ID of badge that should be assigned.
@ -254,16 +258,13 @@ void AppendCopyableBadgeList(std::vector<BadgeID> &dst, std::span<const BadgeID>
/** Apply features from all badges to their badge classes. */
void ApplyBadgeFeaturesToClassBadges()
{
for (const Badge &badge : _badges.specs) {
for (const Badge &badge : GetBadges()) {
Badge *class_badge = GetClassBadge(badge.class_index);
assert(class_badge != nullptr);
class_badge->features.Set(badge.features);
}
}
static constexpr uint MAX_BADGE_HEIGHT = 12; ///< Maximal height of a badge sprite.
static constexpr uint MAX_BADGE_WIDTH = MAX_BADGE_HEIGHT * 2; ///< Maximal width.
/**
* Get sprite for the given badge.
* @param badge Badge being queried.
@ -272,7 +273,7 @@ static constexpr uint MAX_BADGE_WIDTH = MAX_BADGE_HEIGHT * 2; ///< Maximal width
* @param remap Palette remap to use if the flag is company-coloured.
* @returns Custom sprite to draw, or \c 0 if not available.
*/
static PalSpriteID GetBadgeSprite(const Badge &badge, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, PaletteID remap)
PalSpriteID GetBadgeSprite(const Badge &badge, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, PaletteID remap)
{
BadgeResolverObject object(badge, feature, introduction_date);
const SpriteGroup *group = object.Resolve();
@ -284,112 +285,19 @@ static PalSpriteID GetBadgeSprite(const Badge &badge, GrfSpecFeature feature, st
}
/**
* Get the largest badge size (within limits) for a badge class.
* @param class_index Badge class.
* @param feature Feature being used.
* @returns Largest base size of the badge class for the feature.
* Create a list of used badge classes for a feature.
* @param feature GRF feature being used.
*/
static Dimension GetBadgeMaximalDimension(BadgeClassID class_index, GrfSpecFeature feature)
UsedBadgeClasses::UsedBadgeClasses(GrfSpecFeature feature)
{
Dimension d = { 0, MAX_BADGE_HEIGHT };
for (auto index : _badges.classes) {
Badge *class_badge = GetBadge(index);
if (!class_badge->features.Test(feature)) continue;
for (const auto &badge : _badges.specs) {
if (badge.class_index != class_index) continue;
PalSpriteID ps = GetBadgeSprite(badge, feature, std::nullopt, PAL_NONE);
if (ps.sprite == 0) continue;
d.width = std::max(d.width, GetSpriteSize(ps.sprite, nullptr, ZOOM_LVL_NORMAL).width);
if (d.width > MAX_BADGE_WIDTH) break;
this->classes.push_back(class_badge->class_index);
}
d.width = std::min(d.width, MAX_BADGE_WIDTH);
return d;
}
/** Utility class to create a list of badge classes used by a feature. */
class UsedBadgeClasses {
public:
/**
* Create a list of used badge classes for a feature.
* @param feature GRF feature being used.
*/
explicit UsedBadgeClasses(GrfSpecFeature feature)
{
for (auto index : _badges.classes) {
Badge *class_badge = GetBadge(index);
if (!class_badge->features.Test(feature)) continue;
this->classes.push_back(class_badge->class_index);
}
std::ranges::sort(this->classes, [](const BadgeClassID &a, const BadgeClassID &b)
{
return GetClassBadge(a)->label < GetClassBadge(b)->label;
});
}
std::span<const BadgeClassID> Classes() const { return this->classes; }
private:
std::vector<BadgeClassID> classes; ///< List of badge classes.
};
static bool operator<(const GUIBadgeClasses::Element &a, const GUIBadgeClasses::Element &b)
{
if (a.column_group != b.column_group) return a.column_group < b.column_group;
if (a.sort_order != b.sort_order) return a.sort_order < b.sort_order;
return a.label < b.label;
}
/**
* Construct of list of badge classes and column groups to display.
* @param feature feature being used.
*/
GUIBadgeClasses::GUIBadgeClasses(GrfSpecFeature feature)
{
/* Get list of classes used by feature. */
UsedBadgeClasses used(feature);
uint max_column = 0;
for (BadgeClassID class_index : used.Classes()) {
const Badge *class_badge = GetClassBadge(class_index);
if (class_badge->name == STR_NULL) continue;
Dimension size = GetBadgeMaximalDimension(class_index, feature);
if (size.width == 0) continue;
uint8_t column = 0;
bool visible = true;
uint sort_order = UINT_MAX;
this->gui_classes.emplace_back(class_index, column, visible, sort_order, size, class_badge->label);
if (visible) max_column = std::max<uint>(max_column, column);
}
std::sort(std::begin(this->gui_classes), std::end(this->gui_classes));
/* Determine total width of visible badge columns. */
this->column_widths.resize(max_column + 1);
for (const auto &el : this->gui_classes) {
if (!el.visible) continue;
this->column_widths[el.column_group] += ScaleGUITrad(el.size.width) + WidgetDimensions::scaled.hsep_normal;
}
/* Replace trailing `hsep_normal` spacer with wider `hsep_wide` spacer. */
for (uint &badge_width : this->column_widths) {
if (badge_width == 0) continue;
badge_width = badge_width - WidgetDimensions::scaled.hsep_normal + WidgetDimensions::scaled.hsep_wide;
}
}
/**
* Get total width of all columns.
* @returns sum of all column widths.
*/
uint GUIBadgeClasses::GetTotalColumnsWidth() const
{
return std::accumulate(std::begin(this->column_widths), std::end(this->column_widths), 0U);
std::ranges::sort(this->classes, [](const BadgeClassID &a, const BadgeClassID &b) { return GetClassBadge(a)->label < GetClassBadge(b)->label; });
}
/**
@ -403,7 +311,7 @@ BadgeTextFilter::BadgeTextFilter(StringFilter &filter, GrfSpecFeature feature)
if (filter.IsEmpty()) return;
/* Pre-build list of badges that match by string. */
for (const auto &badge : _badges.specs) {
for (const auto &badge : GetBadges()) {
if (badge.name == STR_NULL) continue;
if (!badge.features.Test(feature)) continue;
@ -427,128 +335,3 @@ bool BadgeTextFilter::Filter(std::span<const BadgeID> badges) const
{
return std::ranges::any_of(badges, [this](const BadgeID &badge) { return std::ranges::binary_search(this->badges, badge); });
}
/**
* Draw names for a list of badge labels.
* @param r Rect to draw in.
* @param badges List of badges.
* @param feature GRF feature being used.
* @returns Vertical position after drawing is complete.
*/
int DrawBadgeNameList(Rect r, std::span<const BadgeID> badges, GrfSpecFeature)
{
if (badges.empty()) return r.top;
std::set<BadgeClassID> class_indexes;
for (const BadgeID &index : badges) class_indexes.insert(GetBadge(index)->class_index);
std::string_view list_separator = GetListSeparator();
for (const BadgeClassID &class_index : class_indexes) {
const Badge *class_badge = GetClassBadge(class_index);
if (class_badge == nullptr || class_badge->name == STR_NULL) continue;
std::string s;
for (const BadgeID &index : badges) {
const Badge *badge = GetBadge(index);
if (badge == nullptr || badge->name == STR_NULL) continue;
if (badge->class_index != class_index) continue;
if (!s.empty()) {
if (badge->flags.Test(BadgeFlag::NameListFirstOnly)) continue;
s += list_separator;
}
AppendStringInPlace(s, badge->name);
if (badge->flags.Test(BadgeFlag::NameListStop)) break;
}
if (s.empty()) continue;
r.top = DrawStringMultiLine(r, GetString(STR_BADGE_NAME_LIST, class_badge->name, std::move(s)), TC_BLACK);
}
return r.top;
}
/**
* Draw a badge column group.
* @param r rect to draw within.
* @param column_group column to draw.
* @param gui_classes gui badge classes.
* @param badges badges to draw.
* @param feature feature being used.
* @param introduction_date introduction date of item.
* @param remap palette remap to for company-coloured badges.
*/
void DrawBadgeColumn(Rect r, int column_group, const GUIBadgeClasses &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, PaletteID remap)
{
bool rtl = _current_text_dir == TD_RTL;
for (const auto &gc : gui_classes.GetClasses()) {
if (gc.column_group != column_group) continue;
if (!gc.visible) continue;
int width = ScaleGUITrad(gc.size.width);
for (const BadgeID &index : badges) {
const Badge &badge = *GetBadge(index);
if (badge.class_index != gc.class_index) continue;
PalSpriteID ps = GetBadgeSprite(badge, feature, introduction_date, remap);
if (ps.sprite == 0) continue;
DrawSpriteIgnorePadding(ps.sprite, ps.pal, r.WithWidth(width, rtl), SA_CENTER);
break;
}
r = r.Indent(width + WidgetDimensions::scaled.hsep_normal, rtl);
}
}
/** Drop down element that draws a list of badges. */
template <class TBase, bool TEnd = true, FontSize TFs = FS_NORMAL>
class DropDownBadges : public TBase {
public:
template <typename... Args>
explicit DropDownBadges(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, Args&&... args)
: TBase(std::forward<Args>(args)...), gui_classes(gui_classes), badges(badges), feature(feature), introduction_date(introduction_date)
{
for (const auto &gc : gui_classes->GetClasses()) {
if (gc.column_group != 0) continue;
dim.width += gc.size.width + WidgetDimensions::scaled.hsep_normal;
dim.height = std::max(dim.height, gc.size.height);
}
}
uint Height() const override { return std::max<uint>(this->dim.height, this->TBase::Height()); }
uint Width() const override { return this->dim.width + WidgetDimensions::scaled.hsep_wide + this->TBase::Width(); }
void Draw(const Rect &full, const Rect &r, bool sel, Colours bg_colour) const override
{
bool rtl = TEnd ^ (_current_text_dir == TD_RTL);
DrawBadgeColumn(r.WithWidth(this->dim.width, rtl), 0, *this->gui_classes, this->badges, this->feature, this->introduction_date, PAL_NONE);
this->TBase::Draw(full, r.Indent(this->dim.width + WidgetDimensions::scaled.hsep_wide, rtl), sel, bg_colour);
}
private:
std::shared_ptr<GUIBadgeClasses> gui_classes;
const std::span<const BadgeID> badges;
const GrfSpecFeature feature;
const std::optional<TimerGameCalendar::Date> introduction_date;
Dimension dim{};
};
using DropDownListBadgeItem = DropDownBadges<DropDownListStringItem>;
using DropDownListBadgeIconItem = DropDownBadges<DropDownListIconItem>;
std::unique_ptr<DropDownListItem> MakeDropDownListBadgeItem(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, std::string &&str, int value, bool masked, bool shaded)
{
return std::make_unique<DropDownListBadgeItem>(gui_classes, badges, feature, introduction_date, std::move(str), value, masked, shaded);
}
std::unique_ptr<DropDownListItem> MakeDropDownListBadgeIconItem(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, const Dimension &dim, SpriteID sprite, PaletteID palette, std::string &&str, int value, bool masked, bool shaded)
{
return std::make_unique<DropDownListBadgeIconItem>(gui_classes, badges, feature, introduction_date, dim, sprite, palette, std::move(str), value, masked, shaded);
}

View File

@ -10,7 +10,6 @@
#ifndef NEWGRF_BADGE_H
#define NEWGRF_BADGE_H
#include "dropdown_type.h"
#include "newgrf.h"
#include "newgrf_badge_type.h"
#include "newgrf_commons.h"
@ -30,6 +29,20 @@ public:
Badge(std::string_view label, BadgeID index, BadgeClassID class_index) : label(label), index(index), class_index(class_index) {}
};
/** Utility class to create a list of badge classes used by a feature. */
class UsedBadgeClasses {
public:
explicit UsedBadgeClasses(GrfSpecFeature feature);
inline std::span<const BadgeClassID> Classes() const
{
return this->classes;
}
private:
std::vector<BadgeClassID> classes; ///< List of badge classes.
};
void ResetBadges();
Badge &GetOrCreateBadge(std::string_view label);
@ -37,43 +50,15 @@ void MarkBadgeSeen(BadgeID index, GrfSpecFeature feature);
void AppendCopyableBadgeList(std::vector<BadgeID> &dst, std::span<const BadgeID> src, GrfSpecFeature feature);
void ApplyBadgeFeaturesToClassBadges();
std::span<const Badge> GetBadges();
Badge *GetBadge(BadgeID index);
Badge *GetBadgeByLabel(std::string_view label);
Badge *GetClassBadge(BadgeClassID class_index);
class GUIBadgeClasses {
public:
struct Element {
BadgeClassID class_index; ///< Badge class index.
uint8_t column_group; ///< Column group in UI. 0 = left, 1 = centre, 2 = right.
bool visible; ///< Whether this element is visible.
uint sort_order; ///< Order of element.
Dimension size; ///< Maximal size of this element.
std::string_view label; ///< Class label (string owned by the class badge)
constexpr Element(BadgeClassID class_index, uint8_t column_group, bool visible, uint sort_order, Dimension size, std::string_view label) :
class_index(class_index), column_group(column_group), visible(visible), sort_order(sort_order), size(size), label(label) {}
};
GUIBadgeClasses() = default;
explicit GUIBadgeClasses(GrfSpecFeature feature);
inline std::span<const Element> GetClasses() const { return this->gui_classes; }
inline std::span<const uint> GetColumnWidths() const { return this->column_widths; }
uint GetTotalColumnsWidth() const;
private:
std::vector<Element> gui_classes{};
std::vector<uint> column_widths{};
};
int DrawBadgeNameList(Rect r, std::span<const BadgeID> badges, GrfSpecFeature feature);
void DrawBadgeColumn(Rect r, int column_group, const GUIBadgeClasses &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, PaletteID remap);
uint32_t GetBadgeVariableResult(const struct GRFFile &grffile, std::span<const BadgeID> badges, uint32_t parameter);
PalSpriteID GetBadgeSprite(const Badge &badge, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, PaletteID remap);
class BadgeTextFilter {
public:
BadgeTextFilter(struct StringFilter &filter, GrfSpecFeature feature);
@ -83,7 +68,4 @@ private:
std::vector<BadgeID> badges{};
};
std::unique_ptr<DropDownListItem> MakeDropDownListBadgeItem(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, std::string &&str, int value, bool masked = false, bool shaded = false);
std::unique_ptr<DropDownListItem> MakeDropDownListBadgeIconItem(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, const Dimension &dim, SpriteID sprite, PaletteID palette, std::string &&str, int value, bool masked = false, bool shaded = false);
#endif /* NEWGRF_BADGE_H */

View File

@ -0,0 +1,241 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file newgrf_badge.cpp Functionality for NewGRF badges. */
#include "stdafx.h"
#include "dropdown_type.h"
#include "newgrf.h"
#include "newgrf_badge.h"
#include "newgrf_badge_gui.h"
#include "newgrf_badge_type.h"
#include "strings_func.h"
#include "timer/timer_game_calendar.h"
#include "window_gui.h"
#include "zoom_func.h"
#include "table/strings.h"
#include "dropdown_common_type.h"
#include "safeguards.h"
static constexpr uint MAX_BADGE_HEIGHT = 12; ///< Maximal height of a badge sprite.
static constexpr uint MAX_BADGE_WIDTH = MAX_BADGE_HEIGHT * 2; ///< Maximal width.
/**
* Get the largest badge size (within limits) for a badge class.
* @param class_index Badge class.
* @param feature Feature being used.
* @returns Largest base size of the badge class for the feature.
*/
static Dimension GetBadgeMaximalDimension(BadgeClassID class_index, GrfSpecFeature feature)
{
Dimension d = {0, MAX_BADGE_HEIGHT};
for (const auto &badge : GetBadges()) {
if (badge.class_index != class_index) continue;
PalSpriteID ps = GetBadgeSprite(badge, feature, std::nullopt, PAL_NONE);
if (ps.sprite == 0) continue;
d.width = std::max(d.width, GetSpriteSize(ps.sprite, nullptr, ZOOM_LVL_NORMAL).width);
if (d.width > MAX_BADGE_WIDTH) break;
}
d.width = std::min(d.width, MAX_BADGE_WIDTH);
return d;
}
static bool operator<(const GUIBadgeClasses::Element &a, const GUIBadgeClasses::Element &b)
{
if (a.column_group != b.column_group) return a.column_group < b.column_group;
if (a.sort_order != b.sort_order) return a.sort_order < b.sort_order;
return a.label < b.label;
}
/**
* Construct of list of badge classes and column groups to display.
* @param feature feature being used.
*/
GUIBadgeClasses::GUIBadgeClasses(GrfSpecFeature feature)
{
/* Get list of classes used by feature. */
UsedBadgeClasses used(feature);
uint max_column = 0;
for (BadgeClassID class_index : used.Classes()) {
const Badge *class_badge = GetClassBadge(class_index);
if (class_badge->name == STR_NULL) continue;
Dimension size = GetBadgeMaximalDimension(class_index, feature);
if (size.width == 0) continue;
uint8_t column = 0;
bool visible = true;
uint sort_order = UINT_MAX;
this->gui_classes.emplace_back(class_index, column, visible, sort_order, size, class_badge->label);
if (visible) max_column = std::max<uint>(max_column, column);
}
std::sort(std::begin(this->gui_classes), std::end(this->gui_classes));
/* Determine total width of visible badge columns. */
this->column_widths.resize(max_column + 1);
for (const auto &el : this->gui_classes) {
if (!el.visible) continue;
this->column_widths[el.column_group] += ScaleGUITrad(el.size.width) + WidgetDimensions::scaled.hsep_normal;
}
/* Replace trailing `hsep_normal` spacer with wider `hsep_wide` spacer. */
for (uint &badge_width : this->column_widths) {
if (badge_width == 0) continue;
badge_width = badge_width - WidgetDimensions::scaled.hsep_normal + WidgetDimensions::scaled.hsep_wide;
}
}
/**
* Get total width of all columns.
* @returns sum of all column widths.
*/
uint GUIBadgeClasses::GetTotalColumnsWidth() const
{
return std::accumulate(std::begin(this->column_widths), std::end(this->column_widths), 0U);
}
/**
* Draw names for a list of badge labels.
* @param r Rect to draw in.
* @param badges List of badges.
* @param feature GRF feature being used.
* @returns Vertical position after drawing is complete.
*/
int DrawBadgeNameList(Rect r, std::span<const BadgeID> badges, GrfSpecFeature)
{
if (badges.empty()) return r.top;
std::set<BadgeClassID> class_indexes;
for (const BadgeID &index : badges) class_indexes.insert(GetBadge(index)->class_index);
std::string_view list_separator = GetListSeparator();
for (const BadgeClassID &class_index : class_indexes) {
const Badge *class_badge = GetClassBadge(class_index);
if (class_badge == nullptr || class_badge->name == STR_NULL) continue;
std::string s;
for (const BadgeID &index : badges) {
const Badge *badge = GetBadge(index);
if (badge == nullptr || badge->name == STR_NULL) continue;
if (badge->class_index != class_index) continue;
if (!s.empty()) {
if (badge->flags.Test(BadgeFlag::NameListFirstOnly)) continue;
s += list_separator;
}
AppendStringInPlace(s, badge->name);
if (badge->flags.Test(BadgeFlag::NameListStop)) break;
}
if (s.empty()) continue;
r.top = DrawStringMultiLine(r, GetString(STR_BADGE_NAME_LIST, class_badge->name, std::move(s)), TC_BLACK);
}
return r.top;
}
/**
* Draw a badge column group.
* @param r rect to draw within.
* @param column_group column to draw.
* @param gui_classes gui badge classes.
* @param badges badges to draw.
* @param feature feature being used.
* @param introduction_date introduction date of item.
* @param remap palette remap to for company-coloured badges.
*/
void DrawBadgeColumn(Rect r, int column_group, const GUIBadgeClasses &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, PaletteID remap)
{
bool rtl = _current_text_dir == TD_RTL;
for (const auto &gc : gui_classes.GetClasses()) {
if (gc.column_group != column_group) continue;
if (!gc.visible) continue;
int width = ScaleGUITrad(gc.size.width);
for (const BadgeID &index : badges) {
const Badge &badge = *GetBadge(index);
if (badge.class_index != gc.class_index) continue;
PalSpriteID ps = GetBadgeSprite(badge, feature, introduction_date, remap);
if (ps.sprite == 0) continue;
DrawSpriteIgnorePadding(ps.sprite, ps.pal, r.WithWidth(width, rtl), SA_CENTER);
break;
}
r = r.Indent(width + WidgetDimensions::scaled.hsep_normal, rtl);
}
}
/** Drop down element that draws a list of badges. */
template <class TBase, bool TEnd = true, FontSize TFs = FS_NORMAL>
class DropDownBadges : public TBase {
public:
template <typename... Args>
explicit DropDownBadges(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, Args &&...args) :
TBase(std::forward<Args>(args)...), gui_classes(gui_classes), badges(badges), feature(feature), introduction_date(introduction_date)
{
for (const auto &gc : gui_classes->GetClasses()) {
if (gc.column_group != 0) continue;
dim.width += gc.size.width + WidgetDimensions::scaled.hsep_normal;
dim.height = std::max(dim.height, gc.size.height);
}
}
uint Height() const override
{
return std::max<uint>(this->dim.height, this->TBase::Height());
}
uint Width() const override
{
return this->dim.width + WidgetDimensions::scaled.hsep_wide + this->TBase::Width();
}
void Draw(const Rect &full, const Rect &r, bool sel, Colours bg_colour) const override
{
bool rtl = TEnd ^ (_current_text_dir == TD_RTL);
DrawBadgeColumn(r.WithWidth(this->dim.width, rtl), 0, *this->gui_classes, this->badges, this->feature, this->introduction_date, PAL_NONE);
this->TBase::Draw(full, r.Indent(this->dim.width + WidgetDimensions::scaled.hsep_wide, rtl), sel, bg_colour);
}
private:
std::shared_ptr<GUIBadgeClasses> gui_classes;
const std::span<const BadgeID> badges;
const GrfSpecFeature feature;
const std::optional<TimerGameCalendar::Date> introduction_date;
Dimension dim{};
};
using DropDownListBadgeItem = DropDownBadges<DropDownListStringItem>;
using DropDownListBadgeIconItem = DropDownBadges<DropDownListIconItem>;
std::unique_ptr<DropDownListItem> MakeDropDownListBadgeItem(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, std::string &&str, int value, bool masked, bool shaded)
{
return std::make_unique<DropDownListBadgeItem>(gui_classes, badges, feature, introduction_date, std::move(str), value, masked, shaded);
}
std::unique_ptr<DropDownListItem> MakeDropDownListBadgeIconItem(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, const Dimension &dim, SpriteID sprite, PaletteID palette, std::string &&str, int value, bool masked, bool shaded)
{
return std::make_unique<DropDownListBadgeIconItem>(gui_classes, badges, feature, introduction_date, dim, sprite, palette, std::move(str), value, masked, shaded);
}

View File

@ -0,0 +1,55 @@
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file newgrf_badge.h Functions related to NewGRF badges. */
#ifndef NEWGRF_BADGE_GUI_H
#define NEWGRF_BADGE_GUI_H
#include "dropdown_type.h"
#include "newgrf.h"
#include "newgrf_badge_type.h"
#include "timer/timer_game_calendar.h"
class GUIBadgeClasses {
public:
struct Element {
BadgeClassID class_index; ///< Badge class index.
uint8_t column_group; ///< Column group in UI. 0 = left, 1 = centre, 2 = right.
bool visible; ///< Whether this element is visible.
uint sort_order; ///< Order of element.
Dimension size; ///< Maximal size of this element.
std::string_view label; ///< Class label (string owned by the class badge)
};
GUIBadgeClasses() = default;
explicit GUIBadgeClasses(GrfSpecFeature feature);
inline std::span<const Element> GetClasses() const
{
return this->gui_classes;
}
inline std::span<const uint> GetColumnWidths() const
{
return this->column_widths;
}
uint GetTotalColumnsWidth() const;
private:
std::vector<Element> gui_classes{};
std::vector<uint> column_widths{};
};
int DrawBadgeNameList(Rect r, std::span<const BadgeID> badges, GrfSpecFeature feature);
void DrawBadgeColumn(Rect r, int column_group, const GUIBadgeClasses &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, PaletteID remap);
std::unique_ptr<DropDownListItem> MakeDropDownListBadgeItem(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, std::string &&str, int value, bool masked = false, bool shaded = false);
std::unique_ptr<DropDownListItem> MakeDropDownListBadgeIconItem(const std::shared_ptr<GUIBadgeClasses> &gui_classes, std::span<const BadgeID> badges, GrfSpecFeature feature, std::optional<TimerGameCalendar::Date> introduction_date, const Dimension &dim, SpriteID sprite, PaletteID palette, std::string &&str, int value, bool masked = false, bool shaded = false);
#endif /* NEWGRF_BADGE_GUI_H */

View File

@ -12,7 +12,7 @@
#include "company_func.h"
#include "hotkeys.h"
#include "newgrf.h"
#include "newgrf_badge.h"
#include "newgrf_badge_gui.h"
#include "newgrf_object.h"
#include "newgrf_text.h"
#include "object.h"

View File

@ -14,6 +14,7 @@
#include "hotkeys.h"
#include "ini_type.h"
#include "newgrf_badge.h"
#include "newgrf_badge_gui.h"
#include "picker_gui.h"
#include "querystring_gui.h"
#include "settings_type.h"

View File

@ -11,6 +11,7 @@
#define PICKER_GUI_H
#include "newgrf_badge.h"
#include "newgrf_badge_gui.h"
#include "querystring_gui.h"
#include "sortlist_type.h"
#include "stringfilter_type.h"

View File

@ -18,6 +18,7 @@
#include "command_func.h"
#include "waypoint_func.h"
#include "newgrf_badge.h"
#include "newgrf_badge_gui.h"
#include "newgrf_station.h"
#include "company_base.h"
#include "strings_func.h"

View File

@ -39,7 +39,7 @@
#include "waypoint_cmd.h"
#include "road_cmd.h"
#include "tunnelbridge_cmd.h"
#include "newgrf_badge.h"
#include "newgrf_badge_gui.h"
#include "newgrf_roadstop.h"
#include "picker_gui.h"
#include "timer/timer.h"