diff --git a/src/cargo_type.h b/src/cargo_type.h index 402e81c1b..c84f1f490 100644 --- a/src/cargo_type.h +++ b/src/cargo_type.h @@ -63,14 +63,14 @@ enum CargoType { CT_PLASTIC = 10, CT_FIZZY_DRINKS = 11, - NUM_CARGO = 32, ///< Maximal number of cargo types in a game. + NUM_CARGO = 64, ///< Maximal number of cargo types in a game. CT_AUTO_REFIT = 0xFD, ///< Automatically choose cargo type when doing auto refitting. CT_NO_REFIT = 0xFE, ///< Do not refit cargo of a vehicle (used in vehicle orders and auto-replace/auto-new). CT_INVALID = 0xFF, ///< Invalid cargo type. }; -typedef uint32 CargoTypes; +typedef uint64 CargoTypes; static const CargoTypes ALL_CARGOTYPES = (CargoTypes)UINT32_MAX; diff --git a/src/core/bitmath_func.hpp b/src/core/bitmath_func.hpp index 31e679b00..72026fa6a 100644 --- a/src/core/bitmath_func.hpp +++ b/src/core/bitmath_func.hpp @@ -12,6 +12,8 @@ #ifndef BITMATH_FUNC_HPP #define BITMATH_FUNC_HPP +#include + /** * Fetch \a n bits from \a x, started at bit \a s. * @@ -108,6 +110,22 @@ static inline bool HasBit(const T x, const uint8 y) } /** + * Checks if a bit in a std::bitset is set. + * + * This function is a wrapper for std::bitset.test(). + * + * @param x The value to check + * @param y The position of the bit to check, started from the LSB + * @pre y < N + * @return True if the bit is set, false else. + */ +template +static inline bool HasBit(const std::bitset x, const uint8 y) +{ + return x.test(y); +} + +/** * Set a bit in a variable. * * This function sets a bit in a variable. The variable is changed @@ -126,6 +144,22 @@ static inline T SetBit(T &x, const uint8 y) } /** + * Set a bit in a std::bitset. + * + * This function is a wrapper for std::bitset.set(). + * + * @param x The variable to set a bit + * @param y The bit position to set + * @pre y < N + * @return The new value of the old value with the bit set + */ +template +static inline std::bitset SetBit(const std::bitset &x, const uint8 y) +{ + return x.set(y); +} + +/** * Sets several bits in a variable. * * This macro sets several bits in a variable. The bits to set are provided @@ -156,6 +190,22 @@ static inline T ClrBit(T &x, const uint8 y) } /** + * Clears a bit in a std::bitset. + * + * This function is a wrapper for std::bitset.clear(). + * + * @param x The variable to clear the bit + * @param y The bit position to clear + * @pre y < N + * @return The new value of the old value with the bit cleared + */ +template +static inline std::bitset ClrBit(const std::bitset &x, const uint8 y) +{ + return x.reset(y); +} + +/** * Clears several bits in a variable. * * This macro clears several bits in a variable. The bits to clear are @@ -185,6 +235,21 @@ static inline T ToggleBit(T &x, const uint8 y) return x = (T)(x ^ ((T)1U << y)); } +/** + * Toggles a bit in a std::bitset. + * + * This function is a wrapper for std::bitset.flip(). + * + * @param x The variable to toggle the bit + * @param y The bit position to toggle + * @pre y < N + * @return The new value of the old value with the bit toggled + */ +template +static inline std::bitset ToggleBit(const std::bitset &x, const uint8 y) +{ + return x.flip(y); +} /** Lookup table to check which bit is set in a 6 bit variable */ extern const uint8 _ffb_64[64]; @@ -267,6 +332,20 @@ static inline uint CountBits(T value) } /** + * Counts the number of set bits in a std::bitset. + * + * This function is a wrapper for std::bitset.count(). + * + * @param value the value to count the number of bits in. + * @return the number of bits. + */ +template +static inline uint CountBits(const std::bitset value) +{ + return (uint)value.count(); +} + +/** * Test whether \a value has exactly 1 bit set * * @param value the value to test. @@ -279,6 +358,18 @@ static inline bool HasExactlyOneBit(T value) } /** + * Test whether \a std::bitset has exactly 1 bit set. + * + * @param value the value to test. + * @return does \a value have exactly 1 bit set? + */ +template +static inline bool HasExactlyOneBit(const std::bitset value) +{ + return value.count() == 1; +} + +/** * Test whether \a value has at most 1 bit set * * @param value the value to test. diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp index c12c6ace4..b119fbffd 100644 --- a/src/graph_gui.cpp +++ b/src/graph_gui.cpp @@ -33,8 +33,8 @@ #include "safeguards.h" /* Bitmasks of company and cargo indices that shouldn't be drawn. */ -static uint _legend_excluded_companies; -static uint _legend_excluded_cargo; +static CompanyMask _legend_excluded_companies; +static CargoTypes _legend_excluded_cargo; /* Apparently these don't play well with enums. */ static const OverflowSafeInt64 INVALID_DATAPOINT(INT64_MAX); // Value used for a datapoint that shouldn't be drawn. @@ -166,14 +166,14 @@ struct ValuesInterval { struct BaseGraphWindow : Window { protected: - static const int GRAPH_MAX_DATASETS = 32; + static const int GRAPH_MAX_DATASETS = 64; static const int GRAPH_AXIS_LINE_COLOUR = PC_BLACK; static const int GRAPH_NUM_MONTHS = 24; ///< Number of months displayed in the graph. static const int MIN_GRAPH_NUM_LINES_Y = 9; ///< Minimal number of horizontal lines to draw. static const int MIN_GRID_PIXEL_SIZE = 20; ///< Minimum distance between graph lines. - uint excluded_data; ///< bitmask of the datasets that shouldn't be displayed. + std::bitset excluded_data; ///< bitmask of the datasets that shouldn't be displayed. byte num_dataset; byte num_on_x_axis; byte num_vert_lines; @@ -561,7 +561,7 @@ public: */ void UpdateStatistics(bool initialize) { - uint excluded_companies = _legend_excluded_companies; + CompanyMask excluded_companies = _legend_excluded_companies; /* Exclude the companies which aren't valid */ for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) { @@ -902,7 +902,7 @@ struct PaymentRatesGraphWindow : BaseGraphWindow { void UpdateExcludedData() { - this->excluded_data = 0; + this->excluded_data.reset(); int i = 0; const CargoSpec *cs; @@ -967,7 +967,7 @@ struct PaymentRatesGraphWindow : BaseGraphWindow { case WID_CPR_ENABLE_CARGOES: /* Remove all cargoes from the excluded lists. */ _legend_excluded_cargo = 0; - this->excluded_data = 0; + this->excluded_data.reset(); this->UpdateLoweredWidgets(); this->SetDirty(); break; diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index 9a9056061..07d685e92 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -350,7 +350,8 @@ static const SaveLoad _company_economy_desc[] = { SLE_CONDVAR(CompanyEconomyEntry, company_value, SLE_INT64, 2, SL_MAX_VERSION), SLE_CONDVAR(CompanyEconomyEntry, delivered_cargo[NUM_CARGO - 1], SLE_INT32, 0, 169), - SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, NUM_CARGO, 170, SL_MAX_VERSION), + SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, 32, 170, 198), + SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, NUM_CARGO, 199, SL_MAX_VERSION), SLE_VAR(CompanyEconomyEntry, performance_history, SLE_INT32), SLE_END() diff --git a/src/saveload/economy_sl.cpp b/src/saveload/economy_sl.cpp index dabf120fc..0effb5b2f 100644 --- a/src/saveload/economy_sl.cpp +++ b/src/saveload/economy_sl.cpp @@ -29,7 +29,7 @@ static void Load_PRIC() /** Cargo payment rates in pre 126 savegames */ static void Load_CAPR() { - uint num_cargo = IsSavegameVersionBefore(55) ? 12 : NUM_CARGO; + uint num_cargo = IsSavegameVersionBefore(55) ? 12 : IsSavegameVersionBefore(199) ? 32 : NUM_CARGO; int vt = IsSavegameVersionBefore(65) ? SLE_FILE_I32 : SLE_FILE_I64; SlArray(NULL, num_cargo, vt | SLE_VAR_NULL); SlArray(NULL, num_cargo, SLE_FILE_U16 | SLE_VAR_NULL); diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index d06214e23..692f73cf2 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -266,8 +266,9 @@ * 196 27778 1.7.x * 197 27978 1.8.x * 198 + * 199 */ -extern const uint16 SAVEGAME_VERSION = 198; ///< Current savegame version of OpenTTD. +extern const uint16 SAVEGAME_VERSION = 199; ///< Current savegame version of OpenTTD. SavegameType _savegame_type; ///< type of savegame we are loading FileToSaveLoad _file_to_saveload; ///< File to save or load in the openttd loop. diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index 391ba30a8..f01123da0 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -329,6 +329,7 @@ static void Load_STNS() _cargo_days = 0; _cargo_feeder_share = 0; + uint num_cargo = IsSavegameVersionBefore(55) ? 12 : IsSavegameVersionBefore(199) ? 32 : NUM_CARGO; int index; while ((index = SlIterateArray()) != -1) { Station *st = new (index) Station(); @@ -337,7 +338,6 @@ static void Load_STNS() _waiting_acceptance = 0; - uint num_cargo = IsSavegameVersionBefore(55) ? 12 : NUM_CARGO; for (CargoID i = 0; i < num_cargo; i++) { GoodsEntry *ge = &st->goods[i]; SlObject(ge, GetGoodsDesc()); @@ -377,10 +377,11 @@ static void Ptrs_STNS() /* Don't run when savegame version is higher than or equal to 123. */ if (!IsSavegameVersionBefore(123)) return; + uint num_cargo = IsSavegameVersionBefore(199) ? 32 : NUM_CARGO; Station *st; FOR_ALL_STATIONS(st) { if (!IsSavegameVersionBefore(68)) { - for (CargoID i = 0; i < NUM_CARGO; i++) { + for (CargoID i = 0; i < num_cargo; i++) { GoodsEntry *ge = &st->goods[i]; SwapPackets(ge); SlObject(ge, GetGoodsDesc()); @@ -440,7 +441,8 @@ static const SaveLoad _station_desc[] = { SLE_VAR(Station, last_vehicle_type, SLE_UINT8), SLE_VAR(Station, had_vehicle_of_type, SLE_UINT8), SLE_LST(Station, loading_vehicles, REF_VEHICLE), - SLE_CONDVAR(Station, always_accepted, SLE_UINT32, 127, SL_MAX_VERSION), + SLE_CONDVAR(Station, always_accepted, SLE_FILE_U32 | SLE_VAR_U64, 127, 198), + SLE_CONDVAR(Station, always_accepted, SLE_UINT64, 199, SL_MAX_VERSION), SLE_END() }; @@ -520,6 +522,7 @@ static void Load_STNN() { _num_flows = 0; + uint num_cargo = IsSavegameVersionBefore(199) ? 32 : NUM_CARGO; int index; while ((index = SlIterateArray()) != -1) { bool waypoint = (SlReadByte() & FACIL_WAYPOINT) != 0; @@ -538,7 +541,7 @@ static void Load_STNN() memcpy(st->airport.psa->storage, _old_st_persistent_storage.storage, sizeof(st->airport.psa->storage)); } - for (CargoID i = 0; i < NUM_CARGO; i++) { + for (CargoID i = 0; i < num_cargo; i++) { SlObject(&st->goods[i], GetGoodsDesc()); FlowSaveLoad flow; FlowStat *fs = NULL; @@ -580,9 +583,10 @@ static void Ptrs_STNN() /* Don't run when savegame version lower than 123. */ if (IsSavegameVersionBefore(123)) return; + uint num_cargo = IsSavegameVersionBefore(199) ? 32 : NUM_CARGO; Station *st; FOR_ALL_STATIONS(st) { - for (CargoID i = 0; i < NUM_CARGO; i++) { + for (CargoID i = 0; i < num_cargo; i++) { GoodsEntry *ge = &st->goods[i]; if (IsSavegameVersionBefore(183)) { SwapPackets(ge); diff --git a/src/saveload/town_sl.cpp b/src/saveload/town_sl.cpp index 41ac70165..13438d85b 100644 --- a/src/saveload/town_sl.cpp +++ b/src/saveload/town_sl.cpp @@ -192,7 +192,8 @@ static const SaveLoad _town_desc[] = { SLE_CONDLST(Town, psa_list, REF_STORAGE, 161, SL_MAX_VERSION), - SLE_CONDVAR(Town, cargo_produced, SLE_UINT32, 166, SL_MAX_VERSION), + SLE_CONDVAR(Town, cargo_produced, SLE_FILE_U32 | SLE_VAR_U64, 166, 198), + SLE_CONDVAR(Town, cargo_produced, SLE_UINT64, 199, SL_MAX_VERSION), /* reserve extra space in savegame here. (currently 30 bytes) */ SLE_CONDNULL(30, 2, SL_MAX_VERSION), @@ -274,12 +275,13 @@ static void Save_TOWN() static void Load_TOWN() { int index; + uint num_cargo = IsSavegameVersionBefore(199) ? 32 : NUM_CARGO; while ((index = SlIterateArray()) != -1) { Town *t = new (index) Town(); SlObject(t, _town_desc); - for (CargoID i = 0; i < NUM_CARGO; i++) { + for (CargoID i = 0; i < num_cargo; i++) { SlObject(&t->supplied[i], _town_supplied_desc); } for (int i = TE_BEGIN; i < TE_END; i++) { diff --git a/src/strings.cpp b/src/strings.cpp index fd45e6a0b..63d8e69d4 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -1147,7 +1147,7 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg } case SCC_CARGO_LIST: { // {CARGO_LIST} - CargoTypes cmask = args->GetInt32(SCC_CARGO_LIST); + CargoTypes cmask = args->GetInt64(SCC_CARGO_LIST); bool first = true; const CargoSpec *cs; diff --git a/src/window.cpp b/src/window.cpp index e2ce84542..f17fccf93 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -2457,20 +2457,20 @@ static EventState HandleViewportScroll() } Point delta; + if (_settings_client.gui.scroll_mode != VSM_VIEWPORT_RMB_FIXED) { + delta.x = -_cursor.delta.x; + delta.y = -_cursor.delta.y; + } else { + delta.x = _cursor.delta.x; + delta.y = _cursor.delta.y; + } + if (scrollwheel_scrolling) { /* We are using scrollwheels for scrolling */ delta.x = _cursor.h_wheel; delta.y = _cursor.v_wheel; _cursor.v_wheel = 0; _cursor.h_wheel = 0; - } else { - if (_settings_client.gui.scroll_mode != VSM_VIEWPORT_RMB_FIXED) { - delta.x = -_cursor.delta.x; - delta.y = -_cursor.delta.y; - } else { - delta.x = _cursor.delta.x; - delta.y = _cursor.delta.y; - } } /* Create a scroll-event and send it to the window */ @@ -2866,12 +2866,7 @@ static void MouseLoop(MouseClick click, int mousewheel) } if (vp != NULL) { - if (scrollwheel_scrolling && !(w->flags & WF_DISABLE_VP_SCROLL)) { - _scrolling_viewport = true; - _cursor.fix_at = true; - return; - } - + if (scrollwheel_scrolling) click = MC_RIGHT; // we are using the scrollwheel in a viewport, so we emulate right mouse button switch (click) { case MC_DOUBLE_LEFT: case MC_LEFT: @@ -2890,6 +2885,10 @@ static void MouseLoop(MouseClick click, int mousewheel) _scrolling_viewport = true; _cursor.fix_at = (_settings_client.gui.scroll_mode == VSM_VIEWPORT_RMB_FIXED || _settings_client.gui.scroll_mode == VSM_MAP_RMB_FIXED); + + /* clear 2D scrolling caches before we start a 2D scroll */ + _cursor.h_wheel = 0; + _cursor.v_wheel = 0; return; } break; @@ -2904,7 +2903,7 @@ static void MouseLoop(MouseClick click, int mousewheel) case MC_LEFT: case MC_DOUBLE_LEFT: DispatchLeftClickEvent(w, x - w->left, y - w->top, click == MC_DOUBLE_LEFT ? 2 : 1); - return; + break; default: if (!scrollwheel_scrolling || w == NULL || w->window_class != WC_SMALLMAP) break; @@ -2912,19 +2911,11 @@ static void MouseLoop(MouseClick click, int mousewheel) * Simulate a right button click so we can get started. */ FALLTHROUGH; - case MC_RIGHT: - DispatchRightClickEvent(w, x - w->left, y - w->top); - return; + case MC_RIGHT: DispatchRightClickEvent(w, x - w->left, y - w->top); break; - case MC_HOVER: - DispatchHoverEvent(w, x - w->left, y - w->top); - break; + case MC_HOVER: DispatchHoverEvent(w, x - w->left, y - w->top); break; } } - - /* We're not doing anything with 2D scrolling, so reset the value. */ - _cursor.h_wheel = 0; - _cursor.v_wheel = 0; } /**