Changeset - r26681:a05a7fd62f4b
[Not reviewed]
master
0 3 0
peter1138 - 5 years ago 2019-02-27 07:04:17
peter1138@openttd.org
Change: Add variant hierarchy to build vehicle window list.
3 files changed with 188 insertions and 90 deletions:
0 comments (0 inline, 0 general)
src/autoreplace_gui.cpp
Show inline comments
 
@@ -33,11 +33,11 @@
 

	
 
#include "safeguards.h"
 

	
 
void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList *eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group);
 
void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group);
 

	
 
static bool EngineNumberSorter(const EngineID &a, const EngineID &b)
 
static bool EngineNumberSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	return Engine::Get(a)->list_position < Engine::Get(b)->list_position;
 
	return Engine::Get(a.engine_id)->list_position < Engine::Get(b.engine_id)->list_position;
 
}
 

	
 
/**
 
@@ -113,6 +113,22 @@ class ReplaceVehicleWindow : public Wind
 
		return true;
 
	}
 

	
 
	void AddChildren(const GUIEngineList &source, GUIEngineList &target, EngineID parent, int indent, int side)
 
	{
 
		for (const auto &item : source) {
 
			if (item.variant_id != parent || item.engine_id == parent) continue;
 

	
 
			const Engine *e = Engine::Get(item.engine_id);
 
			EngineDisplayFlags flags = item.flags;
 
			if (e->display_last_variant != INVALID_ENGINE) flags &= ~EngineDisplayFlags::Shaded;
 
			target.emplace_back(e->display_last_variant == INVALID_ENGINE ? item.engine_id : e->display_last_variant, item.engine_id, flags, indent);
 

	
 
			/* Add variants if not folded */
 
			if ((item.flags & (EngineDisplayFlags::HasVariants | EngineDisplayFlags::IsFolded)) == EngineDisplayFlags::HasVariants) {
 
				AddChildren(source, target, item.engine_id, indent + 1, side);
 
			}
 
		}
 
	}
 

	
 
	/**
 
	 * Generate an engines list
 
@@ -120,12 +136,12 @@ class ReplaceVehicleWindow : public Wind
 
	 */
 
	void GenerateReplaceVehList(bool draw_left)
 
	{
 
		std::vector<EngineID> variants;
 
		EngineID selected_engine = INVALID_ENGINE;
 
		VehicleType type = (VehicleType)this->window_number;
 
		byte side = draw_left ? 0 : 1;
 

	
 
		GUIEngineList *list = &this->engines[side];
 
		list->clear();
 
		GUIEngineList list;
 

	
 
		for (const Engine *e : Engine::IterateType(type)) {
 
			if (!draw_left && !this->show_hidden_engines && e->IsHidden(_local_company)) continue;
 
@@ -155,15 +171,37 @@ class ReplaceVehicleWindow : public Wind
 
				if (!CheckAutoreplaceValidity(this->sel_engine[0], eid, _local_company)) continue;
 
			}
 

	
 
			list->push_back(eid);
 
			EngineDisplayFlags flags = (side == 0) ? EngineDisplayFlags::None : e->display_flags;
 
			if (side == 1 && eid == this->sel_engine[0]) flags |= EngineDisplayFlags::Shaded;
 
			list.emplace_back(eid, e->info.variant_id, flags, 0);
 

	
 
			if (side == 1 && e->info.variant_id != INVALID_ENGINE) variants.push_back(e->info.variant_id);
 
			if (eid == this->sel_engine[side]) selected_engine = eid; // The selected engine is still in the list
 
		}
 

	
 
		if (side == 1) {
 
			/* ensure primary engine of variant group is in list */
 
			for (const auto &variant : variants) {
 
				if (std::find(list.begin(), list.end(), variant) == list.end()) {
 
					const Engine *e = Engine::Get(variant);
 
					list.emplace_back(variant, e->info.variant_id, e->display_flags | EngineDisplayFlags::Shaded, 0);
 
				}
 
			}
 
		}
 

	
 
		this->sel_engine[side] = selected_engine; // update which engine we selected (the same or none, if it's not in the list anymore)
 
		if (draw_left) {
 
			EngList_Sort(list, &EngineNumberSorter);
 
			EngList_Sort(&list, &EngineNumberSorter);
 
		} else {
 
			_engine_sort_direction = this->descending_sort_order;
 
			EngList_Sort(list, _engine_sort_functions[this->window_number][this->sort_criteria]);
 
			EngList_Sort(&list, _engine_sort_functions[this->window_number][this->sort_criteria]);
 
		}
 

	
 
		this->engines[side].clear();
 
		if (side == 1) {
 
			AddChildren(list, this->engines[side], INVALID_ENGINE, 0, side);
 
		} else {
 
			this->engines[side].swap(list);
 
		}
 
	}
 

	
 
