|
@@ -154,22 +154,13 @@ static void TrainDepotMoveVehicle(const
|
|
|
|
|
|
DoCommandP(v->tile, v->index + ((wagon == NULL ? INVALID_VEHICLE : wagon->index) << 16), _ctrl_pressed ? 1 : 0, CMD_MOVE_RAIL_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_MOVE_VEHICLE));
|
|
|
}
|
|
|
|
|
|
/** Array containing the cell size in pixels of the #DEPOT_WIDGET_MATRIX widget for each vehicle type.
|
|
|
* @note The train vehicle type uses the entire row for each train. */
|
|
|
static Dimension _block_sizes[4];
|
|
|
|
|
|
/** Array containing the default number of cells in horizontal and vertical direction in the #DEPOT_WIDGET_MATRIX widget for each vehicle type.
|
|
|
* @note The train vehicle type uses the entire row for each train. */
|
|
|
static const Dimension _resize_cap[] = {
|
|
|
{10 * 29, 6}, ///< VEH_TRAIN
|
|
|
{ 5, 5}, ///< VEH_ROAD
|
|
|
{ 3, 3}, ///< VEH_SHIP
|
|
|
{ 4, 3}, ///< VEH_AIRCRAFT
|
|
|
};
|
|
|
static Dimension _base_block_sizes[4];
|
|
|
|
|
|
static void InitBlocksizeForShipAircraft(VehicleType type)
|
|
|
{
|
|
|
uint max_width = 0;
|
|
|
uint max_height = 0;
|
|
|
|
|
@@ -187,30 +178,30 @@ static void InitBlocksizeForShipAircraft
|
|
|
if (y > max_height) max_height = y;
|
|
|
}
|
|
|
|
|
|
switch (type) {
|
|
|
default: NOT_REACHED();
|
|
|
case VEH_SHIP:
|
|
|
_block_sizes[VEH_SHIP].width = max(90U, max_width + 20); // we need 20 pixels from the right edge to the sprite
|
|
|
_base_block_sizes[VEH_SHIP].width = max(76U, max_width);
|
|
|
break;
|
|
|
case VEH_AIRCRAFT:
|
|
|
_block_sizes[VEH_AIRCRAFT].width = max(74U, max_width);
|
|
|
_base_block_sizes[VEH_AIRCRAFT].width = max(67U, max_width);
|
|
|
break;
|
|
|
}
|
|
|
_block_sizes[type].height = max(GetVehicleHeight(type), max_height);
|
|
|
_base_block_sizes[type].height = max(GetVehicleHeight(type), max_height);
|
|
|
}
|
|
|
|
|
|
/** Set the size of the blocks in the window so we can be sure that they are big enough for the vehicle sprites in the current game.
|
|
|
* @note Calling this function once for each game is enough. */
|
|
|
void InitDepotWindowBlockSizes()
|
|
|
{
|
|
|
_block_sizes[VEH_TRAIN].width = 1;
|
|
|
_block_sizes[VEH_TRAIN].height = GetVehicleHeight(VEH_TRAIN);
|
|
|
_base_block_sizes[VEH_TRAIN].width = 0;
|
|
|
_base_block_sizes[VEH_TRAIN].height = GetVehicleHeight(VEH_TRAIN);
|
|
|
|
|
|
_block_sizes[VEH_ROAD].width = 56;
|
|
|
_block_sizes[VEH_ROAD].height = GetVehicleHeight(VEH_ROAD);
|
|
|
_base_block_sizes[VEH_ROAD].width = 32;
|
|
|
_base_block_sizes[VEH_ROAD].height = GetVehicleHeight(VEH_ROAD);
|
|
|
|
|
|
InitBlocksizeForShipAircraft(VEH_SHIP);
|
|
|
InitBlocksizeForShipAircraft(VEH_AIRCRAFT);
|
|
|
}
|
|
|
|
|
|
static void DepotSellAllConfirmationCallback(Window *w, bool confirmed);
|
|
@@ -251,34 +242,34 @@ struct DepotWindow : Window {
|
|
|
* @param right Right side of the box to draw in.
|
|
|
* @param y Top of the box to draw in.
|
|
|
*/
|
|
|
void DrawVehicleInDepot(const Vehicle *v, int left, int right, int y) const
|
|
|
{
|
|
|
bool free_wagon = false;
|
|
|
int sprite_y = y + this->resize.step_height - GetVehicleHeight(v->type);
|
|
|
int sprite_y = y + (this->resize.step_height - GetVehicleHeight(v->type)) / 2;
|
|
|
int x = left + 2;
|
|
|
|
|
|
switch (v->type) {
|
|
|
case VEH_TRAIN: {
|
|
|
const Train *u = Train::From(v);
|
|
|
free_wagon = u->IsFreeWagon();
|
|
|
|
|
|
uint x_space = free_wagon ? TRAININFO_DEFAULT_VEHICLE_WIDTH : 0;
|
|
|
DrawTrainImage(u, x + 24 + x_space, right - 10, sprite_y - 1, this->sel, this->hscroll.GetPosition());
|
|
|
DrawTrainImage(u, x + this->header_width + x_space, right - count_width, sprite_y - 1, this->sel, free_wagon ? 0 : this->hscroll.GetPosition());
|
|
|
|
|
|
/* Number of wagons relative to a standard length wagon (rounded up) */
|
|
|
SetDParam(0, (u->tcache.cached_total_length + 7) / 8);
|
|
|
DrawString(left, right - 1, y + 4, STR_TINY_BLACK_COMA, TC_FROMSTRING, SA_RIGHT); // Draw the counter
|
|
|
DrawString(left, right - 1, y + (this->resize.step_height - FONT_HEIGHT_SMALL) / 2, STR_TINY_BLACK_COMA, TC_FROMSTRING, SA_RIGHT); // Draw the counter
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
case VEH_ROAD: DrawRoadVehImage( v, x + 24, right, sprite_y, this->sel); break;
|
|
|
case VEH_SHIP: DrawShipImage( v, x + 12, right, sprite_y - 1, this->sel); break;
|
|
|
case VEH_ROAD: DrawRoadVehImage( v, x + this->header_width, right, sprite_y, this->sel); break;
|
|
|
case VEH_SHIP: DrawShipImage( v, x + this->header_width, right, sprite_y - 1, this->sel); break;
|
|
|
case VEH_AIRCRAFT: {
|
|
|
const Sprite *spr = GetSprite(v->GetImage(DIR_W), ST_NORMAL);
|
|
|
DrawAircraftImage(v, x + 12, right,
|
|
|
DrawAircraftImage(v, x + this->header_width, right,
|
|
|
y + max(spr->height + spr->y_offs - 14, 0), // tall sprites needs an y offset
|
|
|
this->sel);
|
|
|
} break;
|
|
|
default: NOT_REACHED();
|
|
|
}
|
|
|
|
|
@@ -286,22 +277,23 @@ struct DepotWindow : Window {
|
|
|
DrawString(x, right - 1, y + 2, STR_DEPOT_NO_ENGINE);
|
|
|
} else {
|
|
|
byte diff_x = 0, diff_y = 0;
|
|
|
|
|
|
if (v->type == VEH_TRAIN || v->type == VEH_ROAD) {
|
|
|
/* Arrange unitnumber and flag horizontally */
|
|
|
diff_x = 15;
|
|
|
diff_x = this->flag_width;
|
|
|
diff_y = (this->resize.step_height - this->flag_height) / 2 - 2;
|
|
|
} else {
|
|
|
/* Arrange unitnumber and flag vertically */
|
|
|
diff_y = 12;
|
|
|
diff_y = FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL;
|
|
|
}
|
|
|
|
|
|
DrawSprite((v->vehstatus & VS_STOPPED) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, x + diff_x, y + diff_y);
|
|
|
DrawSprite((v->vehstatus & VS_STOPPED) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, x, y + diff_y);
|
|
|
|
|
|
SetDParam(0, v->unitnumber);
|
|
|
DrawString(x, right - 1, y + 2, (uint16)(v->max_age - DAYS_IN_LEAP_YEAR) >= v->age ? STR_BLACK_COMMA : STR_RED_COMMA);
|
|
|
DrawString(x + diff_x, right - 1, y + 2, (uint16)(v->max_age - DAYS_IN_LEAP_YEAR) >= v->age ? STR_BLACK_COMMA : STR_RED_COMMA);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void DrawWidget(const Rect &r, int widget) const
|
|
|
{
|
|
|
if (widget != DEPOT_WIDGET_MATRIX) return;
|
|
@@ -359,91 +351,88 @@ struct DepotWindow : Window {
|
|
|
MODE_SHOW_VEHICLE,
|
|
|
MODE_START_STOP,
|
|
|
};
|
|
|
|
|
|
DepotGUIAction GetVehicleFromDepotWndPt(int x, int y, const Vehicle **veh, GetDepotVehiclePtData *d) const
|
|
|
{
|
|
|
uint xt, xm = 0, ym = 0;
|
|
|
uint xt = 0, xm = 0, ym = 0;
|
|
|
if (this->type == VEH_TRAIN) {
|
|
|
xt = 0;
|
|
|
x -= 23;
|
|
|
xm = x;
|
|
|
} else {
|
|
|
xt = x / this->resize.step_width;
|
|
|
xm = x % this->resize.step_width;
|
|
|
if (xt >= this->hscroll.GetCapacity()) return MODE_ERROR;
|
|
|
|
|
|
ym = y % this->resize.step_height;
|
|
|
}
|
|
|
ym = y % this->resize.step_height;
|
|
|
|
|
|
uint row = y / this->resize.step_height;
|
|
|
if (row >= this->vscroll.GetCapacity()) return MODE_ERROR;
|
|
|
|
|
|
uint16 boxes_in_each_row = GB(this->GetWidget<NWidgetCore>(DEPOT_WIDGET_MATRIX)->widget_data, MAT_COL_START, MAT_COL_BITS);
|
|
|
int pos = ((row + this->vscroll.GetPosition()) * boxes_in_each_row) + xt;
|
|
|
uint boxes_in_each_row = GB(this->GetWidget<NWidgetCore>(DEPOT_WIDGET_MATRIX)->widget_data, MAT_COL_START, MAT_COL_BITS);
|
|
|
uint pos = ((row + this->vscroll.GetPosition()) * boxes_in_each_row) + xt;
|
|
|
|
|
|
if ((int)(this->vehicle_list.Length() + this->wagon_list.Length()) <= pos) {
|
|
|
if (this->vehicle_list.Length() + this->wagon_list.Length() <= pos) {
|
|
|
/* Clicking on 'line' / 'block' without a vehicle */
|
|
|
if (this->type == VEH_TRAIN) {
|
|
|
/* End the dragging */
|
|
|
d->head = NULL;
|
|
|
d->wagon = NULL;
|
|
|
return MODE_DRAG_VEHICLE;
|
|
|
} else {
|
|
|
return MODE_ERROR; // empty block, so no vehicle is selected
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int skip = 0;
|
|
|
if ((int)this->vehicle_list.Length() > pos) {
|
|
|
if (this->vehicle_list.Length() > pos) {
|
|
|
*veh = this->vehicle_list[pos];
|
|
|
skip = this->hscroll.GetPosition();
|
|
|
/* Skip vehicles that are scrolled off the list */
|
|
|
x += this->hscroll.GetPosition();
|
|
|
} else {
|
|
|
pos -= this->vehicle_list.Length();
|
|
|
*veh = this->wagon_list[pos];
|
|
|
/* free wagons don't have an initial loco. */
|
|
|
x -= VEHICLEINFO_FULL_VEHICLE_WIDTH;
|
|
|
}
|
|
|
|
|
|
switch (this->type) {
|
|
|
case VEH_TRAIN: {
|
|
|
const Train *v = Train::From(*veh);
|
|
|
d->head = d->wagon = v;
|
|
|
|
|
|
/* either pressed the flag or the number, but only when it's a loco */
|
|
|
if (x < 0 && v->IsFrontEngine()) return (x >= -10) ? MODE_START_STOP : MODE_SHOW_VEHICLE;
|
|
|
const Train *v = NULL;
|
|
|
if (this->type == VEH_TRAIN) {
|
|
|
v = Train::From(*veh);
|
|
|
d->head = d->wagon = v;
|
|
|
}
|
|
|
|
|
|
/* Skip vehicles that are scrolled off the list */
|
|
|
x += skip;
|
|
|
if (xm <= this->header_width) {
|
|
|
switch (this->type) {
|
|
|
case VEH_TRAIN:
|
|
|
case VEH_ROAD:
|
|
|
if (xm <= this->flag_width) return MODE_START_STOP;
|
|
|
break;
|
|
|
|
|
|
/* find the vehicle in this row that was clicked */
|
|
|
for (; v != NULL; v = v->Next()) {
|
|
|
x -= v->GetDisplayImageWidth();
|
|
|
if (x < 0) break;
|
|
|
}
|
|
|
|
|
|
d->wagon = (v != NULL ? v->GetFirstEnginePart() : NULL);
|
|
|
case VEH_SHIP:
|
|
|
case VEH_AIRCRAFT:
|
|
|
if (xm <= this->flag_width && ym >= (uint)(FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL)) return MODE_START_STOP;
|
|
|
break;
|
|
|
|
|
|
return MODE_DRAG_VEHICLE;
|
|
|
default: NOT_REACHED();
|
|
|
}
|
|
|
return MODE_SHOW_VEHICLE;
|
|
|
}
|
|
|
|
|
|
case VEH_ROAD:
|
|
|
if (xm >= 24) return MODE_DRAG_VEHICLE;
|
|
|
if (xm <= 16) return MODE_SHOW_VEHICLE;
|
|
|
break;
|
|
|
if (this->type != VEH_TRAIN) return MODE_DRAG_VEHICLE;
|
|
|
|
|
|
/* Account for the header */
|
|
|
x -= this->header_width;
|
|
|
|
|
|
case VEH_SHIP:
|
|
|
if (xm >= 19) return MODE_DRAG_VEHICLE;
|
|
|
if (ym <= 10) return MODE_SHOW_VEHICLE;
|
|
|
break;
|
|
|
/* find the vehicle in this row that was clicked */
|
|
|
for (; v != NULL; v = v->Next()) {
|
|
|
x -= v->GetDisplayImageWidth();
|
|
|
if (x < 0) break;
|
|
|
}
|
|
|
|
|
|
case VEH_AIRCRAFT:
|
|
|
if (xm >= 12) return MODE_DRAG_VEHICLE;
|
|
|
if (ym <= 12) return MODE_SHOW_VEHICLE;
|
|
|
break;
|
|
|
d->wagon = (v != NULL ? v->GetFirstEnginePart() : NULL);
|
|
|
|
|
|
default: NOT_REACHED();
|
|
|
}
|
|
|
return MODE_START_STOP;
|
|
|
return MODE_DRAG_VEHICLE;
|
|
|
}
|
|
|
|
|
|
/** Handle click in the depot matrix.
|
|
|
* @param x Horizontal position in the matrix widget in pixels.
|
|
|
* @param y Vertical position in the matrix widget in pixels.
|
|
|
*/
|
|
@@ -594,31 +583,65 @@ struct DepotWindow : Window {
|
|
|
this->GetWidget<NWidgetCore>(DEPOT_WIDGET_SELL_ALL)->widget_data = SPR_SELL_ALL_AIRCRAFT;
|
|
|
this->GetWidget<NWidgetCore>(DEPOT_WIDGET_AUTOREPLACE)->widget_data = SPR_REPLACE_AIRCRAFT;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
uint count_width;
|
|
|
uint header_width;
|
|
|
uint flag_width;
|
|
|
uint flag_height;
|
|
|
|
|
|
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *resize)
|
|
|
{
|
|
|
switch (widget) {
|
|
|
case DEPOT_WIDGET_SELL_CHAIN:
|
|
|
case DEPOT_WIDGET_H_SCROLL:
|
|
|
/* Hide the 'sell chain' and the horizontal scrollbar when not a train depot. */
|
|
|
if (this->type != VEH_TRAIN) {
|
|
|
size->height = 0;
|
|
|
resize->height = 0;
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
case DEPOT_WIDGET_MATRIX:
|
|
|
resize->width = _block_sizes[this->type].width;
|
|
|
resize->height = _block_sizes[this->type].height;
|
|
|
size->width = _block_sizes[this->type].width * ((this->type == VEH_TRAIN) ? 1 : _resize_cap[this->type].width);
|
|
|
size->height = _block_sizes[this->type].height * _resize_cap[this->type].height;
|
|
|
if (this->type == VEH_TRAIN) size->width += 36; // Make space for the horizontal scrollbar vertically, and the unit number, flag, and length counter horizontally.
|
|
|
break;
|
|
|
case DEPOT_WIDGET_MATRIX: {
|
|
|
uint min_height = 0;
|
|
|
uint base_width = 0;
|
|
|
|
|
|
if (this->type == VEH_TRAIN) {
|
|
|
SetDParam(0, 100);
|
|
|
this->count_width = GetStringBoundingBox(STR_TINY_BLACK_COMA).width + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
|
|
|
base_width += this->count_width;
|
|
|
}
|
|
|
|
|
|
SetDParam(0, 999);
|
|
|
Dimension unumber = GetStringBoundingBox(STR_BLACK_COMMA);
|
|
|
const Sprite *spr = GetSprite(SPR_FLAG_VEH_STOPPED, ST_NORMAL);
|
|
|
this->flag_width = spr->width + WD_FRAMERECT_RIGHT;
|
|
|
this->flag_height = spr->height;
|
|
|
|
|
|
if (this->type == VEH_TRAIN || this->type == VEH_ROAD) {
|
|
|
min_height = max<uint>(unumber.height + WD_MATRIX_TOP, spr->height);
|
|
|
this->header_width = unumber.width + this->flag_width;
|
|
|
} else {
|
|
|
min_height = unumber.height + spr->height + WD_MATRIX_TOP + WD_PAR_VSEP_NORMAL + WD_MATRIX_BOTTOM;
|
|
|
this->header_width = max<uint>(unumber.width, this->flag_width) + WD_FRAMERECT_RIGHT;
|
|
|
}
|
|
|
base_width += this->header_width;
|
|
|
|
|
|
resize->height = max(_base_block_sizes[this->type].height, min_height);
|
|
|
if (this->type == VEH_TRAIN) {
|
|
|
resize->width = 1;
|
|
|
size->width = base_width + 10 * 29; // about 10 parts
|
|
|
size->height = resize->height * 5;
|
|
|
} else {
|
|
|
resize->width = base_width + _base_block_sizes[this->type].width;
|
|
|
size->width = resize->width * (this->type == VEH_ROAD ? 5 : 3);
|
|
|
size->height = resize->height * (this->type == VEH_ROAD ? 5 : 3);
|
|
|
}
|
|
|
} break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
virtual void OnInvalidateData(int data)
|
|
|
{
|
|
|
this->generate_list = true;
|