Improve performance of name sorting in town and station list windows
This commit is contained in:
@@ -17,6 +17,8 @@
|
|||||||
#include "viewport_type.h"
|
#include "viewport_type.h"
|
||||||
#include "station_map.h"
|
#include "station_map.h"
|
||||||
#include "core/geometry_type.hpp"
|
#include "core/geometry_type.hpp"
|
||||||
|
#include "core/alloc_type.hpp"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
typedef Pool<BaseStation, StationID, 32, 64000> StationPool;
|
typedef Pool<BaseStation, StationID, 32, 64000> StationPool;
|
||||||
extern StationPool _station_pool;
|
extern StationPool _station_pool;
|
||||||
@@ -59,6 +61,7 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
|
|||||||
|
|
||||||
char *name; ///< Custom name
|
char *name; ///< Custom name
|
||||||
StringID string_id; ///< Default name (town area) of station
|
StringID string_id; ///< Default name (town area) of station
|
||||||
|
std::unique_ptr<const char, FreeDeleter> cached_name; ///< NOSAVE: Cache of the resolved name of the station, if not using a custom name
|
||||||
|
|
||||||
Town *town; ///< The town this station is associated with
|
Town *town; ///< The town this station is associated with
|
||||||
OwnerByte owner; ///< The owner of this station
|
OwnerByte owner; ///< The owner of this station
|
||||||
@@ -113,6 +116,13 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
|
|||||||
*/
|
*/
|
||||||
virtual void UpdateVirtCoord() = 0;
|
virtual void UpdateVirtCoord() = 0;
|
||||||
|
|
||||||
|
inline const char *GetCachedName() const
|
||||||
|
{
|
||||||
|
if (this->name != nullptr) return this->name;
|
||||||
|
if (!this->cached_name) const_cast<BaseStation *>(this)->FillCachedName();
|
||||||
|
return this->cached_name.get();
|
||||||
|
}
|
||||||
|
|
||||||
virtual void MoveSign(TileIndex new_xy)
|
virtual void MoveSign(TileIndex new_xy)
|
||||||
{
|
{
|
||||||
this->xy = new_xy;
|
this->xy = new_xy;
|
||||||
@@ -176,6 +186,9 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void PostDestructor(size_t index);
|
static void PostDestructor(size_t index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void FillCachedName();
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FOR_ALL_BASE_STATIONS(var) FOR_ALL_ITEMS_FROM(BaseStation, station_index, var, 0)
|
#define FOR_ALL_BASE_STATIONS(var) FOR_ALL_ITEMS_FROM(BaseStation, station_index, var, 0)
|
||||||
|
@@ -232,6 +232,12 @@ void UpdateAllVirtCoords()
|
|||||||
RebuildViewportKdtree();
|
RebuildViewportKdtree();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClearAllCachedNames()
|
||||||
|
{
|
||||||
|
ClearAllStationCachedNames();
|
||||||
|
ClearAllTownCachedNames();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialization of the windows and several kinds of caches.
|
* Initialization of the windows and several kinds of caches.
|
||||||
* This is not done directly in AfterLoadGame because these
|
* This is not done directly in AfterLoadGame because these
|
||||||
@@ -248,6 +254,7 @@ static void InitializeWindowsAndCaches()
|
|||||||
SetupColoursAndInitialWindow();
|
SetupColoursAndInitialWindow();
|
||||||
|
|
||||||
/* Update coordinates of the signs. */
|
/* Update coordinates of the signs. */
|
||||||
|
ClearAllCachedNames();
|
||||||
UpdateAllVirtCoords();
|
UpdateAllVirtCoords();
|
||||||
ResetViewportAfterLoadGame();
|
ResetViewportAfterLoadGame();
|
||||||
|
|
||||||
|
@@ -527,6 +527,7 @@ struct GameOptionsWindow : Window {
|
|||||||
ReadLanguagePack(&_languages[index]);
|
ReadLanguagePack(&_languages[index]);
|
||||||
DeleteWindowByClass(WC_QUERY_STRING);
|
DeleteWindowByClass(WC_QUERY_STRING);
|
||||||
CheckForMissingGlyphs();
|
CheckForMissingGlyphs();
|
||||||
|
ClearAllCachedNames();
|
||||||
UpdateAllVirtCoords();
|
UpdateAllVirtCoords();
|
||||||
ReInitAllWindows();
|
ReInitAllWindows();
|
||||||
break;
|
break;
|
||||||
|
@@ -456,6 +456,26 @@ void UpdateAllStationVirtCoords()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseStation::FillCachedName()
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
int64 args_array[] = { this->index };
|
||||||
|
StringParameters tmp_params(args_array);
|
||||||
|
char *end = GetStringWithArgs(buf, Waypoint::IsExpected(this) ? STR_WAYPOINT_NAME : STR_STATION_NAME, &tmp_params, lastof(buf));
|
||||||
|
char *alloced = MallocT<char>(end - buf + 1);
|
||||||
|
memcpy(alloced, buf, end - buf + 1);
|
||||||
|
this->cached_name.reset(alloced);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearAllStationCachedNames()
|
||||||
|
{
|
||||||
|
BaseStation *st;
|
||||||
|
|
||||||
|
FOR_ALL_BASE_STATIONS(st) {
|
||||||
|
st->cached_name.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a mask of the cargo types that the station accepts.
|
* Get a mask of the cargo types that the station accepts.
|
||||||
* @param st Station to query
|
* @param st Station to query
|
||||||
@@ -4006,6 +4026,7 @@ CommandCost CmdRenameStation(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (flags & DC_EXEC) {
|
if (flags & DC_EXEC) {
|
||||||
|
st->cached_name.reset();
|
||||||
free(st->name);
|
free(st->name);
|
||||||
st->name = reset ? nullptr : stredup(text);
|
st->name = reset ? nullptr : stredup(text);
|
||||||
|
|
||||||
|
@@ -27,6 +27,7 @@ void FindStationsAroundTiles(const TileArea &location, StationList *stations, bo
|
|||||||
|
|
||||||
void ShowStationViewWindow(StationID station);
|
void ShowStationViewWindow(StationID station);
|
||||||
void UpdateAllStationVirtCoords();
|
void UpdateAllStationVirtCoords();
|
||||||
|
void ClearAllStationCachedNames();
|
||||||
|
|
||||||
CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad);
|
CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad);
|
||||||
CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, CargoTypes *always_accepted = nullptr);
|
CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, CargoTypes *always_accepted = nullptr);
|
||||||
|
@@ -213,19 +213,7 @@ protected:
|
|||||||
/** Sort stations by their name */
|
/** Sort stations by their name */
|
||||||
static bool StationNameSorter(const Station * const &a, const Station * const &b)
|
static bool StationNameSorter(const Station * const &a, const Station * const &b)
|
||||||
{
|
{
|
||||||
static char buf_cache[64];
|
int r = strnatcmp(a->GetCachedName(), b->GetCachedName()); // Sort by name (natural sorting).
|
||||||
char buf[64];
|
|
||||||
|
|
||||||
SetDParam(0, a->index);
|
|
||||||
GetString(buf, STR_STATION_NAME, lastof(buf));
|
|
||||||
|
|
||||||
if (b != last_station) {
|
|
||||||
last_station = b;
|
|
||||||
SetDParam(0, b->index);
|
|
||||||
GetString(buf_cache, STR_STATION_NAME, lastof(buf_cache));
|
|
||||||
}
|
|
||||||
|
|
||||||
int r = strnatcmp(buf, buf_cache); // Sort by name (natural sorting).
|
|
||||||
if (r == 0) return a->index < b->index;
|
if (r == 0) return a->index < b->index;
|
||||||
return r < 0;
|
return r < 0;
|
||||||
}
|
}
|
||||||
@@ -1177,21 +1165,13 @@ bool CargoSorter::SortCount(const CargoDataEntry *cd1, const CargoDataEntry *cd2
|
|||||||
|
|
||||||
bool CargoSorter::SortStation(StationID st1, StationID st2) const
|
bool CargoSorter::SortStation(StationID st1, StationID st2) const
|
||||||
{
|
{
|
||||||
static char buf1[MAX_LENGTH_STATION_NAME_CHARS];
|
|
||||||
static char buf2[MAX_LENGTH_STATION_NAME_CHARS];
|
|
||||||
|
|
||||||
if (!Station::IsValidID(st1)) {
|
if (!Station::IsValidID(st1)) {
|
||||||
return Station::IsValidID(st2) ? this->order == SO_ASCENDING : this->SortId(st1, st2);
|
return Station::IsValidID(st2) ? this->order == SO_ASCENDING : this->SortId(st1, st2);
|
||||||
} else if (!Station::IsValidID(st2)) {
|
} else if (!Station::IsValidID(st2)) {
|
||||||
return order == SO_DESCENDING;
|
return order == SO_DESCENDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDParam(0, st1);
|
int res = strnatcmp(Station::Get(st1)->GetCachedName(), Station::Get(st2)->GetCachedName()); // Sort by name (natural sorting).
|
||||||
GetString(buf1, STR_STATION_NAME, lastof(buf1));
|
|
||||||
SetDParam(0, st2);
|
|
||||||
GetString(buf2, STR_STATION_NAME, lastof(buf2));
|
|
||||||
|
|
||||||
int res = strnatcmp(buf1, buf2); // Sort by name (natural sorting).
|
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
return this->SortId(st1, st2);
|
return this->SortId(st1, st2);
|
||||||
} else {
|
} else {
|
||||||
|
14
src/town.h
14
src/town.h
@@ -21,7 +21,9 @@
|
|||||||
#include "openttd.h"
|
#include "openttd.h"
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
#include "company_func.h"
|
#include "company_func.h"
|
||||||
|
#include "core/alloc_type.hpp"
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct BuildingCounts {
|
struct BuildingCounts {
|
||||||
@@ -65,6 +67,7 @@ struct Town : TownPool::PoolItem<&_town_pool> {
|
|||||||
uint16 townnametype;
|
uint16 townnametype;
|
||||||
uint32 townnameparts;
|
uint32 townnameparts;
|
||||||
char *name; ///< Custom town name. If nullptr, the town was not renamed and uses the generated name.
|
char *name; ///< Custom town name. If nullptr, the town was not renamed and uses the generated name.
|
||||||
|
std::unique_ptr<const char, FreeDeleter> cached_name; ///< NOSAVE: Cache of the resolved name of the town, if not using a custom town name
|
||||||
|
|
||||||
byte flags; ///< See #TownFlags.
|
byte flags; ///< See #TownFlags.
|
||||||
|
|
||||||
@@ -158,6 +161,13 @@ struct Town : TownPool::PoolItem<&_town_pool> {
|
|||||||
|
|
||||||
void UpdateVirtCoord();
|
void UpdateVirtCoord();
|
||||||
|
|
||||||
|
inline const char *GetCachedName() const
|
||||||
|
{
|
||||||
|
if (this->name != nullptr) return this->name;
|
||||||
|
if (!this->cached_name) const_cast<Town *>(this)->FillCachedName();
|
||||||
|
return this->cached_name.get();
|
||||||
|
}
|
||||||
|
|
||||||
static inline Town *GetByTile(TileIndex tile)
|
static inline Town *GetByTile(TileIndex tile)
|
||||||
{
|
{
|
||||||
return Town::Get(GetTownIndex(tile));
|
return Town::Get(GetTownIndex(tile));
|
||||||
@@ -165,11 +175,15 @@ struct Town : TownPool::PoolItem<&_town_pool> {
|
|||||||
|
|
||||||
static Town *GetRandom();
|
static Town *GetRandom();
|
||||||
static void PostDestructor(size_t index);
|
static void PostDestructor(size_t index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void FillCachedName();
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32 GetWorldPopulation();
|
uint32 GetWorldPopulation();
|
||||||
|
|
||||||
void UpdateAllTownVirtCoords();
|
void UpdateAllTownVirtCoords();
|
||||||
|
void ClearAllTownCachedNames();
|
||||||
void ShowTownViewWindow(TownID town);
|
void ShowTownViewWindow(TownID town);
|
||||||
void ExpandTown(Town *t);
|
void ExpandTown(Town *t);
|
||||||
|
|
||||||
|
@@ -229,6 +229,15 @@ void Town::UpdateLabel()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Town::FillCachedName()
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
char *end = GetTownName(buf, this, lastof(buf));
|
||||||
|
char *alloced = MallocT<char>(end - buf + 1);
|
||||||
|
memcpy(alloced, buf, end - buf + 1);
|
||||||
|
this->cached_name.reset(alloced);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the cost for removing this house
|
* Get the cost for removing this house
|
||||||
* @return the cost (inflation corrected etc)
|
* @return the cost (inflation corrected etc)
|
||||||
@@ -522,6 +531,15 @@ void UpdateAllTownVirtCoords()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClearAllTownCachedNames()
|
||||||
|
{
|
||||||
|
Town *t;
|
||||||
|
|
||||||
|
FOR_ALL_TOWNS(t) {
|
||||||
|
t->cached_name.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the towns population
|
* Change the towns population
|
||||||
* @param t Town which population has changed
|
* @param t Town which population has changed
|
||||||
@@ -2863,11 +2881,13 @@ CommandCost CmdRenameTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (flags & DC_EXEC) {
|
if (flags & DC_EXEC) {
|
||||||
|
t->cached_name.reset();
|
||||||
free(t->name);
|
free(t->name);
|
||||||
t->name = reset ? nullptr : stredup(text);
|
t->name = reset ? nullptr : stredup(text);
|
||||||
|
|
||||||
t->UpdateVirtCoord();
|
t->UpdateVirtCoord();
|
||||||
InvalidateWindowData(WC_TOWN_DIRECTORY, 0, 1);
|
InvalidateWindowData(WC_TOWN_DIRECTORY, 0, 1);
|
||||||
|
ClearAllStationCachedNames();
|
||||||
UpdateAllStationVirtCoords();
|
UpdateAllStationVirtCoords();
|
||||||
}
|
}
|
||||||
return CommandCost();
|
return CommandCost();
|
||||||
|
@@ -675,22 +675,7 @@ private:
|
|||||||
/** Sort by town name */
|
/** Sort by town name */
|
||||||
static bool TownNameSorter(const Town * const &a, const Town * const &b)
|
static bool TownNameSorter(const Town * const &a, const Town * const &b)
|
||||||
{
|
{
|
||||||
static char buf_cache[64];
|
return strnatcmp(a->GetCachedName(), b->GetCachedName()) < 0; // Sort by name (natural sorting).
|
||||||
char buf[64];
|
|
||||||
|
|
||||||
SetDParam(0, a->index);
|
|
||||||
GetString(buf, STR_TOWN_NAME, lastof(buf));
|
|
||||||
|
|
||||||
/* If 'b' is the same town as in the last round, use the cached value
|
|
||||||
* We do this to speed stuff up ('b' is called with the same value a lot of
|
|
||||||
* times after each other) */
|
|
||||||
if (b != last_town) {
|
|
||||||
last_town = b;
|
|
||||||
SetDParam(0, b->index);
|
|
||||||
GetString(buf_cache, STR_TOWN_NAME, lastof(buf_cache));
|
|
||||||
}
|
|
||||||
|
|
||||||
return strnatcmp(buf, buf_cache) < 0; // Sort by name (natural sorting).
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sort by population (default descending, as big towns are of the most interest). */
|
/** Sort by population (default descending, as big towns are of the most interest). */
|
||||||
|
@@ -87,6 +87,7 @@ bool ScrollMainWindowToTile(TileIndex tile, bool instant = false);
|
|||||||
bool ScrollMainWindowTo(int x, int y, int z = -1, bool instant = false);
|
bool ScrollMainWindowTo(int x, int y, int z = -1, bool instant = false);
|
||||||
|
|
||||||
void UpdateAllVirtCoords();
|
void UpdateAllVirtCoords();
|
||||||
|
void ClearAllCachedNames();
|
||||||
|
|
||||||
extern Point _tile_fract_coords;
|
extern Point _tile_fract_coords;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user