@@ -177,7 +215,7 @@ class ReplaceVehicleWindow : public Wind
 
			this->GenerateReplaceVehList(true);
 
			this->vscroll[0]->SetCount((uint)this->engines[0].size());
 
			if (this->reset_sel_engine && this->sel_engine[0] == INVALID_ENGINE && this->engines[0].size() != 0) {
 
				this->sel_engine[0] = this->engines[0][0];
 
				this->sel_engine[0] = this->engines[0][0].engine_id;
 
			}
 
		}
 

	
 
@@ -198,8 +236,8 @@ class ReplaceVehicleWindow : public Wind
 
				this->vscroll[1]->SetCount((uint)this->engines[1].size());
 
				if (this->reset_sel_engine && this->sel_engine[1] != INVALID_ENGINE) {
 
					int position = 0;
 
					for (EngineID &eid : this->engines[1]) {
 
						if (eid == this->sel_engine[1]) break;
 
					for (const auto &item : this->engines[1]) {
 
						if (item.engine_id == this->sel_engine[1]) break;
 
						++position;
 
					}
 
					this->vscroll[1]->ScrollTowards(position);
 
@@ -433,7 +471,7 @@ public:
 
				EngineID end    = static_cast<EngineID>(std::min<size_t>(this->vscroll[side]->GetCapacity() + start, this->engines[side].size()));
 

	
 
				/* Do the actual drawing */
 
				DrawEngineList((VehicleType)this->window_number, r, &this->engines[side], start, end, this->sel_engine[side], side == 0, this->sel_group);
 
				DrawEngineList((VehicleType)this->window_number, r, this->engines[side], start, end, this->sel_engine[side], side == 0, this->sel_group);
 
				break;
 
			}
 
		}
 
@@ -579,7 +617,7 @@ public:
 
				uint i = this->vscroll[click_side]->GetScrolledRowFromWidget(pt.y, this, widget);
 
				size_t engine_count = this->engines[click_side].size();
 

	
 
				EngineID e = engine_count > i ? this->engines[click_side][i] : INVALID_ENGINE;
 
				EngineID e = engine_count > i ? this->engines[click_side][i].engine_id : INVALID_ENGINE;
 

	
 
				/* If Ctrl is pressed on the left side and we don't have any engines of the selected type, stop autoreplacing.
 
				 * This is most common when we have finished autoreplacing the engine and want to remove it from the list. */
src/build_vehicle_gui.cpp
Show inline comments
 
@@ -106,9 +106,9 @@ static CargoID _engine_sort_last_cargo_c
 
 * @param b second engine to compare
 
 * @return for descending order: returns true if a < b. Vice versa for ascending order
 
 */
 
static bool EngineNumberSorter(const EngineID &a, const EngineID &b)
 
static bool EngineNumberSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	int r = Engine::Get(a)->list_position - Engine::Get(b)->list_position;
 
	int r = Engine::Get(a.engine_id)->list_position - Engine::Get(b.engine_id)->list_position;
 

	
 
	return _engine_sort_direction ? r > 0 : r < 0;
 
}
 
