25 #include <unordered_map>
26 #include "eng3d/string.hpp"
27 #include "eng3d/texture.hpp"
28 #include "eng3d/ui/button.hpp"
29 #include "eng3d/ui/close_button.hpp"
30 #include "eng3d/ui/image.hpp"
31 #include "eng3d/ui/tooltip.hpp"
32 #include "eng3d/ui/div.hpp"
33 #include "eng3d/ui/label.hpp"
34 #include "eng3d/ui/table.hpp"
65 :
UI::Window(_x, _y, 400, 200),
71 this->
padding = glm::ivec2(0, 24);
73 auto& flex_column1 = this->make_widget<UI::Div>(5, 5, 24, 190);
76 auto& flex_column2 = this->make_widget<UI::Div>(35, 5, 24, 190);
80 auto& flat_btn = flex_column1.make_widget<
UI::Image>(0, 0, 24, 24,
"gfx/flat_icon.png");
84 flat_btn.set_tooltip(
"Flat map");
86 auto& globe_btn = flex_column2.make_widget<
UI::Image>(0, 0, 24, 24,
"gfx/globe_icon.png");
90 globe_btn.set_tooltip(
"Globe map");
92 auto& landscape_ibtn = flex_column1.make_widget<
UI::Image>(0, 0, 24, 24,
"gfx/icon.png");
94 this->gs.
map->set_selection(
nullptr);
96 set_mapmode_options(
nullptr);
98 landscape_ibtn.set_tooltip(
"Terrain");
100 auto& political_ibtn = flex_column1.make_widget<
UI::Image>(0, 0, 24, 24,
"gfx/icon.png");
102 this->gs.
map->set_selection(
nullptr);
104 set_mapmode_options(
nullptr);
106 political_ibtn.set_tooltip(
"Political");
108 auto& relations_ibtn = flex_column1.make_widget<
UI::Image>(0, 0, 24, 24,
"gfx/icon.png");
119 this->gs.
map->set_map_mode(map_mode, map_tooltip);
120 set_mapmode_options(
nullptr);
122 relations_ibtn.set_tooltip(
"Relations");
124 auto& transport_cost_ibtn = flex_column1.make_widget<
UI::Image>(0, 0, 24, 24,
"gfx/icon.png");
126 this->gs.
map->set_selection([](
const World&,
Map& map,
const Province& selected_province) {
129 set_mapmode_options(
nullptr);
131 transport_cost_ibtn.set_tooltip(
"Transport cost");
133 auto& population_ibtn = flex_column1.make_widget<
UI::Image>(0, 0, 24, 24,
"gfx/icon.png");
135 this->gs.
map->set_selection(
nullptr);
137 set_mapmode_options(
nullptr);
139 population_ibtn.set_tooltip(
"Population");
141 auto& terrain_color_ibtn = flex_column2.make_widget<
UI::Image>(0, 0, 24, 24,
"gfx/icon.png");
143 this->gs.
map->set_selection(
nullptr);
145 std::vector<ProvinceColor> province_color;
146 for(
unsigned int i = 0; i < world.provinces.size(); i++) {
147 const auto& province = world.provinces[i];
149 province_color.emplace_back(
ProvinceId(i), color);
153 return province_color;
156 return world.terrain_types[world.provinces[id].terrain_type_id].name;
158 this->gs.
map->set_map_mode(map_mode, map_tooltip);
159 set_mapmode_options(
nullptr);
161 terrain_color_ibtn.set_tooltip(
"Simple terrain");
163 auto& language_ibtn = flex_column2.make_widget<
UI::Image>(0, 0, 24, 24,
"gfx/icon.png");
165 this->gs.
map->set_selection(
nullptr);
168 set_mapmode_options(
nullptr);
170 language_ibtn.set_tooltip(
"Language diversity");
172 auto& religion_ibtn = flex_column2.make_widget<
UI::Image>(0, 0, 24, 24,
"gfx/icon.png");
174 this->gs.
map->set_selection(
nullptr);
176 set_mapmode_options(
nullptr);
178 religion_ibtn.set_tooltip(
"Religion");
180 auto& commodity_price_ibtn = flex_column2.make_widget<
UI::Image>(0, 0, 24, 24,
"gfx/icon.png");
182 this->gs.
map->set_selection(
nullptr);
185 commodity_price_ibtn.set_tooltip(
"Commodity");
187 auto& militancy_ibtn = flex_column2.make_widget<
UI::Image>(0, 0, 24, 24,
"gfx/icon.png");
189 this->gs.
map->set_selection([](
const World&,
Map& map,
const Province& selected_province) {
191 return [id](
const World& world) {
192 const auto& province = world.provinces[id];
193 const auto& nation = world.nations[province.owner_id];
194 const auto& ai =
ai_man[nation];
196 auto max_amount = 0.f;
197 for(
const auto& province : world.provinces)
198 max_amount = glm::max(ai.potential_risk[province], max_amount);
203 std::vector<ProvinceColor> province_color;
204 for(
const auto& province : world.provinces) {
205 auto ratio = province.average_militancy();
206 province_color.emplace_back(province.get_id(), Eng3D::Color::lerp(min, max, ratio));
208 return province_color;
210 })(selected_province),
212 return [province_id](
const World& world,
const ProvinceId id) -> std::string {
213 const auto& province = world.provinces[id];
214 return translate_format(
"Average militancy: %.2f", province.average_militancy());
216 })(selected_province));
218 set_mapmode_options(
nullptr);
220 militancy_ibtn.set_tooltip(
"Militancy");
222 auto& debug_ibtn = flex_column2.make_widget<
UI::Image>(0, 0, 24, 24,
"gfx/icon.png");
224 this->gs.
map->set_selection([](
const World&,
Map& map,
const Province& selected_province) {
226 return [id](
const World& world) {
227 const auto& province = world.provinces[id];
228 const auto& nation = world.nations[province.owner_id];
229 const auto& ai =
ai_man[nation];
231 auto max_amount = 0.f;
232 for(
const auto& province : world.provinces)
233 max_amount = glm::max(ai.potential_risk[province], max_amount);
238 std::vector<ProvinceColor> province_color;
239 for(
const auto& province : world.provinces) {
240 auto ratio = ai.potential_risk[province] / max_amount;
241 province_color.emplace_back(province.get_id(), Eng3D::Color::lerp(min, max, ratio));
243 return province_color;
245 })(selected_province),
247 return [province_id](
const World& world,
const ProvinceId id) -> std::string {
248 const auto& province = world.provinces[id];
249 const auto& nation = world.nations[province.owner_id];
250 const auto& ai =
ai_man[nation];
251 return translate_format(
"Potential risk: %.2f (Our strenght: %.2f)\nWar weight: %.2f\nUnit battle weight: %.2f\nUnit exist weight: %.2f\nCoastal weight: %.2f\nReconquer weight: %.2f\nStrength threshold: %.2f\nErratic: %.2f\nOverride threshold: %.2f\nGains/losses: %zu/%zu\nMilitary strength: %.2f", ai.potential_risk[province], ai.military_strength, ai.war_weight, ai.unit_battle_weight, ai.unit_exist_weight, ai.coastal_weight, ai.reconquer_weight, ai.strength_threshold, ai.erratic, ai.override_threshold, ai.gains, ai.losses);
253 })(selected_province));
255 set_mapmode_options(
nullptr);
257 debug_ibtn.set_tooltip(
"Debug");
262 void Minimap::set_mapmode_options(Widget* widget) {
264 mapmode_options->kill();
265 mapmode_options = widget;
269 void MapmodeCommodityOptions::update_map_mode() {
273 this->gs.
map->set_map_mode(map_mode, map_tooltip);
277 :
UI::Div(-200, -300, 200, 500, nullptr),
288 const auto& product = world.provinces[id].products[this->commodity_id];
289 return product.price;
292 auto& price_btn = this->make_widget<UI::Button>(0, 0, 125, 24);
293 price_btn.set_text(
"Price");
296 const auto& product = world.provinces[id].products[this->commodity_id];
297 return product.price;
301 auto& demand_btn = this->make_widget<UI::Button>(0, 0, 125, 24);
302 demand_btn.set_text(
"Demand");
305 const auto& product = world.provinces[id].products[this->commodity_id];
306 return product.demand;
310 auto& supply_btn = this->make_widget<UI::Button>(0, 0, 125, 24);
311 supply_btn.set_text(
"Supply");
314 const auto& product = world.provinces[id].products[this->commodity_id];
315 return product.supply;
319 auto& price_delta_btn = this->make_widget<UI::Button>(0, 0, 125, 24);
320 price_delta_btn.set_text(
"Price change");
321 price_delta_btn.set_on_click([
this](
UI::Widget&) {
323 const auto& product = world.provinces[id].products[this->commodity_id];
324 return product.price_delta;
328 auto& production_btn = this->make_widget<UI::Button>(0, 0, 125, 24);
329 production_btn.set_text(
"Production");
330 production_btn.set_on_click([
this](
UI::Widget&) {
332 const auto& province = world.provinces[id];
333 const auto& product = province.products[this->commodity_id];
335 for(
const auto& building_type : world.building_types)
336 if (building_type.output_id == this->commodity_id)
337 total += province.buildings[building_type].get_output_amount();
343 std::vector<int> sizes{ 160 };
344 std::vector<std::string> header{
"Goods" };
345 auto& table = this->make_widget<UI::Table<CommodityId::Type>>(4, 4, 400 - 8, 35, sizes, header);
346 for(
const auto& commodity : gs.
world->commodities) {
347 auto& row = table.get_row(commodity);
348 auto commodity_row = row.get_element(0);
352 commodity_row->make_widget<
UI::Image>(0, 0, 35, 35, good_tex);
354 commodity_row->set_key(good_str);
356 this->commodity_id = commodity.get_id();
364 return [good_id](
const World& world,
const ProvinceId id) -> std::string {
365 const auto& province = world.provinces[id];
366 const auto& product = province.products[good_id];
368 auto total_production = 0.f;
369 for(
const auto& building_type : world.building_types)
370 if (building_type.output_id == good_id)
371 total_production += province.buildings[building_type].get_output_amount();
374 "%s,\nPrice %.2f\nGlobal demand %.2f\nDemand %.2f (Sold today %.2f)\nSupply %.2f (Produced today %.2f)\nProduction %.2f\n",
375 province.name.c_str(), product.price, product.global_demand, product.demand, product.bought, product.supply, product.produced, total_production);
376 for(
const auto& building_type : world.building_types) {
377 const auto& building = province.buildings[building_type];
379 str +=
translate_format(
"%s (level %.0f), scale %.0f, workers %.0f, budget %.0f\n", building_type.name.c_str(), building.level, building.production_scale, building.workers, building.budget);
389 return [province_value, min_col, max_col](
const World& world) {
390 std::vector<std::pair<ProvinceId, float>> province_amounts;
391 auto max_value = glm::epsilon<float>();
392 for(
auto const& province : world.provinces) {
393 auto id = province.get_id();
395 float value = std::log2f(province_value(world,
id) + 1.f);
396 max_value = glm::max(value, max_value);
397 province_amounts.emplace_back(
id, value);
401 std::vector<ProvinceColor> province_color;
402 for(
auto const& [prov_id, value] : province_amounts) {
403 auto ratio = value / max_value;
407 return province_color;
411 #include "eng3d/utils.hpp"
413 return [id](
const World& world) {
414 std::vector<ProvinceColor> provinces_color;
415 const auto& nation = world.nations[id];
416 for(
size_t i = 0; i < world.provinces.size(); i++) {
417 const auto& province = world.provinces[i];
418 if(province.controller_id == nation || world.nations[province.controller_id].is_puppeted_by(nation)) {
420 provinces_color.emplace_back(
ProvinceId(i), color);
424 const auto& relation = world.get_relation(province.controller_id,
id);
425 const uint8_t r = relation.relation < 0.f ? -relation.relation : 0;
426 const uint8_t g = relation.relation > 0.f ? relation.relation : 0;
427 const uint8_t b = relation.is_allied() ? 0x80 : 0;
429 provinces_color.emplace_back(
ProvinceId(i), color);
431 return provinces_color;
436 return [nation_id](
const World& world,
const ProvinceId id) -> std::string {
437 const auto& province = world.provinces[id];
438 const auto& province_controller = world.nations[province.controller_id];
441 if(province.controller_id == province.owner_id) {
442 str += province_controller.get_client_hint().name;
444 str +=
translate_format(
"Province owned by %s and controlled by %s", world.nations[province.owner_id].get_client_hint().name.c_str(), province_controller.get_client_hint().name.c_str());
447 if(province_controller.is_puppeted) {
448 str +=
string_format(
"\nPuppet of %s", world.nations[province_controller.puppet_master_id].get_client_hint().name.c_str());
452 if(province.controller_id != nation_id) {
453 const auto& nation = world.nations[province.controller_id];
454 const auto& relation = world.
get_relation(nation, nation_id);
455 if(relation.is_allied()) {
456 str +=
string_format(
"\nAllied with %s", nation.get_client_hint().name.c_str());
457 }
else if(relation.has_war) {
458 str +=
string_format(
"\nAt war with %s", nation.get_client_hint().name.c_str());
461 static std::array<std::string, 7> rel_lvls = {
471 size_t idx = (1.f + relation.relation) * rel_lvls.size();
472 str +=
string_format(
"\n%.2f%% - %s", relation.relation * 100.f, rel_lvls[idx % rel_lvls.size()].c_str());
474 nation.get_allies([&](
const auto& _nation) {
475 str +=
string_format(
"%s,", _nation.get_client_hint().name.c_str());
483 std::vector<ProvinceColor> province_color;
484 for(
size_t i = 0; i < world.provinces.size(); i++)
488 return province_color;
492 std::vector<ProvinceColor> province_color;
494 for(
size_t i = 0; i < world.provinces.size(); i++) {
495 const auto& province = world.provinces[i];
496 std::vector<size_t> religion_amounts(world.religions.size());
497 size_t total_amount = province.total_pops();
498 size_t max_amount = 0;
499 size_t max_religion_id = 0;
500 for(
const auto& religion : world.religions) {
501 religion_amounts[religion] = province.religions[religion] * total_amount;
502 size_t amount = religion_amounts[religion];
503 if(amount > max_amount) {
505 max_religion_id = religion;
510 province_color.emplace_back(
ProvinceId(i), color);
514 return province_color;
518 const auto& province = world.provinces[id];
519 const auto it = std::max_element(province.religions.begin(), province.religions.end());
520 return world.religions[std::distance(province.religions.begin(), it)].name;
524 std::vector<ProvinceColor> province_color;
526 for(
size_t i = 0; i < world.provinces.size(); i++) {
527 const auto& province = world.provinces[i];
528 std::vector<size_t> language_amounts(world.languages.size());
529 size_t total_amount = province.total_pops();
530 size_t max_amount = 0;
531 size_t max_language_id = 0;
532 for(
const auto& language : world.languages) {
533 language_amounts[language] = province.languages[language] * total_amount;
534 size_t amount = language_amounts[language];
535 if(amount > max_amount) {
537 max_language_id = language;
542 province_color.emplace_back(
ProvinceId(i), color);
546 return province_color;
550 const auto& province = world.provinces[id];
551 if(!province.is_populated())
return "";
552 const auto it = std::max_element(province.languages.begin(), province.languages.end());
553 return world.languages[std::distance(province.languages.begin(), it)].name;
558 std::vector<std::pair<ProvinceId, float>> province_amounts;
559 float max_amount = 1.f;
560 for(
auto const& province : world.provinces) {
561 float amount = std::accumulate(province.pops.cbegin(), province.pops.cend(), 0, [](
const float a,
const auto& e) {
564 amount = std::log2(amount);
565 max_amount = glm::max(amount, max_amount);
566 province_amounts.emplace_back(province.get_id(), amount);
572 std::vector<ProvinceColor> province_color;
573 for(
auto const& [province_id, amount] : province_amounts) {
579 auto ratio = amount / max_amount;
581 province_color.emplace_back(province_id, color);
583 return province_color;
587 const auto& province = world.provinces[id];
588 if(!province.is_populated())
return "";
589 size_t amount = province.total_pops();
590 return string_format(
"%s\nPopulation: %zu", province.name.c_str(), amount);
594 return [id](
const World& world) {
596 std::vector<std::pair<ProvinceId, float>> province_amounts;
597 auto max_amount = 1.f;
598 for(
const auto& province : world.provinces) {
599 auto amount = world.economy_state.trade.get_trade_cost(world.provinces[
id], province, glm::vec2{ world.width, world.height });
600 amount = std::log2(amount);
601 max_amount = glm::max(amount, max_amount);
602 province_amounts.emplace_back(province.get_id(), amount);
608 std::vector<ProvinceColor> province_color;
609 for(
const auto& [province_id, amount] : province_amounts) {
610 if(province_id ==
id)
615 auto ratio = amount / max_amount;
618 return province_color;
623 return [province_id](
const World& world,
const ProvinceId id) -> std::string {
624 const auto& province = world.provinces[province_id];
625 const auto& other_province = world.provinces[id];
627 return translate_format(
"Transport from %s to %s costs %.2f", province.name.c_str(), other_province.name.c_str(), amount);
std::vector< AIManager > ai_man
std::shared_ptr< Eng3D::IO::Asset::Base > get_unique(const Eng3D::IO::Path &path)
Obtaining an unique asset means the "first-found" policy applies.
Eng3D::TextureManager tex_man
Eng3D::IO::PackageManager package_man
std::shared_ptr< Eng3D::Texture > load(const std::string &path, TextureOptions options=default_options)
Finds a texture in the list of a texture manager if the texture is already in the list we load the sa...
std::unique_ptr< Map > map
MapmodeCommodityOptions(GameState &gs)
Minimap(GameState &gs, int x, int y, UI::Origin origin)
void set_map_mode(mapmode_generator mapmode_func, mapmode_tooltip tooltip_func)
A single province, which is used to simulate economy in a "bulk-tiles" way instead of doing economica...
Border class that defines the texture and size of borders of the widgets.
Image widget, can display pictures or effects on the screen.
Simple widget for drawing text on the screen, no multiline support.
Nation::Relation & get_relation(NationId a, NationId b)
Economy::EconomyState economy_state
std::string empty_province_tooltip(const World &, const ProvinceId)
std::string political_province_tooltip(const World &world, const ProvinceId id)
std::vector< ProvinceColor > political_map_mode(const World &world)
std::function< std::string(const World &world, const ProvinceId id)> mapmode_tooltip
std::function< std::vector< ProvinceColor >const World &world)> mapmode_generator
Origin
The origin of the widget.
mapmode_generator relations_map_mode(NationId id)
std::vector< ProvinceColor > language_map_mode(const World &world)
const Eng3D::Color MAPMODE_DEFAULT_MAX_COL
mapmode_generator trade_map_mode(ProvinceId id)
std::vector< ProvinceColor > terrain_map_mode(const World &world)
const Eng3D::Color MAPMODE_DEFAULT_MIN_COL
std::vector< ProvinceColor > religion_map_mode(const World &world)
mapmode_tooltip commodity_tooltip(CommodityId id)
mapmode_tooltip relations_tooltip(NationId id)
mapmode_generator commodity_map_mode(CommodityId id)
std::string religion_tooltip(const World &world, const ProvinceId id)
mapmode_tooltip trade_tooltip(ProvinceId id)
std::vector< ProvinceColor > population_map_mode(const World &world)
std::string language_tooltip(const World &world, const ProvinceId id)
mapmode_generator generic_map_mode(std::function< float(const World &, ProvinceId)> province_value, Eng3D::Color min_col=MAPMODE_DEFAULT_MIN_COL, Eng3D::Color max_col=MAPMODE_DEFAULT_MAX_COL)
std::string population_tooltip(const World &world, const ProvinceId id)
std::string translate(const std::string_view str)
std::string string_format(const std::string_view format, Args &&... args)
String formatter.
std::string translate_format(const std::string_view format, Args &&... args)
String formatter, with translation.
float get_trade_cost(const Province &province1, const Province &province2, glm::vec2 world_size) const
Primitive color type used through the engine.
constexpr static Color rgb8(uint8_t red, uint8_t green, uint8_t blue)
Create a color from RGB components.
constexpr static Color bgr32(uint32_t abgr)
constexpr static Color lerp(Color color1, Color color2, float lamda)
Combine two colors with LERP.
constexpr Id get_id() const