Project Alice
Loading...
Searching...
No Matches
gui_nation_picker.hpp
Go to the documentation of this file.
1#pragma once
2
4#include "gui_chat_window.hpp"
5#include "serialization.hpp"
6
7namespace ui {
8
9class nation_picker_poptypes_chart : public piechart<dcon::pop_type_id> {
10protected:
11 void on_update(sys::state& state) noexcept override {
12 distribution.clear();
13 auto n = retrieve<dcon::nation_id>(state, parent);
14 for(auto pt : state.world.in_pop_type) {
15 auto amount = state.world.nation_get_demographics(n, demographics::to_key(state, pt));
16 distribution.emplace_back(pt.id, amount);
17 }
19 }
20};
21
22class nation_picker_cultures_chart : public piechart<dcon::culture_id> {
23protected:
24 void on_update(sys::state& state) noexcept override {
25 distribution.clear();
26 auto n = retrieve<dcon::nation_id>(state, parent);
27 for(auto c : state.world.in_culture) {
28 auto amount = state.world.nation_get_demographics(n, demographics::to_key(state, c));
29 distribution.emplace_back(c.id, amount);
30 }
32 }
33};
34
35class nation_picker_ideologies_chart : public piechart<dcon::ideology_id> {
36protected:
37 void on_update(sys::state& state) noexcept override {
38 distribution.clear();
39 auto n = retrieve<dcon::nation_id>(state, parent);
40 for(auto c : state.world.in_ideology) {
41 auto amount = state.world.nation_get_demographics(n, demographics::to_key(state, c));
42 distribution.emplace_back(c.id, amount);
43 }
45 }
46};
47
49 int16_t piechart_offset = 0;
50 element_base* overlay1 = nullptr;
51 element_base* overlay2 = nullptr;
52public:
53 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
54 if(name == "player_shield") {
55 return make_element_by_type<flag_button>(state, id);
56 } else if(name == "flag_overlay") {
57 return make_element_by_type<nation_flag_frame>(state, id);
58 } else if(name == "selected_nation_totalrank") {
59 return make_element_by_type<nation_rank_text>(state, id);
60 } else if(name == "selected_nation_label") {
61 return make_element_by_type<generic_name_text<dcon::nation_id>>(state, id);
62 } else if(name == "selected_countrystatus") {
63 return make_element_by_type<nation_status_text>(state, id);
64 } else if(name == "selected_fog") {
65 return make_element_by_type<nation_government_type_text>(state, id);
66 } else if(name == "selected_prestige_rank") {
67 return make_element_by_type<nation_prestige_rank_text>(state, id);
68 } else if(name == "selected_industry_rank") {
69 return make_element_by_type<nation_industry_rank_text>(state, id);
70 } else if(name == "selected_military_rank") {
71 return make_element_by_type<nation_military_rank_text>(state, id);
72 } else if(name == "selected_population_amount") {
73 return make_element_by_type<nation_population_text>(state, id);
74 } else if(name == "selected_population_chart") {
75 // at left
76 auto aptr = make_element_by_type<nation_picker_cultures_chart>(state, id);
77 if(piechart_offset == 0)
78 piechart_offset = aptr->base_data.size.x + 4;
79 aptr->base_data.position.x -= piechart_offset;
80 add_child_to_front(std::move(aptr));
81 // at middle
82 auto bptr = make_element_by_type<nation_picker_ideologies_chart>(state, id);
83 add_child_to_front(std::move(bptr));
84 // at right
85 auto cptr = make_element_by_type<nation_picker_poptypes_chart>(state, id);
86 cptr->base_data.position.x += piechart_offset;
87 // bring overlays on top
88 if(overlay1)
89 move_child_to_front(overlay1);
90 if(overlay2)
91 move_child_to_front(overlay2);
92 return cptr;
93 } else if(name == "selected_population_chart_overlay") {
94 // at left
95 auto aptr = make_element_by_type<image_element_base>(state, id);
96 if(piechart_offset == 0)
97 piechart_offset = aptr->base_data.size.x + 4;
98 aptr->base_data.position.x -= piechart_offset;
99 overlay1 = aptr.get();
100 add_child_to_front(std::move(aptr));
101 // at middle
102 auto bptr = make_element_by_type<image_element_base>(state, id);
103 overlay2 = bptr.get();
104 add_child_to_front(std::move(bptr));
105 // at right
106 auto cptr = make_element_by_type<image_element_base>(state, id);
107 cptr->base_data.position.x += piechart_offset;
108 return cptr;
109 } else if(name == "wars_overlappingbox") {
110 auto ptr = make_element_by_type<overlapping_enemy_flags>(state, id);
111 ptr->base_data.position.y -= 8 - 1; // Nudge
112 return ptr;
113 } else if(name == "allies_overlappingbox") {
114 auto ptr = make_element_by_type<overlapping_ally_flags>(state, id);
115 ptr->base_data.position.y -= 8 - 1; // Nudge
116 return ptr;
117 } else if(name == "puppets_overlappingbox") {
118 auto ptr = make_element_by_type<overlapping_puppet_flags>(state, id);
119 ptr->base_data.position.y -= 8 - 1; // Nudge
120 ptr->base_data.position.x += 20;
121 return ptr;
122 } else if(name == "puppets_label") {
123 auto ptr = make_element_by_type<nation_puppet_list_label>(state, id);
124 return ptr;
125 }
126
127 return nullptr;
128 }
129};
130
131
132struct save_item {
136 dcon::national_identity_id save_flag;
137 dcon::government_type_id as_gov;
138 bool is_new_game = false;
139 std::string name = "fe_new_game";
140
141 bool is_bookmark() const {
142 return file_name.starts_with(NATIVE("bookmark_"));
143 }
144
145 bool operator==(save_item const& o) const {
147 }
148 bool operator!=(save_item const& o) const {
149 return !(*this == o);
150 }
151};
152
154public:
155 void on_create(sys::state& state) noexcept override {
158 }
159
160 void button_action(sys::state& state) noexcept override {
161 save_item* i = retrieve< save_item*>(state, parent);
162 if(!i->is_new_game && i->file_name == state.loaded_save_file)
163 return;
164
165 window::change_cursor(state, window::cursor_type::busy); //show busy cursor so player doesn't question
166 if(state.ui_state.request_window)
167 static_cast<ui::diplomacy_request_window*>(state.ui_state.request_window)->messages.clear();
168 if(state.ui_state.msg_window)
169 static_cast<ui::message_window*>(state.ui_state.msg_window)->messages.clear();
170 if(state.ui_state.request_topbar_listbox)
171 static_cast<ui::diplomatic_message_topbar_listbox*>(state.ui_state.request_topbar_listbox)->messages.clear();
172 if(state.ui_state.msg_log_window)
173 static_cast<ui::message_log_window*>(state.ui_state.msg_log_window)->messages.clear();
174 for(const auto& win : land_combat_end_popup::land_reports_pool)
175 win->set_visible(state, false);
176 for(const auto& win : naval_combat_end_popup::naval_reports_pool)
177 win->set_visible(state, false);
179
180 state.network_state.save_slock.store(true, std::memory_order::release);
181 std::vector<dcon::nation_id> players;
182 for(const auto n : state.world.in_nation)
183 if(state.world.nation_get_is_player_controlled(n))
184 players.push_back(n);
185 dcon::nation_id old_local_player_nation = state.local_player_nation;
186 state.preload();
187 bool loaded = false;
188 if(i->is_new_game) {
189 if(!sys::try_read_scenario_as_save_file(state, state.loaded_scenario_file)) {
190 auto msg = std::string("Scenario file ") + simple_fs::native_to_utf8(state.loaded_scenario_file) + " could not be loaded.";
191 ui::popup_error_window(state, "Scenario Error", msg);
192 } else {
193 loaded = true;
194 }
195 } else {
197 auto msg = std::string("Save file ") + simple_fs::native_to_utf8(i->file_name) + " could not be loaded.";
198 ui::popup_error_window(state, "Save Error", msg);
199 state.save_list_updated.store(true, std::memory_order::release); //update savefile list
200 //try loading save from scenario so we atleast have something to work on
201 if(!sys::try_read_scenario_as_save_file(state, state.loaded_scenario_file)) {
202 auto msg2 = std::string("Scenario file ") + simple_fs::native_to_utf8(state.loaded_scenario_file) + " could not be loaded.";
203 ui::popup_error_window(state, "Scenario Error", msg2);
204 } else {
205 loaded = true;
206 }
207 } else {
208 loaded = true;
209 }
210 }
211 if(loaded) {
212 /* Updating this flag lets the network state know that we NEED to send the
213 savefile data, otherwise it is safe to assume the client has its own data
214 friendly reminder that, scenario loading and reloading ends up with different outcomes */
215 state.network_state.is_new_game = false;
216 if(state.network_mode == sys::network_mode_type::host) {
217 /* Save the buffer before we fill the unsaved data */
218 state.local_player_nation = dcon::nation_id{ };
220 state.fill_unsaved_data();
221 for(const auto n : players)
222 state.world.nation_set_is_player_controlled(n, true);
223 state.local_player_nation = old_local_player_nation;
224 assert(state.world.nation_get_is_player_controlled(state.local_player_nation));
225 /* Now send the saved buffer before filling the unsaved data to the clients
226 henceforth. */
228 memset(&c, 0, sizeof(command::payload));
230 c.source = state.local_player_nation;
231 c.data.notify_save_loaded.target = dcon::nation_id{};
232 network::broadcast_save_to_clients(state, c, state.network_state.current_save_buffer.get(), state.network_state.current_save_length, state.network_state.current_save_checksum);
233 } else {
234 state.fill_unsaved_data();
235 }
236 }
237 /* Savefiles might load with new railroads, so for responsiveness we
238 update whenever one is loaded. */
239 state.map_state.set_selected_province(dcon::province_id{});
240 state.map_state.unhandled_province_selection = true;
241 state.railroad_built.store(true, std::memory_order::release);
242 state.network_state.save_slock.store(false, std::memory_order::release);
243 state.game_state_updated.store(true, std::memory_order_release);
244
246 }
247 void on_update(sys::state& state) noexcept override {
248 save_item* i = retrieve< save_item*>(state, parent);
249 frame = i->file_name == state.loaded_save_file ? 1 : 0;
250 }
251};
252
254protected:
256 bool visible = false;
257public:
258 void button_action(sys::state& state) noexcept override { }
259
260 void on_update(sys::state& state) noexcept override {
261 save_item* i = retrieve< save_item*>(state, parent);
262 auto tag = i->save_flag;
263 auto gov = i->as_gov;
264 visible = !i->is_new_game && !i->is_bookmark();
265
266 if(!visible)
267 return;
268
269 if(!bool(tag))
270 tag = state.national_definitions.rebel_id;
271
273 if(gov) {
274 auto id = state.world.national_identity_get_government_flag_type(tag, gov);
275 if(id != 0)
276 ft = culture::flag_type(id - 1);
277 else
278 ft = culture::flag_type(state.world.government_type_get_flag(gov));
279 }
281 }
282
283 void render(sys::state& state, int32_t x, int32_t y) noexcept override {
284 if(!visible)
285 return;
286
287 dcon::gfx_object_id gid;
292 }
293 if(gid && flag_texture_handle > 0) {
294 auto& gfx_def = state.ui_defs.gfx[gid];
295 if(gfx_def.type_dependent) {
296 auto mask_handle = ogl::get_texture_handle(state, dcon::texture_id(gfx_def.type_dependent - 1), true);
297 auto& mask_tex = state.open_gl.asset_textures[dcon::texture_id(gfx_def.type_dependent - 1)];
299 float(x) + float(base_data.size.x - mask_tex.size_x) * 0.5f,
300 float(y) + float(base_data.size.y - mask_tex.size_y) * 0.5f,
301 float(mask_tex.size_x),
302 float(mask_tex.size_y),
303 flag_texture_handle, mask_handle, base_data.get_rotation(), gfx_def.is_vertically_flipped(),
304 false);
305 } else {
307 float(x), float(y), float(base_data.size.x), float(base_data.size.y), flag_texture_handle, base_data.get_rotation(),
308 gfx_def.is_vertically_flipped(),
309 false);
310 }
311 }
313 }
314};
315
317public:
318 void on_update(sys::state& state) noexcept override {
319 save_item* i = retrieve< save_item*>(state, parent);
320 if(i->is_new_game) {
322 } else if(i->is_bookmark()) {
324 } else {
325 auto name = text::get_name(state, state.world.national_identity_get_nation_from_identity_holder(i->save_flag));
326 if(auto gov_name = state.world.national_identity_get_government_name(i->save_flag, i->as_gov); state.key_is_localized(gov_name)) {
327 name = gov_name;
328 }
330 }
331 }
332};
333
335public:
336 void on_update(sys::state& state) noexcept override {
337 save_item* i = retrieve< save_item*>(state, parent);
339 }
340};
341
342class save_game_item : public listbox_row_element_base<std::shared_ptr<save_item>> {
343public:
344 void on_create(sys::state& state) noexcept override {
346 base_data.position.x += 9; // Nudge
347 base_data.position.y += 7; // Nudge
348 }
349
350 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
351 if(name == "save_game") {
352 return make_element_by_type<select_save_game>(state, id);
353 } else if(name == "shield") {
354 return make_element_by_type<save_flag>(state, id);
355 } else if(name == "title") {
356 return make_element_by_type<save_name>(state, id);
357 } else if(name == "date") {
358 return make_element_by_type<save_date>(state, id);
359 }
360 return nullptr;
361 }
362
363 message_result get(sys::state& state, Cyto::Any& payload) noexcept override {
364 if(payload.holds_type<save_item*>()) {
365 payload.emplace<save_item*>(content.get());
367 }
369 }
370};
371
372class saves_listbox : public listbox_element_base<save_game_item, std::shared_ptr<save_item>> {
373protected:
374 std::string_view get_row_element_name() override {
375 return "alice_savegameentry";
376 }
377
379 row_contents.clear();
380 row_contents.push_back(std::make_shared<save_item>(save_item{ NATIVE(""), 0, sys::date(0), dcon::national_identity_id{ }, dcon::government_type_id{ }, true, std::string("") }));
381
383 for(auto& f : simple_fs::list_files(sdir, NATIVE(".bin"))) {
384 auto of = simple_fs::open_file(f);
385 if(of) {
386 auto content = simple_fs::view_contents(*of);
388 if(content.file_size > sys::sizeof_save_header(h))
389 sys::read_save_header(reinterpret_cast<uint8_t const*>(content.data), h);
390 if(h.checksum.is_equal(state.scenario_checksum)) {
391 row_contents.push_back(std::make_shared<save_item>(save_item{ simple_fs::get_file_name(f), h.timestamp, h.d, h.tag, h.cgov, false, std::string(h.save_name) }));
392 }
393 }
394 }
395
396 std::sort(row_contents.begin() + 1, row_contents.end(), [](std::shared_ptr<save_item> const& a, std::shared_ptr<save_item> const& b) {
397 if(a->is_bookmark() != b->is_bookmark())
398 return a->is_bookmark();
399 return a->timestamp > b->timestamp;
400 });
401
402 update(state);
403 }
404
405public:
406 void on_create(sys::state& state) noexcept override {
407 base_data.size.x -= 20; //nudge
409 base_data.position.y = 0;
412 }
413
414 void on_update(sys::state& state) noexcept override {
415 if(state.save_list_updated.load(std::memory_order::acquire) == true) {
416 state.save_list_updated.store(false, std::memory_order::release); // acknowledge update
418 }
419 }
420};
421
423public:
424 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
425 if(name == "save_games_list") {
426 return make_element_by_type<saves_listbox>(state, id);
427 }
428 return nullptr;
429 }
430};
431
433public:
434 void on_update(sys::state& state) noexcept override {
435 auto n = retrieve<dcon::nation_id>(state, parent);
436 if(state.network_mode == sys::network_mode_type::single_player) {
437 disabled = n == state.local_player_nation;
438 } else {
439 // Prevent (via UI) the player from selecting a nation already selected by someone
441 }
442 }
443
444 void button_action(sys::state& state) noexcept override {
445 auto n = retrieve<dcon::nation_id>(state, parent);
446 if(state.network_mode == sys::network_mode_type::single_player) {
447 state.local_player_nation = n;
448 state.world.nation_set_is_player_controlled(n, true);
449 state.ui_state.nation_picker->impl_on_update(state);
450 } else {
451 command::notify_player_picks_nation(state, state.local_player_nation, n);
452 }
453 }
454};
455
456class playable_nations_item : public listbox_row_element_base<dcon::nation_id> {
457public:
458 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
459 if(name == "playable_countries_button") {
460 auto ptr = make_element_by_type<pick_nation_button>(state, id);
461 ptr->base_data.position.x += 9; // Nudge
462 ptr->base_data.position.y = 0; // Nudge
463 return ptr;
464 } else if(name == "playable_countries_flag") {
465 auto ptr = make_element_by_type<flag_button>(state, id);
466 ptr->base_data.position.x += 9; // Nudge
467 ptr->base_data.position.y = 1; // Nudge
468 return ptr;
469 } else if(name == "country_name") {
470 auto ptr = make_element_by_type<generic_name_text<dcon::nation_id>>(state, id);
471 ptr->base_data.position.x += 9; // Nudge
472 ptr->base_data.position.y = 5; // Nudge
473 return ptr;
474 } else if(name == "prestige_rank") {
475 auto ptr = make_element_by_type<nation_prestige_rank_text>(state, id);
476 ptr->base_data.position.x += 9; // Nudge
477 ptr->base_data.position.y = 5; // Nudge
478 return ptr;
479 } else if(name == "industry_rank") {
480 auto ptr = make_element_by_type<nation_industry_rank_text>(state, id);
481 ptr->base_data.position.x += 9; // Nudge
482 ptr->base_data.position.y = 5; // Nudge
483 return ptr;
484 } else if(name == "military_rank") {
485 auto ptr = make_element_by_type<nation_military_rank_text>(state, id);
486 ptr->base_data.position.x += 9; // Nudge
487 ptr->base_data.position.y = 5; // Nudge
488 return ptr;
489 }
490 return nullptr;
491 }
492};
493
494enum class picker_sort {
496};
497
498class playable_nations_lb : public listbox_element_base<playable_nations_item, dcon::nation_id> {
499protected:
500 std::string_view get_row_element_name() override {
501 return "playable_countries_list_item";
502 }
503
504public:
505 void on_update(sys::state& state) noexcept override {
506 row_contents.clear();
507 for(auto n : state.world.in_nation) {
508 if(n.get_owned_province_count() > 0)
509 row_contents.push_back(n);
510 }
511 auto s = retrieve<picker_sort>(state, parent);
512 switch(s) {
514 std::sort(row_contents.begin(), row_contents.end(), [&](dcon::nation_id a, dcon::nation_id b) {
515 return text::get_name_as_string(state, fatten(state.world, a)) < text::get_name_as_string(state, fatten(state.world, b));
516 });
517 break;
519 std::sort(row_contents.begin(), row_contents.end(), [&](dcon::nation_id a, dcon::nation_id b) {
520 return state.world.nation_get_military_rank(a) < state.world.nation_get_military_rank(b);
521 });
522 break;
524 std::sort(row_contents.begin(), row_contents.end(), [&](dcon::nation_id a, dcon::nation_id b) {
525 return state.world.nation_get_industrial_rank(a) < state.world.nation_get_industrial_rank(b);
526 });
527 break;
529 std::sort(row_contents.begin(), row_contents.end(), [&](dcon::nation_id a, dcon::nation_id b) {
530 return state.world.nation_get_prestige_rank(a) < state.world.nation_get_prestige_rank(b);
531 });
532 break;
533 default:
534 break;
535 }
536 update(state);
537 }
538};
539
540template< picker_sort stype>
542 void button_action(sys::state& state) noexcept override {
544 }
545};
546
548 picker_sort sort_order = picker_sort::name;
549 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
550 if(name == "lobby_sort_countryname") {
551 auto ptr = make_element_by_type<playable_nations_sort_button<picker_sort::name>>(state, id);
552 ptr->base_data.position.y += 1; // Nudge
553 return ptr;
554 } else if(name == "lobby_sort_prestige") {
555 return make_element_by_type<playable_nations_sort_button<picker_sort::p_rank>>(state, id);
556 } else if(name == "lobby_sort_industry") {
557 return make_element_by_type<playable_nations_sort_button<picker_sort::indust_rank>>(state, id);
558 } else if(name == "lobby_sort_military") {
559 return make_element_by_type<playable_nations_sort_button<picker_sort::mil_rank>>(state, id);
560 } else if(name == "playable_countries_list") {
561 return make_element_by_type<playable_nations_lb>(state, id);
562 }
563 return nullptr;
564 }
565
566 message_result get(sys::state& state, Cyto::Any& payload) noexcept override {
567 if(payload.holds_type<picker_sort>()) {
568 payload.emplace<picker_sort>(sort_order);
571 auto v = any_cast<element_selection_wrapper<picker_sort>>(payload);
572 sort_order = v.data;
575 }
576 return window_element_base::get(state, payload);
577 }
578};
579
581public:
582 void on_update(sys::state& state) noexcept override {
584 auto myd = state.current_date.to_ymd(state.start_date);
587 }
588};
589
590
592public:
593 void button_action(sys::state& state) noexcept override {
594 if(state.network_mode == sys::network_mode_type::client) {
595 //clients cant start the game, only tell that they're "ready"
596 } else {
597 if(auto cap = state.world.nation_get_capital(state.local_player_nation); cap) {
598 if(state.map_state.get_zoom() < map::zoom_very_close)
599 state.map_state.zoom = map::zoom_very_close;
600 state.map_state.center_map_on_province(state, cap);
601 }
602 command::notify_start_game(state, state.local_player_nation);
603 }
604 }
605
606 void on_update(sys::state& state) noexcept override {
607 disabled = !bool(state.local_player_nation);
608 if(state.network_mode == sys::network_mode_type::client) {
609 if(state.network_state.save_stream) { //in the middle of a save stream
610 disabled = true;
611 } else {
612 if(!state.session_host_checksum.is_equal(state.get_save_checksum())) { //can't start if checksum doesn't match
613 disabled = true;
614 }
615 }
616 }
617 }
618
619 void render(sys::state& state, int32_t x, int32_t y) noexcept override {
620 if(state.network_mode == sys::network_mode_type::host) {
621 bool old_disabled = disabled;
622 for(auto const& client : state.network_state.clients) {
623 if(client.is_active()) {
624 disabled = disabled || !client.send_buffer.empty();
625 }
626 }
628 disabled = old_disabled;
629 } else if(state.network_mode == sys::network_mode_type::client) {
630 if(state.network_state.save_stream) {
631 set_button_text(state, text::format_percentage(float(state.network_state.recv_count) / float(state.network_state.save_data.size())));
632 } else {
634 }
636 } else {
638 }
639 }
640
643 }
644
645 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override {
646 if(state.network_mode == sys::network_mode_type::client) {
647 auto box = text::open_layout_box(contents, 0);
648 if(state.network_state.save_stream) {
649 text::localised_format_box(state, contents, box, std::string_view("alice_play_save_stream"));
650 } else if(!state.session_host_checksum.is_equal(state.get_save_checksum())) {
651 text::localised_format_box(state, contents, box, std::string_view("alice_play_checksum_host"));
652 }
653 for(auto const& client : state.network_state.clients) {
654 if(client.is_active()) {
655 if(!client.send_buffer.empty()) {
658 text::localised_format_box(state, contents, box, std::string_view("alice_play_pending_client"), sub);
659 }
660 }
661 }
662 text::close_layout_box(contents, box);
663 }
664 }
665};
666
668public:
669 void button_action(sys::state& state) noexcept override {
671 }
672};
673
675public:
676 void on_update(sys::state& state) noexcept override {
677 auto n = retrieve<dcon::nation_id>(state, parent);
678 if(state.network_mode == sys::network_mode_type::host) {
679 // on render
680 } else {
682 }
683 }
684 void render(sys::state& state, int32_t x, int32_t y) noexcept override {
685 auto n = retrieve<dcon::nation_id>(state, parent);
686 if(state.network_mode == sys::network_mode_type::host) {
687 set_text(state, text::produce_simple_string(state, "ready")); // default
688 if(state.network_state.is_new_game == false) {
689 for(auto const& c : state.network_state.clients) {
690 if(c.is_active() && c.playing_as == n) {
691 auto completed = c.total_sent_bytes - c.save_stream_offset;
692 auto total = c.save_stream_size;
693 if(total > 0.f) {
694 float progress = float(completed) / float(total);
695 if(progress < 1.f) {
699 }
700 }
701 break;
702 }
703 }
704 }
705 }
707 }
708};
709
711public:
712 void on_update(sys::state& state) noexcept override {
713 int32_t count = 0;
714 if(state.network_mode == sys::network_mode_type::single_player) {
715 count = 1;
716 } else {
717 state.world.for_each_nation([&](dcon::nation_id n) {
718 if(state.world.nation_get_is_player_controlled(n))
719 count++;
720 });
721 }
722
725 set_text(state, text::resolve_string_substitution(state, "fe_num_players", sub));
726 }
727};
728
730public:
731 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
732 if(name == "player_shield") {
733 auto ptr = make_element_by_type<flag_button>(state, id);
734 ptr->base_data.position.x += 10; // Nudge
735 ptr->base_data.position.y += 7; // Nudge
736 return ptr;
737 } else if(name == "name") {
738 auto ptr = make_element_by_type<player_name_text>(state, id);
739 ptr->base_data.position.x += 10; // Nudge
740 ptr->base_data.position.y += 7; // Nudge
741 return ptr;
742 } else if(name == "save_progress") {
743 auto ptr = make_element_by_type<multiplayer_status_text>(state, id);
744 ptr->base_data.position.x += 10; // Nudge
745 ptr->base_data.position.y += 7; // Nudge
746 return ptr;
747 } else if(name == "button_kick") {
748 auto ptr = make_element_by_type<player_kick_button>(state, id);
749 ptr->base_data.position.x += 10; // Nudge
750 ptr->base_data.position.y += 7; // Nudge
751 return ptr;
752 } else if(name == "button_ban") {
753 auto ptr = make_element_by_type<player_ban_button>(state, id);
754 ptr->base_data.position.x += 10; // Nudge
755 ptr->base_data.position.y += 7; // Nudge
756 return ptr;
757 } else if(name == "frontend_player_entry") {
758 auto ptr = make_element_by_type<image_element_base>(state, id);
759 ptr->base_data.position.x += 10; // Nudge
760 ptr->base_data.position.y += 7; // Nudge
761 return ptr;
762 } else {
763 return nullptr;
764 }
765 }
766};
767
768class nation_picker_multiplayer_listbox : public listbox_element_base<nation_picker_multiplayer_entry, dcon::nation_id> {
769protected:
770 std::string_view get_row_element_name() override {
771 return "multiplayer_entry_server";
772 }
773public:
774 void on_update(sys::state& state) noexcept override {
775 row_contents.clear();
776 if(state.network_mode == sys::network_mode_type::single_player) {
777 row_contents.push_back(state.local_player_nation);
778 } else {
779 state.world.for_each_nation([&](dcon::nation_id n) {
780 if(state.world.nation_get_is_player_controlled(n))
781 row_contents.push_back(n);
782 });
783 }
784 update(state);
785 }
786};
787
789public:
790 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
791 if(name == "multiplayer_list") {
792 return make_element_by_type<nation_picker_multiplayer_listbox>(state, id);
793 } else if(name == "checksum") {
794 return make_element_by_type<simple_text_element_base>(state, id);
795 } else if(name == "num_players") {
796 return make_element_by_type<number_of_players_text>(state, id);
797 }
798 return nullptr;
799 }
800};
801
803 void populate_layout(sys::state& state, text::endless_layout& contents) noexcept {
804 text::add_line(state, contents, "alice_readme");
806 text::add_line(state, contents, "gc_desc");
807 }
808public:
809 void on_reset_text(sys::state& state) noexcept override {
811 text::layout_parameters{ 0, 0, static_cast<int16_t>(base_data.size.x), static_cast<int16_t>(base_data.size.y),
812 base_data.data.text.font_handle, 0, text::alignment::left,
813 text::is_black_from_font_id(base_data.data.text.font_handle) ? text::text_color::black : text::text_color::white,
814 false });
815 populate_layout(state, container);
817 }
818 void on_create(sys::state& state) noexcept override {
821 }
822};
823
825public:
826 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
827 if(name == "frontend_chat_bg") {
828 return make_element_by_type<image_element_base>(state, id);
829 } else if(name == "lobby_chat_edit") {
830 return make_element_by_type<invisible_element>(state, id);
831 } else if(name == "newgame_tab") {
832 return make_element_by_type<invisible_element>(state, id);
833 } else if(name == "savedgame_tab") {
834 return make_element_by_type<invisible_element>(state, id);
835 } else if(name == "year_label") {
836 return make_element_by_type<date_label>(state, id);
837 } else if(name == "multiplayer") {
838 return make_element_by_type<nation_picker_multiplayer_window>(state, id);
839 } else if(name == "singleplayer") {
840 return make_element_by_type<nation_details_window>(state, id);
841 } else if(name == "save_games") {
842 return make_element_by_type<saves_window>(state, id);
843 } else if(name == "bookmarks") {
844 return make_element_by_type<invisible_element>(state, id);
845 } else if(name == "playable_countries_window") {
846 return make_element_by_type<playable_nations_window>(state, id);
847 } else if(name == "back_button") {
848 return make_element_by_type<quit_game_button>(state, id);
849 } else if(name == "play_button") {
850 return make_element_by_type<start_game_button>(state, id);
851 } else if(name == "chatlog") {
852 auto ptr = make_element_by_type<nation_alice_readme_text>(state, state.ui_state.defs_by_name.find(state.lookup_key("alice_readme_text"))->second.definition);
853 add_child_to_front(std::move(ptr));
854 return make_element_by_type<invisible_element>(state, id);
855 }
856 return nullptr;
857 }
858
859 message_result get(sys::state& state, Cyto::Any& payload) noexcept override {
860 if(payload.holds_type<dcon::nation_id>()) {
861 payload.emplace<dcon::nation_id>(state.local_player_nation);
863 }
864 return window_element_base::get(state, payload);
865 }
866};
867
868}
ANY_ALWAYS_INLINE bool holds_type() const noexcept
Definition: cyto_any.hpp:429
T & emplace(Args &&... args)
Definition: cyto_any.hpp:373
void set_button_text(sys::state &state, std::string const &new_text)
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void on_create(sys::state &state) noexcept override
void add_child_to_front(std::unique_ptr< element_base > child) noexcept final
void move_child_to_front(element_base *child) noexcept final
void impl_on_update(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
element_base * parent
virtual message_result get(sys::state &state, Cyto::Any &payload) noexcept
element_data base_data
void set_visible(sys::state &state, bool vis)
void render(sys::state &state, int32_t x, int32_t y) noexcept override
static std::vector< std::unique_ptr< ui::land_combat_end_popup > > land_reports_pool
void on_update(sys::state &state) noexcept override
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void on_reset_text(sys::state &state) noexcept override
void on_create(sys::state &state) noexcept override
std::unique_ptr< element_base > make_child(sys::state &state, std::string_view name, dcon::gui_def_id id) noexcept override
message_result get(sys::state &state, Cyto::Any &payload) noexcept override
std::unique_ptr< element_base > make_child(sys::state &state, std::string_view name, dcon::gui_def_id id) noexcept override
void on_update(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
std::unique_ptr< element_base > make_child(sys::state &state, std::string_view name, dcon::gui_def_id id) noexcept override
std::string_view get_row_element_name() override
void on_update(sys::state &state) noexcept override
std::unique_ptr< element_base > make_child(sys::state &state, std::string_view name, dcon::gui_def_id id) noexcept override
void on_update(sys::state &state) noexcept override
static std::vector< std::unique_ptr< ui::naval_combat_end_popup > > naval_reports_pool
void on_update(sys::state &state) noexcept override
void button_action(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
std::unique_ptr< element_base > make_child(sys::state &state, std::string_view name, dcon::gui_def_id id) noexcept override
void on_update(sys::state &state) noexcept override
std::string_view get_row_element_name() override
void button_action(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void button_action(sys::state &state) noexcept override
message_result get(sys::state &state, Cyto::Any &payload) noexcept override
std::unique_ptr< element_base > make_child(sys::state &state, std::string_view name, dcon::gui_def_id id) noexcept override
void on_create(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
std::string_view get_row_element_name() override
void update_save_list(sys::state &state) noexcept
void on_create(sys::state &state) noexcept override
std::unique_ptr< element_base > make_child(sys::state &state, std::string_view name, dcon::gui_def_id id) noexcept override
void calibrate_scrollbar(sys::state &state) noexcept
void on_create(sys::state &state) noexcept override
multiline_text_element_base * delegate
void on_create(sys::state &state) noexcept override
void button_action(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void set_text(sys::state &state, std::string const &new_text)
void button_action(sys::state &state) noexcept override
void update_tooltip(sys::state &state, int32_t x, int32_t y, text::columnar_layout &contents) noexcept override
tooltip_behavior has_tooltip(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
void render(sys::state &state, int32_t x, int32_t y) noexcept override
#define assert(condition)
Definition: debug.h:74
bool can_notify_player_picks_nation(sys::state &state, dcon::nation_id source, dcon::nation_id target)
Definition: commands.cpp:4630
dcon::demographics_key to_key(sys::state const &state, dcon::pop_type_id v)
constexpr float zoom_very_close
Definition: constants.hpp:606
void broadcast_save_to_clients(sys::state &state, command::payload &c, uint8_t const *buffer, uint32_t length, sys::checksum_key const &k)
Definition: network.cpp:775
void write_network_save(sys::state &state)
Definition: network.cpp:759
void render_masked_rect(sys::state const &state, color_modification enabled, float x, float y, float width, float height, GLuint texture_handle, GLuint mask_texture_handle, ui::rotation r, bool flipped, bool rtl)
void render_textured_rect(sys::state const &state, color_modification enabled, float x, float y, float width, float height, GLuint texture_handle, ui::rotation r, bool flipped, bool rtl)
GLuint get_texture_handle(sys::state &state, dcon::texture_id id, bool keep_data)
Definition: texture.cpp:577
GLuint get_flag_handle(sys::state &state, dcon::national_identity_id nat_id, culture::flag_type type)
Definition: texture.cpp:544
std::vector< unopened_file > list_files(directory const &dir, native_char const *extension)
directory get_or_create_save_game_directory()
std::optional< file > open_file(directory const &dir, native_string_view file_name)
std::string native_to_utf8(native_string_view data_in)
file_contents view_contents(file const &f)
native_string get_file_name(unopened_file const &f)
bool try_read_scenario_as_save_file(sys::state &state, native_string_view name)
uint8_t const * read_save_header(uint8_t const *ptr_in, save_header &header_out)
size_t sizeof_save_header(save_header const &header_in)
bool try_read_save_file(sys::state &state, native_string_view name)
std::string resolve_string_substitution(sys::state &state, dcon::text_key source_text, substitution_map const &mp)
Definition: text.cpp:2113
layout_box open_layout_box(layout_base &dest, int32_t indent)
Definition: text.cpp:1799
std::string date_to_string(sys::state &state, sys::date date)
Definition: text.cpp:1082
void localised_format_box(sys::state &state, layout_base &dest, layout_box &box, std::string_view key, text::substitution_map const &sub)
Definition: text.cpp:1880
endless_layout create_endless_layout(sys::state &state, layout &dest, layout_parameters const &params)
Definition: text.cpp:1100
void add_line(sys::state &state, layout_base &dest, dcon::text_key txt, int32_t indent)
Definition: text.cpp:1899
void add_line_break_to_layout(sys::state &state, columnar_layout &dest)
Definition: text.cpp:1152
void add_to_substitution_map(substitution_map &mp, variable_type key, substitution value)
Definition: text.cpp:1068
ankerl::unordered_dense::map< uint32_t, substitution > substitution_map
Definition: text.hpp:794
std::string produce_simple_string(sys::state const &state, dcon::text_key id)
Definition: text.cpp:617
dcon::text_key get_name(sys::state &state, dcon::nation_id id)
Definition: text.cpp:880
std::string format_percentage(float num, size_t digits)
Definition: text.cpp:977
void close_layout_box(columnar_layout &dest, layout_box &box)
Definition: text.cpp:1807
void popup_error_window(sys::state &state, std::string_view title, std::string_view body)
tooltip_behavior
void send(sys::state &state, element_base *parent, T value)
@ count
Definition: gui_event.hpp:126
message_result
void clear_event_windows(sys::state &state)
Definition: gui_event.cpp:1152
ogl::color_modification get_color_modification(bool is_under_mouse, bool is_disabled, bool is_interactable)
void close_window(sys::state &game_state)
Definition: window_nix.cpp:101
void change_cursor(sys::state &state, cursor_type type)
Definition: window_nix.cpp:351
#define NATIVE(X)
std::string native_string
ulong uint64_t
uchar uint8_t
command_type type
Definition: commands.hpp:521
union command::payload::dtype data
dcon::nation_id source
Definition: commands.hpp:520
bool is_equal(const checksum_key &a) noexcept
dcon::national_identity_id tag
dcon::government_type_id cgov
checksum_key checksum
dcon::gfx_object_id button_image
element_type get_element_type() const
rotation get_rotation() const
union ui::element_data::internal_data data
dcon::gfx_object_id gfx_object
dcon::government_type_id as_gov
native_string file_name
bool operator!=(save_item const &o) const
dcon::national_identity_id save_flag
bool is_bookmark() const
bool operator==(save_item const &o) const
element_base * msg_log_window
std::unique_ptr< element_base > nation_picker
ankerl::unordered_dense::map< dcon::text_key, element_target, hash_text_key > defs_by_name
element_base * request_window
element_base * request_topbar_listbox
element_base * under_mouse
element_base * msg_window
notify_save_loaded_data notify_save_loaded
Definition: commands.hpp:510