Merge remote-tracking branch 'upstream/master'
This commit is contained in:
+154
-158
@@ -253,7 +253,7 @@ static void StationsWndShowStationRating(int left, int right, int y, CargoType c
|
||||
|
||||
int padding = ScaleGUITrad(1);
|
||||
int width = right - left;
|
||||
int colour = cs->rating_colour;
|
||||
PixelColour colour = cs->rating_colour;
|
||||
TextColour tc = GetContrastColour(colour);
|
||||
uint w = std::min(amount + 5, units_full) * width / units_full;
|
||||
|
||||
@@ -497,7 +497,7 @@ public:
|
||||
}
|
||||
|
||||
case WID_STL_LIST:
|
||||
resize.height = std::max(GetCharacterHeight(FS_NORMAL), GetCharacterHeight(FS_SMALL) + ScaleGUITrad(3));
|
||||
fill.height = resize.height = std::max(GetCharacterHeight(FS_NORMAL), GetCharacterHeight(FS_SMALL) + ScaleGUITrad(3));
|
||||
size.height = padding.height + 5 * resize.height;
|
||||
|
||||
/* Determine appropriate width for mini station rating graph */
|
||||
@@ -659,8 +659,8 @@ public:
|
||||
this->filter.facilities.Flip(static_cast<StationFacility>(widget - WID_STL_TRAIN));
|
||||
this->ToggleWidgetLoweredState(widget);
|
||||
} else {
|
||||
for (uint i : SetBitIterator(this->filter.facilities.base())) {
|
||||
this->RaiseWidget(i + WID_STL_TRAIN);
|
||||
for (StationFacility i : this->filter.facilities) {
|
||||
this->RaiseWidget(to_underlying(i) + WID_STL_TRAIN);
|
||||
}
|
||||
this->filter.facilities = {};
|
||||
this->filter.facilities.Set(static_cast<StationFacility>(widget - WID_STL_TRAIN));
|
||||
@@ -696,7 +696,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void OnDropdownSelect(int widget, int index) override
|
||||
void OnDropdownSelect(WidgetID widget, int index, int) override
|
||||
{
|
||||
if (widget == WID_STL_SORTDROPBTN) {
|
||||
if (this->stations.SortType() != index) {
|
||||
@@ -876,30 +876,6 @@ static constexpr NWidgetPart _nested_station_view_widgets[] = {
|
||||
EndContainer(),
|
||||
};
|
||||
|
||||
/**
|
||||
* Draws icons of waiting cargo in the StationView window
|
||||
*
|
||||
* @param cargo type of cargo
|
||||
* @param waiting number of waiting units
|
||||
* @param left left most coordinate to draw on
|
||||
* @param right right most coordinate to draw on
|
||||
* @param y y coordinate
|
||||
*/
|
||||
static void DrawCargoIcons(CargoType cargo, uint waiting, int left, int right, int y)
|
||||
{
|
||||
int width = ScaleSpriteTrad(10);
|
||||
uint num = std::min<uint>((waiting + (width / 2)) / width, (right - left) / width); // maximum is width / 10 icons so it won't overflow
|
||||
if (num == 0) return;
|
||||
|
||||
SpriteID sprite = CargoSpec::Get(cargo)->GetCargoIcon();
|
||||
|
||||
int x = _current_text_dir == TD_RTL ? left : right - num * width;
|
||||
do {
|
||||
DrawSprite(sprite, PAL_NONE, x, y);
|
||||
x += width;
|
||||
} while (--num);
|
||||
}
|
||||
|
||||
enum SortOrder : uint8_t {
|
||||
SO_DESCENDING,
|
||||
SO_ASCENDING
|
||||
@@ -917,9 +893,13 @@ enum class CargoSortType : uint8_t {
|
||||
|
||||
class CargoSorter {
|
||||
public:
|
||||
using is_transparent = void;
|
||||
CargoSorter(CargoSortType t = CargoSortType::StationID, SortOrder o = SO_ASCENDING) : type(t), order(o) {}
|
||||
CargoSortType GetSortType() {return this->type;}
|
||||
bool operator()(const CargoDataEntry *cd1, const CargoDataEntry *cd2) const;
|
||||
bool operator()(const CargoDataEntry &cd1, const CargoDataEntry &cd2) const;
|
||||
bool operator()(const CargoDataEntry &cd1, const std::unique_ptr<CargoDataEntry> &cd2) const { return this->operator()(cd1, *cd2); }
|
||||
bool operator()(const std::unique_ptr<CargoDataEntry> &cd1, const CargoDataEntry &cd2) const { return this->operator()(*cd1, cd2); }
|
||||
bool operator()(const std::unique_ptr<CargoDataEntry> &cd1, const std::unique_ptr<CargoDataEntry> &cd2) const { return this->operator()(*cd1, *cd2); }
|
||||
|
||||
private:
|
||||
CargoSortType type;
|
||||
@@ -927,16 +907,16 @@ private:
|
||||
|
||||
template <class Tid>
|
||||
bool SortId(Tid st1, Tid st2) const;
|
||||
bool SortCount(const CargoDataEntry *cd1, const CargoDataEntry *cd2) const;
|
||||
bool SortStation (StationID st1, StationID st2) const;
|
||||
bool SortCount(const CargoDataEntry &cd1, const CargoDataEntry &cd2) const;
|
||||
bool SortStation(StationID st1, StationID st2) const;
|
||||
};
|
||||
|
||||
typedef std::set<CargoDataEntry *, CargoSorter> CargoDataSet;
|
||||
typedef std::set<std::unique_ptr<CargoDataEntry>, CargoSorter> CargoDataSet;
|
||||
|
||||
/**
|
||||
* A cargo data entry representing one possible row in the station view window's
|
||||
* top part. Cargo data entries form a tree where each entry can have several
|
||||
* children. Parents keep track of the sums of their childrens' cargo counts.
|
||||
* children. Parents keep track of the sums of their children's cargo counts.
|
||||
*/
|
||||
class CargoDataEntry {
|
||||
public:
|
||||
@@ -948,7 +928,7 @@ public:
|
||||
* @param station ID of the station for which an entry shall be created or retrieved
|
||||
* @return a child entry associated with the given station.
|
||||
*/
|
||||
CargoDataEntry *InsertOrRetrieve(StationID station)
|
||||
CargoDataEntry &InsertOrRetrieve(StationID station)
|
||||
{
|
||||
return this->InsertOrRetrieve<StationID>(station);
|
||||
}
|
||||
@@ -958,7 +938,7 @@ public:
|
||||
* @param cargo type of the cargo for which an entry shall be created or retrieved
|
||||
* @return a child entry associated with the given cargo.
|
||||
*/
|
||||
CargoDataEntry *InsertOrRetrieve(CargoType cargo)
|
||||
CargoDataEntry &InsertOrRetrieve(CargoType cargo)
|
||||
{
|
||||
return this->InsertOrRetrieve<CargoType>(cargo);
|
||||
}
|
||||
@@ -972,7 +952,7 @@ public:
|
||||
void Remove(StationID station)
|
||||
{
|
||||
CargoDataEntry t(station);
|
||||
this->Remove(&t);
|
||||
this->Remove(t);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -982,7 +962,7 @@ public:
|
||||
void Remove(CargoType cargo)
|
||||
{
|
||||
CargoDataEntry t(cargo);
|
||||
this->Remove(&t);
|
||||
this->Remove(t);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -993,7 +973,7 @@ public:
|
||||
CargoDataEntry *Retrieve(StationID station) const
|
||||
{
|
||||
CargoDataEntry t(station);
|
||||
return this->Retrieve(this->children->find(&t));
|
||||
return this->Retrieve(this->children->find(t));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1004,7 +984,7 @@ public:
|
||||
CargoDataEntry *Retrieve(CargoType cargo) const
|
||||
{
|
||||
CargoDataEntry t(cargo);
|
||||
return this->Retrieve(this->children->find(&t));
|
||||
return this->Retrieve(this->children->find(t));
|
||||
}
|
||||
|
||||
void Resort(CargoSortType type, SortOrder order);
|
||||
@@ -1055,19 +1035,19 @@ public:
|
||||
void SetTransfers(bool value) { this->transfers = value; }
|
||||
|
||||
void Clear();
|
||||
private:
|
||||
|
||||
CargoDataEntry(StationID station, uint count, CargoDataEntry *parent);
|
||||
CargoDataEntry(CargoType cargo, uint count, CargoDataEntry *parent);
|
||||
CargoDataEntry(StationID station);
|
||||
CargoDataEntry(CargoType cargo);
|
||||
|
||||
private:
|
||||
CargoDataEntry *Retrieve(CargoDataSet::iterator i) const;
|
||||
|
||||
template <class Tid>
|
||||
CargoDataEntry *InsertOrRetrieve(Tid s);
|
||||
CargoDataEntry &InsertOrRetrieve(Tid s);
|
||||
|
||||
void Remove(CargoDataEntry *entry);
|
||||
void Remove(CargoDataEntry &entry);
|
||||
void IncrementSize();
|
||||
|
||||
CargoDataEntry *parent; ///< the parent of this entry.
|
||||
@@ -1080,7 +1060,7 @@ private:
|
||||
};
|
||||
uint num_children; ///< the number of subentries belonging to this entry.
|
||||
uint count; ///< sum of counts of all children or amount of cargo for this entry.
|
||||
CargoDataSet *children; ///< the children of this entry.
|
||||
std::unique_ptr<CargoDataSet> children; ///< the children of this entry.
|
||||
};
|
||||
|
||||
CargoDataEntry::CargoDataEntry() :
|
||||
@@ -1088,7 +1068,7 @@ CargoDataEntry::CargoDataEntry() :
|
||||
station(StationID::Invalid()),
|
||||
num_children(0),
|
||||
count(0),
|
||||
children(new CargoDataSet(CargoSorter(CargoSortType::CargoType)))
|
||||
children(std::make_unique<CargoDataSet>(CargoSorter(CargoSortType::CargoType)))
|
||||
{}
|
||||
|
||||
CargoDataEntry::CargoDataEntry(CargoType cargo, uint count, CargoDataEntry *parent) :
|
||||
@@ -1096,7 +1076,7 @@ CargoDataEntry::CargoDataEntry(CargoType cargo, uint count, CargoDataEntry *pare
|
||||
cargo(cargo),
|
||||
num_children(0),
|
||||
count(count),
|
||||
children(new CargoDataSet)
|
||||
children(std::make_unique<CargoDataSet>())
|
||||
{}
|
||||
|
||||
CargoDataEntry::CargoDataEntry(StationID station, uint count, CargoDataEntry *parent) :
|
||||
@@ -1104,7 +1084,7 @@ CargoDataEntry::CargoDataEntry(StationID station, uint count, CargoDataEntry *pa
|
||||
station(station),
|
||||
num_children(0),
|
||||
count(count),
|
||||
children(new CargoDataSet)
|
||||
children(std::make_unique<CargoDataSet>())
|
||||
{}
|
||||
|
||||
CargoDataEntry::CargoDataEntry(StationID station) :
|
||||
@@ -1126,7 +1106,6 @@ CargoDataEntry::CargoDataEntry(CargoType cargo) :
|
||||
CargoDataEntry::~CargoDataEntry()
|
||||
{
|
||||
this->Clear();
|
||||
delete this->children;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1134,13 +1113,7 @@ CargoDataEntry::~CargoDataEntry()
|
||||
*/
|
||||
void CargoDataEntry::Clear()
|
||||
{
|
||||
if (this->children != nullptr) {
|
||||
for (auto &it : *this->children) {
|
||||
assert(it != this);
|
||||
delete it;
|
||||
}
|
||||
this->children->clear();
|
||||
}
|
||||
if (this->children != nullptr) this->children->clear();
|
||||
if (this->parent != nullptr) this->parent->count -= this->count;
|
||||
this->count = 0;
|
||||
this->num_children = 0;
|
||||
@@ -1152,13 +1125,10 @@ void CargoDataEntry::Clear()
|
||||
* which only contains the ID of the entry to be removed. In this case child is
|
||||
* not deleted.
|
||||
*/
|
||||
void CargoDataEntry::Remove(CargoDataEntry *entry)
|
||||
void CargoDataEntry::Remove(CargoDataEntry &entry)
|
||||
{
|
||||
CargoDataSet::iterator i = this->children->find(entry);
|
||||
if (i != this->children->end()) {
|
||||
delete *i;
|
||||
this->children->erase(i);
|
||||
}
|
||||
if (i != this->children->end()) this->children->erase(i);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1168,17 +1138,16 @@ void CargoDataEntry::Remove(CargoDataEntry *entry)
|
||||
* @return the new or retrieved subentry
|
||||
*/
|
||||
template <class Tid>
|
||||
CargoDataEntry *CargoDataEntry::InsertOrRetrieve(Tid child_id)
|
||||
CargoDataEntry &CargoDataEntry::InsertOrRetrieve(Tid child_id)
|
||||
{
|
||||
CargoDataEntry tmp(child_id);
|
||||
CargoDataSet::iterator i = this->children->find(&tmp);
|
||||
CargoDataSet::iterator i = this->children->find(tmp);
|
||||
if (i == this->children->end()) {
|
||||
IncrementSize();
|
||||
return *(this->children->insert(new CargoDataEntry(child_id, 0, this)).first);
|
||||
return **(this->children->insert(std::make_unique<CargoDataEntry>(child_id, 0, this)).first);
|
||||
} else {
|
||||
CargoDataEntry *ret = *i;
|
||||
assert(this->children->value_comp().GetSortType() != CargoSortType::Count);
|
||||
return ret;
|
||||
return **i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1204,9 +1173,9 @@ void CargoDataEntry::IncrementSize()
|
||||
|
||||
void CargoDataEntry::Resort(CargoSortType type, SortOrder order)
|
||||
{
|
||||
CargoDataSet *new_subs = new CargoDataSet(this->children->begin(), this->children->end(), CargoSorter(type, order));
|
||||
delete this->children;
|
||||
this->children = new_subs;
|
||||
auto new_children = std::make_unique<CargoDataSet>(CargoSorter(type, order));
|
||||
new_children->merge(*this->children);
|
||||
this->children = std::move(new_children);
|
||||
}
|
||||
|
||||
CargoDataEntry *CargoDataEntry::Retrieve(CargoDataSet::iterator i) const
|
||||
@@ -1215,21 +1184,21 @@ CargoDataEntry *CargoDataEntry::Retrieve(CargoDataSet::iterator i) const
|
||||
return nullptr;
|
||||
} else {
|
||||
assert(this->children->value_comp().GetSortType() != CargoSortType::Count);
|
||||
return *i;
|
||||
return i->get();
|
||||
}
|
||||
}
|
||||
|
||||
bool CargoSorter::operator()(const CargoDataEntry *cd1, const CargoDataEntry *cd2) const
|
||||
bool CargoSorter::operator()(const CargoDataEntry &cd1, const CargoDataEntry &cd2) const
|
||||
{
|
||||
switch (this->type) {
|
||||
case CargoSortType::StationID:
|
||||
return this->SortId<StationID>(cd1->GetStation(), cd2->GetStation());
|
||||
return this->SortId<StationID>(cd1.GetStation(), cd2.GetStation());
|
||||
case CargoSortType::CargoType:
|
||||
return this->SortId<CargoType>(cd1->GetCargo(), cd2->GetCargo());
|
||||
return this->SortId<CargoType>(cd1.GetCargo(), cd2.GetCargo());
|
||||
case CargoSortType::Count:
|
||||
return this->SortCount(cd1, cd2);
|
||||
case CargoSortType::StationString:
|
||||
return this->SortStation(cd1->GetStation(), cd2->GetStation());
|
||||
return this->SortStation(cd1.GetStation(), cd2.GetStation());
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
@@ -1241,12 +1210,12 @@ bool CargoSorter::SortId(Tid st1, Tid st2) const
|
||||
return (this->order == SO_ASCENDING) ? st1 < st2 : st2 < st1;
|
||||
}
|
||||
|
||||
bool CargoSorter::SortCount(const CargoDataEntry *cd1, const CargoDataEntry *cd2) const
|
||||
bool CargoSorter::SortCount(const CargoDataEntry &cd1, const CargoDataEntry &cd2) const
|
||||
{
|
||||
uint c1 = cd1->GetCount();
|
||||
uint c2 = cd2->GetCount();
|
||||
uint c1 = cd1.GetCount();
|
||||
uint c2 = cd2.GetCount();
|
||||
if (c1 == c2) {
|
||||
return this->SortStation(cd1->GetStation(), cd2->GetStation());
|
||||
return this->SortStation(cd1.GetStation(), cd2.GetStation());
|
||||
} else if (this->order == SO_ASCENDING) {
|
||||
return c1 < c2;
|
||||
} else {
|
||||
@@ -1331,6 +1300,8 @@ struct StationViewWindow : public Window {
|
||||
uint expand_shrink_width = 0; ///< The width allocated to the expand/shrink 'button'
|
||||
int rating_lines = RATING_LINES; ///< Number of lines in the cargo ratings view.
|
||||
int accepts_lines = ACCEPTS_LINES; ///< Number of lines in the accepted cargo view.
|
||||
int line_height = 0; ///< Height of a cargo line.
|
||||
Dimension cargo_icon_size{}; ///< Size of largest cargo icon.
|
||||
Scrollbar *vscroll = nullptr;
|
||||
|
||||
/* Height of the #WID_SV_ACCEPT_RATING_LIST widget for different views. */
|
||||
@@ -1391,6 +1362,13 @@ struct StationViewWindow : public Window {
|
||||
this->owner = Station::Get(window_number)->owner;
|
||||
}
|
||||
|
||||
void OnInit() override
|
||||
{
|
||||
this->cargo_icon_size = GetLargestCargoIconSize();
|
||||
this->line_height = std::max<int>(GetCharacterHeight(FS_NORMAL), this->cargo_icon_size.height);
|
||||
this->expand_shrink_width = std::max(GetCharacterWidth(FS_NORMAL, '-'), GetCharacterWidth(FS_NORMAL, '+'));
|
||||
}
|
||||
|
||||
void Close([[maybe_unused]] int data = 0) override
|
||||
{
|
||||
CloseWindowById(WC_TRAINS_LIST, VehicleListIdentifier(VL_STATION_LIST, VEH_TRAIN, this->owner, this->window_number).ToWindowNumber(), false);
|
||||
@@ -1421,25 +1399,25 @@ struct StationViewWindow : public Window {
|
||||
switch (groupings[i]) {
|
||||
case GR_CARGO:
|
||||
assert(i == 0);
|
||||
data = data->InsertOrRetrieve(cargo);
|
||||
data = &data->InsertOrRetrieve(cargo);
|
||||
data->SetTransfers(source != this->window_number);
|
||||
expand = expand->Retrieve(cargo);
|
||||
break;
|
||||
case GR_SOURCE:
|
||||
if (auto_distributed || source != this->window_number) {
|
||||
data = data->InsertOrRetrieve(source);
|
||||
data = &data->InsertOrRetrieve(source);
|
||||
expand = expand->Retrieve(source);
|
||||
}
|
||||
break;
|
||||
case GR_NEXT:
|
||||
if (auto_distributed) {
|
||||
data = data->InsertOrRetrieve(next);
|
||||
data = &data->InsertOrRetrieve(next);
|
||||
expand = expand->Retrieve(next);
|
||||
}
|
||||
break;
|
||||
case GR_DESTINATION:
|
||||
if (auto_distributed) {
|
||||
data = data->InsertOrRetrieve(dest);
|
||||
data = &data->InsertOrRetrieve(dest);
|
||||
expand = expand->Retrieve(dest);
|
||||
}
|
||||
break;
|
||||
@@ -1452,9 +1430,8 @@ struct StationViewWindow : public Window {
|
||||
{
|
||||
switch (widget) {
|
||||
case WID_SV_WAITING:
|
||||
resize.height = GetCharacterHeight(FS_NORMAL);
|
||||
fill.height = resize.height = this->line_height;
|
||||
size.height = 4 * resize.height + padding.height;
|
||||
this->expand_shrink_width = std::max(GetStringBoundingBox("-").width, GetStringBoundingBox("+").width);
|
||||
break;
|
||||
|
||||
case WID_SV_ACCEPT_RATING_LIST:
|
||||
@@ -1490,7 +1467,7 @@ struct StationViewWindow : public Window {
|
||||
this->SetWidgetLoweredState(WID_SV_CLOSE_AIRPORT, st->facilities.Test(StationFacility::Airport) && st->airport.blocks.Test(AirportBlock::AirportClosed));
|
||||
|
||||
extern const Station *_viewport_highlight_station;
|
||||
this->SetWidgetDisabledState(WID_SV_CATCHMENT, st->facilities == StationFacilities{});
|
||||
this->SetWidgetDisabledState(WID_SV_CATCHMENT, st->facilities.None());
|
||||
this->SetWidgetLoweredState(WID_SV_CATCHMENT, citymania::IsHighlightCoverageStation(st));
|
||||
|
||||
this->DrawWidgets();
|
||||
@@ -1527,7 +1504,7 @@ struct StationViewWindow : public Window {
|
||||
/* Draw waiting cargo. */
|
||||
NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_SV_WAITING);
|
||||
Rect waiting_rect = nwi->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
|
||||
this->DrawEntries(&cargo, waiting_rect, pos, maxrows, 0);
|
||||
this->DrawEntries(cargo, waiting_rect, pos, maxrows, 0);
|
||||
scroll_to_row = INT_MAX;
|
||||
}
|
||||
}
|
||||
@@ -1550,20 +1527,20 @@ struct StationViewWindow : public Window {
|
||||
void RecalcDestinations(CargoType cargo)
|
||||
{
|
||||
const Station *st = Station::Get(this->window_number);
|
||||
CargoDataEntry *entry = cached_destinations.InsertOrRetrieve(cargo);
|
||||
entry->Clear();
|
||||
CargoDataEntry &entry = cached_destinations.InsertOrRetrieve(cargo);
|
||||
entry.Clear();
|
||||
|
||||
if (!st->goods[cargo].HasData()) return;
|
||||
|
||||
for (const auto &it : st->goods[cargo].GetData().flows) {
|
||||
StationID from = it.first;
|
||||
CargoDataEntry *source_entry = entry->InsertOrRetrieve(from);
|
||||
CargoDataEntry &source_entry = entry.InsertOrRetrieve(from);
|
||||
uint32_t prev_count = 0;
|
||||
for (const auto &flow_it : *it.second.GetShares()) {
|
||||
StationID via = flow_it.second;
|
||||
CargoDataEntry *via_entry = source_entry->InsertOrRetrieve(via);
|
||||
CargoDataEntry &via_entry = source_entry.InsertOrRetrieve(via);
|
||||
if (via == this->window_number) {
|
||||
via_entry->InsertOrRetrieve(via)->Update(flow_it.first - prev_count);
|
||||
via_entry.InsertOrRetrieve(via).Update(flow_it.first - prev_count);
|
||||
} else {
|
||||
EstimateDestinations(cargo, from, via, flow_it.first - prev_count, via_entry);
|
||||
}
|
||||
@@ -1581,7 +1558,7 @@ struct StationViewWindow : public Window {
|
||||
* @param count Size of the batch of cargo.
|
||||
* @param dest CargoDataEntry to save the results in.
|
||||
*/
|
||||
void EstimateDestinations(CargoType cargo, StationID source, StationID next, uint count, CargoDataEntry *dest)
|
||||
void EstimateDestinations(CargoType cargo, StationID source, StationID next, uint count, CargoDataEntry &dest)
|
||||
{
|
||||
if (Station::IsValidID(next) && Station::IsValidID(source)) {
|
||||
GoodsEntry &ge = Station::Get(next)->goods[cargo];
|
||||
@@ -1594,19 +1571,19 @@ struct StationViewWindow : public Window {
|
||||
const FlowStat::SharesMap *shares = map_it->second.GetShares();
|
||||
uint32_t prev_count = 0;
|
||||
for (FlowStat::SharesMap::const_iterator i = shares->begin(); i != shares->end(); ++i) {
|
||||
tmp.InsertOrRetrieve(i->second)->Update(i->first - prev_count);
|
||||
tmp.InsertOrRetrieve(i->second).Update(i->first - prev_count);
|
||||
prev_count = i->first;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp.GetCount() == 0) {
|
||||
dest->InsertOrRetrieve(StationID::Invalid())->Update(count);
|
||||
dest.InsertOrRetrieve(StationID::Invalid()).Update(count);
|
||||
} else {
|
||||
uint sum_estimated = 0;
|
||||
while (sum_estimated < count) {
|
||||
for (CargoDataSet::iterator i = tmp.Begin(); i != tmp.End() && sum_estimated < count; ++i) {
|
||||
CargoDataEntry *child = *i;
|
||||
uint estimate = DivideApprox(child->GetCount() * count, tmp.GetCount());
|
||||
CargoDataEntry &child = **i;
|
||||
uint estimate = DivideApprox(child.GetCount() * count, tmp.GetCount());
|
||||
if (estimate == 0) estimate = 1;
|
||||
|
||||
sum_estimated += estimate;
|
||||
@@ -1616,10 +1593,10 @@ struct StationViewWindow : public Window {
|
||||
}
|
||||
|
||||
if (estimate > 0) {
|
||||
if (child->GetStation() == next) {
|
||||
dest->InsertOrRetrieve(next)->Update(estimate);
|
||||
if (child.GetStation() == next) {
|
||||
dest.InsertOrRetrieve(next).Update(estimate);
|
||||
} else {
|
||||
EstimateDestinations(cargo, source, child->GetStation(), estimate, dest);
|
||||
EstimateDestinations(cargo, source, child.GetStation(), estimate, dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1627,7 +1604,7 @@ struct StationViewWindow : public Window {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dest->InsertOrRetrieve(StationID::Invalid())->Update(count);
|
||||
dest.InsertOrRetrieve(StationID::Invalid()).Update(count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1647,8 +1624,8 @@ struct StationViewWindow : public Window {
|
||||
for (FlowStat::SharesMap::const_iterator flow_it = shares->begin(); flow_it != shares->end(); ++flow_it) {
|
||||
const CargoDataEntry *via_entry = source_entry->Retrieve(flow_it->second);
|
||||
for (CargoDataSet::iterator dest_it = via_entry->Begin(); dest_it != via_entry->End(); ++dest_it) {
|
||||
CargoDataEntry *dest_entry = *dest_it;
|
||||
ShowCargo(entry, cargo, from, flow_it->second, dest_entry->GetStation(), dest_entry->GetCount());
|
||||
CargoDataEntry &dest_entry = **dest_it;
|
||||
ShowCargo(entry, cargo, from, flow_it->second, dest_entry.GetStation(), dest_entry.GetCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1681,7 +1658,7 @@ struct StationViewWindow : public Window {
|
||||
|
||||
uint remaining = cp->Count();
|
||||
for (CargoDataSet::iterator dest_it = via_entry->Begin(); dest_it != via_entry->End();) {
|
||||
CargoDataEntry *dest_entry = *dest_it;
|
||||
CargoDataEntry &dest_entry = **dest_it;
|
||||
|
||||
/* Advance iterator here instead of in the for statement to test whether this is the last entry */
|
||||
++dest_it;
|
||||
@@ -1693,10 +1670,10 @@ struct StationViewWindow : public Window {
|
||||
* not matching GoodsEntry::TotalCount() */
|
||||
val = remaining;
|
||||
} else {
|
||||
val = std::min<uint>(remaining, DivideApprox(cp->Count() * dest_entry->GetCount(), via_entry->GetCount()));
|
||||
val = std::min<uint>(remaining, DivideApprox(cp->Count() * dest_entry.GetCount(), via_entry->GetCount()));
|
||||
remaining -= val;
|
||||
}
|
||||
this->ShowCargo(entry, cargo, cp->GetFirstStation(), next, dest_entry->GetStation(), val);
|
||||
this->ShowCargo(entry, cargo, cp->GetFirstStation(), next, dest_entry.GetStation(), val);
|
||||
}
|
||||
}
|
||||
this->ShowCargo(entry, cargo, NEW_STATION, NEW_STATION, NEW_STATION, packets.ReservedCount());
|
||||
@@ -1730,16 +1707,16 @@ struct StationViewWindow : public Window {
|
||||
* Mark a specific row, characterized by its CargoDataEntry, as expanded.
|
||||
* @param entry The row to be marked as expanded.
|
||||
*/
|
||||
void SetDisplayedRow(const CargoDataEntry *entry)
|
||||
void SetDisplayedRow(const CargoDataEntry &entry)
|
||||
{
|
||||
std::list<StationID> stations;
|
||||
const CargoDataEntry *parent = entry->GetParent();
|
||||
const CargoDataEntry *parent = entry.GetParent();
|
||||
if (parent->GetParent() == nullptr) {
|
||||
this->displayed_rows.push_back(RowDisplay(&this->expanded_rows, entry->GetCargo()));
|
||||
this->displayed_rows.push_back(RowDisplay(&this->expanded_rows, entry.GetCargo()));
|
||||
return;
|
||||
}
|
||||
|
||||
StationID next = entry->GetStation();
|
||||
StationID next = entry.GetStation();
|
||||
while (parent->GetParent()->GetParent() != nullptr) {
|
||||
stations.push_back(parent->GetStation());
|
||||
parent = parent->GetParent();
|
||||
@@ -1793,9 +1770,10 @@ struct StationViewWindow : public Window {
|
||||
* @param column The "column" the entry will be shown in.
|
||||
* @return either STR_STATION_VIEW_VIA or STR_STATION_VIEW_NONSTOP.
|
||||
*/
|
||||
StringID SearchNonStop(CargoDataEntry *cd, StationID station, int column)
|
||||
StringID SearchNonStop(CargoDataEntry &cd, StationID station, int column)
|
||||
{
|
||||
CargoDataEntry *parent = cd->GetParent();
|
||||
assert(column < NUM_COLUMNS);
|
||||
CargoDataEntry *parent = cd.GetParent();
|
||||
for (int i = column - 1; i > 0; --i) {
|
||||
if (this->groupings[i] == GR_DESTINATION) {
|
||||
if (parent->GetStation() == station) {
|
||||
@@ -1807,10 +1785,10 @@ struct StationViewWindow : public Window {
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
|
||||
if (this->groupings[column + 1] == GR_DESTINATION) {
|
||||
CargoDataSet::iterator begin = cd->Begin();
|
||||
CargoDataSet::iterator end = cd->End();
|
||||
if (begin != end && ++(cd->Begin()) == end && (*(begin))->GetStation() == station) {
|
||||
if (column < NUM_COLUMNS - 1 && this->groupings[column + 1] == GR_DESTINATION) {
|
||||
CargoDataSet::iterator begin = cd.Begin();
|
||||
CargoDataSet::iterator end = cd.End();
|
||||
if (begin != end && ++(cd.Begin()) == end && (*(begin))->GetStation() == station) {
|
||||
return STR_STATION_VIEW_NONSTOP;
|
||||
} else {
|
||||
return STR_STATION_VIEW_VIA;
|
||||
@@ -1820,6 +1798,28 @@ struct StationViewWindow : public Window {
|
||||
return STR_STATION_VIEW_VIA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw icons of waiting cargo.
|
||||
* @param cargo type of cargo
|
||||
* @param waiting number of waiting units
|
||||
* @param r Rect to draw within
|
||||
*/
|
||||
void DrawCargoIcons(CargoType cargo, uint waiting, const Rect &r) const
|
||||
{
|
||||
int width = ScaleSpriteTrad(10);
|
||||
uint num = std::min<uint>((waiting + (width / 2)) / width, r.Width() / width); // maximum is width / 10 icons so it won't overflow
|
||||
if (num == 0) return;
|
||||
|
||||
SpriteID sprite = CargoSpec::Get(cargo)->GetCargoIcon();
|
||||
|
||||
int x = _current_text_dir == TD_RTL ? r.left : r.right - num * width;
|
||||
int y = CentreBounds(r.top, r.bottom, this->cargo_icon_size.height);
|
||||
do {
|
||||
DrawSprite(sprite, PAL_NONE, x, y);
|
||||
x += width;
|
||||
} while (--num);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the given cargo entries in the station GUI.
|
||||
* @param entry Root entry for all cargo to be drawn.
|
||||
@@ -1830,32 +1830,34 @@ struct StationViewWindow : public Window {
|
||||
* @param cargo Current cargo being drawn (if cargo column has been passed).
|
||||
* @return row (in "pos" counting) after the one we have last drawn to.
|
||||
*/
|
||||
int DrawEntries(CargoDataEntry *entry, const Rect &r, int pos, int maxrows, int column, CargoType cargo = INVALID_CARGO)
|
||||
int DrawEntries(CargoDataEntry &entry, const Rect &r, int pos, int maxrows, int column, CargoType cargo = INVALID_CARGO)
|
||||
{
|
||||
assert(column < NUM_COLUMNS);
|
||||
if (this->sortings[column] == CargoSortType::AsGrouping) {
|
||||
if (this->groupings[column] != GR_CARGO) {
|
||||
entry->Resort(CargoSortType::StationString, this->sort_orders[column]);
|
||||
entry.Resort(CargoSortType::StationString, this->sort_orders[column]);
|
||||
}
|
||||
} else {
|
||||
entry->Resort(CargoSortType::Count, this->sort_orders[column]);
|
||||
entry.Resort(CargoSortType::Count, this->sort_orders[column]);
|
||||
}
|
||||
for (CargoDataSet::iterator i = entry->Begin(); i != entry->End(); ++i) {
|
||||
CargoDataEntry *cd = *i;
|
||||
int text_y_offset = (this->line_height - GetCharacterHeight(FS_NORMAL)) / 2;
|
||||
for (CargoDataSet::iterator i = entry.Begin(); i != entry.End(); ++i) {
|
||||
CargoDataEntry &cd = **i;
|
||||
|
||||
Grouping grouping = this->groupings[column];
|
||||
if (grouping == GR_CARGO) cargo = cd->GetCargo();
|
||||
if (grouping == GR_CARGO) cargo = cd.GetCargo();
|
||||
bool auto_distributed = _settings_game.linkgraph.GetDistributionType(cargo) != DT_MANUAL;
|
||||
|
||||
if (pos > -maxrows && pos <= 0) {
|
||||
StringID str = STR_EMPTY;
|
||||
StationID station = StationID::Invalid();
|
||||
int y = r.top - pos * GetCharacterHeight(FS_NORMAL);
|
||||
int y = r.top - pos * this->line_height;
|
||||
if (this->groupings[column] == GR_CARGO) {
|
||||
str = STR_STATION_VIEW_WAITING_CARGO;
|
||||
DrawCargoIcons(cd->GetCargo(), cd->GetCount(), r.left + this->expand_shrink_width, r.right - this->expand_shrink_width, y);
|
||||
this->DrawCargoIcons(cd.GetCargo(), cd.GetCount(), Rect(r.left + this->expand_shrink_width, y, r.right - this->expand_shrink_width, y + this->line_height - 1));
|
||||
} else {
|
||||
if (!auto_distributed) grouping = GR_SOURCE;
|
||||
station = cd->GetStation();
|
||||
station = cd.GetStation();
|
||||
str = this->GetGroupingString(grouping, station);
|
||||
if (grouping == GR_NEXT && str == STR_STATION_VIEW_VIA) str = this->SearchNonStop(cd, station, column);
|
||||
|
||||
@@ -1868,11 +1870,11 @@ struct StationViewWindow : public Window {
|
||||
Rect text = r.Indent(column * WidgetDimensions::scaled.hsep_indent, rtl).Indent(this->expand_shrink_width, !rtl);
|
||||
Rect shrink = r.WithWidth(this->expand_shrink_width, !rtl);
|
||||
|
||||
DrawString(text.left, text.right, y, GetString(str, cargo, cd->GetCount(), station));
|
||||
DrawString(text.left, text.right, y + text_y_offset, GetString(str, cargo, cd.GetCount(), station));
|
||||
|
||||
if (column < NUM_COLUMNS - 1) {
|
||||
const char *sym = nullptr;
|
||||
if (cd->GetNumChildren() > 0) {
|
||||
std::string_view sym;
|
||||
if (cd.GetNumChildren() > 0) {
|
||||
sym = "-";
|
||||
} else if (auto_distributed && str != STR_STATION_VIEW_RESERVED) {
|
||||
sym = "+";
|
||||
@@ -1881,17 +1883,17 @@ struct StationViewWindow : public Window {
|
||||
const GoodsEntry &ge = Station::Get(this->window_number)->goods[cargo];
|
||||
if (ge.HasData()) {
|
||||
const StationCargoList &cargo_list = ge.GetData().cargo;
|
||||
if (grouping == GR_CARGO && (cargo_list.ReservedCount() > 0 || cd->HasTransfers())) {
|
||||
if (grouping == GR_CARGO && (cargo_list.ReservedCount() > 0 || cd.HasTransfers())) {
|
||||
sym = "+";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sym != nullptr) DrawString(shrink.left, shrink.right, y, sym, TC_YELLOW);
|
||||
if (!sym.empty()) DrawString(shrink.left, shrink.right, y + text_y_offset, sym, TC_YELLOW);
|
||||
}
|
||||
this->SetDisplayedRow(cd);
|
||||
}
|
||||
--pos;
|
||||
if (auto_distributed || column == 0) {
|
||||
if ((auto_distributed || column == 0) && column < NUM_COLUMNS - 1) {
|
||||
pos = this->DrawEntries(cd, r, pos, maxrows, column + 1, cargo);
|
||||
}
|
||||
}
|
||||
@@ -2148,7 +2150,7 @@ struct StationViewWindow : public Window {
|
||||
this->SetDirty();
|
||||
}
|
||||
|
||||
void OnDropdownSelect(WidgetID widget, int index) override
|
||||
void OnDropdownSelect(WidgetID widget, int index, int) override
|
||||
{
|
||||
if (widget == WID_SV_SORT_BY) {
|
||||
this->SelectSortBy(index);
|
||||
@@ -2237,14 +2239,12 @@ static std::vector<StationID> _stations_nearby_list;
|
||||
* Add station on this tile to _stations_nearby_list if it's fully within the
|
||||
* station spread.
|
||||
* @param tile Tile just being checked
|
||||
* @param user_data Pointer to TileArea context
|
||||
* @param ctx Pointer to TileArea context
|
||||
* @tparam T the station filter type
|
||||
*/
|
||||
template <class T>
|
||||
static bool AddNearbyStation(TileIndex tile, void *user_data)
|
||||
static void AddNearbyStation(TileIndex tile, TileArea *ctx)
|
||||
{
|
||||
TileArea *ctx = (TileArea *)user_data;
|
||||
|
||||
/* First check if there were deleted stations here */
|
||||
for (auto it = _deleted_stations_nearby.begin(); it != _deleted_stations_nearby.end(); /* nothing */) {
|
||||
if (it->tile == tile) {
|
||||
@@ -2256,21 +2256,19 @@ static bool AddNearbyStation(TileIndex tile, void *user_data)
|
||||
}
|
||||
|
||||
/* Check if own station and if we stay within station spread */
|
||||
if (!IsTileType(tile, MP_STATION)) return false;
|
||||
if (!IsTileType(tile, MP_STATION)) return;
|
||||
|
||||
StationID sid = GetStationIndex(tile);
|
||||
|
||||
/* This station is (likely) a waypoint */
|
||||
if (!T::IsValidID(sid)) return false;
|
||||
if (!T::IsValidID(sid)) return;
|
||||
|
||||
BaseStation *st = BaseStation::Get(sid);
|
||||
if (st->owner != _local_company || std::ranges::find(_stations_nearby_list, sid) != _stations_nearby_list.end()) return false;
|
||||
if (st->owner != _local_company || std::ranges::find(_stations_nearby_list, sid) != _stations_nearby_list.end()) return;
|
||||
|
||||
if (st->rect.BeforeAddRect(ctx->tile, ctx->w, ctx->h, StationRect::ADD_TEST).Succeeded()) {
|
||||
_stations_nearby_list.push_back(sid);
|
||||
}
|
||||
|
||||
return false; // We want to include *all* nearby stations
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2283,7 +2281,7 @@ static bool AddNearbyStation(TileIndex tile, void *user_data)
|
||||
* @tparam T the station filter type, for stations to look for
|
||||
*/
|
||||
template <class T>
|
||||
static const BaseStation *FindStationsNearby(TileArea ta, bool distant_join)
|
||||
static void FindStationsNearby(TileArea ta, bool distant_join)
|
||||
{
|
||||
TileArea ctx = ta;
|
||||
|
||||
@@ -2291,11 +2289,6 @@ static const BaseStation *FindStationsNearby(TileArea ta, bool distant_join)
|
||||
_stations_nearby_list.push_back(NEW_STATION);
|
||||
_deleted_stations_nearby.clear();
|
||||
|
||||
/* Check the inside, to return, if we sit on another station */
|
||||
for (TileIndex t : ta) {
|
||||
if (t < Map::Size() && IsTileType(t, MP_STATION) && T::IsValidID(GetStationIndex(t))) return BaseStation::GetByTile(t);
|
||||
}
|
||||
|
||||
/* Look for deleted stations */
|
||||
for (const BaseStation *st : BaseStation::Iterate()) {
|
||||
if (T::IsValidBaseStation(st) && !st->IsInUse() && st->owner == _local_company) {
|
||||
@@ -2312,16 +2305,20 @@ static const BaseStation *FindStationsNearby(TileArea ta, bool distant_join)
|
||||
}
|
||||
}
|
||||
|
||||
/* Add stations that are within station tile area. Stations do not have to occupy all tiles */
|
||||
for (auto t : ta) {
|
||||
AddNearbyStation<T>(t, &ctx);
|
||||
}
|
||||
|
||||
/* Only search tiles where we have a chance to stay within the station spread.
|
||||
* The complete check needs to be done in the callback as we don't know the
|
||||
* extent of the found station, yet. */
|
||||
if (distant_join && std::min(ta.w, ta.h) >= _settings_game.station.station_spread) return nullptr;
|
||||
if (distant_join && std::min(ta.w, ta.h) >= _settings_game.station.station_spread) return;
|
||||
uint max_dist = distant_join ? _settings_game.station.station_spread - std::min(ta.w, ta.h) : 1;
|
||||
|
||||
TileIndex tile = TileAddByDir(ctx.tile, DIR_N);
|
||||
CircularTileSearch(&tile, max_dist, ta.w, ta.h, AddNearbyStation<T>, &ctx);
|
||||
|
||||
return nullptr;
|
||||
for (auto tile : SpiralTileSequence(TileAddByDir(ctx.tile, DIR_N), max_dist, ta.w, ta.h)) {
|
||||
AddNearbyStation<T>(tile, &ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr NWidgetPart _nested_select_station_widgets[] = {
|
||||
@@ -2377,7 +2374,7 @@ struct SelectStationWindow : Window {
|
||||
if (widget != WID_JS_PANEL) return;
|
||||
|
||||
/* Determine the widest string */
|
||||
Dimension d = GetStringBoundingBox(T::IsWaypoint() ? STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT : STR_JOIN_STATION_CREATE_SPLITTED_STATION);
|
||||
Dimension d = GetStringBoundingBox(T::IsWaypoint() ? STR_JOIN_WAYPOINT_CREATE_SPLIT_WAYPOINT : STR_JOIN_STATION_CREATE_SPLIT_STATION);
|
||||
for (const auto &station : _stations_nearby_list) {
|
||||
if (station == NEW_STATION) continue;
|
||||
const BaseStation *st = BaseStation::Get(station);
|
||||
@@ -2386,7 +2383,7 @@ struct SelectStationWindow : Window {
|
||||
: GetString(STR_STATION_LIST_STATION, st->index, st->facilities)));
|
||||
}
|
||||
|
||||
resize.height = d.height;
|
||||
fill.height = resize.height = d.height;
|
||||
d.height *= 5;
|
||||
d.width += padding.width;
|
||||
d.height += padding.height;
|
||||
@@ -2401,7 +2398,7 @@ struct SelectStationWindow : Window {
|
||||
auto [first, last] = this->vscroll->GetVisibleRangeIterators(_stations_nearby_list);
|
||||
for (auto it = first; it != last; ++it, tr.top += this->resize.step_height) {
|
||||
if (*it == NEW_STATION) {
|
||||
DrawString(tr, T::IsWaypoint() ? STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT : STR_JOIN_STATION_CREATE_SPLITTED_STATION);
|
||||
DrawString(tr, T::IsWaypoint() ? STR_JOIN_WAYPOINT_CREATE_SPLIT_WAYPOINT : STR_JOIN_STATION_CREATE_SPLIT_STATION);
|
||||
} else {
|
||||
const BaseStation *st = BaseStation::Get(*it);
|
||||
DrawString(tr, T::IsWaypoint()
|
||||
@@ -2484,7 +2481,7 @@ static WindowDesc _select_station_desc(
|
||||
* @return whether we need to show the station selection window.
|
||||
*/
|
||||
template <class T>
|
||||
static bool StationJoinerNeeded(TileArea ta, const StationPickerCmdProc &proc)
|
||||
static bool StationJoinerNeeded(const StationPickerCmdProc &proc)
|
||||
{
|
||||
/* Only show selection if distant join is enabled in the settings */
|
||||
if (!_settings_game.station.distant_join_stations) return false;
|
||||
@@ -2501,9 +2498,7 @@ static bool StationJoinerNeeded(TileArea ta, const StationPickerCmdProc &proc)
|
||||
/* only show the popup, if we press ctrl */
|
||||
if (!citymania::_fn_mod) return false;
|
||||
/* Now check if we could build there */
|
||||
if (!proc(true, StationID::Invalid())) return false;
|
||||
|
||||
return FindStationsNearby<T>(ta, false) == nullptr;
|
||||
return proc(true, StationID::Invalid());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2515,8 +2510,9 @@ static bool StationJoinerNeeded(TileArea ta, const StationPickerCmdProc &proc)
|
||||
template <class T>
|
||||
void ShowSelectBaseStationIfNeeded(TileArea ta, StationPickerCmdProc&& proc)
|
||||
{
|
||||
if (StationJoinerNeeded<T>(ta, proc)) {
|
||||
if (StationJoinerNeeded<T>(proc)) {
|
||||
if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace();
|
||||
FindStationsNearby<T>(ta, false);
|
||||
new SelectStationWindow<T>(_select_station_desc, ta, std::move(proc));
|
||||
} else {
|
||||
proc(false, StationID::Invalid());
|
||||
|
||||
Reference in New Issue
Block a user