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;
60 if (!background_texture_) {
64 tile_size_ = original_tile_size_ =
static_cast<float>(background_texture_->get_rect().width());
65 background_file_ = background_file;
69 return background_file_;
73 if (background_color_ == c)
76 is_cache_dirty_ =
true;
78 background_texture_ =
nullptr;
79 background_color_ = c;
80 background_file_ =
"";
82 tile_size_ = original_tile_size_ = 256.0f;
86 return background_color_;
90 if (is_background_tilling_ == is_tilling)
93 is_background_tilling_ = is_tilling;
94 is_cache_dirty_ =
true;
98 return is_background_tilling_;
102 if (tile_size_ == tile_size)
105 tile_size_ = tile_size;
106 is_cache_dirty_ =
true;
114 if (background_insets_ == insets)
117 background_insets_ = insets;
118 is_cache_dirty_ =
true;
122 return background_insets_;
126 if (edge_insets_ == insets)
129 edge_insets_ = insets;
130 is_cache_dirty_ =
true;
138 if (edge_file == edge_file_)
141 is_cache_dirty_ =
true;
144 if (edge_file.empty()) {
145 edge_texture_ =
nullptr;
151 edge_texture_ =
nullptr;
155 <<
"Cannot find file: \"" << edge_file <<
"\" for " << parent_.
get_name()
156 <<
"'s backdrop edge. No edge will be drawn." << std::endl;
163 if (!edge_texture_) {
167 if (edge_texture_->get_rect().width() / edge_texture_->get_rect().height() != 8.0f) {
168 edge_texture_ =
nullptr;
172 <<
"An edge texture width must be exactly 8 times greater than its height "
173 <<
"(in " << edge_file <<
"). No edge will be drawn for " << parent_.
get_name()
174 <<
"'s backdrop." << std::endl;
179 edge_size_ = original_edge_size_ = edge_texture_->get_rect().height();
180 edge_file_ = edge_file;
188 if (edge_color_ == c)
191 is_cache_dirty_ =
true;
192 edge_texture_ =
nullptr;
196 if (edge_size_ == 0.0f)
199 original_edge_size_ = 1.0f;
207 if (edge_size_ == edge_size)
210 edge_size_ = edge_size;
211 is_cache_dirty_ =
true;
219 if (vertex_color_ == c)
223 is_cache_dirty_ =
true;
228 if (alpha != cache_alpha_)
229 is_cache_dirty_ =
true;
232 bool use_vertex_cache =
235 bool has_background = background_texture_ || background_color_ !=
color::empty;
236 bool has_edge = edge_texture_ || edge_color_ !=
color::empty;
238 if (has_background) {
239 if ((use_vertex_cache && !background_cache_) ||
240 (!use_vertex_cache && background_quads_.empty()))
241 is_cache_dirty_ =
true;
245 if ((use_vertex_cache && !edge_cache_) || (!use_vertex_cache && edge_quads_.empty()))
246 is_cache_dirty_ =
true;
251 if (has_background) {
252 if (use_vertex_cache && background_cache_)
259 if (use_vertex_cache && edge_cache_)
267 is_cache_dirty_ =
true;
270void backdrop::update_cache_()
const {
271 if (!is_cache_dirty_)
274 background_quads_.clear();
282 update_background_(
color);
285 cache_alpha_ = alpha;
286 is_cache_dirty_ =
false;
291 std::vector<std::array<vertex, 4>>& output,
297 const auto d_top_left = destination.
top_left();
298 const auto s_top_left = source_uvs.
top_left();
299 const float dest_width = destination.
width();
300 const float dest_height = destination.
height();
303 while (sy < dest_height) {
304 float d_height = tile_size;
305 float s_height = source_uvs.
height();
306 if (sy + tile_size > dest_height)
307 d_height = dest_height - sy;
310 while (sx < dest_width) {
311 float d_width = tile_size;
312 float s_width = source_uvs.
width();
313 if (sx + tile_size > dest_width)
314 d_width = dest_width - sx;
316 output.emplace_back();
317 auto&
quad = output.back();
325 s_height *= d_width / tile_size;
326 s_width *= d_height / tile_size;
332 s_width *= d_width / tile_size;
333 s_height *= d_height / tile_size;
349void backdrop::update_background_(color c)
const {
350 if (!background_texture_ && background_color_ ==
color::empty)
353 if (!background_texture_)
354 c *= background_color_;
357 borders.
left += background_insets_.
left;
358 borders.right -= background_insets_.
right;
359 borders.top += background_insets_.
top;
360 borders.bottom -= background_insets_.
bottom;
364 if (background_texture_) {
365 const vector2f canvas_tl = background_texture_->get_canvas_uv(
vector2f(0.0f, 0.0f),
true);
366 const vector2f canvas_br = background_texture_->get_canvas_uv(
vector2f(1.0f, 1.0f),
true);
367 const bounds2f canvas_uvs =
bounds2f(canvas_tl.x, canvas_br.x, canvas_tl.y, canvas_br.y);
369 float rounded_tile_size =
372 if (background_texture_->is_in_atlas() && is_background_tilling_ &&
373 rounded_tile_size > 1.0f) {
375 parent_, background_quads_, canvas_uvs, rounded_tile_size,
false, c, borders);
377 background_quads_.emplace_back();
378 auto& quad = background_quads_.back();
384 quad[0].uvs = canvas_uvs.top_left();
385 quad[1].uvs = canvas_uvs.top_right();
386 quad[2].uvs = canvas_uvs.bottom_right();
387 quad[3].uvs = canvas_uvs.bottom_left();
388 quad[0].col = quad[1].col = quad[2].col = quad[3].col = c;
391 background_quads_.emplace_back();
392 auto& quad = background_quads_.back();
403 quad[0].col = quad[1].col = quad[2].col = quad[3].col = c;
406 if (renderer.is_vertex_cache_enabled() && !renderer.is_quad_batching_enabled()) {
407 if (!background_cache_)
410 background_cache_->update(background_quads_[0].data(), background_quads_.size() * 4);
411 background_quads_.clear();
415void backdrop::update_edge_(color c)
const {
422 constexpr float uv_step = 1.0f / 8.0f;
425 borders.right -= edge_insets_.
right;
426 borders.top += edge_insets_.
top;
427 borders.bottom -= edge_insets_.
bottom;
430 const float rounded_edge_size =
433 auto repeat_wrap_edge = [&](
const bounds2f& source_uvs,
bool is_rotated,
436 const vector2f canvas_tl = edge_texture_->get_canvas_uv(source_uvs.top_left(),
true);
438 edge_texture_->get_canvas_uv(source_uvs.bottom_right(),
true);
440 bounds2f(canvas_tl.x, canvas_br.x, canvas_tl.y, canvas_br.y);
442 if (edge_texture_->is_in_atlas() && rounded_edge_size > 1.0f) {
444 parent_, edge_quads_, canvas_uvs, rounded_edge_size, is_rotated, c,
447 edge_quads_.emplace_back();
448 auto& quad = edge_quads_.back();
455 if (rounded_edge_size <= 1.0f) {
456 quad[0].uvs = canvas_uvs.top_left();
457 quad[1].uvs = canvas_uvs.top_right();
458 quad[2].uvs = canvas_uvs.bottom_right();
459 quad[3].uvs = canvas_uvs.bottom_left();
462 float factor = destination.width() / rounded_edge_size;
464 canvas_uvs.top_left() +
vector2f(0.0, factor * canvas_uvs.height());
465 quad[1].uvs = canvas_uvs.top_left();
466 quad[2].uvs = canvas_uvs.top_right();
468 canvas_uvs.top_right() +
vector2f(0.0, factor * canvas_uvs.height());
470 float factor = destination.height() / rounded_edge_size;
471 quad[0].uvs = canvas_uvs.top_left();
472 quad[1].uvs = canvas_uvs.top_right();
474 canvas_uvs.top_right() +
vector2f(0.0, factor * canvas_uvs.height());
476 canvas_uvs.top_left() +
vector2f(0.0, factor * canvas_uvs.height());
480 quad[0].col = quad[1].col = quad[2].col = quad[3].col = c;
483 edge_quads_.emplace_back();
484 auto& quad = edge_quads_.back();
494 quad[0].col = quad[1].col = quad[2].col = quad[3].col = c;
500 bounds2f(0.0f, uv_step, 0.0f, 1.0f),
false,
502 borders.left, borders.left + rounded_edge_size, borders.top + rounded_edge_size,
503 borders.bottom - rounded_edge_size));
507 bounds2f(uv_step, 2.0f * uv_step, 0.0f, 1.0f),
false,
509 borders.right - rounded_edge_size, borders.right, borders.top + rounded_edge_size,
510 borders.bottom - rounded_edge_size));
514 bounds2f(2.0f * uv_step, 3.0f * uv_step, 0.0f, 1.0f),
true,
516 borders.left + rounded_edge_size, borders.right - rounded_edge_size, borders.top,
517 borders.top + rounded_edge_size));
521 bounds2f(3.0f * uv_step, 4.0f * uv_step, 0.0f, 1.0f),
true,
523 borders.left + rounded_edge_size, borders.right - rounded_edge_size,
524 borders.bottom - rounded_edge_size, borders.bottom));
528 bounds2f(4.0f * uv_step, 5.0f * uv_step, 0.0f, 1.0f),
false,
530 borders.left, borders.left + rounded_edge_size, borders.top,
531 borders.top + rounded_edge_size));
535 bounds2f(5.0f * uv_step, 6.0f * uv_step, 0.0f, 1.0f),
false,
537 borders.right - rounded_edge_size, borders.right, borders.top,
538 borders.top + rounded_edge_size));
542 bounds2f(6.0f * uv_step, 7.0f * uv_step, 0.0f, 1.0f),
false,
544 borders.left, borders.left + rounded_edge_size, borders.bottom - rounded_edge_size,
549 bounds2f(7.0f * uv_step, 8.0f * uv_step, 0.0f, 1.0f),
false,
551 borders.right - rounded_edge_size, borders.right, borders.bottom - rounded_edge_size,
554 if (renderer.is_vertex_cache_enabled() && !renderer.is_quad_batching_enabled()) {
558 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.
manager & get_manager()
Returns this region's manager.
const bounds2f & get_borders() const
Returns this region's borders.
float get_effective_alpha() const
Returns this region's effective alpha (opacity).
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.