23 #include <type_traits>
32 if (m_event_dispatcher)
45 if (m_event_dispatcher)
56 for (
auto action: m_actions)
64 if (m_event_dispatcher != dispatcher)
68 if (m_event_dispatcher)
73 m_event_dispatcher = dispatcher;
75 if (m_event_dispatcher)
82 m_event_dispatcher = dispatcher;
123 m_gamepad_axis_mappings.emplace_back(&
action, std::move(
mapping));
124 m_actions.emplace(&
action);
129 m_gamepad_button_mappings.emplace_back(&
action, std::move(
mapping));
130 m_actions.emplace(&
action);
136 m_actions.emplace(&
action);
141 m_mouse_button_mappings.emplace_back(&
action, std::move(
mapping));
142 m_actions.emplace(&
action);
147 m_mouse_motion_mappings.emplace_back(&
action, std::move(
mapping));
148 m_actions.emplace(&
action);
153 m_mouse_scroll_mappings.emplace_back(&
action, std::move(
mapping));
154 m_actions.emplace(&
action);
159 auto predicate = [&](
const auto& tuple) ->
bool
161 return std::get<0>(tuple) == &
action;
167 std::erase_if(m_gamepad_axis_mappings, predicate);
171 std::erase_if(m_gamepad_button_mappings, predicate);
175 std::erase_if(m_key_mappings, predicate);
179 std::erase_if(m_mouse_button_mappings, predicate);
183 std::erase_if(m_mouse_motion_mappings, predicate);
187 std::erase_if(m_mouse_scroll_mappings, predicate);
195 for (
const auto& entry: m_gamepad_axis_mappings)
197 if (std::get<0>(entry) == &
action)
202 for (
const auto& entry: m_gamepad_button_mappings)
204 if (std::get<0>(entry) == &
action)
209 for (
const auto& entry: m_key_mappings)
211 if (std::get<0>(entry) == &
action)
216 for (
const auto& entry: m_mouse_button_mappings)
218 if (std::get<0>(entry) == &
action)
223 for (
const auto& entry: m_mouse_motion_mappings)
225 if (std::get<0>(entry) == &
action)
230 for (
const auto& entry: m_mouse_scroll_mappings)
232 if (std::get<0>(entry) == &
action)
243 auto predicate = [&](
const auto& tuple) ->
bool
245 return std::get<0>(tuple) == &
action;
248 std::erase_if(m_gamepad_axis_mappings, predicate);
249 std::erase_if(m_gamepad_button_mappings, predicate);
250 std::erase_if(m_key_mappings, predicate);
251 std::erase_if(m_mouse_button_mappings, predicate);
252 std::erase_if(m_mouse_motion_mappings, predicate);
253 std::erase_if(m_mouse_scroll_mappings, predicate);
260 m_gamepad_axis_mappings.clear();
261 m_gamepad_button_mappings.clear();
262 m_key_mappings.clear();
263 m_mouse_button_mappings.clear();
264 m_mouse_motion_mappings.clear();
265 m_mouse_scroll_mappings.clear();
283 action->evaluate(0.0f);
289 void action_map::handle_gamepad_button_pressed(
const gamepad_button_pressed_event&
event)
291 for (
const auto& [action, mapping]: m_gamepad_button_mappings)
293 if (mapping.button ==
event.button &&
294 (!mapping.gamepad || mapping.gamepad ==
event.gamepad))
296 action->evaluate(1.0f);
301 void action_map::handle_gamepad_button_released(
const gamepad_button_released_event&
event)
303 for (
const auto& [action, mapping]: m_gamepad_button_mappings)
305 if (mapping.button ==
event.button &&
306 (!mapping.gamepad || mapping.gamepad ==
event.gamepad))
308 action->evaluate(0.0f);
313 void action_map::handle_key_pressed(
const key_pressed_event&
event)
315 for (
const auto& [action, mapping]: m_key_mappings)
317 if (mapping.scancode ==
event.scancode &&
318 (!mapping.keyboard || mapping.keyboard ==
event.keyboard) &&
319 (!mapping.modifiers || (mapping.modifiers &
event.modifiers)))
323 action->evaluate(1.0f);
325 else if (mapping.repeat)
327 action->evaluate(0.0f);
328 action->evaluate(1.0f);
334 void action_map::handle_key_released(
const key_released_event&
event)
336 for (
const auto& [action, mapping]: m_key_mappings)
338 if (mapping.scancode ==
event.scancode &&
339 (!mapping.keyboard || mapping.keyboard ==
event.keyboard))
341 action->evaluate(0.0f);
346 void action_map::handle_mouse_moved(
const mouse_moved_event&
event)
348 for (
const auto& [action, mapping]: m_mouse_motion_mappings)
350 if (!mapping.mouse || mapping.mouse ==
event.mouse)
352 const float difference =
static_cast<float>(
event.difference[
static_cast<std::underlying_type_t<mouse_motion_axis>
>(mapping.axis)]);
357 action->evaluate(0.0f);
363 void action_map::handle_mouse_scrolled(
const mouse_scrolled_event&
event)
365 for (
const auto& [action, mapping]: m_mouse_scroll_mappings)
367 if (!mapping.mouse || mapping.mouse ==
event.mouse)
369 const auto velocity =
event.velocity[
static_cast<std::underlying_type_t<mouse_scroll_axis>
>(mapping.axis)];
371 if (velocity && std::signbit(velocity) == mapping.direction)
373 action->evaluate(
std::abs(velocity));
374 action->evaluate(0.0f);
380 void action_map::handle_mouse_button_pressed(
const mouse_button_pressed_event&
event)
382 for (
const auto& [action, mapping]: m_mouse_button_mappings)
384 if (mapping.button ==
event.button &&
385 (!mapping.mouse || mapping.mouse ==
event.mouse))
387 action->evaluate(1.0f);
392 void action_map::handle_mouse_button_released(
const mouse_button_released_event&
event)
394 for (
const auto& [action, mapping]: m_mouse_button_mappings)
396 if (mapping.button ==
event.button &&
397 (!mapping.mouse || mapping.mouse ==
event.mouse))
399 action->evaluate(0.0f);
404 void action_map::handle_update(
const update_event&
event)
406 for (
const auto* action: m_actions)
414 std::vector<gamepad_axis_mapping> mappings;
416 for (
const auto& [mapped_action,
mapping]: m_gamepad_axis_mappings)
418 if (mapped_action == &
action)
420 mappings.emplace_back(
mapping);
429 std::vector<gamepad_button_mapping> mappings;
431 for (
const auto& [mapped_action,
mapping]: m_gamepad_button_mappings)
433 if (mapped_action == &
action)
435 mappings.emplace_back(
mapping);
444 std::vector<key_mapping> mappings;
446 for (
const auto& [mapped_action,
mapping]: m_key_mappings)
448 if (mapped_action == &
action)
450 mappings.emplace_back(
mapping);
459 std::vector<mouse_button_mapping> mappings;
461 for (
const auto& [mapped_action,
mapping]: m_mouse_button_mappings)
463 if (mapped_action == &
action)
465 mappings.emplace_back(
mapping);
474 std::vector<mouse_motion_mapping> mappings;
476 for (
const auto& [mapped_action,
mapping]: m_mouse_motion_mappings)
478 if (mapped_action == &
action)
480 mappings.emplace_back(
mapping);
489 std::vector<mouse_scroll_mapping> mappings;
491 for (
const auto& [mapped_action,
mapping]: m_mouse_scroll_mappings)
493 if (mapped_action == &
action)
495 mappings.emplace_back(
mapping);
502 void action_map::subscribe()
507 m_subscriptions.emplace_back(m_event_dispatcher->
subscribe<
key_pressed_event>(std::bind_front(&action_map::handle_key_pressed,
this)));
508 m_subscriptions.emplace_back(m_event_dispatcher->
subscribe<
key_released_event>(std::bind_front(&action_map::handle_key_released,
this)));
511 m_subscriptions.emplace_back(m_event_dispatcher->
subscribe<
mouse_moved_event>(std::bind_front(&action_map::handle_mouse_moved,
this)));
512 m_subscriptions.emplace_back(m_event_dispatcher->
subscribe<
mouse_scrolled_event>(std::bind_front(&action_map::handle_mouse_scrolled,
this)));
513 m_subscriptions.emplace_back(m_event_dispatcher->
subscribe<
update_event>(std::bind_front(&action_map::handle_update,
this)));
516 void action_map::unsubscribe()
518 m_subscriptions.clear();
Forwards messages from publishers to subscribers.
std::shared_ptr< subscription > subscribe(subscriber< T > &&subscriber)
Subscribes a function object to messages dispatched by this dispatcher.
constexpr int difference(T x, T y) noexcept
Returns the number of differing bits between two values, known as Hamming distance.
Publish-subscribe messaging.
constexpr vector< T, N > abs(const vector< T, N > &x)
Returns the absolute values of each element.