lxgui
Loading...
Searching...
No Matches
gui_scroll_frame.cpp
1#include "lxgui/gui_scroll_frame.hpp"
2
3#include "lxgui/gui_alive_checker.hpp"
4#include "lxgui/gui_frame.hpp"
5#include "lxgui/gui_manager.hpp"
6#include "lxgui/gui_out.hpp"
7#include "lxgui/gui_region_tpl.hpp"
8#include "lxgui/gui_render_target.hpp"
9#include "lxgui/gui_renderer.hpp"
10#include "lxgui/gui_texture.hpp"
11
12namespace lxgui::gui {
13
15 utils::control_block& block, manager& mgr, const frame_core_attributes& attr) :
16 frame(block, mgr, attr) {
17
18 initialize_(*this, attr);
19}
20
22 // Make sure the scroll child is destroyed now.
23 // It relies on this scroll_frame still being alive
24 // when being destroyed, but the scroll_frame destructor
25 // would be called before its inherited frame destructor
26 // (which would otherwise take care of destroying the scroll child).
27 if (scroll_child_)
29}
30
31bool scroll_frame::can_use_script(const std::string& script_name) const {
32 return base::can_use_script(script_name) || script_name == "OnHorizontalScroll" ||
33 script_name == "OnScrollRangeChanged" || script_name == "OnVerticalScroll";
34}
35
36void scroll_frame::fire_script(const std::string& script_name, const event_data& data) {
37 if (!is_loaded())
38 return;
39
40 alive_checker checker(*this);
41 base::fire_script(script_name, data);
42 if (!checker.is_alive())
43 return;
44
45 if (script_name == "OnSizeChanged") {
47
49 if (!checker.is_alive())
50 return;
51 }
52}
53
55 base::copy_from(obj);
56
57 const scroll_frame* scroll_obj = down_cast<scroll_frame>(&obj);
58 if (!scroll_obj)
59 return;
60
62 this->set_vertical_scroll(scroll_obj->get_vertical_scroll());
63
64 if (const frame* other_child = scroll_obj->get_scroll_child().get()) {
66 attr.object_type = other_child->get_region_type();
67 attr.name = other_child->get_raw_name();
68 attr.inheritance = {scroll_obj->get_scroll_child()};
69
70 utils::observer_ptr<frame> scroll_child = create_child(std::move(attr));
71
72 if (scroll_child) {
73 scroll_child->set_manually_inherited(true);
74 scroll_child->notify_loaded();
75 this->set_scroll_child(remove_child(scroll_child));
76 }
77 }
78}
79
81 if (scroll_child_) {
84 } else if (!is_virtual() && !scroll_texture_) {
85 // Create the scroll texture
86 auto scroll_texture =
87 create_layered_region<texture>(layer::artwork, "$parentScrollTexture");
88
89 if (!scroll_texture)
90 return;
91
92 scroll_texture->set_manually_inherited(true);
93 scroll_texture->set_all_anchors(observer_from(this));
94
96 scroll_texture->set_texture(scroll_render_target_);
97
98 scroll_texture->notify_loaded();
99 scroll_texture_ = scroll_texture;
100 }
101
102 scroll_child_ = obj;
103
104 if (scroll_child_) {
105 add_child(std::move(obj));
106
107 scroll_child_->set_manually_inherited(true);
108 if (!is_virtual())
109 scroll_child_->set_frame_renderer(observer_from(this));
110
111 scroll_child_->clear_all_anchors();
112 if (!is_virtual())
114
116 "OnSizeChanged", [&](frame&, const event_data&) { update_scroll_range_(); });
117
119 }
120
122}
123
124void scroll_frame::set_horizontal_scroll(float horizontal_scroll) {
125 if (scroll_.x == horizontal_scroll)
126 return;
127
128 scroll_.x = horizontal_scroll;
129
130 alive_checker checker(*this);
131 fire_script("OnHorizontalScroll");
132 if (!checker.is_alive())
133 return;
134
135 scroll_child_->modify_anchor(point::top_left).offset = -scroll_;
136 scroll_child_->notify_borders_need_update();
137
139}
140
142 return scroll_.x;
143}
144
148
149void scroll_frame::set_vertical_scroll(float vertical_scroll) {
150 if (scroll_.y == vertical_scroll)
151 return;
152
153 scroll_.y = vertical_scroll;
154
155 alive_checker checker(*this);
156 fire_script("OnVerticalScroll");
157 if (!checker.is_alive())
158 return;
159
160 scroll_child_->modify_anchor(point::top_left).offset = -scroll_;
161 scroll_child_->notify_borders_need_update();
162
164}
165
167 return scroll_.y;
168}
169
173
174void scroll_frame::update_(float delta) {
175 alive_checker checker(*this);
176 base::update_(delta);
177 if (!checker.is_alive())
178 return;
179
180 if (is_visible()) {
184 }
185 }
186}
187
189 if (!scroll_child_)
190 return;
191
192 const vector2f apparent_size = get_apparent_dimensions();
193 const vector2f child_apparent_size = scroll_child_->get_apparent_dimensions();
194 const auto old_scroll_range = scroll_range_;
195
196 scroll_range_ = child_apparent_size - apparent_size;
197
198 if (scroll_range_.x < 0)
199 scroll_range_.x = 0;
200 if (scroll_range_.y < 0)
201 scroll_range_.y = 0;
202
203 if (!is_virtual() && scroll_range_ != old_scroll_range) {
204 alive_checker checker(*this);
205 fire_script("OnScrollRangeChanged");
206 if (!checker.is_alive())
207 return;
208 }
209}
210
216
218 if (!scroll_texture_)
219 return;
220
221 const vector2f apparent_size = get_apparent_dimensions();
222
223 if (apparent_size.x <= 0 || apparent_size.y <= 0)
224 return;
225
226 float factor = get_manager().get_interface_scaling_factor();
227 vector2ui scaled_size =
228 vector2ui(std::round(apparent_size.x * factor), std::round(apparent_size.y * factor));
229
231 scroll_render_target_->set_dimensions(scaled_size);
232 scroll_texture_->set_tex_rect(std::array<float, 4>{0.0f, 0.0f, 1.0f, 1.0f});
233 } else {
236
239 }
240
244 } else {
246 }
247}
248
269
270utils::observer_ptr<const frame>
271scroll_frame::find_topmost_frame(const std::function<bool(const frame&)>& predicate) const {
272 if (base::find_topmost_frame(predicate)) {
273 if (auto hovered_frame = frame_renderer::find_topmost_frame(predicate))
274 return hovered_frame;
275
276 return observer_from(this);
277 }
278
279 return nullptr;
280}
281
286
290
291const std::vector<std::string>& scroll_frame::get_type_list_() const {
292 return get_type_list_impl_<scroll_frame>();
293}
294
295} // namespace lxgui::gui
Utility class for safe checking of region validity.
bool is_alive() const
Check if the wrapped region is still alive.
static const color empty
Definition gui_color.hpp:43
Stores a variable number of arguments for an event.
virtual void notify_strata_needs_redraw(strata strata_id)
Tells this renderer that one of its region requires redraw.
void render_strata_(const strata_data &strata_obj) const
std::array< strata_data, num_strata > strata_list_
utils::observer_ptr< const frame > find_topmost_frame(const std::function< bool(const frame &)> &predicate) const
Find the top-most frame matching the provided predicate.
A region that can contain other regions and react to events.
utils::observer_ptr< frame > add_child(utils::owner_ptr< frame > child)
Adds a frame to this frame's children.
void copy_from(const region &obj) override
Copies a region's parameters into this frame (inheritance).
virtual void fire_script(const std::string &script_name, const event_data &data=event_data{})
Calls a script.
virtual void update_(float delta)
void notify_renderer_need_redraw() override
Notifies the renderer of this region that it needs to be redrawn.
virtual bool can_use_script(const std::string &script_name) const
Returns 'true' if this frame can use a script.
utils::owner_ptr< frame > remove_child(const utils::observer_ptr< frame > &child)
Removes a frame from this frame's children.
utils::observer_ptr< frame > create_child(frame_core_attributes attr)
Creates a new frame as child of this frame.
virtual utils::observer_ptr< const frame > find_topmost_frame(const std::function< bool(const frame &)> &predicate) const
Find the topmost frame matching the provided predicate.
void notify_scaling_factor_updated() override
Tells this region that the global interface scaling factor has changed.
Manages the user interface.
float get_interface_scaling_factor() const
Returns the current UI scaling factor.
const renderer & get_renderer() const
Returns the renderer implementation.
The base class of all elements in the GUI.
manager & get_manager()
Returns this region's manager.
const bounds2f & get_borders() const
Returns this region's borders.
void initialize_(T &self, const region_core_attributes &attr)
Set up function to call in all derived class constructors.
bool is_virtual() const
Checks if this region is virtual.
bool is_visible() const
Checks if this region can be seen on the screen.
vector2f get_apparent_dimensions() const
Returns this region's apparent width and height (in pixels).
const std::string & get_name() const
Returns this region's name.
bool is_loaded() const
Checks if this region has been fully loaded.
Abstract type for implementation specific management.
void set_view(const matrix4f &view_matrix)
Sets the view matrix to use when rendering (viewport).
void end()
Ends rendering.
virtual std::shared_ptr< render_target > create_render_target(const vector2ui &dimensions, material::filter filt=material::filter::none)=0
Creates a new render target.
void begin(std::shared_ptr< render_target > target=nullptr)
Begins rendering on a particular render target.
A frame with scrollable content.
std::shared_ptr< render_target > scroll_render_target_
void set_scroll_child(utils::owner_ptr< frame > obj)
Sets this scroll_frame's scroll child.
float get_vertical_scroll_range() const
Returns the maximum vertical offset of the scroll child.
float get_horizontal_scroll_range() const
Returns the maximum horizontal offset of the scroll child.
~scroll_frame() override
Destructor.
void set_vertical_scroll(float vertical_scroll)
Sets the vertical offset of the scroll child.
void notify_scaling_factor_updated() override
Tells this region that the global interface scaling factor has changed.
utils::observer_ptr< texture > scroll_texture_
utils::observer_ptr< frame > scroll_child_
void copy_from(const region &obj) override
Copies a region's parameters into this scroll_frame (inheritance).
void update_(float delta) override
void fire_script(const std::string &script_name, const event_data &data=event_data{}) override
Calls a script.
utils::scoped_connection scroll_child_on_resize_connection_
const std::vector< std::string > & get_type_list_() const override
float get_horizontal_scroll() const
Returns the horizontal offset of the scroll child.
vector2f get_target_dimensions() const override
Returns the width and height of of this renderer's main render target (e.g., screen).
bool can_use_script(const std::string &script_name) const override
Returns 'true' if this scroll_frame can use a script.
scroll_frame(utils::control_block &block, manager &mgr, const frame_core_attributes &attr)
Constructor.
utils::observer_ptr< const frame > find_topmost_frame(const std::function< bool(const frame &)> &predicate) const override
Find the topmost frame matching the provided predicate.
const utils::observer_ptr< frame > & get_scroll_child()
Returns this scroll_frame's scroll child.
float get_vertical_scroll() const
Returns the vertical offset of the scroll child.
void notify_strata_needs_redraw(strata strata_id) override
Tells this renderer that one of its region requires redraw.
void set_horizontal_scroll(float horizontal_scroll)
Sets the horizontal offset of the scroll child.
void disconnect() noexcept
Disconnect the slot.
vector2< float > vector2f
Holds 2D coordinates (as floats)
vector2< std::size_t > vector2ui
Holds 2D coordinates (as unsigned integers)
utils::observer_ptr< ObjectType > observer_from(ObjectType *self)
Obtain an observer pointer from a raw pointer (typically 'this')
oup::observable_sealed_ptr< T > owner_ptr
Struct holding all the core information about a frame necessary for its creation.
static matrix4f translation(const vector2f &dx) noexcept
static matrix4f view(const vector2f &window) noexcept
std::vector< utils::observer_ptr< const region > > inheritance