Changeset 6662 for code/branches/gamestates2/src
- Timestamp:
- Mar 31, 2010, 1:05:28 AM (15 years ago)
- Location:
- code/branches/gamestates2
- Files:
-
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/gamestates2
- Property svn:mergeinfo changed
/code/branches/gamestate merged: 6621-6630,6655-6661
- Property svn:mergeinfo changed
-
code/branches/gamestates2/src/libraries/core/Core.cc
r6595 r6662 78 78 79 79 SetCommandLineArgument(settingsFile, "orxonox.ini").information("THE configuration file"); 80 SetCommandLineSwitch(noIOConsole).information("Use this if you don't want to use the IOConsole (for instance for Lua debugging)"); 80 81 #ifdef ORXONOX_PLATFORM_WINDOWS 81 82 SetCommandLineArgument(limitToCPU, 1).information("Limits the program to one CPU/core (1, 2, 3, etc.). Default is the first core (faster than off)"); … … 88 89 , consoleCommandDestroyer_(CommandExecutor::destroyExternalCommands) 89 90 , bGraphicsLoaded_(false) 91 , bStartIOConsole_(true) 90 92 { 91 93 // Set the hard coded fixed paths … … 149 151 150 152 // create persistent io console 151 this->ioConsole_.reset(new IOConsole()); 153 if (CommandLineParser::getValue("noIOConsole").getBool()) 154 { 155 ModifyConfigValue(bStartIOConsole_, tset, false); 156 } 157 if (this->bStartIOConsole_) 158 this->ioConsole_.reset(new IOConsole()); 152 159 153 160 // creates the class hierarchy for all classes with factories … … 193 200 .description("If true, all random actions are different each time you start the game") 194 201 .callback(this, &Core::initRandomNumberGenerator); 202 SetConfigValue(bStartIOConsole_, true) 203 .description("Set to false if you don't want to use the IOConsole (for Lua debugging for instance)"); 195 204 } 196 205 … … 327 336 } 328 337 // Process console events and status line 329 this->ioConsole_->preUpdate(time); 338 if (this->ioConsole_ != NULL) 339 this->ioConsole_->preUpdate(time); 330 340 // Process thread commands 331 341 this->tclThreadManager_->preUpdate(time); -
code/branches/gamestates2/src/libraries/core/Core.h
r6595 r6662 97 97 scoped_ptr<TclBind> tclBind_; 98 98 scoped_ptr<TclThreadManager> tclThreadManager_; 99 scoped_ptr<Scope<ScopeID::Root> > 99 scoped_ptr<Scope<ScopeID::Root> > rootScope_; 100 100 // graphical 101 101 scoped_ptr<GraphicsManager> graphicsManager_; //!< Interface to OGRE … … 108 108 std::string language_; //!< The language 109 109 bool bInitRandomNumberGenerator_; //!< If true, srand(time(0)) is called 110 bool bStartIOConsole_; //!< Set to false if you don't want to use the IOConsole 110 111 111 112 static Core* singletonPtr_s; -
code/branches/gamestates2/src/libraries/core/GUIManager.cc
r6595 r6662 253 253 } 254 254 255 const std::string& GUIManager::createInputState(const std::string& name, TriBool::Value show Mouse, TriBool::Value useKeyboard, bool bBlockJoyStick)255 const std::string& GUIManager::createInputState(const std::string& name, TriBool::Value showCursor, TriBool::Value useKeyboard, bool bBlockJoyStick) 256 256 { 257 257 InputState* state = InputManager::getInstance().createInputState(name); 258 258 259 if (GraphicsManager::getInstance().isFullScreen() && showMouse == TriBool::True || 260 !GraphicsManager::getInstance().isFullScreen() && showMouse == TriBool::False) 259 /* Table that maps isFullScreen() and showCursor to mouseExclusive 260 isFullscreen / showCursor | True | False | Dontcare 261 ---------------------------------------------------- 262 true | True | True | Dontcare 263 ---------------------------------------------------- 264 false | False | True | Dontcare 265 */ 266 if (showCursor == TriBool::Dontcare) 267 state->setMouseExclusive(TriBool::Dontcare); 268 else if (GraphicsManager::getInstance().isFullScreen() || showCursor == TriBool::False) 261 269 state->setMouseExclusive(TriBool::True); 262 270 else 263 state->setMouseExclusive(TriBool:: Dontcare);264 265 if (show Mouse== TriBool::True)271 state->setMouseExclusive(TriBool::False); 272 273 if (showCursor == TriBool::True) 266 274 state->setMouseHandler(this); 267 else if (show Mouse== TriBool::False)275 else if (showCursor == TriBool::False) 268 276 state->setMouseHandler(&InputHandler::EMPTY); 269 277 -
code/branches/gamestates2/src/libraries/core/GUIManager.h
r6595 r6662 81 81 void setBackground(const std::string& name); 82 82 83 const std::string& createInputState(const std::string& name, TriBool::Value show Mouse= TriBool::True, TriBool::Value useKeyboard = TriBool::True, bool bBlockJoyStick = false); // tolua_export83 const std::string& createInputState(const std::string& name, TriBool::Value showCursor = TriBool::True, TriBool::Value useKeyboard = TriBool::True, bool bBlockJoyStick = false); // tolua_export 84 84 85 85 void setCamera(Ogre::Camera* camera); -
code/branches/gamestates2/src/libraries/core/LuaState.cc
r6417 r6662 37 37 38 38 #include "util/Debug.h" 39 #include "util/Exception.h" 40 #include "util/ScopeGuard.h" 41 #include "IOConsole.h" 39 42 #include "Resource.h" 40 43 #include "ToluaBindCore.h" … … 54 57 // Create new lua state and configure it 55 58 luaState_ = lua_open(); 59 Loki::ScopeGuard luaStateGuard = Loki::MakeGuard(&lua_close, luaState_); 56 60 #if LUA_VERSION_NUM == 501 57 61 luaL_openlibs(luaState_); … … 78 82 79 83 // Parse init script 80 this->doFile("LuaStateInit.lua"); 84 if (!this->doFile("LuaStateInit.lua")) 85 ThrowException(InitialisationFailed, "Running LuaStateInit.lua failed"); 86 87 luaStateGuard.Dismiss(); 81 88 } 82 89 … … 96 103 } 97 104 98 voidLuaState::includeFile(const std::string& filename)105 bool LuaState::includeFile(const std::string& filename) 99 106 { 100 107 shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename); 101 108 if (sourceInfo != NULL) 102 this->includeString(Resource::open(sourceInfo)->getAsString(), sourceInfo); 103 else 104 COUT(2) << "LuaState: Cannot include file '" << filename << "'." << std::endl; 105 } 106 107 void LuaState::includeString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo) 109 return this->includeString(Resource::open(sourceInfo)->getAsString(), sourceInfo); 110 else 111 { 112 COUT(2) << "LuaState: Cannot include file '" << filename << "' (not found)." << std::endl; 113 return false; 114 } 115 } 116 117 bool LuaState::includeString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo) 108 118 { 109 119 // Parse string with provided include parser (otherwise don't preparse at all) … … 114 124 luaInput = code; 115 125 116 this->doString(luaInput, sourceFileInfo); 117 } 118 119 void LuaState::doFile(const std::string& filename) 126 if (sourceFileInfo != NULL) 127 { 128 // Also fill a map with the actual source code. This is just for the include* commands 129 // where the content of sourceFileInfo->filename doesn't match 'code' 130 this->sourceCodeMap_[sourceFileInfo->filename] = code; 131 } 132 133 bool returnValue = this->doString(luaInput, sourceFileInfo); 134 135 if (sourceFileInfo != NULL) 136 { 137 // Delete source code entry 138 if (sourceFileInfo != NULL) 139 this->sourceCodeMap_.erase(sourceFileInfo->filename); 140 } 141 142 return returnValue; 143 } 144 145 bool LuaState::doFile(const std::string& filename) 120 146 { 121 147 shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename); 122 148 if (sourceInfo != NULL) 123 this->doString(Resource::open(sourceInfo)->getAsString(), sourceInfo); 124 else 125 COUT(2) << "LuaState: Cannot do file '" << filename << "'." << std::endl; 126 } 127 128 void LuaState::doString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo) 149 return this->doString(Resource::open(sourceInfo)->getAsString(), sourceInfo); 150 else 151 { 152 COUT(2) << "LuaState: Cannot do file '" << filename << "' (not found)." << std::endl; 153 return false; 154 } 155 } 156 157 bool LuaState::doString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo) 129 158 { 130 159 // Save the old source file info … … 134 163 sourceFileInfo_ = sourceFileInfo; 135 164 136 int error = 0; 165 std::string chunkname; 166 if (sourceFileInfo != NULL) 167 { 168 // Provide lua_load with the filename for debug purposes 169 // The '@' is a Lua convention to identify the chunk name as filename 170 chunkname = '@' + sourceFileInfo->filename; 171 } 172 else 173 { 174 // Use the code string to identify the chunk 175 chunkname = code; 176 } 177 178 // Push custom error handler that uses the debugger 179 int errorHandler = 1; 180 lua_getglobal(this->luaState_, "errorHandler"); 181 if (lua_isnil(this->luaState_, -1)) 182 { 183 lua_pop(this->luaState_, 1); 184 errorHandler = 0; 185 } 186 137 187 #if LUA_VERSION_NUM != 501 138 188 LoadS ls; 139 189 ls.s = code.c_str(); 140 190 ls.size = code.size(); 141 error = lua_load(luaState_, &orxonox::LuaState::lua_Chunkreader, &ls, code.c_str());191 int error = lua_load(luaState_, &orxonox::LuaState::lua_Chunkreader, &ls, chunkname.c_str()); 142 192 #else 143 error = luaL_loadstring(luaState_, code.c_str());193 int error = luaL_loadbuffer(luaState_, code.c_str(), code.size(), chunkname.c_str()); 144 194 #endif 145 195 146 // execute the chunk 196 switch (error) 197 { 198 case LUA_ERRSYNTAX: // Syntax error 199 COUT(1) << "Lua syntax error: " << lua_tostring(luaState_, -1) << std::endl; 200 break; 201 case LUA_ERRMEM: // Memory allocation error 202 COUT(1) << "Lua memory allocation error: Consult your dentist immediately!" << std::endl; 203 lua_pop(luaState_, 1); 204 break; 205 } 206 147 207 if (error == 0) 148 error = lua_pcall(luaState_, 0, 1, 0); 208 { 209 // Execute the chunk in protected mode with an error handler function (stack index) 210 error = lua_pcall(luaState_, 0, 1, errorHandler); 211 212 switch (error) 213 { 214 case LUA_ERRRUN: // Runtime error 215 // Remove error string from stack (we already display the error in the 216 // 'errorHandler' Lua function in LuaStateInit.lua) 217 lua_pop(luaState_, 1); 218 break; 219 case LUA_ERRERR: // Error in the error handler 220 COUT(1) << "Lua error in error handler: " << lua_tostring(luaState_, -1) << std::endl; 221 break; 222 case LUA_ERRMEM: // Memory allocation error 223 COUT(1) << "Lua memory allocation error: Consult your dentist immediately!" << std::endl; 224 lua_pop(luaState_, 1); 225 break; 226 } 227 } 228 149 229 if (error != 0) 150 230 { 151 std::string origin; 152 if (sourceFileInfo != NULL) 153 origin = " originating from " + sourceFileInfo_->filename; 154 COUT(1) << "Error in Lua-script" << origin << ": " << lua_tostring(luaState_, -1) << std::endl; 155 // return value is nil 231 // Push a nil return value 156 232 lua_pushnil(luaState_); 157 233 } 158 // push return value because it will get lost since the return value of this function is void 234 235 // Set return value to a global variable because we cannot return a table in this function 236 // here. It would work for numbers, pointers and strings, but certainly not for Lua tables. 159 237 lua_setglobal(luaState_, "LuaStateReturnValue"); 160 238 161 239 // Load the old info again 162 240 sourceFileInfo_ = oldSourceFileInfo; 241 242 return (error == 0); 163 243 } 164 244 … … 180 260 else 181 261 return true; 262 } 263 264 //! Returns the content of a file 265 std::string LuaState::getSourceCode(const std::string& filename) 266 { 267 // Try the internal map first to get the actual Lua code 268 // and not just some pseudo Lua-XML code when using include* commands 269 std::map<std::string, std::string>::const_iterator it = this->sourceCodeMap_.find(filename); 270 if (it != this->sourceCodeMap_.end()) 271 return it->second; 272 shared_ptr<ResourceInfo> info = Resource::getInfo(filename); 273 if (info == NULL) 274 return ""; 275 else 276 return Resource::open(info)->getAsString(); 277 } 278 279 bool LuaState::usingIOConsole() const 280 { 281 return IOConsole::exists(); 182 282 } 183 283 -
code/branches/gamestates2/src/libraries/core/LuaState.h
r6595 r6662 71 71 ~LuaState(); 72 72 73 voiddoFile(const std::string& filename); // tolua_export74 voiddoString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo = shared_ptr<ResourceInfo>());73 bool doFile(const std::string& filename); // tolua_export 74 bool doString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo = shared_ptr<ResourceInfo>()); 75 75 76 voidincludeFile(const std::string& filename); // tolua_export77 voidincludeString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo = shared_ptr<ResourceInfo>());76 bool includeFile(const std::string& filename); // tolua_export 77 bool includeString(const std::string& code, const shared_ptr<ResourceInfo>& sourceFileInfo = shared_ptr<ResourceInfo>()); 78 78 79 79 void luaPrint(const std::string& str); // tolua_export 80 80 void luaLog(unsigned int level, const std::string& message); // tolua_export 81 81 bool fileExists(const std::string& filename); // tolua_export 82 std::string getSourceCode(const std::string& filename); // tolua_export 82 83 83 84 const std::stringstream& getOutput() const { return output_; } … … 91 92 92 93 Functor* createLuaFunctor(const std::string& code) { return new LuaFunctor(code, this); } // tolua_export 94 //! Tells about whether IOConsole was activated. The Lua debugger only works with a normal console. 95 bool usingIOConsole() const; // tolua_export 93 96 94 97 static bool addToluaInterface(int (*function)(lua_State*), const std::string& name); … … 114 117 bool bIsRunning_; 115 118 shared_ptr<ResourceInfo> sourceFileInfo_; 119 std::map<std::string, std::string> sourceCodeMap_; 116 120 std::string (*includeParseFunction_)(const std::string&); 117 121 -
code/branches/gamestates2/src/libraries/core/Resource.cc
r6501 r6662 29 29 #include "Resource.h" 30 30 31 #include <boost/filesystem/path.hpp> 31 32 #include <OgreException.h> 33 #include <OgreFileSystem.h> 32 34 #include <OgreResourceGroupManager.h> 33 35 … … 89 91 ptr->group = group; 90 92 ptr->size = it->uncompressedSize; 93 if (dynamic_cast<Ogre::FileSystemArchive*>(it->archive) != NULL) 94 { 95 boost::filesystem::path base(it->archive->getName()); 96 base /= it->filename; 97 ptr->fileSystemPath = base.string(); 98 } 91 99 return ptr; 92 100 } -
code/branches/gamestates2/src/libraries/core/Resource.h
r6417 r6662 57 57 //! Uncompressed size 58 58 size_t size; 59 //! Absolute file path ("" for files not on filesystem) 60 std::string fileSystemPath; 59 61 }; 60 62 -
code/branches/gamestates2/src/libraries/core/input/InputDevice.h
r6417 r6662 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/gamestates2/src/libraries/core/input/InputHandler.h
r6105 r6662 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/gamestates2/src/libraries/core/input/InputManager.cc
r6595 r6662 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/gamestates2/src/libraries/core/input/InputManager.h
r6595 r6662 36 36 #include <string> 37 37 #include <vector> 38 #include <boost/function.hpp> 38 39 39 40 #include "util/Singleton.h" 40 41 #include "util/TriBool.h" 41 42 #include "core/WindowEventListener.h" 42 #include "InputState.h"43 43 44 44 // tolua_begin … … 76 76 Nothing = 0x00, 77 77 Bad = 0x02, 78 Ticking = 0x04, 79 Calibrating = 0x08, 80 ReloadRequest = 0x10, 78 Calibrating = 0x04, 81 79 }; 82 80 … … 170 168 //! Returns a pointer to the OIS InputManager. Only you if you know what you're doing! 171 169 OIS::InputManager* getOISInputManager() { return this->oisInputManager_; } 170 //! Returns the position of the cursor as std::pair of ints 172 171 std::pair<int, int> getMousePosition() const; 172 //! Tells whether the mouse is used exclusively to the game 173 bool isMouseExclusive() const { return this->exclusiveMouse_; } // tolua_export 174 175 //------------------------------- 176 // Function call caching 177 //------------------------------- 178 void pushCall(const boost::function<void ()>& function) 179 { this->callBuffer_.push_back(function); } 173 180 174 181 static InputManager& getInstance() { return Singleton<InputManager>::getInstance(); } // tolua_export … … 208 215 std::vector<InputState*> activeStatesTicked_; //!< Like activeStates_, but only contains the ones that currently receive events 209 216 210 std::set<InputState*> stateEnterRequests_; //!< Requests to enter a new state 211 std::set<InputState*> stateLeaveRequests_; //!< Requests to leave a running state 212 std::set<InputState*> stateDestroyRequests_; //!< Requests to destroy a state 217 std::vector<boost::function<void ()> > callBuffer_; //!< Caches all calls from InputStates to be executed afterwards (see preUpdate) 213 218 214 219 static InputManager* singletonPtr_s; //!< Pointer reference to the singleton -
code/branches/gamestates2/src/libraries/core/input/InputPrereqs.h
r6417 r6662 42 42 #include <ois/OISMouse.h> 43 43 #include <ois/OISJoyStick.h> 44 #include "util/OrxEnum.h" 44 45 45 46 namespace orxonox … … 448 449 }; 449 450 } 451 452 //! Enumeration wrapper for input state priorities 453 struct InputStatePriority : OrxEnum<InputStatePriority> 454 { 455 OrxEnumConstructors(InputStatePriority); 456 457 static const int Empty = -1; 458 static const int Dynamic = 0; 459 460 static const int HighPriority = 1000; 461 static const int Console = HighPriority + 0; 462 static const int Calibrator = HighPriority + 1; 463 static const int Detector = HighPriority + 2; 464 }; 450 465 } 451 466 -
code/branches/gamestates2/src/libraries/core/input/InputState.h
r6595 r6662 35 35 #include <string> 36 36 #include <vector> 37 38 #include "util/OrxEnum.h" 37 #include <boost/function.hpp> 38 #include <boost/bind.hpp> 39 39 40 #include "util/TriBool.h" 40 41 #include "InputHandler.h" 42 #include "InputManager.h" 41 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__))) 42 47 43 48 namespace orxonox 44 49 { 45 //! Enumeration wrapper for input state priorities46 struct InputStatePriority : OrxEnum<InputStatePriority>47 {48 OrxEnumConstructors(InputStatePriority);49 50 static const int Empty = -1;51 static const int Dynamic = 0;52 53 static const int HighPriority = 1000;54 static const int Console = HighPriority + 0;55 static const int Calibrator = HighPriority + 1;56 static const int Detector = HighPriority + 2;57 };58 59 60 50 /** 61 51 @brief … … 144 134 145 135 //! Generic function that distributes all 9 button events 146 template <typename EventType, class Traits>147 void buttonEvent(unsigned int device, const typename Traits::ButtonTypeParam button);136 template <typename EventType, class ButtonTypeParam> 137 void buttonEvent(unsigned int device, ButtonTypeParam button); 148 138 149 139 //! Event handler … … 190 180 for (unsigned int i = 0; i < handlers_.size(); ++i) 191 181 if (handlers_[i] != NULL) 192 handlers_[i]->allDevicesUpdated(dt);182 INPUT_STATE_PUSH_CALL(i, allDevicesUpdated, dt); 193 183 } 194 184 … … 199 189 case InputDeviceEnumerator::Keyboard: 200 190 if (handlers_[keyboardIndex_s] != NULL) 201 handlers_[keyboardIndex_s]->keyboardUpdated(dt);191 INPUT_STATE_PUSH_CALL(keyboardIndex_s, keyboardUpdated, dt); 202 192 break; 203 193 204 194 case InputDeviceEnumerator::Mouse: 205 195 if (handlers_[mouseIndex_s] != NULL) 206 handlers_[mouseIndex_s]->mouseUpdated(dt);196 INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseUpdated, dt); 207 197 break; 208 198 209 199 default: // joy sticks 210 200 if (handlers_[device] != NULL) 211 handlers_[device]->joyStickUpdated(device - firstJoyStickIndex_s, dt);201 INPUT_STATE_PUSH_CALL(device, joyStickUpdated, device - firstJoyStickIndex_s, dt); 212 202 break; 213 203 } 214 204 } 215 205 216 template <typename EventType, class Traits>217 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) 218 208 { 219 209 assert(device < handlers_.size()); 220 210 if (handlers_[device] != NULL) 221 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 } 222 216 } 223 217 … … 225 219 { 226 220 if (handlers_[mouseIndex_s] != NULL) 227 handlers_[mouseIndex_s]->mouseMoved(abs, rel, clippingSize);221 INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseMoved, abs, rel, clippingSize); 228 222 } 229 223 … … 231 225 { 232 226 if (handlers_[mouseIndex_s] != NULL) 233 handlers_[mouseIndex_s]->mouseScrolled(abs, rel);227 INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseScrolled, abs, rel); 234 228 } 235 229 … … 238 232 assert(device < handlers_.size()); 239 233 if (handlers_[device] != NULL) 240 handlers_[device]->axisMoved(device - firstJoyStickIndex_s, axis, value);234 INPUT_STATE_PUSH_CALL(device, axisMoved, device - firstJoyStickIndex_s, axis, value); 241 235 } 242 236 } -
code/branches/gamestates2/src/libraries/util/Singleton.h
r6536 r6662 49 49 public: 50 50 //! Returns a reference to the singleton instance 51 static T& getInstance()51 FORCEINLINE static T& getInstance() 52 52 { 53 53 assert(T::singletonPtr_s != NULL); … … 56 56 57 57 //! Tells whether the singleton has been created 58 static bool exists()58 FORCEINLINE static bool exists() 59 59 { 60 60 return (T::singletonPtr_s != NULL); … … 62 62 63 63 //! Update method called by ClassSingletonManager (if used) 64 void preUpdateSingleton(const Clock& time) { static_cast<T*>(T::singletonPtr_s)->preUpdate(time); }64 FORCEINLINE void preUpdateSingleton(const Clock& time) { static_cast<T*>(T::singletonPtr_s)->preUpdate(time); } 65 65 //! Empty update method for the static polymorphism 66 void preUpdate(const Clock& time) { }66 FORCEINLINE void preUpdate(const Clock& time) { } 67 67 //! Update method called by ClassSingletonManager (if used) 68 void postUpdateSingleton(const Clock& time) { static_cast<T*>(T::singletonPtr_s)->postUpdate(time); }68 FORCEINLINE void postUpdateSingleton(const Clock& time) { static_cast<T*>(T::singletonPtr_s)->postUpdate(time); } 69 69 //! Empty update method for the static polymorphism 70 void postUpdate(const Clock& time) { }70 FORCEINLINE void postUpdate(const Clock& time) { } 71 71 72 72 protected:
Note: See TracChangeset
for help on using the changeset viewer.