summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lang/english.txt6
-rw-r--r--train_gui.c231
-rw-r--r--window.h5
3 files changed, 165 insertions, 77 deletions
diff --git a/lang/english.txt b/lang/english.txt
index 4a9f6bd8c..9e3fff998 100644
--- a/lang/english.txt
+++ b/lang/english.txt
@@ -2557,6 +2557,12 @@ STR_8840_BUILD_NEW_TRAIN_VEHICLE :{BLACK}Build ne
STR_8841_DRAG_TRAIN_VEHICLE_TO_HERE :{BLACK}Drag train vehicle to here to sell it
STR_8842_CENTER_MAIN_VIEW_ON_TRAIN :{BLACK}Centre main view on train depot location
STR_8843_TRAIN_VEHICLE_SELECTION :{BLACK}Train vehicle selection list - click on vehicle for information
+STR_BLACK_ENGINES :{BLACK}Engines
+STR_BLACK_WAGONS :{BLACK}Wagons
+STR_BLACK_BOTH :{BLACK}Both
+STR_BUILD_TRAIN_ENGINES_TIP :{BLACK}Click to see engines only
+STR_BUILD_TRAIN_WAGONS_TIP :{BLACK}Click to see wagons only
+STR_BUILD_TRAIN_BOTH_TIP :{BLACK}Click to see both engines and wagons
STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN :{BLACK}Build the highlighted train vehicle
STR_8845_RENAME_TRAIN_VEHICLE_TYPE :{BLACK}Rename train vehicle type
STR_8846_CURRENT_TRAIN_ACTION_CLICK :{BLACK}Current train action - click here to stop/start train
diff --git a/train_gui.c b/train_gui.c
index ae967b00c..f290df9ed 100644
--- a/train_gui.c
+++ b/train_gui.c
@@ -29,11 +29,29 @@ typedef enum BuildTrainWidgets {
BUILD_TRAIN_WIDGET_LIST,
BUILD_TRAIN_WIDGET_SCROLLBAR,
BUILD_TRAIN_WIDGET_PANEL,
+ BUILD_TRAIN_WIDGET_ENGINES,
+ BUILD_TRAIN_WIDGET_WAGONS,
+ BUILD_TRAIN_WIDGET_BOTH,
BUILD_TRAIN_WIDGET_BUILD,
BUILD_TRAIN_WIDGET_RENAME,
BUILD_TRAIN_WIDGET_RESIZE,
} BuildTrainWidget;
+static const Widget _new_rail_vehicle_widgets[] = {
+ { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
+ { WWT_CAPTION, RESIZE_NONE, 14, 11, 227, 0, 13, STR_JUST_STRING, STR_018C_WINDOW_TITLE_DRAG_THIS},
+ { WWT_MATRIX, RESIZE_BOTTOM, 14, 0, 215, 14, 125, 0x801, STR_8843_TRAIN_VEHICLE_SELECTION},
+ { WWT_SCROLLBAR, RESIZE_BOTTOM, 14, 216, 227, 14, 125, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
+ { WWT_PANEL, RESIZE_TB, 14, 0, 227, 126, 197, 0x0, STR_NULL},
+ { WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 76, 198, 209, STR_BLACK_ENGINES, STR_BUILD_TRAIN_ENGINES_TIP},
+ { WWT_PUSHTXTBTN, RESIZE_TB, 14, 77, 151, 198, 209, STR_BLACK_WAGONS, STR_BUILD_TRAIN_WAGONS_TIP},
+ { WWT_PUSHTXTBTN, RESIZE_TB, 14, 152, 227, 198, 209, STR_BLACK_BOTH, STR_BUILD_TRAIN_BOTH_TIP},
+ { WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 107, 210, 221, STR_881F_BUILD_VEHICLE, STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN},
+ { WWT_PUSHTXTBTN, RESIZE_TB, 14, 108, 215, 210, 221, STR_8820_RENAME, STR_8845_RENAME_TRAIN_VEHICLE_TYPE},
+ { WWT_RESIZEBOX, RESIZE_TB, 14, 216, 227, 210, 221, 0x0, STR_RESIZE_BUTTON},
+ { WIDGETS_END},
+};
+
/**
* Draw the purchase info details of train engine at a given location.
@@ -187,99 +205,170 @@ void CcCloneTrain(bool success, TileIndex tile, uint32 p1, uint32 p2)
{
if (success) ShowTrainViewWindow(GetVehicle(_new_vehicle_id));
}
+static void engine_drawing_loop(const EngineID *engines, const uint16 engine_count,
+ const int x, int *y, const EngineID sel, EngineID *position, const int16 show_max)
+{
+ for (; (*position) < min(engine_count, show_max); (*position)++) {
+ EngineID i = engines[*position];
+
+ DrawString(x + 59, *y + 2, GetCustomEngineName(i), sel == i ? 0xC : 0x10);
+ DrawTrainEngine(x + 29, *y + 6, i, GetEnginePalette(i, _local_player));
+ *y += 14;
+ }
+}
-static void engine_drawing_loop(int *x, int *y, int *pos, int *sel,
- EngineID *selected_id, RailType railtype, byte show_max, bool is_engine)
+static inline void ExtendEngineListSize(const EngineID **engine_list, uint16 *engine_list_length, uint16 step_size)
{
+ *engine_list_length = min(*engine_list_length + step_size, NUM_TRAIN_ENGINES);
+ *engine_list = realloc((void*)*engine_list, (*engine_list_length) * sizeof((*engine_list)[0]));
+}
+
+static void GenerateBuildList(EngineID **engines, uint16 *num_engines, EngineID **wagons, uint16 *num_wagons, RailType railtype)
+{
+ uint16 engine_length = *num_engines;
+ uint16 wagon_length = *num_wagons;
EngineID j;
+ (*num_engines) = 0;
+ (*num_wagons) = 0;
+
+ if (engines == NULL) ExtendEngineListSize((const EngineID**)engines, &engine_length, 25);
+ if (wagons == NULL) ExtendEngineListSize((const EngineID**)wagons, &wagon_length, 25);
+
for (j = 0; j < NUM_TRAIN_ENGINES; j++) {
EngineID i = GetRailVehAtPosition(j);
const Engine *e = GetEngine(i);
const RailVehicleInfo *rvi = RailVehInfo(i);
- if (!HasPowerOnRail(e->railtype, railtype) || !(rvi->flags & RVI_WAGON) != is_engine ||
- !HASBIT(e->player_avail, _local_player))
- continue;
+ if (!HasPowerOnRail(e->railtype, railtype)) continue;
+ if (!IsEngineBuildable(i, VEH_Train)) continue;
+
+ if (rvi->flags & RVI_WAGON) {
+ if (*num_wagons == wagon_length) ExtendEngineListSize((const EngineID**)wagons, &wagon_length, 5);
+ (*wagons)[(*num_wagons)++] = i;
+ } else {
+ if (*num_engines == engine_length) ExtendEngineListSize((const EngineID**)engines, &engine_length, 5);
+ (*engines)[(*num_engines)++] = i;
+ }
+ }
+
+ /* Reduce array sizes if they are too big */
+ if (*num_engines == engine_length) *engines = realloc((void*)*engines, (*num_engines) * sizeof((*engines)[0]));
+ if (*num_wagons == wagon_length) *wagons = realloc((void*)*wagons, (*num_wagons) * sizeof((*wagons)[0]));
+}
+
+static void DrawTrainBuildWindow(Window *w)
+{
+ int x = 1;
+ int y = 15;
+ EngineID position = w->vscroll.pos;
+ EngineID selected_id = WP(w,buildtrain_d).sel_engine;
+ int max = w->vscroll.pos + w->vscroll.cap;
+ uint16 scrollcount = 0;
+
+ SetWindowWidgetDisabledState(w, BUILD_TRAIN_WIDGET_BUILD, w->window_number == 0); // Disable unless we got a depot to build in
+
+ /* Draw the clicked engine/wagon/both button pressed and unpress the other two */
+ SetWindowWidgetLoweredState(w, BUILD_TRAIN_WIDGET_ENGINES, WP(w,buildtrain_d).show_engine_wagon == 1);
+ SetWindowWidgetLoweredState(w, BUILD_TRAIN_WIDGET_WAGONS, WP(w,buildtrain_d).show_engine_wagon == 2);
+ SetWindowWidgetLoweredState(w, BUILD_TRAIN_WIDGET_BOTH, WP(w,buildtrain_d).show_engine_wagon == 3);
+
+ GenerateBuildList(&WP(w,buildtrain_d).engines, &WP(w,buildtrain_d).num_engines, &WP(w,buildtrain_d).wagons, &WP(w,buildtrain_d).num_wagons, WP(w,buildtrain_d).railtype);
+
+ if (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0)) scrollcount += WP(w,buildtrain_d).num_engines;
+ if (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 1)) scrollcount += WP(w,buildtrain_d).num_wagons;
+
+ SetVScrollCount(w, scrollcount);
+ SetDParam(0, WP(w,buildtrain_d).railtype + STR_881C_NEW_RAIL_VEHICLES);
+ DrawWindowWidgets(w);
+
+ if (selected_id == INVALID_ENGINE && scrollcount != 0) {
+ if (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0) && WP(w,buildtrain_d).num_engines != 0) {
+ selected_id = WP(w,buildtrain_d).engines[0];
+ } else {
+ selected_id = WP(w,buildtrain_d).wagons[0];
+ }
+ WP(w,buildtrain_d).sel_engine = selected_id;
+ }
+
+ /* Draw the engines */
+ if (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0)) {
+ engine_drawing_loop(WP(w,buildtrain_d).engines, WP(w,buildtrain_d).num_engines, x, &y, selected_id, &position, max);
+
+ /* Magically set the number 0 line to the one right after the last engine
+ * This way the line numbers fit the indexes in the wagon array */
+ position -= WP(w,buildtrain_d).num_engines;
+ max -= WP(w,buildtrain_d).num_engines;
+ }
+
+ /* Draw the wagons */
+ if (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 1)) {
+ engine_drawing_loop(WP(w,buildtrain_d).wagons, WP(w,buildtrain_d).num_wagons, x, &y, selected_id, &position, max);
+ }
- if (*sel == 0) *selected_id = i;
+ if (selected_id != INVALID_ENGINE) {
+ const RailVehicleInfo *rvi = RailVehInfo(selected_id);
- if (IS_INT_INSIDE(--*pos, -show_max, 0)) {
- DrawString(*x + 59, *y + 2, GetCustomEngineName(i), *sel == 0 ? 0xC : 0x10);
- DrawTrainEngine(*x + 29, *y + 6, i, GetEnginePalette(i, _local_player));
- *y += 14;
+ if (rvi->flags & RVI_WAGON) {
+ DrawTrainWagonPurchaseInfo(2, w->widget[BUILD_TRAIN_WIDGET_PANEL].top + 1, selected_id);
+ } else {
+ DrawTrainEnginePurchaseInfo(2, w->widget[BUILD_TRAIN_WIDGET_PANEL].top + 1, selected_id);
}
- --*sel;
}
}
static void NewRailVehicleWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
- case WE_PAINT:
-
- SetWindowWidgetDisabledState(w, BUILD_TRAIN_WIDGET_BUILD, w->window_number == 0);
+ case WE_CREATE:
+ WP(w,buildtrain_d).num_engines = 0;
+ WP(w,buildtrain_d).num_wagons = 0;
+ WP(w,buildtrain_d).engines = NULL;
+ WP(w,buildtrain_d).wagons = NULL;
+ WP(w,buildtrain_d).show_engine_wagon = 3;
+ break;
- {
- int count = 0;
- RailType railtype = WP(w,buildtrain_d).railtype;
- EngineID i;
+ case WE_DESTROY:
+ free((void*)WP(w,buildtrain_d).engines);
+ free((void*)WP(w,buildtrain_d).wagons);
+ break;
- for (i = 0; i < NUM_TRAIN_ENGINES; i++) {
- const Engine *e = GetEngine(i);
- if (HasPowerOnRail(e->railtype, railtype) &&
- HASBIT(e->player_avail, _local_player)) {
- count++;
- }
- }
- SetVScrollCount(w, count);
- }
+ case WE_PAINT:
+ DrawTrainBuildWindow(w);
+ break;
- SetDParam(0, WP(w,buildtrain_d).railtype + STR_881C_NEW_RAIL_VEHICLES);
- DrawWindowWidgets(w);
-
- {
- RailType railtype = WP(w,buildtrain_d).railtype;
- int sel = WP(w,buildtrain_d).sel_index;
- int pos = w->vscroll.pos;
- int x = 1;
- int y = 15;
- EngineID selected_id = INVALID_ENGINE;
-
- /* Ensure that custom engines which substituted wagons
- * are sorted correctly.
- * XXX - DO NOT EVER DO THIS EVER AGAIN! GRRR hacking in wagons as
- * engines to get more types.. Stays here until we have our own format
- * then it is exit!!! */
- engine_drawing_loop(&x, &y, &pos, &sel, &selected_id, railtype, w->vscroll.cap, true); // True engines
- engine_drawing_loop(&x, &y, &pos, &sel, &selected_id, railtype, w->vscroll.cap, false); // Feeble wagons
-
- WP(w,buildtrain_d).sel_engine = selected_id;
-
- if (selected_id != INVALID_ENGINE) {
- const RailVehicleInfo *rvi = RailVehInfo(selected_id);
-
- if (!(rvi->flags & RVI_WAGON)) {
- /* it's an engine */
- DrawTrainEnginePurchaseInfo(2, w->widget[BUILD_TRAIN_WIDGET_PANEL].top + 1,selected_id);
- } else {
- /* it's a wagon */
- DrawTrainWagonPurchaseInfo(2, w->widget[BUILD_TRAIN_WIDGET_PANEL].top + 1, selected_id);
- }
- }
- }
- break;
case WE_CLICK: {
switch (e->we.click.widget) {
case BUILD_TRAIN_WIDGET_LIST: {
- uint i = (e->we.click.pt.y - 14) / 14;
- if (i < w->vscroll.cap) {
- WP(w,buildtrain_d).sel_index = i + w->vscroll.pos;
+ uint i = ((e->we.click.pt.y - 14) / 14) + w->vscroll.pos;
+ if (i < WP(w,buildtrain_d).num_engines + WP(w,buildtrain_d).num_wagons) {
+ if (i < WP(w,buildtrain_d).num_engines && HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0)) {
+ WP(w,buildtrain_d).sel_engine = WP(w,buildtrain_d).engines[i];
+ } else {
+ WP(w,buildtrain_d).sel_engine = WP(w,buildtrain_d).wagons[i - (HASBIT(WP(w,buildtrain_d).show_engine_wagon, 0) ? WP(w,buildtrain_d).num_engines : 0)];
+ }
SetWindowDirty(w);
}
} break;
+ case BUILD_TRAIN_WIDGET_ENGINES:
+ case BUILD_TRAIN_WIDGET_WAGONS:
+ case BUILD_TRAIN_WIDGET_BOTH: {
+ /* First we need to figure out the new show_engine_wagon setting
+ * Because the button widgets are ordered as they are (in a row), we can calculate as following:
+ * engines = bit 0 (1 for set), wagons bit 1 (2 for set), both (2 | 1 = 3)
+ * Those numbers are the same as the clicked button - BUILD_TRAIN_WIDGET_ENGINES + 1 */
+
+ byte click_state = e->we.click.widget - BUILD_TRAIN_WIDGET_ENGINES + 1;
+ if (WP(w,buildtrain_d).show_engine_wagon == click_state) break; // We clicked the pressed button
+ WP(w,buildtrain_d).sel_engine = INVALID_ENGINE;
+ WP(w,buildtrain_d).show_engine_wagon = click_state;
+ w->vscroll.pos = 0;
+ SetWindowDirty(w);
+ }
+ break;
+
case BUILD_TRAIN_WIDGET_BUILD: {
EngineID sel_eng = WP(w,buildtrain_d).sel_engine;
if (sel_eng != INVALID_ENGINE)
@@ -314,20 +403,8 @@ static void NewRailVehicleWndProc(Window *w, WindowEvent *e)
}
}
-static const Widget _new_rail_vehicle_widgets[] = {
-{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, RESIZE_NONE, 14, 11, 227, 0, 13, STR_JUST_STRING, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_MATRIX, RESIZE_BOTTOM, 14, 0, 215, 14, 125, 0x801, STR_8843_TRAIN_VEHICLE_SELECTION},
-{ WWT_SCROLLBAR, RESIZE_BOTTOM, 14, 216, 227, 14, 125, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-{ WWT_PANEL, RESIZE_TB, 14, 0, 227, 126, 197, 0x0, STR_NULL},
-{ WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 107, 198, 209, STR_881F_BUILD_VEHICLE, STR_8844_BUILD_THE_HIGHLIGHTED_TRAIN},
-{ WWT_PUSHTXTBTN, RESIZE_TB, 14, 108, 215, 198, 209, STR_8820_RENAME, STR_8845_RENAME_TRAIN_VEHICLE_TYPE},
-{ WWT_RESIZEBOX, RESIZE_TB, 14, 216, 227, 198, 209, 0x0, STR_RESIZE_BUTTON},
-{ WIDGETS_END},
-};
-
static const WindowDesc _new_rail_vehicle_desc = {
- -1, -1, 228, 210,
+ -1, -1, 228, 222,
WC_BUILD_VEHICLE,0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
_new_rail_vehicle_widgets,
diff --git a/window.h b/window.h
index 47faf3b66..e7a116e63 100644
--- a/window.h
+++ b/window.h
@@ -393,8 +393,13 @@ assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(tooltips_d));
typedef struct {
byte railtype;
byte sel_index;
+ byte show_engine_wagon;
EngineID sel_engine;
EngineID rename_engine;
+ EngineID *engines;
+ EngineID *wagons;
+ uint16 num_engines;
+ uint16 num_wagons;
} buildtrain_d;
assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(buildtrain_d));