# train_gui.cpp

Go to the documentation of this file.

    00001 /* $Id: train_gui.cpp 14267 2008-09-07 21:41:47Z rubidium $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "openttd.h"
    00007 #include "debug.h"
    00008 #include "gui.h"
    00009 #include "window_gui.h"
    00010 #include "gfx_func.h"
    00011 #include "command_func.h"
    00012 #include "vehicle_gui.h"
    00013 #include "depot.h"
    00014 #include "train.h"
    00015 #include "newgrf_engine.h"
    00016 #include "strings_func.h"
    00017 #include "vehicle_func.h"
    00018 #include "settings_type.h"
    00019
    00020 #include "table/sprites.h"
    00021 #include "table/strings.h"
    00022
    00023 void CcBuildWagon(bool success, TileIndex tile, uint32 p1, uint32 p2)
    00024 {
    00025   Vehicle *v, *found;
    00026
    00027   if (!success) return;
    00028
    00029   /* find a locomotive in the depot. */
    00030   found = NULL;
    00031   FOR_ALL_VEHICLES(v) {
    00032     if (v->type == VEH_TRAIN && IsFrontEngine(v) &&
    00033         v->tile == tile &&
    00034         v->u.rail.track == TRACK_BIT_DEPOT) {
    00035       if (found != NULL) return; // must be exactly one.
    00036       found = v;
    00037     }
    00038   }
    00039
    00040   /* if we found a loco, */
    00041   if (found != NULL) {
    00042     found = GetLastVehicleInChain(found);
    00043     /* put the new wagon at the end of the loco. */
    00044     DoCommandP(0, _new_vehicle_id | (found->index << 16), 0, NULL, CMD_MOVE_RAIL_VEHICLE);
    00045     RebuildVehicleLists();
    00046   }
    00047 }
    00048
    00049 void CcBuildLoco(bool success, TileIndex tile, uint32 p1, uint32 p2)
    00050 {
    00051   const Vehicle *v;
    00052
    00053   if (!success) return;
    00054
    00055   v = GetVehicle(_new_vehicle_id);
    00056   if (tile == _backup_orders_tile) {
    00057     _backup_orders_tile = 0;
    00058     RestoreVehicleOrders(v);
    00059   }
    00060   ShowVehicleViewWindow(v);
    00061 }
    00062
    00068 int WagonLengthToPixels(int len)
    00069 {
    00070   return (len * _traininfo_vehicle_width) / 8;
    00071 }
    00072
    00073 void DrawTrainImage(const Vehicle *v, int x, int y, VehicleID selection, int count, int skip)
    00074 {
    00075   DrawPixelInfo tmp_dpi, *old_dpi;
    00076   int dx = -(skip * 8) / _traininfo_vehicle_width;
    00077   /* Position of highlight box */
    00078   int highlight_l = 0;
    00079   int highlight_r = 0;
    00080
    00081   if (!FillDrawPixelInfo(&tmp_dpi, x - 2, y - 1, count + 1, 14)) return;
    00082
    00083   count = (count * 8) / _traininfo_vehicle_width;
    00084
    00085   old_dpi = _cur_dpi;
    00086   _cur_dpi = &tmp_dpi;
    00087
    00088   do {
    00089     int width = v->u.rail.cached_veh_length;
    00090
    00091     if (dx + width > 0) {
    00092       if (dx <= count) {
    00093         SpriteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
    00094         DrawSprite(v->GetImage(DIR_W), pal, 16 + WagonLengthToPixels(dx), 7 + (is_custom_sprite(RailVehInfo(v->engine_type)->image_index) ? _traininfo_vehicle_pitch : 0));
    00095         if (v->index == selection) {
    00096           /* Set the highlight position */
    00097           highlight_l = WagonLengthToPixels(dx) + 1;
    00098           highlight_r = WagonLengthToPixels(dx + width) + 1;
    00099         }
    00100       }
    00101     }
    00102     dx += width;
    00103
    00104     v = v->Next();
    00105   } while (dx < count && v != NULL);
    00106
    00107   if (highlight_l != highlight_r) {
    00108     /* Draw the highlight. Now done after drawing all the engines, as
    00109      * the next engine after the highlight could overlap it. */
    00110     DrawFrameRect(highlight_l, 0, highlight_r, 13, 15, FR_BORDERONLY);
    00111   }
    00112
    00113   _cur_dpi = old_dpi;
    00114 }
    00115
    00116 static void TrainDetailsCargoTab(const Vehicle *v, int x, int y)
    00117 {
    00118   if (v->cargo_cap != 0) {
    00119     StringID str = STR_8812_EMPTY;
    00120
    00121     if (!v->cargo.Empty()) {
    00122       SetDParam(0, v->cargo_type);
    00123       SetDParam(1, v->cargo.Count());
    00124       SetDParam(2, v->cargo.Source());
    00125       SetDParam(3, _patches.freight_trains);
    00126       str = FreightWagonMult(v->cargo_type) > 1 ? STR_FROM_MULT : STR_8813_FROM;
    00127     }
    00128     DrawString(x, y, str, TC_FROMSTRING);
    00129   }
    00130 }
    00131
    00132 static void TrainDetailsInfoTab(const Vehicle *v, int x, int y)
    00133 {
    00134   if (RailVehInfo(v->engine_type)->railveh_type == RAILVEH_WAGON) {
    00135     SetDParam(0, v->engine_type);
    00136     SetDParam(1, v->value);
    00137     DrawString(x, y, STR_882D_VALUE, TC_BLACK);
    00138   } else {
    00139     SetDParam(0, v->engine_type);
    00140     SetDParam(1, v->build_year);
    00141     SetDParam(2, v->value);
    00142     DrawString(x, y, STR_882C_BUILT_VALUE, TC_BLACK);
    00143   }
    00144 }
    00145
    00146 static void TrainDetailsCapacityTab(const Vehicle *v, int x, int y)
    00147 {
    00148   if (v->cargo_cap != 0) {
    00149     SetDParam(0, v->cargo_type);
    00150     SetDParam(1, v->cargo_cap);
    00151     SetDParam(2, _patches.freight_trains);
    00152     DrawString(x, y, FreightWagonMult(v->cargo_type) > 1 ? STR_CAPACITY_MULT : STR_013F_CAPACITY, TC_FROMSTRING);
    00153   }
    00154 }
    00155
    00156 int GetTrainDetailsWndVScroll(VehicleID veh_id, byte det_tab)
    00157 {
    00158   AcceptedCargo act_cargo;
    00159   AcceptedCargo max_cargo;
    00160   int num = 0;
    00161
    00162   if (det_tab == 3) { // Total cargo tab
    00163     memset(max_cargo, 0, sizeof(max_cargo));
    00164     memset(act_cargo, 0, sizeof(act_cargo));
    00165
    00166     for (const Vehicle *v = GetVehicle(veh_id) ; v != NULL ; v = v->Next()) {
    00167       act_cargo[v->cargo_type] += v->cargo.Count();
    00168       max_cargo[v->cargo_type] += v->cargo_cap;
    00169     }
    00170
    00171     /* Set scroll-amount seperately from counting, as to not compute num double
    00172      * for more carriages of the same type
    00173      */
    00174     for (CargoID i = 0; i < NUM_CARGO; i++) {
    00175       if (max_cargo[i] > 0) num++; // only count carriages that the train has
    00176     }
    00177     num++; // needs one more because first line is description string
    00178   } else {
    00179     for (const Vehicle *v = GetVehicle(veh_id) ; v != NULL ; v = v->Next()) {
    00180       if (!IsArticulatedPart(v) || v->cargo_cap != 0) num++;
    00181     }
    00182   }
    00183
    00184   return num;
    00185 }
    00186
    00187 void DrawTrainDetails(const Vehicle *v, int x, int y, int vscroll_pos, uint16 vscroll_cap, byte det_tab)
    00188 {
    00189   /* draw the first 3 details tabs */
    00190   if (det_tab != 3) {
    00191     const Vehicle *u = v;
    00192     x = 1;
    00193     for (;;) {
    00194       if (--vscroll_pos < 0 && vscroll_pos >= -vscroll_cap) {
    00195         int dx = 0;
    00196         int px;
    00197         int py;
    00198
    00199         u = v;
    00200         do {
    00201           SpriteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
    00202           DrawSprite(u->GetImage(DIR_W), pal, x + WagonLengthToPixels(4 + dx), y + 6 + (is_custom_sprite(RailVehInfo(u->engine_type)->image_index) ? _traininfo_vehicle_pitch : 0));
    00203           dx += u->u.rail.cached_veh_length;
    00204           u = u->Next();
    00205         } while (u != NULL && IsArticulatedPart(u) && u->cargo_cap == 0);
    00206
    00207         px = x + WagonLengthToPixels(dx) + 2;
    00208         py = y + 2;
    00209         switch (det_tab) {
    00210           default: NOT_REACHED();
    00211           case 0: TrainDetailsCargoTab(   v, px, py); break;
    00212           case 1:
    00213             /* Only show name and value for the 'real' part */
    00214             if (!IsArticulatedPart(v)) {
    00215               TrainDetailsInfoTab(v, px, py);
    00216             }
    00217             break;
    00218           case 2: TrainDetailsCapacityTab(v, px, py); break;
    00219         }
    00220         y += 14;
    00221
    00222         v = u;
    00223       } else {
    00224         /* Move to the next line */
    00225         do {
    00226           v = v->Next();
    00227         } while (v != NULL && IsArticulatedPart(v) && v->cargo_cap == 0);
    00228       }
    00229       if (v == NULL) return;
    00230     }
    00231   } else {
    00232     AcceptedCargo act_cargo;
    00233     AcceptedCargo max_cargo;
    00234     Money         feeder_share = 0;
    00235
    00236     memset(max_cargo, 0, sizeof(max_cargo));
    00237     memset(act_cargo, 0, sizeof(act_cargo));
    00238
    00239     for (const Vehicle *u = v; u != NULL ; u = u->Next()) {
    00240       act_cargo[u->cargo_type] += u->cargo.Count();
    00241       max_cargo[u->cargo_type] += u->cargo_cap;
    00242       feeder_share             += u->cargo.FeederShare();
    00243     }
    00244
    00245     /* draw total cargo tab */
    00246     DrawString(x, y + 2, STR_TOTAL_CAPACITY_TEXT, TC_FROMSTRING);
    00247     for (CargoID i = 0; i < NUM_CARGO; i++) {
    00248       if (max_cargo[i] > 0 && --vscroll_pos < 0 && vscroll_pos > -vscroll_cap) {
    00249         y += 14;
    00250         SetDParam(0, i);            // {CARGO} #1
    00251         SetDParam(1, act_cargo[i]); // {CARGO} #2
    00252         SetDParam(2, i);            // {SHORTCARGO} #1
    00253         SetDParam(3, max_cargo[i]); // {SHORTCARGO} #2
    00254         SetDParam(4, _patches.freight_trains);
    00255         DrawString(x, y + 2, FreightWagonMult(i) > 1 ? STR_TOTAL_CAPACITY_MULT : STR_TOTAL_CAPACITY, TC_FROMSTRING);
    00256       }
    00257     }
    00258     SetDParam(0, feeder_share);
    00259     DrawString(x, y + 15, STR_FEEDER_CARGO_VALUE, TC_FROMSTRING);
    00260   }
    00261 }