changeset 4635:491fa837d48b draft

(svn r6503) -Codechange: added a function to tell what vehicles a depot contains This will ensure that you can always get the same list when checking for vehicles in a depot (no need to duplicate code for each place, that needs such a list) Since the vehicles are only looped once for each redraw, drawing speed is around twice as fast (measured to be 114%-121% faster depending on the number of vehicles in the game)
author bjarni <bjarni@openttd.org>
date Sun, 24 Sep 2006 15:01:02 +0000
parents b63a1005649b
children b998124415b0
files aircraft_gui.c roadveh_gui.c ship_gui.c train_gui.c vehicle.c vehicle.h window.h
diffstat 7 files changed, 259 insertions(+), 196 deletions(-) [+]
line wrap: on
line diff
--- a/aircraft_gui.c
+++ b/aircraft_gui.c
@@ -661,9 +661,10 @@
 
 static void DrawAircraftDepotWindow(Window *w)
 {
+	Vehicle **vl = WP(w, traindepot_d).vehicle_list;
 	TileIndex tile = w->window_number;
-	Vehicle *v;
-	int num,x,y;
+	int x, y, max;
+	uint16 num = WP(w, traindepot_d).engine_count;
 
 
 	/* setup disabled buttons */
@@ -671,15 +672,6 @@
 		IsTileOwner(tile, _local_player) ? 0 : ((1<<4) | (1<<7) | (1<<8));
 
 	/* determine amount of items for scroller */
-	num = 0;
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_Aircraft &&
-				v->subtype <= 2 &&
-				v->vehstatus & VS_HIDDEN &&
-				v->tile == tile) {
-			num++;
-		}
-	}
 	SetVScrollCount(w, (num + w->hscroll.cap - 1) / w->hscroll.cap);
 
 	SetDParam(0, GetStationIndex(tile));
@@ -688,33 +680,29 @@
 	x = 2;
 	y = 15;
 	num = w->vscroll.pos * w->hscroll.cap;
+	max = min(WP(w, traindepot_d).engine_count, num + (w->vscroll.cap * w->hscroll.cap));
 
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_Aircraft &&
-				v->subtype <= 2 &&
-				v->vehstatus&VS_HIDDEN &&
-				v->tile == tile &&
-				--num < 0 && num >= -w->vscroll.cap * w->hscroll.cap) {
+	for (; num < max; num++) {
+		const Vehicle *v = vl[num];
 
-			DrawAircraftImage(v, x+12, y, WP(w,traindepot_d).sel);
+		DrawAircraftImage(v, x + 12, y, WP(w,traindepot_d).sel);
 
-			SetDParam(0, v->unitnumber);
-			DrawString(x, y+2, (uint16)(v->max_age-366) >= v->age ? STR_00E2 : STR_00E3, 0);
-
-			DrawSprite((v->vehstatus & VS_STOPPED) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, x, y + 12);
+		SetDParam(0, v->unitnumber);
+		DrawString(x, y + 2, (uint16)(v->max_age-366) >= v->age ? STR_00E2 : STR_00E3, 0);
 
-			if ((x+=74) == 2 + 74 * w->hscroll.cap) {
-				x = 2;
-				y += 24;
-			}
+		DrawSprite((v->vehstatus & VS_STOPPED) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, x, y + 12);
+
+		if ((x += 74) == 2 + 74 * w->hscroll.cap) {
+			x = 2;
+			y += 24;
 		}
 	}
 }
 
