25 #include "eng3d/texture.hpp"
26 #include "eng3d/string.hpp"
27 #include "eng3d/ui/piechart.hpp"
28 #include "eng3d/ui/label.hpp"
29 #include "eng3d/ui/image.hpp"
30 #include "eng3d/ui/tooltip.hpp"
31 #include "eng3d/ui/button.hpp"
32 #include "eng3d/ui/table.hpp"
33 #include "eng3d/ui/close_button.hpp"
51 std::vector<UI::ChartData> languages_data, religions_data, pop_types_data;
52 for(
const auto& language : gs.
world->languages) {
56 languages_pie->
set_data(languages_data);
58 for(
const auto& religion : gs.
world->religions) {
62 religions_pie->
set_data(religions_data);
64 std::vector<size_t> pop_type_sizes(gs.
world->pop_types.size(), 0);
65 for(
const auto& pop : province.
pops)
66 pop_type_sizes[pop.type_id] += pop.size;
67 for(
const auto& pop_type : gs.
world->pop_types) {
68 const auto i =
static_cast<size_t>(pop_type.get_id());
70 static_cast<uint8_t
>((i * 3) % 256),
71 static_cast<uint8_t
>((i * 7) % 256),
72 static_cast<uint8_t
>((i * 15) % 256)
76 pop_types_pie->
set_data(pop_types_data);
79 UI::Widget& ProvincePopulationTab::create_pop_table() {
80 std::vector<int> sizes{ 64, 96 };
81 std::vector<std::string> header{
"Size",
"Budget" };
84 header.push_back(
" ");
87 auto& pop_table = this->make_widget<UI::Table<uint32_t>>(0, 352, this->
height - (352 + 32), 30, sizes, header);
88 pop_table.reserve(this->province.
pops.size());
89 pop_table.set_on_each_tick([
this, &pop_table](
UI::Widget&) {
90 for(
size_t i = 0; i < this->province.
pops.size(); i++) {
91 auto& pop = this->province.
pops[i];
92 auto& row = pop_table.get_row(i);
95 auto* size = row.get_element(row_index++);
97 size->set_text(size_str);
98 size->set_key(pop.size);
100 auto* budget = row.get_element(row_index++);
101 auto budget_str =
string_format(
"%.0f", pop.budget / pop.size);
102 budget->set_text(budget_str);
104 budget->set_tooltip(budget_tip);
105 budget->set_key(pop.budget / pop.size);
108 auto* remove_btn = row.get_element(row_index++);
109 auto remove_btn_str =
"X";
110 remove_btn->set_text(remove_btn_str);
111 remove_btn->set_key(remove_btn_str);
112 remove_btn->set_on_click([
this, i, &pop_table](
UI::Widget&) {
113 pop_table.remove_row(i);
114 const_cast<Province&
>(this->province).pops[i].size = 0.f;
115 pop_table.on_each_tick(pop_table);
120 pop_table.on_each_tick(pop_table);
124 UI::Widget& ProvincePopulationTab::create_stock_table() {
125 std::vector<int> sizes{ 100, 100, 100, 100, 100 };
126 std::vector<std::string> header{
"Commodity",
"Amount",
"Demand",
"Glob Demand",
"Price" };
127 auto& stock_table = this->make_widget<UI::Table<uint32_t>>(0, 352, this->
height - (352 + 32), 30, sizes, header);
128 stock_table.reserve(this->province.
pops.size());
129 stock_table.set_on_each_tick([
this, &stock_table](
UI::Widget&) {
130 for(
const auto& commodity : this->gs.
world->commodities) {
131 auto& product = this->province.products[commodity];
132 auto& row = stock_table.get_row(commodity.get_id());
133 size_t row_index = 0;
135 auto* commodity_row = row.get_element(row_index++);
136 commodity_row->set_key(commodity.name.c_str());
137 auto& commodity_img = commodity_row->make_widget<UI::Image>(0, 0, 35, 35, commodity.get_icon_path(), true);
138 commodity_img.set_tooltip(commodity.name);
140 auto* amount = row.get_element(row_index++);
141 amount->set_key(product.supply,
"%.0f");
143 auto* demand = row.get_element(row_index++);
144 demand->set_key(product.demand,
"%.1f");
146 auto* global_demand = row.get_element(row_index++);
147 global_demand->set_key(product.global_demand,
"%.2f");
149 auto* price = row.get_element(row_index++);
150 price->set_key(product.price,
"%.2f");
153 stock_table.on_each_tick(stock_table);
158 :
UI::Group(_x, _y, _parent->width - _x, _parent->height - _y, _parent),
160 province{ _province }
166 auto& landscape_img = this->make_widget<UI::Image>(0, 0, this->
width - 16, 128 + 64 + 16, terrain_type.get_icon_path());
167 landscape_img.set_tooltip(
translate_format(
"%s, penalty %.2f", terrain_type.name.c_str(), terrain_type.penalty));
169 auto& owner_flag = this->make_widget<UI::AspectImage>(0, 0, 96, 48, gs.
get_nation_flag(gs.
world->nations[this->province.owner_id]));
173 owner_flag.set_tooltip(
translate_format(
"%s owns this province", gs.
world->nations[this->province.owner_id].name.c_str()));
177 auto& nuclei_flex_row = this->make_widget<UI::Div>(0, landscape_img.height - 24, this->width, 24);
179 for(
const auto nucleus_id : province.
nuclei) {
180 auto& nucleus = this->gs.
world->nations[nucleus_id];
185 owner_flag.set_tooltip(
translate_format(
"%s has claims on this province", nucleus.name.c_str()));
188 auto& pop_table = create_pop_table();
189 auto& stock_table = create_stock_table();
190 stock_table.right_side_of(pop_table);
192 auto& languages_lab = this->make_widget<UI::Label>(0, 0,
"Languages");
193 languages_lab.below_of(landscape_img);
194 this->languages_pie = &this->make_widget<UI::PieChart>(0, 0, 96, 96);
195 this->languages_pie->
below_of(languages_lab);
197 auto& religions_lab = this->make_widget<UI::Label>(0, 0,
"Religions");
198 religions_lab.below_of(landscape_img);
199 religions_lab.right_side_of(*this->languages_pie);
200 this->religions_pie = &this->make_widget<UI::PieChart>(0, 0, 96, 96);
201 this->religions_pie->
below_of(religions_lab);
204 auto& pop_types_lab = this->make_widget<UI::Label>(0, 0,
"Professions");
205 pop_types_lab.below_of(landscape_img);
206 pop_types_lab.right_side_of(*this->religions_pie);
207 this->pop_types_pie = &this->make_widget<UI::PieChart>(0, 0, 96, 96);
208 this->pop_types_pie->
below_of(pop_types_lab);
218 :
UI::Group(_x, _y, _parent->width - _x, _parent->height - _y, _parent),
220 province{ _province }
227 :
UI::Group(_x, _y, _parent->width - _x, _parent->height - _y, _parent),
229 province{ _province }
235 :
UI::Group(_x, _y, _parent->width - _x, _parent->height - _y, _parent),
237 province{ _province },
238 language{ _gs.world->languages[0] },
239 religion{ _gs.world->religions[0] }
243 std::vector<int> sizes{ 96, 128 };
244 std::vector<std::string> header{
"Language",
"Religion" };
245 auto& table = this->make_widget<UI::Table<uint32_t>>(0, 0, this->
height, 30, sizes, header);
246 table.reserve(this->
gs.
world->languages.size());
247 table.set_on_each_tick([
this, &table](
Widget&) {
248 for(
size_t i = 0; i < this->
gs.
world->religions.size() || i < this->
gs.
world->languages.size(); i++) {
249 auto& row = table.get_row(i);
250 size_t row_index = 0;
252 auto& row_religion = i >= this->
gs.
world->religions.size() ? this->
gs.
world->religions[0] : this->
gs.
world->religions[i];
253 auto* religion_icon = row.get_element(row_index++);
255 religion_icon->set_tooltip(row_religion.name);
256 religion_icon->set_key(row_religion.name);
257 religion_icon->set_on_click([
this, religion_id = row_religion.get_id()](
UI::Widget&) {
258 const_cast<Province&>(this->province).religions[religion_id] = 1.f;
259 this->gs.map->update_mapmode();
260 this->gs.input.selected_religion = &this->gs.world->religions[religion_id];
263 auto& row_language = i >= this->
gs.
world->languages.size() ? this->
gs.
world->languages[0] : this->
gs.
world->languages[i];
264 auto* name = row.get_element(row_index++);
265 name->set_text(row_language.name);
266 name->set_tooltip(row_language.name);
267 name->set_key(row_language.name);
268 name->set_on_click([
this, language_id = row_language.get_id()](
UI::Widget&) {
269 const_cast<Province&>(this->province).languages[language_id] = 1.f;
270 this->gs.map->update_mapmode();
271 this->gs.input.selected_language = &this->gs.world->languages[language_id];
275 table.on_each_tick(table);
279 :
UI::Group(_x, _y, _parent->width - _x, _parent->height - _y, _parent),
281 province{ _province },
282 terrain_type{ _gs.world->terrain_types[0] }
284 std::vector<int> sizes{ 96, 128 };
285 std::vector<std::string> header{
"Landscape",
"Name" };
286 auto& table = this->make_widget<UI::Table<uint32_t>>(0, 0, this->
height, 30, sizes, header);
287 table.reserve(
gs.
world->terrain_types.size());
288 table.set_on_each_tick([
this, &table](
Widget&) {
289 for(
auto& terrain_type_row : this->
gs.
world->terrain_types) {
290 auto& row = table.get_row(terrain_type_row);
291 size_t row_index = 0;
293 auto landscape = row.get_element(row_index++);
295 landscape->current_texture = landscape_icon;
296 landscape->set_tooltip(terrain_type_row.name);
297 landscape->set_key(terrain_type_row.name);
299 auto name = row.get_element(row_index++);
300 name->set_text(terrain_type_row.name);
301 name->set_tooltip(terrain_type_row.name);
302 name->set_key(terrain_type_row.name);
303 name->set_on_click([
this, &terrain_type_row](
UI::Widget&) {
306 if(terrain_type_row.is_water_body) {
307 nc_province.unpopulate();
308 nc_province.nuclei.clear();
309 for(
auto& building : nc_province.buildings)
313 this->
gs.
map->update_mapmode();
317 table.on_each_tick(table);
321 :
UI::Window(-400, -400, 800, 800),
323 province{ _province }
329 this->gs.
map->set_selected_province(
true, this->province.
get_id());
335 auto& flex_row = this->make_widget<UI::Div>(0, 0, this->
width, 32);
338 flex_row.height += 32;
340 this->pop_tab = &this->make_widget<ProvincePopulationTab>(gs, 0, flex_row.height, province);
342 auto& pop_ibtn = flex_row.make_widget<
UI::Image>(0, 0, 32, 32,
"gfx/pv_1.png");
348 this->edit_language_tab->
is_render =
false;
349 this->edit_terrain_tab->
is_render =
false;
352 pop_ibtn.set_tooltip(
translate(
"Population"));
354 this->econ_tab = &this->make_widget<ProvinceEconomyTab>(gs, 0, flex_row.height, province);
356 auto& econ_ibtn = flex_row.make_widget<
UI::Image>(0, 0, 32, 32,
"gfx/money.png");
362 this->edit_language_tab->
is_render =
false;
363 this->edit_terrain_tab->
is_render =
false;
366 econ_ibtn.set_tooltip(
translate(
"Economy"));
368 this->build_tab = &this->make_widget<ProvinceBuildingTab>(gs, 0, flex_row.height, province);
370 auto& build_ibtn = flex_row.make_widget<
UI::Image>(0, 0, 32, 32,
"gfx/pv_0.png");
376 this->edit_language_tab->
is_render =
false;
377 this->edit_terrain_tab->
is_render =
false;
380 build_ibtn.set_tooltip(
translate(
"Buildings"));
383 auto& fill_pops_btn = flex_row.make_widget<
UI::Button>(0, this->
height - 64, 32, 32);
387 for(
const auto& pop_type : this->gs.
world->pop_types)
388 if(pop_type.social_value > max_sv)
389 max_sv = pop_type.social_value;
396 for(
const auto& pop_type : this->gs.
world->pop_types) {
397 auto& pop = province.
pops[pop_type];
398 pop.type_id = pop_type.get_id();
401 pop.budget = pop.size;
403 this->gs.
map->update_mapmode();
406 fill_pops_btn.set_tooltip(
translate_format(
"Add POPs (will add %zu POPs)", gs.
world->pop_types.size()));
408 this->edit_language_tab = &this->make_widget<ProvinceEditLanguageTab>(gs, 0, 32, province);
409 this->edit_language_tab->
is_render =
false;
410 auto& edit_language_btn = flex_row.make_widget<
UI::Image>(0, 0, 32, 32,
"gfx/money.png");
415 this->edit_language_tab->
is_render =
true;
416 this->edit_terrain_tab->
is_render =
false;
418 edit_language_btn.set_tooltip(
translate(
"Edit primary language and religion"));
420 this->edit_terrain_tab = &this->make_widget<ProvinceEditTerrainTab>(gs, 0, 32, province);
421 this->edit_terrain_tab->
is_render =
false;
422 auto& edit_terrain_btn = flex_row.make_widget<
UI::Image>(0, 0, 32, 32,
"gfx/money.png");
427 this->edit_language_tab->
is_render =
false;
428 this->edit_terrain_tab->
is_render =
true;
430 edit_terrain_btn.set_tooltip(
translate(
"Edit terrain"));
432 auto& density_sld = this->make_widget<UI::Slider>(0, 32, 128, 24, 0.1f, 2.f);
433 density_sld.set_value(0.f);
434 density_sld.set_on_click([
this](
UI::Widget& w) {
437 const auto den = o.get_value();
438 for(
auto& pop :
const_cast<Province&
>(this->province).pops)
440 this->gs.
map->update_mapmode();
441 this->gs.
map->map_render->request_update_visibility();
444 density_sld.set_tooltip(
translate(
"Density slider"));
446 auto& rename_inp = this->make_widget<UI::Input>(128, 32, 128, 24);
447 rename_inp.set_buffer(province.
name);
448 auto& xchg_name_btn = this->make_widget<UI::Button>(128 + 128, 32, 32, 32);
449 xchg_name_btn.set_on_click([
this, &rename_inp](
UI::Widget&) {
451 this->gs.
map->create_labels();
454 xchg_name_btn.set_tooltip(
"Rename province");
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::atomic< bool > update_tick
std::unique_ptr< Map > map
std::shared_ptr< Eng3D::Texture > get_nation_flag(const Nation &nation)
static UI::Table< uint32_t > * new_table(GameState &gs, int _x, int _y, int _w, int _h, std::vector< ProvinceId > provinces, UI::Widget *parent)
ProvincePopulationTab(GameState &gs, int x, int y, Province &province, UI::Widget *_parent)
ProvinceView(GameState &gs, Province &province)
A single province, which is used to simulate economy in a "bulk-tiles" way instead of doing economica...
std::vector< float > religions
Percentage of each religion prescence on the pops, from 0 to 1.
std::array< Pop, 7 > pops
std::vector< NationId > nuclei
std::vector< float > languages
Percentage of each languages from 0 to 1.
TerrainTypeId terrain_type_id
A version of the Image widget that keeps aspect ratio of the image (useful for flags)
Generalized chart data, used mostly by chart widgets, however it's not specific to any widget.
Image widget, can display pictures or effects on the screen.
void set_data(std::vector< ChartData > data)
void set_close_btn_function(std::function< void(Widget &)> on_click)
T::Id get_id(const T &obj) const
Get the id of an object, this is a template for all types except for tiles and locally-stored types (...
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.
Primitive color type used through the engine.
constexpr static Color bgr32(uint32_t abgr)
A reference to a string on the global string pool.
constexpr Id get_id() const
ProvinceBuildingTab(GameState &gs, int x, int y, Province &province, UI::Widget *_parent)
ProvinceEconomyTab(GameState &gs, int x, int y, Province &province, UI::Widget *_parent)
ProvinceEditLanguageTab(GameState &gs, int x, int y, Province &province, UI::Widget *_parent)
ProvinceEditTerrainTab(GameState &gs, int x, int y, Province &province, UI::Widget *_parent)