input_manager.hpp 3.85 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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
			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();
		void _handle_event(SDL_Event& event);

	  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