-static int GetVehicleFromAircraftDepotWndPt(const Window *w, int x, int y, Vehicle **veh) {
+static int GetVehicleFromAircraftDepotWndPt(const Window *w, int x, int y, Vehicle **veh)
+{
+	Vehicle **vl = WP(w, traindepot_d).vehicle_list;
 	uint xt,row,xm,ym;
-	Vehicle *v;
-	TileIndex tile;
 	int pos;
 
 	xt = x / 74;
@@ -728,23 +716,17 @@
 
 	pos = (row + w->vscroll.pos) * w->hscroll.cap + xt;
 
-	tile = w->window_number;
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_Aircraft && v->subtype <= 2 &&
-				v->vehstatus & VS_HIDDEN && v->tile == tile &&
-				--pos < 0) {
-			*veh = v;
-			if (xm >= 12) return 0;
-			if (ym <= 12) return -1; /* show window */
-			return -2; /* start stop */
-		}
-	}
-	return 1; /* outside */
+	if (WP(w, traindepot_d).engine_count <= pos) return 1; // empty block, so no vehicle is selected
+	*veh = vl[pos];
+
+	if (xm >= 12) return 0; // drag vehicle
+	if (ym <= 12) return -1; // show window
+	return -2; // start stop
 }
 
 static void AircraftDepotClickAircraft(Window *w, int x, int y)
 {
-	Vehicle *v;
+	Vehicle *v = NULL;
 	int mode = GetVehicleFromAircraftDepotWndPt(w, x, y, &v);
 
 	// share / copy orders
@@ -805,7 +787,13 @@
 static void AircraftDepotWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+	case WE_CREATE:
+		WP(w, traindepot_d).vehicle_list = NULL;
+		WP(w, traindepot_d).engine_list_length = 0;
+		break;
+
 	case WE_PAINT:
+		BuildDepotVehicleList(VEH_Aircraft, w->window_number, &WP(w, traindepot_d).vehicle_list, &WP(w, traindepot_d).engine_list_length, &WP(w, traindepot_d).engine_count, NULL, NULL, NULL);
 		DrawAircraftDepotWindow(w);
 		break;
 
@@ -858,6 +846,7 @@
 
 	case WE_DESTROY:
 		DeleteWindowById(WC_BUILD_VEHICLE, w->window_number);
+		free((void*)WP(w, traindepot_d).vehicle_list);
 		break;
 
 	case WE_DRAGDROP:
--- a/roadveh_gui.c
+++ b/roadveh_gui.c
@@ -616,9 +616,10 @@
 
 static void DrawRoadDepotWindow(Window *w)
 {
+	Vehicle **vl = WP(w, traindepot_d).vehicle_list;
 	TileIndex tile;
-	Vehicle *v;
-	int num,x,y;
+	int x, y, max;
+	uint16 num = WP(w, traindepot_d).engine_count;
 	Depot *depot;
 
 	tile = w->window_number;
@@ -628,10 +629,6 @@
 		IsTileOwner(tile, _local_player) ? 0 : ((1<<4) | (1<<7) | (1<<8));
 
 	/* determine amount of items for scroller */
-	num = 0;
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_Road && IsRoadVehInDepot(v) && v->tile == tile) num++;
-	}
 	SetVScrollCount(w, (num + w->hscroll.cap - 1) / w->hscroll.cap);
 
 	/* locate the depot struct */
@@ -644,30 +641,28 @@
 	x = 2;
 	y = 15;
 	num = w->vscroll.pos * w->hscroll.cap;
