lxgui
input_dispatcher.cpp
1 #include "lxgui/input_dispatcher.hpp"
2 
3 #include "lxgui/gui_event_emitter.hpp"
4 #include "lxgui/gui_event_receiver.hpp"
5 #include "lxgui/gui_out.hpp"
6 #include "lxgui/input_source.hpp"
7 #include "lxgui/utils_exception.hpp"
8 #include "lxgui/utils_std.hpp"
9 #include "lxgui/utils_string.hpp"
10 
11 #include <iostream>
12 
13 namespace lxgui::input {
14 
15 dispatcher::dispatcher(source& src) : source_(src) {
16  connections_.push_back(src.on_key_pressed.connect([&](key key_id) {
17  // Record press time
18  key_pressed_time_[static_cast<std::size_t>(key_id)] = timer::now();
19  // Forward
20  on_key_pressed(key_pressed_data{key_id});
21  }));
22 
23  connections_.push_back(src.on_key_pressed_repeat.connect([&](key key_id) {
24  // Forward
25  on_key_pressed_repeat(key_pressed_repeat_data{key_id});
26  }));
27 
28  connections_.push_back(src.on_key_released.connect([&](key key_id) {
29  // Forward
30  on_key_released(key_released_data{key_id});
31  }));
32 
33  connections_.push_back(src.on_text_entered.connect([&](std::uint32_t c) {
34  // Forward
35  on_text_entered(text_entered_data{c});
36  }));
37 
38  connections_.push_back(
39  src.on_mouse_pressed.connect([&](mouse_button button_id, gui::vector2f mouse_pos) {
40  // Apply scaling factor to mouse coordinates
41  mouse_pos /= scaling_factor_;
42 
43  // Record press time
44  auto time_last = mouse_pressed_time_[static_cast<std::size_t>(button_id)];
45  auto time_now = timer::now();
46  mouse_pressed_time_[static_cast<std::size_t>(button_id)] = time_now;
47  double click_time = std::chrono::duration<double>(time_now - time_last).count();
48 
49  // Forward
50  on_mouse_pressed(mouse_pressed_data{button_id, mouse_pos});
51 
52  if (click_time < double_click_time_)
53  on_mouse_double_clicked(mouse_double_clicked_data{button_id, mouse_pos});
54  }));
55 
56  connections_.push_back(
57  src.on_mouse_released.connect([&](mouse_button button_id, gui::vector2f mouse_pos) {
58  // Apply scaling factor to mouse coordinates
59  mouse_pos /= scaling_factor_;
60 
61  // Forward
62  bool was_dragged = is_mouse_dragged_ && button_id == mouse_drag_button_;
63  on_mouse_released(mouse_released_data{button_id, mouse_pos, was_dragged});
64 
65  if (was_dragged) {
66  is_mouse_dragged_ = false;
67  on_mouse_drag_stop(mouse_drag_stop_data{button_id, mouse_pos});
68  }
69  }));
70 
71  connections_.push_back(src.on_mouse_wheel.connect([&](float wheel, gui::vector2f mouse_pos) {
72  // Apply scaling factor to mouse coordinates
73  mouse_pos /= scaling_factor_;
74  // Forward
75  on_mouse_wheel(mouse_wheel_data{wheel, mouse_pos});
76  }));
77 
78  connections_.push_back(
79  src.on_mouse_moved.connect([&](gui::vector2f movement, gui::vector2f mouse_pos) {
80  // Apply scaling factor to mouse coordinates
81  movement /= scaling_factor_;
82  mouse_pos /= scaling_factor_;
83 
84  // Forward
85  on_mouse_moved(mouse_moved_data{movement, mouse_pos});
86 
87  if (!is_mouse_dragged_) {
88  std::size_t mouse_button_pressed = std::numeric_limits<std::size_t>::max();
89  for (std::size_t i = 0; i < mouse_button_number; ++i) {
90  if (mouse_is_down(static_cast<mouse_button>(i))) {
91  mouse_button_pressed = i;
92  break;
93  }
94  }
95 
96  if (mouse_button_pressed != std::numeric_limits<std::size_t>::max()) {
97  is_mouse_dragged_ = true;
98  mouse_drag_button_ = static_cast<mouse_button>(mouse_button_pressed);
99  on_mouse_drag_start(mouse_drag_start_data{mouse_drag_button_, mouse_pos});
100  }
101  }
102  }));
103 }
104 
105 bool dispatcher::any_key_is_down() const {
106  const auto& is_key_down = source_.get_key_state().is_key_down;
107  for (std::size_t i = 1; i < key_number; ++i) {
108  if (is_key_down[i])
109  return true;
110  }
111 
112  return false;
113 }
114 
115 bool dispatcher::key_is_down(key key_id) const {
116  return source_.get_key_state().is_key_down[static_cast<std::size_t>(key_id)];
117 }
118 
119 double dispatcher::get_key_down_duration(key key_id) const {
120  if (!key_is_down(key_id))
121  return 0.0;
122 
123  return std::chrono::duration<double>(
124  timer::now() - key_pressed_time_[static_cast<std::size_t>(key_id)])
125  .count();
126 }
127 
128 bool dispatcher::mouse_is_down(mouse_button button_id) const {
129  return source_.get_mouse_state().is_button_down[static_cast<std::size_t>(button_id)];
130 }
131 
132 double dispatcher::get_mouse_down_duration(mouse_button button_id) const {
133  if (!mouse_is_down(button_id))
134  return 0.0;
135 
136  return std::chrono::duration<double>(
137  timer::now() - mouse_pressed_time_[static_cast<std::size_t>(button_id)])
138  .count();
139 }
140 
141 void dispatcher::set_doubleclick_time(double double_click_time) {
142  double_click_time_ = double_click_time;
143 }
144 
145 double dispatcher::get_doubleclick_time() const {
146  return double_click_time_;
147 }
148 
149 bool dispatcher::alt_is_pressed() const {
150  return key_is_down(key::k_lmenu) || key_is_down(key::k_rmenu);
151 }
152 
153 bool dispatcher::shift_is_pressed() const {
154  return key_is_down(key::k_lshift) || key_is_down(key::k_rshift);
155 }
156 
157 bool dispatcher::ctrl_is_pressed() const {
158  return key_is_down(key::k_lcontrol) || key_is_down(key::k_rcontrol);
159 }
160 
161 gui::vector2f dispatcher::get_mouse_position() const {
162  return source_.get_mouse_state().position / scaling_factor_;
163 }
164 
165 float dispatcher::get_mouse_wheel() const {
166  return source_.get_mouse_state().wheel;
167 }
168 
169 const source& dispatcher::get_source() const {
170  return source_;
171 }
172 
173 source& dispatcher::get_source() {
174  return source_;
175 }
176 
177 void dispatcher::set_interface_scaling_factor(float scaling_factor) {
178  scaling_factor_ = scaling_factor;
179 }
180 
181 float dispatcher::get_interface_scaling_factor() const {
182  return scaling_factor_;
183 }
184 
185 } // namespace lxgui::input
dispatcher(source &src)
Initializes this dispatcher with a chosen input source.
The base class for input source implementation.
utils::signal< void(input::key)> on_key_pressed
Signal triggered when a keyboard key is pressed.
connection connect(function_type function)
Connect a new slot to this signal.
vector2< float > vector2f
Holds 2D coordinates (as floats)
constexpr std::size_t key_number
Definition: input_keys.hpp:251
constexpr std::size_t mouse_button_number
Definition: input_keys.hpp:250