input_manager.hpp 3.86 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
/** initialization & event handling of input devices *************************
 *                                                                           *
 * Copyright (c) 2016 Florian Oetke                                          *
 *  This file is distributed under the MIT License                           *
 *  See LICENSE file for details.                                            *
\*****************************************************************************/

#pragma once

#include <mirrage/input/events.hpp>
11
#include <mirrage/input/types.hpp>
12
13
14

#include <mirrage/utils/messagebus.hpp>
#include <mirrage/utils/str_id.hpp>
15
#include <mirrage/utils/units.hpp>
16

Lotrado's avatar
Lotrado committed
17
#include <SDL.h>
18
#include <glm/vec2.hpp>
19
20
21
22
23
#include <gsl/gsl>
#include <memory>
#include <unordered_map>


24
25
26
namespace mirrage::asset {
	class Asset_manager;
}
27

28
namespace mirrage::input {
29
30
31
32
33
34

	class Input_mapper;
	class Input_manager;

	struct Sdl_event_filter {
		Sdl_event_filter(Input_manager&);
35
36
		Sdl_event_filter(Sdl_event_filter&&) noexcept;
		Sdl_event_filter& operator=(Sdl_event_filter&&) noexcept;
37
38
39
40
41
		virtual ~Sdl_event_filter();
		virtual bool propagate(SDL_Event&) = 0;
		virtual void pre_input_events() {}
		virtual void post_input_events() {}

42
43
	  private:
		Input_manager* _manager;
44
45
46
	};

	class Input_manager {
47
48
	  private:
		static constexpr auto _max_pointers = 2;
49

50
51
52
53
54
55
56
57
58
59
60
	  public:
		Input_manager(util::Message_bus& bus, asset::Asset_manager&);
		Input_manager(const Input_manager&) = delete;
		Input_manager(Input_manager&&)      = delete;
		~Input_manager() noexcept;

		void update(util::Time dt);

		void add_event_filter(Sdl_event_filter&);
		void remove_event_filter(Sdl_event_filter&);

61
62
		void screen_to_world_coords(std::function<glm::vec2(glm::vec2)> func)
		{
63
64
			_screen_to_world_coords = func;
		}
65
66

		auto viewport() const noexcept { return _viewport; }
67
68
		void viewport(glm::vec4 v) { _viewport = v; }
		void window(SDL_Window* w) { _sdl_window = w; }
Florian Oetke's avatar
Florian Oetke committed
69
		auto window() { return _sdl_window; }
70

71
72
		auto last_pointer_world_position(int idx = 0) const noexcept
		{
73
74
			return _pointer_world_pos[gsl::narrow<std::size_t>(idx)];
		}
75
76
		auto last_pointer_screen_position(int idx = 0) const noexcept
		{
77
78
79
			return _pointer_screen_pos[gsl::narrow<std::size_t>(idx)];
		}

80
81
		auto pointer_world_position(int idx = 0) const noexcept
		{
82
83
84
			auto uidx = gsl::narrow<std::size_t>(idx);
			return _pointer_active[uidx] ? util::justCopy(_pointer_world_pos[uidx]) : util::nothing;
		}
85
86
		auto pointer_screen_position(int idx = 0) const noexcept
		{
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
			auto uidx = gsl::narrow<std::size_t>(idx);
			return _pointer_active[uidx] ? util::justCopy(_pointer_screen_pos[uidx]) : util::nothing;
		}

		void enable_context(Context_id id);

		void world_space_events(bool e) { _world_space_events = e; }

		void capture_mouse(bool enable);
		auto capture_mouse() const noexcept { return _mouse_captured; }

	  private:
		void _add_gamepad(int joystick_id);
		void _remove_gamepad(int instance_id);

		void _on_mouse_motion(const SDL_MouseMotionEvent& motion);

		void _poll_events();
105
		void _handle_event(SDL_Event& event, bool filtered);
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128

	  private:
		class Gamepad;

		util::Mailbox_collection _mailbox;

		glm::vec4                             _viewport;
		SDL_Window*                           _sdl_window;
		bool                                  _world_space_events = true;
		bool                                  _mouse_captured     = false;
		glm::vec2                             _mouse_capture_screen_pos;
		std::function<glm::vec2(glm::vec2)>   _screen_to_world_coords;
		std::vector<std::unique_ptr<Gamepad>> _gamepads;

		std::vector<Sdl_event_filter*> _event_filter;

		std::array<glm::vec2, _max_pointers> _pointer_screen_pos{};
		std::array<glm::vec2, _max_pointers> _pointer_world_pos{};
		std::array<bool, _max_pointers>      _pointer_active{};
		std::array<int64_t, _max_pointers>   _pointer_finger_id{};

		std::unique_ptr<Input_mapper> _mapper;
	};
129
} // namespace mirrage::input