+	max = min(WP(w, traindepot_d).engine_count, num + (w->vscroll.cap * w->hscroll.cap));
 
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_Road && IsRoadVehInDepot(v) && v->tile == tile &&
-				--num < 0 && num >= -w->vscroll.cap * w->hscroll.cap) {
-			DrawRoadVehImage(v, x+24, y, WP(w,traindepot_d).sel);
+	for (; num < max; num++) {
+		const Vehicle *v = vl[num];
+		DrawRoadVehImage(v, x + 24, y, WP(w,traindepot_d).sel);
 
-			SetDParam(0, v->unitnumber);
-			DrawString(x, y+2, (uint16)(v->max_age-366) >= v->age ? STR_00E2 : STR_00E3, 0);
-
-			DrawSprite((v->vehstatus & VS_STOPPED) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, x + 16, y);
+		SetDParam(0, v->unitnumber);
+		DrawString(x, y + 2, (uint16)(v->max_age-366) >= v->age ? STR_00E2 : STR_00E3, 0);
 
-			if ((x+=56) == 2 + 56 * w->hscroll.cap) {
-				x = 2;
-				y += 14;
-			}
+		DrawSprite((v->vehstatus & VS_STOPPED) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, x + 16, y);
+
+		if ((x += 56) == 2 + 56 * w->hscroll.cap) {
+			x = 2;
+			y += 14;
 		}
 	}
 }
 
 static int GetVehicleFromRoadDepotWndPt(const Window *w, int x, int y, Vehicle **veh)
 {
+	Vehicle **vl = WP(w, traindepot_d).vehicle_list;
 	uint xt,row,xm;
-	TileIndex tile;
-	Vehicle *v;
 	int pos;
 
 	xt = x / 56;
@@ -679,18 +674,12 @@
 
 	pos = (row + w->vscroll.pos) * w->hscroll.cap + xt;
 
-	tile = w->window_number;
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_Road && IsRoadVehInDepot(v) && v->tile == tile &&
-				--pos < 0) {
-			*veh = v;
-			if (xm >= 24) return 0;
-			if (xm <= 16) return -1; /* show window */
-			return -2; /* start stop */
-		}
-	}
+	if (WP(w, traindepot_d).engine_count <= pos) return 1; // empty block, so no vehicle is selected
+	*veh = vl[pos];
 
-	return 1; /* outside */
+	if (xm >= 24) return 0; // drag vehicle
+	if (xm <= 16) return -1; // show window
+	return -2; // start stop
 }
 
 static void RoadDepotClickVeh(Window *w, int x, int y)
@@ -755,7 +744,13 @@
 static void RoadDepotWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+	case WE_CREATE:
+		WP(w, traindepot_d).vehicle_list = NULL;
+		WP(w, traindepot_d).engine_list_length = 0;
+		break;
+
 	case WE_PAINT:
+		BuildDepotVehicleList(VEH_Road, w->window_number, &WP(w, traindepot_d).vehicle_list, &WP(w, traindepot_d).engine_list_length, &WP(w, traindepot_d).engine_count, NULL, NULL, NULL);
 		DrawRoadDepotWindow(w);
 		break;
 
@@ -808,6 +803,7 @@
 
 	case WE_DESTROY:
 		DeleteWindowById(WC_BUILD_VEHICLE, w->window_number);
+		free((void*)WP(w, traindepot_d).vehicle_list);
 		break;
 
 	case WE_DRAGDROP:
--- a/ship_gui.c
+++ b/ship_gui.c
@@ -606,9 +606,10 @@
 
 static void DrawShipDepotWindow(Window *w)
 {
+	Vehicle **vl = WP(w, traindepot_d).vehicle_list;
 	TileIndex tile;
-	Vehicle *v;
-	int num,x,y;
+	int x, y, max;
+	uint16 num = WP(w, traindepot_d).engine_count;
 	Depot *depot;
 
 	tile = w->window_number;
@@ -618,10 +619,6 @@
 		IsTileOwner(tile, _local_player) ? 0 : ((1 << 4) | (1 << 7));
 
 	/* determine amount of items for scroller */
-	num = 0;
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_Ship && IsShipInDepot(v) && v->tile == tile) num++;
-	}
 	SetVScrollCount(w, (num + w->hscroll.cap - 1) / w->hscroll.cap);
 
 	/* locate the depot struct */
@@ -634,30 +631,28 @@
 	x = 2;
 	y = 15;
 	num = w->vscroll.pos * w->hscroll.cap;
