lxgui
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 
12 namespace 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 
31 bool 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 
36 void 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 
54 void scroll_frame::copy_from(const region& obj) {
55  base::copy_from(obj);
56 
57  const scroll_frame* scroll_obj = down_cast<scroll_frame>(&obj);
58  if (!scroll_obj)
59  return;
60 
61  this->set_horizontal_scroll(scroll_obj->get_horizontal_scroll());
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())
113  scroll_child_->set_anchor(point::top_left, get_name(), -scroll_);
114 
116  "OnSizeChanged", [&](frame&, const event_data&) { update_scroll_range_(); });
117 
119  }
120 
122 }
123 
124 void 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 
146  return scroll_range_.x;
147 }
148 
149 void 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 
171  return scroll_range_.y;
172 }
173 
174 void 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 
213 
215 }
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 
230  if (scroll_render_target_) {
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 {
234  auto& renderer = get_manager().get_renderer();
236 
239  }
240 
241  if (scroll_render_target_) {
244  } else {
246  }
247 }
248 
251 
253 
254  vector2f view = vector2f(scroll_render_target_->get_canvas_dimensions()) /
256 
258 
260 
261  for (const auto& s : strata_list_) {
262  render_strata_(s);
263  }
264 
265  renderer.end();
266 
268 }
269 
270 utils::observer_ptr<const frame>
271 scroll_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 
285 }
286 
288  return get_apparent_dimensions();
289 }
290 
291 const 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:42
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.
Definition: gui_frame.hpp:255
utils::observer_ptr< frame > add_child(utils::owner_ptr< frame > child)
Adds a frame to this frame's children.
Definition: gui_frame.cpp:678
void copy_from(const region &obj) override
Copies a region's parameters into this frame (inheritance).
Definition: gui_frame.cpp:195
virtual void fire_script(const std::string &script_name, const event_data &data=event_data{})
Calls a script.
Definition: gui_frame.cpp:1105
virtual void update_(float delta)
Definition: gui_frame.cpp:1561
void notify_renderer_need_redraw() override
Notifies the renderer of this region that it needs to be redrawn.
Definition: gui_frame.cpp:1481
virtual bool can_use_script(const std::string &script_name) const
Returns 'true' if this frame can use a script.
Definition: gui_frame.cpp:183
utils::owner_ptr< frame > remove_child(const utils::observer_ptr< frame > &child)
Removes a frame from this frame's children.
Definition: gui_frame.cpp:690
utils::observer_ptr< frame > create_child(frame_core_attributes attr)
Creates a new frame as child of this frame.
Definition: gui_frame.cpp:666
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.
Definition: gui_frame.cpp:832
void notify_scaling_factor_updated() override
Tells this region that the global interface scaling factor has changed.
Definition: gui_frame.cpp:1488
Manages the user interface.
Definition: gui_manager.hpp:44
float get_interface_scaling_factor() const
Returns the current UI scaling factor.
Definition: gui_manager.cpp:87
const renderer & get_renderer() const
Returns the renderer implementation.
The base class of all elements in the GUI.
Definition: gui_region.hpp:161
const bounds2f & get_borders() const
Returns this region's borders.
Definition: gui_region.cpp:361
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.
Definition: gui_region.cpp:553
bool is_visible() const
Checks if this region can be seen on the screen.
Definition: gui_region.cpp:207
manager & get_manager()
Returns this region's manager.
Definition: gui_region.hpp:693
vector2f get_apparent_dimensions() const
Returns this region's apparent width and height (in pixels).
Definition: gui_region.cpp:276
const std::string & get_name() const
Returns this region's name.
Definition: gui_region.cpp:140
bool is_loaded() const
Checks if this region has been fully loaded.
Definition: gui_region.cpp:798
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_
const utils::observer_ptr< frame > & get_scroll_child()
Returns this scroll_frame's scroll child.
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.
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)
utils::observer_ptr< ObjectType > observer_from(ObjectType *self)
Obtain an observer pointer from a raw pointer (typically 'this')
Definition: gui_region.hpp:946
vector2< std::size_t > vector2ui
Holds 2D coordinates (as unsigned integers)
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
Definition: gui_matrix4.cpp:29
static matrix4f view(const vector2f &window) noexcept
Definition: gui_matrix4.cpp:53
std::vector< utils::observer_ptr< const region > > inheritance