e3c8a739d3f35d3963ba50372f69e67b27b35a91
[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 static int translate_keysym(SDL_Keycode sym);
12
13 static SDL_Window *win;
14 static SDL_GLContext ctx;
15 static bool fullscreen, mouse_grabbed;
16 static bool quit;
17
18 static unsigned int start_time;
19 static unsigned int modkeys;
20
21 SDL_GameController *gamepad;
22
23 static int scale_factor = 1;
24
25 int main(int argc, char **argv)
26 {
27         if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) {
28                 fprintf(stderr, "failed to initialize SDL\n");
29                 return 1;
30         }
31
32         SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
33         SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8);
34         SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1);
35 #ifndef NDEBUG
36         SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
37 #endif
38
39         int defpos = SDL_WINDOWPOS_UNDEFINED;
40         unsigned int sdlflags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
41
42         if(!(win = SDL_CreateWindow("demo", defpos, defpos, 1024, 768, sdlflags))) {
43                 // try again without sRGB capability
44                 SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 0);
45                 if(!(win = SDL_CreateWindow("demo", defpos, defpos, 1024, 768, sdlflags))) {
46                         fprintf(stderr, "failed to create window\n");
47                         SDL_Quit();
48                         return 1;
49                 }
50                 fprintf(stderr, "failed to get an sRGB framebuffer.\n");
51         }
52         int val;
53         SDL_GL_GetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, &val);
54         printf("SDL says we %s an sRGB framebuffer\n", val ? "got" : "didn't get");
55         fb_srgb = val;
56
57         if(!(ctx = SDL_GL_CreateContext(win))) {
58                 fprintf(stderr, "failed to create OpenGL context\n");
59                 SDL_Quit();
60                 return 1;
61         }
62         SDL_GL_GetDrawableSize(win, &win_width, &win_height);
63         win_aspect = (float)win_width / (float)win_height;
64
65         printf("detected %d joysticks\n", SDL_NumJoysticks());
66         for(int i=0; i<SDL_NumJoysticks(); i++) {
67                 if(SDL_IsGameController(i)) {
68                         if(!(gamepad = SDL_GameControllerOpen(i))) {
69                                 fprintf(stderr, "failed to open game controller %i: %s\n", i, SDL_GetError());
70                                 continue;
71                         }
72                         printf("Using gamepad: %s\n", SDL_GameControllerNameForIndex(i));
73                 }
74         }
75
76         if(!init(argc, argv)) {
77                 SDL_Quit();
78                 return 1;
79         }
80         app_reshape(win_width, win_height);
81
82         while(!quit) {
83                 SDL_Event ev;
84
85                 time_msec = SDL_GetTicks() - start_time;
86                 while(SDL_PollEvent(&ev)) {
87                         process_event(&ev);
88                         if(quit) goto break_evloop;
89                 }
90
91                 app_display();
92         }
93 break_evloop:
94
95         app_cleanup();
96         SDL_Quit();
97         return 0;
98 }
99
100 void app_swap_buffers()
101 {
102         SDL_GL_SwapWindow(win);
103 }
104
105 void app_quit()
106 {
107         quit = true;
108 }
109
110 unsigned int app_get_modifiers()
111 {
112         return modkeys;
113 }
114
115 void app_resize(int x, int y)
116 {
117         SDL_SetWindowSize(win, x, y);
118 }
119
120 void app_fullscreen(bool fs)
121 {
122         SDL_SetWindowFullscreen(win, fs ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
123         fullscreen = fs;
124 }
125
126 void app_toggle_fullscreen()
127 {
128         app_fullscreen(!fullscreen);
129 }
130
131 bool app_is_fullscreen()
132 {
133         return fullscreen;
134 }
135
136 void app_grab_mouse(bool grab)
137 {
138         if(grab) {
139                 SDL_WarpMouseInWindow(win, win_width / 2, win_height / 2);
140         }
141         //SDL_SetWindowGrab(win, grab ? SDL_TRUE : SDL_FALSE);
142         //SDL_ShowCursor(grab ? 1 : 0);
143         SDL_SetRelativeMouseMode(grab ? SDL_TRUE : SDL_FALSE);
144         mouse_grabbed = grab;
145 }
146
147 void app_toggle_grab_mouse()
148 {
149         app_grab_mouse(!mouse_grabbed);
150 }
151
152 bool app_is_mouse_grabbed()
153 {
154         return mouse_grabbed;
155 }
156
157
158 static bool init(int argc, char **argv)
159 {
160         if(!app_init(argc, argv)) {
161                 return false;
162         }
163
164         start_time = SDL_GetTicks();
165         return true;
166 }
167
168 static void process_event(SDL_Event *ev)
169 {
170         int key;
171
172         switch(ev->type) {
173         case SDL_QUIT:
174                 quit = true;
175                 break;
176
177         case SDL_KEYDOWN:
178         case SDL_KEYUP:
179                 proc_modkeys();
180                 if((key = translate_keysym(ev->key.keysym.sym)) != -1) {
181                         app_keyboard(key, ev->key.state == SDL_PRESSED);
182                 }
183                 break;
184
185         case SDL_MOUSEBUTTONDOWN:
186         case SDL_MOUSEBUTTONUP:
187                 proc_modkeys();
188                 app_mouse_button(ev->button.button - SDL_BUTTON_LEFT, ev->button.state == SDL_PRESSED,
189                                 ev->button.x * scale_factor, ev->button.y * scale_factor);
190                 break;
191
192         case SDL_MOUSEMOTION:
193                 if(mouse_grabbed) {
194                         app_mouse_delta(ev->motion.xrel, ev->motion.yrel);
195                 } else {
196                         app_mouse_motion(ev->motion.x * scale_factor, ev->motion.y * scale_factor);
197                 }
198                 break;
199
200         case SDL_MOUSEWHEEL:
201                 app_mouse_wheel(ev->wheel.y);
202                 break;
203
204         case SDL_WINDOWEVENT:
205                 if(ev->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
206                         SDL_GL_GetDrawableSize(win, &win_width, &win_height);
207                         win_aspect = (float)win_width / (float)win_height;
208                         scale_factor = win_width / ev->window.data1;
209                         app_reshape(win_width, win_height);
210                 }
211                 break;
212
213         case SDL_CONTROLLERAXISMOTION:
214                 app_gamepad_axis(ev->caxis.axis, ev->caxis.value / 32768.0f);
215                 break;
216
217         case SDL_CONTROLLERBUTTONDOWN:
218         case SDL_CONTROLLERBUTTONUP:
219                 app_gamepad_button(ev->cbutton.button, ev->type == SDL_CONTROLLERBUTTONDOWN);
220                 break;
221         }
222 }
223
224 static void proc_modkeys()
225 {
226         modkeys = 0;
227         SDL_Keymod sdlmod = SDL_GetModState();
228         if(sdlmod & KMOD_SHIFT) {
229                 modkeys |= MOD_SHIFT;
230         }
231         if(sdlmod & KMOD_ALT) {
232                 modkeys |= MOD_ALT;
233         }
234         if(sdlmod & KMOD_CTRL) {
235                 modkeys |= MOD_CTRL;
236         }
237 }
238
239 static int translate_keysym(SDL_Keycode sym)
240 {
241         switch(sym) {
242         case SDLK_RETURN:
243                 return '\n';
244         case SDLK_DELETE:
245                 return KEY_DEL;
246         case SDLK_LEFT:
247                 return KEY_LEFT;
248         case SDLK_RIGHT:
249                 return KEY_RIGHT;
250         case SDLK_UP:
251                 return KEY_UP;
252         case SDLK_DOWN:
253                 return KEY_DOWN;
254         case SDLK_PAGEUP:
255                 return KEY_PGUP;
256         case SDLK_PAGEDOWN:
257                 return KEY_PGDOWN;
258         case SDLK_HOME:
259                 return KEY_HOME;
260         case SDLK_END:
261                 return KEY_END;
262         default:
263                 break;
264         }
265
266         if(sym < 127) {
267                 return sym;
268         }
269         if(sym >= SDLK_F1 && sym <= SDLK_F12) {
270                 return KEY_F1 + sym - SDLK_F1;
271         }
272         return -1;
273 }