src/build_vehicle_gui.cpp
branchNewGRF_ports
changeset 10991 d8811e327d12
parent 10731 67db0d431d5e
equal deleted inserted replaced
10731:67db0d431d5e 10991:d8811e327d12
    27 #include "settings_type.h"
    27 #include "settings_type.h"
    28 #include "gfx_func.h"
    28 #include "gfx_func.h"
    29 #include "widgets/dropdown_func.h"
    29 #include "widgets/dropdown_func.h"
    30 #include "string_func.h"
    30 #include "string_func.h"
    31 #include "window_gui.h"
    31 #include "window_gui.h"
       
    32 #include "engine_gui.h"
    32 
    33 
    33 #include "table/sprites.h"
    34 #include "table/sprites.h"
    34 #include "table/strings.h"
    35 #include "table/strings.h"
    35 
    36 
    36 enum BuildVehicleWidgets {
    37 enum BuildVehicleWidgets {
   504 	SetDParam(1, (GetCargo(rvi->cargo_type)->weight * GetEngineProperty(engine_number, 0x14, rvi->capacity) >> 4) + weight);
   505 	SetDParam(1, (GetCargo(rvi->cargo_type)->weight * GetEngineProperty(engine_number, 0x14, rvi->capacity) >> 4) + weight);
   505 	DrawString(x, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT, TC_FROMSTRING);
   506 	DrawString(x, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT, TC_FROMSTRING);
   506 	y += 10;
   507 	y += 10;
   507 
   508 
   508 	/* Wagon speed limit, displayed if above zero */
   509 	/* Wagon speed limit, displayed if above zero */
   509 	if (_settings.vehicle.wagon_speed_limits) {
   510 	if (_settings_game.vehicle.wagon_speed_limits) {
   510 		uint max_speed = GetEngineProperty(engine_number, 0x09, rvi->max_speed);
   511 		uint max_speed = GetEngineProperty(engine_number, 0x09, rvi->max_speed);
   511 		if (max_speed > 0) {
   512 		if (max_speed > 0) {
   512 			SetDParam(0, max_speed * 10 / 16);
   513 			SetDParam(0, max_speed * 10 / 16);
   513 			DrawString(x, y, STR_PURCHASE_INFO_SPEED, TC_FROMSTRING);
   514 			DrawString(x, y, STR_PURCHASE_INFO_SPEED, TC_FROMSTRING);
   514 			y += 10;
   515 			y += 10;
   542 	SetDParam(1, GetEngineProperty(engine_number, 0x0B, rvi->power));
   543 	SetDParam(1, GetEngineProperty(engine_number, 0x0B, rvi->power));
   543 	DrawString(x, y, STR_PURCHASE_INFO_SPEED_POWER, TC_FROMSTRING);
   544 	DrawString(x, y, STR_PURCHASE_INFO_SPEED_POWER, TC_FROMSTRING);
   544 	y += 10;
   545 	y += 10;
   545 
   546 
   546 	/* Max tractive effort - not applicable if old acceleration or maglev */
   547 	/* Max tractive effort - not applicable if old acceleration or maglev */
   547 	if (_settings.vehicle.realistic_acceleration && rvi->railtype != RAILTYPE_MAGLEV) {
   548 	if (_settings_game.vehicle.realistic_acceleration && rvi->railtype != RAILTYPE_MAGLEV) {
   548 		SetDParam(0, ((weight << multihead) * 10 * GetEngineProperty(engine_number, 0x1F, rvi->tractive_effort)) / 256);
   549 		SetDParam(0, ((weight << multihead) * 10 * GetEngineProperty(engine_number, 0x1F, rvi->tractive_effort)) / 256);
   549 		DrawString(x, y, STR_PURCHASE_INFO_MAX_TE, TC_FROMSTRING);
   550 		DrawString(x, y, STR_PURCHASE_INFO_MAX_TE, TC_FROMSTRING);
   550 		y += 10;
   551 		y += 10;
   551 	}
   552 	}
   552 
   553 
   742  * @param min where to start in the list
   743  * @param min where to start in the list
   743  * @param max where in the list to end
   744  * @param max where in the list to end
   744  * @param selected_id what engine to highlight as selected, if any
   745  * @param selected_id what engine to highlight as selected, if any
   745  * @param count_location Offset to print the engine count (used by autoreplace). 0 means it's off
   746  * @param count_location Offset to print the engine count (used by autoreplace). 0 means it's off
   746  */
   747  */
   747 void DrawEngineList(VehicleType type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, int count_location, GroupID selected_group)
   748 void DrawEngineList(VehicleType type, int x, int y, const GUIEngineList *eng_list, uint16 min, uint16 max, EngineID selected_id, int count_location, GroupID selected_group)
   748 {
   749 {
   749 	byte step_size = GetVehicleListHeight(type);
   750 	byte step_size = GetVehicleListHeight(type);
   750 	byte x_offset = 0;
   751 	byte x_offset = 0;
   751 	byte y_offset = 0;
   752 	byte y_offset = 0;
   752 
   753 
   753 	assert(max <= eng_list.size());
   754 	assert(max <= eng_list->Length());
   754 
   755 
   755 	switch (type) {
   756 	switch (type) {
   756 		case VEH_TRAIN:
   757 		case VEH_TRAIN:
   757 			x++; // train and road vehicles use the same offset, except trains are one more pixel to the right
   758 			x++; // train and road vehicles use the same offset, except trains are one more pixel to the right
   758 			/* Fallthough */
   759 			/* Fallthough */
   776 			break;
   777 			break;
   777 		default: NOT_REACHED();
   778 		default: NOT_REACHED();
   778 	}
   779 	}
   779 
   780 
   780 	for (; min < max; min++, y += step_size) {
   781 	for (; min < max; min++, y += step_size) {
   781 		const EngineID engine = eng_list[min];
   782 		const EngineID engine = (*eng_list)[min];
   782 		/* Note: num_engines is only used in the autoreplace GUI, so it is correct to use _local_player here. */
   783 		/* Note: num_engines is only used in the autoreplace GUI, so it is correct to use _local_player here. */
   783 		const uint num_engines = GetGroupNumEngines(_local_player, selected_group, engine);
   784 		const uint num_engines = GetGroupNumEngines(_local_player, selected_group, engine);
   784 
   785 
   785 		SetDParam(0, engine);
   786 		SetDParam(0, engine);
   786 		DrawString(x + x_offset, y, STR_ENGINE_NAME, engine == selected_id ? TC_WHITE : TC_BLACK);
   787 		DrawString(x + x_offset, y, STR_ENGINE_NAME, engine == selected_id ? TC_WHITE : TC_BLACK);
   803 	bool descending_sort_order;
   804 	bool descending_sort_order;
   804 	byte sort_criteria;
   805 	byte sort_criteria;
   805 	bool regenerate_list;
   806 	bool regenerate_list;
   806 	EngineID sel_engine;
   807 	EngineID sel_engine;
   807 	EngineID rename_engine;
   808 	EngineID rename_engine;
   808 	EngineList eng_list;
   809 	GUIEngineList eng_list;
   809 
   810 
   810 	BuildVehicleWindow(const WindowDesc *desc, TileIndex tile, VehicleType type) : Window(desc, tile == 0 ? (int)type : tile)
   811 	BuildVehicleWindow(const WindowDesc *desc, TileIndex tile, VehicleType type) : Window(desc, tile == 0 ? (int)type : tile)
   811 	{
   812 	{
   812 		this->vehicle_type = type;
   813 		this->vehicle_type = type;
   813 		int vlh = GetVehicleListHeight(this->vehicle_type);
   814 		int vlh = GetVehicleListHeight(this->vehicle_type);
   845 		this->SetupWindowStrings(type);
   846 		this->SetupWindowStrings(type);
   846 		ResizeButtons(this, BUILD_VEHICLE_WIDGET_BUILD, BUILD_VEHICLE_WIDGET_RENAME);
   847 		ResizeButtons(this, BUILD_VEHICLE_WIDGET_BUILD, BUILD_VEHICLE_WIDGET_RENAME);
   847 
   848 
   848 		this->GenerateBuildList(); // generate the list, since we need it in the next line
   849 		this->GenerateBuildList(); // generate the list, since we need it in the next line
   849 		/* Select the first engine in the list as default when opening the window */
   850 		/* Select the first engine in the list as default when opening the window */
   850 		if (this->eng_list.size() > 0) this->sel_engine = this->eng_list[0];
   851 		if (this->eng_list.Length() > 0) this->sel_engine = this->eng_list[0];
   851 
   852 
   852 		this->FindWindowPlacementAndResize(desc);
   853 		this->FindWindowPlacementAndResize(desc);
   853 	}
   854 	}
   854 
   855 
   855 	/* Setup widget strings to fit the different types of vehicles */
   856 	/* Setup widget strings to fit the different types of vehicles */
   903 		int num_engines = 0;
   904 		int num_engines = 0;
   904 		int num_wagons  = 0;
   905 		int num_wagons  = 0;
   905 
   906 
   906 		this->filter.railtype = (this->window_number <= VEH_END) ? RAILTYPE_END : GetRailType(this->window_number);
   907 		this->filter.railtype = (this->window_number <= VEH_END) ? RAILTYPE_END : GetRailType(this->window_number);
   907 
   908 
   908 		this->eng_list.clear();
   909 		this->eng_list.Clear();
   909 
   910 
   910 		/* Make list of all available train engines and wagons.
   911 		/* Make list of all available train engines and wagons.
   911 		* Also check to see if the previously selected engine is still available,
   912 		* Also check to see if the previously selected engine is still available,
   912 		* and if not, reset selection to INVALID_ENGINE. This could be the case
   913 		* and if not, reset selection to INVALID_ENGINE. This could be the case
   913 		* when engines become obsolete and are removed */
   914 		* when engines become obsolete and are removed */
   917 			const RailVehicleInfo *rvi = &e->u.rail;
   918 			const RailVehicleInfo *rvi = &e->u.rail;
   918 
   919 
   919 			if (this->filter.railtype != RAILTYPE_END && !HasPowerOnRail(rvi->railtype, this->filter.railtype)) continue;
   920 			if (this->filter.railtype != RAILTYPE_END && !HasPowerOnRail(rvi->railtype, this->filter.railtype)) continue;
   920 			if (!IsEngineBuildable(eid, VEH_TRAIN, _local_player)) continue;
   921 			if (!IsEngineBuildable(eid, VEH_TRAIN, _local_player)) continue;
   921 
   922 
   922 			this->eng_list.push_back(eid);
   923 			*this->eng_list.Append() = eid;
       
   924 
   923 			if (rvi->railveh_type != RAILVEH_WAGON) {
   925 			if (rvi->railveh_type != RAILVEH_WAGON) {
   924 				num_engines++;
   926 				num_engines++;
   925 			} else {
   927 			} else {
   926 				num_wagons++;
   928 				num_wagons++;
   927 			}
   929 			}
   946 	/* Figure out what road vehicle EngineIDs to put in the list */
   948 	/* Figure out what road vehicle EngineIDs to put in the list */
   947 	void GenerateBuildRoadVehList()
   949 	void GenerateBuildRoadVehList()
   948 	{
   950 	{
   949 		EngineID sel_id = INVALID_ENGINE;
   951 		EngineID sel_id = INVALID_ENGINE;
   950 
   952 
   951 		this->eng_list.clear();
   953 		this->eng_list.Clear();
   952 
   954 
   953 		const Engine *e;
   955 		const Engine *e;
   954 		FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
   956 		FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
   955 			EngineID eid = e->index;
   957 			EngineID eid = e->index;
   956 			if (!IsEngineBuildable(eid, VEH_ROAD, _local_player)) continue;
   958 			if (!IsEngineBuildable(eid, VEH_ROAD, _local_player)) continue;
   957 			if (!HasBit(this->filter.roadtypes, HasBit(EngInfo(eid)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD)) continue;
   959 			if (!HasBit(this->filter.roadtypes, HasBit(EngInfo(eid)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD)) continue;
   958 			this->eng_list.push_back(eid);
   960 			*this->eng_list.Append() = eid;
   959 
   961 
   960 			if (eid == this->sel_engine) sel_id = eid;
   962 			if (eid == this->sel_engine) sel_id = eid;
   961 		}
   963 		}
   962 		this->sel_engine = sel_id;
   964 		this->sel_engine = sel_id;
   963 	}
   965 	}
   964 
   966 
   965 	/* Figure out what ship EngineIDs to put in the list */
   967 	/* Figure out what ship EngineIDs to put in the list */
   966 	void GenerateBuildShipList()
   968 	void GenerateBuildShipList()
   967 	{
   969 	{
   968 		EngineID sel_id = INVALID_ENGINE;
   970 		EngineID sel_id = INVALID_ENGINE;
   969 		this->eng_list.clear();
   971 		this->eng_list.Clear();
   970 
   972 
   971 		const Engine *e;
   973 		const Engine *e;
   972 		FOR_ALL_ENGINES_OF_TYPE(e, VEH_SHIP) {
   974 		FOR_ALL_ENGINES_OF_TYPE(e, VEH_SHIP) {
   973 			EngineID eid = e->index;
   975 			EngineID eid = e->index;
   974 			if (!IsEngineBuildable(eid, VEH_SHIP, _local_player)) continue;
   976 			if (!IsEngineBuildable(eid, VEH_SHIP, _local_player)) continue;
   975 			this->eng_list.push_back(eid);
   977 			*this->eng_list.Append() = eid;
   976 
   978 
   977 			if (eid == this->sel_engine) sel_id = eid;
   979 			if (eid == this->sel_engine) sel_id = eid;
   978 		}
   980 		}
   979 		this->sel_engine = sel_id;
   981 		this->sel_engine = sel_id;
   980 	}
   982 	}
   982 	/* Figure out what aircraft EngineIDs to put in the list */
   984 	/* Figure out what aircraft EngineIDs to put in the list */
   983 	void GenerateBuildAircraftList()
   985 	void GenerateBuildAircraftList()
   984 	{
   986 	{
   985 		EngineID sel_id = INVALID_ENGINE;
   987 		EngineID sel_id = INVALID_ENGINE;
   986 
   988 
   987 		this->eng_list.clear();
   989 		this->eng_list.Clear();
   988 
   990 
   989 		/* Make list of all available planes.
   991 		/* Make list of all available planes.
   990 		* Also check to see if the previously selected plane is still available,
   992 		* Also check to see if the previously selected plane is still available,
   991 		* and if not, reset selection to INVALID_ENGINE. This could be the case
   993 		* and if not, reset selection to INVALID_ENGINE. This could be the case
   992 		* when planes become obsolete and are removed */
   994 		* when planes become obsolete and are removed */
   995 			EngineID eid = e->index;
   997 			EngineID eid = e->index;
   996 			if (!IsEngineBuildable(eid, VEH_AIRCRAFT, _local_player)) continue;
   998 			if (!IsEngineBuildable(eid, VEH_AIRCRAFT, _local_player)) continue;
   997 			/* First VEH_END window_numbers are fake to allow a window open for all different types at once */
   999 			/* First VEH_END window_numbers are fake to allow a window open for all different types at once */
   998 			if (this->window_number > VEH_END && !CanAircraftUseStation(eid, this->window_number)) continue;
  1000 			if (this->window_number > VEH_END && !CanAircraftUseStation(eid, this->window_number)) continue;
   999 
  1001 
  1000 			this->eng_list.push_back(eid);
  1002 			*this->eng_list.Append() = eid;
  1001 			if (eid == this->sel_engine) sel_id = eid;
  1003 			if (eid == this->sel_engine) sel_id = eid;
  1002 		}
  1004 		}
  1003 
  1005 
  1004 		this->sel_engine = sel_id;
  1006 		this->sel_engine = sel_id;
  1005 	}
  1007 	}
  1036 				this->SetDirty();
  1038 				this->SetDirty();
  1037 				break;
  1039 				break;
  1038 
  1040 
  1039 			case BUILD_VEHICLE_WIDGET_LIST: {
  1041 			case BUILD_VEHICLE_WIDGET_LIST: {
  1040 				uint i = (pt.y - this->widget[BUILD_VEHICLE_WIDGET_LIST].top) / GetVehicleListHeight(this->vehicle_type) + this->vscroll.pos;
  1042 				uint i = (pt.y - this->widget[BUILD_VEHICLE_WIDGET_LIST].top) / GetVehicleListHeight(this->vehicle_type) + this->vscroll.pos;
  1041 				size_t num_items = this->eng_list.size();
  1043 				size_t num_items = this->eng_list.Length();
  1042 				this->sel_engine = (i < num_items) ? this->eng_list[i] : INVALID_ENGINE;
  1044 				this->sel_engine = (i < num_items) ? this->eng_list[i] : INVALID_ENGINE;
  1043 				this->SetDirty();
  1045 				this->SetDirty();
  1044 				break;
  1046 				break;
  1045 			}
  1047 			}
  1046 
  1048 
  1102 		if (this->regenerate_list) {
  1104 		if (this->regenerate_list) {
  1103 			this->regenerate_list = false;
  1105 			this->regenerate_list = false;
  1104 			this->GenerateBuildList();
  1106 			this->GenerateBuildList();
  1105 		}
  1107 		}
  1106 
  1108 
  1107 		uint max = min(this->vscroll.pos + this->vscroll.cap, this->eng_list.size());
  1109 		uint max = min(this->vscroll.pos + this->vscroll.cap, this->eng_list.Length());
  1108 
  1110 
  1109 		this->SetWidgetDisabledState(BUILD_VEHICLE_WIDGET_BUILD, this->window_number <= VEH_END);
  1111 		this->SetWidgetDisabledState(BUILD_VEHICLE_WIDGET_BUILD, this->window_number <= VEH_END);
  1110 
  1112 
  1111 		SetVScrollCount(this, this->eng_list.size());
  1113 		SetVScrollCount(this, this->eng_list.Length());
  1112 		SetDParam(0, this->filter.railtype + STR_881C_NEW_RAIL_VEHICLES); // This should only affect rail vehicles
  1114 		SetDParam(0, this->filter.railtype + STR_881C_NEW_RAIL_VEHICLES); // This should only affect rail vehicles
  1113 
  1115 
  1114 		/* Set text of sort by dropdown */
  1116 		/* Set text of sort by dropdown */
  1115 		this->widget[BUILD_VEHICLE_WIDGET_SORT_DROPDOWN].data = _sort_listing[this->vehicle_type][this->sort_criteria];
  1117 		this->widget[BUILD_VEHICLE_WIDGET_SORT_DROPDOWN].data = _sort_listing[this->vehicle_type][this->sort_criteria];
  1116 
  1118 
  1117 		this->DrawWidgets();
  1119 		this->DrawWidgets();
  1118 
  1120 
  1119 		DrawEngineList(this->vehicle_type, this->widget[BUILD_VEHICLE_WIDGET_LIST].left + 2, this->widget[BUILD_VEHICLE_WIDGET_LIST].top + 1, this->eng_list, this->vscroll.pos, max, this->sel_engine, 0, DEFAULT_GROUP);
  1121 		DrawEngineList(this->vehicle_type, this->widget[BUILD_VEHICLE_WIDGET_LIST].left + 2, this->widget[BUILD_VEHICLE_WIDGET_LIST].top + 1, &this->eng_list, this->vscroll.pos, max, this->sel_engine, 0, DEFAULT_GROUP);
  1120 
  1122 
  1121 		if (this->sel_engine != INVALID_ENGINE) {
  1123 		if (this->sel_engine != INVALID_ENGINE) {
  1122 			const Widget *wi = &this->widget[BUILD_VEHICLE_WIDGET_PANEL];
  1124 			const Widget *wi = &this->widget[BUILD_VEHICLE_WIDGET_PANEL];
  1123 			int text_end = DrawVehiclePurchaseInfo(2, wi->top + 1, wi->right - wi->left - 2, this->sel_engine);
  1125 			int text_end = DrawVehiclePurchaseInfo(2, wi->top + 1, wi->right - wi->left - 2, this->sel_engine);
  1124 
  1126