+	max = min(WP(w, traindepot_d).engine_count, num + (w->vscroll.cap * w->hscroll.cap));
 
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_Ship && IsShipInDepot(v) && v->tile == tile &&
-				--num < 0 && num >= -w->vscroll.cap * w->hscroll.cap) {
-			DrawShipImage(v, x+19, y, WP(w,traindepot_d).sel);
+	for (; num < max; num++) {
+		const Vehicle *v = vl[num];
+		DrawShipImage(v, x + 19, y, WP(w,traindepot_d).sel);
 
-			SetDParam(0, v->unitnumber);
-			DrawString(x, y+2, (uint16)(v->max_age-366) >= v->age ? STR_00E2 : STR_00E3, 0);
-
-			DrawSprite((v->vehstatus & VS_STOPPED) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, x, y + 9);
+		SetDParam(0, v->unitnumber);
+		DrawString(x, y + 2, (uint16)(v->max_age-366) >= v->age ? STR_00E2 : STR_00E3, 0);
 
-			if ((x+=90) == 2 + 90 * w->hscroll.cap) {
-				x = 2;
-				y += 24;
-			}
+		DrawSprite((v->vehstatus & VS_STOPPED) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, x, y + 9);
+
+		if ((x += 90) == 2 + 90 * w->hscroll.cap) {
+			x = 2;
+			y += 24;
 		}
 	}
 }
 
 static int GetVehicleFromShipDepotWndPt(const Window *w, int x, int y, Vehicle **veh)
 {
+	Vehicle **vl = WP(w, traindepot_d).vehicle_list;
 	uint xt,row,xm,ym;
-	TileIndex tile;
-	Vehicle *v;
 	int pos;
 
 	xt = x / 90;
@@ -670,23 +665,16 @@
 
 	pos = (row + w->vscroll.pos) * w->hscroll.cap + xt;
 
-	tile = w->window_number;
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_Ship && v->vehstatus & VS_HIDDEN && v->tile == tile &&
-				--pos < 0) {
-			*veh = v;
-			if (xm >= 19) return 0;
-			if (ym <= 10) return -1; /* show window */
-			return -2; /* start stop */
-		}
-	}
-
-	return 1; /* outside */
+	if (WP(w, traindepot_d).engine_count <= pos) return 1; // empty block, so no vehicle is selected
+	*veh = vl[pos];
+	if (xm >= 19) return 0; // drag vehicle
+	if (ym <= 10) return -1; // show window
+	return -2; // start stop
 }
 
 static void ShipDepotClick(Window *w, int x, int y)
 {
-	Vehicle *v;
+	Vehicle *v = NULL;
 	int mode = GetVehicleFromShipDepotWndPt(w, x, y, &v);
 
 	// share / copy orders
@@ -746,34 +734,40 @@
 static void ShipDepotWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+	case WE_CREATE:
+		WP(w, traindepot_d).vehicle_list = NULL;
+		WP(w, traindepot_d).engine_count = 0;
+		break;
+
 	case WE_PAINT:
+		BuildDepotVehicleList(VEH_Ship, w->window_number, &WP(w, traindepot_d).vehicle_list, &WP(w, traindepot_d).engine_list_length, &WP(w, traindepot_d).engine_count, NULL, NULL, NULL);
 		DrawShipDepotWindow(w);
 		break;
 
 	case WE_CLICK:
 		switch (e->we.click.widget) {
-		case 5:
+		case 5: // List
 			ShipDepotClick(w, e->we.click.pt.x, e->we.click.pt.y);
 			break;
 
-		case 7:
+		case 7: // Build vehicle
 			ResetObjectToPlace();
 			ShowBuildShipWindow(w->window_number);
 			break;
 
-			case 8: /* clone button */
+		case 8: // Clone button
 			InvalidateWidget(w, 8);
-				TOGGLEBIT(w->click_state, 8);
+			TOGGLEBIT(w->click_state, 8);
 
-				if (HASBIT(w->click_state, 8)) {
-					_place_clicked_vehicle = NULL;
-					SetObjectToPlaceWnd(SPR_CURSOR_CLONE, VHM_RECT, w);
-				} else {
-					ResetObjectToPlace();
-				}
-					break;
+			if (HASBIT(w->click_state, 8)) {
+				_place_clicked_vehicle = NULL;
+				SetObjectToPlaceWnd(SPR_CURSOR_CLONE, VHM_RECT, w);
+			} else {
+				ResetObjectToPlace();
+			}
+			break;
 
-			case 9: ScrollMainWindowToTile(w->window_number); break;
+		case 9: ScrollMainWindowToTile(w->window_number); break;
 		}
 		break;
 
@@ -799,6 +793,7 @@
 
 	case WE_DESTROY:
 		DeleteWindowById(WC_BUILD_VEHICLE, w->window_number);
+		free((void*)WP(w, traindepot_d).vehicle_list);
 		break;
 
 	case WE_DRAGDROP:
--- a/train_gui.c
+++ b/train_gui.c
@@ -398,10 +398,11 @@
 
 static void DrawTrainDepotWindow(Window *w)
 {
+	Vehicle **vl = WP(w, traindepot_d).vehicle_list;
 	TileIndex tile;
-	Vehicle *v, *u;
-	int num,x,y,i, hnum;
+	int x, y, i, hnum, max;
 	Depot *depot;
+	uint16 num;
 
 	tile = w->window_number;
 
@@ -410,25 +411,14 @@
 		IsTileOwner(tile, _local_player) ? 0 : ((1 << 4) | (1 << 5) | (1 << 8) | (1<<9));
 
 	/* determine amount of items for scroller */
-	num = 0;
 	hnum = 8;
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_Train &&
-				(IsFrontEngine(v) || IsFreeWagon(v)) &&
-				v->tile == tile &&
-				v->u.rail.track == 0x80) {
-			num++;
-			// determine number of items in the X direction.
-			if (IsFrontEngine(v)) {
-				hnum = max(hnum, v->u.rail.cached_total_length);
-			}
-		}
+	for (num = 0; num < WP(w, traindepot_d).engine_count; num++) {
+		const Vehicle *v = vl[num];
+		hnum = maxu(hnum, v->u.rail.cached_total_length);
 	}
 
 	/* Always have 1 empty row, so people can change the setting of the train */
-	num++;
-
-	SetVScrollCount(w, num);
+	SetVScrollCount(w, WP(w, traindepot_d).engine_count + WP(w, traindepot_d).wagon_count + 1);
 	SetHScrollCount(w, WagonLengthToPixels(hnum));
 
 	/* locate the depot struct */
@@ -441,44 +431,45 @@
 	x = 2;
 	y = 15;
 	num = w->vscroll.pos;
+	max = min(WP(w, traindepot_d).engine_count, w->vscroll.pos + w->vscroll.cap);
 
-	// draw all trains
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_Train && IsFrontEngine(v) &&
-				v->tile == tile && v->u.rail.track == 0x80 &&
-				--num < 0 && num >= -w->vscroll.cap) {
-			DrawTrainImage(v, x+21, y, w->hscroll.cap + 4, w->hscroll.pos, WP(w,traindepot_d).sel);
-			/* Draw the train number */
-			SetDParam(0, v->unitnumber);
-			DrawString(x, y, (v->max_age - 366 < v->age) ? STR_00E3 : STR_00E2, 0);
+
+	/* draw all trains */
+	for (; num < max; num++) {
+		const Vehicle *v = vl[num];
 
-			// Number of wagons relative to a standard length wagon (rounded up)
-			SetDParam(0, (v->u.rail.cached_total_length + 7) / 8);
-			DrawStringRightAligned(w->widget[6].right - 1, y + 4, STR_TINY_BLACK, 0); // Draw the counter
+		DrawTrainImage(v, x + 21, y, w->hscroll.cap + 4, w->hscroll.pos, WP(w,traindepot_d).sel);
+		/* Draw the train number */
+		SetDParam(0, v->unitnumber);
+		DrawString(x, y, (v->max_age - 366 < v->age) ? STR_00E3 : STR_00E2, 0);
 
-			/* Draw the pretty flag */
-			DrawSprite(v->vehstatus & VS_STOPPED ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, x + 15, y);
+		/* Number of wagons relative to a standard length wagon (rounded up) */
+		SetDParam(0, (v->u.rail.cached_total_length + 7) / 8);
+		DrawStringRightAligned(w->widget[6].right - 1, y + 4, STR_TINY_BLACK, 0); // Draw the counter
 
-			y += 14;
-		}
+		/* Draw the pretty flag */
+		DrawSprite(v->vehstatus & VS_STOPPED ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, x + 15, y);
+
+		y += 14;
 	}
 
