1 #include "lxgui/gui_backdrop.hpp"
3 #include "lxgui/gui_frame.hpp"
4 #include "lxgui/gui_manager.hpp"
5 #include "lxgui/gui_material.hpp"
6 #include "lxgui/gui_out.hpp"
7 #include "lxgui/gui_quad.hpp"
8 #include "lxgui/gui_renderer.hpp"
9 #include "lxgui/utils_file_system.hpp"
22 if (other.background_file_.empty())
27 if (other.edge_file_.empty())
35 if (background_file_ == background_file)
38 is_cache_dirty_ =
true;
41 if (background_file.empty()) {
42 background_texture_ =
nullptr;
43 background_file_ =
"";
48 background_texture_ =
nullptr;
49 background_file_ =
"";
52 <<
"Cannot find file: \"" << background_file <<
"\" for " << parent_.
get_name()
53 <<
"'s backdrop background file. No background will be drawn." << std::endl;
61 tile_size_ = original_tile_size_ =
static_cast<float>(background_texture_->get_rect().width());
62 background_file_ = background_file;
66 return background_file_;
70 if (background_color_ == c)
73 is_cache_dirty_ =
true;
75 background_texture_ =
nullptr;
76 background_color_ = c;
77 background_file_ =
"";
79 tile_size_ = original_tile_size_ = 256.0f;
83 return background_color_;
87 if (is_background_tilling_ == is_tilling)
90 is_background_tilling_ = is_tilling;
91 is_cache_dirty_ =
true;
95 return is_background_tilling_;
99 if (tile_size_ == tile_size)
102 tile_size_ = tile_size;
103 is_cache_dirty_ =
true;
111 if (background_insets_ == insets)
114 background_insets_ = insets;
115 is_cache_dirty_ =
true;
119 return background_insets_;
123 if (edge_insets_ == insets)
126 edge_insets_ = insets;
127 is_cache_dirty_ =
true;
135 if (edge_file == edge_file_)
138 is_cache_dirty_ =
true;
141 if (edge_file.empty()) {
142 edge_texture_ =
nullptr;
148 edge_texture_ =
nullptr;
152 <<
"Cannot find file: \"" << edge_file <<
"\" for " << parent_.
get_name()
153 <<
"'s backdrop edge. No edge will be drawn." << std::endl;
161 if (edge_texture_->get_rect().width() / edge_texture_->get_rect().height() != 8.0f) {
162 edge_texture_ =
nullptr;
166 <<
"An edge texture width must be exactly 8 times greater than its height "
167 <<
"(in " << edge_file <<
"). No edge will be drawn for " << parent_.
get_name()
168 <<
"'s backdrop." << std::endl;
173 edge_size_ = original_edge_size_ = edge_texture_->get_rect().height();
174 edge_file_ = edge_file;
182 if (edge_color_ == c)
185 is_cache_dirty_ =
true;
186 edge_texture_ =
nullptr;
190 if (edge_size_ == 0.0f)
193 original_edge_size_ = 1.0f;
201 if (edge_size_ == edge_size)
204 edge_size_ = edge_size;
205 is_cache_dirty_ =
true;
213 if (vertex_color_ == c)
217 is_cache_dirty_ =
true;
222 if (alpha != cache_alpha_)
223 is_cache_dirty_ =
true;
226 bool use_vertex_cache =
229 bool has_background = background_texture_ || background_color_ !=
color::empty;
230 bool has_edge = edge_texture_ || edge_color_ !=
color::empty;
232 if (has_background) {
233 if ((use_vertex_cache && !background_cache_) ||
234 (!use_vertex_cache && background_quads_.empty()))
235 is_cache_dirty_ =
true;
239 if ((use_vertex_cache && !edge_cache_) || (!use_vertex_cache && edge_quads_.empty()))
240 is_cache_dirty_ =
true;
245 if (has_background) {
246 if (use_vertex_cache && background_cache_)
253 if (use_vertex_cache && edge_cache_)
261 is_cache_dirty_ =
true;
264 void backdrop::update_cache_()
const {
265 if (!is_cache_dirty_)
268 background_quads_.clear();
276 update_background_(
color);
279 cache_alpha_ = alpha;
280 is_cache_dirty_ =
false;
285 std::vector<std::array<vertex, 4>>& output,
291 const auto d_top_left = destination.
top_left();
292 const auto s_top_left = source_uvs.
top_left();
293 const float dest_width = destination.
width();
294 const float dest_height = destination.
height();
297 while (sy < dest_height) {
298 float d_height = tile_size;
299 float s_height = source_uvs.
height();
300 if (sy + tile_size > dest_height)
301 d_height = dest_height - sy;
304 while (sx < dest_width) {
305 float d_width = tile_size;
306 float s_width = source_uvs.
width();
307 if (sx + tile_size > dest_width)
308 d_width = dest_width - sx;
310 output.emplace_back();
311 auto&
quad = output.back();
319 s_height *= d_width / tile_size;
320 s_width *= d_height / tile_size;
326 s_width *= d_width / tile_size;
327 s_height *= d_height / tile_size;
343 void backdrop::update_background_(color c)
const {
344 if (!background_texture_ && background_color_ ==
color::empty)
347 if (!background_texture_)
348 c *= background_color_;
351 borders.
left += background_insets_.
left;
352 borders.right -= background_insets_.
right;
353 borders.top += background_insets_.
top;
354 borders.bottom -= background_insets_.
bottom;
358 if (background_texture_) {
359 const vector2f canvas_tl = background_texture_->get_canvas_uv(
vector2f(0.0f, 0.0f),
true);
360 const vector2f canvas_br = background_texture_->get_canvas_uv(
vector2f(1.0f, 1.0f),
true);
361 const bounds2f canvas_uvs =
bounds2f(canvas_tl.x, canvas_br.x, canvas_tl.y, canvas_br.y);
363 float rounded_tile_size =
366 if (background_texture_->is_in_atlas() && is_background_tilling_ &&
367 rounded_tile_size > 1.0f) {
369 parent_, background_quads_, canvas_uvs, rounded_tile_size,
false, c, borders);
371 background_quads_.emplace_back();
372 auto& quad = background_quads_.back();
378 quad[0].uvs = canvas_uvs.top_left();
379 quad[1].uvs = canvas_uvs.top_right();
380 quad[2].uvs = canvas_uvs.bottom_right();
381 quad[3].uvs = canvas_uvs.bottom_left();
382 quad[0].col = quad[1].col = quad[2].col = quad[3].col = c;
385 background_quads_.emplace_back();
386 auto& quad = background_quads_.back();
397 quad[0].col = quad[1].col = quad[2].col = quad[3].col = c;
400 if (renderer.is_vertex_cache_enabled() && !renderer.is_quad_batching_enabled()) {
401 if (!background_cache_)
404 background_cache_->update(background_quads_[0].data(), background_quads_.size() * 4);
405 background_quads_.clear();
409 void backdrop::update_edge_(color c)
const {
416 constexpr
float uv_step = 1.0f / 8.0f;
419 borders.right -= edge_insets_.
right;
420 borders.top += edge_insets_.
top;
421 borders.bottom -= edge_insets_.
bottom;
424 const float rounded_edge_size =
427 auto repeat_wrap_edge = [&](
const bounds2f& source_uvs,
bool is_rotated,
430 const vector2f canvas_tl = edge_texture_->get_canvas_uv(source_uvs.top_left(),
true);
432 edge_texture_->get_canvas_uv(source_uvs.bottom_right(),
true);
434 bounds2f(canvas_tl.x, canvas_br.x, canvas_tl.y, canvas_br.y);
436 if (edge_texture_->is_in_atlas() && rounded_edge_size > 1.0f) {
438 parent_, edge_quads_, canvas_uvs, rounded_edge_size, is_rotated, c,
441 edge_quads_.emplace_back();
442 auto& quad = edge_quads_.back();
449 if (rounded_edge_size <= 1.0f) {
450 quad[0].uvs = canvas_uvs.top_left();
451 quad[1].uvs = canvas_uvs.top_right();
452 quad[2].uvs = canvas_uvs.bottom_right();
453 quad[3].uvs = canvas_uvs.bottom_left();
456 float factor = destination.width() / rounded_edge_size;
458 canvas_uvs.top_left() +
vector2f(0.0, factor * canvas_uvs.height());
459 quad[1].uvs = canvas_uvs.top_left();
460 quad[2].uvs = canvas_uvs.top_right();
462 canvas_uvs.top_right() +
vector2f(0.0, factor * canvas_uvs.height());
464 float factor = destination.height() / rounded_edge_size;
465 quad[0].uvs = canvas_uvs.top_left();
466 quad[1].uvs = canvas_uvs.top_right();
468 canvas_uvs.top_right() +
vector2f(0.0, factor * canvas_uvs.height());
470 canvas_uvs.top_left() +
vector2f(0.0, factor * canvas_uvs.height());
474 quad[0].col = quad[1].col = quad[2].col = quad[3].col = c;
477 edge_quads_.emplace_back();
478 auto& quad = edge_quads_.back();
488 quad[0].col = quad[1].col = quad[2].col = quad[3].col = c;
494 bounds2f(0.0f, uv_step, 0.0f, 1.0f),
false,
496 borders.left, borders.left + rounded_edge_size, borders.top + rounded_edge_size,
497 borders.bottom - rounded_edge_size));
501 bounds2f(uv_step, 2.0f * uv_step, 0.0f, 1.0f),
false,
503 borders.right - rounded_edge_size, borders.right, borders.top + rounded_edge_size,
504 borders.bottom - rounded_edge_size));
508 bounds2f(2.0f * uv_step, 3.0f * uv_step, 0.0f, 1.0f),
true,
510 borders.left + rounded_edge_size, borders.right - rounded_edge_size, borders.top,
511 borders.top + rounded_edge_size));
515 bounds2f(3.0f * uv_step, 4.0f * uv_step, 0.0f, 1.0f),
true,
517 borders.left + rounded_edge_size, borders.right - rounded_edge_size,
518 borders.bottom - rounded_edge_size, borders.bottom));
522 bounds2f(4.0f * uv_step, 5.0f * uv_step, 0.0f, 1.0f),
false,
524 borders.left, borders.left + rounded_edge_size, borders.top,
525 borders.top + rounded_edge_size));
529 bounds2f(5.0f * uv_step, 6.0f * uv_step, 0.0f, 1.0f),
false,
531 borders.right - rounded_edge_size, borders.right, borders.top,
532 borders.top + rounded_edge_size));
536 bounds2f(6.0f * uv_step, 7.0f * uv_step, 0.0f, 1.0f),
false,
538 borders.left, borders.left + rounded_edge_size, borders.bottom - rounded_edge_size,
543 bounds2f(7.0f * uv_step, 8.0f * uv_step, 0.0f, 1.0f),
false,
545 borders.right - rounded_edge_size, borders.right, borders.bottom - rounded_edge_size,
548 if (renderer.is_vertex_cache_enabled() && !renderer.is_quad_batching_enabled()) {
552 edge_cache_->update(edge_quads_[0].data(), edge_quads_.size() * 4);
Draws borders and background of a frame.
bool is_background_tilling() const
Checks if tilling is enabled for the background texture.
float get_tile_size() const
Returns this backdrop's tile size.
color get_edge_color() const
Returns the edge color.
void set_tile_size(float tile_size)
Sets the apparent tile size.
void set_edge_color(const color &c)
Sets the edge color.
const bounds2f & get_edge_insets() const
Returns this backdrop's edge insets.
float get_edge_size() const
Returns this backdrop's edge size.
void set_edge_size(float edge_size)
Sets the apparent edge size.
void set_vertex_color(const color &c)
Sets the color to be multiplied to all drawn vertices.
const bounds2f & get_background_insets() const
Returns this backdrop's background insets.
const std::string & get_edge_file() const
Returns this backdrop's edge file.
void set_edge_insets(const bounds2f &insets)
Sets insets for the edge texture.
backdrop(frame &parent)
Constructor.
color get_background_color() const
Returns the background color.
void set_background_insets(const bounds2f &insets)
Sets insets for the background texture.
void copy_from(const backdrop &other)
Copies a backdrop's parameters into this one (inheritance).
void set_edge(const std::string &edge_file)
Sets the edge/corner texture.
const std::string & get_background_file() const
Returns this backdrop's background file.
void set_background(const std::string &background_file)
Sets the background texture.
void set_background_tilling(bool is_tilling)
Enables tilling for the background texture.
void set_background_color(const color &c)
Sets the background color.
void notify_borders_updated() const
Tells this backdrop that its parent frame has changed dimensions.
void render() const
Renders this backdrop on the current render target.
Holds a single color (float RGBA, 128 bits)
A region that can contain other regions and react to events.
const renderer & get_renderer() const
Returns the renderer implementation.
const bounds2f & get_borders() const
Returns this region's borders.
float get_effective_alpha() const
Returns this region's effective alpha (opacity).
manager & get_manager()
Returns this region's manager.
float round_to_pixel(float value, utils::rounding_method method=utils::rounding_method::nearest) const
Round an absolute position on screen to the nearest physical pixel.
const std::string & get_name() const
Returns this region's name.
Abstract type for implementation specific management.
bool is_quad_batching_enabled() const
Checks if the renderer has quad render batching enabled.
std::shared_ptr< material > create_atlas_material(const std::string &atlas_category, const std::string &file_name, material::filter filt=material::filter::none)
Creates a new material from a texture file.
void render_cache(const material *mat, const vertex_cache &cache, const matrix4f &model_transform=matrix4f::identity)
Renders a vertex cache.
void render_quads(const material *mat, const std::vector< std::array< vertex, 4 >> &quad_list)
Renders a set of quads.
bool is_vertex_cache_enabled() const
Checks if the renderer has enabled support for vertex caches.
@ quads
3 vertices per element
vector2< float > vector2f
Holds 2D coordinates (as floats)
bounds2< float > bounds2f
Holds 2D bounds of a region (as floats).
void repeat_wrap(const frame &parent, std::vector< std::array< vertex, 4 >> &output, const bounds2f &source_uvs, float tile_size, bool is_rotated, const color color, const bounds2f &destination)
const std::string warning
@ nearest_not_zero
Equivalent to round() but only returns 0 if input is exactly 0.
bool file_exists(const std::string &file)
T height() const noexcept
vector2< T > top_left() const noexcept
Simple structure holding four vertices and a material.