@@ -119,10 +119,10 @@ static bool EngineNumberSorter(const Eng
 
 * @param b second engine to compare
 
 * @return for descending order: returns true if a < b. Vice versa for ascending order
 
 */
 
static bool EngineIntroDateSorter(const EngineID &a, const EngineID &b)
 
static bool EngineIntroDateSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	const int va = Engine::Get(a)->intro_date;
 
	const int vb = Engine::Get(b)->intro_date;
 
	const int va = Engine::Get(a.engine_id)->intro_date;
 
	const int vb = Engine::Get(b.engine_id)->intro_date;
 
	const int r = va - vb;
 

	
 
	/* Use EngineID to sort instead since we want consistent sorting */
 
@@ -139,19 +139,19 @@ static EngineID _last_engine[2] = { INVA
 
 * @param b second engine to compare
 
 * @return for descending order: returns true if a < b. Vice versa for ascending order
 
 */
 
static bool EngineNameSorter(const EngineID &a, const EngineID &b)
 
static bool EngineNameSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	static char     last_name[2][64] = { "", "" };
 

	
 
	if (a != _last_engine[0]) {
 
		_last_engine[0] = a;
 
		SetDParam(0, a);
 
	if (a.engine_id != _last_engine[0]) {
 
		_last_engine[0] = a.engine_id;
 
		SetDParam(0, a.engine_id);
 
		GetString(last_name[0], STR_ENGINE_NAME, lastof(last_name[0]));
 
	}
 

	
 
	if (b != _last_engine[1]) {
 
		_last_engine[1] = b;
 
		SetDParam(0, b);
 
	if (b.engine_id != _last_engine[1]) {
 
		_last_engine[1] = b.engine_id;
 
		SetDParam(0, b.engine_id);
 
		GetString(last_name[1], STR_ENGINE_NAME, lastof(last_name[1]));
 
	}
 

	
 
@@ -168,10 +168,10 @@ static bool EngineNameSorter(const Engin
 
 * @param b second engine to compare
 
 * @return for descending order: returns true if a < b. Vice versa for ascending order
 
 */
 
static bool EngineReliabilitySorter(const EngineID &a, const EngineID &b)
 
static bool EngineReliabilitySorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	const int va = Engine::Get(a)->reliability;
 
	const int vb = Engine::Get(b)->reliability;
 
	const int va = Engine::Get(a.engine_id)->reliability;
 
	const int vb = Engine::Get(b.engine_id)->reliability;
 
	const int r = va - vb;
 

	
 
	/* Use EngineID to sort instead since we want consistent sorting */
 
@@ -185,10 +185,10 @@ static bool EngineReliabilitySorter(cons
 
 * @param b second engine to compare
 
 * @return for descending order: returns true if a < b. Vice versa for ascending order
 
 */
 
static bool EngineCostSorter(const EngineID &a, const EngineID &b)
 
static bool EngineCostSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	Money va = Engine::Get(a)->GetCost();
 
	Money vb = Engine::Get(b)->GetCost();
 
	Money va = Engine::Get(a.engine_id)->GetCost();
 
	Money vb = Engine::Get(b.engine_id)->GetCost();
 
	int r = ClampToI32(va - vb);
 

	
 
	/* Use EngineID to sort instead since we want consistent sorting */
 
@@ -202,10 +202,10 @@ static bool EngineCostSorter(const Engin
 
 * @param b second engine to compare
 
 * @return for descending order: returns true if a < b. Vice versa for ascending order
 
 */
 
static bool EngineSpeedSorter(const EngineID &a, const EngineID &b)
 
static bool EngineSpeedSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	int va = Engine::Get(a)->GetDisplayMaxSpeed();
 
	int vb = Engine::Get(b)->GetDisplayMaxSpeed();
 
	int va = Engine::Get(a.engine_id)->GetDisplayMaxSpeed();
 
	int vb = Engine::Get(b.engine_id)->GetDisplayMaxSpeed();
 
	int r = va - vb;
 

	
 
	/* Use EngineID to sort instead since we want consistent sorting */
 
@@ -219,10 +219,10 @@ static bool EngineSpeedSorter(const Engi
 
 * @param b second engine to compare
 
 * @return for descending order: returns true if a < b. Vice versa for ascending order
 
 */
 
static bool EnginePowerSorter(const EngineID &a, const EngineID &b)
 
static bool EnginePowerSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	int va = Engine::Get(a)->GetPower();
 
	int vb = Engine::Get(b)->GetPower();
 
	int va = Engine::Get(a.engine_id)->GetPower();
 
	int vb = Engine::Get(b.engine_id)->GetPower();
 
	int r = va - vb;
 

	
 
	/* Use EngineID to sort instead since we want consistent sorting */
 
@@ -236,10 +236,10 @@ static bool EnginePowerSorter(const Engi
 
 * @param b second engine to compare
 
 * @return for descending order: returns true if a < b. Vice versa for ascending order
 
 */
 
static bool EngineTractiveEffortSorter(const EngineID &a, const EngineID &b)
 
static bool EngineTractiveEffortSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	int va = Engine::Get(a)->GetDisplayMaxTractiveEffort();
 
	int vb = Engine::Get(b)->GetDisplayMaxTractiveEffort();
 
	int va = Engine::Get(a.engine_id)->GetDisplayMaxTractiveEffort();
 
	int vb = Engine::Get(b.engine_id)->GetDisplayMaxTractiveEffort();
 
	int r = va - vb;
 

	
 
	/* Use EngineID to sort instead since we want consistent sorting */
 
@@ -253,10 +253,10 @@ static bool EngineTractiveEffortSorter(c
 
 * @param b second engine to compare
 
 * @return for descending order: returns true if a < b. Vice versa for ascending order
 
 */
 
static bool EngineRunningCostSorter(const EngineID &a, const EngineID &b)
 
static bool EngineRunningCostSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	Money va = Engine::Get(a)->GetRunningCost();
 
	Money vb = Engine::Get(b)->GetRunningCost();
 
	Money va = Engine::Get(a.engine_id)->GetRunningCost();
 
	Money vb = Engine::Get(b.engine_id)->GetRunningCost();
 
	int r = ClampToI32(va - vb);
 

	
 
	/* Use EngineID to sort instead since we want consistent sorting */
 
@@ -270,10 +270,10 @@ static bool EngineRunningCostSorter(cons
 
 * @param b second engine to compare
 
 * @return for descending order: returns true if a < b. Vice versa for ascending order
 
 */
 
static bool EnginePowerVsRunningCostSorter(const EngineID &a, const EngineID &b)
 
static bool EnginePowerVsRunningCostSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	const Engine *e_a = Engine::Get(a);
 
	const Engine *e_b = Engine::Get(b);
 
	const Engine *e_a = Engine::Get(a.engine_id);
 
	const Engine *e_b = Engine::Get(b.engine_id);
 
	uint p_a = e_a->GetPower();
 
	uint p_b = e_b->GetPower();
 
	Money r_a = e_a->GetRunningCost();
 
@@ -312,13 +312,13 @@ static bool EnginePowerVsRunningCostSort
 
 * @param b second engine to compare
 
 * @return for descending order: returns true if a < b. Vice versa for ascending order
 
 */
 
static bool TrainEngineCapacitySorter(const EngineID &a, const EngineID &b)
 
static bool TrainEngineCapacitySorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	const RailVehicleInfo *rvi_a = RailVehInfo(a);
 
	const RailVehicleInfo *rvi_b = RailVehInfo(b);
 
	const RailVehicleInfo *rvi_a = RailVehInfo(a.engine_id);
 
	const RailVehicleInfo *rvi_b = RailVehInfo(b.engine_id);
 

	
 
	int va = GetTotalCapacityOfArticulatedParts(a) * (rvi_a->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1);
 
	int vb = GetTotalCapacityOfArticulatedParts(b) * (rvi_b->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1);
 
	int va = GetTotalCapacityOfArticulatedParts(a.engine_id) * (rvi_a->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1);
 
	int vb = GetTotalCapacityOfArticulatedParts(b.engine_id) * (rvi_b->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1);
 
	int r = va - vb;
 

	
 
	/* Use EngineID to sort instead since we want consistent sorting */
 
@@ -332,10 +332,10 @@ static bool TrainEngineCapacitySorter(co
 
 * @param b second engine to compare
 
 * @return for descending order: returns true if a < b. Vice versa for ascending order
 
 */
 
static bool TrainEnginesThenWagonsSorter(const EngineID &a, const EngineID &b)
 
static bool TrainEnginesThenWagonsSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	int val_a = (RailVehInfo(a)->railveh_type == RAILVEH_WAGON ? 1 : 0);
 
	int val_b = (RailVehInfo(b)->railveh_type == RAILVEH_WAGON ? 1 : 0);
 
	int val_a = (RailVehInfo(a.engine_id)->railveh_type == RAILVEH_WAGON ? 1 : 0);
 
	int val_b = (RailVehInfo(b.engine_id)->railveh_type == RAILVEH_WAGON ? 1 : 0);
 
	int r = val_a - val_b;
 

	
 
	/* Use EngineID to sort instead since we want consistent sorting */
 
@@ -351,10 +351,10 @@ static bool TrainEnginesThenWagonsSorter
 
 * @param b second engine to compare
 
 * @return for descending order: returns true if a < b. Vice versa for ascending order
 
 */
 
static bool RoadVehEngineCapacitySorter(const EngineID &a, const EngineID &b)
 
static bool RoadVehEngineCapacitySorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	int va = GetTotalCapacityOfArticulatedParts(a);
 
	int vb = GetTotalCapacityOfArticulatedParts(b);
 
	int va = GetTotalCapacityOfArticulatedParts(a.engine_id);
 
	int vb = GetTotalCapacityOfArticulatedParts(b.engine_id);
 
	int r = va - vb;
 

	
 
	/* Use EngineID to sort instead since we want consistent sorting */
 
@@ -370,10 +370,10 @@ static bool RoadVehEngineCapacitySorter(
 
 * @param b second engine to compare
 
 * @return for descending order: returns true if a < b. Vice versa for ascending order
 
 */
 
static bool ShipEngineCapacitySorter(const EngineID &a, const EngineID &b)
 
static bool ShipEngineCapacitySorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	const Engine *e_a = Engine::Get(a);
 
	const Engine *e_b = Engine::Get(b);
 
	const Engine *e_a = Engine::Get(a.engine_id);
 
	const Engine *e_b = Engine::Get(b.engine_id);
 

	
 
	int va = e_a->GetDisplayDefaultCapacity();
 
	int vb = e_b->GetDisplayDefaultCapacity();
 
@@ -392,10 +392,10 @@ static bool ShipEngineCapacitySorter(con
 
 * @param b second engine to compare
 
 * @return for descending order: returns true if a < b. Vice versa for ascending order
 
 */
 
static bool AircraftEngineCargoSorter(const EngineID &a, const EngineID &b)
 
static bool AircraftEngineCargoSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	const Engine *e_a = Engine::Get(a);
 
	const Engine *e_b = Engine::Get(b);
 
	const Engine *e_a = Engine::Get(a.engine_id);
 
	const Engine *e_b = Engine::Get(b.engine_id);
 

	
 
	uint16 mail_a, mail_b;
 
	int va = e_a->GetDisplayDefaultCapacity(&mail_a);
 
@@ -420,10 +420,10 @@ static bool AircraftEngineCargoSorter(co
 
 * @param b second engine to compare
 
 * @return for descending order: returns true if a < b. Vice versa for ascending order
 
 */
 
static bool AircraftRangeSorter(const EngineID &a, const EngineID &b)
 
static bool AircraftRangeSorter(const GUIEngineListItem &a, const GUIEngineListItem &b)
 
{
 
	uint16 r_a = Engine::Get(a)->GetRange();
 
	uint16 r_b = Engine::Get(b)->GetRange();
 
	uint16 r_a = Engine::Get(a.engine_id)->GetRange();
 
	uint16 r_b = Engine::Get(b.engine_id)->GetRange();
 

	
 
	int r = r_a - r_b;
 

	
 
@@ -537,14 +537,14 @@ const StringID _engine_sort_listing[][12
 
}};
 

	
 
/** Filters vehicles by cargo and engine (in case of rail vehicle). */
 
static bool CDECL CargoAndEngineFilter(const EngineID *eid, const CargoID cid)
 
static bool CDECL CargoAndEngineFilter(const GUIEngineListItem *item, const CargoID cid)
 
{
 
	if (cid == CF_ANY) {
 
		return true;
 
	} else if (cid == CF_ENGINES) {
 
		return Engine::Get(*eid)->GetPower() != 0;
 
		return Engine::Get(item->engine_id)->GetPower() != 0;
 
	} else {
 
		CargoTypes refit_mask = GetUnionOfArticulatedRefitMasks(*eid, true) & _standard_cargo_mask;
 
		CargoTypes refit_mask = GetUnionOfArticulatedRefitMasks(item->engine_id, true) & _standard_cargo_mask;
 
		return (cid == CF_NONE ? refit_mask == 0 : HasBit(refit_mask, cid));
 
	}
 
}
 
@@ -962,12 +962,12 @@ int DrawVehiclePurchaseInfo(int left, in
 
 * @param show_count Whether to show the amount of engines or not
 
 * @param selected_group the group to list the engines of
 
 */
 
void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList *eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group)
 
void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group)
 
{
 
	static const int sprite_y_offsets[] = { -1, -1, -2, -2 };
 

	
 
	/* Obligatory sanity checks! */
 
	assert(max <= eng_list->size());
 
	assert(max <= eng_list.size());
 

	
 
	bool rtl = _current_text_dir == TD_RTL;
 
	int step_size = GetEngineListHeight(type);
 
@@ -998,7 +998,7 @@ void DrawEngineList(VehicleType type, co
 

	
 
	int y = ir.top;
 
	for (; min < max; min++, y += step_size) {
 
		const EngineID engine = (*eng_list)[min];
 
		const EngineID engine = eng_list[min].engine_id;
 
		/* Note: num_engines is only used in the autoreplace GUI, so it is correct to use _local_company here. */
 
		const uint num_engines = GetGroupNumEngines(_local_company, selected_group, engine);
 

	
 
@@ -1078,6 +1078,23 @@ struct BuildVehicleWindow : Window {
 
		}
 
	}
 

	
 
	void AddChildren(const GUIEngineList &source, EngineID parent, int indent)
 
	{
 
		for (const auto &item : source) {
 
			if (item.variant_id != parent || item.engine_id == parent) continue;
 

	
 
			const Engine *e = Engine::Get(item.engine_id);
 
			EngineDisplayFlags flags = item.flags;
 
			if (e->display_last_variant != INVALID_ENGINE) flags &= ~EngineDisplayFlags::Shaded;
 
			this->eng_list.emplace_back(e->display_last_variant == INVALID_ENGINE ? item.engine_id : e->display_last_variant, item.engine_id, flags, indent);
 

	
 
			/* Add variants if not folded */
 
			if ((item.flags & (EngineDisplayFlags::HasVariants | EngineDisplayFlags::IsFolded)) == EngineDisplayFlags::HasVariants) {
 
				AddChildren(source, item.engine_id, indent + 1);
 
			}
 
		}
 
	}
 

	
 
	BuildVehicleWindow(WindowDesc *desc, TileIndex tile, VehicleType type) : Window(desc)
 
	{
 
		this->vehicle_type = type;
 
@@ -1125,7 +1142,7 @@ struct BuildVehicleWindow : Window {
 
		this->GenerateBuildList(); // generate the list, since we need it in the next line
 
		/* Select the first engine in the list as default when opening the window */
 
		if (this->eng_list.size() > 0) {
 
			this->SelectEngine(this->eng_list[0]);
 
			this->SelectEngine(this->eng_list[0].engine_id);
 
		} else {
 
			this->SelectEngine(INVALID_ENGINE);
 
		}
 
@@ -1257,7 +1274,7 @@ struct BuildVehicleWindow : Window {
 
		if (0 == this->eng_list.size()) { // no engine passed through the filter, invalidate the previously selected engine
 
			this->SelectEngine(INVALID_ENGINE);
 
		} else if (std::find(this->eng_list.begin(), this->eng_list.end(), this->sel_engine) == this->eng_list.end()) { // previously selected engine didn't pass the filter, select the first engine of the list
 
			this->SelectEngine(this->eng_list[0]);
 
			this->SelectEngine(this->eng_list[0].engine_id);
 
		}
 
	}
 

	
 
@@ -1265,17 +1282,19 @@ struct BuildVehicleWindow : Window {
 
	bool FilterSingleEngine(EngineID eid)
 
	{
 
		CargoID filter_type = this->cargo_filter[this->cargo_filter_criteria];
 
		return CargoAndEngineFilter(&eid, filter_type);
 
		GUIEngineListItem item = {eid, eid, EngineDisplayFlags::None, 0};
 
		return CargoAndEngineFilter(&item, filter_type);
 
	}
 

	
 
	/* Figure out what train EngineIDs to put in the list */
 
	void GenerateBuildTrainList()
 
	void GenerateBuildTrainList(GUIEngineList &list)
 
	{
 
		std::vector<EngineID> variants;
 
		EngineID sel_id = INVALID_ENGINE;
 
		int num_engines = 0;
 
		int num_wagons  = 0;
 

	
 
		this->eng_list.clear();
 
		list.clear();
 

	
 
		/* Make list of all available train engines and wagons.
 
		 * Also check to see if the previously selected engine is still available,
 
@@ -1292,7 +1311,7 @@ struct BuildVehicleWindow : Window {
 
			/* Filter now! So num_engines and num_wagons is valid */
 
			if (!FilterSingleEngine(eid)) continue;
 

	
 
			this->eng_list.push_back(eid);
 
			list.emplace_back(eid, e->info.variant_id, e->display_flags, 0);
 

	
 
			if (rvi->railveh_type != RAILVEH_WAGON) {
 
				num_engines++;
 
@@ -1300,9 +1319,18 @@ struct BuildVehicleWindow : Window {
 
				num_wagons++;
 
			}
 

	
 
			if (e->info.variant_id != eid && e->info.variant_id != INVALID_ENGINE) variants.push_back(e->info.variant_id);
 
			if (eid == this->sel_engine) sel_id = eid;
 
		}
 

	
 
		/* ensure primary engine of variant group is in list */
 
		for (const auto &variant : variants) {
 
			if (std::find(list.begin(), list.end(), variant) == list.end()) {
 
				const Engine *e = Engine::Get(variant);
 
				list.emplace_back(variant, e->info.variant_id, e->display_flags | EngineDisplayFlags::Shaded, 0);
 
			}
 
		}
 

	
 
		this->SelectEngine(sel_id);
 

	
 
		/* invalidate cached values for name sorter - engine names could change */
 
@@ -1310,14 +1338,14 @@ struct BuildVehicleWindow : Window {
 

	
 
		/* make engines first, and then wagons, sorted by selected sort_criteria */
 
		_engine_sort_direction = false;
 
		EngList_Sort(&this->eng_list, TrainEnginesThenWagonsSorter);
 
		EngList_Sort(&list, TrainEnginesThenWagonsSorter);
 

	
 
		/* and then sort engines */
 
		_engine_sort_direction = this->descending_sort_order;
 
		EngList_SortPartial(&this->eng_list, _engine_sort_functions[0][this->sort_criteria], 0, num_engines);
 
		EngList_SortPartial(&list, _engine_sort_functions[0][this->sort_criteria], 0, num_engines);
 

	
 
		/* and finally sort wagons */
 
		EngList_SortPartial(&this->eng_list, _engine_sort_functions[0][this->sort_criteria], num_engines, num_wagons);
 
		EngList_SortPartial(&list, _engine_sort_functions[0][this->sort_criteria], num_engines, num_wagons);
 
	}
 

	
 
	/* Figure out what road vehicle EngineIDs to put in the list */
 
@@ -1333,7 +1361,7 @@ struct BuildVehicleWindow : Window {
 
			if (!IsEngineBuildable(eid, VEH_ROAD, _local_company)) continue;
 
			if (this->filter.roadtype != INVALID_ROADTYPE && !HasPowerOnRoad(e->u.road.roadtype, this->filter.roadtype)) continue;
 

	
 
			this->eng_list.push_back(eid);
 
			this->eng_list.emplace_back(eid, e->info.variant_id, e->display_flags, 0);
 

	
 
			if (eid == this->sel_engine) sel_id = eid;
 
		}
 
@@ -1350,7 +1378,7 @@ struct BuildVehicleWindow : Window {
 
			if (!this->show_hidden_engines && e->IsHidden(_local_company)) continue;
 
			EngineID eid = e->index;
 
			if (!IsEngineBuildable(eid, VEH_SHIP, _local_company)) continue;
 
			this->eng_list.push_back(eid);
 
			this->eng_list.emplace_back(eid, e->info.variant_id, e->display_flags, 0);
 

	
 
			if (eid == this->sel_engine) sel_id = eid;
 
		}
 
@@ -1377,7 +1405,7 @@ struct BuildVehicleWindow : Window {
 
			/* First VEH_END window_numbers are fake to allow a window open for all different types at once */
 
			if (!this->listview_mode && !CanVehicleUseStation(eid, st)) continue;
 

	
 
			this->eng_list.push_back(eid);
 
			this->eng_list.emplace_back(eid, e->info.variant_id, e->display_flags, 0);
 
			if (eid == this->sel_engine) sel_id = eid;
 
		}
 

	
 
@@ -1392,13 +1420,18 @@ struct BuildVehicleWindow : Window {
 
		/* Update filter type in case the road/railtype of the depot got converted */
 
		this->UpdateFilterByTile();
 

	
 
		this->eng_list.clear();
 

	
 
		GUIEngineList list;
 

	
 
		switch (this->vehicle_type) {
 
			default: NOT_REACHED();
 
			case VEH_TRAIN:
 
				this->GenerateBuildTrainList();
 
				this->GenerateBuildTrainList(list);
 
				AddChildren(list, INVALID_ENGINE, 0);
 
				this->eng_list.shrink_to_fit();
 
				this->eng_list.RebuildDone();
 
				return; // trains should not reach the last sorting
 
				return;
 
			case VEH_ROAD:
 
				this->GenerateBuildRoadVehList();
 
				break;
 
@@ -1412,9 +1445,23 @@ struct BuildVehicleWindow : Window {
 

	
 
		this->FilterEngineList();
 

	
 
		/* ensure primary engine of variant group is in list after filtering */
 
		std::vector<EngineID> variants;
 
		for (const auto &item : this->eng_list) {
 
			if (item.engine_id != item.variant_id && item.variant_id != INVALID_ENGINE) variants.push_back(item.variant_id);
 
		}
 
		for (const auto &variant : variants) {
 
			if (std::find(this->eng_list.begin(), this->eng_list.end(), variant) == this->eng_list.end()) {
 
				const Engine *e = Engine::Get(variant);
 
				list.emplace_back(variant, e->info.variant_id, e->display_flags | EngineDisplayFlags::Shaded, 0);
 
			}
 
		}
 

	
 
		_engine_sort_direction = this->descending_sort_order;
 
		EngList_Sort(&this->eng_list, _engine_sort_functions[this->vehicle_type][this->sort_criteria]);
 

	
 
		this->eng_list.swap(list);
 
		AddChildren(list, INVALID_ENGINE, 0);
 
		this->eng_list.shrink_to_fit();
 
		this->eng_list.RebuildDone();
 
	}
 
@@ -1440,7 +1487,7 @@ struct BuildVehicleWindow : Window {
 
			case WID_BV_LIST: {
 
				uint i = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_BV_LIST);
 
				size_t num_items = this->eng_list.size();
 
				this->SelectEngine((i < num_items) ? this->eng_list[i] : INVALID_ENGINE);
 
				this->SelectEngine((i < num_items) ? this->eng_list[i].engine_id : INVALID_ENGINE);
 
				this->SetDirty();
 
				if (_ctrl_pressed) {
 
					this->OnClick(pt, WID_BV_SHOW_HIDE, 1);
 
@@ -1589,7 +1636,7 @@ struct BuildVehicleWindow : Window {
 
				DrawEngineList(
 
					this->vehicle_type,
 
					r,
 
					&this->eng_list,
 
					this->eng_list,
 
					this->vscroll->GetPosition(),
 
					static_cast<uint16>(std::min<size_t>(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->eng_list.size())),
 
					this->sel_engine,
src/engine_gui.h
Show inline comments
 
@@ -14,10 +14,23 @@
 
#include "sortlist_type.h"
 
#include "gfx_type.h"
 
#include "vehicle_type.h"
 
#include "engine_base.h"
 

	
 
typedef GUIList<EngineID, CargoID> GUIEngineList;
 
struct GUIEngineListItem {
 
	EngineID engine_id;       ///< Engine to display in build purchase list
 
	EngineID variant_id;      ///< Variant group of the engine.
 
	EngineDisplayFlags flags; ///< Flags for toggling/drawing (un)folded status and controlling indentation.
 
	int8 indent;              ///< Display indentation level.
 

	
 
	GUIEngineListItem(EngineID engine_id, EngineID variant_id, EngineDisplayFlags flags, int indent) : engine_id(engine_id), variant_id(variant_id), flags(flags), indent(indent) {}
 

	
 
typedef bool EngList_SortTypeFunction(const EngineID&, const EngineID&); ///< argument type for #EngList_Sort.
 
	/* Used when searching list only by engine_id. */
 
	bool operator == (const EngineID &other) const { return this->engine_id == other; }
 
};
 

	
 
typedef GUIList<GUIEngineListItem, CargoID> GUIEngineList;
 

	
 
typedef bool EngList_SortTypeFunction(const GUIEngineListItem&, const GUIEngineListItem&); ///< argument type for #EngList_Sort.
 
void EngList_Sort(GUIEngineList *el, EngList_SortTypeFunction compare);
 
void EngList_SortPartial(GUIEngineList *el, EngList_SortTypeFunction compare, uint begin, uint num_items);
 

	
0 comments (0 inline, 0 general)