-	// draw all remaining vehicles
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_Train && IsFreeWagon(v) &&
-				v->tile == tile && v->u.rail.track == 0x80 &&
-				--num < 0 && num >= -w->vscroll.cap) {
-			DrawTrainImage(v, x+50, y, w->hscroll.cap - 29, 0, WP(w,traindepot_d).sel);
-			DrawString(x, y+2, STR_8816, 0);
+	max = min(WP(w, traindepot_d).engine_count + WP(w, traindepot_d).wagon_count, w->vscroll.pos + w->vscroll.cap);
+
+	/* draw all remaining vehicles */
+	for (; num < max; num++) {
+		const Vehicle *v = WP(w, traindepot_d).wagon_list[num - WP(w, traindepot_d).engine_count];
+		const Vehicle *u;
 
-			/*Draw the train counter */
-			i = 0;
-			u = v;
-			do i++; while ( (u=u->next) != NULL); // Determine length of train
-			SetDParam(0, i);                      // Set the counter
-			DrawStringRightAligned(w->widget[6].right - 1, y + 4, STR_TINY_BLACK, 0); // Draw the counter
-			y += 14;
-		}
+		DrawTrainImage(v, x + 50, y, w->hscroll.cap - 29, 0, WP(w,traindepot_d).sel);
+		DrawString(x, y + 2, STR_8816, 0);
+
+		/*Draw the train counter */
+		i = 0;
+		u = v;
+		do i++; while ( (u=u->next) != NULL); // Determine length of train
+		SetDParam(0, i);                      // Set the counter
+		DrawStringRightAligned(w->widget[6].right - 1, y + 4, STR_TINY_BLACK, 0); // Draw the counter
+		y += 14;
 	}
 }
 
