27 #include "settings_type.h" |
27 #include "settings_type.h" |
28 #include "gfx_func.h" |
28 #include "gfx_func.h" |
29 #include "widgets/dropdown_func.h" |
29 #include "widgets/dropdown_func.h" |
30 #include "string_func.h" |
30 #include "string_func.h" |
31 #include "window_gui.h" |
31 #include "window_gui.h" |
|
32 #include "engine_gui.h" |
32 |
33 |
33 #include "table/sprites.h" |
34 #include "table/sprites.h" |
34 #include "table/strings.h" |
35 #include "table/strings.h" |
35 |
36 |
36 enum BuildVehicleWidgets { |
37 enum BuildVehicleWidgets { |
504 SetDParam(1, (GetCargo(rvi->cargo_type)->weight * GetEngineProperty(engine_number, 0x14, rvi->capacity) >> 4) + weight); |
505 SetDParam(1, (GetCargo(rvi->cargo_type)->weight * GetEngineProperty(engine_number, 0x14, rvi->capacity) >> 4) + weight); |
505 DrawString(x, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT, TC_FROMSTRING); |
506 DrawString(x, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT, TC_FROMSTRING); |
506 y += 10; |
507 y += 10; |
507 |
508 |
508 /* Wagon speed limit, displayed if above zero */ |
509 /* Wagon speed limit, displayed if above zero */ |
509 if (_settings.vehicle.wagon_speed_limits) { |
510 if (_settings_game.vehicle.wagon_speed_limits) { |
510 uint max_speed = GetEngineProperty(engine_number, 0x09, rvi->max_speed); |
511 uint max_speed = GetEngineProperty(engine_number, 0x09, rvi->max_speed); |
511 if (max_speed > 0) { |
512 if (max_speed > 0) { |
512 SetDParam(0, max_speed * 10 / 16); |
513 SetDParam(0, max_speed * 10 / 16); |
513 DrawString(x, y, STR_PURCHASE_INFO_SPEED, TC_FROMSTRING); |
514 DrawString(x, y, STR_PURCHASE_INFO_SPEED, TC_FROMSTRING); |
514 y += 10; |
515 y += 10; |
542 SetDParam(1, GetEngineProperty(engine_number, 0x0B, rvi->power)); |
543 SetDParam(1, GetEngineProperty(engine_number, 0x0B, rvi->power)); |
543 DrawString(x, y, STR_PURCHASE_INFO_SPEED_POWER, TC_FROMSTRING); |
544 DrawString(x, y, STR_PURCHASE_INFO_SPEED_POWER, TC_FROMSTRING); |
544 y += 10; |
545 y += 10; |
545 |
546 |
546 /* Max tractive effort - not applicable if old acceleration or maglev */ |
547 /* Max tractive effort - not applicable if old acceleration or maglev */ |
547 if (_settings.vehicle.realistic_acceleration && rvi->railtype != RAILTYPE_MAGLEV) { |
548 if (_settings_game.vehicle.realistic_acceleration && rvi->railtype != RAILTYPE_MAGLEV) { |
548 SetDParam(0, ((weight << multihead) * 10 * GetEngineProperty(engine_number, 0x1F, rvi->tractive_effort)) / 256); |
549 SetDParam(0, ((weight << multihead) * 10 * GetEngineProperty(engine_number, 0x1F, rvi->tractive_effort)) / 256); |
549 DrawString(x, y, STR_PURCHASE_INFO_MAX_TE, TC_FROMSTRING); |
550 DrawString(x, y, STR_PURCHASE_INFO_MAX_TE, TC_FROMSTRING); |
550 y += 10; |
551 y += 10; |
551 } |
552 } |
552 |
553 |
742 * @param min where to start in the list |
743 * @param min where to start in the list |
743 * @param max where in the list to end |
744 * @param max where in the list to end |
744 * @param selected_id what engine to highlight as selected, if any |
745 * @param selected_id what engine to highlight as selected, if any |
745 * @param count_location Offset to print the engine count (used by autoreplace). 0 means it's off |
746 * @param count_location Offset to print the engine count (used by autoreplace). 0 means it's off |
746 */ |
747 */ |
747 void DrawEngineList(VehicleType type, int x, int y, const EngineList eng_list, uint16 min, uint16 max, EngineID selected_id, int count_location, GroupID selected_group) |
748 void DrawEngineList(VehicleType type, int x, int y, const GUIEngineList *eng_list, uint16 min, uint16 max, EngineID selected_id, int count_location, GroupID selected_group) |
748 { |
749 { |
749 byte step_size = GetVehicleListHeight(type); |
750 byte step_size = GetVehicleListHeight(type); |
750 byte x_offset = 0; |
751 byte x_offset = 0; |
751 byte y_offset = 0; |
752 byte y_offset = 0; |
752 |
753 |
753 assert(max <= eng_list.size()); |
754 assert(max <= eng_list->Length()); |
754 |
755 |
755 switch (type) { |
756 switch (type) { |
756 case VEH_TRAIN: |
757 case VEH_TRAIN: |
757 x++; // train and road vehicles use the same offset, except trains are one more pixel to the right |
758 x++; // train and road vehicles use the same offset, except trains are one more pixel to the right |
758 /* Fallthough */ |
759 /* Fallthough */ |
776 break; |
777 break; |
777 default: NOT_REACHED(); |
778 default: NOT_REACHED(); |
778 } |
779 } |
779 |
780 |
780 for (; min < max; min++, y += step_size) { |
781 for (; min < max; min++, y += step_size) { |
781 const EngineID engine = eng_list[min]; |
782 const EngineID engine = (*eng_list)[min]; |
782 /* Note: num_engines is only used in the autoreplace GUI, so it is correct to use _local_player here. */ |
783 /* Note: num_engines is only used in the autoreplace GUI, so it is correct to use _local_player here. */ |
783 const uint num_engines = GetGroupNumEngines(_local_player, selected_group, engine); |
784 const uint num_engines = GetGroupNumEngines(_local_player, selected_group, engine); |
784 |
785 |
785 SetDParam(0, engine); |
786 SetDParam(0, engine); |
786 DrawString(x + x_offset, y, STR_ENGINE_NAME, engine == selected_id ? TC_WHITE : TC_BLACK); |
787 DrawString(x + x_offset, y, STR_ENGINE_NAME, engine == selected_id ? TC_WHITE : TC_BLACK); |
803 bool descending_sort_order; |
804 bool descending_sort_order; |
804 byte sort_criteria; |
805 byte sort_criteria; |
805 bool regenerate_list; |
806 bool regenerate_list; |
806 EngineID sel_engine; |
807 EngineID sel_engine; |
807 EngineID rename_engine; |
808 EngineID rename_engine; |
808 EngineList eng_list; |
809 GUIEngineList eng_list; |
809 |
810 |
810 BuildVehicleWindow(const WindowDesc *desc, TileIndex tile, VehicleType type) : Window(desc, tile == 0 ? (int)type : tile) |
811 BuildVehicleWindow(const WindowDesc *desc, TileIndex tile, VehicleType type) : Window(desc, tile == 0 ? (int)type : tile) |
811 { |
812 { |
812 this->vehicle_type = type; |
813 this->vehicle_type = type; |
813 int vlh = GetVehicleListHeight(this->vehicle_type); |
814 int vlh = GetVehicleListHeight(this->vehicle_type); |
845 this->SetupWindowStrings(type); |
846 this->SetupWindowStrings(type); |
846 ResizeButtons(this, BUILD_VEHICLE_WIDGET_BUILD, BUILD_VEHICLE_WIDGET_RENAME); |
847 ResizeButtons(this, BUILD_VEHICLE_WIDGET_BUILD, BUILD_VEHICLE_WIDGET_RENAME); |
847 |
848 |
848 this->GenerateBuildList(); // generate the list, since we need it in the next line |
849 this->GenerateBuildList(); // generate the list, since we need it in the next line |
849 /* Select the first engine in the list as default when opening the window */ |
850 /* Select the first engine in the list as default when opening the window */ |
850 if (this->eng_list.size() > 0) this->sel_engine = this->eng_list[0]; |
851 if (this->eng_list.Length() > 0) this->sel_engine = this->eng_list[0]; |
851 |
852 |
852 this->FindWindowPlacementAndResize(desc); |
853 this->FindWindowPlacementAndResize(desc); |
853 } |
854 } |
854 |
855 |
855 /* Setup widget strings to fit the different types of vehicles */ |
856 /* Setup widget strings to fit the different types of vehicles */ |
903 int num_engines = 0; |
904 int num_engines = 0; |
904 int num_wagons = 0; |
905 int num_wagons = 0; |
905 |
906 |
906 this->filter.railtype = (this->window_number <= VEH_END) ? RAILTYPE_END : GetRailType(this->window_number); |
907 this->filter.railtype = (this->window_number <= VEH_END) ? RAILTYPE_END : GetRailType(this->window_number); |
907 |
908 |
908 this->eng_list.clear(); |
909 this->eng_list.Clear(); |
909 |
910 |
910 /* Make list of all available train engines and wagons. |
911 /* Make list of all available train engines and wagons. |
911 * Also check to see if the previously selected engine is still available, |
912 * Also check to see if the previously selected engine is still available, |
912 * and if not, reset selection to INVALID_ENGINE. This could be the case |
913 * and if not, reset selection to INVALID_ENGINE. This could be the case |
913 * when engines become obsolete and are removed */ |
914 * when engines become obsolete and are removed */ |
917 const RailVehicleInfo *rvi = &e->u.rail; |
918 const RailVehicleInfo *rvi = &e->u.rail; |
918 |
919 |
919 if (this->filter.railtype != RAILTYPE_END && !HasPowerOnRail(rvi->railtype, this->filter.railtype)) continue; |
920 if (this->filter.railtype != RAILTYPE_END && !HasPowerOnRail(rvi->railtype, this->filter.railtype)) continue; |
920 if (!IsEngineBuildable(eid, VEH_TRAIN, _local_player)) continue; |
921 if (!IsEngineBuildable(eid, VEH_TRAIN, _local_player)) continue; |
921 |
922 |
922 this->eng_list.push_back(eid); |
923 *this->eng_list.Append() = eid; |
|
924 |
923 if (rvi->railveh_type != RAILVEH_WAGON) { |
925 if (rvi->railveh_type != RAILVEH_WAGON) { |
924 num_engines++; |
926 num_engines++; |
925 } else { |
927 } else { |
926 num_wagons++; |
928 num_wagons++; |
927 } |
929 } |
946 /* Figure out what road vehicle EngineIDs to put in the list */ |
948 /* Figure out what road vehicle EngineIDs to put in the list */ |
947 void GenerateBuildRoadVehList() |
949 void GenerateBuildRoadVehList() |
948 { |
950 { |
949 EngineID sel_id = INVALID_ENGINE; |
951 EngineID sel_id = INVALID_ENGINE; |
950 |
952 |
951 this->eng_list.clear(); |
953 this->eng_list.Clear(); |
952 |
954 |
953 const Engine *e; |
955 const Engine *e; |
954 FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) { |
956 FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) { |
955 EngineID eid = e->index; |
957 EngineID eid = e->index; |
956 if (!IsEngineBuildable(eid, VEH_ROAD, _local_player)) continue; |
958 if (!IsEngineBuildable(eid, VEH_ROAD, _local_player)) continue; |
957 if (!HasBit(this->filter.roadtypes, HasBit(EngInfo(eid)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD)) continue; |
959 if (!HasBit(this->filter.roadtypes, HasBit(EngInfo(eid)->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD)) continue; |
958 this->eng_list.push_back(eid); |
960 *this->eng_list.Append() = eid; |
959 |
961 |
960 if (eid == this->sel_engine) sel_id = eid; |
962 if (eid == this->sel_engine) sel_id = eid; |
961 } |
963 } |
962 this->sel_engine = sel_id; |
964 this->sel_engine = sel_id; |
963 } |
965 } |
964 |
966 |
965 /* Figure out what ship EngineIDs to put in the list */ |
967 /* Figure out what ship EngineIDs to put in the list */ |
966 void GenerateBuildShipList() |
968 void GenerateBuildShipList() |
967 { |
969 { |
968 EngineID sel_id = INVALID_ENGINE; |
970 EngineID sel_id = INVALID_ENGINE; |
969 this->eng_list.clear(); |
971 this->eng_list.Clear(); |
970 |
972 |
971 const Engine *e; |
973 const Engine *e; |
972 FOR_ALL_ENGINES_OF_TYPE(e, VEH_SHIP) { |
974 FOR_ALL_ENGINES_OF_TYPE(e, VEH_SHIP) { |
973 EngineID eid = e->index; |
975 EngineID eid = e->index; |
974 if (!IsEngineBuildable(eid, VEH_SHIP, _local_player)) continue; |
976 if (!IsEngineBuildable(eid, VEH_SHIP, _local_player)) continue; |
975 this->eng_list.push_back(eid); |
977 *this->eng_list.Append() = eid; |
976 |
978 |
977 if (eid == this->sel_engine) sel_id = eid; |
979 if (eid == this->sel_engine) sel_id = eid; |
978 } |
980 } |
979 this->sel_engine = sel_id; |
981 this->sel_engine = sel_id; |
980 } |
982 } |
982 /* Figure out what aircraft EngineIDs to put in the list */ |
984 /* Figure out what aircraft EngineIDs to put in the list */ |
983 void GenerateBuildAircraftList() |
985 void GenerateBuildAircraftList() |
984 { |
986 { |
985 EngineID sel_id = INVALID_ENGINE; |
987 EngineID sel_id = INVALID_ENGINE; |
986 |
988 |
987 this->eng_list.clear(); |
989 this->eng_list.Clear(); |
988 |
990 |
989 /* Make list of all available planes. |
991 /* Make list of all available planes. |
990 * Also check to see if the previously selected plane is still available, |
992 * Also check to see if the previously selected plane is still available, |
991 * and if not, reset selection to INVALID_ENGINE. This could be the case |
993 * and if not, reset selection to INVALID_ENGINE. This could be the case |
992 * when planes become obsolete and are removed */ |
994 * when planes become obsolete and are removed */ |
995 EngineID eid = e->index; |
997 EngineID eid = e->index; |
996 if (!IsEngineBuildable(eid, VEH_AIRCRAFT, _local_player)) continue; |
998 if (!IsEngineBuildable(eid, VEH_AIRCRAFT, _local_player)) continue; |
997 /* First VEH_END window_numbers are fake to allow a window open for all different types at once */ |
999 /* First VEH_END window_numbers are fake to allow a window open for all different types at once */ |
998 if (this->window_number > VEH_END && !CanAircraftUseStation(eid, this->window_number)) continue; |
1000 if (this->window_number > VEH_END && !CanAircraftUseStation(eid, this->window_number)) continue; |
999 |
1001 |
1000 this->eng_list.push_back(eid); |
1002 *this->eng_list.Append() = eid; |
1001 if (eid == this->sel_engine) sel_id = eid; |
1003 if (eid == this->sel_engine) sel_id = eid; |
1002 } |
1004 } |
1003 |
1005 |
1004 this->sel_engine = sel_id; |
1006 this->sel_engine = sel_id; |
1005 } |
1007 } |
1102 if (this->regenerate_list) { |
1104 if (this->regenerate_list) { |
1103 this->regenerate_list = false; |
1105 this->regenerate_list = false; |
1104 this->GenerateBuildList(); |
1106 this->GenerateBuildList(); |
1105 } |
1107 } |
1106 |
1108 |
1107 uint max = min(this->vscroll.pos + this->vscroll.cap, this->eng_list.size()); |
1109 uint max = min(this->vscroll.pos + this->vscroll.cap, this->eng_list.Length()); |
1108 |
1110 |
1109 this->SetWidgetDisabledState(BUILD_VEHICLE_WIDGET_BUILD, this->window_number <= VEH_END); |
1111 this->SetWidgetDisabledState(BUILD_VEHICLE_WIDGET_BUILD, this->window_number <= VEH_END); |
1110 |
1112 |
1111 SetVScrollCount(this, this->eng_list.size()); |
1113 SetVScrollCount(this, this->eng_list.Length()); |
1112 SetDParam(0, this->filter.railtype + STR_881C_NEW_RAIL_VEHICLES); // This should only affect rail vehicles |
1114 SetDParam(0, this->filter.railtype + STR_881C_NEW_RAIL_VEHICLES); // This should only affect rail vehicles |
1113 |
1115 |
1114 /* Set text of sort by dropdown */ |
1116 /* Set text of sort by dropdown */ |
1115 this->widget[BUILD_VEHICLE_WIDGET_SORT_DROPDOWN].data = _sort_listing[this->vehicle_type][this->sort_criteria]; |
1117 this->widget[BUILD_VEHICLE_WIDGET_SORT_DROPDOWN].data = _sort_listing[this->vehicle_type][this->sort_criteria]; |
1116 |
1118 |
1117 this->DrawWidgets(); |
1119 this->DrawWidgets(); |
1118 |
1120 |
1119 DrawEngineList(this->vehicle_type, this->widget[BUILD_VEHICLE_WIDGET_LIST].left + 2, this->widget[BUILD_VEHICLE_WIDGET_LIST].top + 1, this->eng_list, this->vscroll.pos, max, this->sel_engine, 0, DEFAULT_GROUP); |
1121 DrawEngineList(this->vehicle_type, this->widget[BUILD_VEHICLE_WIDGET_LIST].left + 2, this->widget[BUILD_VEHICLE_WIDGET_LIST].top + 1, &this->eng_list, this->vscroll.pos, max, this->sel_engine, 0, DEFAULT_GROUP); |
1120 |
1122 |
1121 if (this->sel_engine != INVALID_ENGINE) { |
1123 if (this->sel_engine != INVALID_ENGINE) { |
1122 const Widget *wi = &this->widget[BUILD_VEHICLE_WIDGET_PANEL]; |
1124 const Widget *wi = &this->widget[BUILD_VEHICLE_WIDGET_PANEL]; |
1123 int text_end = DrawVehiclePurchaseInfo(2, wi->top + 1, wi->right - wi->left - 2, this->sel_engine); |
1125 int text_end = DrawVehiclePurchaseInfo(2, wi->top + 1, wi->right - wi->left - 2, this->sel_engine); |
1124 |
1126 |