Changeset 3327 for code/trunk/src/core/input/InputManager.cc
- Timestamp:
- Jul 19, 2009, 5:31:02 PM (16 years ago)
- Location:
- code/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk
- Property svn:mergeinfo changed
/code/branches/core4 merged: 3269,3271-3275,3278,3285,3290-3294,3310
- Property svn:mergeinfo changed
-
code/trunk/src/core/input/InputManager.cc
r3301 r3327 30 30 @file 31 31 @brief 32 Implementation of the InputManager that captures all the input from OIS 33 and redirects it to handlers. 34 */ 32 Implementation of the InputManager and a static variable from the InputHandler. 33 */ 35 34 36 35 #include "InputManager.h" 37 36 37 #include <cassert> 38 38 #include <climits> 39 #include <cassert>40 39 #include <ois/OISException.h> 41 40 #include <ois/OISInputManager.h> 42 43 #include "util/Convert.h" 41 #include <boost/foreach.hpp> 42 44 43 #include "util/Exception.h" 45 44 #include "util/ScopeGuard.h" … … 49 48 #include "core/ConsoleCommand.h" 50 49 #include "core/CommandLine.h" 50 #include "core/Functor.h" 51 51 52 52 #include "InputBuffer.h" 53 53 #include "KeyDetector.h" 54 #include "InputState.h" 55 #include "SimpleInputState.h" 56 #include "ExtendedInputState.h" 57 #include "JoyStickDeviceNumberListener.h" 58 59 // HACK (include this as last, X11 seems to define some macros...) 60 #ifdef ORXONOX_PLATFORM_LINUX 61 # include <ois/linux/LinuxMouse.h> 62 #endif 54 #include "JoyStick.h" 55 #include "JoyStickQuantityListener.h" 56 #include "Mouse.h" 57 #include "Keyboard.h" 63 58 64 59 namespace orxonox 65 60 { 66 SetConsoleCommand(InputManager, calibrate, true);67 SetConsoleCommand(InputManager, reload, false);68 #ifdef ORXONOX_PLATFORM_LINUX69 SetConsoleCommand(InputManager, grabMouse, true);70 SetConsoleCommand(InputManager, ungrabMouse, true);71 #endif72 61 SetCommandLineSwitch(keyboard_no_grab).information("Whether not to exclusively grab the keyboard"); 73 62 74 EmptyHandler InputManager::EMPTY_HANDLER; 63 // Abuse of this source file for the InputHandler 64 InputHandler InputHandler::EMPTY; 65 75 66 InputManager* InputManager::singletonRef_s = 0; 76 67 77 using namespace InputDevice; 78 79 /** 80 @brief 81 Defines the |= operator for easier use. 82 */ 83 inline InputManager::InputManagerState operator|=(InputManager::InputManagerState& lval, 84 InputManager::InputManagerState rval) 85 { 86 return (lval = (InputManager::InputManagerState)(lval | rval)); 87 } 88 89 /** 90 @brief 91 Defines the &= operator for easier use. 92 */ 93 inline InputManager::InputManagerState operator&=(InputManager::InputManagerState& lval, int rval) 94 { 95 return (lval = (InputManager::InputManagerState)(lval & rval)); 68 //! Defines the |= operator for easier use. 69 inline InputManager::State operator|=(InputManager::State& lval, InputManager::State rval) 70 { 71 return (lval = (InputManager::State)(lval | rval)); 72 } 73 74 //! Defines the &= operator for easier use. 75 inline InputManager::State operator&=(InputManager::State& lval, int rval) 76 { 77 return (lval = (InputManager::State)(lval & rval)); 96 78 } 97 79 … … 100 82 // ########## ########## 101 83 // ############################################################ 102 103 /** 104 @brief 105 Constructor only sets member fields to initial zero values 106 and registers the class in the class hierarchy. 107 */ 108 InputManager::InputManager() 109 : inputSystem_(0) 110 , keyboard_(0) 111 , mouse_(0) 112 , joySticksSize_(0) 113 , devicesNum_(0) 84 InputManager::InputManager(size_t windowHnd) 85 : internalState_(Bad) 86 , oisInputManager_(0) 87 , devices_(2) 114 88 , windowHnd_(0) 115 , internalState_(Uninitialised) 116 , stateEmpty_(0) 89 , emptyState_(0) 117 90 , keyDetector_(0) 118 , calibratorCallbackBuffer_(0) 119 , keyboardModifiers_(0) 91 , calibratorCallbackHandler_(0) 120 92 { 121 93 RegisterRootObject(InputManager); … … 124 96 singletonRef_s = this; 125 97 126 setConfigValues(); 127 } 128 129 /** 130 @brief 131 Sets the configurable values. 132 */ 98 CCOUT(4) << "Constructing..." << std::endl; 99 100 this->setConfigValues(); 101 102 this->loadDevices(windowHnd); 103 104 // Lowest priority empty InputState 105 emptyState_ = createInputState("empty", false, false, InputStatePriority::Empty); 106 emptyState_->setHandler(&InputHandler::EMPTY); 107 activeStates_[emptyState_->getPriority()] = emptyState_; 108 109 // KeyDetector to evaluate a pressed key's name 110 InputState* detector = createInputState("detector", false, false, InputStatePriority::Detector); 111 // Create a callback to avoid buttonHeld events after the key has been detected 112 FunctorMember<InputManager>* bufferFunctor = createFunctor(&InputManager::clearBuffers); 113 bufferFunctor->setObject(this); 114 detector->setLeaveFunctor(bufferFunctor); 115 keyDetector_ = new KeyDetector(); 116 detector->setHandler(keyDetector_); 117 118 // Joy stick calibration helper callback 119 InputState* calibrator = createInputState("calibrator", false, false, InputStatePriority::Calibrator); 120 calibrator->setHandler(&InputHandler::EMPTY); 121 calibratorCallbackHandler_ = new InputBuffer(); 122 calibratorCallbackHandler_->registerListener(this, &InputManager::stopCalibration, '\r', true); 123 calibrator->setKeyHandler(calibratorCallbackHandler_); 124 125 this->updateActiveStates(); 126 127 { 128 // calibrate console command 129 FunctorMember<InputManager>* functor = createFunctor(&InputManager::calibrate); 130 functor->setObject(this); 131 this->getIdentifier()->addConsoleCommand(createConsoleCommand(functor, "calibrate"), true); 132 } 133 { 134 // reload console command 135 FunctorMember<InputManager>* functor = createFunctor(&InputManager::reload); 136 functor->setObject(this); 137 this->getIdentifier()->addConsoleCommand(createConsoleCommand(functor, "reload"), false); 138 } 139 140 internalState_ = Nothing; 141 CCOUT(4) << "Construction complete." << std::endl; 142 } 143 133 144 void InputManager::setConfigValues() 134 145 { 135 SetConfigValue(calibrationFilename_, "joystick_calibration.ini")136 .description("Ini filename for the the joy stick calibration data.")137 .callback(this, &InputManager::_calibrationFileCallback);138 }139 140 /**141 @brief142 Callback for the joy stick calibration config file. @see setConfigValues.143 */144 void InputManager::_calibrationFileCallback()145 {146 ConfigFileManager::getInstance().setFilename(ConfigFileType::JoyStickCalibration, calibrationFilename_);147 146 } 148 147 … … 150 149 @brief 151 150 Creates the OIS::InputMananger, the keyboard, the mouse and 152 the joys ticks and assigns the key bindings.151 the joys ticks. If either of the first two fail, this method throws an exception. 153 152 @param windowHnd 154 153 The window handle of the render window … … 157 156 @param windowHeight 158 157 The height of the render window 159 @param joyStickSupport160 Whether or not to load the joy sticks as well161 158 */ 162 void InputManager::initialise(size_t windowHnd, int windowWidth, int windowHeight, bool joyStickSupport) 163 { 164 CCOUT(3) << "Initialising Input System..." << std::endl; 165 166 if (!(internalState_ & OISReady)) 167 { 168 CCOUT(4) << "Initialising OIS components..." << std::endl; 169 170 // store handle internally so we can reload OIS 171 windowHnd_ = windowHnd; 172 173 OIS::ParamList paramList; 174 std::ostringstream windowHndStr; 175 176 // Fill parameter list 177 windowHndStr << static_cast<unsigned int>(windowHnd); 178 paramList.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str())); 159 void InputManager::loadDevices(size_t windowHnd) 160 { 161 CCOUT(3) << "Loading input devices..." << std::endl; 162 163 // When loading the devices they should not already be loaded 164 assert(internalState_ & Bad); 165 assert(devices_[InputDeviceEnumerator::Mouse] == 0); 166 assert(devices_[InputDeviceEnumerator::Keyboard] == 0); 167 assert(devices_.size() == InputDeviceEnumerator::FirstJoyStick); 168 169 // store handle internally so we can reload OIS 170 windowHnd_ = windowHnd; 171 172 OIS::ParamList paramList; 173 std::ostringstream windowHndStr; 174 175 // Fill parameter list 176 windowHndStr << static_cast<unsigned int>(windowHnd); 177 paramList.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str())); 179 178 #if defined(ORXONOX_PLATFORM_WINDOWS) 180 181 182 183 179 //paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_NONEXCLUSIVE"))); 180 //paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND"))); 181 //paramList.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_NONEXCLUSIVE"))); 182 //paramList.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_FOREGROUND"))); 184 183 #elif defined(ORXONOX_PLATFORM_LINUX) 185 paramList.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true"))); 186 paramList.insert(std::make_pair(std::string("x11_mouse_grab"), "true")); 187 paramList.insert(std::make_pair(std::string("x11_mouse_hide"), "true")); 188 bool kbNoGrab; 189 CommandLine::getValue("keyboard_no_grab", &kbNoGrab); 190 if (kbNoGrab) 191 paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false"))); 184 paramList.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true"))); 185 paramList.insert(std::make_pair(std::string("x11_mouse_grab"), "true")); 186 paramList.insert(std::make_pair(std::string("x11_mouse_hide"), "true")); 187 bool kbNoGrab; 188 CommandLine::getValue("keyboard_no_grab", &kbNoGrab); 189 if (kbNoGrab) 190 paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false"))); 191 else 192 paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("true"))); 193 #endif 194 195 try 196 { 197 oisInputManager_ = OIS::InputManager::createInputSystem(paramList); 198 // Exception-safety 199 Loki::ScopeGuard guard = Loki::MakeGuard(OIS::InputManager::destroyInputSystem, oisInputManager_); 200 CCOUT(ORX_DEBUG) << "Created OIS input manager." << std::endl; 201 202 if (oisInputManager_->getNumberOfDevices(OIS::OISKeyboard) > 0) 203 devices_[InputDeviceEnumerator::Keyboard] = new Keyboard(InputDeviceEnumerator::Keyboard, oisInputManager_); 192 204 else 193 paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("true"))); 194 #endif 195 205 ThrowException(InitialisationFailed, "InputManager: No keyboard found, cannot proceed!"); 206 207 // Successful initialisation 208 guard.Dismiss(); 209 } 210 catch (std::exception& ex) 211 { 212 oisInputManager_ = NULL; 213 internalState_ |= Bad; 214 ThrowException(InitialisationFailed, "Could not initialise the input system: " << ex.what()); 215 } 216 217 // TODO: Remove the two parameters 218 this->loadMouse(); 219 this->loadJoySticks(); 220 221 // Reorder states in case some joy sticks were added/removed 222 this->updateActiveStates(); 223 224 CCOUT(3) << "Input devices loaded." << std::endl; 225 } 226 227 //! Creates a new orxonox::Mouse 228 void InputManager::loadMouse() 229 { 230 if (oisInputManager_->getNumberOfDevices(OIS::OISMouse) > 0) 231 { 196 232 try 197 233 { 198 inputSystem_ = OIS::InputManager::createInputSystem(paramList); 199 // Exception-safety 200 Loki::ScopeGuard guard = Loki::MakeGuard(OIS::InputManager::destroyInputSystem, inputSystem_); 201 CCOUT(ORX_DEBUG) << "Created OIS input system" << std::endl; 202 203 _initialiseKeyboard(); 204 205 // Nothing below should throw anymore, dismiss the guard 206 guard.Dismiss(); 207 } 208 catch (OIS::Exception& ex) 209 { 210 ThrowException(InitialisationFailed, "Could not initialise the input system: " << ex.what()); 211 } 212 213 _initialiseMouse(); 214 215 if (joyStickSupport) 216 _initialiseJoySticks(); 217 // Do this anyway to also inform when a joystick was detached. 218 _configureJoySticks(); 219 220 // Set mouse/joystick region 221 if (mouse_) 222 setWindowExtents(windowWidth, windowHeight); 223 224 // clear all buffers 225 _clearBuffers(); 226 227 internalState_ |= OISReady; 228 229 CCOUT(ORX_DEBUG) << "Initialising OIS components done." << std::endl; 234 devices_[InputDeviceEnumerator::Mouse] = new Mouse(InputDeviceEnumerator::Mouse, oisInputManager_); 235 } 236 catch (const OIS::Exception& ex) 237 { 238 CCOUT(2) << "Warning: Failed to create Mouse:" << ex.eText << std::endl 239 << "Proceeding without mouse support." << std::endl; 240 } 230 241 } 231 242 else 232 { 233 CCOUT(2) << "Warning: OIS compoments already initialised, skipping" << std::endl; 234 } 235 236 if (!(internalState_ & InternalsReady)) 237 { 238 CCOUT(4) << "Initialising InputStates components..." << std::endl; 239 240 // Lowest priority empty InputState 241 stateEmpty_ = createInputState<SimpleInputState>("empty", false, false, InputStatePriority::Empty); 242 stateEmpty_->setHandler(&EMPTY_HANDLER); 243 activeStates_[stateEmpty_->getPriority()] = stateEmpty_; 244 245 // KeyDetector to evaluate a pressed key's name 246 SimpleInputState* detector = createInputState<SimpleInputState>("detector", false, false, InputStatePriority::Detector); 247 keyDetector_ = new KeyDetector(); 248 detector->setHandler(keyDetector_); 249 250 // Joy stick calibration helper callback 251 SimpleInputState* calibrator = createInputState<SimpleInputState>("calibrator", false, false, InputStatePriority::Calibrator); 252 calibrator->setHandler(&EMPTY_HANDLER); 253 calibratorCallbackBuffer_ = new InputBuffer(); 254 calibratorCallbackBuffer_->registerListener(this, &InputManager::_completeCalibration, '\r', true); 255 calibrator->setKeyHandler(calibratorCallbackBuffer_); 256 257 internalState_ |= InternalsReady; 258 259 CCOUT(4) << "Initialising InputStates complete." << std::endl; 260 } 261 262 _updateActiveStates(); 263 264 CCOUT(3) << "Initialising complete." << std::endl; 243 CCOUT(ORX_WARNING) << "Warning: No mouse found! Proceeding without mouse support." << std::endl; 244 } 245 246 //! Creates as many joy sticks as are available. 247 void InputManager::loadJoySticks() 248 { 249 for (int i = 0; i < oisInputManager_->getNumberOfDevices(OIS::OISJoyStick); i++) 250 { 251 try 252 { 253 devices_.push_back(new JoyStick(InputDeviceEnumerator::FirstJoyStick + i, oisInputManager_)); 254 } 255 catch (std::exception ex) 256 { 257 CCOUT(2) << "Warning: Failed to create joy stick: " << ex.what() << std::endl; 258 } 259 } 260 261 // inform all JoyStick Device Number Listeners 262 std::vector<JoyStick*> joyStickList; 263 for (unsigned int i = InputDeviceEnumerator::FirstJoyStick; i < devices_.size(); ++i) 264 joyStickList.push_back(static_cast<JoyStick*>(devices_[i])); 265 JoyStickQuantityListener::changeJoyStickQuantity(joyStickList); 266 } 267 268 void InputManager::setKeyDetectorCallback(const std::string& command) 269 { 270 this->keyDetector_->setCallbackCommand(command); 271 } 272 273 // ############################################################ 274 // ##### Destruction ##### 275 // ########## ########## 276 // ############################################################ 277 278 InputManager::~InputManager() 279 { 280 CCOUT(4) << "Destroying..." << std::endl; 281 282 // Destroy calibrator helper handler and state 283 delete keyDetector_; 284 this->destroyState("calibrator"); 285 // Destroy KeyDetector and state 286 delete calibratorCallbackHandler_; 287 this->destroyState("detector"); 288 // destroy the empty InputState 289 this->destroyStateInternal(this->emptyState_); 290 291 // destroy all user InputStates 292 while (statesByName_.size() > 0) 293 this->destroyStateInternal((*statesByName_.rbegin()).second); 294 295 if (!(internalState_ & Bad)) 296 this->destroyDevices(); 297 298 CCOUT(4) << "Destruction complete." << std::endl; 299 singletonRef_s = 0; 265 300 } 266 301 267 302 /** 268 303 @brief 269 Creates a keyboard and sets the event handler.270 @ return271 False if keyboard stays uninitialised, true otherwise.304 Destoys all input devices (joy sticks, mouse, keyboard and OIS::InputManager) 305 @throw 306 Method does not throw 272 307 */ 273 void InputManager::_initialiseKeyboard() 274 { 275 if (keyboard_ != 0) 276 { 277 CCOUT(2) << "Warning: Keyboard already initialised, skipping." << std::endl; 278 return; 279 } 280 if (inputSystem_->getNumberOfDevices(OIS::OISKeyboard) > 0) 281 { 282 keyboard_ = (OIS::Keyboard*)inputSystem_->createInputObject(OIS::OISKeyboard, true); 283 // register our listener in OIS. 284 keyboard_->setEventCallback(this); 285 // note: OIS will not detect keys that have already been down when the keyboard was created. 286 CCOUT(ORX_DEBUG) << "Created OIS keyboard" << std::endl; 287 } 288 else 289 { 290 ThrowException(InitialisationFailed, "InputManager: No keyboard found, cannot proceed!"); 291 } 292 } 293 294 /** 295 @brief 296 Creates a mouse and sets the event handler. 297 @return 298 False if mouse stays uninitialised, true otherwise. 299 */ 300 void InputManager::_initialiseMouse() 301 { 302 if (mouse_ != 0) 303 { 304 CCOUT(2) << "Warning: Mouse already initialised, skipping." << std::endl; 305 return; 306 } 308 void InputManager::destroyDevices() 309 { 310 CCOUT(3) << "Destroying devices..." << std::endl; 311 312 BOOST_FOREACH(InputDevice*& device, devices_) 313 { 314 if (device == NULL) 315 continue; 316 std::string className = device->getClassName(); 317 try 318 { 319 delete device; 320 device = 0; 321 CCOUT(4) << className << " destroyed." << std::endl; 322 } 323 catch (...) 324 { 325 CCOUT(1) << className << " destruction failed! Potential resource leak!" << std::endl; 326 } 327 } 328 devices_.resize(InputDeviceEnumerator::FirstJoyStick); 329 330 assert(oisInputManager_ != NULL); 307 331 try 308 332 { 309 if (inputSystem_->getNumberOfDevices(OIS::OISMouse) > 0) 310 { 311 mouse_ = static_cast<OIS::Mouse*>(inputSystem_->createInputObject(OIS::OISMouse, true)); 312 // register our listener in OIS. 313 mouse_->setEventCallback(this); 314 CCOUT(ORX_DEBUG) << "Created OIS mouse" << std::endl; 315 } 316 else 317 { 318 CCOUT(ORX_WARNING) << "Warning: No mouse found! Proceeding without mouse support." << std::endl; 319 } 320 } 321 catch (OIS::Exception ex) 322 { 323 CCOUT(ORX_WARNING) << "Warning: Failed to create an OIS mouse\n" 324 << "OIS error message: \"" << ex.eText << "\"\n Proceeding without mouse support." << std::endl; 325 mouse_ = 0; 326 } 327 } 328 329 /** 330 @brief 331 Creates all joy sticks and sets the event handler. 332 @return 333 False joy stick stay uninitialised, true otherwise. 334 */ 335 void InputManager::_initialiseJoySticks() 336 { 337 if (joySticksSize_ > 0) 338 { 339 CCOUT(2) << "Warning: Joy sticks already initialised, skipping." << std::endl; 340 return; 341 } 342 if (inputSystem_->getNumberOfDevices(OIS::OISJoyStick) > 0) 343 { 344 for (int i = 0; i < inputSystem_->getNumberOfDevices(OIS::OISJoyStick); i++) 345 { 346 try 347 { 348 OIS::JoyStick* stig = static_cast<OIS::JoyStick*> 349 (inputSystem_->createInputObject(OIS::OISJoyStick, true)); 350 CCOUT(ORX_DEBUG) << "Created OIS joy stick with ID " << stig->getID() << std::endl; 351 joySticks_.push_back(stig); 352 // register our listener in OIS. 353 stig->setEventCallback(this); 354 } 355 catch (OIS::Exception ex) 356 { 357 CCOUT(ORX_WARNING) << "Warning: Failed to create OIS joy number" << i << "\n" 358 << "OIS error message: \"" << ex.eText << "\"" << std::endl; 359 } 360 } 361 } 362 } 363 364 /** 365 @brief 366 Helper function that loads the config value vector of one coefficient 367 */ 368 void loadCalibration(std::vector<int>& list, const std::string& sectionName, const std::string& valueName, size_t size, int defaultValue) 369 { 370 list.resize(size); 371 unsigned int configValueVectorSize = ConfigFileManager::getInstance().getVectorSize(ConfigFileType::JoyStickCalibration, sectionName, valueName); 372 if (configValueVectorSize > size) 373 configValueVectorSize = size; 374 375 for (unsigned int i = 0; i < configValueVectorSize; ++i) 376 { 377 list[i] = multi_cast<int>(ConfigFileManager::getInstance().getValue( 378 ConfigFileType::JoyStickCalibration, sectionName, valueName, i, multi_cast<std::string>(defaultValue), false)); 379 } 380 381 // fill the rest with default values 382 for (unsigned int i = configValueVectorSize; i < size; ++i) 383 { 384 list[i] = defaultValue; 385 } 386 } 387 388 /** 389 @brief 390 Sets the size of all the different lists that are dependent on the number 391 of joy stick devices created and loads the joy stick calibration. 392 @remarks 393 No matter whether there are a mouse and/or keyboard, they will always 394 occupy 2 places in the device number dependent lists. 395 */ 396 void InputManager::_configureJoySticks() 397 { 398 joySticksSize_ = joySticks_.size(); 399 devicesNum_ = 2 + joySticksSize_; 400 joyStickIDs_ .resize(joySticksSize_); 401 joyStickButtonsDown_ .resize(joySticksSize_); 402 povStates_ .resize(joySticksSize_); 403 sliderStates_ .resize(joySticksSize_); 404 joyStickMinValues_ .resize(joySticksSize_); 405 joyStickMaxValues_ .resize(joySticksSize_); 406 joyStickMiddleValues_.resize(joySticksSize_); 407 joyStickCalibrations_.resize(joySticksSize_); 408 409 for (unsigned int iJoyStick = 0; iJoyStick < joySticksSize_; iJoyStick++) 410 { 411 // Generate some sort of execution unique id per joy stick 412 std::string id = "JoyStick_"; 413 id += multi_cast<std::string>(joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_Button)) + "_"; 414 id += multi_cast<std::string>(joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_Axis)) + "_"; 415 id += multi_cast<std::string>(joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_Slider)) + "_"; 416 id += multi_cast<std::string>(joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_POV)) + "_"; 417 id += multi_cast<std::string>(joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_Vector3)) + "_"; 418 id += joySticks_[iJoyStick]->vendor(); 419 for (unsigned int i = 0; i < iJoyStick; ++i) 420 { 421 if (id == joyStickIDs_[i]) 422 { 423 // Two joysticks are probably equal --> add the index as well 424 id += "_" + multi_cast<std::string>(iJoyStick); 425 } 426 } 427 joyStickIDs_[iJoyStick] = id; 428 429 size_t axes = sliderAxes + (size_t)this->joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_Axis); 430 loadCalibration(joyStickMinValues_[iJoyStick], id, "MinValue", axes, -32768); 431 loadCalibration(joyStickMaxValues_[iJoyStick], id, "MaxValue", axes, 32768); 432 loadCalibration(joyStickMiddleValues_[iJoyStick], id, "MiddleValue", axes, 0); 433 } 434 435 _evaluateCalibration(); 436 437 // state management 438 activeStatesTriggered_.resize(devicesNum_); 439 440 // inform all states 441 for (std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.begin(); 442 it != inputStatesByName_.end(); ++it) 443 { 444 it->second->setNumOfJoySticks(joySticksSize_); 445 } 446 447 // inform all JoyStick Device Number Listeners 448 for (ObjectList<JoyStickDeviceNumberListener>::iterator it = ObjectList<JoyStickDeviceNumberListener>::begin(); it; ++it) 449 it->JoyStickDeviceNumberChanged(joySticksSize_); 450 451 } 452 453 void InputManager::_evaluateCalibration() 454 { 455 for (unsigned int iJoyStick = 0; iJoyStick < this->joySticksSize_; ++iJoyStick) 456 { 457 for (unsigned int i = 0; i < this->joyStickMinValues_[iJoyStick].size(); i++) 458 { 459 this->joyStickCalibrations_[iJoyStick].middleValue[i] = this->joyStickMiddleValues_[iJoyStick][i]; 460 this->joyStickCalibrations_[iJoyStick].negativeCoeff[i] = - 1.0f / (this->joyStickMinValues_[iJoyStick][i] - this->joyStickMiddleValues_[iJoyStick][i]); 461 this->joyStickCalibrations_[iJoyStick].positiveCoeff[i] = 1.0f / (this->joyStickMaxValues_[iJoyStick][i] - this->joyStickMiddleValues_[iJoyStick][i]); 462 } 463 } 464 } 465 466 void InputManager::_startCalibration() 467 { 468 for (unsigned int iJoyStick = 0; iJoyStick < this->joySticksSize_; ++iJoyStick) 469 { 470 // Set initial values 471 for (unsigned int i = 0; i < this->joyStickMinValues_[iJoyStick].size(); ++i) 472 this->joyStickMinValues_[iJoyStick][i] = INT_MAX; 473 for (unsigned int i = 0; i < this->joyStickMaxValues_[iJoyStick].size(); ++i) 474 this->joyStickMaxValues_[iJoyStick][i] = INT_MIN; 475 for (unsigned int i = 0; i < this->joyStickMiddleValues_[iJoyStick].size(); ++i) 476 this->joyStickMiddleValues_[iJoyStick][i] = 0; 477 } 478 479 getInstance().internalState_ |= Calibrating; 480 getInstance().requestEnterState("calibrator"); 481 } 482 483 void InputManager::_completeCalibration() 484 { 485 for (unsigned int iJoyStick = 0; iJoyStick < this->joySticksSize_; ++iJoyStick) 486 { 487 // Get the middle positions now 488 unsigned int iAxis = 0; 489 for (unsigned int i = 0; i < sliderAxes/2; ++i) 490 { 491 this->joyStickMiddleValues_[iJoyStick][iAxis++] = this->joySticks_[iJoyStick]->getJoyStickState().mSliders[i].abX; 492 this->joyStickMiddleValues_[iJoyStick][iAxis++] = this->joySticks_[iJoyStick]->getJoyStickState().mSliders[i].abY; 493 } 494 // Note: joyStickMiddleValues_[iJoyStick] was already correctly resized in _configureJoySticks() 495 assert(joySticks_[iJoyStick]->getJoyStickState().mAxes.size() == joyStickMiddleValues_[iJoyStick].size() - sliderAxes); 496 for (unsigned int i = 0; i < joyStickMiddleValues_[iJoyStick].size() - sliderAxes; ++i) 497 { 498 this->joyStickMiddleValues_[iJoyStick][iAxis++] = this->joySticks_[iJoyStick]->getJoyStickState().mAxes[i].abs; 499 } 500 501 for (unsigned int i = 0; i < joyStickMinValues_[iJoyStick].size(); ++i) 502 { 503 // Minimum values 504 if (joyStickMinValues_[iJoyStick][i] == INT_MAX) 505 joyStickMinValues_[iJoyStick][i] = -32768; 506 ConfigFileManager::getInstance().setValue(ConfigFileType::JoyStickCalibration, 507 this->joyStickIDs_[iJoyStick], "MinValue", i, multi_cast<std::string>(joyStickMinValues_[iJoyStick][i]), false); 508 509 // Maximum values 510 if (joyStickMaxValues_[iJoyStick][i] == INT_MIN) 511 joyStickMaxValues_[iJoyStick][i] = 32767; 512 ConfigFileManager::getInstance().setValue(ConfigFileType::JoyStickCalibration, 513 this->joyStickIDs_[iJoyStick], "MaxValue", i, multi_cast<std::string>(joyStickMaxValues_[iJoyStick][i]), false); 514 515 // Middle values 516 ConfigFileManager::getInstance().setValue(ConfigFileType::JoyStickCalibration, 517 this->joyStickIDs_[iJoyStick], "MiddleValue", i, multi_cast<std::string>(joyStickMiddleValues_[iJoyStick][i]), false); 518 } 519 } 520 521 _evaluateCalibration(); 522 523 // restore old input state 524 requestLeaveState("calibrator"); 525 internalState_ &= ~Calibrating; 526 } 527 528 // ############################################################ 529 // ##### Destruction ##### 530 // ########## ########## 531 // ############################################################ 532 533 /** 534 @brief 535 Destroys all the created input devices and states. 536 */ 537 InputManager::~InputManager() 538 { 539 if (internalState_ != Uninitialised) 540 { 541 CCOUT(3) << "Destroying ..." << std::endl; 542 543 // kick all active states 'nicely' 544 for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin(); 545 rit != activeStates_.rend(); ++rit) 546 { 547 (*rit).second->onLeave(); 548 } 549 550 // Destroy calibrator helper handler and state 551 delete keyDetector_; 552 requestDestroyState("calibrator"); 553 // Destroy KeyDetector and state 554 delete calibratorCallbackBuffer_; 555 requestDestroyState("detector"); 556 // destroy the empty InputState 557 _destroyState(this->stateEmpty_); 558 559 // destroy all user InputStates 560 while (inputStatesByName_.size() > 0) 561 _destroyState((*inputStatesByName_.rbegin()).second); 562 563 // destroy the devices 564 _destroyKeyboard(); 565 _destroyMouse(); 566 _destroyJoySticks(); 567 568 try 569 { 570 OIS::InputManager::destroyInputSystem(inputSystem_); 571 } 572 catch (...) 573 { 574 CCOUT(1) << "OIS::InputManager destruction failed! Potential resource leak!" << std::endl; 575 } 576 } 577 578 singletonRef_s = 0; 579 } 580 581 /** 582 @brief 583 Destroys the keyboard and sets it to 0. 584 */ 585 void InputManager::_destroyKeyboard() 586 { 587 assert(inputSystem_); 588 try 589 { 590 if (keyboard_) 591 inputSystem_->destroyInputObject(keyboard_); 592 keyboard_ = 0; 593 CCOUT(4) << "Keyboard destroyed." << std::endl; 333 OIS::InputManager::destroyInputSystem(oisInputManager_); 594 334 } 595 335 catch (...) 596 336 { 597 CCOUT(1) << "Keyboard destruction failed! Potential resource leak!" << std::endl; 598 } 599 } 600 601 /** 602 @brief 603 Destroys the mouse and sets it to 0. 604 */ 605 void InputManager::_destroyMouse() 606 { 607 assert(inputSystem_); 608 try 609 { 610 if (mouse_) 611 inputSystem_->destroyInputObject(mouse_); 612 mouse_ = 0; 613 CCOUT(4) << "Mouse destroyed." << std::endl; 614 } 615 catch (...) 616 { 617 CCOUT(1) << "Mouse destruction failed! Potential resource leak!" << std::endl; 618 } 619 } 620 621 /** 622 @brief 623 Destroys all the joy sticks and resizes the lists to 0. 624 */ 625 void InputManager::_destroyJoySticks() 626 { 627 if (joySticksSize_ > 0) 628 { 629 assert(inputSystem_); 630 for (unsigned int i = 0; i < joySticksSize_; i++) 631 { 632 try 633 { 634 if (joySticks_[i] != 0) 635 inputSystem_->destroyInputObject(joySticks_[i]); 636 } 637 catch (...) 638 { 639 CCOUT(1) << "Joy stick destruction failed! Potential resource leak!" << std::endl; 640 } 641 } 642 643 joySticks_.clear(); 644 // don't use _configureNumberOfJoySticks(), might mess with registered handler if 645 // downgrading from 2 to 1 joystick 646 //_configureNumberOfJoySticks(); 647 joySticksSize_ = 0; 648 } 649 CCOUT(4) << "Joy sticks destroyed." << std::endl; 650 } 651 652 /** 653 @brief 654 Removes and destroys an InputState. 655 @return 656 True if state was removed immediately, false if postponed. 657 */ 658 void InputManager::_destroyState(InputState* state) 659 { 660 assert(state && !(this->internalState_ & Ticking)); 661 std::map<int, InputState*>::iterator it = this->activeStates_.find(state->getPriority()); 662 if (it != this->activeStates_.end()) 663 { 664 this->activeStates_.erase(it); 665 _updateActiveStates(); 666 } 667 inputStatesByName_.erase(state->getName()); 668 delete state; 669 } 670 671 void InputManager::_clearBuffers() 672 { 673 keysDown_.clear(); 674 keyboardModifiers_ = 0; 675 mouseButtonsDown_.clear(); 676 for (unsigned int i = 0; i < joySticksSize_; ++i) 677 { 678 joyStickButtonsDown_[i].clear(); 679 for (int j = 0; j < 4; ++j) 680 { 681 sliderStates_[i].sliderStates[j].x = 0; 682 sliderStates_[i].sliderStates[j].y = 0; 683 povStates_[i][j] = 0; 684 } 685 } 686 } 687 337 CCOUT(1) << "OIS::InputManager destruction failed! Potential resource leak!" << std::endl; 338 } 339 oisInputManager_ = NULL; 340 341 internalState_ |= Bad; 342 CCOUT(3) << "Destroyed devices." << std::endl; 343 } 688 344 689 345 // ############################################################ … … 692 348 // ############################################################ 693 349 694 /** 695 @brief 696 Public interface. Only reloads immediately if the call stack doesn't 697 include the update() method. 698 @param joyStickSupport 699 Whether or not to initialise joy sticks as well. 700 */ 701 void InputManager::reloadInputSystem(bool joyStickSupport) 350 void InputManager::reload() 702 351 { 703 352 if (internalState_ & Ticking) 704 353 { 705 354 // We cannot destroy OIS right now, because reload was probably 706 // caused by a user clicking on a GUI item. The backtrace would then355 // caused by a user clicking on a GUI item. The stack trace would then 707 356 // include an OIS method. So it would be a very bad thing to destroy it.. 708 357 internalState_ |= ReloadRequest; 709 // Misuse of internalState_: We can easily store the joyStickSupport bool. 710 // use Uninitialised as 0 value in order to make use of the overloaded |= operator 711 internalState_ |= joyStickSupport ? JoyStickSupport : Uninitialised; 712 } 713 else if (internalState_ & OISReady) 714 { 715 _reload(joyStickSupport); 716 } 358 } 359 else if (internalState_ & Calibrating) 360 CCOUT(2) << "Warning: Cannot reload input system. Joy sticks are currently being calibrated." << std::endl; 717 361 else 718 { 719 CCOUT(2) << "Warning: Cannot reload OIS. May not yet be initialised or" 720 << "joy sticks are currently calibrating." << std::endl; 721 } 722 } 723 724 /** 725 @brief 726 Internal reload method. Destroys the OIS devices and loads them again. 727 */ 728 void InputManager::_reload(bool joyStickSupport) 729 { 730 try 731 { 732 CCOUT(3) << "Reloading ..." << std::endl; 733 734 // Save mouse clipping size 735 int mouseWidth = mouse_->getMouseState().width; 736 int mouseHeight = mouse_->getMouseState().height; 737 738 internalState_ &= ~OISReady; 739 740 // destroy the devices 741 _destroyKeyboard(); 742 _destroyMouse(); 743 _destroyJoySticks(); 744 745 OIS::InputManager::destroyInputSystem(inputSystem_); 746 inputSystem_ = 0; 747 748 // clear all buffers containing input information 749 _clearBuffers(); 750 751 initialise(windowHnd_, mouseWidth, mouseHeight, joyStickSupport); 752 753 CCOUT(3) << "Reloading done." << std::endl; 754 } 755 catch (OIS::Exception& ex) 756 { 757 CCOUT(1) << "An exception has occured while reloading:\n" << ex.what() << std::endl; 758 } 362 reloadInternal(); 363 } 364 365 //! Internal reload method. Destroys the OIS devices and loads them again. 366 void InputManager::reloadInternal() 367 { 368 CCOUT(3) << "Reloading ..." << std::endl; 369 370 this->destroyDevices(); 371 this->loadDevices(windowHnd_); 372 373 internalState_ &= ~Bad; 374 internalState_ &= ~ReloadRequest; 375 CCOUT(3) << "Reloading complete." << std::endl; 759 376 } 760 377 … … 764 381 // ############################################################ 765 382 766 /**767 @brief768 Updates the states and the InputState situation.769 @param time770 Clock holding the current time.771 */772 383 void InputManager::update(const Clock& time) 773 384 { 774 if (internalState_ == Uninitialised) 775 return; 385 if (internalState_ & Bad) 386 ThrowException(General, "InputManager was not correctly reloaded."); 387 776 388 else if (internalState_ & ReloadRequest) 777 { 778 _reload(internalState_ & JoyStickSupport); 779 internalState_ &= ~ReloadRequest; 780 internalState_ &= ~JoyStickSupport; 781 } 389 reloadInternal(); 782 390 783 391 // check for states to leave … … 787 395 it != stateLeaveRequests_.end(); ++it) 788 396 { 789 (*it)-> onLeave();397 (*it)->left(); 790 398 // just to be sure that the state actually is registered 791 assert( inputStatesByName_.find((*it)->getName()) != inputStatesByName_.end());399 assert(statesByName_.find((*it)->getName()) != statesByName_.end()); 792 400 793 401 activeStates_.erase((*it)->getPriority()); 794 402 if ((*it)->getPriority() < InputStatePriority::HighPriority) 795 403 (*it)->setPriority(0); 796 _updateActiveStates();404 updateActiveStates(); 797 405 } 798 406 stateLeaveRequests_.clear(); … … 806 414 { 807 415 // just to be sure that the state actually is registered 808 assert( inputStatesByName_.find((*it)->getName()) != inputStatesByName_.end());416 assert(statesByName_.find((*it)->getName()) != statesByName_.end()); 809 417 810 418 if ((*it)->getPriority() == 0) 811 419 { 812 420 // Get smallest possible priority between 1 and maxStateStackSize_s 813 #if defined( __MINGW32__ ) // Avoid the strange mingw-stl bug with const_reverse_iterator814 421 for(std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin(); 815 422 rit != activeStates_.rend(); ++rit) 816 #else817 for(std::map<int, InputState*>::const_reverse_iterator rit = activeStates_.rbegin();818 rit != activeStates_.rend(); ++rit)819 #endif820 423 { 821 424 if (rit->first < InputStatePriority::HighPriority) … … 830 433 } 831 434 activeStates_[(*it)->getPriority()] = (*it); 832 _updateActiveStates();833 (*it)-> onEnter();435 updateActiveStates(); 436 (*it)->entered(); 834 437 } 835 438 stateEnterRequests_.clear(); … … 842 445 it != stateDestroyRequests_.end(); ++it) 843 446 { 844 _destroyState((*it));447 destroyStateInternal((*it)); 845 448 } 846 449 stateDestroyRequests_.clear(); 847 450 } 848 451 849 // check whether a state has changed its EMPTY _HANDLERsituation452 // check whether a state has changed its EMPTY situation 850 453 bool bUpdateRequired = false; 851 454 for (std::map<int, InputState*>::iterator it = activeStates_.begin(); it != activeStates_.end(); ++it) 852 455 { 853 if (it->second->ha ndlersChanged())854 { 855 it->second->reset HandlersChanged();456 if (it->second->hasExpired()) 457 { 458 it->second->resetExpiration(); 856 459 bUpdateRequired = true; 857 460 } 858 461 } 859 462 if (bUpdateRequired) 860 _updateActiveStates();463 updateActiveStates(); 861 464 862 465 // mark that we now start capturing and distributing input 863 466 internalState_ |= Ticking; 864 467 865 // Capture all the input. This calls the event handlers in InputManager. 866 if (keyboard_) 867 keyboard_->capture(); 868 if (mouse_) 869 mouse_->capture(); 870 for (unsigned int i = 0; i < joySticksSize_; i++) 871 joySticks_[i]->capture(); 872 873 if (!(internalState_ & Calibrating)) 874 { 875 // call all the handlers for the held key events 876 for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++) 877 { 878 KeyEvent kEvt(keysDown_[iKey], keyboardModifiers_); 879 880 for (unsigned int iState = 0; iState < activeStatesTriggered_[Keyboard].size(); ++iState) 881 activeStatesTriggered_[Keyboard][iState]->keyHeld(kEvt); 882 } 883 884 // call all the handlers for the held mouse button events 885 for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++) 886 { 887 for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState) 888 activeStatesTriggered_[Mouse][iState]->mouseButtonHeld(mouseButtonsDown_[iButton]); 889 } 890 891 // call all the handlers for the held joy stick button events 892 for (unsigned int iJoyStick = 0; iJoyStick < joySticksSize_; iJoyStick++) 893 for (unsigned int iButton = 0; iButton < joyStickButtonsDown_[iJoyStick].size(); iButton++) 894 { 895 for (unsigned int iState = 0; iState < activeStatesTriggered_[JoyStick0 + iJoyStick].size(); ++iState) 896 activeStatesTriggered_[JoyStick0 + iJoyStick][iState]->joyStickButtonHeld(iJoyStick, joyStickButtonsDown_[iJoyStick][iButton]); 897 } 898 899 // update the handlers for each active handler 900 for (unsigned int i = 0; i < devicesNum_; ++i) 901 { 902 for (unsigned int iState = 0; iState < activeStatesTriggered_[i].size(); ++iState) 903 activeStatesTriggered_[i][iState]->updateInput(time.getDeltaTime(), i); 904 } 905 906 // update the handler with a general tick afterwards 907 for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i) 908 activeStatesTicked_[i]->updateInput(time.getDeltaTime()); 909 } 468 // Capture all the input and handle it 469 BOOST_FOREACH(InputDevice* device, devices_) 470 if (device != NULL) 471 device->update(time); 472 473 // Update the states 474 for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i) 475 activeStatesTicked_[i]->update(time.getDeltaTime()); 910 476 911 477 internalState_ &= ~Ticking; … … 917 483 Also, a list of all active states (no duplicates!) is compiled for the general update(). 918 484 */ 919 void InputManager::_updateActiveStates() 920 { 921 for (unsigned int i = 0; i < devicesNum_; ++i) 922 { 485 void InputManager::updateActiveStates() 486 { 487 // temporary resize 488 for (unsigned int i = 0; i < devices_.size(); ++i) 489 { 490 if (devices_[i] == NULL) 491 continue; 492 std::vector<InputState*>& states = devices_[i]->getStateListRef(); 923 493 bool occupied = false; 924 activeStatesTriggered_[i].clear(); 925 #if defined( __MINGW32__ ) // Avoid the strange mingw-stl bug with const_reverse_iterator 494 states.clear(); 926 495 for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin(); rit != activeStates_.rend(); ++rit) 927 496 { 928 #else929 for (std::map<int, InputState*>::const_reverse_iterator rit = activeStates_.rbegin(); rit != activeStates_.rend(); ++rit)930 {931 #endif932 497 if (rit->second->isInputDeviceEnabled(i) && (!occupied || rit->second->bAlwaysGetsInput_)) 933 498 { 934 activeStatesTriggered_[i].push_back(rit->second);499 states.push_back(rit->second); 935 500 if (!rit->second->bTransparent_) 936 501 occupied = true; … … 942 507 // Using a std::set to avoid duplicates 943 508 std::set<InputState*> tempSet; 944 for (unsigned int i = 0; i < devicesNum_; ++i) 945 for (unsigned int iState = 0; iState < activeStatesTriggered_[i].size(); ++iState) 946 tempSet.insert(activeStatesTriggered_[i][iState]); 509 for (unsigned int i = 0; i < devices_.size(); ++i) 510 if (devices_[i] != NULL) 511 for (unsigned int iState = 0; iState < devices_[i]->getStateListRef().size(); ++iState) 512 tempSet.insert(devices_[i]->getStateListRef()[iState]); 947 513 948 514 // copy the content of the std::set back to the actual vector … … 950 516 for (std::set<InputState*>::const_iterator it = tempSet.begin();it != tempSet.end(); ++it) 951 517 activeStatesTicked_.push_back(*it); 952 953 this->mouseButtonsDown_.clear(); 954 } 955 956 /** 957 @brief 958 Clears all buffers that store what keys/buttons are being pressed at the moment. 959 */ 518 } 519 960 520 void InputManager::clearBuffers() 961 521 { 962 this->keysDown_.clear(); 963 this->mouseButtonsDown_.clear(); 964 for (unsigned int i = 0; i < this->joySticksSize_; ++i) 965 this->joyStickButtonsDown_[i].clear(); 966 } 967 968 969 // ############################################################ 970 // ##### OIS events ##### 522 BOOST_FOREACH(InputDevice* device, devices_) 523 if (device != NULL) 524 device->clearBuffers(); 525 } 526 527 void InputManager::calibrate() 528 { 529 COUT(0) << "Move all joy stick axes fully in all directions." << std::endl 530 << "When done, put the axex in the middle position and press enter." << std::endl; 531 532 BOOST_FOREACH(InputDevice* device, devices_) 533 if (device != NULL) 534 device->startCalibration(); 535 536 internalState_ |= Calibrating; 537 enterState("calibrator"); 538 } 539 540 //! Tells all devices to stop the calibration and evaluate it. Buffers are being cleared as well! 541 void InputManager::stopCalibration() 542 { 543 BOOST_FOREACH(InputDevice* device, devices_) 544 if (device != NULL) 545 device->stopCalibration(); 546 547 // restore old input state 548 leaveState("calibrator"); 549 internalState_ &= ~Calibrating; 550 // Clear buffers to prevent button hold events 551 this->clearBuffers(); 552 553 COUT(0) << "Calibration has been stored." << std::endl; 554 } 555 556 //! Gets called by WindowEventListener upon focus change --> clear buffers 557 void InputManager::windowFocusChanged() 558 { 559 this->clearBuffers(); 560 } 561 562 // ############################################################ 563 // ##### Iput States ##### 971 564 // ########## ########## 972 565 // ############################################################ 973 566 974 // ###### Key Events ###### 975 976 /** 977 @brief 978 Event handler for the keyPressed Event. 979 @param e 980 Event information 981 */ 982 bool InputManager::keyPressed(const OIS::KeyEvent &e) 983 { 984 // check whether the key already is in the list (can happen when focus was lost) 985 unsigned int iKey = 0; 986 while (iKey < keysDown_.size() && keysDown_[iKey].key != (KeyCode::ByEnum)e.key) 987 iKey++; 988 if (iKey == keysDown_.size()) 989 keysDown_.push_back(Key(e)); 990 else 991 { 992 // This happens when XAutoRepeat is set under linux. The KeyPressed event gets then sent 993 // continuously. 994 return true; 995 } 996 997 // update modifiers 998 if(e.key == OIS::KC_RMENU || e.key == OIS::KC_LMENU) 999 keyboardModifiers_ |= KeyboardModifier::Alt; // alt key 1000 if(e.key == OIS::KC_RCONTROL || e.key == OIS::KC_LCONTROL) 1001 keyboardModifiers_ |= KeyboardModifier::Ctrl; // ctrl key 1002 if(e.key == OIS::KC_RSHIFT || e.key == OIS::KC_LSHIFT) 1003 keyboardModifiers_ |= KeyboardModifier::Shift; // shift key 1004 1005 KeyEvent kEvt(e, keyboardModifiers_); 1006 for (unsigned int iState = 0; iState < activeStatesTriggered_[Keyboard].size(); ++iState) 1007 activeStatesTriggered_[Keyboard][iState]->keyPressed(kEvt); 1008 1009 return true; 1010 } 1011 1012 /** 1013 @brief 1014 Event handler for the keyReleased Event. 1015 @param e 1016 Event information 1017 */ 1018 bool InputManager::keyReleased(const OIS::KeyEvent &e) 1019 { 1020 // remove the key from the keysDown_ list 1021 for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++) 1022 { 1023 if (keysDown_[iKey].key == (KeyCode::ByEnum)e.key) 1024 { 1025 keysDown_.erase(keysDown_.begin() + iKey); 1026 break; 1027 } 1028 } 1029 1030 // update modifiers 1031 if(e.key == OIS::KC_RMENU || e.key == OIS::KC_LMENU) 1032 keyboardModifiers_ &= ~KeyboardModifier::Alt; // alt key 1033 if(e.key == OIS::KC_RCONTROL || e.key == OIS::KC_LCONTROL) 1034 keyboardModifiers_ &= ~KeyboardModifier::Ctrl; // ctrl key 1035 if(e.key == OIS::KC_RSHIFT || e.key == OIS::KC_LSHIFT) 1036 keyboardModifiers_ &= ~KeyboardModifier::Shift; // shift key 1037 1038 KeyEvent kEvt(e, keyboardModifiers_); 1039 for (unsigned int iState = 0; iState < activeStatesTriggered_[Keyboard].size(); ++iState) 1040 activeStatesTriggered_[Keyboard][iState]->keyReleased(kEvt); 1041 1042 return true; 1043 } 1044 1045 1046 // ###### Mouse Events ###### 1047 1048 /** 1049 @brief 1050 Event handler for the mouseMoved Event. 1051 @param e 1052 Event information 1053 */ 1054 bool InputManager::mouseMoved(const OIS::MouseEvent &e) 1055 { 1056 // check for actual moved event 1057 if (e.state.X.rel != 0 || e.state.Y.rel != 0) 1058 { 1059 IntVector2 abs(e.state.X.abs, e.state.Y.abs); 1060 IntVector2 rel(e.state.X.rel, e.state.Y.rel); 1061 IntVector2 clippingSize(e.state.width, e.state.height); 1062 for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState) 1063 activeStatesTriggered_[Mouse][iState]->mouseMoved(abs, rel, clippingSize); 1064 } 1065 1066 // check for mouse scrolled event 1067 if (e.state.Z.rel != 0) 1068 { 1069 for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState) 1070 activeStatesTriggered_[Mouse][iState]->mouseScrolled(e.state.Z.abs, e.state.Z.rel); 1071 } 1072 1073 return true; 1074 } 1075 1076 /** 1077 @brief 1078 Event handler for the mousePressed Event. 1079 @param e 1080 Event information 1081 @param id 1082 The ID of the mouse button 1083 */ 1084 bool InputManager::mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id) 1085 { 1086 // check whether the button already is in the list (can happen when focus was lost) 1087 unsigned int iButton = 0; 1088 while (iButton < mouseButtonsDown_.size() && mouseButtonsDown_[iButton] != (MouseButtonCode::ByEnum)id) 1089 iButton++; 1090 if (iButton == mouseButtonsDown_.size()) 1091 mouseButtonsDown_.push_back((MouseButtonCode::ByEnum)id); 1092 1093 for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState) 1094 activeStatesTriggered_[Mouse][iState]->mouseButtonPressed((MouseButtonCode::ByEnum)id); 1095 1096 return true; 1097 } 1098 1099 /** 1100 @brief 1101 Event handler for the mouseReleased Event. 1102 @param e 1103 Event information 1104 @param id 1105 The ID of the mouse button 1106 */ 1107 bool InputManager::mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID id) 1108 { 1109 // remove the button from the keysDown_ list 1110 for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++) 1111 { 1112 if (mouseButtonsDown_[iButton] == (MouseButtonCode::ByEnum)id) 1113 { 1114 mouseButtonsDown_.erase(mouseButtonsDown_.begin() + iButton); 1115 break; 1116 } 1117 } 1118 1119 for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState) 1120 activeStatesTriggered_[Mouse][iState]->mouseButtonReleased((MouseButtonCode::ByEnum)id); 1121 1122 return true; 1123 } 1124 1125 1126 // ###### Joy Stick Events ###### 1127 1128 /** 1129 @brief 1130 Returns the joy stick ID (orxonox) according to a OIS::JoyStickEvent 1131 */ 1132 inline unsigned int InputManager::_getJoystick(const OIS::JoyStickEvent& arg) 1133 { 1134 // use the device to identify which one called the method 1135 OIS::JoyStick* joyStick = (OIS::JoyStick*)arg.device; 1136 unsigned int iJoyStick = 0; 1137 while (joySticks_[iJoyStick] != joyStick) 1138 iJoyStick++; 1139 // assert: Unknown joystick fired an event. 1140 assert(iJoyStick != joySticksSize_); 1141 return iJoyStick; 1142 } 1143 1144 bool InputManager::buttonPressed(const OIS::JoyStickEvent &arg, int button) 1145 { 1146 unsigned int iJoyStick = _getJoystick(arg); 1147 1148 // check whether the button already is in the list (can happen when focus was lost) 1149 std::vector<JoyStickButtonCode::ByEnum>& buttonsDown = joyStickButtonsDown_[iJoyStick]; 1150 unsigned int iButton = 0; 1151 while (iButton < buttonsDown.size() && buttonsDown[iButton] != button) 1152 iButton++; 1153 if (iButton == buttonsDown.size()) 1154 buttonsDown.push_back((JoyStickButtonCode::ByEnum)button); 1155 1156 for (unsigned int iState = 0; iState < activeStatesTriggered_[2 + iJoyStick].size(); ++iState) 1157 activeStatesTriggered_[2 + iJoyStick][iState]->joyStickButtonPressed(iJoyStick, (JoyStickButtonCode::ByEnum)button); 1158 1159 return true; 1160 } 1161 1162 bool InputManager::buttonReleased(const OIS::JoyStickEvent &arg, int button) 1163 { 1164 unsigned int iJoyStick = _getJoystick(arg); 1165 1166 // remove the button from the joyStickButtonsDown_ list 1167 std::vector<JoyStickButtonCode::ByEnum>& buttonsDown = joyStickButtonsDown_[iJoyStick]; 1168 for (unsigned int iButton = 0; iButton < buttonsDown.size(); iButton++) 1169 { 1170 if (buttonsDown[iButton] == button) 1171 { 1172 buttonsDown.erase(buttonsDown.begin() + iButton); 1173 break; 1174 } 1175 } 1176 1177 for (unsigned int iState = 0; iState < activeStatesTriggered_[2 + iJoyStick].size(); ++iState) 1178 activeStatesTriggered_[2 + iJoyStick][iState]->joyStickButtonReleased(iJoyStick, (JoyStickButtonCode::ByEnum)button); 1179 1180 return true; 1181 } 1182 1183 /** 1184 @brief 1185 Calls the states for a particular axis with our enumeration. 1186 Used by OIS sliders and OIS axes. 1187 */ 1188 void InputManager::_fireAxis(unsigned int iJoyStick, int axis, int value) 1189 { 1190 if (internalState_ & Calibrating) 1191 { 1192 if (value < joyStickMinValues_[iJoyStick][axis]) 1193 joyStickMinValues_[iJoyStick][axis] = value; 1194 if (value > joyStickMaxValues_[iJoyStick][axis]) 1195 joyStickMaxValues_[iJoyStick][axis] = value; 1196 } 1197 else 1198 { 1199 float fValue = static_cast<float>(value - joyStickCalibrations_[iJoyStick].middleValue[axis]); 1200 if (fValue > 0.0f) 1201 fValue *= joyStickCalibrations_[iJoyStick].positiveCoeff[axis]; 1202 else 1203 fValue *= joyStickCalibrations_[iJoyStick].negativeCoeff[axis]; 1204 1205 for (unsigned int iState = 0; iState < activeStatesTriggered_[2 + iJoyStick].size(); ++iState) 1206 activeStatesTriggered_[2 + iJoyStick][iState]->joyStickAxisMoved(iJoyStick, axis, fValue); 1207 } 1208 } 1209 1210 bool InputManager::axisMoved(const OIS::JoyStickEvent &arg, int axis) 1211 { 1212 unsigned int iJoyStick = _getJoystick(arg); 1213 1214 // keep in mind that the first 8 axes are reserved for the sliders 1215 _fireAxis(iJoyStick, axis + sliderAxes, arg.state.mAxes[axis].abs); 1216 1217 return true; 1218 } 1219 1220 bool InputManager::sliderMoved(const OIS::JoyStickEvent &arg, int id) 1221 { 1222 unsigned int iJoyStick = _getJoystick(arg); 1223 1224 if (sliderStates_[iJoyStick].sliderStates[id].x != arg.state.mSliders[id].abX) 1225 _fireAxis(iJoyStick, id * 2, arg.state.mSliders[id].abX); 1226 else if (sliderStates_[iJoyStick].sliderStates[id].y != arg.state.mSliders[id].abY) 1227 _fireAxis(iJoyStick, id * 2 + 1, arg.state.mSliders[id].abY); 1228 1229 return true; 1230 } 1231 1232 bool InputManager::povMoved(const OIS::JoyStickEvent &arg, int id) 1233 { 1234 unsigned int iJoyStick = _getJoystick(arg); 1235 1236 // translate the POV into 8 simple buttons 1237 1238 int lastState = povStates_[iJoyStick][id]; 1239 if (lastState & OIS::Pov::North) 1240 buttonReleased(arg, 32 + id * 4 + 0); 1241 if (lastState & OIS::Pov::South) 1242 buttonReleased(arg, 32 + id * 4 + 1); 1243 if (lastState & OIS::Pov::East) 1244 buttonReleased(arg, 32 + id * 4 + 2); 1245 if (lastState & OIS::Pov::West) 1246 buttonReleased(arg, 32 + id * 4 + 3); 1247 1248 povStates_[iJoyStick].povStates[id] = arg.state.mPOV[id].direction; 1249 1250 int currentState = povStates_[iJoyStick][id]; 1251 if (currentState & OIS::Pov::North) 1252 buttonPressed(arg, 32 + id * 4 + 0); 1253 if (currentState & OIS::Pov::South) 1254 buttonPressed(arg, 32 + id * 4 + 1); 1255 if (currentState & OIS::Pov::East) 1256 buttonPressed(arg, 32 + id * 4 + 2); 1257 if (currentState & OIS::Pov::West) 1258 buttonPressed(arg, 32 + id * 4 + 3); 1259 1260 return true; 1261 } 1262 1263 1264 // ############################################################ 1265 // ##### Other Public Interface Methods ##### 1266 // ########## ########## 1267 // ############################################################ 1268 1269 /** 1270 @brief 1271 Adjusts the mouse window metrics. 1272 This method has to be called every time the size of the window changes. 1273 @param width 1274 The new width of the render window 1275 @param^height 1276 The new height of the render window 1277 */ 1278 void InputManager::setWindowExtents(const int width, const int height) 1279 { 1280 if (mouse_) 1281 { 1282 // Set mouse region (if window resizes, we should alter this to reflect as well) 1283 mouse_->getMouseState().width = width; 1284 mouse_->getMouseState().height = height; 1285 } 1286 } 1287 1288 /** 1289 @brief 1290 Sets the the name of the command used by the KeyDetector as callback. 1291 @param command 1292 Command name as string 1293 */ 1294 void InputManager::setKeyDetectorCallback(const std::string& command) 1295 { 1296 this->keyDetector_->setCallbackCommand(command); 1297 } 1298 1299 // ###### InputStates ###### 1300 1301 /** 1302 @brief 1303 Adds a new key handler. 1304 @param handler 1305 Pointer to the handler object. 1306 @param name 1307 Unique name of the handler. 1308 @param priority 1309 Determines which InputState gets the input. Higher is better. 1310 Use 0 to handle it implicitely by the order of activation. 1311 Otherwise numbers larger than maxStateStackSize_s have to be used! 1312 @return 1313 True if added, false if name or priority already existed. 1314 */ 1315 bool InputManager::_configureInputState(InputState* state, const std::string& name, bool bAlwaysGetsInput, bool bTransparent, int priority) 567 InputState* InputManager::createInputState(const std::string& name, bool bAlwaysGetsInput, bool bTransparent, InputStatePriority priority) 1316 568 { 1317 569 if (name == "") 1318 return false; 1319 if (!state) 1320 return false; 1321 if (inputStatesByName_.find(name) == inputStatesByName_.end()) 570 return 0; 571 if (statesByName_.find(name) == statesByName_.end()) 1322 572 { 1323 573 if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty) 1324 574 { 1325 575 // Make sure we don't add two high priority states with the same priority 1326 for (std::map<std::string, InputState*>::const_iterator it = this-> inputStatesByName_.begin();1327 it != this-> inputStatesByName_.end(); ++it)576 for (std::map<std::string, InputState*>::const_iterator it = this->statesByName_.begin(); 577 it != this->statesByName_.end(); ++it) 1328 578 { 1329 579 if (it->second->getPriority() == priority) 1330 580 { 1331 581 COUT(2) << "Warning: Could not add an InputState with the same priority '" 1332 << priority<< "' != 0." << std::endl;1333 return false;582 << static_cast<int>(priority) << "' != 0." << std::endl; 583 return 0; 1334 584 } 1335 585 } 1336 586 } 1337 inputStatesByName_[name] = state; 1338 state->setNumOfJoySticks(numberOfJoySticks()); 1339 state->setName(name); 1340 state->bAlwaysGetsInput_ = bAlwaysGetsInput; 1341 state->bTransparent_ = bTransparent; 1342 if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty) 1343 state->setPriority(priority); 1344 return true; 587 InputState* state = new InputState(name, bAlwaysGetsInput, bTransparent, priority); 588 statesByName_[name] = state; 589 590 return state; 1345 591 } 1346 592 else 1347 593 { 1348 594 COUT(2) << "Warning: Could not add an InputState with the same name '" << name << "'." << std::endl; 1349 return false; 1350 } 1351 } 1352 1353 /** 1354 @brief 1355 Removes and destroys an input state internally. 1356 @param name 1357 Name of the handler. 1358 @return 1359 True if removal was successful, false if name was not found. 1360 @remarks 1361 You can't remove the internal states "empty", "calibrator" and "detector". 1362 The removal process is being postponed if InputManager::update() is currently running. 1363 */ 1364 bool InputManager::requestDestroyState(const std::string& name) 1365 { 1366 if (name == "empty") 1367 { 1368 COUT(2) << "InputManager: Removing the empty state is not allowed!" << std::endl; 1369 return false; 1370 } 1371 std::map<std::string, InputState*>::iterator it = inputStatesByName_.find(name); 1372 if (it != inputStatesByName_.end()) 1373 { 1374 if (activeStates_.find(it->second->getPriority()) != activeStates_.end()) 1375 { 1376 // The state is still active. We have to postpone 1377 stateLeaveRequests_.insert(it->second); 1378 stateDestroyRequests_.insert(it->second); 1379 } 1380 else if (this->internalState_ & Ticking) 1381 { 1382 // cannot remove state while ticking 1383 stateDestroyRequests_.insert(it->second); 1384 } 1385 else 1386 _destroyState(it->second); 1387 1388 return true; 1389 } 1390 return false; 1391 } 1392 1393 /** 1394 @brief 1395 Returns the pointer to the requested InputState. 1396 @param name 1397 Unique name of the state. 1398 @return 1399 Pointer to the instance, 0 if name was not found. 1400 */ 595 return 0; 596 } 597 } 598 1401 599 InputState* InputManager::getState(const std::string& name) 1402 600 { 1403 std::map<std::string, InputState*>::iterator it = inputStatesByName_.find(name);1404 if (it != inputStatesByName_.end())601 std::map<std::string, InputState*>::iterator it = statesByName_.find(name); 602 if (it != statesByName_.end()) 1405 603 return it->second; 1406 604 else … … 1408 606 } 1409 607 1410 /** 1411 @brief 1412 Returns the current input state (there might be others active too!) 1413 @return 1414 The current highest prioritised active input state. 1415 */ 1416 InputState* InputManager::getCurrentState() 1417 { 1418 return (*activeStates_.rbegin()).second; 1419 } 1420 1421 /** 1422 @brief 1423 Activates a specific input state. 1424 It might not be really activated if the priority is too low! 1425 @param name 1426 Unique name of the state. 1427 @return 1428 False if name was not found, true otherwise. 1429 */ 1430 bool InputManager::requestEnterState(const std::string& name) 608 bool InputManager::enterState(const std::string& name) 1431 609 { 1432 610 // get pointer from the map with all stored handlers 1433 std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.find(name);1434 if (it != inputStatesByName_.end())611 std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name); 612 if (it != statesByName_.end()) 1435 613 { 1436 614 // exists … … 1450 628 } 1451 629 1452 /** 1453 @brief 1454 Deactivates a specific input state. 1455 @param name 1456 Unique name of the state. 1457 @return 1458 False if name was not found, true otherwise. 1459 */ 1460 bool InputManager::requestLeaveState(const std::string& name) 630 bool InputManager::leaveState(const std::string& name) 1461 631 { 1462 632 if (name == "empty") … … 1466 636 } 1467 637 // get pointer from the map with all stored handlers 1468 std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.find(name);1469 if (it != inputStatesByName_.end())638 std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name); 639 if (it != statesByName_.end()) 1470 640 { 1471 641 // exists … … 1480 650 } 1481 651 1482 1483 // ############################################################ 1484 // ##### Console Commands ##### 1485 // ########## ########## 1486 // ############################################################ 1487 1488 /** 1489 @brief 1490 Starts joy stick calibration. 1491 */ 1492 void InputManager::calibrate() 1493 { 1494 COUT(0) << "Move all joy stick axes fully in all directions." << std::endl 1495 << "When done, put the axex in the middle position and press enter." << std::endl; 1496 1497 getInstance()._startCalibration(); 1498 } 1499 1500 /** 1501 @brief 1502 Reloads the input system 1503 */ 1504 void InputManager::reload(bool joyStickSupport) 1505 { 1506 getInstance().reloadInputSystem(joyStickSupport); 1507 } 1508 1509 1510 // ############################################################ 1511 // ##### ugly hacks ##### 1512 // ########## ########## 1513 // ############################################################ 1514 1515 #ifdef ORXONOX_PLATFORM_LINUX 1516 void InputManager::grabMouse() 1517 { 1518 OIS::LinuxMouse* linuxMouse = dynamic_cast<OIS::LinuxMouse*>(singletonRef_s->mouse_); 1519 assert(linuxMouse); 1520 linuxMouse->grab(true); 1521 } 1522 1523 void InputManager::ungrabMouse() 1524 { 1525 OIS::LinuxMouse* linuxMouse = dynamic_cast<OIS::LinuxMouse*>(singletonRef_s->mouse_); 1526 assert(linuxMouse); 1527 linuxMouse->grab(false); 1528 } 1529 #endif 652 bool InputManager::destroyState(const std::string& name) 653 { 654 if (name == "empty") 655 { 656 COUT(2) << "InputManager: Removing the empty state is not allowed!" << std::endl; 657 return false; 658 } 659 std::map<std::string, InputState*>::iterator it = statesByName_.find(name); 660 if (it != statesByName_.end()) 661 { 662 if (activeStates_.find(it->second->getPriority()) != activeStates_.end()) 663 { 664 // The state is still active. We have to postpone 665 stateLeaveRequests_.insert(it->second); 666 stateDestroyRequests_.insert(it->second); 667 } 668 else if (this->internalState_ & Ticking) 669 { 670 // cannot remove state while ticking 671 stateDestroyRequests_.insert(it->second); 672 } 673 else 674 destroyStateInternal(it->second); 675 676 return true; 677 } 678 return false; 679 } 680 681 //! Destroys an InputState internally. 682 void InputManager::destroyStateInternal(InputState* state) 683 { 684 assert(state && !(this->internalState_ & Ticking)); 685 std::map<int, InputState*>::iterator it = this->activeStates_.find(state->getPriority()); 686 if (it != this->activeStates_.end()) 687 { 688 this->activeStates_.erase(it); 689 updateActiveStates(); 690 } 691 statesByName_.erase(state->getName()); 692 delete state; 693 } 1530 694 }
Note: See TracChangeset
for help on using the changeset viewer.