mirror of https://github.com/OpenTTD/OpenTTD
Add: Filter purchase lists by badge text. (#13588)
parent
5e43aaff35
commit
7a23bfa747
|
@ -1436,6 +1436,8 @@ struct BuildVehicleWindow : Window {
|
||||||
|
|
||||||
list.clear();
|
list.clear();
|
||||||
|
|
||||||
|
BadgeTextFilter btf(this->string_filter, GSF_TRAINS);
|
||||||
|
|
||||||
/* Make list of all available train engines and wagons.
|
/* Make list of all available train engines and wagons.
|
||||||
* Also check to see if the previously selected engine is still available,
|
* Also check to see if the previously selected engine is still available,
|
||||||
* and if not, reset selection to EngineID::Invalid(). This could be the case
|
* and if not, reset selection to EngineID::Invalid(). This could be the case
|
||||||
|
@ -1452,7 +1454,7 @@ struct BuildVehicleWindow : Window {
|
||||||
if (!FilterSingleEngine(eid)) continue;
|
if (!FilterSingleEngine(eid)) continue;
|
||||||
|
|
||||||
/* Filter by name or NewGRF extra text */
|
/* Filter by name or NewGRF extra text */
|
||||||
if (!FilterByText(e)) continue;
|
if (!FilterByText(e) && !btf.Filter(e->badges)) continue;
|
||||||
|
|
||||||
list.emplace_back(eid, e->info.variant_id, e->display_flags, 0);
|
list.emplace_back(eid, e->info.variant_id, e->display_flags, 0);
|
||||||
|
|
||||||
|
@ -1501,6 +1503,8 @@ struct BuildVehicleWindow : Window {
|
||||||
|
|
||||||
this->eng_list.clear();
|
this->eng_list.clear();
|
||||||
|
|
||||||
|
BadgeTextFilter btf(this->string_filter, GSF_ROADVEHICLES);
|
||||||
|
|
||||||
for (const Engine *e : Engine::IterateType(VEH_ROAD)) {
|
for (const Engine *e : Engine::IterateType(VEH_ROAD)) {
|
||||||
if (!this->show_hidden_engines && e->IsVariantHidden(_local_company)) continue;
|
if (!this->show_hidden_engines && e->IsVariantHidden(_local_company)) continue;
|
||||||
EngineID eid = e->index;
|
EngineID eid = e->index;
|
||||||
|
@ -1508,7 +1512,7 @@ struct BuildVehicleWindow : Window {
|
||||||
if (this->filter.roadtype != INVALID_ROADTYPE && !HasPowerOnRoad(e->u.road.roadtype, this->filter.roadtype)) continue;
|
if (this->filter.roadtype != INVALID_ROADTYPE && !HasPowerOnRoad(e->u.road.roadtype, this->filter.roadtype)) continue;
|
||||||
|
|
||||||
/* Filter by name or NewGRF extra text */
|
/* Filter by name or NewGRF extra text */
|
||||||
if (!FilterByText(e)) continue;
|
if (!FilterByText(e) && !btf.Filter(e->badges)) continue;
|
||||||
|
|
||||||
this->eng_list.emplace_back(eid, e->info.variant_id, e->display_flags, 0);
|
this->eng_list.emplace_back(eid, e->info.variant_id, e->display_flags, 0);
|
||||||
|
|
||||||
|
@ -1523,13 +1527,15 @@ struct BuildVehicleWindow : Window {
|
||||||
EngineID sel_id = EngineID::Invalid();
|
EngineID sel_id = EngineID::Invalid();
|
||||||
this->eng_list.clear();
|
this->eng_list.clear();
|
||||||
|
|
||||||
|
BadgeTextFilter btf(this->string_filter, GSF_SHIPS);
|
||||||
|
|
||||||
for (const Engine *e : Engine::IterateType(VEH_SHIP)) {
|
for (const Engine *e : Engine::IterateType(VEH_SHIP)) {
|
||||||
if (!this->show_hidden_engines && e->IsVariantHidden(_local_company)) continue;
|
if (!this->show_hidden_engines && e->IsVariantHidden(_local_company)) continue;
|
||||||
EngineID eid = e->index;
|
EngineID eid = e->index;
|
||||||
if (!IsEngineBuildable(eid, VEH_SHIP, _local_company)) continue;
|
if (!IsEngineBuildable(eid, VEH_SHIP, _local_company)) continue;
|
||||||
|
|
||||||
/* Filter by name or NewGRF extra text */
|
/* Filter by name or NewGRF extra text */
|
||||||
if (!FilterByText(e)) continue;
|
if (!FilterByText(e) && !btf.Filter(e->badges)) continue;
|
||||||
|
|
||||||
this->eng_list.emplace_back(eid, e->info.variant_id, e->display_flags, 0);
|
this->eng_list.emplace_back(eid, e->info.variant_id, e->display_flags, 0);
|
||||||
|
|
||||||
|
@ -1547,6 +1553,8 @@ struct BuildVehicleWindow : Window {
|
||||||
|
|
||||||
const Station *st = this->listview_mode ? nullptr : Station::GetByTile(TileIndex(this->window_number));
|
const Station *st = this->listview_mode ? nullptr : Station::GetByTile(TileIndex(this->window_number));
|
||||||
|
|
||||||
|
BadgeTextFilter btf(this->string_filter, GSF_AIRCRAFT);
|
||||||
|
|
||||||
/* Make list of all available planes.
|
/* Make list of all available planes.
|
||||||
* Also check to see if the previously selected plane is still available,
|
* Also check to see if the previously selected plane is still available,
|
||||||
* and if not, reset selection to EngineID::Invalid(). This could be the case
|
* and if not, reset selection to EngineID::Invalid(). This could be the case
|
||||||
|
@ -1559,7 +1567,7 @@ struct BuildVehicleWindow : Window {
|
||||||
if (!this->listview_mode && !CanVehicleUseStation(eid, st)) continue;
|
if (!this->listview_mode && !CanVehicleUseStation(eid, st)) continue;
|
||||||
|
|
||||||
/* Filter by name or NewGRF extra text */
|
/* Filter by name or NewGRF extra text */
|
||||||
if (!FilterByText(e)) continue;
|
if (!FilterByText(e) && !btf.Filter(e->badges)) continue;
|
||||||
|
|
||||||
this->eng_list.emplace_back(eid, e->info.variant_id, e->display_flags, 0);
|
this->eng_list.emplace_back(eid, e->info.variant_id, e->display_flags, 0);
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "newgrf_badge.h"
|
#include "newgrf_badge.h"
|
||||||
#include "newgrf_badge_type.h"
|
#include "newgrf_badge_type.h"
|
||||||
#include "newgrf_spritegroup.h"
|
#include "newgrf_spritegroup.h"
|
||||||
|
#include "stringfilter_type.h"
|
||||||
#include "strings_func.h"
|
#include "strings_func.h"
|
||||||
#include "timer/timer_game_calendar.h"
|
#include "timer/timer_game_calendar.h"
|
||||||
#include "window_gui.h"
|
#include "window_gui.h"
|
||||||
|
@ -389,6 +390,42 @@ uint GUIBadgeClasses::GetTotalColumnsWidth() const
|
||||||
return std::accumulate(std::begin(this->column_widths), std::end(this->column_widths), 0U);
|
return std::accumulate(std::begin(this->column_widths), std::end(this->column_widths), 0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a badge text filter.
|
||||||
|
* @param filter string filter.
|
||||||
|
* @param feature feature being used.
|
||||||
|
*/
|
||||||
|
BadgeTextFilter::BadgeTextFilter(StringFilter &filter, GrfSpecFeature feature)
|
||||||
|
{
|
||||||
|
/* Do not filter if the filter text box is empty */
|
||||||
|
if (filter.IsEmpty()) return;
|
||||||
|
|
||||||
|
/* Pre-build list of badges that match by string. */
|
||||||
|
for (const auto &badge : _badges.specs) {
|
||||||
|
if (badge.name == STR_NULL) continue;
|
||||||
|
if (!badge.features.Test(feature)) continue;
|
||||||
|
|
||||||
|
filter.ResetState();
|
||||||
|
filter.AddLine(GetString(badge.name));
|
||||||
|
if (!filter.GetState()) continue;
|
||||||
|
|
||||||
|
auto it = std::ranges::lower_bound(this->badges, badge.index);
|
||||||
|
if (it != std::end(this->badges) && *it == badge.index) continue;
|
||||||
|
|
||||||
|
this->badges.insert(it, badge.index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if any of the given badges matches the filtered badge list.
|
||||||
|
* @param badges List of badges.
|
||||||
|
* @returns true iff at least one badge in badges is present.
|
||||||
|
*/
|
||||||
|
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.
|
* Draw names for a list of badge labels.
|
||||||
* @param r Rect to draw in.
|
* @param r Rect to draw in.
|
||||||
|
|
|
@ -74,6 +74,15 @@ void DrawBadgeColumn(Rect r, int column_group, const GUIBadgeClasses &badge_clas
|
||||||
|
|
||||||
uint32_t GetBadgeVariableResult(const struct GRFFile &grffile, std::span<const BadgeID> badges, uint32_t parameter);
|
uint32_t GetBadgeVariableResult(const struct GRFFile &grffile, std::span<const BadgeID> badges, uint32_t parameter);
|
||||||
|
|
||||||
|
class BadgeTextFilter {
|
||||||
|
public:
|
||||||
|
BadgeTextFilter(struct StringFilter &filter, GrfSpecFeature feature);
|
||||||
|
bool Filter(std::span<const BadgeID> badges) const;
|
||||||
|
|
||||||
|
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, StringID str, int value, bool masked = false, bool shaded = false);
|
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, StringID 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, StringID 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, StringID str, int value, bool masked = false, bool shaded = false);
|
||||||
|
|
||||||
|
|
|
@ -147,6 +147,8 @@ static bool TypeIDSorter(PickerItem const &a, PickerItem const &b)
|
||||||
/** Filter types by class name. */
|
/** Filter types by class name. */
|
||||||
static bool TypeTagNameFilter(PickerItem const *item, PickerFilterData &filter)
|
static bool TypeTagNameFilter(PickerItem const *item, PickerFilterData &filter)
|
||||||
{
|
{
|
||||||
|
if (filter.btf.has_value() && filter.btf->Filter(filter.callbacks->GetTypeBadges(item->class_index, item->index))) return true;
|
||||||
|
|
||||||
filter.ResetState();
|
filter.ResetState();
|
||||||
filter.AddLine(GetString(filter.callbacks->GetTypeName(item->class_index, item->index)));
|
filter.AddLine(GetString(filter.callbacks->GetTypeName(item->class_index, item->index)));
|
||||||
return filter.GetState();
|
return filter.GetState();
|
||||||
|
@ -449,6 +451,11 @@ void PickerWindow::OnEditboxChanged(WidgetID wid)
|
||||||
|
|
||||||
case WID_PW_TYPE_FILTER:
|
case WID_PW_TYPE_FILTER:
|
||||||
this->type_string_filter.SetFilterTerm(this->type_editbox.text.GetText());
|
this->type_string_filter.SetFilterTerm(this->type_editbox.text.GetText());
|
||||||
|
if (!type_string_filter.IsEmpty()) {
|
||||||
|
this->type_string_filter.btf.emplace(this->type_string_filter, this->callbacks.GetFeature());
|
||||||
|
} else {
|
||||||
|
this->type_string_filter.btf.reset();
|
||||||
|
}
|
||||||
this->types.SetFilterState(!type_string_filter.IsEmpty());
|
this->types.SetFilterState(!type_string_filter.IsEmpty());
|
||||||
this->InvalidateData(PickerInvalidation::Type);
|
this->InvalidateData(PickerInvalidation::Type);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -144,6 +144,7 @@ public:
|
||||||
|
|
||||||
struct PickerFilterData : StringFilter {
|
struct PickerFilterData : StringFilter {
|
||||||
const PickerCallbacks *callbacks; ///< Callbacks for filter functions to access to callbacks.
|
const PickerCallbacks *callbacks; ///< Callbacks for filter functions to access to callbacks.
|
||||||
|
std::optional<BadgeTextFilter> btf;
|
||||||
};
|
};
|
||||||
|
|
||||||
using PickerClassList = GUIList<int, std::nullptr_t, PickerFilterData &>; ///< GUIList holding classes to display.
|
using PickerClassList = GUIList<int, std::nullptr_t, PickerFilterData &>; ///< GUIList holding classes to display.
|
||||||
|
|
Loading…
Reference in New Issue