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