train_gui.c
changeset 4765 d109bfb2cc73
parent 4764 79341214c15d
child 4766 aa276d0ec2eb
equal deleted inserted replaced
4764:79341214c15d 4765:d109bfb2cc73
    27 	BUILD_TRAIN_WIDGET_CLOSEBOX = 0,
    27 	BUILD_TRAIN_WIDGET_CLOSEBOX = 0,
    28 	BUILD_TRAIN_WIDGET_CAPTION,
    28 	BUILD_TRAIN_WIDGET_CAPTION,
    29 	BUILD_TRAIN_WIDGET_LIST,
    29 	BUILD_TRAIN_WIDGET_LIST,
    30 	BUILD_TRAIN_WIDGET_SCROLLBAR,
    30 	BUILD_TRAIN_WIDGET_SCROLLBAR,
    31 	BUILD_TRAIN_WIDGET_PANEL,
    31 	BUILD_TRAIN_WIDGET_PANEL,
       
    32 	BUILD_TRAIN_WIDGET_ENGINES,
       
    33 	BUILD_TRAIN_WIDGET_WAGONS,
       
    34 	BUILD_TRAIN_WIDGET_BOTH,
    32 	BUILD_TRAIN_WIDGET_BUILD,
    35 	BUILD_TRAIN_WIDGET_BUILD,
    33 	BUILD_TRAIN_WIDGET_RENAME,
    36 	BUILD_TRAIN_WIDGET_RENAME,
    34 	BUILD_TRAIN_WIDGET_RESIZE,
    37 	BUILD_TRAIN_WIDGET_RESIZE,
    35 } BuildTrainWidget;
    38 } BuildTrainWidget;
       
    39 
       
    40 static const Widget _new_rail_vehicle_widgets[] = {
       
    41 	{   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,               STR_018B_CLOSE_WINDOW},
       
    42 	{    WWT_CAPTION,   RESIZE_NONE,    14,    11,   227,     0,    13, STR_JUST_STRING,        STR_018C_WINDOW_TITLE_DRAG_THIS},
       
    43 	{     WWT_MATRIX, RESIZE_BOTTOM,    14,     0,   215,    14,   125, 0x801,                  STR_8843_TRAIN_VEHICLE_SELECTION},
       
    44 	{  WWT_SCROLLBAR, RESIZE_BOTTOM,    14,   216,   227,    14,   125, 0x0,                    STR_0190_SCROLL_BAR_SCROLLS_LIST},
       
    45 	{      WWT_PANEL,     RESIZE_TB,    14,     0,   227,   126,   197, 0x0,                    STR_NULL},
       
    46 	{ WWT_PUSHTXTBTN,     RESIZE_TB,    14,     0,    76,   198,   209, STR_BLACK_ENGINES,      STR_BUILD_TRAIN_ENGINES_TIP},
       
    47 	{ WWT_PUSHTXTBTN,     RESIZE_TB,    14,    77,   151,   198,   209, STR_BLACK_WAGONS,       STR_BUILD_TRAIN_WAGONS_TIP},
       
    48 	{ WWT_PUSHTXTBTN,     RESIZE_TB,    14,   152,   227,   198,   209, STR_BLACK_BOTH,         STR_BUILD_TRAIN_BOTH_TIP},
       
    49 	{ WWT_PUSHTXTBTN,     RESIZE_TB,    14,     0,   107,   210,   221, STR_881F_BUILD_VEHICLE, STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN},
       
    50 	{ WWT_PUSHTXTBTN,     RESIZE_TB,    14,   108,   215,   210,   221, STR_8820_RENAME,        STR_8845_RENAME_TRAIN_VEHICLE_TYPE},
       
    51 	{  WWT_RESIZEBOX,     RESIZE_TB,    14,   216,   227,   210,   221, 0x0,                    STR_RESIZE_BUTTON},
       
    52 	{   WIDGETS_END},
       
    53 };
    36 
    54 
    37 
    55 
    38 /**
    56 /**
    39  * Draw the purchase info details of train engine at a given location.
    57  * Draw the purchase info details of train engine at a given location.
    40  * @param x,y location where to draw the info
    58  * @param x,y location where to draw the info
   185 
   203 
   186 void CcCloneTrain(bool success, TileIndex tile, uint32 p1, uint32 p2)
   204 void CcCloneTrain(bool success, TileIndex tile, uint32 p1, uint32 p2)
   187 {
   205 {
   188 	if (success) ShowTrainViewWindow(GetVehicle(_new_vehicle_id));
   206 	if (success) ShowTrainViewWindow(GetVehicle(_new_vehicle_id));
   189 }
   207 }
   190 
   208 static void engine_drawing_loop(const EngineID *engines, const uint16 engine_count,
   191 static void engine_drawing_loop(int *x, int *y, int *pos, int *sel,
   209 								const int x, int *y, const EngineID sel, EngineID *position, const int16 show_max)
   192 	EngineID *selected_id, RailType railtype, byte show_max, bool is_engine)
   210 {
   193 {
   211 	for (; (*position) < min(engine_count, show_max); (*position)++) {
       
   212 		EngineID i = engines[*position];
       
   213 
       
   214 		DrawString(x + 59, *y + 2, GetCustomEngineName(i), sel == i ? 0xC : 0x10);
       
   215 		DrawTrainEngine(x + 29, *y + 6, i, GetEnginePalette(i, _local_player));
       
   216 		*y += 14;
       
   217 	}
       
   218 }
       
   219 
       
   220 static inline void ExtendEngineListSize(const EngineID **engine_list, uint16 *engine_list_length, uint16 step_size)
       
   221 {
       
   222 	*engine_list_length = min(*engine_list_length + step_size, NUM_TRAIN_ENGINES);
       
   223 	*engine_list = realloc((void*)*engine_list, (*engine_list_length) * sizeof((*engine_list)[0]));
       
   224 }
       
   225 
       
   226 static void GenerateBuildList(EngineID **engines, uint16 *num_engines, EngineID **wagons, uint16 *num_wagons, RailType railtype)
       
   227 {
       
   228 	uint16 engine_length = *num_engines;
       
   229 	uint16 wagon_length  = *num_wagons;
   194 	EngineID j;
   230 	EngineID j;
       
   231 
       
   232 	(*num_engines) = 0;
       
   233 	(*num_wagons)  = 0;
       
   234 
       
   235 	if (engines == NULL) ExtendEngineListSize((const EngineID**)engines, &engine_length, 25);
       
   236 	if (wagons  == NULL) ExtendEngineListSize((const EngineID**)wagons,  &wagon_length,  25);
   195 
   237 
   196 	for (j = 0; j < NUM_TRAIN_ENGINES; j++) {
   238 	for (j = 0; j < NUM_TRAIN_ENGINES; j++) {
   197 		EngineID i = GetRailVehAtPosition(j);
   239 		EngineID i = GetRailVehAtPosition(j);
   198 		const Engine *e = GetEngine(i);
   240 		const Engine *e = GetEngine(i);
   199 		const RailVehicleInfo *rvi = RailVehInfo(i);
   241 		const RailVehicleInfo *rvi = RailVehInfo(i);
   200 
   242 
   201 		if (!HasPowerOnRail(e->railtype, railtype) || !(rvi->flags & RVI_WAGON) != is_engine ||
   243 		if (!HasPowerOnRail(e->railtype, railtype)) continue;
   202 				!HASBIT(e->player_avail, _local_player))
   244 		if (!IsEngineBuildable(i, VEH_Train)) continue;
   203 			continue;
   245 
   204 
   246 		if (rvi->flags & RVI_WAGON) {
   205 		if (*sel == 0) *selected_id = i;
   247 			if (*num_wagons == wagon_length) ExtendEngineListSize((const EngineID**)wagons, &wagon_length, 5);
   206 
   248 			(*wagons)[(*num_wagons)++] = i;
   207 		if (IS_INT_INSIDE(--*pos, -show_max, 0)) {
   249 		} else {
   208 			DrawString(*x + 59, *y + 2, GetCustomEngineName(i), *sel == 0 ? 0xC : 0x10);
   250 			if (*num_engines == engine_length) ExtendEngineListSize((const EngineID**)engines, &engine_length, 5);
   209 			DrawTrainEngine(*x + 29, *y + 6, i, GetEnginePalette(i, _local_player));
   251 			(*engines)[(*num_engines)++] = i;
   210 			*y += 14;
   252 		}
   211 		}
   253 	}
   212 		--*sel;
   254 
       
   255 	/* Reduce array sizes if they are too big */
       
   256 	if (*num_engines == engine_length) *engines = realloc((void*)*engines, (*num_engines) * sizeof((*engines)[0]));
       
   257 	if (*num_wagons == wagon_length) *wagons = realloc((void*)*wagons, (*num_wagons) * sizeof((*wagons)[0]));
       
   258 }
       
   259 
       
   260 static void DrawTrainBuildWindow(Window *w)
       
   261 {
       
   262 	int x = 1;
       
   263 	int y = 15;
       
   264 	EngineID position = w->vscroll.pos;
       
   265 	EngineID selected_id = WP(w,buildtrain_d).sel_engine;
       
   266 	int max = w->vscroll.pos + w->vscroll.cap;
       
   267 	uint16 scrollcount = 0;
       
   268 
       
   269 	SetWindowWidgetDisabledState(w, BUILD_TRAIN_WIDGET_BUILD, w->window_number == 0); // Disable unless we got a depot to build in
       
   270 
       
   271 	/* Draw the clicked engine/wagon/both button pressed and unpress the other two */
       
   272 	SetWindowWidgetLoweredState(w, BUILD_TRAIN_WIDGET_ENGINES, WP(w,buildtrain_d).show_engine_wagon == 1);
       
   273 	SetWindowWidgetLoweredState(w, BUILD_TRAIN_WIDGET_WAGONS,  WP(w,buildtrain_d).show_engine_wagon == 2);
       
   274 	SetWindowWidgetLoweredState(w, BUILD_TRAIN_WIDGET_BOTH,    WP(w,buildtrain_d).show_engine_wagon == 3);
       
   275 
       
   276 	GenerateBuildList(&WP(w,buildtrain_d).engines, &WP(w,buildtrain_d).num_engines, &WP(w,buildtrain_d).wagons, &WP(w,buildtrain_d).num_wagons, WP(w,buildtrain_d).railtype);
       
   277 
       
   278 	if (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0)) scrollcount += WP(w,buildtrain_d).num_engines;
       
   279 	if (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 1)) scrollcount += WP(w,buildtrain_d).num_wagons;
       
   280 
       
   281 	SetVScrollCount(w, scrollcount);
       
   282 	SetDParam(0, WP(w,buildtrain_d).railtype + STR_881C_NEW_RAIL_VEHICLES);
       
   283 	DrawWindowWidgets(w);
       
   284 
       
   285 	if (selected_id == INVALID_ENGINE && scrollcount != 0) {
       
   286 		if (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0) && WP(w,buildtrain_d).num_engines != 0) {
       
   287 			selected_id = WP(w,buildtrain_d).engines[0];
       
   288 		} else {
       
   289 			selected_id = WP(w,buildtrain_d).wagons[0];
       
   290 		}
       
   291 		WP(w,buildtrain_d).sel_engine = selected_id;
       
   292 	}
       
   293 
       
   294 	/* Draw the engines */
       
   295 	if (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0)) {
       
   296 		engine_drawing_loop(WP(w,buildtrain_d).engines, WP(w,buildtrain_d).num_engines, x, &y, selected_id, &position, max);
       
   297 
       
   298 		/* Magically set the number 0 line to the one right after the last engine
       
   299 		* This way the line numbers fit the indexes in the wagon array */
       
   300 		position -= WP(w,buildtrain_d).num_engines;
       
   301 		max      -= WP(w,buildtrain_d).num_engines;
       
   302 	}
       
   303 
       
   304 	/* Draw the wagons */
       
   305 	if (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 1)) {
       
   306 		engine_drawing_loop(WP(w,buildtrain_d).wagons,  WP(w,buildtrain_d).num_wagons,  x, &y, selected_id, &position, max);
       
   307 	}
       
   308 
       
   309 	if (selected_id != INVALID_ENGINE) {
       
   310 		const RailVehicleInfo *rvi = RailVehInfo(selected_id);
       
   311 
       
   312 		if (rvi->flags & RVI_WAGON) {
       
   313 			DrawTrainWagonPurchaseInfo(2, w->widget[BUILD_TRAIN_WIDGET_PANEL].top + 1, selected_id);
       
   314 		} else {
       
   315 			DrawTrainEnginePurchaseInfo(2, w->widget[BUILD_TRAIN_WIDGET_PANEL].top + 1, selected_id);
       
   316 		}
   213 	}
   317 	}
   214 }
   318 }
   215 
   319 
   216 static void NewRailVehicleWndProc(Window *w, WindowEvent *e)
   320 static void NewRailVehicleWndProc(Window *w, WindowEvent *e)
   217 {
   321 {
   218 	switch (e->event) {
   322 	switch (e->event) {
       
   323 		case WE_CREATE:
       
   324 			WP(w,buildtrain_d).num_engines = 0;
       
   325 			WP(w,buildtrain_d).num_wagons  = 0;
       
   326 			WP(w,buildtrain_d).engines = NULL;
       
   327 			WP(w,buildtrain_d).wagons  = NULL;
       
   328 			WP(w,buildtrain_d).show_engine_wagon = 3;
       
   329 			break;
       
   330 
       
   331 		case WE_DESTROY:
       
   332 			free((void*)WP(w,buildtrain_d).engines);
       
   333 			free((void*)WP(w,buildtrain_d).wagons);
       
   334 			break;
       
   335 
   219 		case WE_PAINT:
   336 		case WE_PAINT:
   220 
   337 			DrawTrainBuildWindow(w);
   221 			SetWindowWidgetDisabledState(w, BUILD_TRAIN_WIDGET_BUILD, w->window_number == 0);
   338 			break;
   222 
   339 
   223 			{
       
   224 				int count = 0;
       
   225 				RailType railtype = WP(w,buildtrain_d).railtype;
       
   226 				EngineID i;
       
   227 
       
   228 				for (i = 0; i < NUM_TRAIN_ENGINES; i++) {
       
   229 					const Engine *e = GetEngine(i);
       
   230 					if (HasPowerOnRail(e->railtype, railtype) &&
       
   231 							HASBIT(e->player_avail, _local_player)) {
       
   232 						count++;
       
   233 					}
       
   234 				}
       
   235 				SetVScrollCount(w, count);
       
   236 			}
       
   237 
       
   238 			SetDParam(0, WP(w,buildtrain_d).railtype + STR_881C_NEW_RAIL_VEHICLES);
       
   239 			DrawWindowWidgets(w);
       
   240 
       
   241 			{
       
   242 				RailType railtype = WP(w,buildtrain_d).railtype;
       
   243 				int sel = WP(w,buildtrain_d).sel_index;
       
   244 				int pos = w->vscroll.pos;
       
   245 				int x = 1;
       
   246 				int y = 15;
       
   247 				EngineID selected_id = INVALID_ENGINE;
       
   248 
       
   249 				/* Ensure that custom engines which substituted wagons
       
   250 				 * are sorted correctly.
       
   251 				 * XXX - DO NOT EVER DO THIS EVER AGAIN! GRRR hacking in wagons as
       
   252 				 * engines to get more types.. Stays here until we have our own format
       
   253 				 * then it is exit!!! */
       
   254 				engine_drawing_loop(&x, &y, &pos, &sel, &selected_id, railtype, w->vscroll.cap, true); // True engines
       
   255 				engine_drawing_loop(&x, &y, &pos, &sel, &selected_id, railtype, w->vscroll.cap, false); // Feeble wagons
       
   256 
       
   257 				WP(w,buildtrain_d).sel_engine = selected_id;
       
   258 
       
   259 				if (selected_id != INVALID_ENGINE) {
       
   260 					const RailVehicleInfo *rvi = RailVehInfo(selected_id);
       
   261 
       
   262 					if (!(rvi->flags & RVI_WAGON)) {
       
   263 						/* it's an engine */
       
   264 						DrawTrainEnginePurchaseInfo(2, w->widget[BUILD_TRAIN_WIDGET_PANEL].top + 1,selected_id);
       
   265 					} else {
       
   266 						/* it's a wagon */
       
   267 						DrawTrainWagonPurchaseInfo(2, w->widget[BUILD_TRAIN_WIDGET_PANEL].top + 1, selected_id);
       
   268 					}
       
   269 				}
       
   270 			}
       
   271 		break;
       
   272 
   340 
   273 		case WE_CLICK: {
   341 		case WE_CLICK: {
   274 			switch (e->we.click.widget) {
   342 			switch (e->we.click.widget) {
   275 				case BUILD_TRAIN_WIDGET_LIST: {
   343 				case BUILD_TRAIN_WIDGET_LIST: {
   276 					uint i = (e->we.click.pt.y - 14) / 14;
   344 					uint i = ((e->we.click.pt.y - 14) / 14) + w->vscroll.pos;
   277 					if (i < w->vscroll.cap) {
   345 					if (i < WP(w,buildtrain_d).num_engines + WP(w,buildtrain_d).num_wagons) {
   278 						WP(w,buildtrain_d).sel_index = i + w->vscroll.pos;
   346 						if (i < WP(w,buildtrain_d).num_engines && HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0)) {
       
   347 							WP(w,buildtrain_d).sel_engine = WP(w,buildtrain_d).engines[i];
       
   348 						} else {
       
   349 							WP(w,buildtrain_d).sel_engine = WP(w,buildtrain_d).wagons[i - (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0) ? WP(w,buildtrain_d).num_engines : 0)];
       
   350 						}
   279 						SetWindowDirty(w);
   351 						SetWindowDirty(w);
   280 					}
   352 					}
   281 				} break;
   353 				} break;
       
   354 
       
   355 				case BUILD_TRAIN_WIDGET_ENGINES:
       
   356 				case BUILD_TRAIN_WIDGET_WAGONS:
       
   357 				case BUILD_TRAIN_WIDGET_BOTH: {
       
   358 					/* First we need to figure out the new show_engine_wagon setting
       
   359 					 * Because the button widgets are ordered as they are (in a row), we can calculate as following:
       
   360 					 * engines = bit 0 (1 for set), wagons bit 1 (2 for set), both (2 | 1 = 3)
       
   361 					 * Those numbers are the same as the clicked button - BUILD_TRAIN_WIDGET_ENGINES + 1 */
       
   362 
       
   363 					byte click_state = e->we.click.widget - BUILD_TRAIN_WIDGET_ENGINES + 1;
       
   364 					if (WP(w,buildtrain_d).show_engine_wagon == click_state) break; // We clicked the pressed button
       
   365 					WP(w,buildtrain_d).sel_engine = INVALID_ENGINE;
       
   366 					WP(w,buildtrain_d).show_engine_wagon = click_state;
       
   367 					w->vscroll.pos = 0;
       
   368 					SetWindowDirty(w);
       
   369 					}
       
   370 					break;
   282 
   371 
   283 				case BUILD_TRAIN_WIDGET_BUILD: {
   372 				case BUILD_TRAIN_WIDGET_BUILD: {
   284 					EngineID sel_eng = WP(w,buildtrain_d).sel_engine;
   373 					EngineID sel_eng = WP(w,buildtrain_d).sel_engine;
   285 					if (sel_eng != INVALID_ENGINE)
   374 					if (sel_eng != INVALID_ENGINE)
   286 						DoCommandP(w->window_number, sel_eng, 0, (RailVehInfo(sel_eng)->flags & RVI_WAGON) ? CcBuildWagon : CcBuildLoco, CMD_BUILD_RAIL_VEHICLE | CMD_MSG(STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE));
   375 						DoCommandP(w->window_number, sel_eng, 0, (RailVehInfo(sel_eng)->flags & RVI_WAGON) ? CcBuildWagon : CcBuildLoco, CMD_BUILD_RAIL_VEHICLE | CMD_MSG(STR_882B_CAN_T_BUILD_RAILROAD_VEHICLE));
   312 			w->widget[BUILD_TRAIN_WIDGET_LIST].data = (w->vscroll.cap << 8) + 1;
   401 			w->widget[BUILD_TRAIN_WIDGET_LIST].data = (w->vscroll.cap << 8) + 1;
   313 		} break;
   402 		} break;
   314 	}
   403 	}
   315 }
   404 }
   316 
   405 
   317 static const Widget _new_rail_vehicle_widgets[] = {
       
   318 {   WWT_CLOSEBOX,   RESIZE_NONE,    14,     0,    10,     0,    13, STR_00C5,               STR_018B_CLOSE_WINDOW},
       
   319 {    WWT_CAPTION,   RESIZE_NONE,    14,    11,   227,     0,    13, STR_JUST_STRING,        STR_018C_WINDOW_TITLE_DRAG_THIS},
       
   320 {     WWT_MATRIX, RESIZE_BOTTOM,    14,     0,   215,    14,   125, 0x801,                  STR_8843_TRAIN_VEHICLE_SELECTION},
       
   321 {  WWT_SCROLLBAR, RESIZE_BOTTOM,    14,   216,   227,    14,   125, 0x0,                    STR_0190_SCROLL_BAR_SCROLLS_LIST},
       
   322 {      WWT_PANEL,     RESIZE_TB,    14,     0,   227,   126,   197, 0x0,                    STR_NULL},
       
   323 { WWT_PUSHTXTBTN,     RESIZE_TB,    14,     0,   107,   198,   209, STR_881F_BUILD_VEHICLE, STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN},
       
   324 { WWT_PUSHTXTBTN,     RESIZE_TB,    14,   108,   215,   198,   209, STR_8820_RENAME,        STR_8845_RENAME_TRAIN_VEHICLE_TYPE},
       
   325 {  WWT_RESIZEBOX,     RESIZE_TB,    14,   216,   227,   198,   209, 0x0,                    STR_RESIZE_BUTTON},
       
   326 {   WIDGETS_END},
       
   327 };
       
   328 
       
   329 static const WindowDesc _new_rail_vehicle_desc = {
   406 static const WindowDesc _new_rail_vehicle_desc = {
   330 	-1, -1, 228, 210,
   407 	-1, -1, 228, 222,
   331 	WC_BUILD_VEHICLE,0,
   408 	WC_BUILD_VEHICLE,0,
   332 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
   409 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
   333 	_new_rail_vehicle_widgets,
   410 	_new_rail_vehicle_widgets,
   334 	NewRailVehicleWndProc
   411 	NewRailVehicleWndProc
   335 };
   412 };