Advanced Strategic Command
events.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  mousesdl.cpp - description
3  -------------------
4  begin : Sun Dec 19 1999
5  copyright : (C) 1999 by Martin Bickel
6  email : bickel@asc-hq.org
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 
19 
20 #include <queue>
21 #include <SDL.h>
22 #include <SDL_thread.h>
23 
24 #include "ctype.h"
25 
26 #include "../events.h"
27 #include "../stack.h"
28 #include "../basegfx.h"
29 #include "../global.h"
30 // #include "keysymbols.h"
31 #include "../errors.h"
32 #include "../util/messaginghub.h"
33 #include "graphicsqueue.h"
34 
36 
37 SDL_mutex* keyboardmutex = NULL;
38 SDL_mutex* eventHandlingMutex = NULL;
39 SDL_mutex* eventQueueMutex = NULL;
40 SDL_mutex* graphicsQueueMutex = NULL;
41 
42 queue<tkey> keybuffer_sym;
43 queue<Uint32> keybuffer_prnt;
44 queue<SDL_Event> eventQueue;
45 bool _queueEvents = true;
47 
48 volatile bool eventThreadRunning = false;
49 
50 
51 std::list<GraphicsQueueOperation*> graphicsQueue;
52 
53 int exitprogram = 0;
54 
55 
56 /***************************************************************************
57  * *
58  * Mouse handling routines *
59  * *
60  ***************************************************************************/
61 
62 
63 bool redrawScreen = false;
64 
65 const bool trueflag = true;
66 
67 const bool* mouseUpdateFlag = &trueflag;
68 
69 void setMouseUpdateFlag( const bool* flag )
70 {
71  mouseUpdateFlag = flag;
72 }
73 
74 
75 void mousevisible( int an)
76 {}
77 
78 
80 {
81  return 2;
82 }
83 
84 int mouseTranslate ( int m)
85 {
86 
87  const int mousetranslate[3] = {
88  0, 2,1
89  } ; // in DOS right button is 1 and center is 2
90 
91  if ( m >= 3 )
92  return m;
93  else
94  return mousetranslate[m];
95 }
96 
97 
98 
99 void setmouseposition ( int x, int y )
100 {}
101 
102 
103 
104 void setnewmousepointer ( void* picture, int hotspotx, int hotspoty )
105 {}
106 
107 
108 int mouseinrect ( int x1, int y1, int x2, int y2 )
109 {
110  if ( mouseparams.x >= x1 && mouseparams.y >= y1 && mouseparams.x <= x2 && mouseparams.y <= y2 )
111  return 1;
112  else
113  return 0;
114 }
115 
116 int mouseinrect ( const tmouserect* rect )
117 {
118  if ( mouseparams.x >= rect->x1 && mouseparams.y >= rect->y1 && mouseparams.x <= rect->x2 && mouseparams.y <= rect->y2 )
119  return 1;
120  else
121  return 0;
122 }
123 
124 
125 
127 {
128  tmouserect c;
129  c.x1 = x1 + b.x1;
130  c.y1 = y1 + b.y1;
131  c.x2 = x2 + b.x2;
132  c.y2 = y2 + b.y2;
133  return c;
134 }
135 
136 
137 
138 /***************************************************************************
139  * *
140  * Keyboard handling routines *
141  * *
142  ***************************************************************************/
143 
144 
145 
146 int keypress( void )
147 {
148  int result = 0;
149  int r = SDL_mutexP ( keyboardmutex );
150  if ( !r ) {
151  result = !keybuffer_sym.empty ( );
152  r = SDL_mutexV ( keyboardmutex );
153  }
154  return result;
155 }
156 
157 void getkeysyms ( tkey* keysym, int* keyprnt )
158 {
159  int found = 0;
160  do {
161  int r = SDL_mutexP ( keyboardmutex );
162  if ( !r ) {
163  if ( !keybuffer_prnt.empty() ) {
164  *keysym = keybuffer_sym.front();
165  *keyprnt = keybuffer_prnt.front();
166  keybuffer_sym.pop();
167  keybuffer_prnt.pop();
168  found++;
169  }
170  r = SDL_mutexV ( keyboardmutex );
171  }
172  if (!found ) {
173  int t = ticker;
174  while ( t + 5 > ticker )
176  }
177  } while ( !found );
178 }
179 
180 
181 char skeypress(tkey keynr)
182 {
183  Uint8 *keystate = SDL_GetKeyState ( NULL );
184  return keystate[ keynr ];
185 }
186 
187 bool isKeyPressed(SDLKey key)
188 {
189  Uint8 *keystate = SDL_GetKeyState ( NULL );
190  return keystate[ key ];
191 }
192 
193 
194 
195 void wait(void)
196 {}
197 
198 
199 
200 tkey char2key(int c )
201 {
202  if ( c < 128 )
203  return tolower(c);
204  else
205  return ct_invvalue;
206 }
207 
208 
209 int releasetimeslice( void )
210 {
211  SDL_Delay(10);
212  if ( redrawScreen ) {
213  redrawScreen = false;
214  copy2screen();
215  }
216  return 0;
217 }
218 
219 
220 
221 
222 
223 
224 
225 
226 /***************************************************************************
227  * *
228  * Timer routines *
229  * *
230  ***************************************************************************/
231 
232 
233 
234 volatile int ticker = 0; // was static, but I think this needs to be global somewhere
235 
236 void ndelay(int time)
237 {
238  long l;
239 
240  l = ticker;
241  do {
243  } while (ticker - l > time);
244 }
245 
246 
247 int tticker = 0;
248 
249 void starttimer(void)
250 {
251  tticker = ticker;
252 }
253 
255 {
256  if (tticker + time <= ticker) return 1;
257  else return 0;
258 }
259 
260 
261 
262 /***************************************************************************
263  * *
264  * Event handling routines *
265  * *
266  ***************************************************************************/
267 
268 #include <iostream>
269 
270 volatile int closeEventThread = 0;
271 
272 const int keyTranslationNum = 7;
273 int keyTranslation[keyTranslationNum][2] = { { 228, 132 }, // "a
274  { 246, 148 }, // "o
275  { 252, 129 }, // "u
276  { 196, 142 }, // "A
277  { 214, 153 }, // "O
278  { 220, 154 }, // "U
279  { 223, 225 } }; // sz
280 
281 
283 {
284  SDL_mutexP ( eventHandlingMutex );
285 }
286 
288 {
289  SDL_mutexV ( eventHandlingMutex );
290 }
291 
292 
294 {
295  EventHandlingMutex ehm;
296 
297  SDL_Event event;
298  int result;
299  if ( SDL_PollEvent ( &event ) == 1) {
301  switch ( event.type ) {
302  case SDL_MOUSEBUTTONUP:
303  case SDL_MOUSEBUTTONDOWN:
304  {
305  int taste = mouseTranslate(event.button.button - 1);
306  int state = event.button.type == SDL_MOUSEBUTTONDOWN;
307  if ( state )
308  mouseparams.taste |= (1 << taste);
309  else
310  mouseparams.taste &= ~(1 << taste);
311  mouseparams.x = event.button.x;
312  mouseparams.y = event.button.y;
313  }
314  break;
315 
316  case SDL_MOUSEMOTION:
317  {
318  mouseparams.x = event.motion.x;
319  mouseparams.y = event.motion.y;
320  mouseparams.x1 = event.motion.x;
321  mouseparams.y1 = event.motion.y;
322  mouseparams.taste = 0;
323  for ( int i = 0; i < 3; i++ )
324  if ( event.motion.state & (1 << i) )
325  mouseparams.taste |= 1 << mouseTranslate(i);
326  }
327  break;
328  case SDL_KEYDOWN:
329  {
330  int r = SDL_mutexP ( keyboardmutex );
331  if ( !r ) {
332  tkey key = event.key.keysym.sym;
333  if ( event.key.keysym.mod & KMOD_ALT )
334  key |= ct_altp;
335  if ( event.key.keysym.mod & KMOD_CTRL )
336  key |= ct_stp;
337  if ( event.key.keysym.mod & KMOD_SHIFT )
338  key |= ct_shp;
339  keybuffer_sym.push ( key );
340 
341  int newsym = event.key.keysym.unicode;
342  for ( int i = 0; i < keyTranslationNum; i++ )
343  if ( event.key.keysym.unicode == keyTranslation[i][0] )
344  newsym = keyTranslation[i][1];
345  keybuffer_prnt.push ( newsym );
346  r = SDL_mutexV ( keyboardmutex );
347  }
348  }
349  break;
350  case SDL_KEYUP:
351  {}
352  break;
353 
354  case SDL_QUIT:
355  exitprogram = 1;
356  break;
357 #ifdef _WIN32_
358  case SDL_ACTIVEEVENT:
359  redrawScreen = true;
360  break;
361 #endif
362  }
363  } else {
364 #ifdef _WIN32_
365  if ( event.type == SDL_ACTIVEEVENT ) {
366  queueOperation( new UpdateRectOp( SDL_GetVideoSurface(), 0,0,0,0), false, true );
367  }
368 #endif
369 
370  }
371  result = 1;
372  if ( _queueEvents ) {
373  SDL_mutexP( eventQueueMutex );
374  eventQueue.push ( event );
375  SDL_mutexV( eventQueueMutex );
376  }
377 
378 
379  } else
380  result = 0;
381 
382  return result;
383 }
384 
385 #if defined(_WIN32_) || defined(__APPLE__)
386 #define FirstThreadEvents 1
387 #endif
388 
389 bool syncGraphics = true;
390 
391 
392 sigc::signal<void,const SDL_Surface*> postScreenUpdate;
393 
394 void queueOperation( GraphicsQueueOperation* gqo, bool wait, bool forceAsync )
395 {
396  if ( !eventThreadRunning ) {
397  gqo->execute();
398  delete gqo;
399  return;
400  }
401 
402  SDL_mutexP( graphicsQueueMutex );
403  graphicsQueue.push_back( gqo );
404  SDL_mutexV( graphicsQueueMutex );
405 
406  if ( forceAsync )
407  return;
408 
409  if ( syncGraphics || wait ) {
410  bool finished = false;
411  do {
412  SDL_Delay(10);
413  SDL_mutexP( graphicsQueueMutex );
414  finished = graphicsQueue.empty();
415  SDL_mutexV( graphicsQueueMutex );
416  } while (!finished);
417  }
418 }
419 
420 
422 {
423  if ( *mouseUpdateFlag )
424  SDL_ShowCursor( 0 );
425 
426  SDL_UpdateRect( screen, x,y,w,h);
428 
429  if ( *mouseUpdateFlag )
430  SDL_ShowCursor( 1 );
431 };
432 
433 
434 UpdateRectsOp::UpdateRectsOp( SDL_Surface *screen, int numrects, SDL_Rect *rects)
435 {
436  this->numrects = numrects;
437  this->rects = new SDL_Rect[numrects];
438  for ( int i = 0; i< numrects; ++i )
439  this->rects[i] = rects[i];
440  this->screen = screen;
441 };
442 
444 {
445  delete[] rects;
446 }
447 
449 {
450  if ( *mouseUpdateFlag )
451  SDL_ShowCursor( 0 );
452 
453  SDL_UpdateRects( screen, numrects, rects);
455 
456  if ( *mouseUpdateFlag )
457  SDL_ShowCursor( 1 );
458 }
459 
460 
462 {
463  if ( *mouseUpdateFlag )
464  SDL_ShowCursor( 0 );
465 
466  SDL_Surface* screen = SDL_SetVideoMode(x, y, depth, flags);
467  if (screen == NULL)
468  screen = SDL_SetVideoMode(x, y, depth, flags & ~SDL_FULLSCREEN );
469 
470  srf( screen );
471  initASCGraphicSubsystem( screen );
472 
473  if ( *mouseUpdateFlag )
474  SDL_ShowCursor( 1 );
475 };
476 
477 
479 {
480 #ifdef FirstThreadEvents
481  GraphicsQueueOperation* gqo = NULL;
482  SDL_mutexP( graphicsQueueMutex );
483  if ( !graphicsQueue.empty() ) {
484  gqo = graphicsQueue.front();
485  SDL_mutexV( graphicsQueueMutex );
486  if ( gqo ) {
487  gqo->execute();
488 
489  SDL_mutexP( graphicsQueueMutex );
490  graphicsQueue.pop_front();
491  SDL_mutexV( graphicsQueueMutex );
492  delete gqo;
493  return true;
494  } else
495  return false;
496  } else {
497  SDL_mutexV( graphicsQueueMutex );
498  return false;
499  }
500 #else
501  return false;
502 #endif
503 }
504 
505 int eventthread ( void* nothing )
506 {
507 #ifdef FirstThreadEvents
508  eventThreadRunning = true;
509 #endif
510  while ( !closeEventThread ) {
511  if ( !processEvents() )
512  SDL_Delay(10);
514  ticker = getTicker();
515  }
516 #ifdef FirstThreadEvents
517  eventThreadRunning = false;
518  while ( processGraphicsQueue() )
519  SDL_Delay(10);
520 #endif
521  return closeEventThread;
522 }
523 
524 
526 {
527  return SDL_GetTicks() / 10;
528 }
529 
530 #ifdef FirstThreadEvents
531 int (*_gamethread)(void *);
532 
533 int gameThreadWrapper ( void* data )
534 {
535  try {
536  int res = _gamethread ( data );
537  closeEventThread = 1;
538  return res;
539  }
540 #ifndef WIN32
541  catch ( ... ) {
542  fatalError ("An unhandled exception occured. Quitting application");
543  }
544 #else
545  catch ( ASCexception ) {
546  fatalError ("An unhandled exception occured. Quitting application");
547  }
548 #endif
549  closeEventThread = -1;
550  return -1;
551 }
552 #endif
553 
554 
556 SDL_Thread* secondThreadHandle = NULL;
557 
558 
559 
560 int initializeEventHandling ( int (*gamethread)(void *) , void *data )
561 {
562 
563  mouseparams.xsize = 10;
564  mouseparams.ysize = 10;
565 
566  keyboardmutex = SDL_CreateMutex ();
567  if ( !keyboardmutex ) {
568  printf("creating keyboard mutex failed\n" );
569  exit(1);
570  }
571 
572  eventHandlingMutex = SDL_CreateMutex ();
573  if ( !eventHandlingMutex ) {
574  printf("creating eventHandling mutex failed\n" );
575  exit(1);
576  }
577 
578 
579  eventQueueMutex = SDL_CreateMutex ();
580  if ( !eventQueueMutex ) {
581  printf("creating eventQueueMutex failed\n" );
582  exit(1);
583  }
584 
585  graphicsQueueMutex = SDL_CreateMutex();
586  if ( !graphicsQueueMutex ) {
587  printf("creating graphicsQueueMutex failed\n" );
588  exit(1);
589  }
590 
591  SDL_EnableUNICODE ( 1 );
592  SDL_EnableKeyRepeat ( 250, 30 );
593 
594 
595 #ifdef FirstThreadEvents
596  _gamethread = gamethread;
597  secondThreadHandle = SDL_CreateThread ( gameThreadWrapper, data );
598  int res = eventthread( NULL );
599 #else
600  secondThreadHandle = SDL_CreateThread ( eventthread, NULL );
601  int res = gamethread( data );
602  closeEventThread = 1;
603 #endif
604 
605 
606  SDL_WaitThread ( secondThreadHandle, NULL );
607  return res;
608 }
609 
610 
611 
612 void exit_asc( int returnresult )
613 {
614 #ifndef FirstThreadEvents
615  if ( secondThreadHandle ) {
616  closeEventThread = 1;
617  SDL_WaitThread ( secondThreadHandle, NULL );
618  }
619  exit( returnresult );
620 #else
621  if ( secondThreadHandle ) {
622  throw ThreadExitException();
623  }
624  exit( returnresult );
625 
626 
627 #endif
628 
629 
630 }
631 
632 
633 bool setEventRouting( bool queue, bool legacy )
634 {
635  bool prev = _queueEvents;
636 
638 
639  _queueEvents = queue;
640  if ( !queue ) {
641  // clear all waiting events in the queue
642  SDL_mutexP( eventQueueMutex );
643  while ( !eventQueue.empty())
644  eventQueue.pop();
645  SDL_mutexV( eventQueueMutex );
646  }
647 
648  return prev;
649 }
650 
652 {
654 }
655 
656 
657 bool getQueuedEvent ( SDL_Event& event )
658 {
659  SDL_mutexP( eventQueueMutex );
660  if ( !eventQueue.empty() ) {
661  event = eventQueue.front();
662  eventQueue.pop();
663  SDL_mutexV( eventQueueMutex );
664  return true;
665  }
666  SDL_mutexV( eventQueueMutex );
667  return false;
668 }
669 
670 bool peekEvent ( SDL_Event& event )
671 {
672  SDL_mutexP( eventQueueMutex );
673  if ( !eventQueue.empty() ) {
674  event = eventQueue.front();
675  SDL_mutexV( eventQueueMutex );
676  return true;
677  }
678  SDL_mutexV( eventQueueMutex );
679  return false;
680 }
681 
682 
const bool * mouseUpdateFlag
Definition: events.cpp:67
SDL_mutex * keyboardmutex
Definition: events.cpp:37
volatile bool eventThreadRunning
Definition: events.cpp:48
void setmouseposition(int x, int y)
Definition: events.cpp:99
volatile tmousesettings mouseparams
Definition: events.cpp:35
virtual void execute()=0
#define ct_altp
Definition: keysymbols.h:28
bool redrawScreen
Definition: events.cpp:63
queue< SDL_Event > eventQueue
Definition: events.cpp:44
int mouseTranslate(int m)
Definition: events.cpp:84
int eventthread(void *nothing)
Definition: events.cpp:505
int initializeEventHandling(int(*gamethread)(void *), void *data)
Definition: events.cpp:560
int x1
Definition: events.h:64
int tticker
Definition: events.cpp:247
queue< Uint32 > keybuffer_prnt
Definition: events.cpp:43
int exitprogram
Definition: events.cpp:53
int mouseinrect(int x1, int y1, int x2, int y2)
Definition: events.cpp:108
bool syncGraphics
Definition: events.cpp:389
void execute()
Definition: events.cpp:461
volatile int ticker
Definition: events.cpp:234
void mousevisible(int an)
Definition: events.cpp:75
bool getQueuedEvent(SDL_Event &event)
if the events are being queue, get one.
Definition: events.cpp:657
#define ct_stp
Definition: keysymbols.h:27
void setMouseUpdateFlag(const bool *flag)
passes a references which' value determines if the mouse cursor is hidden on screen updates ...
Definition: events.cpp:69
SDL_mutex * graphicsQueueMutex
Definition: events.cpp:40
bool _fillLegacyEventStructures
Definition: events.cpp:46
bool legacyEventSystemActive()
Definition: events.cpp:651
Uint8 taste
Definition: events.h:95
const int keyTranslationNum
Definition: events.cpp:272
char skeypress(tkey keynr)
Definition: events.cpp:181
void initASCGraphicSubsystem(SDL_Surface *_screen)
Definition: graphics.cpp:42
const bool trueflag
Definition: events.cpp:65
void starttimer(void)
Definition: events.cpp:249
#define ct_invvalue
Definition: keysymbols.h:25
bool processGraphicsQueue()
Definition: events.cpp:478
UpdateRectsOp(SDL_Surface *screen, int numrects, SDL_Rect *rects)
Definition: events.cpp:434
bool time_elapsed(int time)
Definition: events.cpp:254
void ndelay(int time)
Definition: events.cpp:236
queue< tkey > keybuffer_sym
Definition: events.cpp:42
void wait(void)
Definition: events.cpp:195
volatile int closeEventThread
Definition: events.cpp:270
std::list< GraphicsQueueOperation * > graphicsQueue
Definition: events.cpp:51
SDL_Thread * secondThreadHandle
The handle for the second thread; depending on platform this could be the event handling thread or th...
Definition: events.cpp:556
int getmousestatus()
Definition: events.cpp:79
int keyTranslation[keyTranslationNum][2]
Definition: events.cpp:273
bool peekEvent(SDL_Event &event)
gets the next event without removing it from the queue.
Definition: events.cpp:670
sigc::signal< void, const SDL_Surface * > postScreenUpdate
Definition: events.cpp:392
int processEvents()
Definition: events.cpp:293
SDL_mutex * eventQueueMutex
Definition: events.cpp:39
int tkey
Definition: events.h:126
int y2
Definition: events.h:65
void getkeysyms(tkey *keysym, int *keyprnt)
Definition: events.cpp:157
bool isKeyPressed(SDLKey key)
Definition: events.cpp:187
void setnewmousepointer(void *picture, int hotspotx, int hotspoty)
Definition: events.cpp:104
int copy2screen(void)
Definition: graphics.cpp:91
int getTicker()
Definition: events.cpp:525
void queueOperation(GraphicsQueueOperation *gqo, bool wait, bool forceAsync)
Definition: events.cpp:394
enum GameMap::State state
tmouserect operator+(const tmouserect &b) const
Definition: events.cpp:126
bool _queueEvents
Definition: events.cpp:45
#define ct_shp
Definition: keysymbols.h:26
int keypress(void)
Definition: events.cpp:146
int y1
Definition: events.h:64
void fatalError(const ASCString &string)
void exit_asc(int returnresult)
Definition: events.cpp:612
void execute()
Definition: events.cpp:448
int gamethread(void *data)
Definition: sg.cpp:1373
int x2
Definition: events.h:65
SDL_Surface * screen
Definition: graphics.cpp:31
void execute()
Definition: events.cpp:421
bool setEventRouting(bool queue, bool legacy)
Defines what happens with the SDL events.
Definition: events.cpp:633
SDL_mutex * eventHandlingMutex
Definition: events.cpp:38
int releasetimeslice(void)
Definition: events.cpp:209
tkey char2key(int c)
Definition: events.cpp:200
GameTime time
the time in the game, mesured in a turns and moves
Definition: gamemap.h:235