input_manager.hpp 3.61 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/** 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/types.hpp>
#include <mirrage/input/events.hpp>

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

#include <glm/vec2.hpp>
#include <SDL2/SDL.h>
#include <gsl/gsl>
#include <memory>
#include <unordered_map>


24
namespace mirrage {
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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
	namespace asset {
		class Asset_manager;
	}

namespace input {

	class Input_mapper;
	class Input_manager;

	struct Sdl_event_filter {
		Sdl_event_filter(Input_manager&);
		Sdl_event_filter(Sdl_event_filter&&)noexcept;
		Sdl_event_filter& operator=(Sdl_event_filter&&)noexcept;
		virtual ~Sdl_event_filter();
		virtual bool propagate(SDL_Event&) = 0;
		virtual void pre_input_events() {}
		virtual void post_input_events() {}

		private:
			Input_manager* _manager;
	};

	class Input_manager {
		private:
			static constexpr auto _max_pointers = 2;
		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&);

			void screen_to_world_coords(std::function<glm::vec2(glm::vec2)> func) {
				_screen_to_world_coords = func;
			}
			void viewport(glm::vec4 v) {
				_viewport = v;
			}
			void window(SDL_Window* w) {
				_sdl_window = w;
			}

			auto last_pointer_world_position(int idx=0)const noexcept {
				return _pointer_world_pos[gsl::narrow<std::size_t>(idx)];
			}
			auto last_pointer_screen_position(int idx=0)const noexcept {
				return _pointer_screen_pos[gsl::narrow<std::size_t>(idx)];
			}

			auto pointer_world_position(int idx=0)const noexcept {
				auto uidx = gsl::narrow<std::size_t>(idx);
				return _pointer_active[uidx] ? util::justCopy(_pointer_world_pos[uidx]) : util::nothing;
			}
			auto pointer_screen_position(int idx=0)const noexcept {
				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;
	};

}
}