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