1
0
Fork 0

(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)
release/0.5
bjarni 2006-09-24 15:01:02 +00:00
parent 1c56a5ae0f
commit 8f4a4a81da
7 changed files with 256 additions and 193 deletions

View File

@ -661,9 +661,10 @@ void ShowAircraftViewWindow(const Vehicle *v)
static void DrawAircraftDepotWindow(Window *w) static void DrawAircraftDepotWindow(Window *w)
{ {
Vehicle **vl = WP(w, traindepot_d).vehicle_list;
TileIndex tile = w->window_number; TileIndex tile = w->window_number;
Vehicle *v; int x, y, max;
int num,x,y; uint16 num = WP(w, traindepot_d).engine_count;
/* setup disabled buttons */ /* setup disabled buttons */
@ -671,15 +672,6 @@ static void DrawAircraftDepotWindow(Window *w)
IsTileOwner(tile, _local_player) ? 0 : ((1<<4) | (1<<7) | (1<<8)); IsTileOwner(tile, _local_player) ? 0 : ((1<<4) | (1<<7) | (1<<8));
/* determine amount of items for scroller */ /* 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); SetVScrollCount(w, (num + w->hscroll.cap - 1) / w->hscroll.cap);
SetDParam(0, GetStationIndex(tile)); SetDParam(0, GetStationIndex(tile));
@ -688,33 +680,29 @@ static void DrawAircraftDepotWindow(Window *w)
x = 2; x = 2;
y = 15; y = 15;
num = w->vscroll.pos * w->hscroll.cap; 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) { for (; num < max; num++) {
if (v->type == VEH_Aircraft && const Vehicle *v = vl[num];
v->subtype <= 2 &&
v->vehstatus&VS_HIDDEN &&
v->tile == tile &&
--num < 0 && num >= -w->vscroll.cap * w->hscroll.cap) {
DrawAircraftImage(v, x+12, y, WP(w,traindepot_d).sel); DrawAircraftImage(v, x + 12, y, WP(w,traindepot_d).sel);
SetDParam(0, v->unitnumber); SetDParam(0, v->unitnumber);
DrawString(x, y+2, (uint16)(v->max_age-366) >= v->age ? STR_00E2 : STR_00E3, 0); 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) { if ((x += 74) == 2 + 74 * w->hscroll.cap) {
x = 2; x = 2;
y += 24; 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; uint xt,row,xm,ym;
Vehicle *v;
TileIndex tile;
int pos; int pos;
xt = x / 74; 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; pos = (row + w->vscroll.pos) * w->hscroll.cap + xt;
tile = w->window_number; if (WP(w, traindepot_d).engine_count <= pos) return 1; // empty block, so no vehicle is selected
FOR_ALL_VEHICLES(v) { *veh = vl[pos];
if (v->type == VEH_Aircraft && v->subtype <= 2 &&
v->vehstatus & VS_HIDDEN && v->tile == tile && if (xm >= 12) return 0; // drag vehicle
--pos < 0) { if (ym <= 12) return -1; // show window
*veh = v; return -2; // start stop
if (xm >= 12) return 0;
if (ym <= 12) return -1; /* show window */
return -2; /* start stop */
}
}
return 1; /* outside */
} }
static void AircraftDepotClickAircraft(Window *w, int x, int y) static void AircraftDepotClickAircraft(Window *w, int x, int y)
{ {
Vehicle *v; Vehicle *v = NULL;
int mode = GetVehicleFromAircraftDepotWndPt(w, x, y, &v); int mode = GetVehicleFromAircraftDepotWndPt(w, x, y, &v);
// share / copy orders // share / copy orders
@ -805,7 +787,13 @@ static void ClonePlaceObj(const Window *w)
static void AircraftDepotWndProc(Window *w, WindowEvent *e) static void AircraftDepotWndProc(Window *w, WindowEvent *e)
{ {
switch (e->event) { 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: 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); DrawAircraftDepotWindow(w);
break; break;
@ -858,6 +846,7 @@ static void AircraftDepotWndProc(Window *w, WindowEvent *e)
case WE_DESTROY: case WE_DESTROY:
DeleteWindowById(WC_BUILD_VEHICLE, w->window_number); DeleteWindowById(WC_BUILD_VEHICLE, w->window_number);
free((void*)WP(w, traindepot_d).vehicle_list);
break; break;
case WE_DRAGDROP: case WE_DRAGDROP:

View File

@ -616,9 +616,10 @@ void ShowBuildRoadVehWindow(TileIndex tile)
static void DrawRoadDepotWindow(Window *w) static void DrawRoadDepotWindow(Window *w)
{ {
Vehicle **vl = WP(w, traindepot_d).vehicle_list;
TileIndex tile; TileIndex tile;
Vehicle *v; int x, y, max;
int num,x,y; uint16 num = WP(w, traindepot_d).engine_count;
Depot *depot; Depot *depot;
tile = w->window_number; tile = w->window_number;
@ -628,10 +629,6 @@ static void DrawRoadDepotWindow(Window *w)
IsTileOwner(tile, _local_player) ? 0 : ((1<<4) | (1<<7) | (1<<8)); IsTileOwner(tile, _local_player) ? 0 : ((1<<4) | (1<<7) | (1<<8));
/* determine amount of items for scroller */ /* 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); SetVScrollCount(w, (num + w->hscroll.cap - 1) / w->hscroll.cap);
/* locate the depot struct */ /* locate the depot struct */
@ -644,30 +641,28 @@ static void DrawRoadDepotWindow(Window *w)
x = 2; x = 2;
y = 15; y = 15;
num = w->vscroll.pos * w->hscroll.cap; 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) { for (; num < max; num++) {
if (v->type == VEH_Road && IsRoadVehInDepot(v) && v->tile == tile && const Vehicle *v = vl[num];
--num < 0 && num >= -w->vscroll.cap * w->hscroll.cap) { DrawRoadVehImage(v, x + 24, y, WP(w,traindepot_d).sel);
DrawRoadVehImage(v, x+24, y, WP(w,traindepot_d).sel);
SetDParam(0, v->unitnumber); SetDParam(0, v->unitnumber);
DrawString(x, y+2, (uint16)(v->max_age-366) >= v->age ? STR_00E2 : STR_00E3, 0); 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) { if ((x += 56) == 2 + 56 * w->hscroll.cap) {
x = 2; x = 2;
y += 14; y += 14;
}
} }
} }
} }
static int GetVehicleFromRoadDepotWndPt(const Window *w, int x, int y, Vehicle **veh) static int GetVehicleFromRoadDepotWndPt(const Window *w, int x, int y, Vehicle **veh)
{ {
Vehicle **vl = WP(w, traindepot_d).vehicle_list;
uint xt,row,xm; uint xt,row,xm;
TileIndex tile;
Vehicle *v;
int pos; int pos;
xt = x / 56; 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; pos = (row + w->vscroll.pos) * w->hscroll.cap + xt;
tile = w->window_number; if (WP(w, traindepot_d).engine_count <= pos) return 1; // empty block, so no vehicle is selected
FOR_ALL_VEHICLES(v) { *veh = vl[pos];
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 */
}
}
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) 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) static void RoadDepotWndProc(Window *w, WindowEvent *e)
{ {
switch (e->event) { 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: 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); DrawRoadDepotWindow(w);
break; break;
@ -808,6 +803,7 @@ static void RoadDepotWndProc(Window *w, WindowEvent *e)
case WE_DESTROY: case WE_DESTROY:
DeleteWindowById(WC_BUILD_VEHICLE, w->window_number); DeleteWindowById(WC_BUILD_VEHICLE, w->window_number);
free((void*)WP(w, traindepot_d).vehicle_list);
break; break;
case WE_DRAGDROP: case WE_DRAGDROP:

View File

@ -606,9 +606,10 @@ void ShowShipViewWindow(const Vehicle *v)
static void DrawShipDepotWindow(Window *w) static void DrawShipDepotWindow(Window *w)
{ {
Vehicle **vl = WP(w, traindepot_d).vehicle_list;
TileIndex tile; TileIndex tile;
Vehicle *v; int x, y, max;
int num,x,y; uint16 num = WP(w, traindepot_d).engine_count;
Depot *depot; Depot *depot;
tile = w->window_number; tile = w->window_number;
@ -618,10 +619,6 @@ static void DrawShipDepotWindow(Window *w)
IsTileOwner(tile, _local_player) ? 0 : ((1 << 4) | (1 << 7)); IsTileOwner(tile, _local_player) ? 0 : ((1 << 4) | (1 << 7));
/* determine amount of items for scroller */ /* 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); SetVScrollCount(w, (num + w->hscroll.cap - 1) / w->hscroll.cap);
/* locate the depot struct */ /* locate the depot struct */
@ -634,30 +631,28 @@ static void DrawShipDepotWindow(Window *w)
x = 2; x = 2;
y = 15; y = 15;
num = w->vscroll.pos * w->hscroll.cap; 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) { for (; num < max; num++) {
if (v->type == VEH_Ship && IsShipInDepot(v) && v->tile == tile && const Vehicle *v = vl[num];
--num < 0 && num >= -w->vscroll.cap * w->hscroll.cap) { DrawShipImage(v, x + 19, y, WP(w,traindepot_d).sel);
DrawShipImage(v, x+19, y, WP(w,traindepot_d).sel);
SetDParam(0, v->unitnumber); SetDParam(0, v->unitnumber);
DrawString(x, y+2, (uint16)(v->max_age-366) >= v->age ? STR_00E2 : STR_00E3, 0); 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) { if ((x += 90) == 2 + 90 * w->hscroll.cap) {
x = 2; x = 2;
y += 24; y += 24;
}
} }
} }
} }
static int GetVehicleFromShipDepotWndPt(const Window *w, int x, int y, Vehicle **veh) 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; uint xt,row,xm,ym;
TileIndex tile;
Vehicle *v;
int pos; int pos;
xt = x / 90; 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; pos = (row + w->vscroll.pos) * w->hscroll.cap + xt;
tile = w->window_number; if (WP(w, traindepot_d).engine_count <= pos) return 1; // empty block, so no vehicle is selected
FOR_ALL_VEHICLES(v) { *veh = vl[pos];
if (v->type == VEH_Ship && v->vehstatus & VS_HIDDEN && v->tile == tile && if (xm >= 19) return 0; // drag vehicle
--pos < 0) { if (ym <= 10) return -1; // show window
*veh = v; return -2; // start stop
if (xm >= 19) return 0;
if (ym <= 10) return -1; /* show window */
return -2; /* start stop */
}
}
return 1; /* outside */
} }
static void ShipDepotClick(Window *w, int x, int y) static void ShipDepotClick(Window *w, int x, int y)
{ {
Vehicle *v; Vehicle *v = NULL;
int mode = GetVehicleFromShipDepotWndPt(w, x, y, &v); int mode = GetVehicleFromShipDepotWndPt(w, x, y, &v);
// share / copy orders // share / copy orders
@ -746,34 +734,40 @@ static void ClonePlaceObj(const Window *w)
static void ShipDepotWndProc(Window *w, WindowEvent *e) static void ShipDepotWndProc(Window *w, WindowEvent *e)
{ {
switch (e->event) { switch (e->event) {
case WE_CREATE:
WP(w, traindepot_d).vehicle_list = NULL;
WP(w, traindepot_d).engine_count = 0;
break;
case WE_PAINT: 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); DrawShipDepotWindow(w);
break; break;
case WE_CLICK: case WE_CLICK:
switch (e->we.click.widget) { switch (e->we.click.widget) {
case 5: case 5: // List
ShipDepotClick(w, e->we.click.pt.x, e->we.click.pt.y); ShipDepotClick(w, e->we.click.pt.x, e->we.click.pt.y);
break; break;
case 7: case 7: // Build vehicle
ResetObjectToPlace(); ResetObjectToPlace();
ShowBuildShipWindow(w->window_number); ShowBuildShipWindow(w->window_number);
break; break;
case 8: /* clone button */ case 8: // Clone button
InvalidateWidget(w, 8); InvalidateWidget(w, 8);
TOGGLEBIT(w->click_state, 8); TOGGLEBIT(w->click_state, 8);
if (HASBIT(w->click_state, 8)) { if (HASBIT(w->click_state, 8)) {
_place_clicked_vehicle = NULL; _place_clicked_vehicle = NULL;
SetObjectToPlaceWnd(SPR_CURSOR_CLONE, VHM_RECT, w); SetObjectToPlaceWnd(SPR_CURSOR_CLONE, VHM_RECT, w);
} else { } else {
ResetObjectToPlace(); ResetObjectToPlace();
} }
break; break;
case 9: ScrollMainWindowToTile(w->window_number); break; case 9: ScrollMainWindowToTile(w->window_number); break;
} }
break; break;
@ -799,6 +793,7 @@ static void ShipDepotWndProc(Window *w, WindowEvent *e)
case WE_DESTROY: case WE_DESTROY:
DeleteWindowById(WC_BUILD_VEHICLE, w->window_number); DeleteWindowById(WC_BUILD_VEHICLE, w->window_number);
free((void*)WP(w, traindepot_d).vehicle_list);
break; break;
case WE_DRAGDROP: case WE_DRAGDROP:

View File

@ -398,10 +398,11 @@ void DrawTrainImage(const Vehicle *v, int x, int y, int count, int skip, Vehicle
static void DrawTrainDepotWindow(Window *w) static void DrawTrainDepotWindow(Window *w)
{ {
Vehicle **vl = WP(w, traindepot_d).vehicle_list;
TileIndex tile; TileIndex tile;
Vehicle *v, *u; int x, y, i, hnum, max;
int num,x,y,i, hnum;
Depot *depot; Depot *depot;
uint16 num;
tile = w->window_number; 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)); IsTileOwner(tile, _local_player) ? 0 : ((1 << 4) | (1 << 5) | (1 << 8) | (1<<9));
/* determine amount of items for scroller */ /* determine amount of items for scroller */
num = 0;
hnum = 8; hnum = 8;
FOR_ALL_VEHICLES(v) { for (num = 0; num < WP(w, traindepot_d).engine_count; num++) {
if (v->type == VEH_Train && const Vehicle *v = vl[num];
(IsFrontEngine(v) || IsFreeWagon(v)) && hnum = maxu(hnum, v->u.rail.cached_total_length);
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);
}
}
} }
/* Always have 1 empty row, so people can change the setting of the train */ /* Always have 1 empty row, so people can change the setting of the train */
num++; SetVScrollCount(w, WP(w, traindepot_d).engine_count + WP(w, traindepot_d).wagon_count + 1);
SetVScrollCount(w, num);
SetHScrollCount(w, WagonLengthToPixels(hnum)); SetHScrollCount(w, WagonLengthToPixels(hnum));
/* locate the depot struct */ /* locate the depot struct */
@ -441,44 +431,45 @@ static void DrawTrainDepotWindow(Window *w)
x = 2; x = 2;
y = 15; y = 15;
num = w->vscroll.pos; 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) /* draw all trains */
SetDParam(0, (v->u.rail.cached_total_length + 7) / 8); for (; num < max; num++) {
DrawStringRightAligned(w->widget[6].right - 1, y + 4, STR_TINY_BLACK, 0); // Draw the counter const Vehicle *v = vl[num];
/* Draw the pretty flag */ DrawTrainImage(v, x + 21, y, w->hscroll.cap + 4, w->hscroll.pos, WP(w,traindepot_d).sel);
DrawSprite(v->vehstatus & VS_STOPPED ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, x + 15, y); /* 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 max = min(WP(w, traindepot_d).engine_count + WP(w, traindepot_d).wagon_count, w->vscroll.pos + w->vscroll.cap);
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 */ /* draw all remaining vehicles */
i = 0; for (; num < max; num++) {
u = v; const Vehicle *v = WP(w, traindepot_d).wagon_list[num - WP(w, traindepot_d).engine_count];
do i++; while ( (u=u->next) != NULL); // Determine length of train const Vehicle *u;
SetDParam(0, i); // Set the counter
DrawStringRightAligned(w->widget[6].right - 1, y + 4, STR_TINY_BLACK, 0); // Draw the counter DrawTrainImage(v, x + 50, y, w->hscroll.cap - 29, 0, WP(w,traindepot_d).sel);
y += 14; 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) static int GetVehicleFromTrainDepotWndPt(const Window *w, int x, int y, GetDepotVehiclePtData *d)
{ {
Vehicle **vl = WP(w, traindepot_d).vehicle_list;
int row; int row;
int skip = 0; int skip = 0;
Vehicle *v; Vehicle *v;
@ -500,38 +492,23 @@ static int GetVehicleFromTrainDepotWndPt(const Window *w, int x, int y, GetDepot
row += w->vscroll.pos; row += w->vscroll.pos;
/* go through all the locomotives */ if (WP(w, traindepot_d).engine_count + WP(w, traindepot_d).wagon_count <= row) {
FOR_ALL_VEHICLES(v) { /* empty row, so no vehicle is selected */
if (v->type == VEH_Train && d->head = NULL;
IsFrontEngine(v) && d->wagon = NULL;
v->tile == w->window_number && return 0;
v->u.rail.track == 0x80 &&
--row < 0) {
skip = w->hscroll.pos;
goto found_it;
}
} }
x -= _traininfo_vehicle_width; /* free wagons don't have an initial loco. */ if (WP(w, traindepot_d).engine_count > row) {
v = vl[row];
/* and then the list of free wagons */ skip = w->hscroll.pos;
FOR_ALL_VEHICLES(v) { } else {
if (v->type == VEH_Train && vl = WP(w, traindepot_d).wagon_list;
IsFreeWagon(v) && v = vl[row - WP(w, traindepot_d).engine_count];
v->tile == w->window_number && /* free wagons don't have an initial loco. */
v->u.rail.track == 0x80 && x -= _traininfo_vehicle_width;
--row < 0) {
goto found_it;
}
} }
d->head = NULL;
d->wagon = NULL;
/* didn't find anything, get out */
return 0;
found_it:
d->head = d->wagon = v; d->head = d->wagon = v;
/* either pressed the flag or the number, but only when it's a loco */ /* 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) static void TrainDepotWndProc(Window *w, WindowEvent *e)
{ {
switch (e->event) { 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: 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); DrawTrainDepotWindow(w);
break; break;
@ -702,6 +688,8 @@ static void TrainDepotWndProc(Window *w, WindowEvent *e)
case WE_DESTROY: case WE_DESTROY:
DeleteWindowById(WC_BUILD_VEHICLE, w->window_number); DeleteWindowById(WC_BUILD_VEHICLE, w->window_number);
free((void*)WP(w, traindepot_d).vehicle_list);
free((void*)WP(w, traindepot_d).wagon_list);
break; break;
case WE_DRAGDROP: { case WE_DRAGDROP: {

View File

@ -1982,6 +1982,94 @@ static void MaybeReplaceVehicle(Vehicle *v)
_current_player = OWNER_NONE; _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 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 * @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 * @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 * @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; const uint subtype = (type != VEH_Aircraft) ? Train_Front : 2;
uint n = 0; 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) 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; uint n, i;
sort_list = malloc(GetVehicleArraySize() * sizeof(sort_list[0])); sort_list = malloc(GetVehicleArraySize() * sizeof(sort_list[0]));

View File

@ -317,6 +317,7 @@ int CheckTrainStoppedInDepot(const Vehicle *v);
bool VehicleNeedsService(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); 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); int32 SendAllVehiclesToDepot(byte type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id);
/* Flags to add to p2 for goto depot commands */ /* Flags to add to p2 for goto depot commands */

View File

@ -394,6 +394,12 @@ assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(replaceveh_d));
typedef struct { typedef struct {
VehicleID sel; VehicleID sel;
uint16 engine_list_length;
uint16 wagon_list_length;
uint16 engine_count;
uint16 wagon_count;
Vehicle **vehicle_list;
Vehicle **wagon_list;
} traindepot_d; } traindepot_d;
assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(traindepot_d)); assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(traindepot_d));