src/ui/uInputQueue.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 *************************************************************************
00004 
00005 ArmageTron -- Just another Tron Lightcycle Game in 3D.
00006 Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
00007 
00008 **************************************************************************
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00023 
00024 ***************************************************************************
00025 
00026 */
00027 
00028 #include "uInputQueue.h"
00029 #include "rScreen.h"
00030 #include "tConfiguration.h"
00031 #include <iostream>
00032 
00033 #ifndef DEDICATED
00034 #include "rSDL.h"
00035 #endif
00036 
00037 #include  "tRecorder.h"
00038 
00039 #include  "uMenu.h"
00040 
00041 static su_TimerCallback *timer=NULL;
00042 
00043 su_TimerCallback::su_TimerCallback(){
00044     timer = this;
00045 }
00046 
00047 su_TimerCallback::~su_TimerCallback(){
00048     if (timer == this)
00049         timer = NULL;
00050 }
00051 
00052 static inline REAL Time(){
00053     if (timer)
00054         return timer->GetTime();
00055     else
00056         return 0;
00057 }
00058 
00059 bool su_prefetchInput=false;
00060 bool su_contInput=true;
00061 
00062 #define MAX_PENDING_INPUT 100
00063 
00064 static REAL times[MAX_PENDING_INPUT];
00065 static SDL_Event tEvents[MAX_PENDING_INPUT];
00066 
00067 static int   currentIn=0,current_out=0,next_in=1;
00068 
00069 
00070 static inline void increase(int &i){
00071     i++;
00072     if (i>=MAX_PENDING_INPUT)
00073         i=0;
00074 }
00075 
00076 
00077 static bool input_get=false;
00078 
00079 void su_FetchAndStoreSDLInput()
00080 {
00081 #ifndef DEDICATED
00082 #ifndef WIN32
00083 #ifndef MACOSX
00084     if (!tRecorder::IsRunning() )
00085         SDL_PumpEvents();
00086 #endif
00087 #endif
00088 #endif
00089 }
00090 
00091 
00092 bool su_StoreSDLEvent(const SDL_Event &tEvent){
00093     if (next_in!=current_out && !input_get){
00094         //con << "Extra input!\n";
00095         tEvents[currentIn]=tEvent;
00096         times[currentIn]=Time();
00097         increase(currentIn);
00098         next_in=currentIn;
00099         increase(next_in);
00100         return false;
00101     }
00102     return true;
00103 }
00104 
00105 #ifndef DEDICATED
00106 // read and write operators for keysyms
00107 tRECORDING_ENUM( SDLKey );
00108 tRECORDING_ENUM( SDLMod );
00109 #endif
00110 
00111 static char const * recordingSection = "INPUT";
00112 
00114 template< class Archiver > class EventArchiver
00115 {
00116 public:
00117 #ifndef DEDICATED
00118     static void ArchiveKey( Archiver & archive, SDL_KeyboardEvent & key )
00119     {
00120         archive.Archive(key.state).Archive(key.keysym.scancode).Archive(key.keysym.sym).Archive(key.keysym.mod).Archive(key.keysym.unicode);
00121     }
00122 #endif
00123 
00124     static bool Archive( SDL_Event & event, REAL & time, bool & ret )
00125     {
00126         // start archive block if archiving is active
00127         Archiver archive;
00128         if ( archive.Initialize( recordingSection ) )
00129         {
00130 #ifndef DEDICATED
00131             archive.Archive( ret );
00132             if ( !ret )
00133                 return false;
00134 
00135             // write or read data
00136             archive.Archive(time).Archive(event.type);
00137             switch ( event.type )
00138             {
00139             case SDL_ACTIVEEVENT:
00140             {
00141                 SDL_ActiveEvent & active = event.active;
00142 
00143                 archive.Archive(active.gain).Archive(active.state);
00144             }
00145             break;
00146             case SDL_KEYDOWN:
00147             case SDL_KEYUP:
00148             {
00149                 SDL_KeyboardEvent & key = event.key;
00150                 ArchiveKey( archive, key );
00151             }
00152             break;
00153             case SDL_MOUSEMOTION:
00154             {
00155                 SDL_MouseMotionEvent & motion = event.motion;
00156 
00157                 archive.Archive(motion.state).Archive(motion.x).Archive(motion.y).Archive(motion.xrel).Archive(motion.yrel);
00158             }
00159             break;
00160             case SDL_MOUSEBUTTONUP:
00161             case SDL_MOUSEBUTTONDOWN:
00162             {
00163                 SDL_MouseButtonEvent & button = event.button;
00164 
00165                 archive.Archive(button.button).Archive(button.state).Archive(button.x).Archive(button.y);
00166             }
00167             break;
00168             default:
00169                 // do nothing
00170                 break;
00171             }
00172 
00173 #endif  // DEDICATED
00174 
00175             return true;
00176         }
00177 
00178         return false;
00179     }
00180 };
00181 
00182 #ifndef DEDICATED
00184 template<>
00185 void EventArchiver< tRecordingBlock >::ArchiveKey( tRecordingBlock & archive, SDL_KeyboardEvent & orig )
00186 {
00187     SDL_KeyboardEvent key = orig;
00188     if ( uInputScrambler::Scrambled() )
00189     {
00190         switch( key.keysym.sym )
00191         {
00192         case SDLK_ESCAPE:
00193         case SDLK_SPACE:
00194         case SDLK_KP_ENTER:
00195         case SDLK_RETURN:
00196         case SDLK_UP:
00197         case SDLK_DOWN:
00198         case SDLK_LEFT:
00199         case SDLK_RIGHT:
00200         case SDLK_BACKSPACE:
00201         case SDLK_DELETE:
00202             break;
00203         default:
00204             key.keysym.mod = KMOD_NONE;
00205             key.keysym.sym = SDLK_x;
00206             key.keysym.scancode = 0;
00207             key.keysym.unicode = '*';
00208         }
00209     }
00210 
00211     archive.Archive(key.state).Archive(key.keysym.scancode).Archive(key.keysym.sym).Archive(key.keysym.mod).Archive(key.keysym.unicode);
00212 }
00213 #endif
00214 
00215 static const char * su_end = "END";
00216 static const char * su_endInput = "ENDINPUT";
00217 
00218 // flag indicating input was made and an input start marker is needed for the next input loop
00219 static bool su_markerRequired = false;
00220 
00221 void su_EndGetSDLInput()
00222 {
00223     if ( su_markerRequired )
00224     {
00225         // record end of input fetching
00226         tRecorder::Playback(su_endInput);
00227         tRecorder::Record(su_endInput);
00228         su_markerRequired = false;
00229     }
00230 }
00231 
00232 uInputProcessGuard::uInputProcessGuard()
00233 {}
00234 uInputProcessGuard::~uInputProcessGuard()
00235 {
00236     su_EndGetSDLInput();
00237 }
00238 
00239 int uInputScrambler::scrambled_ = 0;
00240 
00241 uInputScrambler::uInputScrambler()
00242 {
00243     scrambled_ ++;
00244 }
00245 
00246 uInputScrambler::~uInputScrambler()
00247 {
00248     --scrambled_;
00249 }
00250 
00251 bool uInputScrambler::Scrambled()
00252 {
00253     return scrambled_ > 0;
00254 }
00255 
00256 bool su_GetSDLInput(SDL_Event &tEvent,REAL &time){
00257     bool ret=false;
00258 
00259     // clear out data
00260     memset( &tEvent, 0, sizeof( SDL_Event ) );
00261 
00262     // find end of recording in playback
00263     if ( tRecorder::Playback(su_end) )
00264     {
00265         tRecorder::Record(su_end);
00266         uMenu::quickexit=true;
00267     }
00268 
00269     // try to fetch event from playback
00270     if ( !EventArchiver< tPlaybackBlock >::Archive( tEvent, time, ret ) )
00271     {
00272         // get real event
00273         sr_LockSDL();
00274         input_get=true;
00275         if (current_out!=currentIn){
00276             time=times[current_out];
00277             tEvent=tEvents[current_out];
00278             increase(current_out);
00279             ret=true;
00280         }
00281         else{
00282             time=Time();
00283             ret=
00284 #ifndef DEDICATED
00285                 SDL_PollEvent(&tEvent);
00286 #else
00287                 false;
00288 #endif
00289         }
00290         sr_UnlockSDL();
00291         input_get=false;
00292     }
00293 
00294     su_markerRequired |= ret;
00295 
00296     // store event in recording
00297     if ( ret )
00298         EventArchiver< tRecordingBlock >::Archive( tEvent, time, ret );
00299 
00300     return ret;
00301 }
00302 
00303 /*
00304 int su_InputThread(void *){
00305     while (su_contInput){
00306         if (sr_screen && su_prefetchInput){
00307             sr_LockSDL();
00308 #ifndef DEDICATED
00309             SDL_PumpEvents();
00310 #endif
00311             sr_UnlockSDL();
00312         }
00313 #ifndef WIN32
00314         usleep(100000);
00315 #endif
00316     }
00317     return 0;
00318 }
00319 */
00320 
00321 

Generated on Sat Mar 15 22:56:14 2008 for Armagetron Advanced by  doxygen 1.5.4