From 5b0915e67774c9e8ac84d192cf6bd409286166ec Mon Sep 17 00:00:00 2001 From: tron Date: Fri, 10 Dec 2004 18:16:08 +0000 Subject: [PATCH] (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. --- aircraft_cmd.c | 6 +- aircraft_gui.c | 284 +++++++++++++++++++---------------------------- gui.h | 8 +- lang/english.txt | 10 ++ main_gui.c | 16 +-- order_cmd.c | 10 ++ roadveh_cmd.c | 9 +- roadveh_gui.c | 278 ++++++++++++++++++---------------------------- ship_cmd.c | 6 +- ship_gui.c | 282 ++++++++++++++++++---------------------------- station_gui.c | 62 ++++++++++- train_cmd.c | 9 +- train_gui.c | 284 +++++++++++++++++++---------------------------- vehicle.c | 5 +- vehicle_gui.c | 106 +++++++++++++++++- vehicle_gui.h | 26 ++--- water_cmd.c | 6 +- window.h | 17 +++ 18 files changed, 676 insertions(+), 748 deletions(-) diff --git a/aircraft_cmd.c b/aircraft_cmd.c index 9929003668..74a8232510 100644 --- a/aircraft_cmd.c +++ b/aircraft_cmd.c @@ -267,8 +267,7 @@ int32 CmdBuildAircraft(int x, int y, uint32 flags, uint32 p1, uint32 p2) } InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); - _vehicle_sort_dirty[VEHAIRCRAFT] = true; // build aircraft - InvalidateWindow(WC_AIRCRAFT_LIST, v->owner); + RebuildVehicleLists(); InvalidateWindow(WC_COMPANY, v->owner); } @@ -299,8 +298,7 @@ static bool CheckStoppedInHangar(Vehicle *v) static void DoDeleteAircraft(Vehicle *v) { DeleteWindowById(WC_VEHICLE_VIEW, v->index); - _vehicle_sort_dirty[VEHAIRCRAFT] = true; // delete aircraft - InvalidateWindow(WC_AIRCRAFT_LIST, v->owner); + RebuildVehicleLists(); InvalidateWindow(WC_COMPANY, v->owner); DeleteVehicleChain(v); } diff --git a/aircraft_gui.c b/aircraft_gui.c index cfe1b72383..5dbfebaa8b 100644 --- a/aircraft_gui.c +++ b/aircraft_gui.c @@ -884,158 +884,125 @@ static void DrawSmallSchedule(Vehicle *v, int x, int y) { } } -// used to get a sorted list of the vehicles -static SortStruct _aircraft_sort[NUM_NORMAL_VEHICLES]; -static uint16 _num_aircraft_sort[MAX_PLAYERS]; -static void GlobalSortAircraftList() -{ - const Vehicle *v; - uint16 *i; - uint32 n = 0; +static Widget _player_aircraft_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_A009_AIRCRAFT, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, +{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_SORT_TIP}, +{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP}, +{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL}, +{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT}, +{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PUSHTXTBTN, 14, 0, 129, 170, 181, STR_A003_NEW_AIRCRAFT, STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES}, +{ WWT_PANEL, 14, 130, 259, 170, 181, 0x0, STR_NULL}, +{ WIDGETS_END}, +}; - // reset #-of aircraft to 0 because ++ is used for value-assignment - for (i = _num_aircraft_sort; i != endof(_num_aircraft_sort); i++) {*i = 0;} - - FOR_ALL_VEHICLES(v) { - if(v->type == VEH_Aircraft && v->subtype <= 2) { - _aircraft_sort[n].index = v->index; - _aircraft_sort[n++].owner = v->owner; - _num_aircraft_sort[v->owner]++; // add number of aircraft of player - } - } - - // create cumulative aircraft-ownership - // aircraft 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_aircraft_sort[1]; i != endof(_num_aircraft_sort); i++) {*i += *(i-1);} - - qsort(_aircraft_sort, n, sizeof(_aircraft_sort[0]), GeneralOwnerSorter); // sort by owner - - // since indexes are messed up after adding/removing a station, mark all lists dirty - memset(_aircraft_sort_dirty, true, sizeof(_aircraft_sort_dirty)); - _vehicle_sort_dirty[VEHAIRCRAFT] = false; - - DEBUG(misc, 1) ("Resorting global aircraft list..."); -} - -static void MakeSortedAircraftList(byte owner) -{ - SortStruct *firstelement; - uint32 n = 0; - - if (owner == 0) { // first element starts at 0th element and has n elements as described above - firstelement = &_aircraft_sort[0]; - n = _num_aircraft_sort[0]; - } else { // nth element starts at the end of the previous one, and has n elements as described above - firstelement = &_aircraft_sort[_num_aircraft_sort[owner-1]]; - n = _num_aircraft_sort[owner] - _num_aircraft_sort[owner-1]; - } - - _internal_sort_order = _aircraft_sort_order[owner]; - _internal_name_sorter_id = STR_SV_AIRCRAFT_NAME; - _last_vehicle_idx = 0; // used for "cache" in namesorting - qsort(firstelement, n, sizeof(_aircraft_sort[0]), _vehicle_sorter[_aircraft_sort_type[owner]]); - - _aircraft_sort_dirty[owner] = false; - - DEBUG(misc, 1) ("Resorting Aircraft list player %d...", owner+1); -} +static Widget _other_player_aircraft_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_A009_AIRCRAFT, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, +{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_SORT_TIP}, +{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP}, +{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL}, +{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT}, +{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WIDGETS_END}, +}; static void PlayerAircraftWndProc(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; + int x = 2; + int y = PLY_WND_PRC__OFFSET_TOP_WIDGET; + int max; + int i; - if (_aircraft_sort_type[window_number] == SORT_BY_UNSORTED) // disable 'Sort By' tooltip on Unsorted sorting criteria + BuildVehicleList(vl, VEH_Aircraft, owner, station); + SortVehicleList(vl); + + SetVScrollCount(w, vl->list_length); + + // disable 'Sort By' tooltip on Unsorted sorting criteria + if (vl->sort_type == SORT_BY_UNSORTED) w->disabled_state |= (1 << 2); - // resort shipps window if roadvehicles have been added/removed - if (_vehicle_sort_dirty[VEHAIRCRAFT]) - GlobalSortAircraftList(); - - if (_aircraft_sort_dirty[window_number]) { - MakeSortedAircraftList(window_number); - /* reset sorting timeout */ - w->custom[0] = DAY_TICKS; - w->custom[1] = PERIODIC_RESORT_DAYS; - } - - // aircraft are stored as a cummulative index, eg 25, 41, 43. This means - // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 aircraft - i = (window_number == 0) ? 0 : _num_aircraft_sort[window_number-1]; - SetVScrollCount(w, _num_aircraft_sort[window_number] - i); - /* draw the widgets */ { - Player *p = DEREF_PLAYER(window_number); - /* Company Name -- (###) Aircraft */ - 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 -- (###) Aircraft */ + SetDParam(0, p->name_1); + SetDParam(1, p->name_2); + SetDParam(2, w->vscroll.count); + _player_aircraft_widgets[1].unkA = STR_A009_AIRCRAFT; + _other_player_aircraft_widgets[1].unkA = STR_A009_AIRCRAFT; + } else { + /* Station Name -- (###) Aircraft */ + SetDParam(0, DEREF_STATION(station)->index); + SetDParam(1, w->vscroll.count); + _player_aircraft_widgets[1].unkA = STR_SCHEDULED_AIRCRAFT; + _other_player_aircraft_widgets[1].unkA = STR_SCHEDULED_AIRCRAFT; + } DrawWindowWidgets(w); } /* draw sorting criteria string */ - DrawString(85, 15, _vehicle_sort_listing[_aircraft_sort_type[window_number]], 0x10); - /* draw arrow pointing up/down for ascending/descending soring */ - DoDrawString(_aircraft_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 aircraft */ - { - 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 aircraft 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_aircraft_sort[window_number]) { - StringID str; - v = DEREF_VEHICLE(_aircraft_sort[i].index); + assert(v->type == VEH_Aircraft && v->subtype <= 2); - assert(v->type == VEH_Aircraft && v->subtype <= 2 && v->owner == window_number); + DrawAircraftImage(v, x + 19, y + 6, INVALID_VEHICLE); + DrawVehicleProfitButton(v, x, y + 13); - DrawAircraftImage(v, x + 19, y + 6, INVALID_VEHICLE); - DrawVehicleProfitButton(v, x, y+13); + SetDParam(0, v->unitnumber); + if (IsAircraftHangarTile(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->unitnumber); - if (IsAircraftHangarTile(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 + 19, y + 28, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0); - - SetDParam(0, v->profit_this_year); - SetDParam(1, v->profit_last_year); - DrawString(x+19, y + 28, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0); - - if (v->string_id != STR_SV_AIRCRAFT_NAME) { - SetDParam(0, v->string_id); - DrawString(x+19, y, STR_01AB, 0); - } - - DrawSmallSchedule(v, x+136, y); - - y += PLY_WND_PRC__SIZE_OF_ROW_BIG; - i++; // next aircraft - if (++n == w->vscroll.cap) { break;} // max number of aircraft in the window + if (v->string_id != STR_SV_AIRCRAFT_NAME) { + SetDParam(0, v->string_id); + DrawString(x + 19, y, STR_01AB, 0); } + + DrawSmallSchedule(v, x + 136, y); + + y += PLY_WND_PRC__SIZE_OF_ROW_BIG; } } break; case WE_CLICK: { switch(e->click.widget) { case 2: /* Flip sorting method ascending/descending */ - _aircraft_sort_order[(byte)w->window_number] ^= 1; - _aircraft_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, _aircraft_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_BIG; @@ -1044,15 +1011,13 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e) id_v += w->vscroll.pos; { - const byte owner = (byte)w->window_number; Vehicle *v; - id_v += (owner == 0) ? 0 : _num_aircraft_sort[owner - 1]; // first element in list - if (id_v >= _num_aircraft_sort[owner]) { return;} // click out of vehicle bound + if (id_v >= vl->list_length) return; // click out of list bound - v = DEREF_VEHICLE(_aircraft_sort[id_v].index); // add the offset id_x to that + v = DEREF_VEHICLE(vl->sort_list[id_v].index); - assert(v->type == VEH_Aircraft && v->subtype <= 2 && v->owner == owner); + assert(v->type == VEH_Aircraft && v->subtype <= 2); ShowAircraftViewWindow(v); } @@ -1078,48 +1043,37 @@ static void PlayerAircraftWndProc(Window *w, WindowEvent *e) } break; case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */ - if (_aircraft_sort_type[(byte)w->window_number] != e->dropdown.index) // if value hasn't changed, dont resort list - _aircraft_sort_dirty[(byte)w->window_number] = true; - - _aircraft_sort_type[(byte)w->window_number] = e->dropdown.index; - - if (_aircraft_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; - _aircraft_sort_dirty[(byte)w->window_number] = true; - DEBUG(misc, 1) ("Periodic resort Aircraft list player %d...", w->window_number+1); - SetWindowDirty(w); - } + if (--vl->resort_timer == 0) { + DEBUG(misc, 1) ("Periodic resort aircraft 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_aircraft_widgets[] = { -{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, -{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_A009_AIRCRAFT, STR_018C_WINDOW_TITLE_DRAG_THIS}, -{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, -{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_SORT_TIP}, -{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP}, -{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL}, -{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT}, -{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, -{ WWT_PUSHTXTBTN, 14, 0, 129, 170, 181, STR_A003_NEW_AIRCRAFT, STR_A020_BUILD_NEW_AIRCRAFT_REQUIRES}, -{ WWT_PANEL, 14, 130, 259, 170, 181, 0x0, STR_NULL}, -{ WIDGETS_END}, -}; - static const WindowDesc _player_aircraft_desc = { -1, -1, 260, 182, WC_AIRCRAFT_LIST,0, @@ -1128,18 +1082,6 @@ static const WindowDesc _player_aircraft_desc = { PlayerAircraftWndProc }; -static const Widget _other_player_aircraft_widgets[] = { -{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, -{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_A009_AIRCRAFT, STR_018C_WINDOW_TITLE_DRAG_THIS}, -{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, -{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_SORT_TIP}, -{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP}, -{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL}, -{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_A01F_AIRCRAFT_CLICK_ON_AIRCRAFT}, -{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, -{ WIDGETS_END}, -}; - static const WindowDesc _other_player_aircraft_desc = { -1, -1, 260, 170, WC_AIRCRAFT_LIST,0, @@ -1148,14 +1090,14 @@ static const WindowDesc _other_player_aircraft_desc = { PlayerAircraftWndProc }; -void ShowPlayerAircraft(int player) +void ShowPlayerAircraft(int player, int station) { Window *w; if (player == _local_player) { - w = AllocateWindowDescFront(&_player_aircraft_desc, player); + w = AllocateWindowDescFront(&_player_aircraft_desc, (station << 16) | player); } else { - w = AllocateWindowDescFront(&_other_player_aircraft_desc, player); + w = AllocateWindowDescFront(&_other_player_aircraft_desc, (station << 16) | player); } if (w) { diff --git a/gui.h b/gui.h index da6f05f49c..45ea66a154 100644 --- a/gui.h +++ b/gui.h @@ -34,7 +34,7 @@ void ShowBuildRailToolbar(int index, int button); void PlaceProc_BuyLand(uint tile); /* train_gui.c */ -void ShowPlayerTrains(int player); +void ShowPlayerTrains(int player, int station); void ShowTrainViewWindow(Vehicle *v); void ShowTrainDetailsWindow(Vehicle *v); void ShowOrdersWindow(Vehicle *v); @@ -44,17 +44,17 @@ void ShowRoadVehViewWindow(Vehicle *v); /* road_gui.c */ void ShowBuildRoadToolbar(); void ShowBuildRoadScenToolbar(); -void ShowPlayerRoadVehicles(int player); +void ShowPlayerRoadVehicles(int player, int station); /* dock_gui.c */ void ShowBuildDocksToolbar(); -void ShowPlayerShips(int player); +void ShowPlayerShips(int player, int station); void ShowShipViewWindow(Vehicle *v); /* aircraft_gui.c */ void ShowBuildAirToolbar(); -void ShowPlayerAircraft(int player); +void ShowPlayerAircraft(int player, int station); /* terraform_gui.c */ void PlaceProc_DemolishArea(uint tile); diff --git a/lang/english.txt b/lang/english.txt index ab06f7f4c1..be7b8be718 100644 --- a/lang/english.txt +++ b/lang/english.txt @@ -2697,3 +2697,13 @@ STR_NEWGRF_TIP :{BLACK}A list of all the Newgrf sets that you have in STR_NEWGRF_NO_FILES_INSTALLED :{BLACK}There are currently no newgrf files installed! Please refer to the manual for instructions to install new graphics. STR_NEWGRF_FILENAME :{BLACK}Filename: STR_NEWGRF_GRF_ID :{BLACK}GRF ID: + +STR_TRAIN :{BLACK}{TRAIN} +STR_LORRY :{BLACK}{LORRY} +STR_PLANE :{BLACK}{PLANE} +STR_SHIP :{BLACK}{SHIP} + +STR_SCHEDULED_TRAINS :{WHITE}{STATION} - {COMMA16} Trains +STR_SCHEDULED_ROAD_VEHICLES :{WHITE}{STATION} - {COMMA16} Road Vehicles +STR_SCHEDULED_AIRCRAFT :{WHITE}{STATION} - {COMMA16} Aircraft +STR_SCHEDULED_SHIPS :{WHITE}{STATION} - {COMMA16} Ships diff --git a/main_gui.c b/main_gui.c index 80567b2ed4..918b3c6a09 100644 --- a/main_gui.c +++ b/main_gui.c @@ -292,22 +292,22 @@ static void MenuClickIndustry(int index) static void MenuClickShowTrains(int index) { - ShowPlayerTrains(index); + ShowPlayerTrains(index, -1); } static void MenuClickShowRoad(int index) { - ShowPlayerRoadVehicles(index); + ShowPlayerRoadVehicles(index, -1); } static void MenuClickShowShips(int index) { - ShowPlayerShips(index); + ShowPlayerShips(index, -1); } static void MenuClickShowAir(int index) { - ShowPlayerAircraft(index); + ShowPlayerAircraft(index, -1); } static void MenuClickBuildRail(int index) @@ -1819,10 +1819,10 @@ static void MainToolbarWndProc(Window *w, WindowEvent *e) case WKC_F10:ShowOperatingProfitGraph(); break; case WKC_F11: ShowCompanyLeagueTable(); break; case WKC_F12: ShowBuildIndustryWindow(); break; - case WKC_SHIFT | WKC_F1: ShowPlayerTrains(local); break; - case WKC_SHIFT | WKC_F2: ShowPlayerRoadVehicles(local); break; - case WKC_SHIFT | WKC_F3: ShowPlayerShips(local); break; - case WKC_SHIFT | WKC_F4: ShowPlayerAircraft(local); break; + case WKC_SHIFT | WKC_F1: ShowPlayerTrains(local, -1); break; + case WKC_SHIFT | WKC_F2: ShowPlayerRoadVehicles(local, -1); break; + case WKC_SHIFT | WKC_F3: ShowPlayerShips(local, -1); break; + case WKC_SHIFT | WKC_F4: ShowPlayerAircraft(local, -1); break; case WKC_SHIFT | WKC_F5: ToolbarZoomInClick(w); break; case WKC_SHIFT | WKC_F6: ToolbarZoomOutClick(w); break; case WKC_SHIFT | WKC_F7: ShowBuildRailToolbar(_last_built_railtype,-1); break; diff --git a/order_cmd.c b/order_cmd.c index e08448b186..9de4a8c184 100644 --- a/order_cmd.c +++ b/order_cmd.c @@ -62,6 +62,8 @@ int32 CmdInsertOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) } } } + + RebuildVehicleLists(); } return 0; @@ -81,6 +83,8 @@ static int32 DecloneOrder(Vehicle *dst, uint32 flags) dst->schedule_ptr = _ptr_to_next_order++; InvalidateWindow(WC_VEHICLE_ORDERS, dst->index); + + RebuildVehicleLists(); } return 0; } @@ -126,6 +130,8 @@ int32 CmdDeleteOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) } } } + + RebuildVehicleLists(); } return 0; @@ -240,6 +246,8 @@ int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) InvalidateWindow(WC_VEHICLE_ORDERS, src->index); InvalidateWindow(WC_VEHICLE_ORDERS, dst->index); + + RebuildVehicleLists(); } break; } @@ -281,6 +289,8 @@ int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2) memcpy(dst->schedule_ptr, src->schedule_ptr, (src->num_orders + 1) * sizeof(uint16)); InvalidateWindow(WC_VEHICLE_ORDERS, dst->index); + + RebuildVehicleLists(); } break; } diff --git a/roadveh_cmd.c b/roadveh_cmd.c index f9acd3c448..7df7b7f44c 100644 --- a/roadveh_cmd.c +++ b/roadveh_cmd.c @@ -184,8 +184,7 @@ int32 CmdBuildRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) VehiclePositionChanged(v); InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); - _vehicle_sort_dirty[VEHROAD] = true; // build a new bus/truck - InvalidateWindow(WC_ROADVEH_LIST, v->owner); + RebuildVehicleLists(); InvalidateWindow(WC_COMPANY, v->owner); } @@ -228,8 +227,7 @@ int32 CmdSellRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) if (flags & DC_EXEC) { // Invalidate depot InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); - _vehicle_sort_dirty[VEHROAD] = true; // sell a bus/truck - InvalidateWindow(WC_ROADVEH_LIST, v->owner); + RebuildVehicleLists(); InvalidateWindow(WC_COMPANY, v->owner); DeleteWindowById(WC_VEHICLE_VIEW, v->index); DeleteVehicle(v); @@ -422,8 +420,7 @@ static void RoadVehDelete(Vehicle *v) DeleteWindowById(WC_VEHICLE_VIEW, v->index); InvalidateWindow(WC_VEHICLE_DETAILS, v->index); - _vehicle_sort_dirty[VEHROAD] = true; // delete bus/truck (eg. crash for example) - InvalidateWindow(WC_ROADVEH_LIST, v->owner); + RebuildVehicleLists(); InvalidateWindow(WC_COMPANY, v->owner); if(IS_TILETYPE(v->tile, MP_STATION)) diff --git a/roadveh_gui.c b/roadveh_gui.c index b86ded196d..c9682ecf9d 100644 --- a/roadveh_gui.c +++ b/roadveh_gui.c @@ -698,154 +698,122 @@ void ShowRoadDepotWindow(uint tile) } } -// used to get a sorted list of the vehicles -static SortStruct _road_sort[NUM_NORMAL_VEHICLES]; -static uint16 _num_road_sort[MAX_PLAYERS]; -static void GlobalSortRoadVehList() -{ - const Vehicle *v; - uint16 *i; - uint32 n = 0; +static Widget _player_roadveh_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9001_ROAD_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, +{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_SORT_TIP}, +{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP}, +{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL}, +{ WWT_MATRIX, 14, 0, 248, 26, 207, 0x701, STR_901A_ROAD_VEHICLES_CLICK_ON}, +{ WWT_SCROLLBAR, 14, 249, 259, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +/* only for our road list, a 'Build Vehicle' button that opens the depot of the last built depot */ +{ WWT_PUSHTXTBTN, 14, 0, 129, 208, 219, STR_8815_NEW_VEHICLES, STR_901B_BUILD_NEW_ROAD_VEHICLES}, +{ WWT_PANEL, 14, 130, 259, 208, 219, 0x0, STR_NULL}, +{ WIDGETS_END}, +}; - // reset #-of roadvehicles to 0 because ++ is used for value-assignment - for (i = _num_road_sort; i != endof(_num_road_sort); i++) {*i = 0;} - - FOR_ALL_VEHICLES(v) { - if(v->type == VEH_Road) { - _road_sort[n].index = v->index; - _road_sort[n++].owner = v->owner; - _num_road_sort[v->owner]++; // add number of roadvehicless of player - } - } - - // create cumulative roadvehicle-ownership - // roads 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_road_sort[1]; i != endof(_num_road_sort); i++) {*i += *(i-1);} - - qsort(_road_sort, n, sizeof(_road_sort[0]), GeneralOwnerSorter); // sort by owner - - // since indexes are messed up after adding/removing a station, mark all lists dirty - memset(_road_sort_dirty, true, sizeof(_road_sort_dirty)); - _vehicle_sort_dirty[VEHROAD] = false; - - DEBUG(misc, 1) ("Resorting global roadvehicles list..."); -} - -static void MakeSortedRoadVehList(byte owner) -{ - SortStruct *firstelement; - uint32 n = 0; - - if (owner == 0) { // first element starts at 0th element and has n elements as described above - firstelement = &_road_sort[0]; - n = _num_road_sort[0]; - } else { // nth element starts at the end of the previous one, and has n elements as described above - firstelement = &_road_sort[_num_road_sort[owner-1]]; - n = _num_road_sort[owner] - _num_road_sort[owner-1]; - } - - _internal_sort_order = _road_sort_order[owner]; - _internal_name_sorter_id = STR_SV_ROADVEH_NAME; - _last_vehicle_idx = 0; // used for "cache" in namesorting - qsort(firstelement, n, sizeof(_road_sort[0]), _vehicle_sorter[_road_sort_type[owner]]); - - _road_sort_dirty[owner] = false; - - DEBUG(misc, 1) ("Resorting Roadvehicles list player %d...", owner+1); -} +static Widget _other_player_roadveh_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9001_ROAD_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, +{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_SORT_TIP}, +{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP}, +{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL}, +{ WWT_MATRIX, 14, 0, 248, 26, 207, 0x701, STR_901A_ROAD_VEHICLES_CLICK_ON}, +{ WWT_SCROLLBAR, 14, 249, 259, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WIDGETS_END}, +}; static void PlayerRoadVehWndProc(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; + int x = 2; + int y = PLY_WND_PRC__OFFSET_TOP_WIDGET; + int max; + int i; - if (_road_sort_type[window_number] == SORT_BY_UNSORTED) // disable 'Sort By' tooltip on Unsorted sorting criteria + BuildVehicleList(vl, VEH_Road, owner, station); + SortVehicleList(vl); + + SetVScrollCount(w, vl->list_length); + + // disable 'Sort By' tooltip on Unsorted sorting criteria + if (vl->sort_type == SORT_BY_UNSORTED) w->disabled_state |= (1 << 2); - // resort roadvehicles window if roadvehicles have been added/removed - if (_vehicle_sort_dirty[VEHROAD]) - GlobalSortRoadVehList(); - - if (_road_sort_dirty[window_number]) { - MakeSortedRoadVehList(window_number); - /* reset sorting timeout */ - w->custom[0] = DAY_TICKS; - w->custom[1] = PERIODIC_RESORT_DAYS; - } - - // roads are stored as a cummulative index, eg 25, 41, 43. This means - // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 roads - i = (window_number == 0) ? 0 : _num_road_sort[window_number-1]; - SetVScrollCount(w, _num_road_sort[window_number] - i); - /* draw the widgets */ { - Player *p = DEREF_PLAYER(window_number); - /* Company Name -- (###) Roadvehicles */ - 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 -- (###) Road vehicles */ + SetDParam(0, p->name_1); + SetDParam(1, p->name_2); + SetDParam(2, w->vscroll.count); + _player_roadveh_widgets[1].unkA = STR_9001_ROAD_VEHICLES; + _other_player_roadveh_widgets[1].unkA = STR_9001_ROAD_VEHICLES; + } else { + /* Station Name -- (###) Road vehicles */ + SetDParam(0, DEREF_STATION(station)->index); + SetDParam(1, w->vscroll.count); + _player_roadveh_widgets[1].unkA = STR_SCHEDULED_ROAD_VEHICLES; + _other_player_roadveh_widgets[1].unkA = STR_SCHEDULED_ROAD_VEHICLES; + } DrawWindowWidgets(w); } /* draw sorting criteria string */ - DrawString(85, 15, _vehicle_sort_listing[_road_sort_type[window_number]], 0x10); - /* draw arrow pointing up/down for ascending/descending soring */ - DoDrawString(_road_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 roadvehicles */ - { - 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 roads 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_road_sort[window_number]) { - StringID str; - v = DEREF_VEHICLE(_road_sort[i].index); + assert(v->type == VEH_Road && v->owner == owner); - assert(v->type == VEH_Road && v->owner == window_number); + DrawRoadVehImage(v, x + 22, y + 6, INVALID_VEHICLE); + DrawVehicleProfitButton(v, x, y + 13); - DrawRoadVehImage(v, x + 22, y + 6, INVALID_VEHICLE); - DrawVehicleProfitButton(v, x, y+13); + SetDParam(0, v->unitnumber); + if (IsRoadDepotTile(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->unitnumber); - if (IsRoadDepotTile(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 + 24, y + 18, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0); - SetDParam(0, v->profit_this_year); - SetDParam(1, v->profit_last_year); - DrawString(x + 24, y + 18, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0); - - if (v->string_id != STR_SV_ROADVEH_NAME) { - SetDParam(0, v->string_id); - DrawString(x+24, y, STR_01AB, 0); - } - - y += PLY_WND_PRC__SIZE_OF_ROW_SMALL; - i++; // next road - if (++n == w->vscroll.cap) { break;} // max number of roads in the window + if (v->string_id != STR_SV_TRAIN_NAME) { + SetDParam(0, v->string_id); + DrawString(x + 24, y, STR_01AB, 0); } + + y += PLY_WND_PRC__SIZE_OF_ROW_SMALL; } } break; case WE_CLICK: { switch(e->click.widget) { case 2: /* Flip sorting method ascending/descending */ - _road_sort_order[(byte)w->window_number] ^= 1; - _road_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, _road_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; @@ -855,13 +823,11 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e) id_v += w->vscroll.pos; { - const byte owner = (byte)w->window_number; Vehicle *v; - id_v += (owner == 0) ? 0 : _num_road_sort[owner - 1]; // first element in list - if (id_v >= _num_road_sort[owner]) { return;} // click out of vehicle bound + if (id_v >= vl->list_length) return; // click out of list bound - v = DEREF_VEHICLE(_road_sort[id_v].index); // add the offset id_x to that + v = DEREF_VEHICLE(vl->sort_list[id_v].index); assert(v->type == VEH_Road && v->owner == owner); @@ -889,49 +855,37 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e) } break; case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */ - if (_road_sort_type[(byte)w->window_number] != e->dropdown.index) // if value hasn't changed, dont resort list - _road_sort_dirty[(byte)w->window_number] = true; - - _road_sort_type[(byte)w->window_number] = e->dropdown.index; - - if (_road_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; - _road_sort_dirty[(byte)w->window_number] = true; - DEBUG(misc, 1) ("Periodic resort Roadvehicles list player %d...", w->window_number+1); - SetWindowDirty(w); - } + if (--vl->resort_timer == 0) { + DEBUG(misc, 1) ("Periodic resort road vehicles 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_roadveh_widgets[] = { -{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, -{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9001_ROAD_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS}, -{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, -{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_SORT_TIP}, -{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP}, -{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL}, -{ WWT_MATRIX, 14, 0, 248, 26, 207, 0x701, STR_901A_ROAD_VEHICLES_CLICK_ON}, -{ WWT_SCROLLBAR, 14, 249, 259, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, -/* only for our road list, a 'Build Vehicle' button that opens the depot of the last built depot */ -{ WWT_PUSHTXTBTN, 14, 0, 129, 208, 219, STR_8815_NEW_VEHICLES, STR_901B_BUILD_NEW_ROAD_VEHICLES}, -{ WWT_PANEL, 14, 130, 259, 208, 219, 0x0, STR_NULL}, -{ WIDGETS_END}, -}; - static const WindowDesc _player_roadveh_desc = { -1, -1, 260, 220, WC_ROADVEH_LIST,0, @@ -940,18 +894,6 @@ static const WindowDesc _player_roadveh_desc = { PlayerRoadVehWndProc }; -static const Widget _other_player_roadveh_widgets[] = { -{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, -{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9001_ROAD_VEHICLES, STR_018C_WINDOW_TITLE_DRAG_THIS}, -{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, -{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_SORT_TIP}, -{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP}, -{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL}, -{ WWT_MATRIX, 14, 0, 248, 26, 207, 0x701, STR_901A_ROAD_VEHICLES_CLICK_ON}, -{ WWT_SCROLLBAR, 14, 249, 259, 26, 207, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, -{ WIDGETS_END}, -}; - static const WindowDesc _other_player_roadveh_desc = { -1, -1, 260, 208, WC_ROADVEH_LIST,0, @@ -961,14 +903,14 @@ static const WindowDesc _other_player_roadveh_desc = { }; -void ShowPlayerRoadVehicles(int player) +void ShowPlayerRoadVehicles(int player, int station) { Window *w; if ( player == _local_player) { - w = AllocateWindowDescFront(&_player_roadveh_desc, player); + w = AllocateWindowDescFront(&_player_roadveh_desc, (station << 16) | player); } else { - w = AllocateWindowDescFront(&_other_player_roadveh_desc, player); + w = AllocateWindowDescFront(&_other_player_roadveh_desc, (station << 16) | player); } if (w) { w->caption_color = player; diff --git a/ship_cmd.c b/ship_cmd.c index 578fce38a3..2c91fda3c2 100644 --- a/ship_cmd.c +++ b/ship_cmd.c @@ -870,8 +870,7 @@ int32 CmdBuildShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) VehiclePositionChanged(v); InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); - _vehicle_sort_dirty[VEHSHIP] = true; // build a ship - InvalidateWindow(WC_SHIPS_LIST, v->owner); + RebuildVehicleLists(); InvalidateWindow(WC_COMPANY, v->owner); } @@ -894,8 +893,7 @@ int32 CmdSellShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) if (flags & DC_EXEC) { InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); - _vehicle_sort_dirty[VEHSHIP] = true; // sell a ship - InvalidateWindow(WC_SHIPS_LIST, v->owner); + RebuildVehicleLists(); InvalidateWindow(WC_COMPANY, v->owner); DeleteWindowById(WC_VEHICLE_VIEW, v->index); DeleteVehicle(v); diff --git a/ship_gui.c b/ship_gui.c index f13c752ffa..1e5eaca681 100644 --- a/ship_gui.c +++ b/ship_gui.c @@ -866,157 +866,122 @@ static void DrawSmallShipSchedule(Vehicle *v, int x, int y) { } } -// used to get a sorted list of the vehicles -static SortStruct _ship_sort[NUM_NORMAL_VEHICLES]; -static uint16 _num_ship_sort[MAX_PLAYERS]; -static void GlobalSortShipList() -{ - const Vehicle *v; - uint16 *i; - uint32 n = 0; +static Widget _player_ships_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9805_SHIPS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, +{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_NULL}, +{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP}, +{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL}, +{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR}, +{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WWT_PUSHTXTBTN, 14, 0, 129, 170, 181, STR_9804_NEW_SHIPS, STR_9824_BUILD_NEW_SHIPS_REQUIRES}, +{ WWT_PANEL, 14, 130, 259, 170, 181, 0x0, STR_NULL}, +{ WIDGETS_END}, +}; - // reset #-of ships to 0 because ++ is used for value-assignment - for (i = _num_ship_sort; i != endof(_num_ship_sort); i++) {*i = 0;} - - FOR_ALL_VEHICLES(v) { - if(v->type == VEH_Ship) { - _ship_sort[n].index = v->index; - _ship_sort[n++].owner = v->owner; - _num_ship_sort[v->owner]++; // add number of ships of player - } - } - - // create cumulative ship-ownership - // ships 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_ship_sort[1]; i != endof(_num_ship_sort); i++) {*i += *(i-1);} - - qsort(_ship_sort, n, sizeof(_ship_sort[0]), GeneralOwnerSorter); // sort by owner - - // since indexes are messed up after adding/removing a station, mark all lists dirty - memset(_ship_sort_dirty, true, sizeof(_ship_sort_dirty)); - _vehicle_sort_dirty[VEHSHIP] = false; - - DEBUG(misc, 1) ("Resorting global ships list..."); -} - -static void MakeSortedShipList(byte owner) -{ - SortStruct *firstelement; - uint32 n = 0; - - if (owner == 0) { // first element starts at 0th element and has n elements as described above - firstelement = &_ship_sort[0]; - n = _num_ship_sort[0]; - } else { // nth element starts at the end of the previous one, and has n elements as described above - firstelement = &_ship_sort[_num_ship_sort[owner-1]]; - n = _num_ship_sort[owner] - _num_ship_sort[owner-1]; - } - - _internal_sort_order = _ship_sort_order[owner]; - _internal_name_sorter_id = STR_SV_SHIP_NAME; - _last_vehicle_idx = 0; // used for "cache" in namesorting - qsort(firstelement, n, sizeof(_ship_sort[0]), _vehicle_sorter[_ship_sort_type[owner]]); - - _ship_sort_dirty[owner] = false; - - DEBUG(misc, 1) ("Resorting Ships list player %d...", owner+1); -} +static Widget _other_player_ships_widgets[] = { +{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, +{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9805_SHIPS, STR_018C_WINDOW_TITLE_DRAG_THIS}, +{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, +{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_NULL}, +{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP}, +{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL}, +{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR}, +{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ WIDGETS_END}, +}; static void PlayerShipsWndProc(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; + int x = 2; + int y = PLY_WND_PRC__OFFSET_TOP_WIDGET; + int max; + int i; - if (_ship_sort_type[window_number] == SORT_BY_UNSORTED) // disable 'Sort By' tooltip on Unsorted sorting criteria + BuildVehicleList(vl, VEH_Ship, owner, station); + SortVehicleList(vl); + + SetVScrollCount(w, vl->list_length); + + // disable 'Sort By' tooltip on Unsorted sorting criteria + if (vl->sort_type == SORT_BY_UNSORTED) w->disabled_state |= (1 << 2); - // resort shipps window if roadvehicles have been added/removed - if (_vehicle_sort_dirty[VEHSHIP]) - GlobalSortShipList(); - - if (_ship_sort_dirty[window_number]) { - MakeSortedShipList(window_number); - /* reset sorting timeout */ - w->custom[0] = DAY_TICKS; - w->custom[1] = PERIODIC_RESORT_DAYS; - } - - // ships are stored as a cummulative index, eg 25, 41, 43. This means - // Player0: 25; Player1: (41-25) 16; Player2: (43-41) 2 ships - i = (window_number == 0) ? 0 : _num_ship_sort[window_number-1]; - SetVScrollCount(w, _num_ship_sort[window_number] - i); - /* draw the widgets */ { - Player *p = DEREF_PLAYER(window_number); - /* Company Name -- (###) Ships */ - 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_ships_widgets[1].unkA = STR_9805_SHIPS; + _other_player_ships_widgets[1].unkA = STR_9805_SHIPS; + } else { + /* Station Name -- (###) Trains */ + SetDParam(0, DEREF_STATION(station)->index); + SetDParam(1, w->vscroll.count); + _player_ships_widgets[1].unkA = STR_SCHEDULED_SHIPS; + _other_player_ships_widgets[1].unkA = STR_SCHEDULED_SHIPS; + } DrawWindowWidgets(w); } /* draw sorting criteria string */ - DrawString(85, 15, _vehicle_sort_listing[_ship_sort_type[window_number]], 0x10); - /* draw arrow pointing up/down for ascending/descending soring */ - DoDrawString(_ship_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 ship vehicles */ - { - 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 ship 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_ship_sort[window_number]) { - StringID str; - v = DEREF_VEHICLE(_ship_sort[i].index); + assert(v->type == VEH_Ship); - assert(v->type == VEH_Ship && v->owner == window_number); + DrawShipImage(v, x + 19, y + 6, INVALID_VEHICLE); + DrawVehicleProfitButton(v, x, y + 13); - DrawShipImage(v, x + 19, y + 6, INVALID_VEHICLE); - DrawVehicleProfitButton(v, x, y+13); + SetDParam(0, v->unitnumber); + if (IsShipDepotTile(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->unitnumber); - if (IsShipDepotTile(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 + 12, y + 28, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0); - SetDParam(0, v->profit_this_year); - SetDParam(1, v->profit_last_year); - DrawString(x + 12, y + 28, STR_0198_PROFIT_THIS_YEAR_LAST_YEAR, 0); - - if (v->string_id != STR_SV_SHIP_NAME) { - SetDParam(0, v->string_id); - DrawString(x+12, y, STR_01AB, 0); - } - - DrawSmallShipSchedule(v, x+138, y); - - - y += PLY_WND_PRC__SIZE_OF_ROW_BIG; - i++; // next ship - if (++n == w->vscroll.cap) { break;} // max number of ships in the window + if (v->string_id != STR_SV_SHIP_NAME) { + SetDParam(0, v->string_id); + DrawString(x + 12, y, STR_01AB, 0); } + + DrawSmallShipSchedule(v, x + 138, y); + + y += PLY_WND_PRC__SIZE_OF_ROW_BIG; } } break; case WE_CLICK: { switch(e->click.widget) { case 2: /* Flip sorting method ascending/descending */ - _ship_sort_order[(byte)w->window_number] ^= 1; - _ship_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, _ship_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_BIG; @@ -1026,15 +991,13 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e) id_v += w->vscroll.pos; { - const byte owner = (byte)w->window_number; Vehicle *v; - id_v += (owner == 0) ? 0 : _num_ship_sort[owner - 1]; // first element in list - if (id_v >= _num_ship_sort[owner]) { return;} // click out of vehicle bound + if (id_v >= vl->list_length) return; // click out of list bound - v = DEREF_VEHICLE(_ship_sort[id_v].index); // add the offset id_x to that + v = DEREF_VEHICLE(vl->sort_list[id_v].index); - assert(v->type == VEH_Ship && v->owner == owner); + assert(v->type == VEH_Ship); ShowShipViewWindow(v); } @@ -1060,48 +1023,37 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e) } break; case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */ - if (_ship_sort_type[(byte)w->window_number] != e->dropdown.index) // if value hasn't changed, dont resort list - _ship_sort_dirty[(byte)w->window_number] = true; - - _ship_sort_type[(byte)w->window_number] = e->dropdown.index; - - if (_ship_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; - _ship_sort_dirty[(byte)w->window_number] = true; - DEBUG(misc, 1) ("Periodic resort Ships list player %d...", w->window_number+1); - SetWindowDirty(w); - } + if (--vl->resort_timer == 0) { + DEBUG(misc, 1) ("Periodic resort ships 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_ships_widgets[] = { -{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, -{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9805_SHIPS, STR_018C_WINDOW_TITLE_DRAG_THIS}, -{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, -{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_NULL}, -{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP}, -{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL}, -{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR}, -{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, -{ WWT_PUSHTXTBTN, 14, 0, 129, 170, 181, STR_9804_NEW_SHIPS, STR_9824_BUILD_NEW_SHIPS_REQUIRES}, -{ WWT_PANEL, 14, 130, 259, 170, 181, 0x0, STR_NULL}, -{ WIDGETS_END}, -}; - static const WindowDesc _player_ships_desc = { -1, -1, 260, 182, WC_SHIPS_LIST,0, @@ -1110,18 +1062,6 @@ static const WindowDesc _player_ships_desc = { PlayerShipsWndProc }; -static const Widget _other_player_ships_widgets[] = { -{ WWT_CLOSEBOX, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, -{ WWT_CAPTION, 14, 11, 259, 0, 13, STR_9805_SHIPS, STR_018C_WINDOW_TITLE_DRAG_THIS}, -{ WWT_PUSHTXTBTN, 14, 0, 80, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, -{ WWT_PANEL, 14, 81, 237, 14, 25, 0x0, STR_NULL}, -{ WWT_CLOSEBOX, 14, 238, 248, 14, 25, STR_0225, STR_SORT_TIP}, -{ WWT_PANEL, 14, 249, 259, 14, 25, 0x0, STR_NULL}, -{ WWT_MATRIX, 14, 0, 248, 26, 169, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR}, -{ WWT_SCROLLBAR, 14, 249, 259, 26, 169, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, -{ WIDGETS_END}, -}; - static const WindowDesc _other_player_ships_desc = { -1, -1, 260, 170, WC_SHIPS_LIST,0, @@ -1131,14 +1071,14 @@ static const WindowDesc _other_player_ships_desc = { }; -void ShowPlayerShips(int player) +void ShowPlayerShips(int player, int station) { Window *w; if ( player == _local_player) { - w = AllocateWindowDescFront(&_player_ships_desc, player); + w = AllocateWindowDescFront(&_player_ships_desc, (station << 16) | player); } else { - w = AllocateWindowDescFront(&_other_player_ships_desc, player); + w = AllocateWindowDescFront(&_other_player_ships_desc, (station << 16) | player); } if (w) { w->caption_color = w->window_number; diff --git a/station_gui.c b/station_gui.c index beaa84d683..39b1a424f7 100644 --- a/station_gui.c +++ b/station_gui.c @@ -264,9 +264,13 @@ static const Widget _station_view_expanded_widgets[] = { { WWT_SCROLLBAR, 14, 238, 248, 14, 65, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, { WWT_EMPTY, 0, 0, 0, 0, 0, 0x0, STR_NULL}, { WWT_IMGBTN, 14, 0, 248, 66, 197, 0x0, STR_NULL}, -{ WWT_PUSHTXTBTN, 14, 0, 82, 198, 209, STR_00E4_LOCATION, STR_3053_CENTER_MAIN_VIEW_ON_STATION}, -{ WWT_PUSHTXTBTN, 14, 83, 165, 198, 209, STR_3033_ACCEPTS, STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO}, -{ WWT_PUSHTXTBTN, 14, 166, 248, 198, 209, STR_0130_RENAME, STR_3055_CHANGE_NAME_OF_STATION}, +{ WWT_PUSHTXTBTN, 14, 0, 63, 198, 209, STR_00E4_LOCATION, STR_3053_CENTER_MAIN_VIEW_ON_STATION}, +{ WWT_PUSHTXTBTN, 14, 64, 128, 198, 209, STR_3033_ACCEPTS, STR_3056_SHOW_LIST_OF_ACCEPTED_CARGO}, +{ WWT_PUSHTXTBTN, 14, 129, 192, 198, 209, STR_0130_RENAME, STR_3055_CHANGE_NAME_OF_STATION}, +{ WWT_PUSHTXTBTN, 14, 193, 206, 198, 209, STR_TRAIN, STR_NULL }, +{ WWT_PUSHTXTBTN, 14, 207, 220, 198, 209, STR_LORRY, STR_NULL }, +{ WWT_PUSHTXTBTN, 14, 221, 234, 198, 209, STR_PLANE, STR_NULL }, +{ WWT_PUSHTXTBTN, 14, 235, 248, 198, 209, STR_SHIP, STR_NULL }, { WIDGETS_END}, }; @@ -277,9 +281,13 @@ static const Widget _station_view_widgets[] = { { WWT_SCROLLBAR, 14, 238, 248, 14, 65, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, { WWT_IMGBTN, 14, 0, 248, 66, 97, 0x0, STR_NULL}, { WWT_EMPTY, 0, 0, 0, 0, 0, 0x0, STR_NULL}, -{ WWT_PUSHTXTBTN, 14, 0, 82, 98, 109, STR_00E4_LOCATION, STR_3053_CENTER_MAIN_VIEW_ON_STATION}, -{ WWT_PUSHTXTBTN, 14, 83, 165, 98, 109, STR_3032_RATINGS, STR_3054_SHOW_STATION_RATINGS}, -{ WWT_PUSHTXTBTN, 14, 166, 248, 98, 109, STR_0130_RENAME, STR_3055_CHANGE_NAME_OF_STATION}, +{ WWT_PUSHTXTBTN, 14, 0, 63, 98, 109, STR_00E4_LOCATION, STR_3053_CENTER_MAIN_VIEW_ON_STATION}, +{ WWT_PUSHTXTBTN, 14, 64, 128, 98, 109, STR_3032_RATINGS, STR_3054_SHOW_STATION_RATINGS}, +{ WWT_PUSHTXTBTN, 14, 129, 192, 98, 109, STR_0130_RENAME, STR_3055_CHANGE_NAME_OF_STATION}, +{ WWT_PUSHTXTBTN, 14, 193, 206, 98, 109, STR_TRAIN, STR_NULL }, +{ WWT_PUSHTXTBTN, 14, 207, 220, 98, 109, STR_LORRY, STR_NULL }, +{ WWT_PUSHTXTBTN, 14, 221, 234, 98, 109, STR_PLANE, STR_NULL }, +{ WWT_PUSHTXTBTN, 14, 235, 248, 98, 109, STR_SHIP, STR_NULL }, { WIDGETS_END}, }; @@ -310,6 +318,13 @@ static void DrawStationViewWindow(Window *w) SetVScrollCount(w, num); w->disabled_state = st->owner == _local_player ? 0 : (1 << 8); + + if (!(st->facilities & FACIL_TRAIN)) SETBIT(w->disabled_state, 9); + if (!(st->facilities & FACIL_TRUCK_STOP) && + !(st->facilities & FACIL_BUS_STOP)) SETBIT(w->disabled_state, 10); + if (!(st->facilities & FACIL_AIRPORT)) SETBIT(w->disabled_state, 11); + if (!(st->facilities & FACIL_DOCK)) SETBIT(w->disabled_state, 12); + SetDParam(0, st->index); SetDParam(1, st->facilities); DrawWindowWidgets(w); @@ -443,6 +458,30 @@ static void StationViewWndProc(Window *w, WindowEvent *e) SetDParam(1, st->town->townnameparts); ShowQueryString(st->string_id, STR_3030_RENAME_STATION_LOADING, 31, 180, w->window_class, w->window_number); } break; + + case 9: { + const Station *st = DEREF_STATION(w->window_number); + ShowPlayerTrains(st->owner, w->window_number); + break; + } + + case 10: { + const Station *st = DEREF_STATION(w->window_number); + ShowPlayerRoadVehicles(st->owner, w->window_number); + break; + } + + case 11: { + const Station *st = DEREF_STATION(w->window_number); + ShowPlayerAircraft(st->owner, w->window_number); + break; + } + + case 12: { + const Station *st = DEREF_STATION(w->window_number); + ShowPlayerShips(st->owner, w->window_number); + break; + } } break; @@ -456,6 +495,17 @@ static void StationViewWndProc(Window *w, WindowEvent *e) st = DEREF_STATION(w->window_number); DoCommandP(st->xy, w->window_number, 0, NULL, CMD_RENAME_STATION | CMD_MSG(STR_3031_CAN_T_RENAME_STATION)); } break; + + case WE_DESTROY: { + WindowNumber wno = + (w->window_number << 16) | DEREF_STATION(w->window_number)->owner; + + DeleteWindowById(WC_TRAINS_LIST, wno); + DeleteWindowById(WC_ROADVEH_LIST, wno); + DeleteWindowById(WC_SHIPS_LIST, wno); + DeleteWindowById(WC_AIRCRAFT_LIST, wno); + break; + } } } diff --git a/train_cmd.c b/train_cmd.c index 1b79001fc5..256ccb6d54 100644 --- a/train_cmd.c +++ b/train_cmd.c @@ -499,8 +499,7 @@ int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) NormalizeTrainVehInDepot(v); InvalidateWindow(WC_VEHICLE_DEPOT, tile); - _vehicle_sort_dirty[VEHTRAIN] = true; // build a trainengine - InvalidateWindow(WC_TRAINS_LIST, v->owner); + RebuildVehicleLists(); InvalidateWindow(WC_COMPANY, v->owner); } } @@ -811,8 +810,7 @@ int32 CmdSellRailWagon(int x, int y, uint32 flags, uint32 p1, uint32 p2) // always redraw the depot. maybe redraw train list InvalidateWindow(WC_VEHICLE_DEPOT, first->tile); if (first->subtype == 0) { - _vehicle_sort_dirty[VEHTRAIN] = true; // sell a wagon / locomotive - InvalidateWindow(WC_TRAINS_LIST, first->owner); + RebuildVehicleLists(); } // when selling an attached locomotive. we need to delete its window. if (v->subtype == 0) { @@ -2254,8 +2252,7 @@ static void DeleteLastWagon(Vehicle *v) InvalidateWindow(WC_VEHICLE_DETAILS, v->index); DeleteWindowById(WC_VEHICLE_VIEW, v->index); - _vehicle_sort_dirty[VEHTRAIN] = true; // remove crashed train - InvalidateWindow(WC_TRAINS_LIST, v->owner); + RebuildVehicleLists(); InvalidateWindow(WC_COMPANY, v->owner); BeginVehicleMove(v); diff --git a/train_gui.c b/train_gui.c index 79ba7d27f9..e05778ea93 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; +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}, +}; - // 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; - - 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; + int x = 2; + int y = PLY_WND_PRC__OFFSET_TOP_WIDGET; + int max; + int i; - if (_train_sort_type[window_number] == SORT_BY_UNSORTED) // disable 'Sort By' tooltip on Unsorted sorting criteria + BuildVehicleList(vl, VEH_Train, owner, station); + SortVehicleList(vl); + + SetVScrollCount(w, vl->list_length); + + // disable 'Sort By' tooltip on Unsorted sorting criteria + if (vl->sort_type == SORT_BY_UNSORTED) w->disabled_state |= (1 << 2); - // resort trains window if roadvehicles have been added/removed - if (_vehicle_sort_dirty[VEHTRAIN]) - GlobalSortTrainList(); - - if (_train_sort_dirty[window_number]) { - MakeSortedTrainList(window_number); - /* reset sorting timeout */ - w->custom[0] = DAY_TICKS; - w->custom[1] = PERIODIC_RESORT_DAYS; - } - - // 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); - /* 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->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); - 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 + 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; diff --git a/vehicle.c b/vehicle.c index 1701ff70e7..145d225613 100644 --- a/vehicle.c +++ b/vehicle.c @@ -1449,10 +1449,7 @@ int32 CmdNameVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) StringID old_str = v->string_id; v->string_id = str; DeleteName(old_str); - _train_sort_dirty[v->owner] = true; - _aircraft_sort_dirty[v->owner] = true; - _ship_sort_dirty[v->owner] = true; - _road_sort_dirty[v->owner] = true; + ResortVehicleLists(); MarkWholeScreenDirty(); } else { DeleteName(str); diff --git a/vehicle_gui.c b/vehicle_gui.c index 9e2edc6cbd..5dd09734d0 100644 --- a/vehicle_gui.c +++ b/vehicle_gui.c @@ -2,6 +2,7 @@ #include "ttd.h" #include "table/strings.h" #include "vehicle.h" +#include "window.h" VehicleSortListingTypeFunctions * const _vehicle_sorter[] = { &VehicleUnsortedSorter, @@ -28,14 +29,109 @@ const StringID _vehicle_sort_listing[] = { INVALID_STRING_ID }; +void RebuildVehicleLists(void) +{ + Window *w; + + for (w = _windows; w != _last_window; ++w) + switch (w->window_class) { + case WC_TRAINS_LIST: + case WC_ROADVEH_LIST: + case WC_SHIPS_LIST: + case WC_AIRCRAFT_LIST: + WP(w, vehiclelist_d).flags |= VL_REBUILD; + SetWindowDirty(w); + break; + + default: + break; + } +} + +void ResortVehicleLists(void) +{ + Window *w; + + for (w = _windows; w != _last_window; ++w) + switch (w->window_class) { + case WC_TRAINS_LIST: + case WC_ROADVEH_LIST: + case WC_SHIPS_LIST: + case WC_AIRCRAFT_LIST: + WP(w, vehiclelist_d).flags |= VL_RESORT; + SetWindowDirty(w); + break; + + default: + break; + } +} + +void BuildVehicleList(vehiclelist_d *vl, int type, int owner, int station) +{ + SortStruct sort_list[NUM_NORMAL_VEHICLES]; + int subtype = (type != VEH_Aircraft) ? 0 : 2; + int n = 0; + int i; + + if (!(vl->flags & VL_REBUILD)) return; + + DEBUG(misc, 1) ("Building vehicle list for player %d station %d...", + owner, station); + + if (station != -1) { + const Vehicle *v; + FOR_ALL_VEHICLES(v) { + if (v->type == type && v->subtype <= subtype) { + const Order *ord; + for (ord = v->schedule_ptr; ord->type != OT_NOTHING; ++ord) + if (ord->type == OT_GOTO_STATION && ord->station == station) { + sort_list[n].index = v - _vehicles; + sort_list[n].owner = v->owner; + ++n; + break; + } + } + } + } else { + const Vehicle *v; + FOR_ALL_VEHICLES(v) { + if (v->type == type && v->subtype <= subtype && v->owner == owner) { + sort_list[n].index = v - _vehicles; + sort_list[n].owner = v->owner; + ++n; + } + } + } + + vl->sort_list = realloc(vl->sort_list, n * sizeof(vl->sort_list[0])); /* XXX unchecked malloc */ + vl->list_length = n; + + for (i = 0; i < n; ++i) + vl->sort_list[i] = sort_list[i]; + + vl->flags &= ~VL_REBUILD; + vl->flags |= VL_RESORT; +} + +void SortVehicleList(vehiclelist_d *vl) +{ + if (!(vl->flags & VL_RESORT)) return; + + _internal_sort_order = vl->flags & VL_DESC; + _internal_name_sorter_id = STR_SV_TRAIN_NAME; + _last_vehicle_idx = 0; // used for "cache" in namesorting + qsort(vl->sort_list, vl->list_length, sizeof(vl->sort_list[0]), + _vehicle_sorter[vl->sort_type]); + + vl->resort_timer = DAY_TICKS * PERIODIC_RESORT_DAYS; + vl->flags &= ~VL_RESORT; +} + + /* General Vehicle GUI based procedures that are independent of vehicle types */ void InitializeVehiclesGuiList() { - memset(_train_sort_dirty, true, sizeof(_train_sort_dirty)); - memset(_aircraft_sort_dirty, true, sizeof(_aircraft_sort_dirty)); - memset(_ship_sort_dirty, true, sizeof(_ship_sort_dirty)); - memset(_road_sort_dirty, true, sizeof(_road_sort_dirty)); - memset(_vehicle_sort_dirty, true, sizeof(_vehicle_sort_dirty)); } // draw the vehicle profit button in the vehicle list window. diff --git a/vehicle_gui.h b/vehicle_gui.h index 3883967f0f..9339d4647b 100644 --- a/vehicle_gui.h +++ b/vehicle_gui.h @@ -1,10 +1,18 @@ #ifndef VEHICLE_GUI_H #define VEHICLE_GUI_H +struct vehiclelist_d; + void DrawVehicleProfitButton(Vehicle *v, int x, int y); void InitializeVehiclesGuiList(); /* sorter stuff */ +void RebuildVehicleLists(void); +void ResortVehicleLists(void); + +void BuildVehicleList(struct vehiclelist_d *vl, int type, int owner, int station); +void SortVehicleList(struct vehiclelist_d *vl); + typedef struct SortStruct { // store owner through sorting process uint32 index; byte owner; @@ -42,24 +50,6 @@ enum VehicleSortTypes { VEHAIRCRAFT = 3 }; -VARDEF bool _vehicle_sort_dirty[4]; // global sort, vehicles added/removed (4 types of vehicles) - -VARDEF bool _train_sort_dirty[MAX_PLAYERS]; // vehicles for a given player needs to be resorted (new criteria) -VARDEF byte _train_sort_type[MAX_PLAYERS]; // different criteria for sorting -VARDEF bool _train_sort_order[MAX_PLAYERS]; // sort descending/ascending - -VARDEF bool _aircraft_sort_dirty[MAX_PLAYERS]; // vehicles for a given player needs to be resorted (new criteria) -VARDEF byte _aircraft_sort_type[MAX_PLAYERS]; // different criteria for sorting -VARDEF bool _aircraft_sort_order[MAX_PLAYERS]; // sort descending/ascending - -VARDEF bool _ship_sort_dirty[MAX_PLAYERS]; // vehicles for a given player needs to be resorted (new criteria) -VARDEF byte _ship_sort_type[MAX_PLAYERS]; // different criteria for sorting -VARDEF bool _ship_sort_order[MAX_PLAYERS]; // sort descending/ascending - -VARDEF bool _road_sort_dirty[MAX_PLAYERS]; // vehicles for a given player needs to be resorted (new criteria) -VARDEF byte _road_sort_type[MAX_PLAYERS]; // different criteria for sorting -VARDEF bool _road_sort_order[MAX_PLAYERS]; // sort descending/ascending - enum { PLY_WND_PRC__OFFSET_TOP_WIDGET = 26, PLY_WND_PRC__SIZE_OF_ROW_SMALL = 26, diff --git a/water_cmd.c b/water_cmd.c index 9a7db7ad30..8682e59119 100644 --- a/water_cmd.c +++ b/water_cmd.c @@ -533,8 +533,7 @@ static void FloodVehicle(Vehicle *v) v->vehstatus |= VS_CRASHED; v->u.road.crashed_ctr = 2000; // max 2220, disappear pretty fast - _vehicle_sort_dirty[VEHROAD] = true; - InvalidateWindow(WC_ROADVEH_LIST, v->owner); + RebuildVehicleLists(); } else if (v->type == VEH_Train) { @@ -550,8 +549,7 @@ static void FloodVehicle(Vehicle *v) v = u; v->u.rail.crash_anim_pos = 4000; // max 4440, disappear pretty fast - _vehicle_sort_dirty[VEHTRAIN] = true; - InvalidateWindow(WC_TRAINS_LIST, v->owner); + RebuildVehicleLists(); } else return; diff --git a/window.h b/window.h index ee955ddf90..68a29fa730 100644 --- a/window.h +++ b/window.h @@ -1,6 +1,8 @@ #ifndef WINDOW_H #define WINDOW_H +#include "vehicle_gui.h" + typedef union WindowEvent WindowEvent; //typedef void WindowProc(Window *w, int event, int wparam, long lparam); @@ -288,6 +290,21 @@ typedef struct { NewsItem *ni; } news_d; +typedef enum VehicleListFlags { + VL_DESC = 0x01, + VL_RESORT = 0x02, + VL_REBUILD = 0x04 +} VehicleListFlags; + +typedef struct vehiclelist_d { + SortStruct *sort_list; + uint16 list_length; + byte sort_type; + VehicleListFlags flags; + uint16 resort_timer; +} vehiclelist_d; +assert_compile(sizeof(vehiclelist_d) <= WINDOW_CUSTOM_SIZE); + enum WindowEvents { WE_CLICK = 0, WE_PAINT = 1,