From 5b0915e67774c9e8ac84d192cf6bd409286166ec Mon Sep 17 00:00:00 2001 From: tron Date: Fri, 10 Dec 2004 18:16:08 +0000 Subject: (svn r1009) -Feature: per-station vehicle lists This adds a little button per vehicle class to the station window which opens a list of all vehicles that have this station on their schedule. As side effect this gets rid of some global variables. --- train_gui.c | 288 ++++++++++++++++++++++++------------------------------------ 1 file changed, 117 insertions(+), 171 deletions(-) (limited to 'train_gui.c') diff --git a/train_gui.c b/train_gui.c index 79ba7d27f..e05778ea9 100644 --- a/train_gui.c +++ b/train_gui.c @@ -10,6 +10,7 @@ #include "command.h" #include "player.h" #include "engine.h" +#include "vehicle_gui.h" int _traininfo_vehicle_pitch = 0; @@ -39,7 +40,7 @@ void CcBuildWagon(bool success, uint tile, uint32 p1, uint32 p2) found = GetLastVehicleInChain(found); // put the new wagon at the end of the loco. DoCommandP(0, _new_wagon_id | (found->index<<16), 0, NULL, CMD_MOVE_RAIL_VEHICLE); - _vehicle_sort_dirty[VEHTRAIN] = true; + RebuildVehicleLists(); } } @@ -1166,155 +1167,125 @@ void ShowTrainDetailsWindow(Vehicle *v) WP(w,traindetails_d).tab = 0; } -// used to get a sorted list of the vehicles -static SortStruct _train_sort[NUM_NORMAL_VEHICLES]; -static uint16 _num_train_sort[MAX_PLAYERS]; -static void GlobalSortTrainList() -{ - const Vehicle *v; - uint16 *i; - uint32 n = 0; - - // reset #-of trains to 0 because ++ is used for value-assignment - for (i = _num_train_sort; i != endof(_num_train_sort); i++) {*i = 0;} - - FOR_ALL_VEHICLES(v) { - if(v->type == VEH_Train && v->subtype == 0) { - _train_sort[n].index = v->index; - _train_sort[n++].owner = v->owner; - _num_train_sort[v->owner]++; // add number of trains of player - } - } - - // create cumulative train-ownership - // trains are stored as a cummulative index, eg 25, 41, 43. This means - // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 - for (i = &_num_train_sort[1]; i != endof(_num_train_sort); i++) {*i += *(i-1);} - - qsort(_train_sort, n, sizeof(_train_sort[0]), GeneralOwnerSorter); // sort by owner - - // since indexes are messed up after adding/removing a station, mark all lists dirty - memset(_train_sort_dirty, true, sizeof(_train_sort_dirty)); - _vehicle_sort_dirty[VEHTRAIN] = false; - - DEBUG(misc, 1) ("Resorting global trains list..."); -} - -static void MakeSortedTrainList(byte owner) -{ - SortStruct *firstelement; - uint32 n = 0; - - if (owner == 0) { // first element starts at 0th element and has n elements as described above - firstelement = &_train_sort[0]; - n = _num_train_sort[0]; - } else { // nth element starts at the end of the previous one, and has n elements as described above - firstelement = &_train_sort[_num_train_sort[owner-1]]; - n = _num_train_sort[owner] - _num_train_sort[owner-1]; - } - - _internal_sort_order = _train_sort_order[owner]; - _internal_name_sorter_id = STR_SV_TRAIN_NAME; - _last_vehicle_idx = 0; // used for "cache" in namesorting - qsort(firstelement, n, sizeof(_train_sort[0]), _vehicle_sorter[_train_sort_type[owner]]); - - _train_sort_dirty[owner] = false; +static Widget _player_trains_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 324, 0, 13, STR_881B_TRAINS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, +{ WWT_PANEL, 14, 81, 232, 14, 25, 0x0, STR_SORT_TIP}, +{ WWT_CLOSEBOX, 14, 233, 243, 14, 25, STR_0225, STR_SORT_TIP}, +{ WWT_PANEL, 14, 244, 324, 14, 25, 0x0, STR_NULL}, +{ WWT_MATRIX, 14, 0, 313, 26, 207, 0x701, STR_883D_TRAINS_CLICK_ON_TRAIN_FOR}, +{ WWT_SCROLLBAR, 14, 314, 324, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PUSHTXTBTN, 14, 0, 161, 208, 219, STR_8815_NEW_VEHICLES, STR_883E_BUILD_NEW_TRAINS_REQUIRES}, +{ WWT_PANEL, 14, 162, 324, 208, 219, 0x0, STR_NULL}, +{ WIDGETS_END}, +}; - DEBUG(misc, 1) ("Resorting Trains list player %d...", owner+1); -} +static Widget _other_player_trains_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 324, 0, 13, STR_881B_TRAINS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, +{ WWT_PANEL, 14, 81, 232, 14, 25, 0x0, STR_SORT_TIP}, +{ WWT_CLOSEBOX, 14, 233, 243, 14, 25, STR_0225, STR_SORT_TIP}, +{ WWT_PANEL, 14, 244, 324, 14, 25, 0x0, STR_NULL}, +{ WWT_MATRIX, 14, 0, 313, 26, 207, 0x701, STR_883D_TRAINS_CLICK_ON_TRAIN_FOR}, +{ WWT_SCROLLBAR, 14, 314, 324, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WIDGETS_END}, +}; static void PlayerTrainsWndProc(Window *w, WindowEvent *e) { + int station = (int)w->window_number >> 16; + int owner = w->window_number & 0xff; + vehiclelist_d *vl = &WP(w, vehiclelist_d); + switch(e->event) { case WE_PAINT: { - uint32 i; - const byte window_number = (byte)w->window_number; - - if (_train_sort_type[window_number] == SORT_BY_UNSORTED) // disable 'Sort By' tooltip on Unsorted sorting criteria - w->disabled_state |= (1 << 2); + int x = 2; + int y = PLY_WND_PRC__OFFSET_TOP_WIDGET; + int max; + int i; - // resort trains window if roadvehicles have been added/removed - if (_vehicle_sort_dirty[VEHTRAIN]) - GlobalSortTrainList(); + BuildVehicleList(vl, VEH_Train, owner, station); + SortVehicleList(vl); - if (_train_sort_dirty[window_number]) { - MakeSortedTrainList(window_number); - /* reset sorting timeout */ - w->custom[0] = DAY_TICKS; - w->custom[1] = PERIODIC_RESORT_DAYS; - } + SetVScrollCount(w, vl->list_length); - // Trains are stored as a cummulative index, eg 25, 41, 43. This means - // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 trains - i = (window_number == 0) ? 0 : _num_train_sort[window_number-1]; - SetVScrollCount(w, _num_train_sort[window_number] - i); + // disable 'Sort By' tooltip on Unsorted sorting criteria + if (vl->sort_type == SORT_BY_UNSORTED) + w->disabled_state |= (1 << 2); /* draw the widgets */ { - Player *p = DEREF_PLAYER(window_number); - /* Company Name -- (###) Trains */ - SetDParam(0, p->name_1); - SetDParam(1, p->name_2); - SetDParam(2, w->vscroll.count); + const Player *p = DEREF_PLAYER(owner); + /* XXX hack */ + if (station == -1) { + /* Company Name -- (###) Trains */ + SetDParam(0, p->name_1); + SetDParam(1, p->name_2); + SetDParam(2, w->vscroll.count); + _player_trains_widgets[1].unkA = STR_881B_TRAINS; + _other_player_trains_widgets[1].unkA = STR_881B_TRAINS; + } else { + /* Station Name -- (###) Trains */ + SetDParam(0, DEREF_STATION(station)->index); + SetDParam(1, w->vscroll.count); + _player_trains_widgets[1].unkA = STR_SCHEDULED_TRAINS; + _other_player_trains_widgets[1].unkA = STR_SCHEDULED_TRAINS; + } DrawWindowWidgets(w); } /* draw sorting criteria string */ - DrawString(85, 15, _vehicle_sort_listing[_train_sort_type[window_number]], 0x10); - /* draw arrow pointing up/down for ascending/descending soring */ - DoDrawString(_train_sort_order[window_number] & 1 ? "\xAA" : "\xA0", 69, 15, 0x10); + DrawString(85, 15, _vehicle_sort_listing[vl->sort_type], 0x10); + /* draw arrow pointing up/down for ascending/descending sorting */ + DoDrawString( + vl->flags & VL_DESC ? "\xAA" : "\xA0", 69, 15, 0x10); - /* draw the trains */ - { - Vehicle *v; - int n = 0; - const int x = 2; // offset from left side of widget - int y = PLY_WND_PRC__OFFSET_TOP_WIDGET; // offset from top of widget - i += w->vscroll.pos; // offset from sorted trains list of current player + max = min(w->vscroll.pos + w->vscroll.cap, vl->list_length); + for (i = w->vscroll.pos; i < max; ++i) { + Vehicle *v = DEREF_VEHICLE(vl->sort_list[i].index); + StringID str; - while (i < _num_train_sort[window_number]) { - StringID str; - v = DEREF_VEHICLE(_train_sort[i].index); + assert(v->type == VEH_Train && v->owner == owner); - assert(v->type == VEH_Train && v->subtype == 0 && v->owner == window_number); + DrawTrainImage( + v, x + 21, y + 6 + _traininfo_vehicle_pitch, 10, 0, INVALID_VEHICLE); + DrawVehicleProfitButton(v, x, y + 13); - DrawTrainImage(v, x + 21, y + 6 + _traininfo_vehicle_pitch, 10, 0, INVALID_VEHICLE); - DrawVehicleProfitButton(v, x, y+13); - - SetDParam(0, v->unitnumber); - if (IsTrainDepotTile(v->tile)) { - str = STR_021F; - } else { - str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2; - } - DrawString(x, y+2, str, 0); - - SetDParam(0, v->profit_this_year); - SetDParam(1, v->profit_last_year); - DrawString(x + 21, y + 18, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0); - - if (v->string_id != STR_SV_TRAIN_NAME) { - SetDParam(0, v->string_id); - DrawString(x+21, y, STR_01AB, 0); - } - - y += PLY_WND_PRC__SIZE_OF_ROW_SMALL; - i++; // next train - if (++n == w->vscroll.cap) { break;} // max number of trains in the window + SetDParam(0, v->unitnumber); + if (IsTrainDepotTile(v->tile)) + str = STR_021F; + else + str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2; + DrawString(x, y + 2, str, 0); + + SetDParam(0, v->profit_this_year); + SetDParam(1, v->profit_last_year); + DrawString(x + 21, y + 18, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0); + + if (v->string_id != STR_SV_TRAIN_NAME) { + SetDParam(0, v->string_id); + DrawString(x + 21, y, STR_01AB, 0); } + + y += PLY_WND_PRC__SIZE_OF_ROW_SMALL; } - } break; + break; + } case WE_CLICK: { switch(e->click.widget) { case 2: /* Flip sorting method ascending/descending */ - _train_sort_order[(byte)w->window_number] ^= 1; - _train_sort_dirty[(byte)w->window_number] = true; + vl->flags ^= VL_DESC; + vl->flags |= VL_RESORT; SetWindowDirty(w); break; + case 3: case 4:/* Select sorting criteria dropdown menu */ - ShowDropDownMenu(w, _vehicle_sort_listing, _train_sort_type[(byte)w->window_number], 4, 0); // do it for widget 4 + ShowDropDownMenu(w, _vehicle_sort_listing, vl->sort_type, 4, 0); return; + case 6: { /* Matrix to show vehicles */ uint32 id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_SMALL; @@ -1323,13 +1294,11 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e) id_v += w->vscroll.pos; { - const byte owner = (byte)w->window_number; Vehicle *v; - id_v += (owner == 0) ? 0 : _num_train_sort[owner - 1]; // first element in list - if (id_v >= _num_train_sort[owner]) { return;} // click out of vehicle bound + if (id_v >= vl->list_length) return; // click out of list bound - v = DEREF_VEHICLE(_train_sort[id_v].index); // add the offset id_x to that + v = DEREF_VEHICLE(vl->sort_list[id_v].index); assert(v->type == VEH_Train && v->subtype == 0 && v->owner == owner); @@ -1357,48 +1326,37 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e) } break; case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */ - if (_train_sort_type[(byte)w->window_number] != e->dropdown.index) // if value hasn't changed, dont resort list - _train_sort_dirty[(byte)w->window_number] = true; - - _train_sort_type[(byte)w->window_number] = e->dropdown.index; - - if (_train_sort_type[(byte)w->window_number] != SORT_BY_UNSORTED) // enable 'Sort By' if a sorter criteria is chosen - w->disabled_state &= ~(1 << 2); - + if (vl->sort_type != e->dropdown.index) { + // value has changed -> resort + vl->flags |= VL_RESORT; + vl->sort_type = e->dropdown.index; + + // enable 'Sort By' if a sorter criteria is chosen + if (vl->sort_type != SORT_BY_UNSORTED) + w->disabled_state &= ~(1 << 2); + } SetWindowDirty(w); break; + case WE_CREATE: /* set up resort timer */ - w->custom[0] = DAY_TICKS; - w->custom[1] = PERIODIC_RESORT_DAYS; + vl->sort_list = NULL; + vl->flags = VL_REBUILD; + vl->sort_type = SORT_BY_UNSORTED; + vl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; break; + case WE_TICK: /* resort the list every 20 seconds orso (10 days) */ - if (--w->custom[0] == 0) { - w->custom[0] = DAY_TICKS; - if (--w->custom[1] == 0) { - w->custom[1] = PERIODIC_RESORT_DAYS; - _train_sort_dirty[(byte)w->window_number] = true; - DEBUG(misc, 1) ("Periodic resort Trains list player %d...", w->window_number+1); - SetWindowDirty(w); - } + if (--vl->resort_timer == 0) { + DEBUG(misc, 1) ("Periodic resort trains list player %d station %d", + owner, station); + vl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; + vl->flags |= VL_RESORT; + SetWindowDirty(w); } break; } } -static const Widget _player_trains_widgets[] = { -{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, -{ WWT_CAPTION, 14, 11, 324, 0, 13, STR_881B_TRAINS, STR_018C_WINDOW_TITLE_DRAG_THIS}, -{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, -{ WWT_PANEL, 14, 81, 232, 14, 25, 0x0, STR_SORT_TIP}, -{ WWT_CLOSEBOX, 14, 233, 243, 14, 25, STR_0225, STR_SORT_TIP}, -{ WWT_PANEL, 14, 244, 324, 14, 25, 0x0, STR_NULL}, -{ WWT_MATRIX, 14, 0, 313, 26, 207, 0x701, STR_883D_TRAINS_CLICK_ON_TRAIN_FOR}, -{ WWT_SCROLLBAR, 14, 314, 324, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, -{ WWT_PUSHTXTBTN, 14, 0, 161, 208, 219, STR_8815_NEW_VEHICLES, STR_883E_BUILD_NEW_TRAINS_REQUIRES}, -{ WWT_PANEL, 14, 162, 324, 208, 219, 0x0, STR_NULL}, -{ WIDGETS_END}, -}; - static const WindowDesc _player_trains_desc = { -1, -1, 325, 220, WC_TRAINS_LIST,0, @@ -1407,18 +1365,6 @@ static const WindowDesc _player_trains_desc = { PlayerTrainsWndProc }; -static const Widget _other_player_trains_widgets[] = { -{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, -{ WWT_CAPTION, 14, 11, 324, 0, 13, STR_881B_TRAINS, STR_018C_WINDOW_TITLE_DRAG_THIS}, -{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, -{ WWT_PANEL, 14, 81, 232, 14, 25, 0x0, STR_SORT_TIP}, -{ WWT_CLOSEBOX, 14, 233, 243, 14, 25, STR_0225, STR_SORT_TIP}, -{ WWT_PANEL, 14, 244, 324, 14, 25, 0x0, STR_NULL}, -{ WWT_MATRIX, 14, 0, 313, 26, 207, 0x701, STR_883D_TRAINS_CLICK_ON_TRAIN_FOR}, -{ WWT_SCROLLBAR, 14, 314, 324, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, -{ WIDGETS_END}, -}; - static const WindowDesc _other_player_trains_desc = { -1, -1, 325, 208, WC_TRAINS_LIST,0, @@ -1427,14 +1373,14 @@ static const WindowDesc _other_player_trains_desc = { PlayerTrainsWndProc }; -void ShowPlayerTrains(int player) +void ShowPlayerTrains(int player, int station) { Window *w; if (player == _local_player) { - w = AllocateWindowDescFront(&_player_trains_desc, player); + w = AllocateWindowDescFront(&_player_trains_desc, (station << 16) | player); } else { - w = AllocateWindowDescFront(&_other_player_trains_desc, player); + w = AllocateWindowDescFront(&_other_player_trains_desc, (station << 16) | player); } if (w) { w->caption_color = w->window_number; -- cgit v1.2.3-54-g00ecf