@@ -489,6 +480,7 @@
 
 static int GetVehicleFromTrainDepotWndPt(const Window *w, int x, int y, GetDepotVehiclePtData *d)
 {
+	Vehicle **vl = WP(w, traindepot_d).vehicle_list;
 	int row;
 	int skip = 0;
 	Vehicle *v;
@@ -500,38 +492,23 @@
 
 	row += w->vscroll.pos;
 
-	/* go through all the locomotives */
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_Train &&
-				IsFrontEngine(v) &&
-				v->tile == w->window_number &&
-				v->u.rail.track == 0x80 &&
-				--row < 0) {
-			skip = w->hscroll.pos;
-			goto found_it;
-		}
+	if (WP(w, traindepot_d).engine_count + WP(w, traindepot_d).wagon_count <= row) {
+		/* empty row, so no vehicle is selected */
+		d->head = NULL;
+		d->wagon = NULL;
+		return 0;
 	}
 
-	x -= _traininfo_vehicle_width; /* free wagons don't have an initial loco. */
-
-	/* and then the list of free wagons */
-	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_Train &&
-				IsFreeWagon(v) &&
-				v->tile == w->window_number &&
-				v->u.rail.track == 0x80 &&
-				--row < 0) {
-			goto found_it;
-		}
+	if (WP(w, traindepot_d).engine_count > row) {
+		v = vl[row];
+		skip = w->hscroll.pos;
+	} else {
+		vl = WP(w, traindepot_d).wagon_list;
+		v = vl[row - WP(w, traindepot_d).engine_count];
+		/* free wagons don't have an initial loco. */
+		x -= _traininfo_vehicle_width;
 	}
 
-	d->head = NULL;
-	d->wagon = NULL;
-
-	/* didn't find anything, get out */
-	return 0;
-
-found_it:
 	d->head = d->wagon = v;
 
 	/* either pressed the flag or the number, but only when it's a loco */
