rudimentary gamepad controls
[laserbrain_demo] / src / main.cc
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <GL/glew.h>
5 #include <SDL2/SDL.h>
6 #include "app.h"
7
8 static bool init(int argc, char **argv);
9 static void process_event(SDL_Event *ev);
10 static void proc_modkeys();
11
12 static SDL_Window *win;
13 static SDL_GLContext ctx;
14 static bool fullscreen, mouse_grabbed;
15 static bool quit;
16
17 static unsigned int start_time;
18 static unsigned int modkeys;
19
20 SDL_GameController *gamepad;
21
22 static int scale_factor = 1;
23
24 int main(int argc, char **argv)
25 {
26         if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) {
27                 fprintf(stderr, "failed to initialize SDL\n");
28                 return 1;
29         }
30
31         SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
32         SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8);
33         SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1);
34
35         int defpos = SDL_WINDOWPOS_UNDEFINED;
36         unsigned int sdlflags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
37
38         if(!(win = SDL_CreateWindow("demo", defpos, defpos, 1024, 768, sdlflags))) {
39                 // try again without sRGB capability
40                 SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 0);
41                 if(!(win = SDL_CreateWindow("demo", defpos, defpos, 1024, 768, sdlflags))) {
42                         fprintf(stderr, "failed to create window\n");
43                         SDL_Quit();
44                         return 1;
45                 }
46                 fprintf(stderr, "failed to get an sRGB framebuffer.\n");
47         }
48         int val;
49         SDL_GL_GetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, &val);
50         printf("SDL says we %s an sRGB framebuffer\n", val ? "got" : "didn't get");
51
52         if(!(ctx = SDL_GL_CreateContext(win))) {
53                 fprintf(stderr, "failed to create OpenGL context\n");
54                 SDL_Quit();
55                 return 1;
56         }
57         SDL_GL_GetDrawableSize(win, &win_width, &win_height);
58         win_aspect = (float)win_width / (float)win_height;
59
60         printf("detected %d joysticks\n", SDL_NumJoysticks());
61         for(int i=0; i<SDL_NumJoysticks(); i++) {
62                 if(SDL_IsGameController(i)) {
63                         if(!(gamepad = SDL_GameControllerOpen(i))) {
64                                 fprintf(stderr, "failed to open game controller %i: %s\n", i, SDL_GetError());
65                                 continue;
66                         }
67                         printf("Using gamepad: %s\n", SDL_GameControllerNameForIndex(i));
68                 }
69         }
70
71         if(!init(argc, argv)) {
72                 SDL_Quit();
73                 return 1;
74         }
75         app_reshape(win_width, win_height);
76
77         while(!quit) {
78                 SDL_Event ev;
79
80                 time_msec = SDL_GetTicks() - start_time;
81                 while(SDL_PollEvent(&ev)) {
82                         process_event(&ev);
83                         if(quit) goto break_evloop;
84                 }
85
86                 app_display();
87         }
88 break_evloop:
89
90         app_cleanup();
91         SDL_Quit();
92         return 0;
93 }
94
95 void app_swap_buffers()
96 {
97         SDL_GL_SwapWindow(win);
98 }
99
100 void app_quit()
101 {
102         quit = true;
103 }
104
105 unsigned int app_get_modifiers()
106 {
107         return modkeys;
108 }
109
110 void app_resize(int x, int y)
111 {
112         SDL_SetWindowSize(win, x, y);
113 }
114
115 void app_fullscreen(bool fs)
116 {
117         SDL_SetWindowFullscreen(win, fs ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
118         fullscreen = fs;
119 }
120
121 void app_toggle_fullscreen()
122 {
123         app_fullscreen(!fullscreen);
124 }
125
126 bool app_is_fullscreen()
127 {
128         return fullscreen;
129 }
130
131 void app_grab_mouse(bool grab)
132 {
133         if(grab) {
134                 SDL_WarpMouseInWindow(win, win_width / 2, win_height / 2);
135         }
136         //SDL_SetWindowGrab(win, grab ? SDL_TRUE : SDL_FALSE);
137         //SDL_ShowCursor(grab ? 1 : 0);
138         SDL_SetRelativeMouseMode(grab ? SDL_TRUE : SDL_FALSE);
139         mouse_grabbed = grab;
140 }
141
142 void app_toggle_grab_mouse()
143 {
144         app_grab_mouse(!mouse_grabbed);
145 }
146
147 bool app_is_mouse_grabbed()
148 {
149         return mouse_grabbed;
150 }
151
152
153 static bool init(int argc, char **argv)
154 {
155         glewInit();
156
157         if(!app_init(argc, argv)) {
158                 return false;
159         }
160
161         start_time = SDL_GetTicks();
162         return true;
163 }
164
165 static void process_event(SDL_Event *ev)
166 {
167         switch(ev->type) {
168         case SDL_QUIT:
169                 quit = true;
170                 break;
171
172         case SDL_KEYDOWN:
173         case SDL_KEYUP:
174                 proc_modkeys();
175                 app_keyboard(ev->key.keysym.sym, ev->key.state == SDL_PRESSED);
176                 break;
177
178         case SDL_MOUSEBUTTONDOWN:
179         case SDL_MOUSEBUTTONUP:
180                 proc_modkeys();
181                 app_mouse_button(ev->button.button - SDL_BUTTON_LEFT, ev->button.state == SDL_PRESSED,
182                                 ev->button.x * scale_factor, ev->button.y * scale_factor);
183                 break;
184
185         case SDL_MOUSEMOTION:
186                 if(mouse_grabbed) {
187                         // XXX xrel/yrel seems faster by default
188                         app_mouse_delta(ev->motion.xrel * 0.75, ev->motion.yrel * 0.75);
189                 } else {
190                         app_mouse_motion(ev->motion.x * scale_factor, ev->motion.y * scale_factor);
191                 }
192                 break;
193
194         case SDL_WINDOWEVENT:
195                 if(ev->window.event == SDL_WINDOWEVENT_RESIZED) {
196                         SDL_GL_GetDrawableSize(win, &win_width, &win_height);
197                         win_aspect = (float)win_width / (float)win_height;
198                         scale_factor = win_width / ev->window.data1;
199                         app_reshape(win_width, win_height);
200                 }
201                 break;
202
203         case SDL_CONTROLLERAXISMOTION:
204                 app_gamepad_axis(ev->caxis.axis, ev->caxis.value / 65535.0f);
205                 break;
206         }
207 }
208
209 static void proc_modkeys()
210 {
211         modkeys = 0;
212         SDL_Keymod sdlmod = SDL_GetModState();
213         if(sdlmod & KMOD_SHIFT) {
214                 modkeys |= MOD_SHIFT;
215         }
216         if(sdlmod & KMOD_ALT) {
217                 modkeys |= MOD_ALT;
218         }
219         if(sdlmod & KMOD_CTRL) {
220                 modkeys |= MOD_CTRL;
221         }
222 }