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