lxgui
gui_slider.cpp
1 #include "lxgui/gui_slider.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_texture.hpp"
9 
10 #include <algorithm>
11 #include <sstream>
12 
13 namespace lxgui::gui {
14 
15 void step_value(float& value, float step) {
16  // Makes the value a multiple of the step,
17  // value = N*step, where N is an integer.
18  if (step != 0.0f)
19  value = std::round(value / step) * step;
20 }
21 
22 slider::slider(utils::control_block& block, manager& mgr, const frame_core_attributes& attr) :
23  frame(block, mgr, attr) {
24 
25  initialize_(*this, attr);
26 
27  enable_mouse();
29 }
30 
31 std::string slider::serialize(const std::string& tab) const {
32  std::ostringstream str;
33 
34  str << base::serialize(tab);
35  str << tab << " # Orientation: " << utils::to_string(orientation_) << "\n";
36  str << tab << " # Value : " << value_ << "\n";
37  str << tab << " # Min value : " << min_value_ << "\n";
38  str << tab << " # Max value : " << max_value_ << "\n";
39  str << tab << " # Step : " << value_step_ << "\n";
40  str << tab << " # Click out : " << allow_clicks_outside_thumb_ << "\n";
41 
42  return str.str();
43 }
44 
45 bool slider::can_use_script(const std::string& script_name) const {
46  return base::can_use_script(script_name) || script_name == "OnValueChanged";
47 }
48 
49 void slider::fire_script(const std::string& script_name, const event_data& data) {
50  alive_checker checker(*this);
51  base::fire_script(script_name, data);
52  if (!checker.is_alive())
53  return;
54 
55  if (script_name == "OnDragStart") {
56  if (thumb_texture_ &&
57  thumb_texture_->is_in_region({data.get<float>(2), data.get<float>(3)})) {
58  anchor& a = thumb_texture_->modify_anchor(point::center);
59 
61  thumb_texture_, &a,
63  [&]() { constrain_thumb_(); });
64 
65  is_thumb_dragged_ = true;
66  }
67  } else if (script_name == "OnDragStop") {
68  if (thumb_texture_) {
71 
72  is_thumb_dragged_ = false;
73  }
74  } else if (script_name == "OnMouseDown") {
76  const vector2f apparent_size = get_apparent_dimensions();
77 
78  float value;
80  float offset = data.get<float>(2) - borders_.left;
81  value = offset / apparent_size.x;
83  } else {
84  float offset = data.get<float>(3) - borders_.top;
85  value = offset / apparent_size.y;
87  }
88  }
89  }
90 }
91 
92 void slider::copy_from(const region& obj) {
93  base::copy_from(obj);
94 
95  const slider* slider_obj = down_cast<slider>(&obj);
96  if (!slider_obj)
97  return;
98 
99  this->set_value_step(slider_obj->get_value_step());
100  this->set_min_value(slider_obj->get_min_value());
101  this->set_max_value(slider_obj->get_max_value());
102  this->set_value(slider_obj->get_value());
103  this->set_thumb_draw_layer(slider_obj->get_thumb_draw_layer());
104  this->set_orientation(slider_obj->get_orientation());
106 
107  if (const texture* thumb = slider_obj->get_thumb_texture().get()) {
109  attr.name = thumb->get_raw_name();
110  attr.inheritance = {slider_obj->get_thumb_texture()};
111 
112  auto tex = this->create_layered_region<texture>(thumb->get_draw_layer(), std::move(attr));
113 
114  if (tex) {
115  tex->set_manually_inherited(true);
116  tex->notify_loaded();
117  this->set_thumb_texture(tex);
118  }
119  }
120 }
121 
123  if (max_value_ == min_value_)
124  return;
125 
126  const vector2f apparent_size = get_apparent_dimensions();
127 
128  if ((orientation_ == orientation::horizontal && apparent_size.x <= 0) ||
129  (orientation_ == orientation::vertical && apparent_size.y <= 0))
130  return;
131 
132  float old_value = value_;
133 
134  if (is_thumb_dragged_) {
136  value_ = thumb_texture_->get_anchor(point::center).offset.x / apparent_size.x;
137  else
138  value_ = thumb_texture_->get_anchor(point::center).offset.y / apparent_size.y;
139 
141  value_ = std::clamp(value_, min_value_, max_value_);
143  }
144 
145  float coef = (value_ - min_value_) / (max_value_ - min_value_);
146 
147  anchor& a = thumb_texture_->modify_anchor(point::center);
148 
149  vector2f new_offset;
151  new_offset = vector2f(apparent_size.x * coef, 0);
152  else
153  new_offset = vector2f(0, apparent_size.y * coef);
154 
155  if (new_offset != a.offset) {
156  a.offset = new_offset;
157  thumb_texture_->notify_borders_need_update();
158  }
159 
160  if (value_ != old_value)
161  fire_script("OnValueChanged");
162 }
163 
164 void slider::set_min_value(float min_value) {
165  if (min_value == min_value_)
166  return;
167 
168  min_value_ = min_value;
169  if (min_value_ > max_value_)
171  else
173 
174  if (value_ < min_value_) {
175  value_ = min_value_;
176  fire_script("OnValueChanged");
177  }
178 
180 }
181 
182 void slider::set_max_value(float max_value) {
183  if (max_value == max_value_)
184  return;
185 
186  max_value_ = max_value;
187  if (max_value_ < min_value_)
189  else
191 
192  if (value_ > max_value_) {
193  value_ = max_value_;
194  fire_script("OnValueChanged");
195  }
196 
198 }
199 
200 void slider::set_min_max_values(float min_value, float max_value) {
201  if (min_value == min_value_ && max_value == max_value_)
202  return;
203 
204  min_value_ = std::min(min_value, max_value);
205  max_value_ = std::max(min_value, max_value);
208 
209  if (value_ > max_value_ || value_ < min_value_) {
210  value_ = std::clamp(value_, min_value_, max_value_);
211  fire_script("OnValueChanged");
212  }
213 
215 }
216 
217 void slider::set_value(float value, bool silent) {
218  value = std::clamp(value, min_value_, max_value_);
219  step_value(value, value_step_);
220 
221  if (value == value_)
222  return;
223 
224  value_ = value;
225 
226  if (!silent)
227  fire_script("OnValueChanged");
228 
230 }
231 
232 void slider::set_value_step(float value_step) {
233  if (value_step_ == value_step)
234  return;
235 
236  value_step_ = value_step;
237 
240 
241  float old_value = value_;
242  value_ = std::clamp(value_, min_value_, max_value_);
244 
245  if (value_ != old_value)
246  fire_script("OnValueChanged");
247 
249 }
250 
251 void slider::set_thumb_texture(utils::observer_ptr<texture> tex) {
252  thumb_texture_ = std::move(tex);
253  if (!thumb_texture_)
254  return;
255 
256  thumb_texture_->set_draw_layer(thumb_layer_);
257  thumb_texture_->clear_all_anchors();
258  thumb_texture_->set_anchor(
259  point::center, thumb_texture_->get_parent().get() == this ? "$parent" : name_,
261 
263 }
264 
266  if (orientation_ == orient)
267  return;
268 
269  orientation_ = orient;
270 
271  if (thumb_texture_) {
272  thumb_texture_->set_anchor(
275  }
276 
278 }
279 
281  thumb_layer_ = thumb_layer;
282 
283  if (thumb_texture_)
284  thumb_texture_->set_draw_layer(thumb_layer_);
285 }
286 
287 float slider::get_min_value() const {
288  return min_value_;
289 }
290 
291 float slider::get_max_value() const {
292  return max_value_;
293 }
294 
295 float slider::get_value() const {
296  return value_;
297 }
298 
299 float slider::get_value_step() const {
300  return value_step_;
301 }
302 
304  return orientation_;
305 }
306 
308  return thumb_layer_;
309 }
310 
313 }
314 
317 }
318 
319 bool slider::is_in_region(const vector2f& position) const {
321  if (base::is_in_region(position))
322  return true;
323  }
324 
325  return thumb_texture_ && thumb_texture_->is_in_region(position);
326 }
327 
329  if (!thumb_texture_)
330  return;
331 
332  if (max_value_ == min_value_) {
333  thumb_texture_->hide();
334  return;
335  } else
336  thumb_texture_->show();
337 
339 }
340 
344 }
345 
348 }
349 
350 const std::vector<std::string>& slider::get_type_list_() const {
351  return get_type_list_impl_<slider>();
352 }
353 
354 } // namespace lxgui::gui
Utility class for safe checking of region validity.
bool is_alive() const
Check if the wrapped region is still alive.
Stores a position for a UI region.
Definition: gui_anchor.hpp:97
Stores a variable number of arguments for an event.
const utils::variant & get(std::size_t index) const
Returns a parameter of this event.
A region that can contain other regions and react to events.
Definition: gui_frame.hpp:255
std::string serialize(const std::string &tab) const override
Prints all relevant information about this region in a string.
Definition: gui_frame.cpp:84
bool is_in_region(const vector2f &position) const override
Checks if the provided coordinates are inside this frame.
Definition: gui_frame.cpp:819
void copy_from(const region &obj) override
Copies a region's parameters into this frame (inheritance).
Definition: gui_frame.cpp:195
void enable_mouse()
Marks this frame as able to receive mouse input (click & move).
Definition: gui_frame.hpp:372
virtual void fire_script(const std::string &script_name, const event_data &data=event_data{})
Calls a script.
Definition: gui_frame.cpp:1105
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
void enable_drag(const std::string &button_name)
Tells this frame to react to mouse drag.
Definition: gui_frame.cpp:1154
Manages the user interface.
Definition: gui_manager.hpp:44
root & get_root()
Returns the UI root object, which contains root frames.
The base class of all elements in the GUI.
Definition: gui_region.hpp:161
void initialize_(T &self, const region_core_attributes &attr)
Set up function to call in all derived class constructors.
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
std::string name_
Definition: gui_region.hpp:804
virtual void notify_borders_need_update()
Tells this region that its borders need updating.
Definition: gui_region.cpp:744
bool is_moving(const region &obj) const
Checks if the given object is allowed to move.
Definition: gui_root.cpp:336
void start_moving(utils::observer_ptr< region > obj, anchor *a=nullptr, constraint constraint=constraint::none, std::function< void()> apply_constraint_func=nullptr)
Start manually moving a region with the mouse.
Definition: gui_root.cpp:303
void stop_moving()
Stops movement for the current object.
Definition: gui_root.cpp:331
A frame with a movable texture.
Definition: gui_slider.hpp:30
void set_value(float value, bool silent=false)
Sets this slider's value.
Definition: gui_slider.cpp:217
bool allow_clicks_outside_thumb_
Definition: gui_slider.hpp:217
orientation orientation_
Definition: gui_slider.hpp:210
void notify_borders_need_update() override
Tells this region that its borders need updating.
Definition: gui_slider.cpp:341
void set_orientation(orientation orient)
Sets the orientation of this slider.
Definition: gui_slider.cpp:265
void set_min_value(float min_value)
Sets this slider's minimum value.
Definition: gui_slider.cpp:164
layer get_thumb_draw_layer() const
Returns the draw layer of this slider's thumb texture.
Definition: gui_slider.cpp:307
void fire_script(const std::string &script_name, const event_data &data=event_data{}) override
Calls a script.
Definition: gui_slider.cpp:49
bool is_in_region(const vector2f &position) const override
Checks if the provided coordinates are in the slider.
Definition: gui_slider.cpp:319
float get_value() const
Returns this slider's value.
Definition: gui_slider.cpp:295
void set_min_max_values(float min_value, float max_value)
Sets the slider's value range.
Definition: gui_slider.cpp:200
void set_thumb_texture(utils::observer_ptr< texture > tex)
Sets the texture to use for the thumb.
Definition: gui_slider.cpp:251
const utils::observer_ptr< texture > & get_thumb_texture()
Returns the texture used for the thumb.
Definition: gui_slider.hpp:78
void notify_thumb_texture_needs_update_()
Definition: gui_slider.cpp:346
const std::vector< std::string > & get_type_list_() const override
Definition: gui_slider.cpp:350
utils::observer_ptr< texture > thumb_texture_
Definition: gui_slider.hpp:220
void update_thumb_texture_()
Definition: gui_slider.cpp:328
float get_value_step() const
Returns this slider's value step.
Definition: gui_slider.cpp:299
orientation get_orientation() const
Returns the orientation of this slider.
Definition: gui_slider.cpp:303
bool can_use_script(const std::string &script_name) const override
Returns 'true' if this slider can use a script.
Definition: gui_slider.cpp:45
void set_thumb_draw_layer(layer thumb_layer)
Sets the draw layer of this slider's thumb texture.
Definition: gui_slider.cpp:280
void set_value_step(float value_step)
Sets this slider's value step.
Definition: gui_slider.cpp:232
float get_min_value() const
Returns this slider's minimum value.
Definition: gui_slider.cpp:287
void set_max_value(float max_value)
Sets this slider's maximum value.
Definition: gui_slider.cpp:182
bool are_clicks_outside_thumb_allowed() const
Checks if clicks are allowed outside of the thumb.
Definition: gui_slider.cpp:315
slider(utils::control_block &block, manager &mgr, const frame_core_attributes &attr)
Constructor.
Definition: gui_slider.cpp:22
void copy_from(const region &obj) override
Copies a region's parameters into this slider (inheritance).
Definition: gui_slider.cpp:92
void set_allow_clicks_outside_thumb(bool allow)
Allows the user to click anywhere in the slider to relocate the thumb.
Definition: gui_slider.cpp:311
float get_max_value() const
Returns this slider's maximum value.
Definition: gui_slider.cpp:291
std::string serialize(const std::string &tab) const override
Prints all relevant information about this region in a string.
Definition: gui_slider.cpp:31
A layered_region that can draw images and colored rectangles.
Definition: gui_texture.hpp:23
layer
ID of a layer for rendering inside a frame.
vector2< float > vector2f
Holds 2D coordinates (as floats)
void step_value(float &value, float step)
Definition: gui_slider.cpp:15
Struct holding all the core information about a frame necessary for its creation.
Struct holding all the core information about a region necessary for its creation.
std::vector< utils::observer_ptr< const region > > inheritance