00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <stdarg.h>
00029 #include "uInput.h"
00030 #include "tMemManager.h"
00031 #include "rScreen.h"
00032 #include "tInitExit.h"
00033 #include "tConfiguration.h"
00034 #include "rConsole.h"
00035 #include "uMenu.h"
00036 #include "tSysTime.h"
00037
00038 #include <vector>
00039 #include <map>
00040
00041 bool su_mouseGrab = false;
00042
00043 static uAction* su_allActions[uMAX_ACTIONS];
00044 static int su_allActionsLen = 0;
00045
00046 uAction::uAction(uAction *&anchor,const char* name,
00047 int priority_,
00048 uInputType t)
00049 :tListItem<uAction>(anchor),type(t),priority(priority_),internalName(name){
00050 globalID = localID = su_allActionsLen++;
00051
00052 tASSERT(localID < uMAX_ACTIONS);
00053
00054 su_allActions[localID] = this;
00055
00056 tString descname;
00057 descname << "input_" << name << "_text";
00058 tToLower( descname );
00059
00060 const_cast<tOutput&>(description).AddLocale(descname);
00061
00062 tString helpname;
00063 helpname << "input_" << name << "_help";
00064 tToLower( helpname );
00065
00066 const_cast<tOutput&>(helpText).AddLocale(helpname);
00067 }
00068
00069 uAction::uAction(uAction *&anchor,const char* name,
00070 const tOutput& desc,
00071 const tOutput& help,
00072 int priority_,
00073 uInputType t)
00074 :tListItem<uAction>(anchor),type(t),priority(priority_),internalName(name), description(desc), helpText(help){
00075 globalID = localID = su_allActionsLen++;
00076
00077 tASSERT(localID < uMAX_ACTIONS);
00078
00079 su_allActions[localID] = this;
00080 }
00081
00082 uAction::~uAction(){
00083 su_allActions[localID] = NULL;
00084 }
00085
00086 uAction * uAction::Find( char const * name )
00087 {
00088 for (int i=su_allActionsLen-1;i>=0;i--)
00089 if (!strcmp(name,su_allActions[i]->internalName))
00090 return su_allActions[i];
00091
00092 return 0;
00093 }
00094
00095
00096
00097
00098
00099 typedef std::vector< uInput * > uInputs;
00100 uInputs su_inputs;
00101 std::map< std::string, uInput * > su_inputMap;
00102
00103 uInput::uInput( tString const & persistentID, tString const & name )
00104 : persistentID_( persistentID ), name_( name )
00105 , pressed_( 0 )
00106 {
00107 ID_ = su_inputs.size();
00108 su_inputs.push_back( this );
00109 su_inputMap[ persistentID ] = this;
00110 }
00111
00112 uInput::~uInput()
00113 {
00114 su_inputs[ID_] = 0;
00115
00116 }
00117
00118 static uInput * su_GetInput( tString const & persistentID )
00119 {
00120 try
00121 {
00122 return su_inputMap[ persistentID ];
00123 }
00124 catch (...)
00125 {
00126 return NULL;
00127 }
00128 }
00129
00130
00131 class uAutoDeleteInput
00132 {
00133 public:
00134 uAutoDeleteInput()
00135 {
00136 }
00137
00138 ~uAutoDeleteInput()
00139 {
00140 for ( uInputs::iterator iter = unknowns.begin(); iter != unknowns.end(); ++iter )
00141 {
00142 delete(*iter);
00143 *iter = 0;
00144 }
00145 }
00146
00147 uInput * Create( tString const & persistentID, tString const & name )
00148 {
00149 uInput * input = new uInput( persistentID, name );
00150 unknowns.push_back( input );
00151 return input;
00152 }
00153
00154
00155 uInputs unknowns;
00156 };
00157
00158 static uAutoDeleteInput & su_GetAutoDeleteInput()
00159 {
00160 static uAutoDeleteInput filler;
00161 return filler;
00162 }
00163
00164 static uInput * su_NewInput( tString const & ID, tString const & name )
00165 {
00166 return su_GetAutoDeleteInput().Create( ID, name );
00167 }
00168
00169 static uInput * su_NewInput( char const * ID, char const * name )
00170 {
00171 return su_GetAutoDeleteInput().Create( tString( ID ), tString( name ) );
00172 }
00173
00174
00175 class uKeyInput
00176 {
00177 public:
00178 uKeyInput()
00179 {
00180 for ( int i = 0; i <= SDLK_LAST; ++i )
00181 {
00182 #ifndef DEDICATED
00183 char const * ID_Raw = SDL_GetKeyName(static_cast< SDLKey >( i ) );
00184 #else
00185 char const * ID_Raw = "unknown key";
00186 #endif
00187 std::ostringstream id;
00188 id << "KEY_";
00189 if ( strcmp( ID_Raw, "unknown key" ) == 0 )
00190 {
00191 id << "UNKNONW_" << i;
00192 }
00193 else
00194 {
00195 for ( char const * c = ID_Raw; *c; ++c )
00196 {
00197 if ( isblank( *c ) )
00198 {
00199 id << "_";
00200 }
00201 else
00202 {
00203 id << char(toupper( *c ));
00204 }
00205 }
00206 }
00207
00208
00209 sdl_keys[i] = su_NewInput( id.str(), tString(ID_Raw) );
00210
00211 tASSERT( sdl_keys[i]->ID() == i );
00212 }
00213 }
00214
00215 ~uKeyInput()
00216 {
00217 }
00218
00219 uInput * sdl_keys[SDLK_LAST+1];
00220 };
00221
00222 static uKeyInput const & su_GetKeyInput()
00223 {
00224 static uKeyInput filler;
00225 return filler;
00226 }
00227
00228 # define MOUSE_BUTTONS 7
00229
00230
00231 class uMouseInput
00232 {
00233 public:
00234 uMouseInput()
00235 {
00236 x_plus = su_NewInput( "MOUSE_X_PLUS", "mouse right" );
00237 x_minus = su_NewInput( "MOUSE_X_MINUS", "mouse left" );
00238 y_plus = su_NewInput( "MOUSE_Y_PLUS", "mouse up" );
00239 y_minus = su_NewInput( "MOUSE_Y_MINUS", "mouse down" );
00240 z_plus = su_NewInput( "MOUSE_Z_PLUS", "mouse z up" );
00241 z_minus = su_NewInput( "MOUSE_Z_MINUS", "mouse z down" );
00242
00243 for ( int i = 0; i < MOUSE_BUTTONS; ++i )
00244 {
00245 std::ostringstream id;
00246 id << "MOUSE_BUTTON_" << i+1;
00247 std::ostringstream name;
00248 name << "mouse button " << i+1;
00249 button[i] = su_NewInput( id.str(), name.str() );
00250 }
00251 }
00252
00253 uInput * x_plus;
00254 uInput * x_minus;
00255 uInput * y_plus;
00256 uInput * y_minus;
00257 uInput * z_plus;
00258 uInput * z_minus;
00259 uInput * button[MOUSE_BUTTONS];
00260 };
00261
00262 static uMouseInput const & su_GetMouseInput()
00263 {
00264 static uMouseInput filler;
00265 return filler;
00266 }
00267
00268 void su_KeyInit()
00269 {
00270 su_GetKeyInput();
00271 su_GetMouseInput();
00272 }
00273
00274
00275
00276
00277
00278 class tConfItem_key:public tConfItemBase{
00279 public:
00280 tConfItem_key():tConfItemBase("KEYBOARD"){}
00281 ~tConfItem_key(){};
00282
00283
00284 virtual void WriteVal(std::ostream &s){
00285 int first=1;
00286 for ( uInputs::const_iterator i = su_inputs.begin(); i != su_inputs.end(); ++i )
00287 {
00288 if ( !(*i)->GetBind() )
00289 continue;
00290
00291 std::string const & id = (*i)->PersistentID();
00292
00293 if (!first)
00294 s << "\nKEYBOARD\t";
00295 else
00296 first=0;
00297
00298 s << id << '\t';
00299 (*i)->GetBind()->Write(s);
00300 }
00301 if (first)
00302 s << "-1";
00303 }
00304
00305
00306 virtual void ReadVal(std::istream &s)
00307 {
00308 tString in;
00309 std::string id;
00310 s >> id;
00311 if ( id != "-1" )
00312 {
00313
00314 uInput * input = su_GetInput( id );
00315
00316 if ( !input )
00317 {
00318
00319 std::istringstream readValue( id );
00320 int value = -1;
00321 readValue >> value;
00322
00323 if ( value >= 0 && value < (int)su_inputs.size() )
00324 {
00325 input = su_inputs[ value ];
00326 }
00327 }
00328
00329 if ( !input )
00330 {
00331 input = su_NewInput( id, tString("") );
00332 }
00333
00334 tASSERT( input );
00335
00336 s >> in;
00337 if (uBindPlayer::IsKeyWord(in))
00338 {
00339 tJUST_CONTROLLED_PTR< uBind > bind = uBindPlayer::NewBind(s);
00340 if ( bind->act )
00341 {
00342 input->SetBind( bind );
00343 }
00344 }
00345 }
00346 char c=' ';
00347 while (c!='\n' && s.good() && !s.eof()) c=s.get();
00348 }
00349 };
00350
00351
00352 static tConfItem_key x;
00353
00354 static uAction *s_playerActions;
00355 static uAction *s_cameraActions;
00356 static uAction *s_globalActions;
00357
00358 uActionPlayer::uActionPlayer(const char *name,
00359 int priority,
00360 uInputType t)
00361 :uAction(s_playerActions,name,priority,t){}
00362
00363 uActionPlayer::uActionPlayer(const char *name,
00364 const tOutput& desc,
00365 const tOutput& help,
00366 int priority,
00367 uInputType t)
00368 :uAction(s_playerActions,name,desc,help,priority,t){}
00369
00370 uActionPlayer::~uActionPlayer(){}
00371
00372 bool uActionPlayer::operator==(const uActionPlayer &x){
00373 return x.globalID == globalID;
00374 }
00375
00376 uActionPlayer *uActionPlayer::Find(int id){
00377 uAction *run = s_playerActions;
00378
00379 while (run){
00380 if (run->ID() == id)
00381 return static_cast<uActionPlayer*>(run);
00382 }
00383
00384 return NULL;
00385 }
00386
00387
00388 uActionCamera::uActionCamera(const char *name,
00389 int priority,
00390 uInputType t)
00391 :uAction(s_cameraActions,name,priority,t){}
00392
00393 uActionCamera::~uActionCamera(){}
00394
00395 bool uActionCamera::operator==(const uActionCamera &x){
00396 return x.globalID == globalID;
00397 }
00398
00399
00400
00401 uActionGlobal::uActionGlobal(const char *name,
00402 int priority,
00403 uInputType t)
00404 :uAction(s_globalActions,name,priority,t){}
00405
00406 uActionGlobal::~uActionGlobal(){}
00407
00408 bool uActionGlobal::operator==(const uActionGlobal &x){
00409 return x.globalID == globalID;
00410 }
00411
00412 bool uActionGlobal::IsBreakingGlobalBind(int sym){
00413 if ( sym >= (int)su_inputs.size() || sym < 0 )
00414 return false;
00415
00416 uInput * input = su_inputs[ sym ];
00417 if ( !input )
00418 return false;
00419
00420 uBind * bind = input->GetBind();
00421 if ( !bind )
00422 return false;
00423
00424 uAction *act = bind->act;
00425 if (!act)
00426 return false;
00427
00428 return uActionGlobalFunc::IsBreakingGlobalBind(act);
00429 }
00430
00431 static void keyboard_init()
00432 {
00433 }
00434
00435 static void keyboard_exit()
00436 {
00437 }
00438
00439 #ifndef NOJOYSTICK
00440
00441 #ifndef DEDICATED
00442 class uJoystick
00443 {
00444 public:
00445 int id;
00446
00447
00448 tString name, internalName;
00449
00450
00451 int numAxes, numButtons, numBalls, numHats;
00452
00453 enum Direction
00454 {
00455 Left = 0,
00456 Right = 1,
00457 Up = 2,
00458 Down = 3
00459 };
00460
00461 uJoystick( int id_ ): id( id_ )
00462 {
00463 tASSERT( id >= 0 && id < SDL_NumJoysticks() );
00464
00465 name = SDL_JoystickName( id );
00466
00467 std::ostringstream iName;
00468 iName << "JOYSTICK_";
00469 for ( char const * c = name.c_str(); *c; ++c )
00470 {
00471 if ( isblank( *c ) )
00472 {
00473 iName << "_";
00474 }
00475 else
00476 {
00477 iName << char(toupper( *c ));
00478 }
00479 }
00480
00481 internalName = iName.str();
00482
00483 SDL_Joystick * stick = SDL_JoystickOpen( id );
00484 numAxes = SDL_JoystickNumAxes( stick );
00485 numButtons = SDL_JoystickNumButtons( stick );
00486 numBalls = SDL_JoystickNumBalls( stick );
00487 numHats = SDL_JoystickNumHats( stick );
00488
00489
00490 if ( numAxes >= 1 )
00491 {
00492 axes[0].push_back( su_NewInput( GetPersistentID( "AXIS", 0, "-" ), GetName( "left" ) ) );
00493 axes[1].push_back( su_NewInput( GetPersistentID( "AXIS", 0, "+" ), GetName( "right" ) ) );
00494 }
00495
00496 if ( numAxes >= 2 )
00497 {
00498 axes[0].push_back( su_NewInput( GetPersistentID( "AXIS", 1, "-" ), GetName( "up" ) ) );
00499 axes[1].push_back( su_NewInput( GetPersistentID( "AXIS", 1, "+" ), GetName( "down" ) ) );
00500 }
00501
00502 for ( int axis = 2; axis < numAxes; ++axis )
00503 {
00504 axes[0].push_back( su_NewInput( GetPersistentID( "AXIS", axis, "-" ), GetName( "axis", axis, "-" ) ) );
00505 axes[1].push_back( su_NewInput( GetPersistentID( "AXIS", axis, "+" ), GetName( "axis", axis, "+" ) ) );
00506 }
00507
00508 for ( int button = 0; button < numButtons; ++button )
00509 {
00510 buttons.push_back( su_NewInput( GetPersistentID( "BUTTON", button ), GetName( "button", button ) ) );
00511 }
00512
00513 char const * directionInternal[] = { "LEFT", "RIGHT", "UP", "DOWN" };
00514 char const * directionHuman[] = { "left", "right", "up", "down" };
00515
00516 for ( int dir = 0; dir < 4; ++dir )
00517 {
00518 char const * internal = directionInternal[dir];
00519 char const * human = directionHuman[dir];
00520
00521 for ( int ball = 0; ball < numBalls; ++ball )
00522 {
00523 balls[dir].push_back( su_NewInput( GetPersistentID( "BALL", ball, internal ), GetName( "ball", ball, human ) ) );
00524 }
00525
00526 for ( int hat = 0; hat < numHats; ++hat )
00527 {
00528 hats[dir].push_back( su_NewInput( GetPersistentID( "HAT", hat, internal ), GetName( "hat", hat, human ) ) );
00529 }
00530 }
00531
00532 hatDirection.resize( numHats );
00533 }
00534
00535 uInput * GetAxis( int index, int dir )
00536 {
00537 tASSERT( index >= 0 && index < numAxes );
00538 tASSERT( 0 == dir || 1 == dir );
00539
00540 axes[1-dir][index]->SetPressed(0);
00541 return axes[dir][index];
00542 }
00543
00544 uInput * GetButton( int index )
00545 {
00546 tASSERT( index >= 0 && index < numButtons );
00547
00548 return buttons[index];
00549 }
00550
00551 uInput * GetBall( int index, Direction dir )
00552 {
00553 tASSERT( index >= 0 && index < numBalls );
00554
00555 balls[dir ^ 1][index]->SetPressed(0);
00556 return balls[dir][index];
00557 }
00558
00559 uInput * GetHat( int index, Direction dir )
00560 {
00561 tASSERT( index >= 0 && index < numHats );
00562
00563 hats[dir ^ 1][index]->SetPressed(0);
00564 return hats[dir][index];
00565 }
00566
00567 int & GetHatDirection( int index, int axis )
00568 {
00569 tASSERT( index >= 0 && index < numHats );
00570 tASSERT( 0 == axis || 1 == axis );
00571
00572 return hatDirection[index].dir[axis];
00573 }
00574 private:
00575
00576 uInputs axes[2], buttons, balls[4], hats[4];
00577
00578 struct HatDirections
00579 {
00580 int dir[2];
00581 HatDirections(){
00582 dir[0] = dir[1] = 0;
00583 }
00584 };
00585
00586 std::vector< HatDirections > hatDirection;
00587
00588
00589 tString GetPersistentID( char const * type, int subID, char const * suffix = NULL ) const
00590 {
00591 std::ostringstream o;
00592 o << internalName << "_" << type << "_" << subID;
00593 if ( suffix )
00594 {
00595 o << "_" << suffix;
00596 }
00597 return o.str();
00598 }
00599
00600
00601 tString GetName( char const * type, int subID, char const * suffix = NULL ) const
00602 {
00603 std::ostringstream o;
00604 o << "Joystick " << id+1 << " " << type << " " << subID+1;
00605 if ( suffix )
00606 {
00607 o << " " << suffix;
00608 }
00609 return o.str();
00610 }
00611
00612
00613 tString GetName( char const * type ) const
00614 {
00615 std::ostringstream o;
00616 o << "Joystick " << id+1 << " " << type;
00617 return o.str();
00618 }
00619 };
00620
00621
00622 class uJoystickInput
00623 {
00624 public:
00625 uJoystickInput()
00626 {
00627
00628 int numJoysticks = SDL_NumJoysticks();
00629 for ( int i = 0; i < numJoysticks; ++i )
00630 {
00631 joysticks.push_back( new uJoystick( i ) );
00632 }
00633 }
00634
00635 ~uJoystickInput()
00636 {
00637
00638 for ( std::vector< uJoystick * >::iterator iter = joysticks.begin(); iter != joysticks.end(); ++iter )
00639 {
00640 delete(*iter);
00641 *iter = 0;
00642 }
00643 }
00644
00645
00646 std::vector< uJoystick * > joysticks;
00647 };
00648
00649 static uJoystickInput & su_GetJoystickInput()
00650 {
00651 static uJoystickInput filler;
00652 return filler;
00653 }
00654
00655 static uJoystick * su_GetJoystick( int id )
00656 {
00657 uJoystickInput & joysticks = su_GetJoystickInput();
00658 tASSERT( id >= 0 && id < (int)joysticks.joysticks.size() );
00659
00660 return joysticks.joysticks[id];
00661 }
00662
00663 void su_JoystickInit()
00664 {
00665 su_GetJoystickInput();
00666 SDL_JoystickEventState( SDL_ENABLE );
00667 }
00668 #endif
00669 #endif
00670
00671 static tInitExit keyboard_ie(&keyboard_init, &keyboard_exit);
00672
00673
00674
00675
00676
00677 uBind::~uBind(){}
00678
00679 uBind::uBind(uAction *a ):lastValue_(0), delayedValue_(0), lastInput_(0), lastTime_(-1), act(a){}
00680
00681 uBind::uBind(std::istream &s): lastValue_(0), delayedValue_(0), lastInput_(0), lastTime_(-1), act(NULL)
00682 {
00683 std::string name;
00684 s >> name;
00685 act = uAction::Find( name.c_str() );
00686 }
00687
00688 void uBind::Write(std::ostream &s){
00689 s << act->internalName << '\t';
00690 }
00691
00692 bool GlobalAct(uAction *act,REAL x){
00693 return uActionGlobalFunc::GlobalAct(act,x);
00694 }
00695
00696 bool uBind::Activate(REAL x, bool delayed )
00697 {
00698 delayedValue_ = x;
00699
00700 if ( !delayed || !Delayable() )
00701 {
00702 lastValue_ = x;
00703 return this->DoActivate( x );
00704 }
00705
00706 return true;
00707 }
00708
00709 void uBind::HanldeDelayed()
00710 {
00711 if ( lastValue_ != delayedValue_ )
00712 {
00713 lastValue_ = delayedValue_;
00714 this->DoActivate( delayedValue_ );
00715 }
00716 }
00717
00718 REAL su_doubleBindTimeout=-10.0f;
00719
00720 bool uBind::IsDoubleBind( uInput const * input )
00721 {
00722 double currentTime = tSysTimeFloat();
00723
00724
00725 bool ret = ( su_doubleBindTimeout > 0 && input != lastInput_ && currentTime - lastTime_ < su_doubleBindTimeout );
00726
00727
00728 lastInput_ = input;
00729 lastTime_ = currentTime;
00730
00731
00732 return ret;
00733 }
00734
00735
00736
00737
00738
00739 static int nextid = 0;
00740
00741 uPlayerPrototype* uPlayerPrototype::PlayerConfig(int i){
00742 tASSERT(i>=0 && i<uMAX_PLAYERS);
00743 return playerConfig[i];
00744 }
00745
00746
00747 uPlayerPrototype::uPlayerPrototype(){
00748 static bool inited=false;
00749 if (!inited)
00750 {
00751 for (int i=uMAX_PLAYERS-1; i >=0; i--)
00752 playerConfig[i] = NULL;
00753
00754 inited = true;
00755 }
00756
00757 id = nextid++;
00758 tASSERT(id < uMAX_PLAYERS);
00759 playerConfig[id] = this;
00760
00761
00762 }
00763
00764 uPlayerPrototype::~uPlayerPrototype(){
00765 playerConfig[id] = NULL;
00766 }
00767
00768 uPlayerPrototype* uPlayerPrototype::playerConfig[uMAX_PLAYERS];
00769
00770 int uPlayerPrototype::Num(){
00771 return nextid;
00772 }
00773
00774
00775
00776
00777
00778 REAL mouse_sensitivity=REAL(.1);
00779
00780
00781 #define su_TRANSFORM_PASSES 2
00782
00783 struct uTransformEventInfo
00784 {
00785 uInput * input;
00786 float value;
00787 bool needsRepeat;
00788
00789 uTransformEventInfo(): input(0), value(0), needsRepeat(false){}
00790 uTransformEventInfo( uInput * input_, float value_ = 1 , bool needsRepeat_ = true ): input(input_), value(value_), needsRepeat(needsRepeat_){}
00791 };
00792
00793
00794 #ifndef DEDICATED
00795 static void su_TransformEvent( SDL_Event & e, std::vector< uTransformEventInfo > & info )
00796 {
00797 switch (e.type)
00798 {
00799 case SDL_MOUSEMOTION:
00800 {
00801
00802 if ( su_mouseGrab &&
00803 e.motion.x==sr_screenWidth/2 && e.motion.x==sr_screenHeight/2)
00804 {
00805 return;
00806 }
00807
00808
00809 info.reserve(4);
00810
00811 REAL xrel=e.motion.xrel;
00812 if (xrel > 0)
00813 {
00814 info.push_back( uTransformEventInfo(
00815 su_GetMouseInput().x_minus,
00816 0,
00817 false ) );
00818 info.push_back( uTransformEventInfo(
00819 su_GetMouseInput().x_plus,
00820 xrel * mouse_sensitivity,
00821 false ) );
00822 }
00823
00824 if (xrel < 0)
00825 {
00826 info.push_back( uTransformEventInfo(
00827 su_GetMouseInput().x_plus,
00828 0,
00829 false ) );
00830 info.push_back( uTransformEventInfo(
00831 su_GetMouseInput().x_minus,
00832 -xrel * mouse_sensitivity,
00833 false ) );
00834 }
00835
00836
00837 REAL yrel=-e.motion.yrel;
00838 if (yrel>0)
00839 {
00840 info.push_back( uTransformEventInfo(
00841 su_GetMouseInput().y_minus,
00842 0,
00843 false ) );
00844 info.push_back( uTransformEventInfo(
00845 su_GetMouseInput().y_plus,
00846 yrel * mouse_sensitivity,
00847 false ) );
00848 }
00849 if (yrel<0)
00850 {
00851 info.push_back( uTransformEventInfo(
00852 su_GetMouseInput().y_plus,
00853 0,
00854 false ) );
00855 info.push_back( uTransformEventInfo(
00856 su_GetMouseInput().y_minus,
00857 -yrel * mouse_sensitivity,
00858 false ) );
00859 }
00860 }
00861 break;
00862 case SDL_MOUSEBUTTONDOWN:
00863 case SDL_MOUSEBUTTONUP:
00864 {
00865 int button=e.button.button;
00866 if (button<=MOUSE_BUTTONS)
00867 {
00868 info.push_back( uTransformEventInfo(
00869 su_GetMouseInput().button[ button ],
00870 ( e.type == SDL_MOUSEBUTTONDOWN ) ? 1 : 0 ) );
00871 }
00872 }
00873 break;
00874 case SDL_KEYDOWN:
00875 case SDL_KEYUP:
00876 {
00877 SDL_keysym &c = e.key.keysym;
00878
00879 info.push_back( uTransformEventInfo(
00880 su_GetKeyInput().sdl_keys[ c.sym ],
00881 ( e.type == SDL_KEYDOWN ) ? 1 : 0 ) );
00882
00883 break;
00884 }
00885 #ifndef NOJOYSTICK
00886 case SDL_JOYAXISMOTION:
00887 {
00888 uJoystick * joystick = su_GetJoystick( e.jaxis.which );
00889 int dir = e.jaxis.value > 0 ? 1 : 0;
00890
00891 info.push_back( uTransformEventInfo(
00892 joystick->GetAxis( e.jaxis.axis, 1-dir ),
00893 0 ) );
00894 info.push_back( uTransformEventInfo(
00895 joystick->GetAxis( e.jaxis.axis, dir ),
00896 fabs( e.jaxis.value )/32768 ) );
00897
00898 break;
00899 }
00900 case SDL_JOYBUTTONDOWN:
00901 case SDL_JOYBUTTONUP:
00902 info.push_back( uTransformEventInfo(
00903 su_GetJoystick( e.jbutton.which )->GetButton( e.jbutton.button ),
00904 ( e.type == SDL_JOYBUTTONDOWN ) ? 1 : 0 ) );
00905 break;
00906 case SDL_JOYHATMOTION:
00907 {
00908 info.reserve(4);
00909
00910 uJoystick * joystick = su_GetJoystick( e.jhat.which );
00911 int hat = e.jhat.hat;
00912 int hatDirection = e.jhat.value;
00913
00914
00915 {
00916 int & lastDir = joystick->GetHatDirection( hat, 0 );
00917 int newDir =
00918 ( ( hatDirection & SDL_HAT_LEFT ) ? -1 : 0 ) +
00919 ( ( hatDirection & SDL_HAT_RIGHT ) ? +1 : 0 );
00920
00921
00922 if ( lastDir < 0 && newDir >= 0 )
00923 {
00924 info.push_back( uTransformEventInfo(
00925 joystick->GetHat( hat, uJoystick::Left ),
00926 0 ) );
00927 }
00928
00929 if ( lastDir > 0 && newDir <= 0 )
00930 {
00931 info.push_back( uTransformEventInfo(
00932 joystick->GetHat( hat, uJoystick::Right ),
00933 0 ) );
00934 }
00935
00936
00937 if ( lastDir >= 0 && newDir < 0 )
00938 {
00939 info.push_back( uTransformEventInfo(
00940 joystick->GetHat( hat, uJoystick::Left ),
00941 1 ) );
00942 }
00943
00944 if ( lastDir <= 0 && newDir > 0 )
00945 {
00946 info.push_back( uTransformEventInfo(
00947 joystick->GetHat( hat, uJoystick::Right ),
00948 1 ) );
00949 }
00950
00951 lastDir = newDir;
00952 }
00953
00954
00955 {
00956 int & lastDir = joystick->GetHatDirection( hat, 1 );
00957 int newDir =
00958 ( ( hatDirection & SDL_HAT_UP ) ? -1 : 0 ) +
00959 ( ( hatDirection & SDL_HAT_DOWN ) ? +1 : 0 );
00960
00961
00962 if ( lastDir < 0 && newDir >= 0 )
00963 {
00964 info.push_back( uTransformEventInfo(
00965 joystick->GetHat( hat, uJoystick::Up ),
00966 0 ) );
00967 }
00968
00969 if ( lastDir > 0 && newDir <= 0 )
00970 {
00971 info.push_back( uTransformEventInfo(
00972 joystick->GetHat( hat, uJoystick::Down ),
00973 0 ) );
00974 }
00975
00976
00977 if ( lastDir >= 0 && newDir < 0 )
00978 {
00979 info.push_back( uTransformEventInfo(
00980 joystick->GetHat( hat, uJoystick::Up ),
00981 1 ) );
00982 }
00983
00984 if ( lastDir <= 0 && newDir > 0 )
00985 {
00986 info.push_back( uTransformEventInfo(
00987 joystick->GetHat( hat, uJoystick::Down ),
00988 1 ) );
00989 }
00990
00991 lastDir = newDir;
00992 }
00993 }
00994 break;
00995 case SDL_JOYBALLMOTION:
00996 {
00997 info.reserve(4);
00998
00999 uJoystick * joystick = su_GetJoystick( e.jball.which );
01000 int ball = e.jball.ball;
01001
01002 REAL xrel=e.jball.xrel;
01003 if (xrel > 0)
01004 {
01005 info.push_back( uTransformEventInfo(
01006 joystick->GetBall( ball, uJoystick::Left ),
01007 0,
01008 false ) );
01009 info.push_back( uTransformEventInfo(
01010 joystick->GetBall( ball, uJoystick::Right ),
01011 xrel,
01012 false ) );
01013 }
01014
01015 if (xrel < 0)
01016 {
01017 info.push_back( uTransformEventInfo(
01018 joystick->GetBall( ball, uJoystick::Right ),
01019 0,
01020 false ) );
01021 info.push_back( uTransformEventInfo(
01022 joystick->GetBall( ball, uJoystick::Left ),
01023 -xrel,
01024 false ) );
01025 }
01026
01027
01028 REAL yrel=-e.jball.yrel;
01029 if (yrel>0)
01030 {
01031 info.push_back( uTransformEventInfo(
01032 joystick->GetBall( ball, uJoystick::Down ),
01033 0,
01034 false ) );
01035 info.push_back( uTransformEventInfo(
01036 joystick->GetBall( ball, uJoystick::Up ),
01037 yrel,
01038 false ) );
01039 }
01040 if (yrel<0)
01041 {
01042 info.push_back( uTransformEventInfo(
01043 joystick->GetBall( ball, uJoystick::Up ),
01044 0,
01045 false ) );
01046 info.push_back( uTransformEventInfo(
01047 joystick->GetBall( ball, uJoystick::Down ),
01048 -yrel,
01049 false ) );
01050 }
01051 }
01052 break;
01053 #endif
01054 default:
01055 break;
01056 }
01057 }
01058 #endif // DEDICATED
01059
01060
01061
01062
01063
01064 class uMenuItemInput: uMenuItem{
01065 uAction *act;
01066 int ePlayer;
01067 bool active;
01068 public:
01069 uMenuItemInput(uMenu *M,uAction *a,int p)
01070 :uMenuItem(M,a->helpText),act(a),ePlayer(p),active(0){
01071 }
01072
01073 virtual ~uMenuItemInput(){}
01074
01075 virtual void Render(REAL x,REAL y,REAL alpha=1,bool selected=0)
01076 {
01077 DisplayText(REAL(x-.02),y,act->description,selected,alpha,1);
01078
01079 if (active)
01080 {
01081 tString s;
01082 s << tOutput("$input_press_any_key");
01083 DisplayText(REAL(x+.02),y,s,selected,alpha,-1);
01084 }
01085 else
01086 {
01087 tString s;
01088
01089 bool first=1;
01090
01091 for ( uInputs::const_iterator i = su_inputs.begin(); i != su_inputs.end(); ++i )
01092 {
01093 uBind * bind = (*i)->GetBind();
01094 if ( bind && (*i)->Name().size() > 0 &&
01095 bind->act==act &&
01096 bind->CheckPlayer(ePlayer) )
01097 {
01098 if (!first)
01099 s << ", ";
01100 else
01101 first=0;
01102
01103 s << (*i)->Name();
01104 }
01105 }
01106 if (!first)
01107 {
01108 DisplayText(REAL(x+.02),y,s,selected,alpha,-1);
01109 }
01110 else
01111 {
01112 DisplayText(REAL(x+.02),y,tOutput("$input_items_unbound"),selected,alpha,-1);
01113 }
01114 }
01115 }
01116
01117 virtual void Enter()
01118 {
01119 active=1;
01120 }
01121
01122 #define MTHRESH 5
01123 #define MREL 2
01124
01125 #ifndef DEDICATED
01126
01127 virtual bool Event(SDL_Event &e){
01128 if ( e.type == SDL_KEYDOWN )
01129 {
01130 SDL_keysym &c = e.key.keysym;
01131 if (!active)
01132 {
01133 if (c.sym==SDLK_DELETE || c.sym==SDLK_BACKSPACE)
01134 {
01135
01136 for ( uInputs::const_iterator i = su_inputs.begin(); i != su_inputs.end(); ++i )
01137 {
01138 uBind * bind = (*i)->GetBind();
01139 if ( bind &&
01140 bind->act==act &&
01141 bind->CheckPlayer(ePlayer) )
01142 {
01143 (*i)->SetBind( NULL );
01144 }
01145 }
01146 return true;
01147 }
01148 return false;
01149 }
01150
01151
01152 if ( c.sym == SDLK_ESCAPE )
01153 {
01154 return false;
01155 }
01156 }
01157
01158
01159 std::vector< uTransformEventInfo > events;
01160 su_TransformEvent( e, events );
01161
01162 for ( std::vector< uTransformEventInfo >::const_iterator i = events.begin(); i != events.end(); ++i )
01163 {
01164 uTransformEventInfo const & info = *i;
01165 if ( info.input && info.value > 0.5 && active )
01166 {
01167 uBind * bind = info.input->GetBind();
01168 if ( bind &&
01169 bind->act==act &&
01170 bind->CheckPlayer(ePlayer))
01171 {
01172 info.input->SetBind( NULL );
01173 }
01174 else
01175 {
01176 info.input->SetBind( uBindPlayer::NewBind(act,ePlayer) );
01177 }
01178
01179 active = false;
01180 return true;
01181 }
01182 }
01183
01184 return false;
01185 }
01186 #endif
01187
01188 virtual tString Help(){
01189 tString ret;
01190 ret << helpText << "\n";
01191 ret << tOutput("$input_item_help");
01192 return ret;
01193 }
01194 };
01195
01196 namespace
01197 {
01198 class Input_Comparator
01199 {
01200 public:
01201 static int Compare( const uAction* a, const uAction* b )
01202 {
01203 if ( a->priority < b->priority )
01204 return 1;
01205 else if ( a->priority > b->priority )
01206 return -1;
01207 return tString::CompareAlphaNumerical( a->internalName, b->internalName );
01208 }
01209 };
01210 }
01211
01212 static int Input_Compare( const tListItemBase* a, const tListItemBase* b)
01213
01214 {
01215 return Input_Comparator::Compare( (const uAction*)a, (const uAction*)b );
01216 }
01217
01218
01219 static void s_InputConfigGeneric(int ePlayer, uAction *&actions,const tOutput &title){
01220 uMenuItemInput **input;
01221
01222 uMenu input_menu(title);
01223
01224 actions->tListItemBase::Sort(&Input_Compare);
01225
01226 int len = actions->Len();
01227
01228 input=tNEW(uMenuItemInput*)[len];
01229 int a=0;
01230 for (uAction *A=actions;A; A = A->Next()){
01231 input[a++]=new uMenuItemInput(&input_menu,
01232 A,
01233 ePlayer+1);
01234
01235 }
01236
01237 input_menu.ReverseItems();
01238 input_menu.Enter();
01239
01240 for (int b=a-1;b>=0;b--)
01241 delete input[b];
01242 delete[] input;
01243 }
01244
01245 void su_InputConfig(int ePlayer){
01246
01247 tOutput name;
01248 name.SetTemplateParameter(1, ePlayer+1);
01249 name.SetTemplateParameter(2, uPlayerPrototype::PlayerConfig(ePlayer)->Name());
01250 name << "$input_for_player";
01251
01252 s_InputConfigGeneric(ePlayer,s_playerActions,name);
01253 }
01254
01255 void su_InputConfigCamera(int player){
01256
01257 tOutput name;
01258 name.SetTemplateParameter(1, uPlayerPrototype::PlayerConfig(player)->Name());
01259 name << "$camera_controls";
01260
01261 s_InputConfigGeneric(player,s_cameraActions,name);
01262 }
01263
01264 void su_InputConfigGlobal(){
01265 s_InputConfigGeneric(-1,s_globalActions,"$input_items_global");
01266 }
01267
01268
01269 REAL key_sensitivity=40;
01270 static double lastTime=0;
01271 static REAL ts=0;
01272
01273 static bool su_delayed = false;
01274
01275 void su_HandleDelayedEvents ()
01276 {
01277
01278 if ( !su_delayed )
01279 {
01280 return;
01281 }
01282
01283 su_delayed = false;
01284
01285 for ( uInputs::const_iterator i = su_inputs.begin(); i != su_inputs.end(); ++i )
01286 {
01287 uBind * bind = (*i)->GetBind();
01288 if ( bind )
01289 {
01290 bind->HanldeDelayed();
01291 }
01292 }
01293 }
01294
01295 bool su_HandleEvent(SDL_Event &e, bool delayed ){
01296 #ifndef DEDICATED
01297 if ( su_delayed && !delayed )
01298 {
01299 su_HandleDelayedEvents();
01300 }
01301
01302 su_delayed = delayed;
01303
01304
01305 bool ret = false;
01306
01307 std::vector< uTransformEventInfo > events;
01308 su_TransformEvent( e, events );
01309
01310 for ( std::vector< uTransformEventInfo >::const_iterator i = events.begin(); i != events.end(); ++i )
01311 {
01312 uTransformEventInfo info = *i;
01313
01314 if ( info.input )
01315 {
01316
01317 if ( info.needsRepeat )
01318 {
01319 info.input->SetPressed( info.value > 0 ? info.value : 0 );
01320 }
01321
01322
01323 uBind * bind = info.input->GetBind();
01324 if ( bind )
01325 {
01326 if ( bind->IsDoubleBind( info.input ) )
01327 {
01328 return true;
01329 }
01330
01331 if ( info.needsRepeat && bind->act && bind->act->type == uAction::uINPUT_ANALOG )
01332 {
01333 info.value *= ts*key_sensitivity;
01334 }
01335
01336 ret |= bind->Activate( info.value, delayed );
01337 }
01338 }
01339 }
01340
01341 return ret;
01342 #endif
01343 return false;
01344 }
01345
01346 void su_InputSync(){
01347 double time=tSysTimeFloat();
01348 ts=REAL(time-lastTime);
01349
01350
01351
01352
01353 lastTime=time;
01354
01355
01356 for ( uInputs::const_iterator i = su_inputs.begin(); i != su_inputs.end(); ++i )
01357 {
01358 uInput * input = *i;
01359 uBind * bind = input->GetBind();
01360 if ( input->GetPressed() > 0 && bind &&
01361 bind->act && bind->act->type == uAction::uINPUT_ANALOG )
01362 {
01363 bind->Activate( ts * key_sensitivity * input->GetPressed(), su_delayed );
01364 }
01365 }
01366 }
01367
01368 void su_ClearKeys()
01369 {
01370
01371 for ( uInputs::const_iterator i = su_inputs.begin(); i != su_inputs.end(); ++i )
01372 {
01373 uInput * input = *i;
01374 uBind * bind = input->GetBind();
01375 if ( input->GetPressed() > 0 && bind )
01376 {
01377 bind->Activate( -1, su_delayed );
01378 input->SetPressed( 0 );
01379 }
01380 }
01381 }
01382
01383
01384
01385
01386
01387 static char const * Player_keyword="PLAYER_BIND";
01388
01389 uBindPlayer::uBindPlayer(uAction *a,int p):uBind(a),ePlayer(p){}
01390
01391 uBindPlayer::~uBindPlayer(){}
01392
01393 uBindPlayer * uBindPlayer::NewBind(std::istream &s)
01394 {
01395
01396 std::string actionName;
01397 s >> actionName;
01398 uAction * act = uAction::Find( actionName.c_str() );
01399
01400
01401 int player;
01402 s >> player;
01403
01404
01405 return NewBind( act, player );
01406 }
01407
01408 uBindPlayer * uBindPlayer::NewBind( uAction * action, int player )
01409 {
01410
01411 for ( uInputs::const_iterator i = su_inputs.begin(); i != su_inputs.end(); ++i )
01412 {
01413 uInput * input = *i;
01414 uBind * old = input->GetBind();
01415
01416
01417 if ( old && old->act == action )
01418 {
01419 uBindPlayer * oldPlayer = dynamic_cast< uBindPlayer * >( old );
01420 if ( oldPlayer && oldPlayer->ePlayer == player )
01421 return oldPlayer;
01422 }
01423 }
01424
01425
01426 return tNEW(uBindPlayer)( action, player );
01427 }
01428
01429 bool uBindPlayer::IsKeyWord(const char *n){
01430 return !strcmp(n,Player_keyword);
01431 }
01432
01433 bool uBindPlayer::CheckPlayer(int p){
01434 return p==ePlayer;
01435 }
01436
01437 void uBindPlayer::Write(std::ostream &s){
01438 s << Player_keyword << '\t';
01439 uBind::Write(s);
01440 s << ePlayer;
01441 }
01442
01443 bool uBindPlayer::Delayable()
01444 {
01445 return ( ePlayer!=0 );
01446 }
01447
01448 bool uBindPlayer::DoActivate(REAL x){
01449 if (ePlayer==0)
01450 return GlobalAct(act,x);
01451 else
01452 return uPlayerPrototype::PlayerConfig(ePlayer-1)->Act(act,x);
01453 }
01454
01455
01456
01457
01458
01459
01460 static uActionGlobalFunc *uActionGlobal_anchor=NULL;
01461
01462 uActionGlobalFunc::uActionGlobalFunc(uActionGlobal *a, ACTION_FUNC *f,
01463 bool rebind )
01464 :tListItem<uActionGlobalFunc>(uActionGlobal_anchor), func (f), act(a),
01465 rebindable(rebind){}
01466
01467 bool uActionGlobalFunc::IsBreakingGlobalBind(uAction *act){
01468 for (uActionGlobalFunc *run = uActionGlobal_anchor; run ; run = run->Next())
01469 if (run->act == act && !run->rebindable)
01470 return true;
01471
01472 return false;
01473 }
01474
01475 bool uActionGlobalFunc::GlobalAct(uAction *act, REAL x){
01476 for (uActionGlobalFunc *run = uActionGlobal_anchor; run ; run = run->Next())
01477 if (run->act == act && run->func(x))
01478 return true;
01479
01480 return false;
01481 }
01482
01483 static uActionGlobal mess_up("MESS_UP");
01484
01485 static uActionGlobal mess_down("MESS_DOWN");
01486
01487 static bool messup_func(REAL x){
01488 if (x>0){
01489 sr_con.Scroll(-1);
01490 }
01491 return true;
01492 }
01493
01494 static bool messdown_func(REAL x){
01495 if (x>0){
01496 sr_con.Scroll(1);
01497 }
01498 return true;
01499 }
01500
01501 static uActionGlobalFunc mu(&mess_up,&messup_func);
01502 static uActionGlobalFunc md(&mess_down,&messdown_func);