Changeset 6657 for code/branches/gamestate/src/libraries/core/input
- Timestamp:
- Mar 30, 2010, 12:13:33 PM (15 years ago)
- Location:
- code/branches/gamestate/src/libraries/core/input
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/gamestate/src/libraries/core/input/InputDevice.h
r6417 r6657 159 159 for (unsigned int iB = 0; iB < pressedButtons_.size(); ++iB) 160 160 for (unsigned int iS = 0; iS < inputStates_.size(); ++iS) 161 inputStates_[iS]->buttonEvent<ButtonEvent::THold, Traits >(161 inputStates_[iS]->buttonEvent<ButtonEvent::THold, Traits::ButtonTypeParam>( 162 162 this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(pressedButtons_[iB])); 163 163 … … 196 196 // Call states 197 197 for (unsigned int i = 0; i < inputStates_.size(); ++i) 198 inputStates_[i]->buttonEvent<ButtonEvent::TPress, Traits >(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button));198 inputStates_[i]->buttonEvent<ButtonEvent::TPress, Traits::ButtonTypeParam>(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button)); 199 199 } 200 200 … … 218 218 // Call states 219 219 for (unsigned int i = 0; i < inputStates_.size(); ++i) 220 inputStates_[i]->buttonEvent<ButtonEvent::TRelease, Traits >(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button));220 inputStates_[i]->buttonEvent<ButtonEvent::TRelease, Traits::ButtonTypeParam>(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button)); 221 221 } 222 222 -
code/branches/gamestate/src/libraries/core/input/InputHandler.h
r6105 r6657 112 112 virtual ~InputHandler() { } 113 113 114 template<class T> void buttonEvent(unsigned int device, const T&button, ButtonEvent::TPress)114 template<class T> void buttonEvent(unsigned int device, T button, ButtonEvent::TPress) 115 115 { this->buttonPressed(button); } 116 template<class T> void buttonEvent(unsigned int device, const T&button, ButtonEvent::TRelease)116 template<class T> void buttonEvent(unsigned int device, T button, ButtonEvent::TRelease) 117 117 { this->buttonReleased(button); } 118 template<class T> void buttonEvent(unsigned int device, const T&button, ButtonEvent::THold)118 template<class T> void buttonEvent(unsigned int device, T button, ButtonEvent::THold) 119 119 { this->buttonHeld(button); } 120 void buttonEvent(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TPress)120 template<> void buttonEvent<JoyStickButtonCode::ByEnum>(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TPress) 121 121 { this->buttonPressed(device - InputDeviceEnumerator::FirstJoyStick, button); } 122 void buttonEvent(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TRelease)122 template<> void buttonEvent<JoyStickButtonCode::ByEnum>(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TRelease) 123 123 { this->buttonReleased(device - InputDeviceEnumerator::FirstJoyStick, button); } 124 void buttonEvent(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::THold)124 template<> void buttonEvent<JoyStickButtonCode::ByEnum>(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::THold) 125 125 { this->buttonHeld(device - InputDeviceEnumerator::FirstJoyStick, button); } 126 126 -
code/branches/gamestate/src/libraries/core/input/InputManager.cc
r6537 r6657 95 95 CCOUT(4) << "Constructing..." << std::endl; 96 96 97 // Allocate space for the function call buffer 98 this->callBuffer_.reserve(16); 99 97 100 this->setConfigValues(); 98 101 … … 266 269 CCOUT(3) << "Destroying..." << std::endl; 267 270 271 // Leave all active InputStates (except "empty") 272 while (this->activeStates_.size() > 1) 273 this->leaveState(this->activeStates_.rbegin()->second->getName()); 274 this->activeStates_.clear(); 275 268 276 // Destroy calibrator helper handler and state 269 277 this->destroyState("calibrator"); 270 278 // Destroy KeyDetector and state 271 279 calibratorCallbackHandler_->destroy(); 272 // destroy the empty InputState280 // Destroy the empty InputState 273 281 this->destroyStateInternal(this->emptyState_); 274 282 275 // destroy all user InputStates283 // Destroy all user InputStates 276 284 while (statesByName_.size() > 0) 277 285 this->destroyStateInternal(statesByName_.rbegin()->second); … … 335 343 void InputManager::reload() 336 344 { 337 if (internalState_ & Ticking) 338 { 339 // We cannot destroy OIS right now, because reload was probably 340 // caused by a user clicking on a GUI item. The stack trace would then 341 // include an OIS method. So it would be a very bad thing to destroy it.. 342 internalState_ |= ReloadRequest; 343 } 344 else if (internalState_ & Calibrating) 345 if (internalState_ & Calibrating) 345 346 CCOUT(2) << "Warning: Cannot reload input system. Joy sticks are currently being calibrated." << std::endl; 346 347 else … … 351 352 void InputManager::reloadInternal() 352 353 { 353 CCOUT( 3) << "Reloading ..." << std::endl;354 CCOUT(4) << "Reloading ..." << std::endl; 354 355 355 356 this->destroyDevices(); … … 357 358 358 359 internalState_ &= ~Bad; 359 internalState_ &= ~ReloadRequest;360 360 CCOUT(4) << "Reloading complete." << std::endl; 361 361 } … … 370 370 if (internalState_ & Bad) 371 371 ThrowException(General, "InputManager was not correctly reloaded."); 372 373 else if (internalState_ & ReloadRequest)374 reloadInternal();375 376 // check for states to leave377 if (!stateLeaveRequests_.empty())378 {379 for (std::set<InputState*>::iterator it = stateLeaveRequests_.begin();380 it != stateLeaveRequests_.end(); ++it)381 {382 (*it)->left();383 // just to be sure that the state actually is registered384 assert(statesByName_.find((*it)->getName()) != statesByName_.end());385 386 activeStates_.erase((*it)->getPriority());387 if ((*it)->getPriority() < InputStatePriority::HighPriority)388 (*it)->setPriority(0);389 updateActiveStates();390 }391 stateLeaveRequests_.clear();392 }393 394 // check for states to enter395 if (!stateEnterRequests_.empty())396 {397 for (std::set<InputState*>::const_iterator it = stateEnterRequests_.begin();398 it != stateEnterRequests_.end(); ++it)399 {400 // just to be sure that the state actually is registered401 assert(statesByName_.find((*it)->getName()) != statesByName_.end());402 403 if ((*it)->getPriority() == 0)404 {405 // Get smallest possible priority between 1 and maxStateStackSize_s406 for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();407 rit != activeStates_.rend(); ++rit)408 {409 if (rit->first < InputStatePriority::HighPriority)410 {411 (*it)->setPriority(rit->first + 1);412 break;413 }414 }415 // In case no normal handler was on the stack416 if ((*it)->getPriority() == 0)417 (*it)->setPriority(1);418 }419 activeStates_[(*it)->getPriority()] = (*it);420 updateActiveStates();421 (*it)->entered();422 }423 stateEnterRequests_.clear();424 }425 426 // check for states to destroy427 if (!stateDestroyRequests_.empty())428 {429 for (std::set<InputState*>::iterator it = stateDestroyRequests_.begin();430 it != stateDestroyRequests_.end(); ++it)431 {432 destroyStateInternal((*it));433 }434 stateDestroyRequests_.clear();435 }436 372 437 373 // check whether a state has changed its EMPTY situation … … 448 384 updateActiveStates(); 449 385 450 // mark that we now start capturing and distributing input 451 internalState_ |= Ticking; 452 453 // Capture all the input and handle it 386 // Capture all the input and collect the function calls 387 // No event gets triggered here yet! 454 388 BOOST_FOREACH(InputDevice* device, devices_) 455 389 if (device != NULL) 456 390 device->update(time); 457 391 458 // Update the states392 // Collect functions calls for the update 459 393 for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i) 460 394 activeStatesTicked_[i]->update(time.getDeltaTime()); 461 395 462 internalState_ &= ~Ticking; 396 // Execute all cached function calls in order 397 // Why so complicated? The problem is that an InputHandler could trigger 398 // a reload that would destroy the OIS devices or it could even leave and 399 // then destroy its own InputState. That would of course lead to access 400 // violations. 401 // If we delay the calls, then OIS and and the InputStates are not anymore 402 // in the call stack and can therefore be edited. 403 for (size_t i = 0; i < this->callBuffer_.size(); ++i) 404 this->callBuffer_[i](); 405 406 this->callBuffer_.clear(); 463 407 } 464 408 … … 470 414 void InputManager::updateActiveStates() 471 415 { 472 assert((internalState_ & InputManager::Ticking) == 0);473 416 // temporary resize 474 417 for (unsigned int i = 0; i < devices_.size(); ++i) … … 622 565 // get pointer from the map with all stored handlers 623 566 std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name); 624 if (it != statesByName_.end()) 625 { 626 // exists 627 if (activeStates_.find(it->second->getPriority()) == activeStates_.end()) 628 { 629 // not active 630 if (stateDestroyRequests_.find(it->second) == stateDestroyRequests_.end()) 567 if (it != statesByName_.end() && activeStates_.find(it->second->getPriority()) == activeStates_.end()) 568 { 569 // exists and not active 570 if (it->second->getPriority() == 0) 571 { 572 // Get smallest possible priority between 1 and maxStateStackSize_s 573 for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin(); 574 rit != activeStates_.rend(); ++rit) 631 575 { 632 // not scheduled for destruction 633 // prevents a state from being added multiple times 634 stateEnterRequests_.insert(it->second); 635 return true; 576 if (rit->first < InputStatePriority::HighPriority) 577 { 578 it->second->setPriority(rit->first + 1); 579 break; 580 } 636 581 } 637 } 638 else if (this->stateLeaveRequests_.find(it->second) != this->stateLeaveRequests_.end()) 639 { 640 // State already scheduled for leaving --> cancel 641 this->stateLeaveRequests_.erase(this->stateLeaveRequests_.find(it->second)); 642 } 582 // In case no normal handler was on the stack 583 if (it->second->getPriority() == 0) 584 it->second->setPriority(1); 585 } 586 activeStates_[it->second->getPriority()] = it->second; 587 updateActiveStates(); 588 it->second->entered(); 589 590 return true; 643 591 } 644 592 return false; … … 654 602 // get pointer from the map with all stored handlers 655 603 std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name); 656 if (it != statesByName_.end()) 657 { 658 // exists 659 if (activeStates_.find(it->second->getPriority()) != activeStates_.end()) 660 { 661 // active 662 stateLeaveRequests_.insert(it->second); 663 return true; 664 } 665 else if (this->stateEnterRequests_.find(it->second) != this->stateEnterRequests_.end()) 666 { 667 // State already scheduled for entering --> cancel 668 this->stateEnterRequests_.erase(this->stateEnterRequests_.find(it->second)); 669 } 604 if (it != statesByName_.end() && activeStates_.find(it->second->getPriority()) != activeStates_.end()) 605 { 606 // exists and active 607 608 it->second->left(); 609 610 activeStates_.erase(it->second->getPriority()); 611 if (it->second->getPriority() < InputStatePriority::HighPriority) 612 it->second->setPriority(0); 613 updateActiveStates(); 614 615 return true; 670 616 } 671 617 return false; … … 682 628 if (it != statesByName_.end()) 683 629 { 684 if (activeStates_.find(it->second->getPriority()) != activeStates_.end()) 685 { 686 // The state is still active. We have to postpone 687 stateLeaveRequests_.insert(it->second); 688 stateDestroyRequests_.insert(it->second); 689 } 690 else if (this->internalState_ & Ticking) 691 { 692 // cannot remove state while ticking 693 stateDestroyRequests_.insert(it->second); 694 } 695 else 696 destroyStateInternal(it->second); 630 this->leaveState(name); 631 destroyStateInternal(it->second); 697 632 698 633 return true; … … 704 639 void InputManager::destroyStateInternal(InputState* state) 705 640 { 706 assert(state && !(this->internalState_ & Ticking)); 707 std::map<int, InputState*>::iterator it = this->activeStates_.find(state->getPriority()); 708 if (it != this->activeStates_.end()) 709 { 710 this->activeStates_.erase(it); 711 updateActiveStates(); 712 } 641 assert(state && this->activeStates_.find(state->getPriority()) == this->activeStates_.end()); 713 642 statesByName_.erase(state->getName()); 714 643 state->destroy(); -
code/branches/gamestate/src/libraries/core/input/InputManager.h
r6656 r6657 36 36 #include <string> 37 37 #include <vector> 38 #include <boost/function.hpp> 38 39 39 40 #include "util/Singleton.h" … … 75 76 Nothing = 0x00, 76 77 Bad = 0x02, 77 Ticking = 0x04, 78 Calibrating = 0x08, 79 ReloadRequest = 0x10, 78 Calibrating = 0x04, 80 79 }; 81 80 … … 171 170 std::pair<int, int> getMousePosition() const; 172 171 172 //------------------------------- 173 // Function call caching 174 //------------------------------- 175 void pushCall(const boost::function<void ()>& function) 176 { this->callBuffer_.push_back(function); } 177 173 178 static InputManager& getInstance() { return Singleton<InputManager>::getInstance(); } // tolua_export 174 179 … … 207 212 std::vector<InputState*> activeStatesTicked_; //!< Like activeStates_, but only contains the ones that currently receive events 208 213 209 std::set<InputState*> stateEnterRequests_; //!< Requests to enter a new state 210 std::set<InputState*> stateLeaveRequests_; //!< Requests to leave a running state 211 std::set<InputState*> stateDestroyRequests_; //!< Requests to destroy a state 214 std::vector<boost::function<void ()> > callBuffer_; //!< Caches all calls from InputStates to be executed afterwards (see preUpdate) 212 215 213 216 static InputManager* singletonPtr_s; //!< Pointer reference to the singleton -
code/branches/gamestate/src/libraries/core/input/InputState.h
r6656 r6657 35 35 #include <string> 36 36 #include <vector> 37 #include <boost/function.hpp> 38 #include <boost/bind.hpp> 37 39 38 40 #include "util/TriBool.h" 39 41 #include "InputHandler.h" 42 #include "InputManager.h" 40 43 #include "JoyStickQuantityListener.h" 44 45 #define INPUT_STATE_PUSH_CALL(deviceIndex, functionName, ...) \ 46 InputManager::getInstance().pushCall(boost::function<void ()>(boost::bind(&InputHandler::functionName, handlers_[deviceIndex], __VA_ARGS__))) 41 47 42 48 namespace orxonox … … 128 134 129 135 //! Generic function that distributes all 9 button events 130 template <typename EventType, class Traits>131 void buttonEvent(unsigned int device, const typename Traits::ButtonTypeParam button);136 template <typename EventType, class ButtonTypeParam> 137 void buttonEvent(unsigned int device, ButtonTypeParam button); 132 138 133 139 //! Event handler … … 174 180 for (unsigned int i = 0; i < handlers_.size(); ++i) 175 181 if (handlers_[i] != NULL) 176 handlers_[i]->allDevicesUpdated(dt);182 INPUT_STATE_PUSH_CALL(i, allDevicesUpdated, dt); 177 183 } 178 184 … … 183 189 case InputDeviceEnumerator::Keyboard: 184 190 if (handlers_[keyboardIndex_s] != NULL) 185 handlers_[keyboardIndex_s]->keyboardUpdated(dt);191 INPUT_STATE_PUSH_CALL(keyboardIndex_s, keyboardUpdated, dt); 186 192 break; 187 193 188 194 case InputDeviceEnumerator::Mouse: 189 195 if (handlers_[mouseIndex_s] != NULL) 190 handlers_[mouseIndex_s]->mouseUpdated(dt);196 INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseUpdated, dt); 191 197 break; 192 198 193 199 default: // joy sticks 194 200 if (handlers_[device] != NULL) 195 handlers_[device]->joyStickUpdated(device - firstJoyStickIndex_s, dt);201 INPUT_STATE_PUSH_CALL(device, joyStickUpdated, device - firstJoyStickIndex_s, dt); 196 202 break; 197 203 } 198 204 } 199 205 200 template <typename EventType, class Traits>201 FORCEINLINE void InputState::buttonEvent(unsigned int device, const typename Traits::ButtonTypeParam button)206 template <typename EventType, class ButtonTypeParam> 207 FORCEINLINE void InputState::buttonEvent(unsigned int device, typename ButtonTypeParam button) 202 208 { 203 209 assert(device < handlers_.size()); 204 210 if (handlers_[device] != NULL) 205 handlers_[device]->buttonEvent(device, button, EventType()); 211 { 212 // We have to store the function pointer to tell the compiler about its actual type because of overloading 213 void (InputHandler::*function)(unsigned int, ButtonTypeParam, EventType) = &InputHandler::buttonEvent<ButtonTypeParam>; 214 InputManager::getInstance().pushCall(boost::function<void ()>(boost::bind(function, handlers_[device], device, button, EventType()))); 215 } 206 216 } 207 217 … … 209 219 { 210 220 if (handlers_[mouseIndex_s] != NULL) 211 handlers_[mouseIndex_s]->mouseMoved(abs, rel, clippingSize);221 INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseMoved, abs, rel, clippingSize); 212 222 } 213 223 … … 215 225 { 216 226 if (handlers_[mouseIndex_s] != NULL) 217 handlers_[mouseIndex_s]->mouseScrolled(abs, rel);227 INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseScrolled, abs, rel); 218 228 } 219 229 … … 222 232 assert(device < handlers_.size()); 223 233 if (handlers_[device] != NULL) 224 handlers_[device]->axisMoved(device - firstJoyStickIndex_s, axis, value);234 INPUT_STATE_PUSH_CALL(device, axisMoved, device - firstJoyStickIndex_s, axis, value); 225 235 } 226 236 }
Note: See TracChangeset
for help on using the changeset viewer.