# engine_gui.cpp

Go to the documentation of this file.

    00001 /* $Id: engine_gui.cpp 15723 2009-03-15 15:12:06Z rubidium $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "window_gui.h"
    00007 #include "gfx_func.h"
    00008 #include "engine_func.h"
    00009 #include "engine_base.h"
    00010 #include "command_func.h"
    00011 #include "news_type.h"
    00012 #include "newgrf_engine.h"
    00013 #include "strings_func.h"
    00014 #include "engine_gui.h"
    00015 #include "articulated_vehicles.h"
    00016 #include "rail.h"
    00017 #include "aircraft.h"
    00018
    00019 #include "table/strings.h"
    00020 #include "table/sprites.h"
    00021
    00022 StringID GetEngineCategoryName(EngineID engine)
    00023 {
    00024   switch (GetEngine(engine)->type) {
    00025     default: NOT_REACHED();
    00026     case VEH_ROAD:              return STR_8103_ROAD_VEHICLE;
    00027     case VEH_AIRCRAFT:          return STR_8104_AIRCRAFT;
    00028     case VEH_SHIP:              return STR_8105_SHIP;
    00029     case VEH_TRAIN:
    00030       return GetRailTypeInfo(RailVehInfo(engine)->railtype)->strings.new_loco;
    00031   }
    00032 }
    00033
    00034 static const Widget _engine_preview_widgets[] = {
    00035 {   WWT_CLOSEBOX,  RESIZE_NONE,  COLOUR_LIGHT_BLUE,    0,   10,    0,   13, STR_00C5,                                  STR_018B_CLOSE_WINDOW},
    00036 {    WWT_CAPTION,  RESIZE_NONE,  COLOUR_LIGHT_BLUE,   11,  299,    0,   13, STR_8100_MESSAGE_FROM_VEHICLE_MANUFACTURE, STR_018C_WINDOW_TITLE_DRAG_THIS},
    00037 {      WWT_PANEL,  RESIZE_NONE,  COLOUR_LIGHT_BLUE,    0,  299,   14,  191, 0x0,                                       STR_NULL},
    00038 { WWT_PUSHTXTBTN,  RESIZE_NONE,  COLOUR_LIGHT_BLUE,   85,  144,  172,  183, STR_00C9_NO,                               STR_NULL},
    00039 { WWT_PUSHTXTBTN,  RESIZE_NONE,  COLOUR_LIGHT_BLUE,  155,  214,  172,  183, STR_00C8_YES,                              STR_NULL},
    00040 {   WIDGETS_END},
    00041 };
    00042
    00043 typedef void DrawEngineProc(int x, int y, EngineID engine, SpriteID pal);
    00044 typedef void DrawEngineInfoProc(EngineID, int x, int y, int maxw);
    00045
    00046 struct DrawEngineInfo {
    00047   DrawEngineProc *engine_proc;
    00048   DrawEngineInfoProc *info_proc;
    00049 };
    00050
    00051 static void DrawTrainEngineInfo(EngineID engine, int x, int y, int maxw);
    00052 static void DrawRoadVehEngineInfo(EngineID engine, int x, int y, int maxw);
    00053 static void DrawShipEngineInfo(EngineID engine, int x, int y, int maxw);
    00054 static void DrawAircraftEngineInfo(EngineID engine, int x, int y, int maxw);
    00055
    00056 static const DrawEngineInfo _draw_engine_list[4] = {
    00057   { DrawTrainEngine,    DrawTrainEngineInfo    },
    00058   { DrawRoadVehEngine,  DrawRoadVehEngineInfo  },
    00059   { DrawShipEngine,     DrawShipEngineInfo     },
    00060   { DrawAircraftEngine, DrawAircraftEngineInfo },
    00061 };
    00062
    00063 struct EnginePreviewWindow : Window {
    00064   EnginePreviewWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
    00065   {
    00066     this->FindWindowPlacementAndResize(desc);
    00067   }
    00068
    00069   virtual void OnPaint()
    00070   {
    00071     this->DrawWidgets();
    00072
    00073     EngineID engine = this->window_number;
    00074     SetDParam(0, GetEngineCategoryName(engine));
    00075     DrawStringMultiCenter(150, 44, STR_8101_WE_HAVE_JUST_DESIGNED_A, 296);
    00076
    00077     SetDParam(0, engine);
    00078     DrawStringCentered(this->width >> 1, 80, STR_ENGINE_NAME, TC_BLACK);
    00079
    00080     const DrawEngineInfo *dei = &_draw_engine_list[GetEngine(engine)->type];
    00081
    00082     int width = this->width;
    00083     dei->engine_proc(width >> 1, 100, engine, 0);
    00084     dei->info_proc(engine, width >> 1, 130, width - 52);
    00085   }
    00086
    00087   virtual void OnClick(Point pt, int widget)
    00088   {
    00089     switch (widget) {
    00090       case 4:
    00091         DoCommandP(0, this->window_number, 0, CMD_WANT_ENGINE_PREVIEW);
    00092         /* Fallthrough */
    00093       case 3:
    00094         delete this;
    00095         break;
    00096     }
    00097   }
    00098 };
    00099
    00100 static const WindowDesc _engine_preview_desc(
    00101   WDP_CENTER, WDP_CENTER, 300, 192, 300, 192,
    00102   WC_ENGINE_PREVIEW, WC_NONE,
    00103   WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_CONSTRUCTION,
    00104   _engine_preview_widgets
    00105 );
    00106
    00107
    00108 void ShowEnginePreviewWindow(EngineID engine)
    00109 {
    00110   AllocateWindowDescFront<EnginePreviewWindow>(&_engine_preview_desc, engine);
    00111 }
    00112
    00113 uint GetTotalCapacityOfArticulatedParts(EngineID engine, VehicleType type)
    00114 {
    00115   uint total = 0;
    00116
    00117   uint16 *cap = GetCapacityOfArticulatedParts(engine, type);
    00118   for (uint c = 0; c < NUM_CARGO; c++) {
    00119     total += cap[c];
    00120   }
    00121
    00122   return total;
    00123 }
    00124
    00125 static void DrawTrainEngineInfo(EngineID engine, int x, int y, int maxw)
    00126 {
    00127   const Engine *e = GetEngine(engine);
    00128
    00129   SetDParam(0, e->GetCost());
    00130   SetDParam(2, e->GetDisplayMaxSpeed());
    00131   SetDParam(3, e->GetPower());
    00132   SetDParam(1, e->GetDisplayWeight());
    00133
    00134   SetDParam(4, e->GetRunningCost());
    00135
    00136   uint capacity = GetTotalCapacityOfArticulatedParts(engine, VEH_TRAIN);
    00137   if (capacity != 0) {
    00138     SetDParam(5, e->GetDefaultCargoType());
    00139     SetDParam(6, capacity);
    00140   } else {
    00141     SetDParam(5, CT_INVALID);
    00142   }
    00143   DrawStringMultiCenter(x, y, STR_VEHICLE_INFO_COST_WEIGHT_SPEED_POWER, maxw);
    00144 }
    00145
    00146 static void DrawAircraftEngineInfo(EngineID engine, int x, int y, int maxw)
    00147 {
    00148   const Engine *e = GetEngine(engine);
    00149   CargoID cargo = e->GetDefaultCargoType();
    00150
    00151   if (cargo == CT_INVALID || cargo == CT_PASSENGERS) {
    00152     SetDParam(0, e->GetCost());
    00153     SetDParam(1, e->GetDisplayMaxSpeed());
    00154     SetDParam(2, e->u.air.passenger_capacity);
    00155     SetDParam(3, e->u.air.mail_capacity);
    00156     SetDParam(4, e->GetRunningCost());
    00157
    00158     DrawStringMultiCenter(x, y, STR_A02E_COST_MAX_SPEED_CAPACITY, maxw);
    00159   } else {
    00160     SetDParam(0, e->GetCost());
    00161     SetDParam(1, e->GetDisplayMaxSpeed());
    00162     SetDParam(2, cargo);
    00163     SetDParam(3, AircraftDefaultCargoCapacity(cargo, &e->u.air));
    00164     SetDParam(4, e->GetRunningCost());
    00165
    00166     DrawStringMultiCenter(x, y, STR_982E_COST_MAX_SPEED_CAPACITY, maxw);
    00167   }
    00168 }
    00169
    00170 static void DrawRoadVehEngineInfo(EngineID engine, int x, int y, int maxw)
    00171 {
    00172   const Engine *e = GetEngine(engine);
    00173
    00174   SetDParam(0, e->GetCost());
    00175   SetDParam(1, e->GetDisplayMaxSpeed());
    00176   SetDParam(2, e->GetRunningCost());
    00177   uint capacity = GetTotalCapacityOfArticulatedParts(engine, VEH_ROAD);
    00178   if (capacity != 0) {
    00179     SetDParam(3, e->GetDefaultCargoType());
    00180     SetDParam(4, capacity);
    00181   } else {
    00182     SetDParam(3, CT_INVALID);
    00183   }
    00184
    00185   DrawStringMultiCenter(x, y, STR_902A_COST_SPEED_RUNNING_COST, maxw);
    00186 }
    00187
    00188 static void DrawShipEngineInfo(EngineID engine, int x, int y, int maxw)
    00189 {
    00190   const ShipVehicleInfo *svi = ShipVehInfo(engine);
    00191   const Engine *e = GetEngine(engine);
    00192
    00193   SetDParam(0, e->GetCost());
    00194   SetDParam(1, e->GetDisplayMaxSpeed());
    00195   SetDParam(2, e->GetDefaultCargoType());
    00196   SetDParam(3, GetEngineProperty(engine, 0x0D, svi->capacity));
    00197   SetDParam(4, e->GetRunningCost());
    00198   DrawStringMultiCenter(x, y, STR_982E_COST_MAX_SPEED_CAPACITY, maxw);
    00199 }
    00200
    00201 void DrawNewsNewVehicleAvail(Window *w, const NewsItem *ni)
    00202 {
    00203   EngineID engine = ni->data_a;
    00204   const DrawEngineInfo *dei = &_draw_engine_list[GetEngine(engine)->type];
    00205
    00206   SetDParam(0, GetEngineCategoryName(engine));
    00207   DrawStringMultiCenter(w->width >> 1, 20, STR_NEW_VEHICLE_NOW_AVAILABLE, w->width - 2);
    00208
    00209   GfxFillRect(25, 56, w->width - 25, w->height - 2, 10);
    00210
    00211   SetDParam(0, engine);
    00212   DrawStringMultiCenter(w->width >> 1, 57, STR_NEW_VEHICLE_TYPE, w->width - 2);
    00213
    00214   dei->engine_proc(w->width >> 1, 88, engine, 0);
    00215   GfxFillRect(25, 56, w->width - 56, 112, PALETTE_TO_STRUCT_GREY, FILLRECT_RECOLOUR);
    00216   dei->info_proc(engine, w->width >> 1, 129, w->width - 52);
    00217 }
    00218
    00219
    00224 void EngList_Sort(GUIEngineList *el, EngList_SortTypeFunction compare)
    00225 {
    00226   uint size = el->Length();
    00227   /* out-of-bounds access at the next line for size == 0 (even with operator[] at some systems)
    00228    * generally, do not sort if there are less than 2 items */
    00229   if (size < 2) return;
    00230   qsort(el->Begin(), size, sizeof(*el->Begin()), compare); // MorphOS doesn't know vector::at(int) ...
    00231 }
    00232
    00239 void EngList_SortPartial(GUIEngineList *el, EngList_SortTypeFunction compare, uint begin, uint num_items)
    00240 {
    00241   if (num_items < 2) return;
    00242   assert(begin < el->Length());
    00243   assert(begin + num_items <= el->Length());
    00244   qsort(el->Get(begin), num_items, sizeof(*el->Begin()), compare);
    00245 }
    00246