InputImpl.cpp
1// Copyright 2019 Arthur Sonzogni. All rights reserved.
2// Use of this source code is governed by the MIT license that can be found in
3// the LICENSE file.
4
5#include <GLFW/glfw3.h>
6
7#include <cmath>
8#include <queue>
9#include <smk/Input.hpp>
10#include <smk/InputImpl.hpp>
11#include <vector>
12
13#ifdef __EMSCRIPTEN__
14 #include <emscripten.h>
15 #include <emscripten/html5.h>
16
17 #include <cmath>
18#endif
19
20namespace smk {
21
22void InputImpl::Update(GLFWwindow* window) {
23 int width = 0;
24 int height = 0;
25 glfwGetWindowSize(window, &width, &height);
26
27 // Update key
28 for(auto& it : key_state_) {
29 it.second.second = it.second.first;
30 it.second.first = glfwGetKey(window, it.first);
31 }
32
33 // Update mouse
34 for (auto& it : mouse_state_) {
35 it.second.second = it.second.first;
36 it.second.first = glfwGetMouseButton(window, it.first);
37 }
38
39 // get mouse position
40 double mouse_x = 0.F;
41 double mouse_y = 0.F;
42 glfwGetCursorPos(window, &mouse_x, &mouse_y);
43 mouse_ = glm::vec2(mouse_x, mouse_y);
44
45 // Update cursor.
46 cursor_press_previous_ = cursor_press_;
47 if (!touches_.empty()) {
48 cursor_ = touches_.begin()->second.position();
49 cursor_press_ = true;
50 touching_ = true;
51 } else if (touching_) {
52 touching_ = false;
53 cursor_press_ = false;
54 } else {
55 cursor_ = mouse_;
56 cursor_press_ = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1);
57 }
58
59 // Update scroll.
60 scroll_old_ = scroll_;
61 scroll_ = glm::vec2(0.f, 0.f);
62}
63
64#ifdef __EMSCRIPTEN__
65void InputImpl::OnTouchEvent(int eventType,
66 const EmscriptenTouchEvent* keyEvent) {
67 for (int i = 0; i < keyEvent->numTouches; ++i) {
68 const EmscriptenTouchPoint& touch = keyEvent->touches[i];
69
70 if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART ||
71 eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) {
72 TouchDataPoint data = {
73 glm::vec2(touch.targetX, touch.targetY),
74 0.f,
75 };
76 auto& internal_touch = touches_[touch.identifier];
77 internal_touch.finger_id = touch.identifier;
78 internal_touch.data_points.push_back(data);
79 continue;
80 }
81
82 auto it = touches_.find(touch.identifier);
83 if (it != touches_.end()) {
84 touches_.erase(it);
85 }
86 }
87}
88#endif
89
90void InputImpl::OnScrollEvent(glm::vec2 offset) {
91 scroll_ += offset;
92}
93
95 auto p = key_state_[key];
96 return ((p.first == GLFW_PRESS) && (p.second == GLFW_RELEASE));
97}
98
100 auto p = key_state_[key];
101 return ((p.first == GLFW_RELEASE) && (p.second == GLFW_PRESS));
102}
103
104bool InputImpl::IsKeyHold(int key) {
105 auto p = key_state_[key];
106 return (p.first == GLFW_PRESS);
107}
108
110 auto p = mouse_state_[key];
111 return ((p.first == GLFW_PRESS) && (p.second == GLFW_RELEASE));
112}
113
115 auto p = mouse_state_[key];
116 return ((p.first == GLFW_RELEASE) && (p.second == GLFW_PRESS));
117}
118
119glm::vec2 InputImpl::mouse() const {
120 return mouse_;
121}
122
123std::map<Input::FingerID, Touch>& InputImpl::touches() {
124 return touches_;
125}
126
128 auto p = mouse_state_[key];
129 return (p.first == GLFW_PRESS);
130}
131
133 return cursor_press_ && cursor_press_previous_;
134}
135
137 return cursor_press_ && !cursor_press_previous_;
138}
139
141 return !cursor_press_ && cursor_press_previous_;
142}
143
144glm::vec2 InputImpl::cursor() const {
145 return cursor_;
146}
147glm::vec2 InputImpl::scroll_offset() const {
148 return scroll_old_;
149}
150
151class InputImpl::CharacterListenerImpl
153 public:
154 explicit CharacterListenerImpl(InputImpl* input) : input_(input) {
155 input_->BindCharacterListener(this);
156 }
157 CharacterListenerImpl(CharacterListenerImpl&) = delete;
158 CharacterListenerImpl(CharacterListenerImpl&&) = delete;
159 CharacterListenerImpl& operator=(CharacterListenerImpl&) = delete;
160 CharacterListenerImpl& operator=(CharacterListenerImpl&&) = delete;
161
162 ~CharacterListenerImpl() override { input_->UnBindCharacterListener(this); }
163
164 bool Receive(wchar_t* c) override {
165 if (queue_.empty()) {
166 return false;
167 }
168
169 *c = queue_.front();
170 queue_.pop();
171 return true;
172 }
173
174 InputImpl* input_;
175 std::queue<wchar_t> queue_;
176};
177
178void InputImpl::BindCharacterListener(
179 InputImpl::CharacterListenerImpl* listener) {
180 character_listeners_.insert(listener);
181}
182
183void InputImpl::UnBindCharacterListener(
184 InputImpl::CharacterListenerImpl* listener) {
185 character_listeners_.erase(listener);
186}
187
188void InputImpl::OnCharacterTyped(wchar_t character) {
189 for (const auto& it : character_listeners_) {
190 it->queue_.push(character);
191 }
192}
193
194Input::CharacterListener InputImpl::MakeCharacterListener() {
195 return std::make_unique<CharacterListenerImpl>(this);
196}
197
198} // namespace smk
bool IsKeyHold(int key) override
Whether a keyboard button is down or not.
Definition: InputImpl.cpp:104
bool IsKeyReleased(int key) override
Whether a keyboard button is released or not.
Definition: InputImpl.cpp:99
glm::vec2 cursor() const override
The cursor position.
Definition: InputImpl.cpp:144
bool IsMousePressed(int key) override
Whether a mouse button is pressed or not.
Definition: InputImpl.cpp:109
bool IsCursorHeld() override
Whether the cursor is down or not.
Definition: InputImpl.cpp:132
std::map< FingerID, Touch > & touches() override
The touch states.
Definition: InputImpl.cpp:123
bool IsCursorPressed() override
Whether the cursor is pressed or not.
Definition: InputImpl.cpp:136
glm::vec2 scroll_offset() const override
The mouse/touchpad scrolling offset since the last frame.
Definition: InputImpl.cpp:147
bool IsCursorReleased() override
Whether the cursor is released or not.
Definition: InputImpl.cpp:140
bool IsKeyPressed(int key) override
Whether a keyboard button is pressed or not.
Definition: InputImpl.cpp:94
bool IsMouseReleased(int key) override
Whether a mouse button is released or not.
Definition: InputImpl.cpp:114
bool IsMouseHeld(int key) override
Whether a mouse button is down or not.
Definition: InputImpl.cpp:127
glm::vec2 mouse() const override
The mouse position.
Definition: InputImpl.cpp:119
Receive characters typed from the keyboard. All the keyboard modifiers are applied (Shift,...
Definition: Input.hpp:113