]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/client/input.c
32c181b24b1e8726c4c5b5b78694547c489175f0
[dragonblocks_alpha.git] / src / client / input.c
1 #include <asprintf/asprintf.h>
2 #include <math.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include "client/camera.h"
6 #include "client/client.h"
7 #include "client/client_config.h"
8 #include "client/client_inventory.h"
9 #include "client/client_player.h"
10 #include "client/debug_menu.h"
11 #include "client/gui.h"
12 #include "client/interact.h"
13 #include "client/input.h"
14 #include "client/screenshot.h"
15 #include "client/window.h"
16 #include "day.h"
17
18 #define SET_STATUS_MESSAGE(args...) { \
19         char *msg; asprintf(&msg, args); \
20         gui_text(status_message, msg); free(msg); \
21         status_message->def.text_color.w = 1.01f; }
22
23 typedef struct {
24         int key;
25         bool state;
26 } KeyListener;
27
28 static bool paused = false;
29
30 static GUIElement *pause_menu;
31 static GUIElement *status_message;
32
33 static KeyListener listener_pause      = {GLFW_KEY_ESCAPE, false};
34 static KeyListener listener_fullscreen = {GLFW_KEY_F11,    false};
35 static KeyListener listener_fly        = {GLFW_KEY_F,      false};
36 static KeyListener listener_collision  = {GLFW_KEY_C,      false};
37 static KeyListener listener_timelapse  = {GLFW_KEY_T,      false};
38 static KeyListener listener_debug_menu = {GLFW_KEY_F3,     false};
39 static KeyListener listener_screenshot = {GLFW_KEY_F2,     false};
40
41 static double cursor_last_x = 0.0;
42 static double cursor_last_y = 0.0;
43
44 // movement mutex needs to be locked
45 static bool move(int forward, int backward, vec3 dir)
46 {
47         // 25.0f; 4.317f
48         f32 sign;
49
50         if (glfwGetKey(window.handle, forward) == GLFW_PRESS)
51                 sign = +1.0f;
52         else if (glfwGetKey(window.handle, backward) == GLFW_PRESS)
53                 sign = -1.0f;
54         else
55                 return false;
56
57         client_player.velocity.x += dir[0] * client_player.movement.speed * sign;
58         client_player.velocity.y += dir[1] * client_player.movement.speed * sign;
59         client_player.velocity.z += dir[2] * client_player.movement.speed * sign;
60
61         return true;
62 }
63
64 static void enter_game()
65 {
66         glfwSetInputMode(window.handle, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
67         pause_menu->visible = false;
68 }
69
70 static bool key_listener(KeyListener *listener)
71 {
72         bool was = listener->state;
73         return !(listener->state = (glfwGetKey(window.handle, listener->key) == GLFW_PRESS)) && was;
74 }
75
76 void input_init()
77 {
78         pause_menu = gui_add(NULL, (GUIElementDef) {
79                 .pos = {0.0f, 0.0f},
80                 .z_index = 0.5f,
81                 .offset = {0, 0},
82                 .margin = {0, 0},
83                 .align = {0.0f, 0.0f},
84                 .scale = {1.0f, 1.0f},
85                 .scale_type = SCALE_PARENT,
86                 .affect_parent_scale = false,
87                 .text = NULL,
88                 .image = NULL,
89                 .text_color = {0.0f, 0.0f, 0.0f, 0.0f},
90                 .bg_color = {0.0f, 0.0f, 0.0f, 0.4f},
91         });
92
93         status_message = gui_add(NULL, (GUIElementDef) {
94                 .pos = {0.5f, 0.25f},
95                 .z_index = 0.1f,
96                 .offset = {0, 0},
97                 .margin = {0, 0},
98                 .align = {0.5f, 0.5f},
99                 .scale = {1.0f, 1.0f},
100                 .scale_type = SCALE_TEXT,
101                 .affect_parent_scale = false,
102                 .text = "",
103                 .image = NULL,
104                 .text_color = {1.0f, 0.91f, 0.13f, 0.0f},
105                 .bg_color = {0.0f, 0.0f, 0.0f, 0.0f},
106         });
107
108         glfwSetInputMode(window.handle, GLFW_STICKY_KEYS, GL_TRUE);
109         enter_game();
110 }
111
112 void input_tick(f64 dtime)
113 {
114         if (status_message->def.text_color.w > 1.0f)
115                 status_message->def.text_color.w = 1.0f;
116         else if (status_message->def.text_color.w > 0.0f)
117                 status_message->def.text_color.w -= dtime * 1.0f;
118
119         if (key_listener(&listener_pause)) {
120                 paused = !paused;
121
122                 if (paused) {
123                         glfwSetInputMode(window.handle, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
124                         pause_menu->visible = true;
125                 } else {
126                         enter_game();
127                 }
128         }
129
130         if (key_listener(&listener_fullscreen)) {
131                 if (window.fullscreen)
132                         window_exit_fullscreen();
133                 else
134                         window_enter_fullscreen();
135         }
136
137         if (!paused) {
138                 if (key_listener(&listener_fly)) {
139                         pthread_rwlock_wrlock(&client_player.lock_movement);
140                         client_player.movement.flight = !client_player.movement.flight;
141
142                         SET_STATUS_MESSAGE("Flight %s", client_player.movement.flight ? "Enabled" : "Disabled")
143                         debug_menu_changed(ENTRY_FLIGHT);
144
145                         pthread_rwlock_unlock(&client_player.lock_movement);
146                 }
147
148                 if (key_listener(&listener_collision)) {
149                         pthread_rwlock_wrlock(&client_player.lock_movement);
150                         client_player.movement.collision = !client_player.movement.collision;
151
152                         SET_STATUS_MESSAGE("Collision %s", client_player.movement.collision ? "Enabled" : "Disabled")
153                         debug_menu_changed(ENTRY_COLLISION);
154
155                         pthread_rwlock_unlock(&client_player.lock_movement);
156                 }
157
158                 if (key_listener(&listener_timelapse)) {
159                         f64 current_time = get_time_of_day();
160                         timelapse = !timelapse;
161                         set_time_of_day(current_time);
162
163                         SET_STATUS_MESSAGE("Timelapse %s", timelapse ? "Enabled" : "Disabled")
164                         debug_menu_changed(ENTRY_TIMELAPSE);
165                 }
166
167                 if (key_listener(&listener_debug_menu))
168                         debug_menu_toggle();
169
170                 if (key_listener(&listener_screenshot)) {
171                         char *screenshot_filename = screenshot();
172                         SET_STATUS_MESSAGE("Screenshot saved to %s", screenshot_filename)
173                         free(screenshot_filename);
174                 }
175         }
176
177         pthread_rwlock_rdlock(&client_player.lock_movement);
178
179         client_player.velocity.x = 0.0f;
180         client_player.velocity.z = 0.0f;
181
182         if (client_player.movement.flight)
183                 client_player.velocity.y = 0.0f;
184
185         if (!paused) {
186                 move(GLFW_KEY_W, GLFW_KEY_S, camera.movement_dirs.front);
187                 move(GLFW_KEY_D, GLFW_KEY_A, camera.movement_dirs.right);
188
189                 if (client_player.movement.flight)
190                         move(GLFW_KEY_SPACE, GLFW_KEY_LEFT_SHIFT, camera.movement_dirs.up);
191                 else if (glfwGetKey(window.handle, GLFW_KEY_SPACE) == GLFW_PRESS)
192                         client_player_jump();
193         }
194
195         pthread_rwlock_unlock(&client_player.lock_movement);
196 }
197
198 void input_cursor(double current_x, double current_y)
199 {
200         if (paused)
201                 return;
202
203         double delta_x = current_x - cursor_last_x;
204         double delta_y = current_y - cursor_last_y;
205         cursor_last_x = current_x;
206         cursor_last_y = current_y;
207
208         ClientEntity *entity = client_player_entity_local();
209         if (!entity)
210                 return;
211
212         pthread_rwlock_wrlock(&entity->lock_pos_rot);
213
214         entity->data.rot.y -= (f32) delta_x * M_PI / 180.0f / 8.0f;
215         entity->data.rot.x += (f32) delta_y * M_PI / 180.0f / 8.0f;
216
217         entity->data.rot.y = fmod(entity->data.rot.y + M_PI * 2.0f, M_PI * 2.0f);
218         entity->data.rot.x = f32_clamp(entity->data.rot.x, -M_PI / 2.0f + 0.01f, M_PI / 2.0f - 0.01f);
219
220         client_player_update_rot(entity);
221         pthread_rwlock_unlock(&entity->lock_pos_rot);
222         refcount_drp(&entity->rc);
223 }
224
225 void input_click(bool left)
226 {
227         if (client_config.swap_mouse_buttons)
228                 left = !left;
229
230         interact_use(left);
231 }