diff options
Diffstat (limited to 'ship_gui.c')
-rw-r--r-- | ship_gui.c | 278 |
1 files changed, 194 insertions, 84 deletions
diff --git a/ship_gui.c b/ship_gui.c index 293132275..12f927b2b 100644 --- a/ship_gui.c +++ b/ship_gui.c @@ -9,7 +9,6 @@ #include "station.h" #include "command.h" #include "player.h" -//#include "town.h" #include "engine.h" @@ -868,100 +867,175 @@ 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 MakeSortedShiptList(byte owner) +{ + SortStruct *firstelement; + Vehicle *v; + uint32 n = 0; + uint16 *i; + + if (_vehicle_sort_dirty[VEHSHIP]) { // only resort the whole array if vehicles have been added/removed + // reset to 0 just to be sure + 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 trains of player + } + } + + // create cumulative ship-ownage + // 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);} + + + // sort by owner, then only subsort the requested owner-vehicles + qsort(_ship_sort, n, sizeof(_ship_sort[0]), GeneralOwnerSorter); + + _last_vehicle_idx = 0; // used for "cache" in namesorting + _vehicle_sort_dirty[VEHSHIP] = false; + } + + 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_type = _ship_sort_type[owner]; + _internal_sort_order = _ship_sort_order[owner]; + _internal_name_sorter_id = STR_SV_SHIP_NAME; + // only name sorting needs a different procedure, all others are handled by the general sorter + qsort(firstelement, n, sizeof(_ship_sort[0]), (_internal_sort_type == SORT_BY_NAME) ? VehicleNameSorter : GeneralVehicleSorter); + + DEBUG(misc, 1) ("Resorting Ships list player %d...", owner+1); +} + static void PlayerShipsWndProc(Window *w, WindowEvent *e) { switch(e->event) { - case WE_PAINT: - /* determine amount of items for scroller */ - { - Vehicle *v; - int num = 0; - byte owner = (byte)w->window_number; - - FOR_ALL_VEHICLES(v) { - if (v->type == VEH_Ship && v->owner == owner) - num++; - } - SetVScrollCount(w, num); + case WE_PAINT: { + uint32 i; + const byte window_number = (byte)w->window_number; + + if (_ship_sort_type[window_number] == SORT_BY_UNSORTED) // disable 'Sort By' tooltip on Unsorted sorting criteria + w->disabled_state |= (1 << 3); + + if (_ship_sort_dirty[window_number] || _vehicle_sort_dirty[VEHSHIP]) { + _ship_sort_dirty[window_number] = false; + MakeSortedShiptList(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(w->window_number); + Player *p = DEREF_PLAYER(window_number); + /* Company Name -- (###) Ships */ SET_DPARAM16(0, p->name_1); SET_DPARAM32(1, p->name_2); + SET_DPARAM16(2, w->vscroll.count); + SET_DPARAM16(3, _vehicle_sort_listing[_ship_sort_type[window_number]]); DrawWindowWidgets(w); } + /* draw arrow pointing up/down for ascending/descending soring */ + DoDrawString(_ship_sort_order[window_number] & 1 ? "\xAA" : "\xA0", 85, 15, 0x10); - /* draw the ships vehicles */ + /* draw the ship vehicles */ { Vehicle *v; - int pos = w->vscroll.pos; - byte owner = (byte)w->window_number; - int x = 2; - int y = 15; - - FOR_ALL_VEHICLES(v) { - if (v->type == VEH_Ship && v->owner == owner && - --pos < 0 && pos >= -4) { - StringID str; - - DrawShipImage(v, x + 19, y + 6, INVALID_VEHICLE); - DrawVehicleProfitButton(v, x, y+13); - - SET_DPARAM16(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); + 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 + + while (i < _num_ship_sort[window_number]) { + StringID str; + v = DEREF_VEHICLE(_ship_sort[i].index); + + DrawShipImage(v, x + 19, y + 6, INVALID_VEHICLE); + DrawVehicleProfitButton(v, x, y+13); + + SET_DPARAM16(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); - SET_DPARAM32(0, v->profit_this_year); - SET_DPARAM32(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) { - SET_DPARAM16(0, v->string_id); - DrawString(x+12, y, STR_01AB, 0); - } + SET_DPARAM32(0, v->profit_this_year); + SET_DPARAM32(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) { + SET_DPARAM16(0, v->string_id); + DrawString(x+12, y, STR_01AB, 0); + } + + DrawSmallShipSchedule(v, x+138, y); - DrawSmallShipSchedule(v, x+138, y); - y += 36; - } + y += PLY_WND_PRC__SIZE_OF_ROW_BIG; + i++; // next ship + if (++n == w->vscroll.cap) { break;} // max number of ships in the window } } - break; - case WE_CLICK: + } break; + + case WE_CLICK: { switch(e->click.widget) { - case 2: { /* click ship */ - int sel; - Vehicle *v; - byte owner; - - sel = (e->click.pt.y - 14) / 36; + case 3: /* Flip sorting method ascending/descending */ + _ship_sort_order[(byte)w->window_number] ^= 1; + _ship_sort_dirty[(byte)w->window_number] = true; + SetWindowDirty(w); + break; + case 4: case 5:/* Select sorting criteria dropdown menu */ + ShowDropDownMenu(w, _vehicle_sort_listing, _ship_sort_type[(byte)w->window_number], 5, 0); // do it for widget 5 + return; + case 6: { /* Matrix to show vehicles */ + int id_v = (e->click.pt.y - PLY_WND_PRC__OFFSET_TOP_WIDGET) / PLY_WND_PRC__SIZE_OF_ROW_BIG; + + if ((uint)id_v >= w->vscroll.cap) { return;} // click out of bounds - if ((uint)sel >= 4) - break; - sel += w->vscroll.pos; - owner = (byte)w->window_number; - FOR_ALL_VEHICLES(v) { - if (v->type == VEH_Ship && v->owner == owner && --sel < 0) { - ShowShipViewWindow(v); - break; - } + id_v += w->vscroll.pos; + + { + byte owner = (byte)w->window_number; + uint16 adder = (owner == 0) ? 0 : _num_ship_sort[owner - 1]; // first element in list + Vehicle *v; + + if (id_v + adder >= _num_ship_sort[owner]) { return;} // click out of vehicle bound + + v = DEREF_VEHICLE(_ship_sort[adder+id_v].index); // add the offset id_x to that + + assert(v->type == VEH_Ship && v->owner == owner && v->owner == _ship_sort[adder+id_v].owner); + + ShowShipViewWindow(v); } - break; - } - case 4: {/* click buy */ + } break; + + case 8: { /* Build new Vehicle */ uint tile; tile = _last_built_ship_depot_tile; do { - if (_map_owner[tile] == _local_player && - IsShipDepotTile(tile)) { - + if (_map_owner[tile] == _local_player && IsShipDepotTile(tile)) { ShowShipDepotWindow(tile); ShowBuildShipWindow(tile); return; @@ -973,38 +1047,74 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e) ShowBuildShipWindow(0); } break; } + } 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 << 3); + + SetWindowDirty(w); + break; + case WE_CREATE: /* set up resort timer */ + w->custom[0] = DAY_TICKS; + w->custom[1] = 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); + } + } break; } } - static const Widget _player_ships_widgets[] = { -{ WWT_TEXTBTN, 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_MATRIX, 14, 0, 248, 14, 157, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR}, -{ WWT_SCROLLBAR, 14, 249, 259, 14, 157, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, -{ WWT_PUSHTXTBTN, 14, 0, 129, 158, 169, STR_9804_NEW_SHIPS, STR_9824_BUILD_NEW_SHIPS_REQUIRES}, -{ WWT_IMGBTN, 14, 130, 259, 158, 169, 0x0}, +{ 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_PANEL, 14, 0, 15, 14, 25, 0x0, 0}, +{ WWT_PUSHTXTBTN, 14, 16, 96, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, +{ WWT_TEXTBTN, 14, 97, 248, 14, 25, STR_02E7, 0}, +{ WWT_CLOSEBOX, 14, 249, 259, 14, 25, STR_0225, STR_SORT_TIP}, +{ 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, 0}, { WWT_LAST}, }; + static const WindowDesc _player_ships_desc = { - -1, -1, 260, 170, + -1, -1, 260, 182, WC_SHIPS_LIST,0, - WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESTORE_DPARAM, _player_ships_widgets, PlayerShipsWndProc }; static const Widget _other_player_ships_widgets[] = { -{ WWT_TEXTBTN, 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_MATRIX, 14, 0, 248, 14, 157, 0x401, STR_9823_SHIPS_CLICK_ON_SHIP_FOR}, -{ WWT_SCROLLBAR, 14, 249, 259, 14, 157, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, +{ 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_PANEL, 14, 0, 15, 14, 25, 0x0, 0}, +{ WWT_PUSHTXTBTN, 14, 16, 96, 14, 25, SRT_SORT_BY, STR_SORT_TIP}, +{ WWT_TEXTBTN, 14, 97, 248, 14, 25, STR_02E7, 0}, +{ WWT_CLOSEBOX, 14, 249, 259, 14, 25, STR_0225, STR_SORT_TIP}, +{ 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_LAST}, }; + static const WindowDesc _other_player_ships_desc = { - -1, -1, 260, 158, + -1, -1, 260, 170, WC_SHIPS_LIST,0, - WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESTORE_DPARAM, _other_player_ships_widgets, PlayerShipsWndProc }; |