src/autoreplace_gui.cpp
branchNewGRF_ports
changeset 6719 4cc327ad39d5
parent 6585 7da94b26498a
child 6720 35756db7e577
equal deleted inserted replaced
6718:5a8b295aa345 6719:4cc327ad39d5
    12 #include "gui.h"
    12 #include "gui.h"
    13 #include "command.h"
    13 #include "command.h"
    14 #include "variables.h"
    14 #include "variables.h"
    15 #include "vehicle_gui.h"
    15 #include "vehicle_gui.h"
    16 #include "newgrf_engine.h"
    16 #include "newgrf_engine.h"
       
    17 #include "group.h"
    17 
    18 
    18 
    19 
    19 static RailType _railtype_selected_in_replace_gui;
    20 static RailType _railtype_selected_in_replace_gui;
    20 
    21 
    21 static bool _rebuild_left_list;
    22 static bool _rebuild_left_list;
    60 }
    61 }
    61 
    62 
    62 /** When an engine is made buildable or is removed from being buildable, add/remove it from the build/autoreplace lists
    63 /** When an engine is made buildable or is removed from being buildable, add/remove it from the build/autoreplace lists
    63  * @param type The type of engine
    64  * @param type The type of engine
    64  */
    65  */
    65 void AddRemoveEngineFromAutoreplaceAndBuildWindows(byte type)
    66 void AddRemoveEngineFromAutoreplaceAndBuildWindows(VehicleType type)
    66 {
    67 {
    67 	_rebuild_left_list = false; // left list is only for the vehicles the player owns and is not related to being buildable
    68 	_rebuild_left_list = false; // left list is only for the vehicles the player owns and is not related to being buildable
    68 	_rebuild_right_list = true;
    69 	_rebuild_right_list = true;
    69 	InvalidateWindowData(WC_REPLACE_VEHICLE, type); // Update the autoreplace window
    70 	InvalidateWindowData(WC_REPLACE_VEHICLE, type); // Update the autoreplace window
    70 	InvalidateWindowClassesData(WC_BUILD_VEHICLE); // The build windows needs updating as well
    71 	InvalidateWindowClassesData(WC_BUILD_VEHICLE); // The build windows needs updating as well
   148 
   149 
   149 	FOR_ALL_ENGINEIDS_OF_TYPE(e, type) {
   150 	FOR_ALL_ENGINEIDS_OF_TYPE(e, type) {
   150 		if (type == VEH_TRAIN && !GenerateReplaceRailList(e, draw_left, WP(w, replaceveh_d).wagon_btnstate)) continue; // special rules for trains
   151 		if (type == VEH_TRAIN && !GenerateReplaceRailList(e, draw_left, WP(w, replaceveh_d).wagon_btnstate)) continue; // special rules for trains
   151 
   152 
   152 		if (draw_left) {
   153 		if (draw_left) {
       
   154 			const GroupID selected_group = WP(w, replaceveh_d).sel_group;
       
   155 			const uint num_engines = IsDefaultGroupID(selected_group) ? p->num_engines[e] : GetGroup(selected_group)->num_engines[e];
       
   156 
   153 			/* Skip drawing the engines we don't have any of and haven't set for replacement */
   157 			/* Skip drawing the engines we don't have any of and haven't set for replacement */
   154 			if (p->num_engines[e] == 0 && EngineReplacementForPlayer(GetPlayer(_local_player), e) == INVALID_ENGINE) continue;
   158 			if (num_engines == 0 && EngineReplacementForPlayer(GetPlayer(_local_player), e, selected_group) == INVALID_ENGINE) continue;
   155 		} else {
   159 		} else {
   156 			/* This is for engines we can replace to and they should depend on what we selected to replace from */
   160 			/* This is for engines we can replace to and they should depend on what we selected to replace from */
   157 			if (!IsEngineBuildable(e, type, _local_player)) continue; // we need to be able to build the engine
   161 			if (!IsEngineBuildable(e, type, _local_player)) continue; // we need to be able to build the engine
   158 			if (!EnginesGotCargoInCommon(e, WP(w, replaceveh_d).sel_engine[0])) continue; // the engines needs to be able to carry the same cargo
   162 			if (!EnginesGotCargoInCommon(e, WP(w, replaceveh_d).sel_engine[0])) continue; // the engines needs to be able to carry the same cargo
       
   163 
       
   164 			/* Road vehicles can't be replaced by trams and vice-versa */
       
   165 			if (type == VEH_ROAD && HASBIT(EngInfo(WP(w, replaceveh_d).sel_engine[0])->misc_flags, EF_ROAD_TRAM) != HASBIT(EngInfo(e)->misc_flags, EF_ROAD_TRAM)) continue;
   159 			if (e == WP(w, replaceveh_d).sel_engine[0]) continue; // we can't replace an engine into itself (that would be autorenew)
   166 			if (e == WP(w, replaceveh_d).sel_engine[0]) continue; // we can't replace an engine into itself (that would be autorenew)
   160 		}
   167 		}
   161 
   168 
   162 		EngList_Add(list, e);
   169 		EngList_Add(list, e);
   163 		if (e == WP(w, replaceveh_d).sel_engine[i]) selected_engine = e; // The selected engine is still in the list
   170 		if (e == WP(w, replaceveh_d).sel_engine[i]) selected_engine = e; // The selected engine is still in the list
   200 	WP(w, replaceveh_d).update_right = false;
   207 	WP(w, replaceveh_d).update_right = false;
   201 	WP(w, replaceveh_d).init_lists   = false;
   208 	WP(w, replaceveh_d).init_lists   = false;
   202 }
   209 }
   203 
   210 
   204 
   211 
   205 void DrawEngineList(byte type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count);
   212 void DrawEngineList(VehicleType type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group);
   206 
   213 
   207 static void ReplaceVehicleWndProc(Window *w, WindowEvent *e)
   214 static void ReplaceVehicleWndProc(Window *w, WindowEvent *e)
   208 {
   215 {
   209 	/* Strings for the pulldown menu */
   216 	/* Strings for the pulldown menu */
   210 	static const StringID _vehicle_type_names[] = {
   217 	static const StringID _vehicle_type_names[] = {
   229 		case WE_PAINT: {
   236 		case WE_PAINT: {
   230 			if (WP(w, replaceveh_d).update_left || WP(w, replaceveh_d).update_right) GenerateLists(w);
   237 			if (WP(w, replaceveh_d).update_left || WP(w, replaceveh_d).update_right) GenerateLists(w);
   231 
   238 
   232 			Player *p = GetPlayer(_local_player);
   239 			Player *p = GetPlayer(_local_player);
   233 			EngineID selected_id[2];
   240 			EngineID selected_id[2];
       
   241 			const GroupID selected_group = WP(w,replaceveh_d).sel_group;
   234 
   242 
   235 			selected_id[0] = WP(w, replaceveh_d).sel_engine[0];
   243 			selected_id[0] = WP(w, replaceveh_d).sel_engine[0];
   236 			selected_id[1] = WP(w, replaceveh_d).sel_engine[1];
   244 			selected_id[1] = WP(w, replaceveh_d).sel_engine[1];
   237 
   245 
   238 			/* Disable the "Start Replacing" button if:
   246 			/* Disable the "Start Replacing" button if:
   240 			 * or The selected replacement engine has a replacement (to prevent loops)
   248 			 * or The selected replacement engine has a replacement (to prevent loops)
   241 			 * or The right list (new replacement) has the existing replacement vehicle selected */
   249 			 * or The right list (new replacement) has the existing replacement vehicle selected */
   242 			SetWindowWidgetDisabledState(w, 4,
   250 			SetWindowWidgetDisabledState(w, 4,
   243 										 selected_id[0] == INVALID_ENGINE ||
   251 										 selected_id[0] == INVALID_ENGINE ||
   244 										 selected_id[1] == INVALID_ENGINE ||
   252 										 selected_id[1] == INVALID_ENGINE ||
   245 										 EngineReplacementForPlayer(p, selected_id[1]) != INVALID_ENGINE ||
   253 										 EngineReplacementForPlayer(p, selected_id[1], selected_group) != INVALID_ENGINE ||
   246 										 EngineReplacementForPlayer(p, selected_id[0]) == selected_id[1]);
   254 										 EngineReplacementForPlayer(p, selected_id[0], selected_group) == selected_id[1]);
   247 
   255 
   248 			/* Disable the "Stop Replacing" button if:
   256 			/* Disable the "Stop Replacing" button if:
   249 			 *   The left list (existing vehicle) is empty
   257 			 *   The left list (existing vehicle) is empty
   250 			 *   or The selected vehicle has no replacement set up */
   258 			 *   or The selected vehicle has no replacement set up */
   251 			SetWindowWidgetDisabledState(w, 6,
   259 			SetWindowWidgetDisabledState(w, 6,
   252 										 selected_id[0] == INVALID_ENGINE ||
   260 										 selected_id[0] == INVALID_ENGINE ||
   253 										 !EngineHasReplacementForPlayer(p, selected_id[0]));
   261 										 !EngineHasReplacementForPlayer(p, selected_id[0], selected_group));
   254 
   262 
   255 			/* now the actual drawing of the window itself takes place */
   263 			/* now the actual drawing of the window itself takes place */
   256 			SetDParam(0, _vehicle_type_names[w->window_number]);
   264 			SetDParam(0, _vehicle_type_names[w->window_number]);
   257 
   265 
   258 			if (w->window_number == VEH_TRAIN) {
   266 			if (w->window_number == VEH_TRAIN) {
   259 				/* set on/off for renew_keep_length */
   267 				/* set on/off for renew_keep_length */
   260 				SetDParam(1, p->renew_keep_length ? STR_CONFIG_PATCHES_ON : STR_CONFIG_PATCHES_OFF);
   268 				SetDParam(1, p->renew_keep_length ? STR_CONFIG_PATCHES_ON : STR_CONFIG_PATCHES_OFF);
   261 
   269 
   262 				/* set wagon/engine button */
   270 				/* set wagon/engine button */
   263 				SetDParam(2, WP(w, replaceveh_d).wagon_btnstate ? STR_ENGINES : STR_WAGONS);
   271 				SetDParam(2, WP(w, replaceveh_d).wagon_btnstate ? STR_ENGINES : STR_WAGONS);
       
   272 
       
   273 				/* sets the colour of that art thing */
       
   274 				w->widget[13].color = _player_colors[_local_player];
       
   275 				w->widget[16].color = _player_colors[_local_player];
   264 			}
   276 			}
   265 
   277 
   266 			w->widget[13].color = _player_colors[_local_player]; // sets the colour of that art thing
       
   267 			w->widget[16].color = _player_colors[_local_player]; // sets the colour of that art thing
       
   268 
       
   269 			DrawWindowWidgets(w);
   278 			DrawWindowWidgets(w);
   270 
       
   271 
   279 
   272 			if (w->window_number == VEH_TRAIN) {
   280 			if (w->window_number == VEH_TRAIN) {
   273 				/* Draw the selected railtype in the pulldown menu */
   281 				/* Draw the selected railtype in the pulldown menu */
   274 				RailType railtype = _railtype_selected_in_replace_gui;
   282 				RailType railtype = _railtype_selected_in_replace_gui;
   275 				DrawString(157, w->widget[14].top + 1, _rail_types_list[railtype], 0x10);
   283 				DrawString(157, w->widget[14].top + 1, _rail_types_list[railtype], 0x10);
   276 			}
   284 			}
   277 
   285 
   278 			/* sets up the string for the vehicle that is being replaced to */
   286 			/* sets up the string for the vehicle that is being replaced to */
   279 			if (selected_id[0] != INVALID_ENGINE) {
   287 			if (selected_id[0] != INVALID_ENGINE) {
   280 				if (!EngineHasReplacementForPlayer(p, selected_id[0])) {
   288 				if (!EngineHasReplacementForPlayer(p, selected_id[0], selected_group)) {
   281 					SetDParam(0, STR_NOT_REPLACING);
   289 					SetDParam(0, STR_NOT_REPLACING);
   282 				} else {
   290 				} else {
   283 					SetDParam(0, GetCustomEngineName(EngineReplacementForPlayer(p, selected_id[0])));
   291 					SetDParam(0, GetCustomEngineName(EngineReplacementForPlayer(p, selected_id[0], selected_group)));
   284 				}
   292 				}
   285 			} else {
   293 			} else {
   286 				SetDParam(0, STR_NOT_REPLACING_VEHICLE_SELECTED);
   294 				SetDParam(0, STR_NOT_REPLACING_VEHICLE_SELECTED);
   287 			}
   295 			}
   288 
   296 
   294 				EngineList list = WP(w, replaceveh_d).list[i]; // which list to draw
   302 				EngineList list = WP(w, replaceveh_d).list[i]; // which list to draw
   295 				EngineID start  = i == 0 ? w->vscroll.pos : w->vscroll2.pos; // what is the offset for the start (scrolling)
   303 				EngineID start  = i == 0 ? w->vscroll.pos : w->vscroll2.pos; // what is the offset for the start (scrolling)
   296 				EngineID end    = min((i == 0 ? w->vscroll.cap : w->vscroll2.cap) + start, EngList_Count(&list));
   304 				EngineID end    = min((i == 0 ? w->vscroll.cap : w->vscroll2.cap) + start, EngList_Count(&list));
   297 
   305 
   298 				/* Do the actual drawing */
   306 				/* Do the actual drawing */
   299 				DrawEngineList(w->window_number, x, 15, list, start, end, WP(w, replaceveh_d).sel_engine[i], i == 0);
   307 				DrawEngineList((VehicleType)w->window_number, x, 15, list, start, end, WP(w, replaceveh_d).sel_engine[i], i == 0, selected_group);
   300 
   308 
   301 				/* Also draw the details if an engine is selected */
   309 				/* Also draw the details if an engine is selected */
   302 				if (WP(w, replaceveh_d).sel_engine[i] != INVALID_ENGINE) {
   310 				if (WP(w, replaceveh_d).sel_engine[i] != INVALID_ENGINE) {
   303 					const Widget *wi = &w->widget[i == 0 ? 3 : 11];
   311 					const Widget *wi = &w->widget[i == 0 ? 3 : 11];
   304 					DrawVehiclePurchaseInfo(wi->left + 2, wi->top + 1, wi->right - wi->left - 2, WP(w, replaceveh_d).sel_engine[i]);
   312 					DrawVehiclePurchaseInfo(wi->left + 2, wi->top + 1, wi->right - wi->left - 2, WP(w, replaceveh_d).sel_engine[i]);
   326 					break;
   334 					break;
   327 
   335 
   328 				case 4: { /* Start replacing */
   336 				case 4: { /* Start replacing */
   329 					EngineID veh_from = WP(w, replaceveh_d).sel_engine[0];
   337 					EngineID veh_from = WP(w, replaceveh_d).sel_engine[0];
   330 					EngineID veh_to = WP(w, replaceveh_d).sel_engine[1];
   338 					EngineID veh_to = WP(w, replaceveh_d).sel_engine[1];
   331 					DoCommandP(0, 3, veh_from + (veh_to << 16), NULL, CMD_SET_AUTOREPLACE);
   339 					DoCommandP(0, 3 + (WP(w, replaceveh_d).sel_group << 16) , veh_from + (veh_to << 16), NULL, CMD_SET_AUTOREPLACE);
   332 				} break;
   340 				} break;
   333 
   341 
   334 				case 6: { /* Stop replacing */
   342 				case 6: { /* Stop replacing */
   335 					EngineID veh_from = WP(w, replaceveh_d).sel_engine[0];
   343 					EngineID veh_from = WP(w, replaceveh_d).sel_engine[0];
   336 					DoCommandP(0, 3, veh_from + (INVALID_ENGINE << 16), NULL, CMD_SET_AUTOREPLACE);
   344 					DoCommandP(0, 3 + (WP(w, replaceveh_d).sel_group << 16), veh_from + (INVALID_ENGINE << 16), NULL, CMD_SET_AUTOREPLACE);
   337 				} break;
   345 				} break;
   338 
   346 
   339 				case 7:
   347 				case 7:
   340 				case 9: {
   348 				case 9: {
   341 					uint i = (e->we.click.pt.y - 14) / w->resize.step_height;
   349 					uint i = (e->we.click.pt.y - 14) / w->resize.step_height;
   478 	_replace_ship_aircraft_vehicle_widgets,
   486 	_replace_ship_aircraft_vehicle_widgets,
   479 	ReplaceVehicleWndProc
   487 	ReplaceVehicleWndProc
   480 };
   488 };
   481 
   489 
   482 
   490 
   483 void ShowReplaceVehicleWindow(byte vehicletype)
   491 void ShowReplaceVehicleWindow(VehicleType vehicletype)
   484 {
   492 {
   485 	Window *w;
   493 	Window *w;
   486 
   494 
   487 	DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype);
   495 	DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype);
   488 
   496 
   507 		default: return;
   515 		default: return;
   508 	}
   516 	}
   509 
   517 
   510 	w->caption_color = _local_player;
   518 	w->caption_color = _local_player;
   511 	w->vscroll2.cap = w->vscroll.cap;   // these two are always the same
   519 	w->vscroll2.cap = w->vscroll.cap;   // these two are always the same
   512 }
   520 	WP(w, replaceveh_d).sel_group = DEFAULT_GROUP;
       
   521  }
       
   522 
       
   523 void ShowReplaceGroupVehicleWindow(GroupID id_g, VehicleType vehicletype)
       
   524 {
       
   525 	Window *w;
       
   526 
       
   527 	DeleteWindowById(WC_REPLACE_VEHICLE, vehicletype);
       
   528 
       
   529 	switch (vehicletype) {
       
   530 		default: NOT_REACHED();
       
   531 		case VEH_TRAIN:
       
   532 			w = AllocateWindowDescFront(&_replace_rail_vehicle_desc, vehicletype);
       
   533 			w->vscroll.cap  = 8;
       
   534 			w->resize.step_height = 14;
       
   535 			WP(w, replaceveh_d).wagon_btnstate = true;
       
   536 			break;
       
   537 		case VEH_ROAD:
       
   538 			w = AllocateWindowDescFront(&_replace_road_vehicle_desc, vehicletype);
       
   539 			w->vscroll.cap  = 8;
       
   540 			w->resize.step_height = 14;
       
   541 			break;
       
   542 		case VEH_SHIP:
       
   543 		case VEH_AIRCRAFT:
       
   544 			w = AllocateWindowDescFront(&_replace_ship_aircraft_vehicle_desc, vehicletype);
       
   545 			w->vscroll.cap  = 4;
       
   546 			w->resize.step_height = 24;
       
   547 			break;
       
   548 	}
       
   549 
       
   550 	w->caption_color = _local_player;
       
   551 	WP(w, replaceveh_d).sel_group = id_g;
       
   552 	w->vscroll2.cap = w->vscroll.cap;   // these two are always the same
       
   553 }