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