Show raw industry production on minimap on max zoom level

This commit is contained in:
dP
2023-03-30 02:35:04 +04:00
parent ef9f6aa7f3
commit 03920496f0
4 changed files with 158 additions and 5 deletions

View File

@@ -11,6 +11,8 @@
#include "../town.h"
#include "../tunnelbridge_map.h"
#include "../core/endian_func.hpp"
#include "../core/geometry_func.hpp"
#include "../core/kdtree.hpp"
#include "../vehicle_base.h"
#include "../sound_func.h"
#include "../window_func.h"
@@ -170,10 +172,104 @@ static bool _smallmap_show_heightmap = false;
/** Highlight a specific industry type */
static IndustryType _smallmap_industry_highlight = INVALID_INDUSTRYTYPE;
/** State of highlight blinking */
static bool _smallmap_industry_highlight_state;
/** For connecting company ID to position in owner list (small map legend) */
static uint _company_to_list_pos[MAX_COMPANIES];
struct IconTextSizeHelper {
protected:
RectPadding padding;
public:
Dimension text_dim = {};
uint num_lines = 0;
Dimension icon_dim;
uint line_height;
uint text_ofs_y;
uint icon_ofs_y;
uint text_ofs_x;
Dimension size;
IconTextSizeHelper(SpriteID icon, RectPadding &padding) {
this->padding = padding;
this->icon_dim = GetSpriteSize(icon);
this->text_ofs_x = this->icon_dim.width + WidgetDimensions::scaled.hsep_normal;
}
void add(StringID string_id, FontSize font_size) {
this->text_dim = maxdim(this->text_dim, GetStringBoundingBox(string_id, font_size));
num_lines++;
};
void calculate() {
// TODO handle RTL
this->line_height = std::max(this->text_dim.height, this->icon_dim.height);
this->text_ofs_y = (this->line_height - this->text_dim.height + 1) / 2;
this->icon_ofs_y = (this->line_height - this->icon_dim.height) / 2;
this->size = {
this->text_ofs_x + this->text_dim.width + this->padding.Horizontal(),
this->line_height * this->num_lines + this->padding.Vertical()
};
}
std::pair<Rect, Rect> make_rects(int left, int top) {
Rect r{left, top, left + (int)this->size.width, top + (int)this->size.height};
return {r, r.Shrink(this->padding)};
}
};
struct MinimapIndustryKdtreeEntry {
int16 mx; // subtile (y - x) / 2
int16 my; // subtile (y + x) / 2
IndustryID index;
};
constexpr bool operator==(const MinimapIndustryKdtreeEntry &lhs, const MinimapIndustryKdtreeEntry &rhs) {
return lhs.index == rhs.index;
}
inline int16 Kdtree_MinimapIndustryXYFunc(const MinimapIndustryKdtreeEntry &e, int dim) { return dim == 0 ? e.mx : e.my; }
typedef Kdtree<MinimapIndustryKdtreeEntry, decltype(&Kdtree_MinimapIndustryXYFunc), int16, int> MinimapIndustryKdtree;
MinimapIndustryKdtree _minimap_industry_idx{Kdtree_MinimapIndustryXYFunc};
uint _max_industry_outputs = 0;
bool is_cached_industry(const Industry *ind) {
const IndustrySpec *indspec = GetIndustrySpec(ind->type);
return ((indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0);
}
MinimapIndustryKdtreeEntry get_industry_entry(const Industry *ind) {
auto x = TileX(ind->location.tile) * TILE_SIZE + ind->location.w * TILE_SIZE / 2;
auto y = TileY(ind->location.tile) * TILE_SIZE + ind->location.h * TILE_SIZE / 2;
uint num_outputs = 0;
for (auto i = 0; i < INDUSTRY_NUM_OUTPUTS; i++)
if (ind->produced_cargo[i] != INVALID_CARGO)
num_outputs++;
_max_industry_outputs = std::max(_max_industry_outputs, num_outputs);
return {(int16)((y - x) / 8), (int16)((y + x) / 8), ind->index};
}
void minimap_add_industry(const Industry *ind) {
if (!is_cached_industry(ind)) return;
_minimap_industry_idx.Insert(get_industry_entry(ind));
}
void minimap_remove_industry(const Industry *ind) {
if (!is_cached_industry(ind)) return;
_minimap_industry_idx.Remove(get_industry_entry(ind));
}
void minimap_init_industries() {
_max_industry_outputs = 0;
for (auto i : Industry::Iterate()) {
minimap_add_industry(i);
}
}
/**
* Fills an array for the industries legends.
*/
@@ -910,6 +1006,48 @@ void SmallMapWindow::DrawVehicles(const DrawPixelInfo *dpi, Blitter *blitter) co
}
}
void SmallMapWindow::DrawIndustryProduction(const DrawPixelInfo *dpi) const
{
if (this->map_type != CM_SMT_IMBA) return;
// Debug(misc, 0, "DrawIndustryProduction {},{} {},{}", dpi->left, dpi->top, sign_w, sign_h);
auto ptl = this->PixelToTile(dpi->left - this->industry_max_sign.width, dpi->top - this->industry_max_sign.height);
auto pbr = this->PixelToTile(dpi->left + dpi->width, dpi->top + dpi->height);
_minimap_industry_idx.FindContained(
(ptl.y - ptl.x) / 8,
(ptl.y + ptl.x) / 8,
(pbr.y - pbr.x) / 8,
(pbr.y + pbr.x) / 8,
[this] (auto &e) {
auto ind = Industry::GetIfValid(e.index);
if (ind == nullptr) return;
auto pt = this->TileToPixel(
TileX(ind->location.tile) * TILE_SIZE + ind->location.w * TILE_SIZE / 2,
TileY(ind->location.tile) * TILE_SIZE + ind->location.h * TILE_SIZE / 2
);
IconTextSizeHelper its{SPR_CARGO_COAL, WidgetDimensions::scaled.framerect};
for (auto i = 0; i < INDUSTRY_NUM_OUTPUTS; i++) {
if (ind->produced_cargo[i] == INVALID_CARGO) continue;
SetDParam(0, ind->last_month_production[i]);
its.add(STR_JUST_INT, FS_SMALL);
}
its.calculate();
this->industry_max_sign = maxdim(this->industry_max_sign, its.size);
auto [r, ir] = its.make_rects(pt.x, pt.y);
GfxFillRect(r, PALETTE_TO_TRANSPARENT, FILLRECT_RECOLOUR);
for (auto i = 0; i < INDUSTRY_NUM_OUTPUTS; i++) {
if (ind->produced_cargo[i] == INVALID_CARGO) continue;
DrawSprite(CargoSpec::Get(ind->produced_cargo[i])->GetCargoIcon(), PAL_NONE, ir.left, ir.top + its.icon_ofs_y);
SetDParam(0, ind->last_month_production[i]);
DrawString(ir.left + its.text_ofs_x, ir.right, ir.top + its.text_ofs_y, STR_JUST_INT, TC_WHITE, SA_LEFT, false, FS_SMALL);
ir.top += its.line_height;
}
}
);
}
/**
* Adds town names to the smallmap.
* @param dpi the part of the smallmap to be drawn into
@@ -1024,6 +1162,8 @@ void SmallMapWindow::DrawSmallMap(DrawPixelInfo *dpi) const
/* Draw vehicles */
if (this->map_type == SMT_CONTOUR || this->map_type == SMT_VEHICLES) this->DrawVehicles(dpi, blitter);
if (this->ui_zoom == 4) this->DrawIndustryProduction(dpi);
/* Draw link stat overlay */
if (this->map_type == SMT_LINKSTATS) this->overlay->Draw(dpi);
@@ -1198,6 +1338,13 @@ void SmallMapWindow::RebuildColourIndexIfNecessary()
SetDParam(0, 9999999); // max reasonable population
this->town_cache.max_sign = GetStringBoundingBox(CM_STR_SMALLMAP_POPULATION);
SetDParam(0, 9999);
auto text_dim = GetStringBoundingBox(STR_JUST_INT, FS_SMALL);
this->industry_max_sign = {
text_dim.width + WidgetDimensions::scaled.framerect.Horizontal(),
text_dim.height * _max_industry_outputs + WidgetDimensions::scaled.framerect.Vertical(),
};
}
/* virtual */ void SmallMapWindow::OnPaint()

