00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "window_gui.h"
00014 #include "gfx_func.h"
00015 #include "command_func.h"
00016 #include "vehicle_gui.h"
00017 #include "train.h"
00018 #include "strings_func.h"
00019 #include "vehicle_func.h"
00020 #include "engine_base.h"
00021 #include "window_func.h"
00022
00023 #include "table/sprites.h"
00024 #include "table/strings.h"
00025
00026 void CcBuildWagon(bool success, TileIndex tile, uint32 p1, uint32 p2)
00027 {
00028 if (!success) return;
00029
00030
00031 const Vehicle *found = NULL;
00032 const Train *t;
00033 FOR_ALL_TRAINS(t) {
00034 if (t->IsFrontEngine() && t->tile == tile &&
00035 t->track == TRACK_BIT_DEPOT) {
00036 if (found != NULL) return;
00037 found = t;
00038 }
00039 }
00040
00041
00042 if (found != NULL) {
00043 found = found->Last();
00044
00045 DoCommandP(0, _new_vehicle_id | (found->index << 16), 0, CMD_MOVE_RAIL_VEHICLE);
00046 InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
00047 }
00048 }
00049
00050 void CcBuildLoco(bool success, TileIndex tile, uint32 p1, uint32 p2)
00051 {
00052 if (!success) return;
00053
00054 const Vehicle *v = Vehicle::Get(_new_vehicle_id);
00055 if (tile == _backup_orders_tile) {
00056 _backup_orders_tile = 0;
00057 RestoreVehicleOrders(v);
00058 }
00059 ShowVehicleViewWindow(v);
00060 }
00061
00071 void DrawTrainImage(const Train *v, int left, int right, int y, VehicleID selection, int skip)
00072 {
00073 bool rtl = _dynlang.text_dir == TD_RTL;
00074 Direction dir = rtl ? DIR_E : DIR_W;
00075
00076 DrawPixelInfo tmp_dpi, *old_dpi;
00077
00078 int highlight_l = 0;
00079 int highlight_r = 0;
00080 int max_width = right - left + 1;
00081
00082 if (!FillDrawPixelInfo(&tmp_dpi, left, y, max_width, 14)) return;
00083
00084 old_dpi = _cur_dpi;
00085 _cur_dpi = &tmp_dpi;
00086
00087 int px = rtl ? max_width + skip : -skip;
00088 bool sel_articulated = false;
00089 for (; v != NULL && (rtl ? px > 0 : px < max_width); v = v->Next()) {
00090 Point offset;
00091 int width = Train::From(v)->GetDisplayImageWidth(&offset);
00092
00093 if (rtl ? px + width > 0 : px - width < max_width) {
00094 SpriteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
00095 DrawSprite(v->GetImage(dir), pal, px + (rtl ? -offset.x : offset.x), 7 + offset.y);
00096 }
00097
00098 if (!v->IsArticulatedPart()) sel_articulated = false;
00099
00100 if (v->index == selection) {
00101
00102 highlight_l = rtl ? px - width : px;
00103 highlight_r = rtl ? px - 1 : px + width - 1;
00104 sel_articulated = true;
00105 } else if ((_cursor.vehchain && highlight_r != 0) || sel_articulated) {
00106 if (rtl) {
00107 highlight_l -= width;
00108 } else {
00109 highlight_r += width;
00110 }
00111 }
00112
00113 px += rtl ? -width : width;
00114 }
00115
00116 if (highlight_l != highlight_r) {
00117
00118
00119 DrawFrameRect(highlight_l, 0, highlight_r, 13, COLOUR_WHITE, FR_BORDERONLY);
00120 }
00121
00122 _cur_dpi = old_dpi;
00123 }
00124
00126 struct CargoSummaryItem {
00127 CargoID cargo;
00128 StringID subtype;
00129 uint capacity;
00130 uint amount;
00131 StationID source;
00132
00134 FORCEINLINE bool operator != (const CargoSummaryItem &other) const
00135 {
00136 return this->cargo != other.cargo || this->subtype != other.subtype;
00137 }
00138 };
00139
00140 enum {
00141 TRAIN_DETAILS_MIN_INDENT = 32,
00142 TRAIN_DETAILS_MAX_INDENT = 72,
00143 };
00144
00146 typedef SmallVector<CargoSummaryItem, 2> CargoSummary;
00148 static CargoSummary _cargo_summary;
00149
00158 static void TrainDetailsCargoTab(const CargoSummaryItem *item, int left, int right, int y)
00159 {
00160 StringID str = STR_VEHICLE_DETAILS_CARGO_EMPTY;
00161
00162 if (item->amount > 0) {
00163 SetDParam(0, item->cargo);
00164 SetDParam(1, item->amount);
00165 SetDParam(2, item->source);
00166 SetDParam(3, _settings_game.vehicle.freight_trains);
00167 str = FreightWagonMult(item->cargo) > 1 ? STR_VEHICLE_DETAILS_CARGO_FROM_MULT : STR_VEHICLE_DETAILS_CARGO_FROM;
00168 }
00169
00170 DrawString(left, right, y, str);
00171 }
00172
00181 static void TrainDetailsInfoTab(const Vehicle *v, int left, int right, int y)
00182 {
00183 if (RailVehInfo(v->engine_type)->railveh_type == RAILVEH_WAGON) {
00184 SetDParam(0, v->engine_type);
00185 SetDParam(1, v->value);
00186 DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_WAGON_VALUE, TC_FROMSTRING, SA_LEFT | SA_STRIP);
00187 } else {
00188 SetDParam(0, v->engine_type);
00189 SetDParam(1, v->build_year);
00190 SetDParam(2, v->value);
00191 DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_ENGINE_BUILT_AND_VALUE, TC_FROMSTRING, SA_LEFT | SA_STRIP);
00192 }
00193 }
00194
00203 static void TrainDetailsCapacityTab(const CargoSummaryItem *item, int left, int right, int y)
00204 {
00205 SetDParam(0, item->cargo);
00206 SetDParam(1, item->capacity);
00207 SetDParam(4, item->subtype);
00208 SetDParam(5, _settings_game.vehicle.freight_trains);
00209 DrawString(left, right, y, FreightWagonMult(item->cargo) > 1 ? STR_VEHICLE_INFO_CAPACITY_MULT : STR_VEHICLE_INFO_CAPACITY);
00210 }
00211
00217 static void GetCargoSummaryOfArticulatedVehicle(const Train *v, CargoSummary *summary)
00218 {
00219 summary->Clear();
00220 do {
00221 if (v->cargo_cap == 0) continue;
00222
00223 CargoSummaryItem new_item;
00224 new_item.cargo = v->cargo_type;
00225 new_item.subtype = GetCargoSubtypeText(v);
00226
00227 CargoSummaryItem *item = summary->Find(new_item);
00228 if (item == summary->End()) {
00229 item = summary->Append();
00230 item->cargo = new_item.cargo;
00231 item->subtype = new_item.subtype;
00232 item->capacity = 0;
00233 item->amount = 0;
00234 item->source = INVALID_STATION;
00235 }
00236
00237 item->capacity += v->cargo_cap;
00238 item->amount += v->cargo.Count();
00239 if (item->source == INVALID_STATION) item->source = v->cargo.Source();
00240 } while ((v = v->Next()) != NULL && v->IsArticulatedPart());
00241 }
00242
00248 static uint GetLengthOfArticulatedVehicle(const Train *v)
00249 {
00250 uint length = 0;
00251
00252 do {
00253 length += v->GetDisplayImageWidth();
00254 } while ((v = v->Next()) != NULL && v->IsArticulatedPart());
00255
00256 return length;
00257 }
00258
00265 int GetTrainDetailsWndVScroll(VehicleID veh_id, TrainDetailsWindowTabs det_tab)
00266 {
00267 int num = 0;
00268
00269 if (det_tab == TDW_TAB_TOTALS) {
00270 CargoArray act_cargo;
00271 CargoArray max_cargo;
00272 for (const Vehicle *v = Vehicle::Get(veh_id); v != NULL; v = v->Next()) {
00273 act_cargo[v->cargo_type] += v->cargo.Count();
00274 max_cargo[v->cargo_type] += v->cargo_cap;
00275 }
00276
00277
00278
00279
00280 for (CargoID i = 0; i < NUM_CARGO; i++) {
00281 if (max_cargo[i] > 0) num++;
00282 }
00283 num++;
00284 } else {
00285 for (const Train *v = Train::Get(veh_id); v != NULL; v = v->GetNextVehicle()) {
00286 GetCargoSummaryOfArticulatedVehicle(v, &_cargo_summary);
00287 num += max(1u, _cargo_summary.Length());
00288
00289 uint length = GetLengthOfArticulatedVehicle(v);
00290 if (length > TRAIN_DETAILS_MAX_INDENT) num++;
00291 }
00292 }
00293
00294 return num;
00295 }
00296
00308 void DrawTrainDetails(const Train *v, int left, int right, int y, int vscroll_pos, uint16 vscroll_cap, TrainDetailsWindowTabs det_tab)
00309 {
00310
00311 if (det_tab != TDW_TAB_TOTALS) {
00312 bool rtl = _dynlang.text_dir == TD_RTL;
00313 Direction dir = rtl ? DIR_E : DIR_W;
00314 int x = rtl ? right : left;
00315 int sprite_y_offset = 4 + (FONT_HEIGHT_NORMAL - 10) / 2;
00316 int line_height = WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM;
00317 for (; v != NULL && vscroll_pos > -vscroll_cap; v = v->GetNextVehicle()) {
00318 GetCargoSummaryOfArticulatedVehicle(v, &_cargo_summary);
00319
00320
00321 int dx = 0;
00322 int px = x;
00323 const Train *u = v;
00324 do {
00325 Point offset;
00326 int width = u->GetDisplayImageWidth(&offset);
00327 if (vscroll_pos <= 0 && vscroll_pos > -vscroll_cap) {
00328 SpriteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
00329 DrawSprite(u->GetImage(dir), pal, px + (rtl ? -offset.x : offset.x), y - line_height * vscroll_pos + sprite_y_offset + offset.y);
00330 }
00331 px += rtl ? -width : width;
00332 dx += width;
00333 u = u->Next();
00334 } while (u != NULL && u->IsArticulatedPart());
00335
00336 bool separate_sprite_row = (dx > TRAIN_DETAILS_MAX_INDENT);
00337 if (separate_sprite_row) {
00338 vscroll_pos--;
00339 dx = 0;
00340 }
00341
00342 uint num_lines = max(1u, _cargo_summary.Length());
00343 for (uint i = 0; i < num_lines; i++) {
00344 int sprite_width = max<int>(dx, TRAIN_DETAILS_MIN_INDENT) + 3;
00345 int data_left = left + (rtl ? 0 : sprite_width);
00346 int data_right = right - (rtl ? sprite_width : 0);
00347 if (vscroll_pos <= 0 && vscroll_pos > -vscroll_cap) {
00348 int py = y - line_height * vscroll_pos;
00349 if (i > 0 || separate_sprite_row) {
00350 if (vscroll_pos != 0) GfxFillRect(left, py - WD_MATRIX_TOP - 1, right, py - WD_MATRIX_TOP, _colour_gradient[COLOUR_GREY][5]);
00351 }
00352 switch (det_tab) {
00353 case TDW_TAB_CARGO:
00354 if (i < _cargo_summary.Length()) {
00355 TrainDetailsCargoTab(&_cargo_summary[i], data_left, data_right, py);
00356 } else {
00357 DrawString(data_left, data_right, py, STR_QUANTITY_N_A, TC_LIGHT_BLUE);
00358 }
00359 break;
00360
00361 case TDW_TAB_INFO:
00362 if (i == 0) TrainDetailsInfoTab(v, data_left, data_right, py);
00363 break;
00364
00365 case TDW_TAB_CAPACITY:
00366 if (i < _cargo_summary.Length()) {
00367 TrainDetailsCapacityTab(&_cargo_summary[i], data_left, data_right, py);
00368 } else {
00369 DrawString(data_left, data_right, py, STR_VEHICLE_INFO_NO_CAPACITY);
00370 }
00371 break;
00372
00373 default: NOT_REACHED();
00374 }
00375 }
00376 vscroll_pos--;
00377 }
00378 }
00379 } else {
00380 CargoArray act_cargo;
00381 CargoArray max_cargo;
00382 Money feeder_share = 0;
00383
00384 for (const Vehicle *u = v; u != NULL; u = u->Next()) {
00385 act_cargo[u->cargo_type] += u->cargo.Count();
00386 max_cargo[u->cargo_type] += u->cargo_cap;
00387 feeder_share += u->cargo.FeederShare();
00388 }
00389
00390
00391 DrawString(left, right, y, STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY_TEXT);
00392 y += WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM;
00393
00394 for (CargoID i = 0; i < NUM_CARGO; i++) {
00395 if (max_cargo[i] > 0 && --vscroll_pos < 0 && vscroll_pos > -vscroll_cap) {
00396 SetDParam(0, i);
00397 SetDParam(1, act_cargo[i]);
00398 SetDParam(2, i);
00399 SetDParam(3, max_cargo[i]);
00400 SetDParam(4, _settings_game.vehicle.freight_trains);
00401 DrawString(left, right, y, FreightWagonMult(i) > 1 ? STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY_MULT : STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY);
00402 y += WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM;
00403 }
00404 }
00405 SetDParam(0, feeder_share);
00406 DrawString(left, right, y, STR_VEHICLE_INFO_FEEDER_CARGO_VALUE);
00407 }
00408 }