31 #include <glm/vec2.hpp>
34 #include "eng3d/ui/widget.hpp"
35 #include "eng3d/ui/ui.hpp"
36 #include "eng3d/ui/checkbox.hpp"
37 #include "eng3d/texture.hpp"
38 #include "eng3d/rectangle.hpp"
39 #include "eng3d/state.hpp"
40 #include "eng3d/ui/tooltip.hpp"
41 #include "eng3d/primitive.hpp"
42 #include "eng3d/utils.hpp"
71 current_texture{ tex }
91 glm::vec2 pos_size = rect_pos.
size();
92 pos_size.x = pos_size.x > 0 ? pos_size.x : 1.f;
93 pos_size.y = pos_size.y > 0 ? pos_size.y : 1.f;
94 glm::vec2 tex_size = rect_tex.
size();
97 float x_ratio = (viewport.
left - rect_pos.
left) / pos_size.x;
98 rect_tex.
left = rect_tex.
left + x_ratio * tex_size.x;
102 float x_ratio = (rect_pos.
right - viewport.
right) / pos_size.x;
103 rect_tex.
right = rect_tex.
right - x_ratio * tex_size.x;
106 if(rect_pos.
top < viewport.
top) {
107 float y_ratio = (viewport.
top - rect_pos.
top) / pos_size.y;
108 rect_tex.
top = rect_tex.
top + y_ratio * tex_size.y;
109 rect_pos.
top = viewport.
top;
112 float y_ratio = (rect_pos.
bottom - viewport.
bottom) / pos_size.y;
113 rect_tex.
bottom = rect_tex.
bottom - y_ratio * tex_size.y;
139 pos_rect.left = x_offset;
140 pos_rect.top = y_offset;
141 pos_rect.right = x_offset + b_w;
142 pos_rect.bottom = y_offset + b_h;
145 tex_rect.right = b_tex_w / border_tex.width;
146 tex_rect.bottom = b_tex_h / border_tex.height;
149 draw_rect(&border_tex, pos_rect, tex_rect, viewport);
152 pos_rect.left =
width - b_w;
153 tex_rect.left = (border_tex.width - b_tex_w) / border_tex.width;
154 pos_rect.right =
width;
155 tex_rect.right = 1.f;
156 draw_rect(&border_tex, pos_rect, tex_rect, viewport);
159 pos_rect.top =
height - b_h;
160 tex_rect.top = (border_tex.height - b_tex_h) / border_tex.height;
162 tex_rect.bottom = 1.f;
163 draw_rect(&border_tex, pos_rect, tex_rect, viewport);
166 pos_rect.left = x_offset;
168 pos_rect.right = x_offset + b_w;
169 tex_rect.right = b_tex_w / border_tex.width;
170 draw_rect(&border_tex, pos_rect, tex_rect, viewport);
173 pos_rect.left = x_offset + b_w;
174 tex_rect.left = b_tex_w / border_tex.width;
175 pos_rect.right =
width - b_w;
176 tex_rect.right = (border_tex.width - b_tex_w) / border_tex.width;
177 pos_rect.top = y_offset;
179 pos_rect.bottom = y_offset + b_h;
180 tex_rect.bottom = b_tex_h / border_tex.height;
181 draw_rect(&border_tex, pos_rect, tex_rect, viewport);
184 pos_rect.top =
height - b_h;
185 tex_rect.top = (border_tex.height - b_tex_h) / border_tex.height;
187 tex_rect.bottom = 1.f;
188 draw_rect(&border_tex, pos_rect, tex_rect, viewport);
191 pos_rect.top = y_offset + b_h;
192 tex_rect.top = b_tex_h / border_tex.height;
193 pos_rect.bottom =
height - b_h;
194 tex_rect.bottom = (border_tex.height - b_tex_h) / border_tex.height;
195 pos_rect.left = x_offset;
197 pos_rect.right = b_w;
198 tex_rect.right = b_tex_w / border_tex.width;
199 draw_rect(&border_tex, pos_rect, tex_rect, viewport);
202 pos_rect.left =
width - b_w;
203 tex_rect.left = (border_tex.width - b_tex_w) / border_tex.width;
204 pos_rect.right =
width;
205 tex_rect.right = 1.f;
206 draw_rect(&border_tex, pos_rect, tex_rect, viewport);
209 pos_rect.left = x_offset + b_w;
210 tex_rect.left = b_tex_w / border_tex.width;
211 pos_rect.right =
width - b_w;
212 tex_rect.right = (border_tex.width - b_tex_w) / border_tex.width;
213 pos_rect.top = y_offset + b_h;
214 tex_rect.top = b_tex_h / border_tex.height;
215 pos_rect.bottom =
height - b_h;
216 tex_rect.bottom = (border_tex.height - b_tex_h) / border_tex.height;
217 draw_rect(&border_tex, pos_rect, tex_rect, viewport);
225 draw_rect(tex, pos_rect, tex_rect, viewport);
241 draw_rect(
nullptr, pos_rect, tex_rect, viewport);
244 draw_rect(
nullptr, pos_rect, tex_rect, viewport);
255 draw_border(viewport);
281 draw_rect(
nullptr, pos_rect, tex_rect, viewport);
288 void UI::Widget::recalc_child_pos() {
292 int movable_children = 0;
293 for(
auto& child : children) {
294 if(!child->is_pinned) {
295 lenght += is_row ? child->width : child->height;
302 size_t current_length = 0;
303 size_t off_x = this->padding.x, off_y = this->padding.y;
304 size_t max_wrap_height = 0, max_wrap_width = 0;
305 int size = 0, difference = 0;
306 switch(flex_justify) {
308 current_length = is_row ? this->padding.x : this->padding.y;
309 for(
auto& child : children) {
310 if(!child->is_pinned) {
312 child->x = current_length;
313 current_length += child->width + flex_gap;
315 child->y = current_length;
316 current_length += child->height + flex_gap;
323 max_wrap_height = glm::max(max_wrap_height, child->height + flex_gap);
324 if(current_length >= this->width) {
325 off_y += max_wrap_height;
326 child->x = max_wrap_height = current_length = 0;
327 current_length += child->width + flex_gap;
331 max_wrap_width = glm::max(max_wrap_width, child->width + flex_gap);
332 if(current_length >= this->height) {
333 off_x += max_wrap_width;
334 child->y = max_wrap_width = current_length = 0;
335 current_length += child->height + flex_gap;
343 current_length = is_row ? width : height;
344 for(
const auto& child :
reverse(children)) {
345 if(!child->is_pinned) {
347 child->x = current_length - child->width - flex_gap;
348 current_length -= child->width;
350 child->y = current_length - child->height - flex_gap;
351 current_length -= child->height;
358 current_length = is_row ? this->padding.x : this->padding.y;
359 size = is_row ? width : height;
360 difference = (size - lenght) / glm::max(movable_children - 1, 1);
361 for(
auto& child : children) {
362 if(!child->is_pinned) {
364 child->x = current_length;
365 current_length += child->width + difference;
367 child->y = current_length;
368 current_length += child->height + difference;
375 size = is_row ? width : height;
376 difference = (size - lenght) / movable_children;
377 current_length = glm::max(difference / 2, 0);
378 for(
auto& child : children) {
379 if(!child->is_pinned) {
381 child->x = current_length;
382 current_length += child->width + difference;
384 child->y = current_length;
385 current_length += child->height + difference;
394 for(
auto& child : children) {
395 if(!child->is_pinned) {
402 if(is_row) child->y = glm::max((
int)height - (
int)child->height, 0);
403 else child->x = glm::max((
int)width - (
int)child->width, 0);
406 if(is_row) child->y = glm::max((
int)height - (
int)child->height, 0) / 2;
407 else child->x = glm::max((
int)width - (
int)child->width, 0) / 2;
416 for(
auto& child : children) {
417 if(!child->is_pinned) {
418 if(child->on_pos_recalc)
419 child->on_pos_recalc(*child, child_index);
429 children.push_back(std::move(std::unique_ptr<UI::Widget>(&child)));
436 static inline unsigned int power_two_floor(
const unsigned int val) {
437 unsigned int power = 2, nextVal = power * 2;
438 while((nextVal *= 2) <= val)
446 if(this->text_str == _text)
return;
449 this->text_str = _text;
450 if(_text.empty())
return;
467 if(text.empty())
return;
476 auto text = _tooltip_text_creator();
484 int child_top = 0, child_bottom = this->height;
485 for(
auto& child : this->children) {
486 if(!child->is_pinned) {
487 child_top = glm::min(child_top, child->y);
488 child_bottom = glm::max(child_bottom, child->y +
static_cast<int>(child->height));
491 child_bottom -= this->height;
492 return glm::ivec2{ child_top, child_bottom };
498 const auto y_bounds = this->get_y_bounds();
499 _y = glm::clamp<int>(_y, -y_bounds.y, -y_bounds.x);
500 for(
auto& child : children)
501 if(!child->is_pinned)
503 this->scrolled_y += _y;
static State & get_instance()
Eng3D::TextureManager tex_man
std::shared_ptr< Eng3D::Texture > get_white()
std::shared_ptr< Eng3D::Texture > gen_text(Eng3D::TrueType::Font &font, Eng3D::Color color, const std::string &msg)
std::shared_ptr< Eng3D::Texture > texture
The UI context that handles all the ui widgets.
std::shared_ptr< Eng3D::TrueType::Font > default_font
std::unique_ptr< Eng3D::OpenGL::Program > obj_shader
std::shared_ptr< Eng3D::Texture > window_top
void add_widget(UI::Widget *widget)
WidgetType
The type of the widget, some widgets share types between them to keep simplicity.
void draw(int instances=0) const
constexpr glm::vec2 size() const
Obtains the current size of the rectangle.
Range< It > reverse(ORange &&originalRange)