gKit2 light
Loading...
Searching...
No Matches
window.cpp
Go to the documentation of this file.
1
3
4#include <cassert>
5#include <cstdio>
6#include <cstdio>
7#include <cstring>
8#include <cmath>
9
10#include <chrono>
11#include <vector>
12#include <set>
13#include <string>
14#include <iostream>
15
16#include "glcore.h"
17#include "window.h"
18#include "files.h"
19
20
21static int width= 0;
22static int height= 0;
24{
25 return width;
26}
28{
29 return height;
30}
31
32static int msaa= 0;
34{
35 return msaa;
36}
37void window_msaa( const int samples )
38{
39 msaa= samples;
40}
41
42static bool srgb= 0;
44{
45 return srgb;
46}
47void window_srgb( const bool flag )
48{
49 srgb= flag;
50}
51
52static std::vector<unsigned char> key_states;
53int key_state( const SDL_Keycode key )
54{
55 SDL_Scancode code= SDL_GetScancodeFromKey(key);
56 assert((size_t) code < key_states.size());
57 return (int) key_states[code];
58}
59void clear_key_state( const SDL_Keycode key )
60{
61 SDL_Scancode code= SDL_GetScancodeFromKey(key);
62 assert((size_t) code < key_states.size());
63 key_states[code]= 0;
64}
65
66static SDL_KeyboardEvent last_key;
67SDL_KeyboardEvent key_event( )
68{
69 return last_key;
70}
72{
73 last_key.type= 0;
74 last_key.keysym.sym= 0;
75}
76
77static SDL_TextInputEvent last_text;
78SDL_TextInputEvent text_event( )
79{
80 return last_text;
81}
83{
84 last_text.text[0]= 0;
85}
86
87static std::vector<std::string> last_drops;
88const std::vector<std::string>& drop_events( )
89{
90 return last_drops;
91}
92
93const char *drop_event( )
94{
95 if(last_drops.empty())
96 return nullptr;
97 else
98 return last_drops.back().c_str();
99}
100
102{
103 last_drops.clear();
104}
105
107{
108 last_drops.clear();
109}
110
111
112static SDL_MouseButtonEvent last_button;
113SDL_MouseButtonEvent button_event( )
114{
115 return last_button;
116}
118{
119 last_button.state= 0;
120}
121
122static SDL_MouseWheelEvent last_wheel;
123SDL_MouseWheelEvent wheel_event( )
124{
125 return last_wheel;
126}
128{
129 last_wheel.x= 0;
130 last_wheel.y= 0;
131}
132
133
134//
135static std::chrono::high_resolution_clock::time_point app_start= {};
136static std::chrono::high_resolution_clock::time_point last_time= {};
137static float last_delta= 0;
138
140{
141 std::chrono::high_resolution_clock::time_point now= std::chrono::high_resolution_clock::now();
142 last_delta= float(std::chrono::duration_cast<std::chrono::microseconds>(now - last_time).count()) / float(1000);
143 last_time= now;
144
145 return float(std::chrono::duration_cast<std::chrono::microseconds>(now - app_start).count()) / float(1000);
146}
147
149{
150// pas super utile, a virer ?
151 return last_delta;
152}
153
154// etat de l'application.
155static int stop= 0;
156
158int run( Window window, int (*draw)() )
159{
160 // configure openGL
161 glViewport(0, 0, width, height);
162
163 // run
164 while(events(window))
165 {
166 // dessiner
167 if(draw() < 1)
168 stop= 1; // fermer l'application si draw() renvoie 0 ou -1...
169
170 // presenter le resultat
171 SDL_GL_SwapWindow(window);
172 }
173
174 return 0;
175}
176
177static int event_count= 0;
178int last_event_count( ) { return event_count; }
179
180
181int events( Window window )
182{
183 bool resize_event= false;
184
185 // gestion des evenements
186 SDL_Event event;
187 while(SDL_PollEvent(&event))
188 {
189 switch(event.type)
190 {
191 case SDL_WINDOWEVENT:
192 // redimensionner la fenetre...
193 if(event.window.event == SDL_WINDOWEVENT_RESIZED)
194 {
195 // traite l'evenement apres la boucle...
196 resize_event= true;
197
198 // conserve les proportions de la fenetre
199 width= event.window.data1;
200 height= event.window.data2;
201 }
202 break;
203
204 case SDL_DROPFILE:
205 //~ printf("drop file '%s'\n", event.drop.file);
206 last_drops.push_back(std::string(event.drop.file));
207 SDL_free(event.drop.file);
208 break;
209
210 case SDL_TEXTINPUT:
211 // conserver le dernier caractere
212 last_text= event.text;
213 break;
214
215 case SDL_KEYDOWN:
216 // modifier l'etat du clavier
217 if((size_t) event.key.keysym.scancode < key_states.size())
218 {
219 key_states[event.key.keysym.scancode]= 1;
220 last_key= event.key; // conserver le dernier evenement
221 }
222
223 // fermer l'application
224 if(event.key.keysym.sym == SDLK_ESCAPE)
225 stop= 1;
226 break;
227
228 case SDL_KEYUP:
229 // modifier l'etat du clavier
230 if((size_t) event.key.keysym.scancode < key_states.size())
231 {
232 key_states[event.key.keysym.scancode]= 0;
233 last_key= event.key; // conserver le dernier evenement
234 }
235 break;
236
237 case SDL_MOUSEBUTTONDOWN:
238 case SDL_MOUSEBUTTONUP:
239 last_button= event.button;
240 break;
241
242 case SDL_MOUSEWHEEL:
243 last_wheel= event.wheel;
244 break;
245
246 case SDL_QUIT:
247 stop= 1; // fermer l'application
248 break;
249 }
250 }
251
252 if(resize_event)
253 {
254 glViewport(0, 0, width, height);
255 }
256
257 return 1 - stop;
258}
259
260
262Window create_window( const int w, const int h, const int major, const int minor )
263{
264 // init sdl
265 if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0)
266 {
267 printf("[error] SDL_Init() failed:\n%s\n", SDL_GetError());
268 return nullptr;
269 }
270
271 // enregistre le destructeur de sdl
272 atexit(SDL_Quit);
273
274 // configuration openGL
275#ifndef GK_OPENGLES
276 printf("creating window(%d, %d) openGL %d.%d....\n", w, h, major, minor);
277
278 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
279 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
280#ifndef GK_RELEASE
281 SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
282#endif
283 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
284
285 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
286 SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, srgb ? 1 : 0);
287 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
288
289 if(msaa > 1)
290 {
291 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
292 SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, msaa);
293 }
294
295#else
296 printf("creating window(%d, %d) openGL ES 3.0...\n", w, h);
297
298 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
299 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
300 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
301 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
302#endif
303
304 // creer la fenetre
305 Window window= SDL_CreateWindow("gKit",
306 SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h,
307 SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
308 if(window == nullptr)
309 {
310 printf("[error] SDL_CreateWindow() failed.\n");
311 return nullptr;
312 }
313
314 // recupere l'etat du clavier
315 int keys;
316 const unsigned char *state= SDL_GetKeyboardState(&keys);
317 key_states.assign(state, state + keys);
318
319 SDL_SetWindowDisplayMode(window, nullptr);
320 SDL_StartTextInput();
321
322 // conserve les dimensions de la fenetre
323 SDL_GetWindowSize(window, &width, &height);
324
325 return window;
326}
327
328void release_window( Window window )
329{
330 SDL_StopTextInput();
331 SDL_DestroyWindow(window);
332}
333
334
335#ifndef NO_GLAD
336#ifndef GK_RELEASE
338static
339void DEBUGCALLBACK debug_print( GLenum source, GLenum type, unsigned int id, GLenum severity, GLsizei length,
340 const char *message, const void *userParam )
341{
342 static std::set<std::string> log;
343 if(log.insert(message).second == false)
344 // le message a deja ete affiche, pas la peine de recommencer 60 fois par seconde.
345 return;
346
347 if(severity == GL_DEBUG_SEVERITY_HIGH)
348 printf("[openGL error]\n%s\n", message);
349 else if(severity == GL_DEBUG_SEVERITY_MEDIUM)
350 printf("[openGL warning]\n%s\n", message);
351 else
352 printf("[openGL message]\n%s\n", message);
353}
354#endif
355#endif
356
358Context create_context( Window window )
359{
360 if(window == nullptr)
361 return nullptr;
362
363 Context context= SDL_GL_CreateContext(window);
364 if(context == nullptr)
365 {
366 printf("[error] creating openGL context.\n");
367 return nullptr;
368 }
369
370 if(SDL_GL_SetSwapInterval(-1) != 0)
371 printf("[warning] can't set adaptive vsync...\n");
372
373 if(SDL_GL_GetSwapInterval() != -1)
374 {
375 printf("vsync ON\n");
376 SDL_GL_SetSwapInterval(1);
377 }
378 else
379 printf("adaptive vsync ON\n");
380
381 {
382 int n= 0;
383 SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &n);
384 if(n > 1)
385 printf("MSAA %d samples\n", n);
386 msaa= n;
387 }
388
389 {
390 int bits= 0;
391 SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &bits);
392 if(bits > 0)
393 printf("Zbuffer %d bits\n", bits);
394 }
395
396 {
397 int flag= 0;
398 SDL_GL_GetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, &flag);
399 if(flag)
400 printf("sRGB framebuffer ON\n");
401
402 srgb= flag;
403 }
404
405 //
406 app_start= std::chrono::high_resolution_clock::now();
407
408#ifndef NO_GLAD
409 // initialise les extensions opengl
410 gladLoadGL();
411
412 // purge les erreurs opengl generees par glew !
413 while(glGetError() != GL_NO_ERROR) {;}
414
415#ifndef GK_RELEASE
416 // configure l'affichage des messages d'erreurs opengl, si l'extension est disponible
417 // inclut dans openGL 4.3, mais pas dispo sur mac...
418 if(GLAD_GL_ARB_debug_output)
419 {
420 printf("debug output enabled...\n");
421 // selectionne tous les messages
422 glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
423 // desactive les messages du compilateur de shaders
424 glDebugMessageControlARB(GL_DEBUG_SOURCE_SHADER_COMPILER, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_FALSE);
425
426 glDebugMessageCallbackARB(debug_print, NULL);
427 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
428 }
429#endif
430#endif
431
432 if(srgb)
433 glEnable(GL_FRAMEBUFFER_SRGB);
434
435
436 return context;
437}
438
439void release_context( Context context )
440{
441 SDL_GL_DeleteContext(context);
442}
443
444
445static std::string smartpath;
446static std::string path;
447
448const char *smart_path( const char *filename )
449{
450 if(exists(filename))
451 return filename;
452
453 if(path.empty())
454 {
455 // recupere la variable d'environnement, si elle existe
456 const char *envbase= std::getenv("GKIT_BASE_PATH");
457 if(envbase != nullptr)
458 {
459 path= std::string(envbase);
460 if(!path.empty() && path[path.size() -1] != '/')
461 {
462 path.append("/"); // force un /, si necessaire
463 printf("[base path] %s\n", path.c_str());
464 }
465 }
466 }
467
468 if(path.empty())
469 {
470 char *base= SDL_GetBasePath();
471 printf("[base path] %s\n", base);
472 path= base;
473 SDL_free(base);
474 }
475
476 smartpath= path + filename;
477 if(exists(smartpath.c_str()))
478 return smartpath.c_str();
479
480 smartpath= path + "../" + filename;
481 if(exists(smartpath.c_str()))
482 return smartpath.c_str();
483
484 return filename; // echec, fichier pas trouve, renvoie quand meme le fichier original.
485 // (permet au moins d'afficher l'erreur fichier non trouve dans l'application)
486}
const char * smart_path(const char *filename)
renvoie le chemin(path) vers le fichier 'filename' apres l'avoir cherche dans un repertoire standard....
Definition window.cpp:448
bool window_srgb()
renvoie le mode srgb de la fenetre de l'application.
Definition window.cpp:43
SDL_MouseButtonEvent button_event()
renvoie le dernier evenement. etat des boutons de la souris.
Definition window.cpp:113
Context create_context(Window window)
cree et configure un contexte opengl
Definition window.cpp:358
void clear_button_event()
desactive l'evenement.
Definition window.cpp:117
void clear_drop_events()
desactive drag/drop.
Definition window.cpp:106
int events(Window window)
fonction interne de gestion d'evenements.
Definition window.cpp:181
const std::vector< std::string > & drop_events()
drag/drop. recupere tous les fichiers.
Definition window.cpp:88
int window_height()
renvoie la hauteur de la fenetre de l'application.
Definition window.cpp:27
SDL_TextInputEvent text_event()
renvoie le dernier evenement. saisie de texte.
Definition window.cpp:78
void release_window(Window window)
destruction de la fenetre.
Definition window.cpp:328
int run(Window window, int(*draw)())
boucle de gestion des evenements de l'application.
Definition window.cpp:158
void clear_key_event()
desactive l'evenement.
Definition window.cpp:71
SDL_KeyboardEvent key_event()
renvoie le dernier evenement. touche speciales.
Definition window.cpp:67
void clear_key_state(const SDL_Keycode key)
desactive une touche du clavier.
Definition window.cpp:59
void printf(Text &text, const int px, const int py, const char *format,...)
affiche un texte a la position x, y. meme utilisation que printf().
Definition text.cpp:140
const char * drop_event()
drag/drop, renvoie le dernier fichier.
Definition window.cpp:93
void clear_drop_event()
desactive drag/drop.
Definition window.cpp:101
void clear_text_event()
desactive l'evenement.
Definition window.cpp:82
Window create_window(const int w, const int h, const int major, const int minor)
creation d'une fenetre pour l'application.
Definition window.cpp:262
void release_context(Context context)
detruit le contexte openGL.
Definition window.cpp:439
void clear_wheel_event()
desactive l'evenement.
Definition window.cpp:127
int key_state(const SDL_Keycode key)
renvoie l'etat d'une touche du clavier. cf la doc SDL2 pour les codes.
Definition window.cpp:53
int window_msaa()
renvoie le nombre de samples MSAA.
Definition window.cpp:33
SDL_MouseWheelEvent wheel_event()
renvoie le dernier evenement. etat de la molette de la souris / glisser sur le pad.
Definition window.cpp:123
int window_width()
renvoie la largeur de la fenetre de l'application.
Definition window.cpp:23
float delta_time()
renvoie le temps ecoule depuis la derniere frame, en millisecondes.
Definition window.cpp:148
float global_time()
renvoie le temps ecoule depuis le lancement de l'application, en millisecondes.
Definition window.cpp:139