@@ -1309,7 +1309,7 @@ protected:
/* Runtime saved values */
static Listing last_sorting;
/* Constants for sorting stations */
/* Constants for sorting industries */
static const StringID sorter_names[];
static GUIIndustryList::SortFunction * const sorter_funcs[];
@@ -1320,6 +1320,14 @@ protected:
StringID cargo_filter_texts[NUM_CARGO + 3]; ///< Texts for filter_cargo, terminated by INVALID_STRING_ID
byte produced_cargo_filter_criteria; ///< Selected produced cargo filter index
byte accepted_cargo_filter_criteria; ///< Selected accepted cargo filter index
static CargoID produced_cargo_filter;
enum class SorterType : uint8 {
IDW_SORT_BY_NAME, ///< Sorter type to sort by name
IDW_SORT_BY_TYPE, ///< Sorter type to sort by type
IDW_SORT_BY_PRODUCTION, ///< Sorter type to sort by production amount
IDW_SORT_BY_TRANSPORTED, ///< Sorter type to sort by transported percentage
};
/**
* Set cargo filter list item index.
@@ -1409,6 +1417,8 @@ protected:
this->cargo_filter[this->produced_cargo_filter_criteria]);
this->industries.Filter(filter);
IndustryDirectoryWindow::produced_cargo_filter = this->cargo_filter[this->produced_cargo_filter_criteria];
this->industries.Sort();
this->vscroll->SetCount((uint)this->industries.size()); // Update scrollbar as well.
@@ -1427,7 +1437,7 @@ protected:
{
assert(id < lengthof(i->produced_cargo));
if (i->produced_cargo[id] == CT_INVALID) return 101;
if (i->produced_cargo[id] == CT_INVALID) return -1;
return ToPercent8(i->last_month_pct_transported[id]);
}
@@ -1440,12 +1450,27 @@ protected:
*/
static int GetCargoTransportedSortValue(const Industry *i)
int p1 = GetCargoTransportedPercentsIfValid(i, 0);
int p2 = GetCargoTransportedPercentsIfValid(i, 1);
if (p1 > p2) Swap(p1, p2); // lower value has higher priority
return (p1 << 8) + p2;
CargoID filter = IndustryDirectoryWindow::produced_cargo_filter;
if (filter == CF_NONE) return 0;
int percentage = 0, produced_cargo_count = 0;
for (uint id = 0; id < lengthof(i->produced_cargo); id++) {
if (filter == CF_ANY) {
int transported = GetCargoTransportedPercentsIfValid(i, id);
if (transported != -1) {
produced_cargo_count++;
percentage += transported;
if (produced_cargo_count == 0 && id == lengthof(i->produced_cargo) - 1 && percentage == 0) {
return transported;
} else if (filter == i->produced_cargo[id]) {
return GetCargoTransportedPercentsIfValid(i, id);
if (produced_cargo_count == 0) return percentage;
return percentage / produced_cargo_count;
/** Sort industries by name */
@@ -1470,10 +1495,18 @@ protected:
/** Sort industries by production and name */
static bool IndustryProductionSorter(const Industry * const &a, const Industry * const &b)
if (filter == CF_NONE) return IndustryTypeSorter(a, b);
uint prod_a = 0, prod_b = 0;
for (uint i = 0; i < lengthof(a->produced_cargo); i++) {
if (a->produced_cargo[i] != CT_INVALID) prod_a += a->last_month_production[i];
if (b->produced_cargo[i] != CT_INVALID) prod_b += b->last_month_production[i];
} else {
if (a->produced_cargo[i] == filter) prod_a += a->last_month_production[i];
if (b->produced_cargo[i] == filter) prod_b += b->last_month_production[i];
int r = prod_a - prod_b;
@@ -1504,26 +1537,45 @@ protected:
GetAllCargoSuffixes(CARGOSUFFIX_OUT, CST_DIR, i, i->type, indsp, i->produced_cargo, cargo_suffix);
/* Get industry productions (CargoID, production, suffix, transported) */
typedef std::tuple<CargoID, uint16, const char*, uint> CargoInfo;
struct CargoInfo {
CargoID cargo_id;
uint16 production;
const char *suffix;
uint transported;
std::vector<CargoInfo> cargos;
for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
if (i->produced_cargo[j] == CT_INVALID) continue;
cargos.emplace_back(i->produced_cargo[j], i->last_month_production[j], cargo_suffix[j].text, ToPercent8(i->last_month_pct_transported[j]));
cargos.push_back({ i->produced_cargo[j], i->last_month_production[j], cargo_suffix[j].text, ToPercent8(i->last_month_pct_transported[j]) });
/* Sort by descending production, then descending transported */
std::sort(cargos.begin(), cargos.end(), [](const CargoInfo a, const CargoInfo b) {
if (std::get<1>(a) != std::get<1>(b)) return std::get<1>(a) > std::get<1>(b);
return std::get<3>(a) > std::get<3>(b);
});
switch (static_cast<IndustryDirectoryWindow::SorterType>(this->industries.SortType())) {
case IndustryDirectoryWindow::SorterType::IDW_SORT_BY_NAME:
case IndustryDirectoryWindow::SorterType::IDW_SORT_BY_TYPE:
case IndustryDirectoryWindow::SorterType::IDW_SORT_BY_PRODUCTION:
std::sort(cargos.begin(), cargos.end(), [](const CargoInfo &a, const CargoInfo &b) {
if (a.production != b.production) return a.production > b.production;
return a.transported > b.transported;
break;
case IndustryDirectoryWindow::SorterType::IDW_SORT_BY_TRANSPORTED:
/* Sort by descending transported, then descending production */
if (a.transported != b.transported) return a.transported > b.transported;
return a.production > b.production;
/* If the produced cargo filter is active then move the filtered cargo to the beginning of the list,
* because this is the one the player interested in, and that way it is not hidden in the 'n' more cargos */
const CargoID cid = this->cargo_filter[this->produced_cargo_filter_criteria];
if (cid != CF_ANY && cid != CF_NONE) {
auto filtered_ci = std::find_if(cargos.begin(), cargos.end(), [cid](const CargoInfo& ci) -> bool {
return std::get<0>(ci) == cid;
auto filtered_ci = std::find_if(cargos.begin(), cargos.end(), [cid](const CargoInfo &ci) -> bool {
return ci.cargo_id == cid;
if (filtered_ci != cargos.end()) {
std::rotate(cargos.begin(), filtered_ci, filtered_ci + 1);
@@ -1534,10 +1586,10 @@ protected:
for (size_t j = 0; j < std::min<size_t>(3, cargos.size()); j++) {
CargoInfo ci = cargos[j];
SetDParam(p++, STR_INDUSTRY_DIRECTORY_ITEM_INFO);
SetDParam(p++, std::get<0>(ci));
SetDParam(p++, std::get<1>(ci));
SetDParamStr(p++, std::get<2>(ci));
SetDParam(p++, std::get<3>(ci));
SetDParam(p++, ci.cargo_id);
SetDParam(p++, ci.production);
SetDParamStr(p++, ci.suffix);
SetDParam(p++, ci.transported);
/* Undisplayed cargos if any */
@@ -1785,6 +1837,8 @@ const StringID IndustryDirectoryWindow::
INVALID_STRING_ID
CargoID IndustryDirectoryWindow::produced_cargo_filter = CF_ANY;
/** Window definition of the industry directory gui */
static WindowDesc _industry_directory_desc(
Status change: