From b0101164e403947b3c676df45921413a69685df3 Mon Sep 17 00:00:00 2001 From: bjarni Date: Sun, 24 Sep 2006 15:01:02 +0000 Subject: (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) --- aircraft_gui.c | 71 ++++++++++++----------------- roadveh_gui.c | 56 +++++++++++------------ ship_gui.c | 83 ++++++++++++++++----------------- train_gui.c | 142 ++++++++++++++++++++++++++------------------------------- vehicle.c | 92 ++++++++++++++++++++++++++++++++++++- vehicle.h | 1 + window.h | 6 +++ 7 files changed, 257 insertions(+), 194 deletions(-) diff --git a/aircraft_gui.c b/aircraft_gui.c index 53487d609..b447be624 100644 --- a/aircraft_gui.c +++ b/aircraft_gui.c @@ -661,9 +661,10 @@ void ShowAircraftViewWindow(const Vehicle *v) 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 @@ static void DrawAircraftDepotWindow(Window *w) 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 @@ static void DrawAircraftDepotWindow(Window *w) 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); + 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); + 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; - } + 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 @@ static int GetVehicleFromAircraftDepotWndPt(const Window *w, int x, int y, Vehic 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 ClonePlaceObj(const Window *w) 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 @@ static void AircraftDepotWndProc(Window *w, WindowEvent *e) case WE_DESTROY: DeleteWindowById(WC_BUILD_VEHICLE, w->window_number); + free((void*)WP(w, traindepot_d).vehicle_list); break; case WE_DRAGDROP: diff --git a/roadveh_gui.c b/roadveh_gui.c index 4e0c649e7..e43710846 100644 --- a/roadveh_gui.c +++ b/roadveh_gui.c @@ -616,9 +616,10 @@ void ShowBuildRoadVehWindow(TileIndex tile) 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 @@ static void DrawRoadDepotWindow(Window *w) 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 @@ static void DrawRoadDepotWindow(Window *w) 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); + 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); + 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; - } + 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 @@ static int GetVehicleFromRoadDepotWndPt(const Window *w, int x, int y, Vehicle * 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 ClonePlaceObj(const Window *w) 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 @@ static void RoadDepotWndProc(Window *w, WindowEvent *e) case WE_DESTROY: DeleteWindowById(WC_BUILD_VEHICLE, w->window_number); + free((void*)WP(w, traindepot_d).vehicle_list); break; case WE_DRAGDROP: diff --git a/ship_gui.c b/ship_gui.c index 3853200dd..6a1fcda09 100644 --- a/ship_gui.c +++ b/ship_gui.c @@ -606,9 +606,10 @@ void ShowShipViewWindow(const Vehicle *v) 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 @@ static void DrawShipDepotWindow(Window *w) 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 @@ static void DrawShipDepotWindow(Window *w) 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); + 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); + 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; - } + 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 @@ static int GetVehicleFromShipDepotWndPt(const Window *w, int x, int y, Vehicle * 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 ClonePlaceObj(const Window *w) 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 @@ static void ShipDepotWndProc(Window *w, WindowEvent *e) case WE_DESTROY: DeleteWindowById(WC_BUILD_VEHICLE, w->window_number); + free((void*)WP(w, traindepot_d).vehicle_list); break; case WE_DRAGDROP: diff --git a/train_gui.c b/train_gui.c index 8d8d1b67b..c097857d2 100644 --- a/train_gui.c +++ b/train_gui.c @@ -398,10 +398,11 @@ void DrawTrainImage(const Vehicle *v, int x, int y, int count, int skip, Vehicle 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 @@ static void DrawTrainDepotWindow(Window *w) 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 @@ static void DrawTrainDepotWindow(Window *w) 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); - // 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 + /* draw all trains */ + for (; num < max; num++) { + const Vehicle *v = vl[num]; - /* Draw the pretty flag */ - DrawSprite(v->vehstatus & VS_STOPPED ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, x + 15, y); + 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); - y += 14; - } + /* 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 + + /* 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); - - /*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; - } + 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; + + 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 @@ typedef struct GetDepotVehiclePtData { 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 @@ static int GetVehicleFromTrainDepotWndPt(const Window *w, int x, int y, GetDepot 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 ClonePlaceObj(const Window *w) 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 @@ static void TrainDepotWndProc(Window *w, WindowEvent *e) 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: { diff --git a/vehicle.c b/vehicle.c index 8633a6cea..749bead26 100644 --- a/vehicle.c +++ b/vehicle.c @@ -1982,6 +1982,94 @@ static void MaybeReplaceVehicle(Vehicle *v) _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 @@ static void MaybeReplaceVehicle(Vehicle *v) * @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 @@ uint GenerateVehicleSortList(const Vehicle** sort_list, byte type, PlayerID owne */ 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])); diff --git a/vehicle.h b/vehicle.h index 2efd39b04..67961c468 100644 --- a/vehicle.h +++ b/vehicle.h @@ -317,6 +317,7 @@ int CheckTrainStoppedInDepot(const Vehicle *v); 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 */ diff --git a/window.h b/window.h index 5bb36158d..0ac18b70a 100644 --- a/window.h +++ b/window.h @@ -394,6 +394,12 @@ assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(replaceveh_d)); 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)); -- cgit v1.2.3-70-g09d2