1 | #pragma once |
2 | #include <memory> |
3 | #include <functional> |
4 | #include <vector> |
5 | #include "taichi/ui/utils/utils.h" |
6 | |
7 | namespace taichi::ui { |
8 | |
9 | class InputHandler { |
10 | public: |
11 | void key_callback(GLFWwindow *window, |
12 | int key, |
13 | int scancode, |
14 | int action, |
15 | int mode) { |
16 | if (action == GLFW_PRESS) { |
17 | keys_[key] = true; |
18 | } else if (action == GLFW_RELEASE) { |
19 | keys_[key] = false; |
20 | } |
21 | for (auto f : user_key_callbacks_) { |
22 | f(key, action); |
23 | } |
24 | } |
25 | |
26 | void mouse_pos_callback(GLFWwindow *window, double xpos, double ypos) { |
27 | if (first_mouse_) { |
28 | last_x_ = xpos; |
29 | last_y_ = ypos; |
30 | first_mouse_ = false; |
31 | } |
32 | |
33 | last_x_ = xpos; |
34 | last_y_ = ypos; |
35 | |
36 | for (auto f : user_mouse_pos_callbacks_) { |
37 | f(xpos, ypos); |
38 | } |
39 | } |
40 | |
41 | void mouse_button_callback(GLFWwindow *window, |
42 | int button, |
43 | int action, |
44 | int modifier) { |
45 | if (button == GLFW_MOUSE_BUTTON_LEFT) { |
46 | if (action == GLFW_PRESS) { |
47 | left_mouse_down_ = true; |
48 | glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); |
49 | } |
50 | if (action == GLFW_RELEASE) { |
51 | left_mouse_down_ = false; |
52 | glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); |
53 | } |
54 | } |
55 | if (action == GLFW_PRESS) { |
56 | keys_[button] = true; |
57 | } else if (action == GLFW_RELEASE) { |
58 | keys_[button] = false; |
59 | } |
60 | for (auto f : user_mouse_button_callbacks_) { |
61 | f(button, action); |
62 | } |
63 | } |
64 | |
65 | bool is_pressed(int key) { |
66 | return keys_[key]; |
67 | } |
68 | |
69 | float last_x() { |
70 | return last_x_; |
71 | } |
72 | |
73 | float last_y() { |
74 | return last_y_; |
75 | } |
76 | |
77 | void add_key_callback(std::function<void(int, int)> f) { |
78 | user_key_callbacks_.push_back(f); |
79 | } |
80 | void add_mouse_pos_callback(std::function<void(double, double)> f) { |
81 | user_mouse_pos_callbacks_.push_back(f); |
82 | } |
83 | void add_mouse_button_callback(std::function<void(int, int)> f) { |
84 | user_mouse_button_callbacks_.push_back(f); |
85 | } |
86 | |
87 | InputHandler() : keys_(1024, false) { |
88 | } |
89 | |
90 | private: |
91 | bool first_mouse_ = true; |
92 | |
93 | bool left_mouse_down_ = false; |
94 | |
95 | std::vector<bool> keys_; |
96 | float last_x_ = 0; |
97 | float last_y_ = 0; |
98 | |
99 | std::vector<std::function<void(int, int)>> user_key_callbacks_; |
100 | std::vector<std::function<void(double, double)>> user_mouse_pos_callbacks_; |
101 | std::vector<std::function<void(int, int)>> user_mouse_button_callbacks_; |
102 | }; |
103 | |
104 | } // namespace taichi::ui |
105 | |