5#include <unordered_map>
12#include "dcon_generated.hpp"
37 for(
auto& c : children) {
40 auto res = c->impl_probe_mouse(
state, x - relative_location.x, y - relative_location.y,
type);
49 for(
auto& c : children) {
52 auto res = c->impl_probe_mouse(
state, x - relative_location.x, y - relative_location.y,
type);
62 for(
auto& c : children) {
73 for(
auto& c : children) {
86 for(
auto& c : children) {
88 c->impl_on_update(
state);
96 for(
size_t i = children.size(); i-- > 0;) {
98 children[i]->impl_on_update(
state);
104 for(
auto& c : children) {
105 c->impl_on_reset_text(
state);
107 on_reset_text(
state);
110 for(
auto& c : children) {
111 c->impl_on_reset_text(
state);
113 on_reset_text(
state);
117 for(
auto& c : children) {
124 for(
auto& c : children) {
133 for(
size_t i = children.size(); i-- > 0;) {
134 if(children[i]->is_visible()) {
136 children[i]->impl_render(
state, x + relative_location.x, y + relative_location.y);
143 for(
size_t i = children.size(); i-- > 0;) {
144 if(children[i]->is_visible()) {
146 children[i]->impl_render(
state, x + relative_location.x, y + relative_location.y);
152 if(
auto it = std::find_if(children.begin(), children.end(), [child](std::unique_ptr<element_base>& p) { return p.get() == child; }); it != children.end()) {
153 if(it + 1 != children.end())
154 std::rotate(it, it + 1, children.end());
155 auto temp = std::move(children.back());
157 temp->parent =
nullptr;
160 return std::unique_ptr<element_base>{};
163 if(
auto it = std::find_if(children.begin(), children.end(), [child](std::unique_ptr<element_base>& p) { return p.get() == child; }); it != children.end()) {
164 if(it != children.begin())
165 std::rotate(children.begin(), it, it + 1);
169 if(
auto it = std::find_if(children.begin(), children.end(), [child](
element_base* p) { return p == child; }); it != children.end()) {
170 if(it != children.begin())
171 std::rotate(children.begin(), it, it + 1);
175 if(
auto it = std::find_if(children.begin(), children.end(), [child](std::unique_ptr<element_base>& p) { return p.get() == child; }); it != children.end()) {
176 if(it + 1 != children.end())
177 std::rotate(it, it + 1, children.end());
181 if(
auto it = std::find_if(children.begin(), children.end(), [child](
element_base* p) { return p == child; }); it != children.end()) {
182 if(it + 1 != children.end())
183 std::rotate(it, it + 1, children.end());
187 child->parent =
this;
188 children.emplace_back(std::move(child));
189 if(children.size() > 1) {
190 std::rotate(children.begin(), children.end() - 1, children.end());
194 child->parent =
this;
195 children.emplace_back(std::move(child));
198 if(
auto it = std::find_if(children.begin(), children.end(), [&
state,
name](std::unique_ptr<element_base>& p) { return parsers::lowercase_str(state.to_string_view(p->base_data.name)) == parsers::lowercase_str(name); }); it != children.end()) {
204 if(0 <= index && index < int32_t(children.size()))
205 return children[index].
get();
209 if(0 <= index && index < int32_t(children.size()))
210 return children[index];
215 if(!is_under_mouse || !is_interactable) {
233 frame = base_data.data.image.frame();
238 dcon::gfx_object_id gid;
240 gid = base_data.data.image.gfx_object;
242 gid = base_data.data.button.button_image;
246 auto& gfx_def =
state.ui_defs.gfx[gid];
247 if(gfx_def.primary_texture_handle) {
250 gfx_def.type_dependent,
float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y),
252 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
253 get_horizontal_flip(
state));
254 }
else if(gfx_def.number_of_frames > 1) {
256 gfx_def.number_of_frames,
float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y),
258 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
259 get_horizontal_flip(
state));
262 float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y),
264 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
265 get_horizontal_flip(
state));
272 dcon::gfx_object_id gid;
274 gid = base_data.data.image.gfx_object;
276 gid = base_data.data.button.button_image;
279 auto const& gfx_def =
state.ui_defs.gfx[gid];
280 if(gfx_def.primary_texture_handle) {
281 if(gfx_def.number_of_frames > 1) {
283 gfx_def.number_of_frames,
float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y),
286 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
287 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
292 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
293 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
301 dcon::gfx_object_id gid = base_data.data.image.gfx_object;
303 auto const& gfx_def =
state.ui_defs.gfx[gid];
304 auto secondary_texture_handle = dcon::texture_id(gfx_def.type_dependent - 1);
305 if(gfx_def.primary_texture_handle) {
307 progress,
float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y),
310 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
311 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
319 float amount = (r + g + b) / 4.f;
320 return sys::pack_color(std::min(1.f, amount + 0.1f), std::min(1.f, amount + 0.1f), std::min(1.f, amount + 0.1f));
323 return sys::pack_color(std::min(1.f, r + 0.1f), std::min(1.f, g + 0.1f), std::min(1.f, b + 0.1f));
326 float amount = (r + g + b) / 4.f;
341 auto& current_font =
state.font_collection.get_font(
state, font_index);
343 if(std::holds_alternative<text::embedded_flag>(t.
source)) {
346 std::get<text::embedded_flag>(t.
source),
353 }
else if(std::holds_alternative<text::embedded_unit_icon>(t.
source)) {
356 std::get<text::embedded_unit_icon>(t.
source),
363 }
else if(std::holds_alternative<text::embedded_commodity_icon>(t.
source)) {
366 std::get<text::embedded_commodity_icon>(t.
source),
372 }
else if(std::holds_alternative<text::embedded_icon>(t.
source)) {
375 std::get<text::embedded_icon>(t.
source),
399 dcon::gfx_object_id gid;
401 gid = base_data.data.image.gfx_object;
403 gid = base_data.data.button.button_image;
406 auto const& gfx_def =
state.ui_defs.gfx[gid];
407 if(gfx_def.primary_texture_handle) {
426 if(gfx_def.number_of_frames > 1) {
428 gfx_def.number_of_frames,
float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y),
431 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
432 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
437 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
438 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
446 if(internal_layout.contents.empty())
449 auto linesz =
state.font_collection.line_height(
state, base_data.data.button.font_handle);
452 auto ycentered = (base_data.size.y - linesz) / 2;
455 for(
auto& t : internal_layout.contents) {
460 float(y + int32_t(ycentered)),
461 base_data.data.button.font_handle,
469 dcon::gfx_object_id gid;
471 gid = base_data.data.image.gfx_object;
473 gid = base_data.data.button.button_image;
476 auto const& gfx_def =
state.ui_defs.gfx[gid];
477 if(gfx_def.primary_texture_handle) {
491 if(gfx_def.number_of_frames > 1) {
493 gfx_def.number_of_frames,
float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y),
496 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
497 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
502 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
503 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
508 if(internal_layout.contents.empty())
511 auto linesz =
state.font_collection.line_height(
state, base_data.data.button.font_handle);
514 auto ycentered = (base_data.size.y - linesz) / 2;
517 for(
auto& t : internal_layout.contents) {
522 float(y + int32_t(ycentered)),
523 base_data.data.button.font_handle,
598 return ogl::color3f{232.0f / 255.0f, 210.0f / 255.0f, 124.0f / 255.0f};
600 return ogl::color3f{ 150.0f / 255.0f, 75.0f / 255.0f, 0.f };
623 auto base_text_handle = base_data.data.button.txt;
625 if(base_text_handle) {
627 internal_layout.contents.clear();
628 internal_layout.number_of_lines = 0;
633 sl.add_text(
state, cached_text);
639 on_reset_text(
state);
651 if(ch >= 32 && ch != U
'`' && ch != 127) {
652 auto s = std::string(get_text(
state));
653 s += char(ch & 0xff);
656 edit_box_update(
state, s);
657 }
else if(ch == 0x16) {
659 std::wstring return_value;
660 if(OpenClipboard(
state.win_ptr->hwnd)) {
661 HGLOBAL hClipboardData = GetClipboardData(CF_UNICODETEXT);
663 if(hClipboardData != NULL) {
664 size_t byteSize = GlobalSize(hClipboardData);
665 void* memory = GlobalLock(hClipboardData);
667 const wchar_t*
text =
reinterpret_cast<const wchar_t*
>(memory);
668 return_value = std::wstring(
text,
text + byteSize /
sizeof(
wchar_t));
669 GlobalUnlock(hClipboardData);
670 if(return_value.length() > 0 && return_value.back() == 0) {
671 return_value.pop_back();
677 if(return_value.size() > 0) {
679 auto new_text = std::string(get_text(
state)) + utf8_val;
680 edit_index += int32_t(utf8_val.length());
681 set_text(
state, new_text);
682 edit_box_update(
state, new_text);
692 auto s = std::string(get_text(
state));
695 edit_box_enter(
state, s);
704 edit_box_tab(
state, s);
710 edit_box_down(
state);
713 edit_box_backtick(
state);
716 edit_box_back_slash(
state);
719 edit_index = std::max<int32_t>(edit_index - 1, 0);
722 edit_index = std::min<int32_t>(edit_index + 1, int32_t(s.length()));
725 if(edit_index < int32_t(s.length())) {
726 s.erase(edit_index, 1);
728 edit_box_update(
state, s);
733 int32_t index = edit_index - 1;
735 while(index > 0 && (s.at(index) !=
' ' || !skip)) {
736 if(s.at(index) !=
' ')
740 s.erase(index, edit_index);
743 edit_box_update(
state, s);
744 }
else if(edit_index > 0 && edit_index <= int32_t(s.length())) {
745 s.erase(edit_index - 1, 1);
748 edit_box_update(
state, s);
773 on_reset_text(
state);
778 dcon::texture_id background_texture_id;
789 if(
bool(background_texture_id)) {
791 float(base_data.size.y),
ogl::get_texture_handle(state, background_texture_id,
true), base_data.get_rotation(),
false,
792 state.world.locale_get_native_rtl(state.font_collection.get_current_locale()));
797 auto old_s = std::string(get_text(state));
798 auto blink_s = std::string(get_text(state));
799 blink_s.insert(
size_t(edit_index), 1,
'|');
800 set_text(state, blink_s);
802 set_text(state, old_s);
809 for(
auto& t : internal_layout.contents) {
829 float y_height = max - min;
830 std::vector<float> scaled_datapoints = std::vector<float>(
count);
831 if(y_height == 0.f) {
832 for(
size_t i = 0; i <
count; i++) {
833 scaled_datapoints[i] = .5f;
836 for(
size_t i = 0; i <
count; i++) {
837 scaled_datapoints[i] = (
datapoints[i] - min) / y_height;
842 lines.set_y(scaled_datapoints.data());
847 float y_height = max - min;
848 std::vector<float> scaled_datapoints = std::vector<float>(
count);
849 if(y_height == 0.f) {
850 for(
size_t i = 0; i <
count; i++) {
851 scaled_datapoints[i] = .5f;
854 for(
size_t i = 0; i <
count; i++) {
855 scaled_datapoints[i] = (
datapoints[i] - min) / y_height;
860 lines.set_y(scaled_datapoints.data());
911 uint16_t font_handle = 0;
936 internal_layout.contents.clear();
937 internal_layout.number_of_lines = 0;
943 sl.add_text(
state, cached_text);
950 internal_layout.contents.clear();
951 internal_layout.number_of_lines = 0;
957 sl.add_text(
state, cached_text);
963 on_reset_text(
state);
969 auto linesz =
state.font_collection.line_height(
state, base_data.data.button.font_handle);
972 auto ycentered = (base_data.size.y - linesz) / 2;
974 for(
auto& t : internal_layout.contents) {
979 float(y + int32_t(ycentered)),
980 base_data.data.button.font_handle,
986 for(
auto& t : internal_layout.contents) {
990 float(x + base_data.data.text.border_size.x) + t.x,
991 float(y + base_data.data.text.border_size.y),
992 base_data.data.button.font_handle,
1020 auto old_handle = base_data.data.text_common.font_handle;
1021 base_data.data.text_common.font_handle &= ~(0x01 << 7);
1022 auto old_value = base_data.data.text_common.font_handle & 0x3F;
1023 base_data.data.text_common.font_handle &= ~(0x003F);
1024 base_data.data.text_common.font_handle |= (old_value - 2);
1027 base_data.data.text_common.font_handle = old_handle;
1030 auto old_handle = base_data.data.text_common.font_handle;
1031 base_data.data.text_common.font_handle &= ~(0x01 << 7);
1032 auto old_value = base_data.data.text_common.font_handle & 0x3F;
1033 base_data.data.text_common.font_handle &= ~(0x003F);
1034 base_data.data.text_common.font_handle |= (old_value - 2);
1037 base_data.data.text_common.font_handle = old_handle;
1044 auto linesz =
state.font_collection.line_height(
state, base_data.data.button.font_handle);
1047 auto ycentered = (base_data.size.y - linesz) / 2;
1049 for(
auto& t : internal_layout.contents) {
1054 float(y + int32_t(ycentered)),
1055 base_data.data.button.font_handle,
1061 for(
auto& t : internal_layout.contents) {
1065 float(x + base_data.data.text.border_size.x) + t.x,
1066 float(y + base_data.data.text.border_size.y),
1067 base_data.data.button.font_handle,
1078 line_height =
state.font_collection.line_height(
state, base_data.data.text.font_handle);
1079 visible_lines = base_data.size.y / std::max<int32_t>(int32_t(line_height), 1);
1089 for(
auto& t : internal_layout.contents) {
1090 float line_offset = t.y - line_height * float(current_line);
1092 if(0 <= line_offset && line_offset < base_data.size.y) {
1097 float(y + line_offset),
1098 base_data.data.text.font_handle,
1108 auto const* chunk = internal_layout.get_chunk_from_position(x, y + int32_t(line_height *
float(current_line)));
1109 if(chunk !=
nullptr) {
1110 if(std::holds_alternative<dcon::nation_id>(chunk->source)) {
1112 state.open_diplomacy(std::get<dcon::nation_id>(chunk->source));
1113 auto cap =
state.world.nation_get_capital(std::get<dcon::nation_id>(chunk->source));
1115 auto map_pos =
state.world.province_get_mid_point(cap);
1116 map_pos.x /= float(
state.map_state.map_data.size_x);
1117 map_pos.y /= float(
state.map_state.map_data.size_y);
1118 map_pos.y = 1.0f - map_pos.y;
1119 state.map_state.set_pos(map_pos);
1121 }
else if(std::holds_alternative<dcon::province_id>(chunk->source)) {
1122 auto prov = std::get<dcon::province_id>(chunk->source);
1123 if(prov && prov.value <
state.province_definitions.first_sea_province.value) {
1125 state.map_state.set_selected_province(prov);
1129 state.map_state.center_map_on_province(
state, prov);
1131 }
else if(std::holds_alternative<dcon::state_instance_id>(chunk->source)) {
1132 auto s = std::get<dcon::state_instance_id>(chunk->source);
1133 auto prov =
state.world.state_instance_get_capital(s);
1134 if(prov && prov.id.value <
state.province_definitions.first_sea_province.value) {
1136 state.map_state.set_selected_province(prov);
1140 state.map_state.center_map_on_province(
state, prov);
1142 }
else if(std::holds_alternative<dcon::national_identity_id>(chunk->source)) {
1143 auto id = std::get<dcon::national_identity_id>(chunk->source);
1144 auto nat =
state.world.national_identity_get_nation_from_identity_holder(
id);
1147 state.open_diplomacy(nat);
1148 auto cap =
state.world.nation_get_capital(nat);
1150 auto map_pos =
state.world.province_get_mid_point(cap);
1151 map_pos.x /= float(
state.map_state.map_data.size_x);
1152 map_pos.y /= float(
state.map_state.map_data.size_y);
1153 map_pos.y = 1.0f - map_pos.y;
1154 state.map_state.set_pos(map_pos);
1157 }
else if(std::holds_alternative<dcon::state_definition_id>(chunk->source)) {
1158 auto s = std::get<dcon::state_definition_id>(chunk->source);
1159 auto prov_rng =
state.world.state_definition_get_abstract_state_membership(s);
1160 dcon::province_id prov = prov_rng.begin() != prov_rng.end() ? (*prov_rng.begin()).get_province().id : dcon::province_id{ };
1161 if(prov && prov.value <
state.province_definitions.first_sea_province.value) {
1163 state.map_state.set_selected_province(prov);
1167 state.map_state.center_map_on_province(
state, prov);
1180 if(line_height == 0.f)
1185 auto chunk = internal_layout.get_chunk_from_position(x, y + int32_t(line_height *
float(current_line)));
1188 if(std::holds_alternative<dcon::nation_id>(chunk->source)
1189 || std::holds_alternative<dcon::province_id>(chunk->source)
1190 || std::holds_alternative<dcon::state_instance_id>(chunk->source)
1191 || std::holds_alternative<dcon::national_identity_id>(chunk->source)
1192 || std::holds_alternative<dcon::state_definition_id>(chunk->source)) {
1212 line_height =
state.font_collection.line_height(
state, base_data.data.button.font_handle);
1213 if(line_height == 0.f)
1215 visible_lines = base_data.size.y / int32_t(line_height);
1220 on_reset_text(
state);
1225 if(internal_layout.contents.empty())
1229 if(line_height == 0.f)
1231 for(
auto& t : internal_layout.contents) {
1232 float line_offset = t.y - line_height * float(current_line);
1233 if(0 <= line_offset && line_offset < base_data.size.y) {
1238 float(y + line_offset),
1239 base_data.data.button.font_handle,
1250 dcon::gfx_object_id gfx_handle;
1259 auto const& gfx_def =
state.ui_defs.gfx[gfx_handle];
1260 if(gfx_def.size.x != 0) {
1261 dat.
size = gfx_def.size;
1263 auto tex_handle = gfx_def.primary_texture_handle;
1266 dat.
size.
y = int16_t(
state.open_gl.asset_textures[tex_handle].size_y);
1267 dat.
size.
x = int16_t(
state.open_gl.asset_textures[tex_handle].size_x / gfx_def.number_of_frames);
1281 if(it->second.generator) {
1282 auto res = it->second.generator(
state, it->second.definition);
1284 std::memcpy(&(res->base_data), &(
state.ui_defs.gui[it->second.definition]),
sizeof(
ui::element_data));
1286 res->on_create(
state);
1292 return std::unique_ptr<element_base>{};
1296 units_root = std::make_unique<container_base>();
1297 rgos_root = std::make_unique<container_base>();
1299 root = std::make_unique<container_base>();
1302 tooltip = std::make_unique<tool_tip>();
1310 auto first_child = base_data.data.window.first_child;
1311 auto num_children = base_data.data.window.num_children;
1312 for(
auto ex :
state.ui_defs.extensions) {
1313 if(ex.window == base_data.name) {
1319 this->add_child_to_back(std::move(ch_res));
1323 for(
uint32_t i = num_children; i-- > 0;) {
1324 auto child_tag = dcon::gui_def_id(dcon::gui_def_id::value_base_t(i + first_child.index()));
1330 this->add_child_to_back(std::move(ch_res));
1339 if(location_abs.x <= oldx && oldx < base_data.size.x + location_abs.x && location_abs.y <= oldy &&
1340 oldy < base_data.size.y + location_abs.y) {
1341 xy_pair new_abs_pos = location_abs;
1342 new_abs_pos.
x += int16_t(x - oldx);
1343 new_abs_pos.
y += int16_t(y - oldy);
1346 new_abs_pos.
x = int16_t(std::clamp(int32_t(new_abs_pos.
x), 0,
ui_width(
state) - base_data.size.x));
1348 new_abs_pos.
y = int16_t(std::clamp(int32_t(new_abs_pos.
y), 0,
ui_height(
state) - base_data.size.y));
1350 if(
state.world.locale_get_native_rtl(
state.font_collection.get_current_locale())) {
1351 base_data.position.x -= int16_t(new_abs_pos.
x - location_abs.x);
1353 base_data.position.x += int16_t(new_abs_pos.
x - location_abs.x);
1355 base_data.position.y += int16_t(new_abs_pos.
y - location_abs.y);
1361 if(distribution.size() > 0)
1367 base_data.position.x -= base_data.size.x;
1368 radius = float(base_data.size.x);
1369 base_data.size.x *= 2;
1370 base_data.size.y *= 2;
1375 std::sort(distribution.begin(), distribution.end(), [](
auto const& a,
auto const& b) { return a.value > b.value; });
1377 for(
auto& e : distribution) {
1380 int32_t int_total = 0;
1383 for(
auto& e : distribution) {
1384 auto ivalue = int32_t(e.value *
float(resolution) / total);
1387 int_total += ivalue;
1390 distribution.clear();
1393 if(int_total < resolution && distribution.size() > 0) {
1394 auto rem = resolution - int_total;
1396 for(
auto& e : distribution) {
1403 }
else if(int_total > resolution) {
1408 for(
auto& e : distribution) {
1410 auto slice_count = size_t(e.slices);
1412 for(
size_t j = 0; j < slice_count; j++) {
1413 data_texture.data[(i + j) * channels] =
uint8_t(color & 0xFF);
1414 data_texture.data[(i + j) * channels + 1] =
uint8_t(color >> 8 & 0xFF);
1415 data_texture.data[(i + j) * channels + 2] =
uint8_t(color >> 16 & 0xFF);
1420 for(; i < resolution; i++) {
1421 data_texture.data[i * channels] =
uint8_t(0);
1422 data_texture.data[i * channels + 1] =
uint8_t(0);
1423 data_texture.data[i * channels + 2] =
uint8_t(0);
1426 data_texture.data_updated =
true;
1431 float const PI = 3.141592653589793238463f;
1432 float dx = float(x) - radius;
1433 float dy = float(y) - radius;
1435 if(dx != 0.0f || dy != 0.0f) {
1436 float dist = std::sqrt(dx * dx + dy * dy);
1437 float angle = std::acos(-dx / dist);
1439 angle = PI + (PI - angle);
1441 index = size_t(angle / (2.f * PI) *
float(resolution));
1443 for(
auto const& e : distribution) {
1444 if(index <
size_t(e.slices)) {
1445 populate_tooltip(
state, e.key, e.value, contents);
1448 index -= size_t(e.slices);
1456 if constexpr(!std::is_same_v<dcon::nation_id, T>)
1466template<
class SrcT,
class DemoT>
1468 this->distribution.clear();
1473 this->parent->impl_get(
state, obj_id_payload);
1474 float total_pops = 0.f;
1476 for_each_demo(
state, [&](DemoT demo_id) {
1478 if(obj_id_payload.
holds_type<dcon::province_id>()) {
1479 auto demo_key = demographics::to_key(state, demo_id);
1480 auto prov_id = any_cast<dcon::province_id>(obj_id_payload);
1481 volume = state.world.province_get_demographics(prov_id, demo_key);
1482 }
else if(obj_id_payload.
holds_type<dcon::nation_id>()) {
1483 auto demo_key = demographics::to_key(state, demo_id);
1484 auto nat_id = any_cast<dcon::nation_id>(obj_id_payload);
1485 volume = state.world.nation_get_demographics(nat_id, demo_key);
1488 if constexpr(std::is_same_v<SrcT, dcon::pop_id>) {
1489 if(obj_id_payload.holds_type<dcon::pop_id>()) {
1490 auto demo_key = pop_demographics::to_key(state, demo_id);
1491 auto pop_id = any_cast<dcon::pop_id>(obj_id_payload);
1492 volume = pop_demographics::get_demo(state, pop_id, demo_key);
1496 this->distribution.emplace_back(demo_id, volume);
1500 this->update_chart(
state);
1504 base_data.data.scrollbar.flags &=
~ui::scrollbar_data::step_size_mask;
1505 scrollbar::on_create(
state);
1508void autoscaling_scrollbar::scale_to_parent() {
1509 base_data.size.y = parent->base_data.size.y;
1510 base_data.data.scrollbar.border_size = base_data.size;
1511 base_data.position.x = parent->base_data.size.x;
1513 left->base_data.position.y = parent->base_data.size.y -
left->base_data.size.y;
1514 right->base_data.position.y = 0;
1515 track->base_data.size.y = parent->base_data.size.y - 2 *
right->base_data.size.y;
1516 track->base_data.position.y =
right->base_data.size.y;
1517 track->base_data.position.x = 5;
1518 slider->base_data.position.x = 0;
1519 settings.track_size = track->base_data.size.y;
1521 left->step_size = -settings.scaling_factor;
1522 right->step_size = -settings.scaling_factor;
1527 impl_get(
state, payload);
1531 auto res = std::make_unique<multiline_text_element_base>();
1534 res->base_data.position.x = 0;
1535 res->base_data.position.y = 0;
1536 res->on_create(
state);
1537 delegate = res.get();
1539 add_child_to_front(std::move(res));
1541 auto ptr = make_element_by_type<multiline_text_scrollbar>(
state,
"standardlistbox_slider");
1543 add_child_to_front(std::move(ptr));
1544 text_scrollbar->scale_to_parent();
1548 if(delegate->internal_layout.number_of_lines > delegate->visible_lines) {
1549 text_scrollbar->set_visible(
state,
true);
1550 text_scrollbar->change_settings(
state,
1553 text_scrollbar->set_visible(
state,
false);
1554 delegate->current_line = 0;
1559 if(delegate->internal_layout.number_of_lines > delegate->visible_lines) {
1560 text_scrollbar->update_scaled_value(
state, text_scrollbar->scaled_value() + std::clamp(-amount, -1.f, 1.f));
1561 delegate->current_line = int32_t(text_scrollbar->scaled_value());
1562 return message_result::consumed;
1564 return message_result::unseen;
1569 auto event = any_cast<multiline_text_scroll_event>(payload);
1570 delegate->current_line =
event.new_value;
1571 return message_result::consumed;
1573 return message_result::unseen;
1577template<
class RowWinT,
class RowConT>
1588 return message_result::unseen;
1592template<
class RowConT>
1594 if(payload.holds_type<RowConT>()) {
1595 payload.emplace<RowConT>(content);
1596 return message_result::consumed;
1598 content = any_cast<wrapped_listbox_row_content<RowConT>>(payload).content;
1599 impl_on_update(
state);
1600 return message_result::consumed;
1602 return message_result::unseen;
1605template<
class RowConT>
1607 if(payload.holds_type<RowConT>()) {
1608 payload.emplace<RowConT>(content);
1609 return message_result::consumed;
1611 content = any_cast<wrapped_listbox_row_content<RowConT>>(payload).content;
1613 return message_result::consumed;
1615 return message_result::unseen;
1618template<
class RowWinT,
class RowConT>
1620 auto content_off_screen = int32_t(row_contents.size() - row_windows.size());
1621 int32_t scroll_pos = list_scrollbar->raw_value();
1622 if(content_off_screen <= 0) {
1623 list_scrollbar->set_visible(
state,
false);
1627 list_scrollbar->set_visible(
state,
true);
1628 scroll_pos = std::min(scroll_pos, content_off_screen);
1632 auto i = int32_t(row_contents.size()) - scroll_pos - 1;
1633 for(int32_t rw_i = int32_t(row_windows.size()) - 1; rw_i >= 0; rw_i--) {
1634 RowWinT* row_window = row_windows[size_t(rw_i)];
1636 row_window->set_visible(
state,
true);
1637 auto prior_content = retrieve<RowConT>(
state, row_window);
1638 auto new_content = row_contents[i--];
1640 if(prior_content != new_content) {
1642 if(!row_window->is_visible()) {
1643 row_window->set_visible(
state,
true);
1645 row_window->impl_on_update(
state);
1648 row_window->set_visible(
state,
true);
1651 row_window->set_visible(
state,
false);
1655 auto i = size_t(scroll_pos);
1656 for(RowWinT* row_window : row_windows) {
1657 if(i < row_contents.size()) {
1658 auto prior_content = retrieve<RowConT>(
state, row_window);
1659 auto new_content = row_contents[i++];
1661 if(prior_content != new_content) {
1663 if(!row_window->is_visible()) {
1664 row_window->set_visible(
state,
true);
1666 row_window->impl_on_update(
state);
1669 row_window->set_visible(
state,
true);
1672 row_window->set_visible(
state,
false);
1678template<
class RowWinT,
class RowConT>
1680 if(row_contents.size() > row_windows.size()) {
1681 amount = is_reversed() ? -amount : amount;
1682 list_scrollbar->update_raw_value(
state, list_scrollbar->raw_value() + (amount < 0 ? 1 : -1));
1685 return message_result::consumed;
1687 return message_result::unseen;
1690template<
class RowWinT,
class RowConT>
1693 for(
auto rc : row_contents) {
1696 list_scrollbar->update_raw_value(
state, list_size);
1701template<
typename contents_type>
1703 if(int32_t(row_contents.size()) > visible_row_count) {
1705 list_scrollbar->update_raw_value(
state, list_scrollbar->raw_value() + (amount < 0 ? 1 : -1));
1706 impl_on_update(
state);
1707 return message_result::consumed;
1709 return message_result::unseen;
1712template<
typename contents_type>
1714 auto content_off_screen = int32_t(row_contents.size()) - visible_row_count;
1715 int32_t scroll_pos = list_scrollbar->raw_value();
1717 if(content_off_screen <= 0) {
1719 list_scrollbar->update_raw_value(
state, 0);
1722 for(; i < int32_t(row_contents.size()); ++i) {
1723 row_windows[i]->set_visible(
state,
true);
1725 for(; i < int32_t(row_windows.size()); ++i) {
1726 row_windows[i]->set_visible(
state,
false);
1730 list_scrollbar->set_visible(
state,
true);
1731 scroll_pos = std::min(scroll_pos, content_off_screen);
1734 for(; i < visible_row_count; ++i) {
1735 row_windows[i]->set_visible(
state,
true);
1737 for(; i < int32_t(row_windows.size()); ++i) {
1738 row_windows[i]->set_visible(
state,
false);
1743template<
typename contents_type>
1746 impl_on_update(
state);
1747 return message_result::consumed;
1750 for(int32_t index = 0; index < int32_t(row_windows.size()); ++index) {
1751 if(row_windows[index] == ptr.
row) {
1752 stored_index = index + list_scrollbar->raw_value();
1753 return message_result::consumed;
1757 return message_result::consumed;
1758 }
else if(payload.holds_type<contents_type>()) {
1759 if(0 <= stored_index && stored_index < int32_t(row_contents.size())) {
1760 payload = row_contents[stored_index];
1762 return message_result::consumed;
1764 return message_result::unseen;
1768template<
typename contents_type>
1770 int32_t
row_height = row_windows[0]->base_data.position.y + row_windows[0]->base_data.size.y;
1771 int32_t height_covered = int32_t(row_windows.size()) *
row_height;
1772 int32_t required_rows = (height - height_covered) /
row_height;
1774 while(required_rows > 0) {
1775 auto new_row = make_row(
state);
1776 row_windows.push_back(new_row.get());
1777 new_row->base_data.position.y += int16_t(height_covered);
1778 add_child_to_back(std::move(new_row));
1785 base_data.size.y = int16_t(
row_height * visible_row_count);
1787 if(visible_row_count != 0) {
1788 if(scrollbar_is_internal)
1789 base_data.size.x -= 16;
1790 list_scrollbar->scale_to_parent();
1791 if(scrollbar_is_internal)
1792 base_data.size.x += 16;
1796template<
typename contents_type>
1798 auto ptr = make_element_by_type<listbox2_scrollbar>(
state,
"standardlistbox_slider");
1800 add_child_to_back(std::move(ptr));
1802 auto base_row = make_row(
state);
1803 row_windows.push_back(base_row.get());
1804 add_child_to_back(std::move(base_row));
1806 resize(
state, base_data.size.y);
1808template<
typename contents_type>
1810 dcon::gfx_object_id gid = base_data.data.list_box.background_image;
1812 auto const& gfx_def =
state.ui_defs.gfx[gid];
1813 if(gfx_def.primary_texture_handle) {
1816 float(base_data.size.x),
float(base_data.size.y),
1818 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
1819 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
1822 float(base_data.size.y),
1824 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
1825 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
1829 container_base::render(
state, x, y);
1832template<
class RowWinT,
class RowConT>
1834 int16_t current_y = 0;
1835 int16_t subwindow_y_size = 0;
1836 while(current_y + subwindow_y_size <= base_data.size.y) {
1837 auto ptr = make_element_by_type<RowWinT>(
state, get_row_element_name());
1838 row_windows.push_back(
static_cast<RowWinT*
>(ptr.get()));
1839 int16_t offset = ptr->base_data.position.y;
1840 ptr->base_data.position.y += current_y;
1841 subwindow_y_size = ptr->base_data.size.y;
1842 current_y += ptr->base_data.size.y + offset;
1843 add_child_to_front(std::move(ptr));
1845 auto ptr = make_element_by_type<standard_listbox_scrollbar<RowWinT, RowConT>>(
state,
"standardlistbox_slider");
1847 add_child_to_front(std::move(ptr));
1848 list_scrollbar->scale_to_parent();
1853template<
class RowWinT,
class RowConT>
1855 dcon::gfx_object_id gid = base_data.data.list_box.background_image;
1857 auto const& gfx_def =
state.ui_defs.gfx[gid];
1858 if(gfx_def.primary_texture_handle) {
1861 float(base_data.size.x),
float(base_data.size.y),
1863 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
1864 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
1867 float(base_data.size.y),
1869 base_data.get_rotation(), gfx_def.is_vertically_flipped(),
1870 state.world.locale_get_native_rtl(
state.font_collection.get_current_locale()));
1874 container_base::render(
state, x, y);
1876template<
class ItemWinT,
class ItemConT>
1878 auto spacing = int16_t(base_data.data.overlapping.spacing);
1879 if(base_data.get_element_type() == element_type::overlapping) {
1880 while(row_contents.size() > windows.size()) {
1881 auto ptr = make_element_by_type<ItemWinT>(
state, get_row_element_name());
1882 if(subwindow_width <= 0) {
1883 subwindow_width = ptr->base_data.size.x;
1885 windows.push_back(
static_cast<ItemWinT*
>(ptr.get()));
1886 add_child_to_front(std::move(ptr));
1889 float size_ratio = float(row_contents.size() * (subwindow_width + spacing)) / float(base_data.size.x);
1890 int16_t offset = spacing + subwindow_width;
1891 if(size_ratio > 1.f) {
1892 offset = int16_t(
float(subwindow_width) / size_ratio);
1894 int16_t current_x = 0;
1895 if(base_data.data.overlapping.image_alignment == alignment::right) {
1896 current_x = base_data.size.x - subwindow_width - offset * int16_t(row_contents.size() - 1);
1898 for(
size_t i = 0; i < windows.size(); i++) {
1899 if(i < row_contents.size()) {
1900 update_subwindow(
state, *windows[i], row_contents[i]);
1901 windows[i]->base_data.position.x = current_x;
1902 current_x += offset;
1903 windows[i]->set_visible(
state,
true);
1905 windows[i]->set_visible(
state,
false);
1911std::string_view overlapping_flags_box::get_row_element_name() {
1912 return "flag_list_flag";
1916 dcon::national_identity_id content) {
1921 current_nation = retrieve<dcon::nation_id>(
state, parent);
1922 populate_flags(
state);
1926 if(
bool(current_nation)) {
1927 row_contents.clear();
1928 for(
auto it :
state.world.nation_get_gp_relationship_as_great_power(current_nation)) {
1930 row_contents.push_back(it.get_influence_target().get_identity_from_identity_holder());
1938 if(
bool(current_nation)) {
1939 row_contents.clear();
1940 for(
auto it :
state.world.nation_get_gp_relationship_as_great_power(current_nation)) {
1942 row_contents.push_back(it.get_influence_target().get_identity_from_identity_holder());
1950 if(
bool(current_nation)) {
1951 row_contents.clear();
1952 if(
state.world.nation_get_in_sphere_of(current_nation)) {
1953 row_contents.push_back(
state.world.nation_get_in_sphere_of(current_nation).get_identity_from_identity_holder());
1955 for(
auto it :
state.world.nation_get_gp_relationship_as_great_power(current_nation)) {
1957 row_contents.push_back(it.get_influence_target().get_identity_from_identity_holder());
1965 if(
bool(current_nation)) {
1966 row_contents.clear();
1968 auto overlord =
state.world.nation_get_overlord_as_subject(current_nation);
1970 if(
bool(overlord_nation)) {
1971 row_contents.push_back(overlord_nation.get_identity_from_identity_holder().id);
1973 for(
auto puppet :
state.world.nation_get_overlord_as_ruler(current_nation)) {
1974 row_contents.push_back(puppet.get_subject().get_identity_from_identity_holder().id);
1982 if(
bool(current_nation)) {
1983 row_contents.clear();
1984 for(
auto rel :
state.world.nation_get_diplomatic_relation(current_nation)) {
1985 if(rel.get_are_allied()) {
1988 row_contents.push_back(fat_ally.get_identity_from_identity_holder().id);
1996 if(
bool(current_nation)) {
1997 row_contents.clear();
1998 for(
auto wa :
state.world.nation_get_war_participant(current_nation)) {
1999 bool is_attacker = wa.get_is_attacker();
2000 for(
auto o : wa.get_war().get_war_participant()) {
2001 if(o.get_is_attacker() != is_attacker) {
2002 row_contents.push_back(o.get_nation().get_identity_from_identity_holder().id);
2011std::string_view overlapping_truce_flags::get_row_element_name() {
2012 return "flag_list_flag";
2025 current_nation = retrieve<dcon::nation_id>(
state, parent);
2027 row_contents.clear();
2028 for(
auto rel :
state.world.nation_get_diplomatic_relation(current_nation)) {
2029 if(rel.get_truce_until() &&
state.current_date < rel.get_truce_until()) {
2030 auto other = rel.get_related_nations(0) != current_nation ? rel.get_related_nations(0) : rel.get_related_nations(1);
2032 row_contents.push_back(
truce_pair{ other, rel.get_truce_until() });
2041 auto nation = retrieve<dcon::national_identity_id>(
state, parent);
2045 return state.world.nation_get_identity_from_identity_holder(retrieve<dcon::nation_id>(
state, parent));
2049dcon::rebel_faction_id flag_button::get_current_rebel_faction(
sys::state&
state)
noexcept {
2050 return retrieve<dcon::rebel_faction_id>(
state, parent);
2059 auto nation = fat_id.get_nation_from_identity_holder();
2060 if(
bool(nation.id) && nation.get_owned_province_count() != 0) {
2061 state.open_diplomacy(nation.id);
2066 auto nid = retrieve<dcon::nation_id>(
state,
this);
2067 auto tid = retrieve<dcon::national_identity_id>(
state,
this);
2069 nid =
state.world.national_identity_get_nation_from_identity_holder(tid);
2071 auto rid = retrieve<dcon::rebel_faction_id>(
state,
this);
2073 nid =
state.world.rebel_faction_get_ruler_from_rebellion_within(rid);
2075 if(nid &&
state.world.nation_get_owned_province_count(nid) != 0)
2076 state.open_diplomacy(nid);
2080 auto nid = retrieve<dcon::nation_id>(
state,
this);
2086 auto tid = retrieve<dcon::national_identity_id>(
state,
this);
2092 auto rid = retrieve<dcon::rebel_faction_id>(
state,
this);
2093 if(!nid && !tid && rid) {
2098 auto reb_tag =
state.national_definitions.rebel_id;
2103 auto nid = retrieve<dcon::nation_id>(
state,
this);
2110 auto tid = retrieve<dcon::national_identity_id>(
state,
this);
2117 auto rid = retrieve<dcon::rebel_faction_id>(
state,
this);
2127 dcon::gfx_object_id gid;
2128 if(base_data.get_element_type() == element_type::image) {
2129 gid = base_data.data.image.gfx_object;
2130 }
else if(base_data.get_element_type() == element_type::button) {
2131 gid = base_data.data.button.button_image;
2133 if(gid && flag_texture_handle > 0) {
2134 auto const& gfx_def =
state.ui_defs.gfx[gid];
2135 if(gfx_def.type_dependent) {
2137 auto& mask_tex =
state.open_gl.asset_textures[dcon::texture_id(gfx_def.type_dependent - 1)];
2139 float(x) +
float(base_data.size.x - mask_tex.size_x) * 0.5f,
2140 float(y) +
float(base_data.size.y - mask_tex.size_y) * 0.5f,
2141 float(mask_tex.size_x),
2142 float(mask_tex.size_y),
2143 flag_texture_handle, mask_handle, base_data.get_rotation(), gfx_def.is_vertically_flipped(),
2147 float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y), flag_texture_handle, base_data.get_rotation(),
2148 gfx_def.is_vertically_flipped(),
2152 image_element_base::render(
state, x, y);
2160 auto nation = fat_id.get_nation_from_identity_holder();
2162 if(
bool(nation.id) && nation.get_owned_province_count() != 0) {
2171 set_current_nation(
state, get_current_nation(
state));
2175 button_element_base::on_create(
state);
2179 dcon::gfx_object_id gid;
2180 if(base_data.get_element_type() == element_type::image) {
2181 gid = base_data.data.image.gfx_object;
2182 }
else if(base_data.get_element_type() == element_type::button) {
2183 gid = base_data.data.button.button_image;
2185 if(gid && flag_texture_handle > 0) {
2186 auto const& gfx_def =
state.ui_defs.gfx[gid];
2187 if(gfx_def.type_dependent) {
2189 auto& mask_tex =
state.open_gl.asset_textures[dcon::texture_id(gfx_def.type_dependent - 1)];
2191 float(x) +
float(base_data.size.x - mask_tex.size_x) * 0.5f,
2192 float(y) +
float(base_data.size.y - mask_tex.size_y) * 0.5f,
2193 float(mask_tex.size_x),
2194 float(mask_tex.size_y),
2195 flag_texture_handle, mask_handle, base_data.get_rotation(), gfx_def.is_vertically_flipped(),
2199 float(x),
float(y),
float(base_data.size.x),
float(base_data.size.y), flag_texture_handle, base_data.get_rotation(),
2200 gfx_def.is_vertically_flipped(),
2204 image_element_base::render(
state, x, y);
2216 if(
auto reb = get_current_rebel_faction(
state); reb) {
2226 auto p = retrieve<dcon::province_id>(
state, parent);
2227 if(p &&
state.local_player_nation)
2232 auto& def =
state.ui_defs.gui[base_definition];
2241 auto p = retrieve<dcon::province_id>(
state, parent);
2249 auto& def =
state.ui_defs.gui[base_definition];
2255 auto p = retrieve<dcon::province_id>(
state, parent);
2258 if(!
state.local_player_nation)
2261 auto name =
state.to_string_view(def.name);
2262 auto tt_name = std::string{
name } +
"_tooltip";
2263 if(
state.key_is_localized(tt_name)) {
2268 if(def.data.button.scriptable_enable) {
2273 if(def.data.button.scriptable_effect) {
2279 auto n = retrieve<dcon::nation_id>(
state, parent);
2280 if(n &&
state.local_player_nation) {
2282 }
else if(
state.local_player_nation) {
2288 auto& def =
state.ui_defs.gui[base_definition];
2297 auto n = retrieve<dcon::nation_id>(
state, parent);
2298 if(!
state.local_player_nation) {
2305 auto& def =
state.ui_defs.gui[base_definition];
2311 auto n = retrieve<dcon::nation_id>(
state, parent);
2313 n =
state.local_player_nation;
2314 if(!
state.local_player_nation)
2317 auto name =
state.to_string_view(def.name);
2318 auto tt_name = std::string{
name } +
"_tooltip";
2319 if(
state.key_is_localized(tt_name)) {
2324 if(def.data.button.scriptable_enable) {
2329 if(def.data.button.scriptable_effect) {
2336 for(
auto tmp = parent; tmp !=
nullptr; tmp = tmp->parent) {
2337 if(tmp->base_data.get_element_type() == element_type::window && tmp->base_data.data.window.is_moveable()) {
2339 return message_result::consumed;
2342 return message_result::consumed;
2346 auto& def =
state.ui_defs.gui[id];
2348 auto res = std::make_unique<image_element_base>();
2351 res->on_create(
state);
2355 auto res = std::make_unique<province_script_button>(
id);
2358 res->on_create(
state);
2361 auto res = std::make_unique<nation_script_button>(
id);
2364 res->on_create(
state);
2367 auto res = std::make_unique<button_element_base>();
2370 res->on_create(
state);
2374 auto res = std::make_unique<window_element_base>();
2376 res->on_create(
state);
2379 auto res = std::make_unique<scrollbar>();
2381 res->on_create(
state);
2384 auto res = std::make_unique<simple_text_element_base>();
2386 res->on_create(
state);
2397 parent->impl_on_drag_finish(
state);
2403 parent->impl_on_drag_finish(
state);
2409 parent->impl_on_drag_finish(
state);
2415 parent->impl_on_drag_finish(
state);
2421 parent->impl_on_drag_finish(
state);
2427 parent->impl_on_drag_finish(
state);
2433 return message_result::consumed;
2435 return message_result::unseen;
2439 return message_result::consumed;
2441 return message_result::unseen;
2446 int32_t pos_in_track = parent_state.
vertical ? y : x;
2449 if(!parent_state.
vertical &&
state.world.locale_get_native_rtl(
state.font_collection.get_current_locale())) {
2450 fp_pos = 1.f - fp_pos;
2451 assert(fp_pos >= 0.f && fp_pos <= 1.f);
2454 return message_result::consumed;
2459 return parent->has_tooltip(
state);
2460 return opaque_element_base::has_tooltip(
state);
2464 return parent->update_tooltip(
state, x, y, contents);
2465 return opaque_element_base::update_tooltip(
state, x, y, contents);
2470 return message_result::consumed;
2479 if(!(location_abs.y <= oldy && oldy < base_data.size.y + location_abs.y)) {
2483 if(!(location_abs.x <= oldx && oldx < base_data.size.x + location_abs.x)) {
2488 int32_t pos_in_track = 0;
2499 base_data.position.y += int16_t(y - oldy);
2501 pos_in_track = base_data.position.y - parent_settings.
buttons_size / 2;
2503 if(
state.world.locale_get_native_rtl(
state.font_collection.get_current_locale())) {
2504 base_data.position.x += int16_t(oldx - x);
2506 base_data.position.x += int16_t(x - oldx);
2509 pos_in_track = base_data.position.x - parent_settings.
buttons_size / 2;
2514 parent->impl_get(
state, adjustment_payload);
2518 stored_value = settings.using_limits ? std::clamp(v, settings.lower_limit, settings.upper_limit) : std::clamp(v, settings.lower_value, settings.upper_value);
2520 float percentage = float(stored_value - settings.lower_value) / float(settings.upper_value - settings.lower_value);
2521 auto offset = settings.buttons_size + int32_t((settings.track_size - settings.buttons_size) * percentage);
2523 if(settings.vertical)
2524 slider->base_data.position.y = int16_t(offset);
2526 slider->base_data.position.x = int16_t(offset);
2530 float scaling_factor = float(settings.scaling_factor);
2533 scaling_factor = 0.25f;
2535 int32_t rv = std::clamp(int32_t(v * scaling_factor), settings.lower_value, settings.upper_value);
2536 update_raw_value(
state, rv);
2538float scrollbar::scaled_value()
const {
2539 return float(stored_value) / float(settings.scaling_factor);
2541int32_t scrollbar::raw_value()
const {
2542 return stored_value;
2546 settings.lower_limit = settings_s.
lower_limit * settings.scaling_factor;
2547 settings.lower_value = settings_s.
lower_value * settings.scaling_factor;
2548 settings.upper_limit = settings_s.
upper_limit * settings.scaling_factor;
2549 settings.upper_value = settings_s.
upper_value * settings.scaling_factor;
2552 settings.upper_value = std::max(settings.upper_value, settings.lower_value + 1);
2554 if(settings.using_limits) {
2556 right_limit->set_visible(
state, settings.lower_value < settings.lower_limit);
2558 float percentage = float(settings.lower_limit - settings.lower_value) / float(settings.upper_value - settings.lower_value);
2559 auto offset = settings.buttons_size + int32_t((settings.track_size - settings.buttons_size) * percentage);
2560 if(settings.vertical)
2561 right_limit->base_data.position.y = int16_t(offset);
2563 right_limit->base_data.position.x = int16_t(offset);
2566 left_limit->set_visible(
state, settings.upper_value > settings.upper_limit);
2568 float percentage = float(settings.upper_limit - settings.lower_value) / float(settings.upper_value - settings.lower_value);
2569 auto offset = settings.buttons_size + int32_t((settings.track_size - settings.buttons_size) * percentage);
2570 if(settings.vertical)
2571 left_limit->base_data.position.y = int16_t(offset + settings.buttons_size - 10);
2573 left_limit->base_data.position.x = int16_t(offset + settings.buttons_size - 10);
2575 if(stored_value < settings.lower_limit || stored_value > settings.upper_limit) {
2576 update_raw_value(
state, stored_value);
2581 right_limit->set_visible(
state,
false);
2583 left_limit->set_visible(
state,
false);
2584 if(stored_value < settings.lower_value || stored_value > settings.upper_value) {
2585 update_raw_value(
state, stored_value);
2596 if(base_data.get_element_type() == element_type::scrollbar) {
2597 auto step = base_data.data.scrollbar.get_step_size();
2598 settings.scaling_factor = 1;
2600 case step_size::twenty_five:
2602 case step_size::two:
2604 case step_size::one:
2606 case step_size::one_tenth:
2607 settings.scaling_factor = 10;
2609 case step_size::one_hundredth:
2610 settings.scaling_factor = 100;
2612 case step_size::one_thousandth:
2613 settings.scaling_factor = 1000;
2616 settings.lower_value = 0;
2617 settings.upper_value = base_data.data.scrollbar.max_value * settings.scaling_factor;
2618 settings.lower_limit = 0;
2619 settings.upper_limit = settings.upper_value;
2621 settings.vertical = !base_data.data.scrollbar.is_horizontal();
2622 stored_value = settings.lower_value;
2624 auto first_child = base_data.data.scrollbar.first_child;
2625 auto num_children = base_data.data.scrollbar.num_children;
2627 if(num_children >= 6) {
2628 auto child_tag = dcon::gui_def_id(dcon::gui_def_id::value_base_t(5 + first_child.index()));
2629 auto ch_res = make_element_by_type<image_element_base>(
state, child_tag);
2630 right_limit = ch_res.get();
2631 right_limit->set_visible(
state,
false);
2632 add_child_to_back(std::move(ch_res));
2634 if(num_children >= 5) {
2635 auto child_tag = dcon::gui_def_id(dcon::gui_def_id::value_base_t(4 + first_child.index()));
2636 auto ch_res = make_element_by_type<image_element_base>(
state, child_tag);
2637 left_limit = ch_res.get();
2638 left_limit->set_visible(
state,
false);
2639 add_child_to_back(std::move(ch_res));
2642 if(num_children >= 4) {
2644 auto child_tag = dcon::gui_def_id(dcon::gui_def_id::value_base_t(2 + first_child.index()));
2645 auto ch_res = make_element_by_type<scrollbar_slider>(
state, child_tag);
2646 slider = ch_res.get();
2647 add_child_to_back(std::move(ch_res));
2650 auto child_tag = dcon::gui_def_id(dcon::gui_def_id::value_base_t(0 + first_child.index()));
2651 auto ch_res = make_element_by_type<scrollbar_left>(
state, child_tag);
2652 left = ch_res.get();
2653 add_child_to_back(std::move(ch_res));
2655 settings.buttons_size = settings.vertical ?
left->base_data.size.y :
left->base_data.size.x;
2656 if(step_size::twenty_five == step)
2657 left->step_size = 25;
2658 else if(step_size::two == step)
2659 left->step_size = 2;
2661 left->step_size = 1;
2664 auto child_tag = dcon::gui_def_id(dcon::gui_def_id::value_base_t(1 + first_child.index()));
2665 auto ch_res = make_element_by_type<scrollbar_right>(
state, child_tag);
2666 right = ch_res.get();
2667 add_child_to_back(std::move(ch_res));
2669 if(step_size::twenty_five == step)
2670 right->step_size = 25;
2671 else if(step_size::two == step)
2672 right->step_size = 2;
2674 right->step_size = 1;
2677 auto child_tag = dcon::gui_def_id(dcon::gui_def_id::value_base_t(3 + first_child.index()));
2678 auto ch_res = make_element_by_type<scrollbar_track>(
state, child_tag);
2679 track = ch_res.get();
2680 add_child_to_back(std::move(ch_res));
2682 settings.track_size = settings.vertical ? track->base_data.size.y : track->base_data.size.x;
2684 left->base_data.position.x = 0;
2685 left->base_data.position.y = 0;
2686 if(settings.vertical) {
2687 track->base_data.position.y = int16_t(settings.buttons_size);
2688 slider->base_data.position.y = int16_t(settings.buttons_size);
2689 right->base_data.position.y = int16_t(settings.track_size + settings.buttons_size);
2691 slider->base_data.position.x = 0;
2692 right->base_data.position.x = 0;
2694 track->base_data.position.x = int16_t(settings.buttons_size);
2695 slider->base_data.position.x = int16_t(settings.buttons_size);
2696 right->base_data.position.x = int16_t(settings.track_size + settings.buttons_size);
2698 slider->base_data.position.y = 0;
2699 right->base_data.position.y = 0;
2706 parent->impl_on_drag_finish(
state);
2711 settings.track_size = track ? int32_t(settings.vertical ? track->base_data.size.y : track->base_data.size.x) : 1;
2713 return message_result::consumed;
2715 auto adjustments = any_cast<value_change>(payload);
2717 if(adjustments.is_relative)
2718 stored_value += adjustments.new_value;
2720 stored_value = adjustments.new_value;
2722 if(adjustments.move_slider) {
2723 update_raw_value(
state, stored_value);
2725 stored_value = settings.using_limits ? std::clamp(stored_value, settings.lower_limit, settings.upper_limit)
2726 : std::clamp(stored_value, settings.lower_value, settings.upper_value);
2729 if(adjustments.move_slider ==
true && adjustments.is_relative ==
false && !
state.ui_state.
drag_target) {
2733 on_value_change(
state, stored_value);
2734 return message_result::unseen;
2736 return message_result::unseen;
2741 auto display_unit = retrieve< unit_var>(
state, parent);
2742 if(std::holds_alternative<dcon::army_id>(display_unit))
2744 else if(std::holds_alternative<dcon::navy_id>(display_unit))
2757 static const std::string_view key_names[] = {
2762 "Multimedia button",
2900 "Navigation Accept",
2901 "Navigation Cancel",
ANY_ALWAYS_INLINE bool holds_type() const noexcept
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void move_child_to_back(element_base *child) noexcept final
void impl_render(sys::state &state, int32_t x, int32_t y) noexcept override
message_result impl_set(sys::state &state, Cyto::Any &payload) noexcept final
void add_child_to_back(std::unique_ptr< element_base > child) noexcept final
std::unique_ptr< element_base > remove_child(element_base *child) noexcept final
void impl_on_reset_text(sys::state &state) noexcept override
void add_child_to_front(std::unique_ptr< element_base > child) noexcept final
mouse_probe impl_probe_mouse(sys::state &state, int32_t x, int32_t y, mouse_probe_type type) noexcept override
void move_child_to_front(element_base *child) noexcept final
element_base * get_child_by_name(sys::state const &state, std::string_view name) noexcept final
message_result impl_on_key_down(sys::state &state, sys::virtual_key key, sys::key_modifiers mods) noexcept final
void impl_on_update(sys::state &state) noexcept override
element_base * get_child_by_index(sys::state const &state, int32_t index) noexcept final
static constexpr dcon::texture_id small_tiles_dialog
static constexpr dcon::texture_id tiles_dialog
static constexpr dcon::texture_id transparency
void on_update(sys::state &state) noexcept override
void on_create(sys::state &state) noexcept override
message_result on_key_down(sys::state &state, sys::virtual_key key, sys::key_modifiers mods) noexcept override
void on_reset_text(sys::state &state) noexcept override
message_result on_lbutton_down(sys::state &state, int32_t x, int32_t y, sys::key_modifiers mods) noexcept override
void render(sys::state &state, int32_t x, int32_t y) noexcept override
static constexpr uint8_t is_invisible_mask
virtual message_result get(sys::state &state, Cyto::Any &payload) noexcept
static constexpr uint8_t wants_update_when_hidden_mask
virtual void impl_render(sys::state &state, int32_t x, int32_t y) noexcept
virtual message_result impl_on_key_down(sys::state &state, sys::virtual_key key, sys::key_modifiers mods) noexcept
virtual void on_create(sys::state &state) noexcept
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
friend void sys::state::on_text(char32_t c)
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void on_create(sys::state &state) noexcept override
void on_create(sys::state &state) noexcept override
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void set_data_points(sys::state &state, std::vector< float > const &datapoints) noexcept
message_result on_lbutton_down(sys::state &state, int32_t x, int32_t y, sys::key_modifiers mods) noexcept override
message_result on_rbutton_down(sys::state &state, int32_t x, int32_t y, sys::key_modifiers mods) noexcept override
void on_create(sys::state &state) noexcept override
message_result test_mouse(sys::state &state, int32_t x, int32_t y, mouse_probe_type type) noexcept override
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void on_reset_text(sys::state &state) noexcept override
message_result impl_set(sys::state &state, Cyto::Any &payload) noexcept final
message_result impl_on_key_down(sys::state &state, sys::virtual_key key, sys::key_modifiers mods) noexcept final
void impl_on_reset_text(sys::state &state) noexcept override
mouse_probe impl_probe_mouse(sys::state &state, int32_t x, int32_t y, mouse_probe_type type) noexcept override
void move_child_to_front(element_base *child) noexcept final
element_base * get_child_by_index(sys::state const &state, int32_t index) noexcept final
void move_child_to_back(element_base *child) noexcept final
void impl_render(sys::state &state, int32_t x, int32_t y) noexcept override
void impl_on_update(sys::state &state) noexcept override
virtual void populate_tooltip(sys::state &state, T t, float percentage, text::columnar_layout &contents) noexcept
void update_chart(sys::state &state)
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void on_create(sys::state &state) noexcept override
void update_tooltip(sys::state &state, int32_t x, int32_t y, text::columnar_layout &contents) noexcept override
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void on_create(sys::state &state) noexcept override
void on_reset_text(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 render(sys::state &state, int32_t x, int32_t y) noexcept override
void on_create(sys::state &state) noexcept override
void set_text(sys::state &state, std::string const &new_text)
void on_reset_text(sys::state &state) noexcept override
text::layout internal_layout
void format_text(sys::state &state)
void render(sys::state &state, int32_t x, int32_t y) noexcept override
void on_create(sys::state &state) noexcept override
void on_drag(sys::state &state, int32_t oldx, int32_t oldy, int32_t x, int32_t y, sys::key_modifiers mods) noexcept override
#define assert(condition)
void use_nation_button(sys::state &state, dcon::nation_id source, dcon::gui_def_id d, dcon::nation_id n)
bool can_use_province_button(sys::state &state, dcon::nation_id source, dcon::gui_def_id d, dcon::province_id p)
void use_province_button(sys::state &state, dcon::nation_id source, dcon::gui_def_id d, dcon::province_id i)
bool can_use_nation_button(sys::state &state, dcon::nation_id source, dcon::gui_def_id d, dcon::nation_id n)
flag_type get_current_flag_type(sys::state const &state, dcon::nation_id target_nation)
pop_satisfaction_wrapper_fat fatten(data_container const &c, pop_satisfaction_wrapper_id id) noexcept
constexpr float zoom_very_close
bool are_at_war(sys::state const &state, dcon::nation_id a, dcon::nation_id b)
constexpr uint8_t level_friendly
constexpr uint8_t level_in_sphere
constexpr uint8_t level_mask
constexpr uint8_t level_cordial
dcon::nation_id get_relationship_partner(sys::state const &state, dcon::diplomatic_relation_id rel_id, dcon::nation_id query)
dcon::text_key name_from_tag(sys::state &state, dcon::national_identity_id tag)
void render_tinted_subsprite(sys::state const &state, int frame, int total_frames, float x, float y, float width, float height, float r, float g, float b, GLuint texture_handle, ui::rotation rot, bool flipped, bool rtl)
void render_bordered_rect(sys::state const &state, color_modification enabled, float border_size, float x, float y, float width, float height, GLuint texture_handle, ui::rotation r, bool flipped, bool rtl)
void render_piechart(sys::state const &state, color_modification enabled, float x, float y, float size, data_texture &t)
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)
GLuint get_rebel_flag_handle(sys::state &state, dcon::rebel_faction_id faction)
void render_text_commodity_icon(sys::state &state, text::embedded_commodity_icon ico, float x, float baseline_y, float font_size, text::font &f)
void render_subsprite(sys::state const &state, color_modification enabled, int frame, int total_frames, float x, float y, float width, float height, GLuint texture_handle, ui::rotation r, bool flipped, bool rtl)
void render_text(sys::state &state, text::stored_glyphs const &txt, color_modification enabled, float x, float y, color3f const &c, uint16_t font_id)
void render_linegraph(sys::state const &state, color_modification enabled, float x, float y, float width, float height, lines &l)
void render_text_flag(sys::state &state, text::embedded_flag ico, float x, float baseline_y, float font_size, text::font &f, ogl::color_modification cmod)
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)
void render_text_icon(sys::state &state, text::embedded_icon ico, float x, float baseline_y, float font_size, text::font &f, ogl::color_modification cmod)
void render_tinted_textured_rect(sys::state const &state, float x, float y, float width, float height, float r, float g, float b, GLuint texture_handle, ui::rotation rot, bool flipped, bool rtl)
void render_text_unit_icon(sys::state &state, text::embedded_unit_icon ico, float x, float baseline_y, float font_size, text::font &f, ogl::color_modification cmod)
void render_progress_bar(sys::state const &state, color_modification enabled, float progress, float x, float y, float width, float height, GLuint left_texture_handle, GLuint right_texture_handle, ui::rotation r, bool flipped, bool rtl)
GLuint get_flag_handle(sys::state &state, dcon::national_identity_id nat_id, culture::flag_type type)
std::string lowercase_str(std::string_view sv)
std::string rebel_name(sys::state &state, dcon::rebel_faction_id reb)
std::string native_to_utf8(native_string_view data_in)
void play_interface_sound(sys::state &state, audio_instance &s, float volume)
audio_instance & get_click_sound(sys::state &state)
float blue_from_int(uint32_t v)
float green_from_int(uint32_t v)
uint32_t pack_color(float r, float g, float b)
float red_from_int(uint32_t v)
void add_to_layout_box(sys::state &state, layout_base &dest, layout_box &box, embedded_flag ico)
int32_t size_from_font_id(uint16_t id)
layout_box open_layout_box(layout_base &dest, int32_t indent)
bool is_black_from_font_id(uint16_t id)
void add_line(sys::state &state, layout_base &dest, dcon::text_key txt, int32_t indent)
void add_line_break_to_layout(sys::state &state, columnar_layout &dest)
text::alignment to_text_alignment(ui::alignment in)
ankerl::unordered_dense::map< uint32_t, substitution > substitution_map
std::string produce_simple_string(sys::state const &state, dcon::text_key id)
dcon::text_key get_name(sys::state &state, dcon::nation_id id)
font_selection font_index_from_font_id(sys::state &state, uint16_t id)
std::string format_percentage(float num, size_t digits)
void add_space_to_layout_box(sys::state &state, layout_base &dest, layout_box &box)
void close_layout_box(columnar_layout &dest, layout_box &box)
int32_t to_generic(dcon::province_id v)
int32_t ui_height(sys::state const &state)
void make_size_from_graphics(sys::state &state, ui::element_data &dat)
xy_pair child_relative_location(sys::state &state, element_base const &parent, element_base const &child)
uint32_t internal_get_interactable_disabled_color(float r, float g, float b)
uint32_t internal_get_disabled_color(float r, float g, float b)
void effect_description(sys::state &state, text::layout_base &layout, dcon::effect_key k, int32_t primary_slot, int32_t this_slot, int32_t from_slot, uint32_t r_lo, uint32_t r_hi)
int32_t ui_width(sys::state const &state)
void render_text_chunk(sys::state &state, text::text_chunk t, float x, float baseline_y, uint16_t font_id, ogl::color3f text_color, ogl::color_modification cmod)
void populate_shortcut_tooltip(sys::state &state, ui::element_base &elm, text::columnar_layout &contents) noexcept
xy_pair get_absolute_location(sys::state &state, element_base const &node)
void send(sys::state &state, element_base *parent, T value)
void trigger_description(sys::state &state, text::layout_base &layout, dcon::trigger_key k, int32_t primary_slot=-1, int32_t this_slot=-1, int32_t from_slot=-1)
ogl::color3f get_text_color(sys::state &state, text::text_color text_color)
std::unique_ptr< element_base > make_element(sys::state &state, std::string_view name)
ogl::color_modification get_color_modification(bool is_under_mouse, bool is_disabled, bool is_interactable)
std::unique_ptr< element_base > make_element_immediate(sys::state &state, dcon::gui_def_id id)
uint32_t internal_get_interactable_color(float r, float g, float b)
message_result greater_result(message_result a, message_result b)
void single_unit_tooltip(sys::state &state, text::columnar_layout &contents, dcon::army_id a)
Holds important data about the game world, state, and other data regarding windowing,...
std::vector< text_chunk > contents
text::stored_glyphs unicodechars
element_type get_element_type() const
static constexpr uint8_t orientation_mask
union ui::element_data::internal_data data
dcon::gfx_object_id gfx_object
listbox2_row_element * row
std::unique_ptr< element_base > army_group_selector_root
element_base * last_tooltip
std::unique_ptr< element_base > province_details_root
std::unique_ptr< tool_tip > tooltip
std::unique_ptr< element_base > rgos_root
ankerl::unordered_dense::map< dcon::text_key, element_target, hash_text_key > defs_by_name
std::unique_ptr< element_base > root
element_base * edit_target
element_base * province_window
std::unique_ptr< element_base > military_root
element_base * drag_target
element_base * under_mouse
std::unique_ptr< element_base > units_root
alignment get_alignment() const
text_base_data text_common