Project Alice
Loading...
Searching...
No Matches
gui_graphics.cpp
Go to the documentation of this file.
1#include "gui_graphics.hpp"
2#include "simple_fs.hpp"
4
5namespace ui {
6
8 // preload special background textures
9 assert(context.ui_defs.textures.size() == size_t(0));
10 {
11 auto stripped_name = simple_fs::remove_double_backslashes(std::string_view("gfx\\interface\\small_tiles_dialog.tga"));
12 context.ui_defs.textures.emplace_back(context.full_state.add_key_win1252(stripped_name));
13 context.map_of_texture_names.insert_or_assign(stripped_name, definitions::small_tiles_dialog);
14 }
15 {
16 auto stripped_name = simple_fs::remove_double_backslashes(std::string_view("gfx\\interface\\tiles_dialog.tga"));
17 context.ui_defs.textures.emplace_back(context.full_state.add_key_win1252(stripped_name));
18 context.map_of_texture_names.insert_or_assign(stripped_name, definitions::tiles_dialog);
19 }
20 {
21 auto stripped_name = simple_fs::remove_double_backslashes(std::string_view("gfx\\interface\\transparency.tga"));
22 context.ui_defs.textures.emplace_back(context.full_state.add_key_win1252(stripped_name));
23 context.map_of_texture_names.insert_or_assign(stripped_name, definitions::transparency);
24 }
25
26 auto rt = get_root(state.common_fs);
27 auto interfc = open_directory(rt, NATIVE("interface"));
28 auto assets = open_directory(rt, NATIVE("assets"));
29
30 {
31 // first, load in special mod gfx
32 // TODO put this in a better location
33 auto all_alice_files = list_files(assets, NATIVE(".gfx"));
34 for(auto& file : all_alice_files) {
35 if(auto ofile = open_file(file); ofile) {
36 auto content = view_contents(*ofile);
37 err.file_name = simple_fs::native_to_utf8(get_full_name(*ofile));
38 parsers::token_generator gen(content.data, content.data + content.file_size);
39 parsers::parse_gfx_files(gen, err, context);
40 }
41 }
42
43 auto all_files = list_files(interfc, NATIVE(".gfx"));
44 for(auto& file : all_files) {
45 if(auto ofile = open_file(file); ofile) {
46 auto content = view_contents(*ofile);
47 err.file_name = simple_fs::native_to_utf8(get_full_name(*ofile));
48 parsers::token_generator gen(content.data, content.data + content.file_size);
49 parsers::parse_gfx_files(gen, err, context);
50 }
51 }
52
53 auto all_sfx_files = list_files(interfc, NATIVE(".sfx"));
54 for(auto& file : all_sfx_files) {
55 if(auto ofile = open_file(file); ofile) {
56 auto content = view_contents(*ofile);
57 err.file_name = simple_fs::native_to_utf8(get_full_name(*ofile));
58 parsers::token_generator gen(content.data, content.data + content.file_size);
59 parsers::parse_sfx_file(gen, err, context);
60 }
61 }
62 }
63
64 {
65 // first, load in special mod gui
66 // TODO put this in a better location
67 auto all_alice_gui_files = list_files(assets, NATIVE(".gui"));
68 for(auto& file : all_alice_gui_files) {
69 if(auto ofile = open_file(file); ofile) {
70 auto content = view_contents(*ofile);
71 err.file_name = simple_fs::native_to_utf8(get_full_name(*ofile));
72 parsers::token_generator gen(content.data, content.data + content.file_size);
73 parsers::parse_gui_files(gen, err, context);
74 context.gui_files.emplace_back(std::move(*ofile));
75 }
76 }
77
78 // load normal .gui files
79 auto all_gui_files = list_files(interfc, NATIVE(".gui"));
80
81 for(auto& file : all_gui_files) {
82 auto file_name = get_full_name(file);
83 if(!parsers::native_has_fixed_suffix_ci(file_name.data(), file_name.data() + file_name.length(),
84 NATIVE("confirmbuild.gui")) &&
85 !parsers::native_has_fixed_suffix_ci(file_name.data(), file_name.data() + file_name.length(), NATIVE("convoys.gui")) &&
86 !parsers::native_has_fixed_suffix_ci(file_name.data(), file_name.data() + file_name.length(),
87 NATIVE("brigadeview.gui"))) {
88 auto ofile = open_file(file);
89 if(ofile) {
90 auto content = view_contents(*ofile);
91 err.file_name = simple_fs::native_to_utf8(get_full_name(*ofile));
92 parsers::token_generator gen(content.data, content.data + content.file_size);
93 parsers::parse_gui_files(gen, err, context);
94 context.gui_files.emplace_back(std::move(*ofile));
95 }
96 }
97 }
98 }
99}
100
103 switch(orientation) {
105 return int16_t(child.base_data.position.y);
107 return int16_t(child.base_data.position.y);
109 return int16_t(parent.base_data.size.y + child.base_data.position.y);
111 return int16_t(parent.base_data.size.y + child.base_data.position.y);
113 return int16_t(child.base_data.position.y);
115 return int16_t(parent.base_data.size.y + child.base_data.position.y);
117 return int16_t(parent.base_data.size.y / 2 + child.base_data.position.y);
118 default:
119 return int16_t(child.base_data.position.y);
120 }
121}
122
125 int16_t y = child_relative_location_y_component(parent, child);
126 switch(orientation) {
129 default:
130 return xy_pair{ int16_t(child.base_data.position.x), y };
133 return xy_pair{ int16_t(parent.base_data.size.x + child.base_data.position.x), y };
137 return xy_pair{ int16_t(parent.base_data.size.x / 2 + child.base_data.position.x), y };
138 }
139}
140
143 int16_t y = child_relative_location_y_component(parent, child);
144 if(state.world.locale_get_native_rtl(state.font_collection.get_current_locale())) {
145 switch(orientation) {
148 default:
149 return xy_pair{ int16_t(parent.base_data.size.x - child.base_data.position.x - child.base_data.size.x), y };
152 return xy_pair{ int16_t(-child.base_data.position.x - child.base_data.size.x), y };
156 return xy_pair{ int16_t(parent.base_data.size.x / 2 - child.base_data.position.x - child.base_data.size.x), y };
157 }
158 }
159 return child_relative_non_mirror_location(state, parent, child);
160}
161
162uint8_t element_base::get_pixel_opacity(sys::state& state, int32_t x, int32_t y, dcon::texture_id tid) {
163 uint8_t* pixels = state.open_gl.asset_textures[tid].data;
164 int32_t width = state.open_gl.asset_textures[tid].size_x;
165 int32_t stride = state.open_gl.asset_textures[tid].channels;
166 if(pixels && 0 <= x && x < width && 0 <= y && y < state.open_gl.asset_textures[tid].size_y)
167 return pixels[(y * width * stride) + (x * stride) + stride - 1];
168 else
169 return 0;
170}
171
173 mouse_probe probe_result = mouse_probe{nullptr, xy_pair{int16_t(x), int16_t(y)}};
174 if(0 <= x && x < base_data.size.x && 0 <= y && y < base_data.size.y && test_mouse(state, x, y, type) == message_result::consumed) {
175 auto elem_type = base_data.get_element_type();
176 if(elem_type == element_type::button || elem_type == element_type::image || elem_type == element_type::listbox) {
177 dcon::gfx_object_id gid;
178 if(elem_type == element_type::button) {
179 gid = base_data.data.button.button_image;
180 } else if(elem_type == element_type::image) {
181 gid = base_data.data.image.gfx_object;
182 } else if(elem_type == element_type::listbox) {
183 gid = base_data.data.list_box.background_image;
184 }
185 if(gid) {
186 auto& gfx_def = state.ui_defs.gfx[gid];
187 auto mask_handle = gfx_def.type_dependent;
188 if(gfx_def.is_partially_transparent() && gfx_def.primary_texture_handle && get_pixel_opacity(state, x, y, gfx_def.primary_texture_handle) > uint8_t(64)) {
189 probe_result.under_mouse = this;
190 } else if(gfx_def.get_object_type() == ui::object_type::flag_mask && mask_handle && gfx_def.primary_texture_handle) {
191 ogl::get_texture_handle(state, dcon::texture_id(mask_handle - 1), true);
192
193 auto& mask_tex = state.open_gl.asset_textures[dcon::texture_id(gfx_def.type_dependent - 1)];
194 auto x_off = float(base_data.size.x - mask_tex.size_x) * 0.5f;
195 auto y_off = float(base_data.size.y - mask_tex.size_y) * 0.5f;
196
197 if(get_pixel_opacity(state, int32_t(x - x_off), int32_t(y - y_off), dcon::texture_id(mask_handle - 1)) > uint8_t(64) || get_pixel_opacity(state, x, y, gfx_def.primary_texture_handle) > uint8_t(64)) {
198 probe_result.under_mouse = this;
199 }
200 } else {
201 probe_result.under_mouse = this;
202 }
203 } else {
204 probe_result.under_mouse = this;
205 }
206 } else {
207 probe_result.under_mouse = this;
208 }
209 }
210 return probe_result;
211}
213 return on_lbutton_down(state, x, y, mods);
214}
215message_result element_base::impl_on_lbutton_up(sys::state& state, int32_t x, int32_t y, sys::key_modifiers mods, bool under_mouse) noexcept {
216 return on_lbutton_up(state, x, y, mods, under_mouse);
217}
219 return on_rbutton_down(state, x, y, mods);
220}
222 return on_key_down(state, key, mods);
223}
224message_result element_base::impl_on_scroll(sys::state& state, int32_t x, int32_t y, float amount,
225 sys::key_modifiers mods) noexcept {
226 return on_scroll(state, x, y, amount, mods);
227}
229 return on_mouse_move(state, x, y, mods);
230}
232 on_update(state);
233}
235 on_reset_text(state);
236}
238 if(auto res = get(state, payload); res != message_result::consumed) {
239 if(parent)
240 return parent->impl_get(state, payload);
242 }
244}
246 return set(state, payload);
247}
248
251}
254}
255message_result element_base::on_lbutton_up(sys::state& state, int32_t x, int32_t y, sys::key_modifiers mods, bool under_mouse) noexcept {
257}
260}
261
262void element_base::on_drag(sys::state& state, int32_t oldx, int32_t oldy, int32_t x, int32_t y,
263 sys::key_modifiers mods) noexcept { }
266}
267message_result element_base::on_scroll(sys::state& state, int32_t x, int32_t y, float amount, sys::key_modifiers mods) noexcept {
269}
272}
276}
279}
280
281void element_base::impl_render(sys::state& state, int32_t x, int32_t y) noexcept {
282 render(state, x, y);
283}
284
286 if(node.parent) {
287 auto parent_loc = get_absolute_location(state, *node.parent);
288 auto rel_loc = child_relative_location(state, *node.parent, node);
289 return xy_pair{int16_t(parent_loc.x + rel_loc.x), int16_t(parent_loc.y + rel_loc.y)};
290 } else {
291 if(state.world.locale_get_native_rtl(state.font_collection.get_current_locale())) {
292 auto pos = node.base_data.position;
293 pos.x = int16_t(state.x_size) - node.base_data.position.x - node.base_data.size.x;
294 return pos;
295 }
296 return node.base_data.position;
297 }
298}
299
301 if(node.parent) {
302 auto parent_loc = get_absolute_non_mirror_location(state, *node.parent);
303 auto rel_loc = child_relative_non_mirror_location(state, *node.parent, node);
304 return xy_pair{ int16_t(parent_loc.x + rel_loc.x), int16_t(parent_loc.y + rel_loc.y) };
305 } else {
306 return node.base_data.position;
307 }
308}
309
310int32_t ui_width(sys::state const& state) {
311 return int32_t(state.x_size / state.user_settings.ui_scale);
312}
313int32_t ui_height(sys::state const& state) {
314 return int32_t(state.y_size / state.user_settings.ui_scale);
315}
316
318 for(size_t i = state.ui_defs.gui.size(); i-- > 0;) {
319 if(state.ui_defs.gui[dcon::gui_def_id(dcon::gui_def_id::value_base_t(i))].is_top_level()) {
320 auto value = element_target{nullptr, dcon::gui_def_id(dcon::gui_def_id::value_base_t(i))};
321 state.ui_state.defs_by_name.insert_or_assign(state.ui_defs.gui[dcon::gui_def_id(dcon::gui_def_id::value_base_t(i))].name, value);
322 }
323 }
324}
325
326} // namespace ui
std::string file_name
Definition: parsers.hpp:61
tag_type emplace_back(T &&... ts)
auto size() const
static constexpr dcon::texture_id small_tiles_dialog
static constexpr dcon::texture_id tiles_dialog
tagged_vector< dcon::text_key, dcon::texture_id > textures
static constexpr dcon::texture_id transparency
virtual message_result impl_set(sys::state &state, Cyto::Any &payload) noexcept
element_base * parent
virtual void impl_on_reset_text(sys::state &state) noexcept
virtual message_result test_mouse(sys::state &state, int32_t x, int32_t y, mouse_probe_type type) noexcept
virtual message_result on_lbutton_down(sys::state &state, int32_t x, int32_t y, sys::key_modifiers mods) noexcept
virtual message_result on_lbutton_up(sys::state &state, int32_t x, int32_t y, sys::key_modifiers mods, bool under_mouse) noexcept
virtual message_result impl_on_rbutton_down(sys::state &state, int32_t x, int32_t y, sys::key_modifiers mods) noexcept
virtual message_result get(sys::state &state, Cyto::Any &payload) noexcept
virtual message_result impl_on_scroll(sys::state &state, int32_t x, int32_t y, float amount, sys::key_modifiers mods) noexcept
virtual message_result set(sys::state &state, Cyto::Any &payload) noexcept
virtual void on_update(sys::state &state) noexcept
virtual void impl_on_update(sys::state &state) noexcept
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 message_result impl_on_lbutton_up(sys::state &state, int32_t x, int32_t y, sys::key_modifiers mods, bool under_mouse) noexcept
virtual message_result on_scroll(sys::state &state, int32_t x, int32_t y, float amount, sys::key_modifiers mods) noexcept
virtual message_result impl_on_lbutton_down(sys::state &state, int32_t x, int32_t y, sys::key_modifiers mods) noexcept
message_result impl_get(sys::state &state, Cyto::Any &payload) noexcept
virtual message_result on_mouse_move(sys::state &state, int32_t x, int32_t y, sys::key_modifiers mods) noexcept
element_data base_data
virtual void on_drag(sys::state &state, int32_t oldx, int32_t oldy, int32_t x, int32_t y, sys::key_modifiers mods) noexcept
virtual message_result on_key_down(sys::state &state, sys::virtual_key key, sys::key_modifiers mods) noexcept
virtual message_result impl_on_mouse_move(sys::state &state, int32_t x, int32_t y, sys::key_modifiers mods) noexcept
virtual mouse_probe impl_probe_mouse(sys::state &state, int32_t x, int32_t y, mouse_probe_type type) noexcept
virtual message_result on_rbutton_down(sys::state &state, int32_t x, int32_t y, sys::key_modifiers mods) noexcept
#define assert(condition)
Definition: debug.h:74
GLuint get_texture_handle(sys::state &state, dcon::texture_id id, bool keep_data)
Definition: texture.cpp:665
bool native_has_fixed_suffix_ci(char const *start, char const *end, char const (&t)[N])
Definition: parsers.hpp:252
std::string remove_double_backslashes(std::string_view data_in)
std::string native_to_utf8(native_string_view data_in)
virtual_key
Definition: constants.hpp:5
key_modifiers
Definition: constants.hpp:156
int32_t ui_height(sys::state const &state)
xy_pair child_relative_location(sys::state &state, element_base const &parent, element_base const &child)
int32_t ui_width(sys::state const &state)
xy_pair get_absolute_location(sys::state &state, element_base const &node)
int16_t child_relative_location_y_component(element_base const &parent, element_base const &child)
orientation
xy_pair child_relative_non_mirror_location(sys::state &state, element_base const &parent, element_base const &child)
message_result
void populate_definitions_map(sys::state &state)
void load_text_gui_definitions(sys::state &state, parsers::building_gfx_context &context, parsers::error_handler &err)
Definition: gui_graphics.cpp:7
xy_pair get_absolute_non_mirror_location(sys::state &state, element_base const &node)
#define NATIVE(X)
uchar uint8_t
std::vector< simple_fs::file > gui_files
ankerl::unordered_dense::map< std::string, dcon::texture_id > map_of_texture_names
dcon::text_key add_key_win1252(std::string const &text)
orientation get_orientation() const
element_base * under_mouse
ankerl::unordered_dense::map< dcon::text_key, element_target, hash_text_key > defs_by_name