Project Alice
Loading...
Searching...
No Matches
gui_unit_grid_box.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <functional>
5#include <unordered_map>
6#include <variant>
7#include <vector>
8#include "dcon_generated.hpp"
9#include "gui_graphics.hpp"
10#include "gui_element_base.hpp"
11#include "gui_element_types.hpp"
12#include "opengl_wrapper.hpp"
13#include "sound.hpp"
14#include "system_state.hpp"
15#include "text.hpp"
16#include "texture.hpp"
17
18namespace ui {
19
20enum class outline_color : uint8_t {
21 gray = 0, gold = 1, blue = 2, cyan = 3, red = 4
22};
23
24using unit_var = std::variant<std::monostate, dcon::army_id, dcon::navy_id>;
25
27public:
28 void on_update(sys::state& state) noexcept override {
29 frame = int32_t(retrieve<outline_color>(state, parent));
30 }
31 void button_action(sys::state& state) noexcept override {
32 auto u = retrieve< unit_var>(state, parent);
33 if(std::holds_alternative<dcon::army_id>(u)) {
34 auto a = std::get<dcon::army_id>(u);
35 // if(state.world.army_get_controller_from_army_control(a) == state.local_player_nation) {
36 state.selected_armies.clear();
37 state.selected_navies.clear();
38 state.select(a);
39 // }
40 } else if(std::holds_alternative<dcon::navy_id>(u)) {
41 auto a = std::get<dcon::navy_id>(u);
42 // if(state.world.navy_get_controller_from_navy_control(a) == state.local_player_nation) {
43 state.selected_armies.clear();
44 state.selected_navies.clear();
45 state.select(a);
46 // }
47 }
48 }
49 void button_shift_action(sys::state& state) noexcept override {
50 auto u = retrieve< unit_var>(state, parent);
51 if(std::holds_alternative<dcon::army_id>(u)) {
52 auto a = std::get<dcon::army_id>(u);
53 if(state.world.army_get_controller_from_army_control(a) == state.local_player_nation) {
54 if(!state.is_selected(a))
55 state.select(a);
56 else
57 state.deselect(a);
58 }
59 } else if(std::holds_alternative<dcon::navy_id>(u)) {
60 auto a = std::get<dcon::navy_id>(u);
61 if(state.world.navy_get_controller_from_navy_control(a) == state.local_player_nation) {
62 if(!state.is_selected(a))
63 state.select(a);
64 else
65 state.deselect(a);
66 }
67 }
68 }
69
72 }
73
74 void update_tooltip(sys::state& state, int32_t x, int32_t y, text::columnar_layout& contents) noexcept override;
75};
76
77class unit_org_bar : public progress_bar {
78public:
79 void on_update(sys::state& state) noexcept override {
80 auto u = retrieve< unit_var>(state, parent);
81 float avg = 0;
82 if(std::holds_alternative<dcon::army_id>(u)) {
83 float total = 0;
84 float count = 0;
85 auto a = std::get<dcon::army_id>(u);
86 for(auto r : state.world.army_get_army_membership(a)) {
87 total += r.get_regiment().get_org();
88 ++count;
89 }
90 if(count > 0) {
91 avg = total / count;
92 }
93 } else if(std::holds_alternative<dcon::navy_id>(u)) {
94 float total = 0;
95 float count = 0;
96 auto a = std::get<dcon::navy_id>(u);
97 for(auto r : state.world.navy_get_navy_membership(a)) {
98 total += r.get_ship().get_org();
99 ++count;
100 }
101 if(count > 0) {
102 avg = total / count;
103 }
104 }
105 progress = avg;
106 }
107};
108
109inline int32_t status_frame(sys::state& state, dcon::army_id a) {
110 auto is_understr = [&]() {
111 for(auto m : state.world.army_get_army_membership(a)) {
112 if(m.get_regiment().get_strength() < 1.0f)
113 return true;
114 }
115 return false;
116 };
117 if(state.world.army_get_black_flag(a)) {
118 return 1;
119 } else if(state.world.army_get_is_retreating(a)) {
120 return 2;
121 } else if(state.world.army_get_battle_from_army_battle_participation(a)) {
122 return 6;
123 } else if(state.world.army_get_navy_from_army_transport(a)) {
124 return 5;
125 } else if(state.world.army_get_arrival_time(a)) {
126 return 7;
128 return 3;
129 } else if(is_understr()) {
130 return 4;
131 } else {
132 return 0;
133 }
134}
135inline int32_t status_frame(sys::state& state, dcon::navy_id a) {
136 auto trange = state.world.navy_get_army_transport(a);
137
138 auto is_understr = [&]() {
139 for(auto m : state.world.navy_get_navy_membership(a)) {
140 if(m.get_ship().get_strength() < 1.0f)
141 return true;
142 }
143 return false;
144 };
145
146 auto nb_level = state.world.province_get_building_level(state.world.navy_get_location_from_navy_location(a), uint8_t(economy::province_building_type::naval_base));
147 if(state.world.navy_get_is_retreating(a)) {
148 return 2;
149 } else if(state.world.navy_get_battle_from_navy_battle_participation(a)) {
150 return 6;
152 return 3;
153 } else if(trange.begin() != trange.end()) {
154 return 5;
155 } else if(!(state.world.navy_get_arrival_time(a)) && nb_level > 0 && is_understr()) {
156 return 4;
157 } else if(state.world.navy_get_arrival_time(a)) {
158 return 7;
159 } else {
160 return 0;
161 }
162}
163
165public:
166 void on_update(sys::state& state) noexcept override {
167 auto u = retrieve< unit_var>(state, parent);
168 if(std::holds_alternative<dcon::army_id>(u)) {
169 auto a = std::get<dcon::army_id>(u);
171 } else if(std::holds_alternative<dcon::navy_id>(u)) {
172 auto a = std::get<dcon::navy_id>(u);
174 }
175 }
176};
177
179public:
180 void on_update(sys::state& state) noexcept override {
181 auto u = retrieve< unit_var>(state, parent);
183 if(std::holds_alternative<dcon::army_id>(u)) {
184 int64_t total = 0;
185 auto a = std::get<dcon::army_id>(u);
186 for(auto m : state.world.army_get_army_membership(a)) {
187 total += int64_t(floor(m.get_regiment().get_strength() * state.defines.pop_size_per_regiment));
188 }
190 } else if(std::holds_alternative<dcon::navy_id>(u)) {
191 float total = 0.0f;
192 auto a = std::get<dcon::navy_id>(u);
193 for(auto m : state.world.navy_get_navy_membership(a)) {
194 total += m.get_ship().get_strength();
195 }
197 }
198
199 }
200};
201
203public:
204 bool visible = false;
205
206 void on_update(sys::state& state) noexcept override {
207 auto u = retrieve< unit_var>(state, parent);
208
209 if(std::holds_alternative<dcon::army_id>(u)) {
210 auto a = std::get<dcon::army_id>(u);
211 auto dig_in = state.world.army_get_dig_in(a);
212 frame = dig_in;
213 visible = true;
214 } else {
215 visible = false;
216 }
217
218 }
219 void render(sys::state& state, int32_t x, int32_t y) noexcept override {
220 if(visible) {
222 }
223 }
224};
225
227public:
228 bool visible = true;
229
230 void on_update(sys::state& state) noexcept override {
231 static std::vector<int32_t> by_icon_count;
232 for(auto& i : by_icon_count)
233 i = 0;
234
235 auto u = retrieve< unit_var>(state, parent);
236
237 visible = true;
238 if(std::holds_alternative<dcon::army_id>(u)) {
239 auto a = std::get<dcon::army_id>(u);
240 if(state.world.army_get_controller_from_army_control(a) != state.local_player_nation) {
241 visible = false;
242 return;
243 }
244
245 for(auto m : state.world.army_get_army_membership(a)) {
246 auto icon = state.military_definitions.unit_base_definitions[m.get_regiment().get_type()].icon - 1;
247 if(uint32_t(icon) >= by_icon_count.size()) {
248 by_icon_count.resize(icon + 1, 0);
249 }
250 ++(by_icon_count[icon]);
251 }
252 } else if(std::holds_alternative<dcon::navy_id>(u)) {
253 auto a = std::get<dcon::navy_id>(u);
254 if(state.world.navy_get_controller_from_navy_control(a) != state.local_player_nation) {
255 visible = false;
256 return;
257 }
258
259 for(auto m : state.world.navy_get_navy_membership(a)) {
260 auto icon = state.military_definitions.unit_base_definitions[m.get_ship().get_type()].icon - 1;
261 if(uint32_t(icon) >= by_icon_count.size()) {
262 by_icon_count.resize(icon + 1, 0);
263 }
264 ++(by_icon_count[icon]);
265 }
266 }
267
268 int32_t max_index = 0;
269 for(uint32_t i = 1; i < by_icon_count.size(); ++i) {
270 if(by_icon_count[i] > by_icon_count[max_index])
271 max_index = int32_t(i);
272 }
273
274 frame = max_index;
275 }
276 void render(sys::state& state, int32_t x, int32_t y) noexcept override {
277 if(visible)
279 }
280};
281
283public:
284 bool visible = true;
285
286 void on_update(sys::state& state) noexcept override {
287 static std::vector<int32_t> by_icon_count;
288 for(auto& i : by_icon_count)
289 i = 0;
290
291 auto u = retrieve< unit_var>(state, parent);
292
293 visible = true;
294 if(std::holds_alternative<dcon::army_id>(u)) {
295 auto a = std::get<dcon::army_id>(u);
296 if(state.world.army_get_controller_from_army_control(a) != state.local_player_nation) {
297 visible = false;
298 return;
299 }
300
301 for(auto m : state.world.army_get_army_membership(a)) {
302 auto icon = state.military_definitions.unit_base_definitions[m.get_regiment().get_type()].icon - 1;
303 if(uint32_t(icon) >= by_icon_count.size()) {
304 by_icon_count.resize(icon + 1, 0);
305 }
306 ++(by_icon_count[icon]);
307 }
308 } else if(std::holds_alternative<dcon::navy_id>(u)) {
309 auto a = std::get<dcon::navy_id>(u);
310 if(state.world.navy_get_controller_from_navy_control(a) != state.local_player_nation) {
311 visible = false;
312 return;
313 }
314
315 for(auto m : state.world.navy_get_navy_membership(a)) {
316 auto icon = state.military_definitions.unit_base_definitions[m.get_ship().get_type()].icon - 1;
317 if(uint32_t(icon) >= by_icon_count.size()) {
318 by_icon_count.resize(icon + 1, 0);
319 }
320 ++(by_icon_count[icon]);
321 }
322 }
323
324 if(by_icon_count.size() == 0) {
325 visible = false;
326 return;
327 }
328
329 {
330 int32_t max_index = 0;
331 for(uint32_t i = 1; i < by_icon_count.size(); ++i) {
332 if(by_icon_count[i] > by_icon_count[max_index])
333 max_index = int32_t(i);
334 }
335 by_icon_count[max_index] = 0;
336 }
337 {
338 int32_t max_index = 0;
339 for(uint32_t i = 1; i < by_icon_count.size(); ++i) {
340 if(by_icon_count[i] > by_icon_count[max_index])
341 max_index = int32_t(i);
342 }
343 if(by_icon_count[max_index] == 0) {
344 visible = false;
345 } else {
346 visible = true;
347 frame = max_index;
348 }
349 }
350 }
351 void render(sys::state& state, int32_t x, int32_t y) noexcept override {
352 if(visible)
354 }
355};
356
358public:
359 bool visible = true;
360
361 message_result get(sys::state& state, Cyto::Any& payload) noexcept override {
362 if(payload.holds_type<dcon::nation_id>()) {
363 auto u = retrieve< unit_var>(state, parent);
364 if(std::holds_alternative<dcon::army_id>(u)) {
365 auto a = std::get<dcon::army_id>(u);
366 payload.emplace<dcon::nation_id>(state.world.army_get_controller_from_army_control(a));
367 } else if(std::holds_alternative<dcon::navy_id>(u)) {
368 auto a = std::get<dcon::navy_id>(u);
369 payload.emplace<dcon::nation_id>(state.world.navy_get_controller_from_navy_control(a));
370 } else {
371 payload.emplace<dcon::nation_id>(dcon::nation_id{});
372 }
374 } else if(payload.holds_type<dcon::rebel_faction_id>()) {
375 auto u = retrieve< unit_var>(state, parent);
376 if(std::holds_alternative<dcon::army_id>(u)) {
377 auto a = std::get<dcon::army_id>(u);
378 payload.emplace<dcon::rebel_faction_id>(state.world.army_get_controller_from_army_rebel_control(a));
379 } else {
380 payload.emplace<dcon::rebel_faction_id>(dcon::rebel_faction_id{});
381 }
383 }
385 }
386 void on_update(sys::state& state) noexcept override {
387
388 visible = true;
389 auto u = retrieve< unit_var>(state, parent);
390
391 if(std::holds_alternative<dcon::army_id>(u)) {
392 auto a = std::get<dcon::army_id>(u);
393 if(state.world.army_get_controller_from_army_control(a) == state.local_player_nation) {
394 visible = false;
395 return;
396 }
397
398 } else if(std::holds_alternative<dcon::navy_id>(u)) {
399 auto a = std::get<dcon::navy_id>(u);
400 if(state.world.navy_get_controller_from_navy_control(a) == state.local_player_nation) {
401 visible = false;
402 return;
403 }
404 } else {
405 visible = false;
406 return;
407 }
408
410 }
411 void render(sys::state& state, int32_t x, int32_t y) noexcept override {
412 if(visible)
414 }
415 mouse_probe impl_probe_mouse(sys::state& state, int32_t x, int32_t y, mouse_probe_type type) noexcept override {
416 if(visible)
418 else
419 return mouse_probe{ nullptr, ui::xy_pair{} };
420 }
421};
422
424 dcon::nation_id controller;
425 bool selected = false;
426 if(std::holds_alternative<dcon::army_id>(display_unit)) {
427 controller = state.world.army_get_controller_from_army_control(std::get<dcon::army_id>(display_unit));
428 selected = state.is_selected(std::get<dcon::army_id>(display_unit));
429 } else if(std::holds_alternative<dcon::navy_id>(display_unit)) {
430 controller = state.world.navy_get_controller_from_navy_control(std::get<dcon::navy_id>(display_unit));
431 selected = state.is_selected(std::get<dcon::navy_id>(display_unit));
432 } else {
433 return outline_color::gray;
434 }
435
436 if(selected && controller == state.local_player_nation) {
437 return outline_color::gold;
438 } else if(controller == state.local_player_nation) {
439 return outline_color::blue;
440 } else if(!controller || military::are_at_war(state, controller, state.local_player_nation)) {
441 return outline_color::red;
442 } else if(military::are_allied_in_war(state, controller, state.local_player_nation)) {
443 return outline_color::cyan;
444 } else {
445 return outline_color::gray;
446 }
447}
448
450 switch(a) {
453 return b == outline_color::gold || b == outline_color::blue;
454 default:
455 return a == b;
456 }
457}
459 if(a == outline_color::gray)
460 return false;
461 if(b == outline_color::gray)
462 return true;
463 return int32_t(a) < int32_t(b);
464}
465
467public:
470
471 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
472 if(name == "frame_bg") {
473 return make_element_by_type<unit_frame_bg>(state, id);
474 } else if(name == "org_bar") {
475 return make_element_by_type<unit_org_bar>(state, id);
476 } else if(name == "status") {
477 return make_element_by_type<unit_status_image>(state, id);
478 } else if(name == "dig_in") {
479 return make_element_by_type<unit_dig_in_pips_image>(state, id);
480 } else if(name == "strength") {
481 return make_element_by_type<unit_strength>(state, id);
482 } else if(name == "unit_2") {
483 return make_element_by_type<unit_second_most_prevalent>(state, id);
484 } else if(name == "unit_1") {
485 return make_element_by_type<unit_most_prevalent>(state, id);
486 } else if(name == "controller_flag") {
487 return make_element_by_type<unit_controller_flag>(state, id);
488 } else {
489 return nullptr;
490 }
491 }
492
493 void on_update(sys::state& state) noexcept override {
495 }
496
497 message_result get(sys::state& state, Cyto::Any& payload) noexcept override {
498 if(payload.holds_type<unit_var>()) {
499 payload.emplace<unit_var>(display_unit);
501 } else if(payload.holds_type<outline_color>()) {
502 payload.emplace<outline_color>(color);
504 }
506 }
507
508 void impl_render(sys::state& state, int32_t x, int32_t y) noexcept override {
509 if(!std::holds_alternative<std::monostate>(display_unit)) {
511 }
512 }
513
514 mouse_probe impl_probe_mouse(sys::state& state, int32_t x, int32_t y, mouse_probe_type type) noexcept override {
515 if(!std::holds_alternative<std::monostate>(display_unit)) {
517 } else {
518 return mouse_probe{ nullptr, ui::xy_pair{} };
519 }
520 }
521};
522
523using grid_row = std::array<unit_var, 4>;
524
526 if(std::holds_alternative<std::monostate>(a))
527 return false;
528 if(std::holds_alternative<std::monostate>(b))
529 return true;
530 if(std::holds_alternative<dcon::navy_id>(a) && std::holds_alternative<dcon::army_id>(b))
531 return true;
532 if(std::holds_alternative<dcon::army_id>(a) && std::holds_alternative<dcon::navy_id>(b))
533 return false;
534
535 auto a_color = to_color(state, a);
536 auto b_color = to_color(state, b);
537
538 if(!color_equivalent(a_color, b_color)) {
539 return color_less(a_color, b_color);
540 }
541
542 if(std::holds_alternative<dcon::army_id>(a)) {
543 auto aa = std::get<dcon::army_id>(a);
544 auto ba = std::get<dcon::army_id>(b);
545 auto aar = state.world.army_get_army_membership(aa);
546 auto bar = state.world.army_get_army_membership(ba);
547 auto acount = int32_t(aar.end() - aar.begin());
548 auto bcount = int32_t(bar.end() - bar.begin());
549 if(acount != bcount)
550 return acount > bcount;
551 return aa.index() < ba.index();
552 } else {
553 auto aa = std::get<dcon::navy_id>(a);
554 auto ba = std::get<dcon::navy_id>(b);
555 auto aar = state.world.navy_get_navy_membership(aa);
556 auto bar = state.world.navy_get_navy_membership(ba);
557 auto acount = int32_t(aar.end() - aar.begin());
558 auto bcount = int32_t(bar.end() - bar.begin());
559 if(acount != bcount)
560 return acount > bcount;
561 return aa.index() < ba.index();
562 }
563
564}
565
566class unit_grid_row : public listbox_row_element_base<grid_row> {
567public:
568 std::array< base_unit_container*, 4> grid_items;
569
570 void on_create(sys::state& state) noexcept override {
572 {
573 auto win = make_element_by_type<base_unit_container>(state, state.ui_state.defs_by_name.find(state.lookup_key("alice_base_unit_icon"))->second.definition);
574 win->base_data.position.x = int16_t(3 + 67 * 0);
575 win->base_data.position.y = int16_t(3);
576 grid_items[0] = win.get();
577 add_child_to_front(std::move(win));
578 }
579 {
580 auto win = make_element_by_type<base_unit_container>(state, state.ui_state.defs_by_name.find(state.lookup_key("alice_base_unit_icon"))->second.definition);
581 win->base_data.position.x = int16_t(3 + 67 * 1);
582 win->base_data.position.y = int16_t(3);
583 grid_items[1] = win.get();
584 add_child_to_front(std::move(win));
585 }
586 {
587 auto win = make_element_by_type<base_unit_container>(state, state.ui_state.defs_by_name.find(state.lookup_key("alice_base_unit_icon"))->second.definition);
588 win->base_data.position.x = int16_t(3 + 67 * 2);
589 win->base_data.position.y = int16_t(3);
590 grid_items[2] = win.get();
591 add_child_to_front(std::move(win));
592 }
593 {
594 auto win = make_element_by_type<base_unit_container>(state, state.ui_state.defs_by_name.find(state.lookup_key("alice_base_unit_icon"))->second.definition);
595 win->base_data.position.x = int16_t(3 + 67 * 3);
596 win->base_data.position.y = int16_t(3);
597 grid_items[3] = win.get();
598 add_child_to_front(std::move(win));
599 }
600 }
601
602 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
603 return nullptr;
604 }
605
606 void on_update(sys::state& state) noexcept override {
607 grid_items[0]->display_unit = content[0];
608 grid_items[1]->display_unit = content[1];
609 grid_items[2]->display_unit = content[2];
610 grid_items[3]->display_unit = content[3];
611 }
612};
613
614
615class unit_grid_lb : public listbox_element_base<unit_grid_row, grid_row> {
616public:
617 std::string_view get_row_element_name() override {
618 return "alice_grid_row";
619 }
620 void on_update(sys::state& state) noexcept override {
621 row_contents.clear();
622
623 static std::vector<unit_var> base_array;
624 base_array.clear();
625
626 auto prov = retrieve<dcon::province_id>(state, parent);
627 bool as_port = retrieve<bool>(state, parent);
628
629 if(as_port || (prov.index() >= state.province_definitions.first_sea_province.index())) {
630 for(auto n : state.world.province_get_navy_location(prov)) {
631 base_array.emplace_back(n.get_navy().id);
632 }
633 }
634 if(as_port) {
635 for(auto a : state.world.province_get_army_location(prov)) {
636 if(a.get_army().get_navy_from_army_transport()) {
637 base_array.emplace_back(a.get_army().id);
638 }
639 }
640 } else if(prov.index() >= state.province_definitions.first_sea_province.index()) {
641 for(auto a : state.world.province_get_army_location(prov)) {
642 base_array.emplace_back(a.get_army().id);
643 }
644 } else {
645 for(auto a : state.world.province_get_army_location(prov)) {
646 if(!(a.get_army().get_navy_from_army_transport())) {
647 base_array.emplace_back(a.get_army().id);
648 }
649 }
650 }
651 for(uint32_t i = 0; i < base_array.size(); i += 4) {
652 grid_row new_row;
653 for(uint32_t j = 0; j < 4 && (i + j) < base_array.size(); ++j) {
654 new_row[j] = base_array[i + j];
655 }
656 row_contents.push_back(new_row);
657 }
658
659 update(state);
660 }
661};
662
664public:
665 bool as_port = false;
666 dcon::province_id for_province;
667
668 std::unique_ptr<element_base> make_child(sys::state& state, std::string_view name, dcon::gui_def_id id) noexcept override {
669 if(name == "grid_listbox") {
670 return make_element_by_type<unit_grid_lb>(state, id);
671 } else {
672 return nullptr;
673 }
674 }
675
676 message_result get(sys::state& state, Cyto::Any& payload) noexcept override {
677 if(payload.holds_type<dcon::province_id>()) {
678 payload.emplace<dcon::province_id>(for_province);
680 } else if(payload.holds_type<bool>()) {
681 payload.emplace<bool>(as_port);
683 }
685 }
686
687 void open(sys::state& state, ui::xy_pair location, ui::xy_pair source_size, dcon::province_id p, bool port) {
688 if(!as_port) {
689 if(p.index() < state.province_definitions.first_sea_province.index()) {
690 auto pname = text::produce_simple_string(state, state.world.province_get_name(p));
691 auto arange = state.world.province_get_army_location(p);
692 if(int32_t(arange.end() - arange.begin()) <= 1)
693 return;
694 } else {
695 auto arange = state.world.province_get_army_location(p);
696 auto nrange = state.world.province_get_navy_location(p);
697 if(int32_t(nrange.end() - nrange.begin()) <= 1 && arange.begin() == arange.end())
698 return;
699 }
700 }
701
702 as_port = port;
703 for_province = p;
704
705 auto mx = int32_t(state.mouse_x_position / state.user_settings.ui_scale);
706 auto my = int32_t(state.mouse_y_position / state.user_settings.ui_scale);
707 if(state.ui_state.mouse_sensitive_target)
709
710 if(location.y + source_size.y + 3 + base_data.size.y < state.ui_state.root->base_data.size.y) { // position below
711 auto desired_x = location.x + source_size.x / 2 - base_data.size.x / 2;
712 auto actual_x = std::clamp(desired_x, 0, state.ui_state.root->base_data.size.x - base_data.size.x);
713 base_data.position.x = int16_t(actual_x);
714 base_data.position.y = int16_t(location.y + source_size.y + 3);
715
716 state.ui_state.target_ul_bounds.x = int16_t(std::min(mx - 4, actual_x));
717 state.ui_state.target_ul_bounds.y = int16_t(std::min(my - 4, location.y + source_size.y + 3));
718 state.ui_state.target_lr_bounds.x = int16_t(std::max(mx + 4, actual_x + base_data.size.x));
719 state.ui_state.target_lr_bounds.y = int16_t(std::max(my + 4, location.y + source_size.y + 3 + base_data.size.y));
720
721 } else if(location.x + source_size.x + 3 + base_data.size.x < state.ui_state.root->base_data.size.x) { // position right
722 auto desired_y = location.y + source_size.y / 2 - base_data.size.y / 2;
723
724 auto actual_y = std::clamp(desired_y, 0, state.ui_state.root->base_data.size.y - base_data.size.y);
725 base_data.position.x = int16_t(location.x + source_size.x + 3);
726 base_data.position.y = int16_t(actual_y);
727
728 state.ui_state.target_ul_bounds.x = int16_t(std::min(mx - 4, location.x + source_size.x + 3));
729 state.ui_state.target_ul_bounds.y = int16_t(std::min(my - 4, actual_y));
730 state.ui_state.target_lr_bounds.x = int16_t(std::max(mx + 4, location.x + source_size.x + 3 + base_data.size.x));
731 state.ui_state.target_lr_bounds.y = int16_t(std::max(my + 4, actual_y + base_data.size.y));
732 } else { //position left
733 auto desired_y = location.y + source_size.y / 2 - base_data.size.y / 2;
734
735 auto actual_y = std::clamp(desired_y, 0, state.ui_state.root->base_data.size.y - base_data.size.y);
736 base_data.position.x = int16_t(location.x - base_data.size.x - 3);
737 base_data.position.y = int16_t(actual_y);
738
739 state.ui_state.target_ul_bounds.x = int16_t(std::min(mx - 4, location.x - base_data.size.x - 3));
740 state.ui_state.target_ul_bounds.y = int16_t(std::min(my - 4, actual_y));
741 state.ui_state.target_lr_bounds.x = int16_t(std::max(mx + 4, location.x - base_data.size.x - 3));
742 state.ui_state.target_lr_bounds.y = int16_t(std::max(my + 4, actual_y + base_data.size.y));
743 }
744
745 state.ui_state.mouse_sensitive_target = this;
746 set_visible(state, true);
747 }
748};
749
750} //namespace ui
std::unique_ptr< element_base > make_child(sys::state &state, std::string_view name, dcon::gui_def_id id) noexcept override
mouse_probe impl_probe_mouse(sys::state &state, int32_t x, int32_t y, mouse_probe_type type) noexcept override
void impl_render(sys::state &state, int32_t x, int32_t y) noexcept override
void on_update(sys::state &state) noexcept override
message_result get(sys::state &state, Cyto::Any &payload) noexcept override
void add_child_to_front(std::unique_ptr< element_base > child) noexcept final
element_base * parent
virtual void impl_render(sys::state &state, int32_t x, int32_t y) noexcept
virtual void on_create(sys::state &state) noexcept
element_data base_data
void set_visible(sys::state &state, bool vis)
virtual mouse_probe impl_probe_mouse(sys::state &state, int32_t x, int32_t y, mouse_probe_type type) noexcept
void on_update(sys::state &state) noexcept override
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void open(sys::state &state, ui::xy_pair location, ui::xy_pair source_size, dcon::province_id p, bool port)
std::unique_ptr< element_base > make_child(sys::state &state, std::string_view name, dcon::gui_def_id id) noexcept override
dcon::province_id for_province
message_result get(sys::state &state, Cyto::Any &payload) 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)
mouse_probe impl_probe_mouse(sys::state &state, int32_t x, int32_t y, mouse_probe_type type) noexcept override
message_result get(sys::state &state, Cyto::Any &payload) noexcept override
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void on_update(sys::state &state) noexcept override
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void on_update(sys::state &state) noexcept override
tooltip_behavior has_tooltip(sys::state &state) noexcept override
void button_action(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
void button_shift_action(sys::state &state) noexcept override
void update_tooltip(sys::state &state, int32_t x, int32_t y, text::columnar_layout &contents) noexcept override
void on_update(sys::state &state) noexcept override
std::string_view get_row_element_name() 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
void on_update(sys::state &state) noexcept override
std::array< base_unit_container *, 4 > grid_items
void on_update(sys::state &state) noexcept override
void render(sys::state &state, int32_t x, int32_t y) 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 on_update(sys::state &state) noexcept override
void on_update(sys::state &state) noexcept override
bool are_allied_in_war(sys::state const &state, dcon::nation_id a, dcon::nation_id b)
Definition: military.cpp:486
bool will_recieve_attrition(sys::state &state, dcon::navy_id a)
Definition: military.cpp:4946
bool are_at_war(sys::state const &state, dcon::nation_id a, dcon::nation_id b)
Definition: military.cpp:475
std::string prettify(int64_t num)
Definition: text.cpp:762
std::string format_float(float num, size_t digits)
Definition: text.cpp:981
std::string produce_simple_string(sys::state const &state, dcon::text_key id)
Definition: text.cpp:617
std::array< unit_var, 4 > grid_row
bool color_less(outline_color a, outline_color b)
int32_t status_frame(sys::state &state, dcon::army_id a)
tooltip_behavior
@ count
Definition: gui_event.hpp:126
bool color_equivalent(outline_color a, outline_color b)
message_result
std::variant< std::monostate, dcon::army_id, dcon::navy_id > unit_var
outline_color to_color(sys::state &state, unit_var display_unit)
bool unit_var_ordering(sys::state &state, unit_var a, unit_var b)
uint uint32_t
uchar uint8_t
ankerl::unordered_dense::map< dcon::text_key, element_target, hash_text_key > defs_by_name
std::unique_ptr< element_base > root
xy_pair target_ul_bounds
element_base * mouse_sensitive_target
xy_pair target_lr_bounds