1#pragma once
2#include <memory>
3#include <functional>
4#include <vector>
5#include "taichi/ui/utils/utils.h"
6
7namespace taichi::ui {
8
9class 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