@@ -648,7 +625,16 @@
 static void TrainDepotWndProc(Window *w, WindowEvent *e)
 {
 	switch (e->event) {
+	case WE_CREATE:
+		WP(w, traindepot_d).vehicle_list = NULL;
+		WP(w, traindepot_d).wagon_list = NULL;
+		WP(w, traindepot_d).engine_count = 0;
+		WP(w, traindepot_d).wagon_count = 0;
+		break;
+
 	case WE_PAINT:
+		BuildDepotVehicleList(VEH_Train, w->window_number, &WP(w, traindepot_d).vehicle_list, &WP(w, traindepot_d).engine_list_length, &WP(w, traindepot_d).engine_count,
+															&WP(w, traindepot_d).wagon_list, &WP(w, traindepot_d).wagon_list_length, &WP(w, traindepot_d).wagon_count);
 		DrawTrainDepotWindow(w);
 		break;
 
@@ -702,6 +688,8 @@
 
 	case WE_DESTROY:
 		DeleteWindowById(WC_BUILD_VEHICLE, w->window_number);
+		free((void*)WP(w, traindepot_d).vehicle_list);
+		free((void*)WP(w, traindepot_d).wagon_list);
 		break;
 
 	case WE_DRAGDROP: {
--- a/vehicle.c
+++ b/vehicle.c
@@ -1982,6 +1982,94 @@
 	_current_player = OWNER_NONE;
 }
 
+/* Extend the list size for BuildDepotVehicleList() */
+static inline void ExtendDepotListSize(Vehicle ***engine_list, uint16 *engine_list_length)
+{
+	*engine_list_length += 25; // which number is best here?
+	*engine_list = realloc(*engine_list, (*engine_list_length) * sizeof((*engine_list)[0]));
+}
+
+/** Generates a list of vehicles inside a depot
+ * Will enlarge allocated space for the list if they are too small, so it's ok to call with (pointer to NULL array, pointer to uninitised uint16, pointer to 0)
+ * If one of the lists is not needed (say wagons when finding ships), all the pointers regarding that list should be set to NULL
+ * @param Type type of vehicle
+ * @param tile The tile the depot is located in
+ * @param ***engine_list Pointer to a pointer to an array of vehicles in the depot (old list is freed and a new one is malloced)
+ * @param *engine_list_length Allocated size of engine_list. Needs to be set to 0 when engine_list points to a NULL array
+ * @param *engine_count The number of engines stored in the list
+ * @param ***wagon_list Pointer to a pointer to an array of free wagons in the depot (old list is freed and a new one is malloced)
+ * @param *wagon_list_length Allocated size of wagon_list. Needs to be set to 0 when wagon_list points to a NULL array
+ * @param *wagon_count The number of engines stored in the list
+ */
+void BuildDepotVehicleList(byte type, TileIndex tile, Vehicle ***engine_list, uint16 *engine_list_length, uint16 *engine_count, Vehicle ***wagon_list, uint16 *wagon_list_length, uint16 *wagon_count)
+{
+	Vehicle *v;
+
+	/* This function should never be called without an array to store results */
+	assert(!(engine_list == NULL && type != VEH_Train));
+	assert(!(type == VEH_Train && engine_list == NULL && wagon_list == NULL));
+
+	/* Both array and the length should either be NULL to disable the list or both should not be NULL */
+	assert((engine_list == NULL && engine_list_length == NULL) || (engine_list != NULL && engine_list_length != NULL));
+	assert((wagon_list == NULL && wagon_list_length == NULL) || (wagon_list != NULL && wagon_list_length != NULL));
+
+	assert(!(engine_list != NULL && engine_count == NULL));
+	assert(!(wagon_list != NULL && wagon_count == NULL));
+
+	if (engine_count != NULL) *engine_count = 0;
+	if (wagon_count != NULL) *wagon_count = 0;
+
+	switch (type) {
+		case VEH_Train:
+			FOR_ALL_VEHICLES(v) {
+				if (v->tile == tile && v->type == VEH_Train && v->u.rail.track == 0x80) {
+					if (IsFrontEngine(v)) {
+						if (engine_list == NULL) continue;
+						if (*engine_count == *engine_list_length) ExtendDepotListSize(engine_list, engine_list_length);
+						(*engine_list)[(*engine_count)++] = v;
+					} else if (IsFreeWagon(v)) {
+						if (wagon_list == NULL) continue;
+						if (*wagon_count == *wagon_list_length) ExtendDepotListSize(wagon_list, wagon_list_length);
+						(*wagon_list)[(*wagon_count)++] = v;
+					}
+				}
+			}
+			break;
+
+		case VEH_Road:
+			FOR_ALL_VEHICLES(v) {
+				if (v->tile == tile && v->type == VEH_Road && IsRoadVehInDepot(v)) {
+					if (*engine_count == *engine_list_length) ExtendDepotListSize(engine_list, engine_list_length);
+					(*engine_list)[(*engine_count)++] = v;
+				}
+			}
+			break;
+
+		case VEH_Ship:
+			FOR_ALL_VEHICLES(v) {
+				if (v->tile == tile && v->type == VEH_Ship && IsShipInDepot(v)) {
+					if (*engine_count == *engine_list_length) ExtendDepotListSize(engine_list, engine_list_length);
+					(*engine_list)[(*engine_count)++] = v;
+				}
+			}
+			break;
+
+		case VEH_Aircraft:
+			FOR_ALL_VEHICLES(v) {
+				if (v->tile == tile &&
+						v->type == VEH_Aircraft &&
+						v->subtype <= 2 &&
+						v->vehstatus & VS_HIDDEN) {
+					if (*engine_count == *engine_list_length) ExtendDepotListSize(engine_list, engine_list_length);
+					(*engine_list)[(*engine_count)++] = v;
+				}
+			}
+			break;
+
+		default: NOT_REACHED();
+	}
+}
+
 /**
 * @param sort_list list to store the list in. Note: it's presumed that it is big enough to store all vehicles in the game (worst case) and it will not check size
 * @param type type of vehicle
@@ -1991,7 +2079,7 @@
 * @param window_type tells what kind of window the list is for. Use the VLW flags in vehicle_gui.h
 * @return the number of vehicles added to the list
 */
-uint GenerateVehicleSortList(const Vehicle** sort_list, byte type, PlayerID owner, StationID station, OrderID order, uint16 window_type)
+uint GenerateVehicleSortList(const Vehicle **sort_list, byte type, PlayerID owner, StationID station, OrderID order, uint16 window_type)
 {
 	const uint subtype = (type != VEH_Aircraft) ? Train_Front : 2;
 	uint n = 0;
@@ -2058,7 +2146,7 @@
  */
 int32 SendAllVehiclesToDepot(byte type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id)
 {
-	const Vehicle** sort_list;
+	const Vehicle **sort_list;
 	uint n, i;
 
 	sort_list = malloc(GetVehicleArraySize() * sizeof(sort_list[0]));
--- a/vehicle.h
+++ b/vehicle.h
@@ -317,6 +317,7 @@
 bool VehicleNeedsService(const Vehicle *v);
 
 uint GenerateVehicleSortList(const Vehicle** sort_list, byte type, PlayerID owner, StationID station, OrderID order, uint16 window_type);
+void BuildDepotVehicleList(byte type, TileIndex tile, Vehicle ***engine_list, uint16 *engine_list_length, uint16 *engine_count, Vehicle ***wagon_list, uint16 *wagon_list_length, uint16 *wagon_count);
 int32 SendAllVehiclesToDepot(byte type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id);
 
 /* Flags to add to p2 for goto depot commands */
--- a/window.h
+++ b/window.h
@@ -394,6 +394,12 @@
 
 typedef struct {
 	VehicleID sel;
+	uint16 engine_list_length;
+	uint16 wagon_list_length;
+	uint16 engine_count;
+	uint16 wagon_count;
+	Vehicle **vehicle_list;
+	Vehicle **wagon_list;
 } traindepot_d;
 assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(traindepot_d));