View File

@@ -44,11 +44,9 @@ void ShowSmallMap();
void BuildLandLegend();
void BuildOwnerLegend();
//struct Mi
// inline uint16 Kdtree_MinimapSignXYFunc(TownID tid, int dim) { return (dim == 0) ? TileX(Town::Get(tid)->xy) : TileY(Town::Get(tid)->xy); }
// typedef Kdtree<TownID, decltype(&Kdtree_TownXYFunc), uint16, int> TownKdtree;
void minimap_add_industry(const Industry *ind);
void minimap_remove_industry(const Industry *ind);
void minimap_init_industries();
class NWidgetSmallmapDisplay;
@@ -108,6 +106,7 @@ protected:
Dimension max_sign;
std::vector<std::tuple<const Town *, uint32, uint>> towns;
} town_cache;
mutable Dimension industry_max_sign;
static void BreakIndustryChainLink();
Point SmallmapRemapCoords(int x, int y) const;

View File

@@ -50,6 +50,7 @@
#include "table/build_industry.h"
#include "citymania/cm_highlight.hpp"
#include "citymania/cm_minimap.hpp"
#include "safeguards.h"
@@ -151,6 +152,8 @@ Industry::~Industry()
* Also we must not decrement industry counts in that case. */
if (this->location.w == 0) return;
citymania::minimap_remove_industry(this);
const bool has_neutral_station = this->neutral_station != nullptr;
for (TileIndex tile_cur : this->location) {
@@ -1931,6 +1934,8 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
InvalidateWindowData(WC_INDUSTRY_DIRECTORY, 0, IDIWD_FORCE_REBUILD);
if (!_generating_world) PopulateStationsNearby(i);
citymania::minimap_add_industry(i);
citymania::UpdateIndustryHighlight();
}

View File

@@ -64,6 +64,7 @@
#include "../table/control_codes.h"
#include "../citymania/cm_highlight.hpp"
#include "../citymania/cm_minimap.hpp"
#include "saveload_internal.h"
@@ -3258,6 +3259,7 @@ bool AfterLoadGame()
AfterLoadLinkGraphs();
AfterLoadFindBTProCBInfo();
citymania::InitializeZoningMap();
citymania::minimap_init_industries();
if ((!_networking || _network_server ) && _settings_client.gui.cm_pause_after_load) _pause_mode = PM_PAUSED_NORMAL;