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