- Timestamp:
- Mar 30, 2010, 12:13:33 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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();
Note: See TracChangeset
for help on using the changeset viewer.