- Timestamp:
- Nov 2, 2008, 12:09:55 AM (16 years ago)
- Location:
- code/branches/objecthierarchy
- Files:
-
- 2 added
- 29 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/objecthierarchy/bin/def_keybindings.ini
r2042 r2101 25 25 KeyEscape="exit" 26 26 KeyF="scale -1 moveUpDown" 27 KeyF1= "OverlayGroup toggleVisibility Debug"27 KeyF1= 28 28 KeyF10= 29 29 KeyF11= … … 41 41 KeyF9= 42 42 KeyG=greet 43 KeyGrave= "openConsole"43 KeyGrave= 44 44 KeyH= 45 45 KeyHome= -
code/branches/objecthierarchy/init/common/def_keybindings.ini
r2013 r2101 10 10 KeyBack= 11 11 KeyBackslash= 12 KeyC= 12 KeyC=switchCamera 13 13 KeyCalculator= 14 14 KeyCapsLock= … … 25 25 KeyEscape="exit" 26 26 KeyF="scale -1 moveUpDown" 27 KeyF1= "OverlayGroup toggleVisibility Debug"27 KeyF1= 28 28 KeyF10= 29 29 KeyF11= … … 41 41 KeyF9= 42 42 KeyG=greet 43 KeyGrave= "openConsole"43 KeyGrave= 44 44 KeyH= 45 45 KeyHome= -
code/branches/objecthierarchy/src/audio/AudioBuffer.cc
r1784 r2101 31 31 namespace audio 32 32 { 33 AudioBuffer::AudioBuffer(std::string file Name)33 AudioBuffer::AudioBuffer(std::string filename) 34 34 { 35 35 // Load wav data into buffers. … … 40 40 41 41 //FIXME deprecated; seems unneeded 42 // alutLoadWAVFile((ALbyte*)file Name.c_str(), &format, &data, &size, &freq, &loop);42 // alutLoadWAVFile((ALbyte*)filename.c_str(), &format, &data, &size, &freq, &loop); 43 43 alBufferData(buffer, format, data, size, freq); 44 44 //FIXME deprecated; seems unneeded -
code/branches/objecthierarchy/src/audio/AudioBuffer.h
r1784 r2101 40 40 { 41 41 public: 42 AudioBuffer(std::string file Name);42 AudioBuffer(std::string filename); 43 43 ~AudioBuffer(); 44 44 -
code/branches/objecthierarchy/src/core/CommandLine.cc
r2003 r2101 30 30 31 31 #include "util/String.h" 32 #include "util/SubString.h" 32 33 33 34 namespace orxonox 34 35 { 36 SetCommandLineArgument(optionsFile, "start.ini").shortcut("o"); 37 35 38 /** 36 39 @brief … … 274 277 } 275 278 } 279 280 /** 281 @brief 282 Parses both command line and start.ini for CommandLineArguments. 283 */ 284 void CommandLine::_parseAll(int argc, char** argv) 285 { 286 // parse command line first 287 std::vector<std::string> args; 288 for (int i = 1; i < argc; ++i) 289 args.push_back(argv[i]); 290 this->_parse(args); 291 292 // look for additional arguments in given file or start.ini as default 293 // They will not overwrite the arguments given directly 294 std::ifstream file; 295 std::string filename = CommandLine::getValue("optionsFile").getString(); 296 file.open(filename.c_str()); 297 args.clear(); 298 if (file) 299 { 300 while (!file.eof()) 301 { 302 std::string line; 303 std::getline(file, line); 304 line = removeTrailingWhitespaces(line); 305 //if (!(line[0] == '#' || line[0] == '%')) 306 //{ 307 SubString tokens(line, " ", " ", false, 92, false, 34, false, 40, 41, false, '#'); 308 for (unsigned i = 0; i < tokens.size(); ++i) 309 if (tokens[i][0] != '#') 310 args.push_back(tokens[i]); 311 //args.insert(args.end(), tokens.getAllStrings().begin(), tokens.getAllStrings().end()); 312 //} 313 } 314 file.close(); 315 } 316 else 317 { 318 COUT(2) << "Warning: Could not find " << filename 319 << " to get additional command line arguments." << std::endl; 320 } 321 322 try 323 { 324 _parse(args); 325 } 326 catch (orxonox::ArgumentException& ex) 327 { 328 COUT(1) << "An Exception occured while parsing " << filename << std::endl; 329 throw(ex); 330 } 331 } 276 332 } -
code/branches/objecthierarchy/src/core/CommandLine.h
r2005 r2101 38 38 39 39 #define SetCommandLineArgument(name, defaultValue) \ 40 CommandLineArgument& CmdArgumentDummyBoolVar##name \40 orxonox::CommandLineArgument& CmdArgumentDummyBoolVar##name \ 41 41 = orxonox::CommandLine::addArgument(#name, defaultValue) 42 42 #define SetCommandLineSwitch(name) \ 43 CommandLineArgument& CmdArgumentDummyBoolVar##name \43 orxonox::CommandLineArgument& CmdArgumentDummyBoolVar##name \ 44 44 = orxonox::CommandLine::addArgument(#name, false) 45 45 … … 135 135 136 136 //! Parse redirection to internal member method. 137 static void parse (const std::vector<std::string>& arguments) { _getInstance()._parse(arguments); }137 static void parseAll(int argc, char** argv) { _getInstance()._parseAll(argc, argv); } 138 138 139 139 static std::string getUsageInformation(); … … 165 165 static CommandLine& _getInstance(); 166 166 167 void _parseAll(int argc, char** argv); 167 168 void _parse(const std::vector<std::string>& arguments); 168 169 void checkFullArgument(const std::string& name, const std::string& value); -
code/branches/objecthierarchy/src/core/ConfigFileManager.cc
r1889 r2101 28 28 29 29 #include "ConfigFileManager.h" 30 #include "ConfigValueContainer.h" 31 #include "ConsoleCommand.h" 32 #include "Identifier.h" 30 31 #include <cassert> 33 32 #include "util/Convert.h" 34 33 #include "util/String.h" 35 34 #include "ConsoleCommand.h" 35 #include "ConfigValueContainer.h" 36 36 37 37 namespace orxonox … … 39 39 const int CONFIG_FILE_MAX_LINELENGHT = 1024; 40 40 const char* const DEFAULT_CONFIG_FILE = "default.ini"; 41 42 ConfigFileManager* ConfigFileManager::singletonRef_s = 0; 41 43 42 44 SetConsoleCommandShortcutExtern(config).argumentCompleter(0, autocompletion::configvalueclasses()).argumentCompleter(1, autocompletion::configvalues()).argumentCompleter(2, autocompletion::configvalue()); … … 45 47 SetConsoleCommandShortcutExtern(cleanConfig); 46 48 SetConsoleCommandShortcutExtern(loadSettings).argumentCompleter(0, autocompletion::files()); 47 SetConsoleCommandShortcutExtern(loadKeybindings).argumentCompleter(0, autocompletion::files());48 49 49 50 bool config(const std::string& classname, const std::string& varname, const std::string& value) … … 83 84 void loadSettings(const std::string& filename) 84 85 { 85 ConfigFileManager::getInstance().setFile(CFT_Settings, filename, false); 86 } 87 88 void loadKeybindings(const std::string& filename) 89 { 90 ConfigFileManager::getInstance().setFile(CFT_Keybindings, filename); 91 } 92 86 ConfigFileManager::getInstance().setFilename(ConfigFileType::Settings, filename); 87 } 93 88 94 89 ////////////////////////// … … 121 116 122 117 123 /////////////////////////////// 118 //////////////////////////////// 124 119 // ConfigFileEntryVectorValue // 125 /////////////////////////////// 120 //////////////////////////////// 126 121 std::string ConfigFileEntryVectorValue::getFileEntry() const 127 122 { … … 217 212 ConfigFile::~ConfigFile() 218 213 { 219 for (std::list<ConfigFileSection*>::iterator it = this->sections_.begin(); it != this->sections_.end(); ) 220 delete (*(it++)); 214 this->clear(); 221 215 } 222 216 223 217 void ConfigFile::load(bool bCreateIfNotExisting) 224 218 { 225 if (bCreateIfNotExisting)226 {227 // This creates the default config file if it's not existing 228 std::ofstream createFile;229 createFile.open(this->filename_.c_str(), std::fstream::app);230 createFile.close();231 }219 // Be sure we start from new 220 this->clear(); 221 222 // This creates the config file if it's not existing 223 std::ofstream createFile; 224 createFile.open(this->filename_.c_str(), std::fstream::app); 225 createFile.close(); 232 226 233 227 // Open the file … … 329 323 file.close(); 330 324 331 COUT( 0) << "Loaded config file \"" << this->filename_ << "\"." << std::endl;325 COUT(3) << "Loaded config file \"" << this->filename_ << "\"." << std::endl; 332 326 333 327 // Save the file in case something changed (like stripped whitespaces) 334 328 this->save(); 329 330 // Update all ConfigValueContainers 331 this->updateConfigValues(); 335 332 } 336 333 … … 366 363 } 367 364 368 void ConfigFile::save (const std::string& filename)365 void ConfigFile::saveAs(const std::string& filename) 369 366 { 370 367 std::string temp = this->filename_; … … 415 412 } 416 413 414 void ConfigFile::clear() 415 { 416 for (std::list<ConfigFileSection*>::iterator it = this->sections_.begin(); it != this->sections_.end(); ) 417 delete (*(it++)); 418 this->sections_.clear(); 419 } 420 417 421 ConfigFileSection* ConfigFile::getSection(const std::string& section) 418 422 { … … 446 450 } 447 451 452 void ConfigFile::updateConfigValues() 453 { 454 if (this->type_ == ConfigFileType::Settings) 455 { 456 for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getIdentifierMapBegin(); it != Identifier::getIdentifierMapEnd(); ++it) 457 { 458 if (it->second->hasConfigValues()) 459 { 460 for (std::map<std::string, ConfigValueContainer*>::const_iterator it2 = (*it).second->getConfigValueMapBegin(); it2 != (*it).second->getConfigValueMapEnd(); ++it2) 461 it2->second->update(); 462 463 it->second->updateConfigValues(); 464 } 465 } 466 } 467 } 468 448 469 449 470 /////////////////////// 450 471 // ConfigFileManager // 451 472 /////////////////////// 473 452 474 ConfigFileManager::ConfigFileManager() 453 { 454 this->setFile(CFT_Settings, DEFAULT_CONFIG_FILE); 475 : mininmalFreeType_(ConfigFileType::numberOfReservedTypes) 476 { 477 assert(singletonRef_s == 0); 478 singletonRef_s = this; 455 479 } 456 480 … … 458 482 { 459 483 for(std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.begin(); it != this->configFiles_.end(); ) 460 delete (*(it++)).second; 461 } 462 463 ConfigFileManager& ConfigFileManager::getInstance() 464 { 465 static ConfigFileManager instance; 466 return instance; 467 } 468 469 void ConfigFileManager::setFile(ConfigFileType type, const std::string& filename, bool bCreateIfNotExisting) 484 delete (it++)->second; 485 486 assert(singletonRef_s != 0); 487 singletonRef_s = 0; 488 } 489 490 void ConfigFileManager::setFilename(ConfigFileType type, const std::string& filename) 470 491 { 471 492 std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.find(type); 472 493 if (it != this->configFiles_.end()) 473 if ((*it).second != 0) 474 delete (*it).second; 475 476 this->configFiles_[type] = new ConfigFile(this->getFilePath(filename)); 477 this->load(type, bCreateIfNotExisting); 478 } 479 480 void ConfigFileManager::load(bool bCreateIfNotExisting) 494 { 495 assert(it->second); 496 delete it->second; 497 } 498 this->configFiles_[type] = new ConfigFile(filename, type); 499 this->load(type); 500 } 501 502 void ConfigFileManager::load() 481 503 { 482 504 for(std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.begin(); it != this->configFiles_.end(); ++it) 483 (*it).second->load(bCreateIfNotExisting); 484 485 this->updateConfigValues(); 505 it->second->load(); 486 506 } 487 507 … … 489 509 { 490 510 for(std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.begin(); it != this->configFiles_.end(); ++it) 491 (*it).second->save();511 it->second->save(); 492 512 } 493 513 … … 495 515 { 496 516 for(std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.begin(); it != this->configFiles_.end(); ++it) 497 this->clean((*it).first, bCleanComments); 498 } 499 500 void ConfigFileManager::load(ConfigFileType type, bool bCreateIfNotExisting) 501 { 502 this->getFile(type)->load(bCreateIfNotExisting); 503 this->updateConfigValues(type); 517 this->clean(it->first, bCleanComments); 518 } 519 520 void ConfigFileManager::load(ConfigFileType type) 521 { 522 this->getFile(type)->load(); 504 523 } 505 524 … … 509 528 } 510 529 511 void ConfigFileManager::save (ConfigFileType type, const std::string& filename)512 { 513 this->getFile(type)->save (filename);530 void ConfigFileManager::saveAs(ConfigFileType type, const std::string& saveFilename) 531 { 532 this->getFile(type)->saveAs(saveFilename); 514 533 } 515 534 … … 519 538 } 520 539 521 void ConfigFileManager::updateConfigValues() const540 void ConfigFileManager::updateConfigValues() 522 541 { 523 542 for(std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.begin(); it != this->configFiles_.end(); ++it) 524 this->updateConfigValues((*it).first); 525 } 526 527 void ConfigFileManager::updateConfigValues(ConfigFileType type) const 528 { 529 if (type == CFT_Settings) 530 { 531 for (std::map<std::string, Identifier*>::const_iterator it = Identifier::getIdentifierMapBegin(); it != Identifier::getIdentifierMapEnd(); ++it) 532 { 533 if ((*it).second->hasConfigValues() /* && (*it).second != ClassIdentifier<KeyBinder>::getIdentifier()*/) 534 { 535 for (std::map<std::string, ConfigValueContainer*>::const_iterator it2 = (*it).second->getConfigValueMapBegin(); it2 != (*it).second->getConfigValueMapEnd(); ++it2) 536 (*it2).second->update(); 537 538 (*it).second->updateConfigValues(); 539 } 540 } 541 } 542 else if (type == CFT_Keybindings) 543 { 544 // todo 545 } 543 it->second->updateConfigValues(); 544 } 545 546 void ConfigFileManager::updateConfigValues(ConfigFileType type) 547 { 548 this->getFile(type)->updateConfigValues(); 549 } 550 551 const std::string& ConfigFileManager::getFilename(ConfigFileType type) 552 { 553 std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.find(type); 554 if (it != this->configFiles_.end()) 555 return it->second->getFilename(); 556 else 557 return BLANKSTRING; 546 558 } 547 559 548 560 ConfigFile* ConfigFileManager::getFile(ConfigFileType type) 549 561 { 550 std::map<ConfigFileType, ConfigFile*>:: iterator it = this->configFiles_.find(type);562 std::map<ConfigFileType, ConfigFile*>::const_iterator it = this->configFiles_.find(type); 551 563 if (it != this->configFiles_.end()) 552 return (*it).second; 553 554 if (type == CFT_Settings) 555 return this->configFiles_[type] = new ConfigFile(DEFAULT_CONFIG_FILE); 556 else 557 return this->configFiles_[type] = new ConfigFile(""); 558 } 559 560 std::string ConfigFileManager::getFilePath(const std::string& name) const 561 { 562 return name; 564 return it->second; 565 else 566 { 567 COUT(1) << "ConfigFileManager: Can't find a config file for type with ID " << (int)type << std::endl; 568 COUT(1) << "Using " << DEFAULT_CONFIG_FILE << " file." << std::endl; 569 this->setFilename(type, DEFAULT_CONFIG_FILE); 570 return getFile(type); 571 } 563 572 } 564 573 } -
code/branches/objecthierarchy/src/core/ConfigFileManager.h
r1887 r2101 41 41 namespace orxonox 42 42 { 43 enum _CoreExport ConfigFileType 44 { 45 CFT_Settings, 46 CFT_Keybindings, 47 CFT_JoyStickCalibration 48 }; 49 43 // Use unsigned int as config file type to have an arbitrary number of files 44 class ConfigFileType 45 { 46 public: 47 ConfigFileType() { } 48 ConfigFileType(unsigned int type) { type_ = type; } 49 ConfigFileType(const ConfigFileType& instance) { type_ = instance.type_; } 50 51 operator unsigned int() { return type_; } 52 ConfigFileType& operator =(unsigned int type) { type_ = type; return *this; } 53 bool operator <(const ConfigFileType& right) const { return (type_ < right.type_); } 54 55 /* *** Put the different config file types here *** */ 56 static const unsigned int NoType = 0; 57 static const unsigned int Settings = 1; 58 static const unsigned int JoyStickCalibration = 2; 59 60 static const unsigned int numberOfReservedTypes = 1024; 61 62 private: 63 unsigned int type_; 64 }; 50 65 51 66 bool config(const std::string& classname, const std::string& varname, const std::string& value); … … 55 70 void cleanConfig(); 56 71 void loadSettings(const std::string& filename); 57 void loadKeybindings(const std::string& filename);58 72 59 73 … … 218 232 { 219 233 public: 220 inline ConfigFile(const std::string& filename) : filename_(filename), bUpdated_(false) {} 234 inline ConfigFile(const std::string& filename, ConfigFileType type) 235 : filename_(filename) 236 , type_(type) 237 , bUpdated_(false) 238 { } 221 239 ~ConfigFile(); 222 240 223 241 void load(bool bCreateIfNotExisting = true); 224 242 void save() const; 225 void save (const std::string& filename);243 void saveAs(const std::string& filename); 226 244 void clean(bool bCleanComments = false); 245 void clear(); 246 247 const std::string& getFilename() { return this->filename_; } 227 248 228 249 inline void setValue(const std::string& section, const std::string& name, const std::string& value, bool bString) … … 241 262 { return this->getSection(section)->getVectorSize(name); } 242 263 264 void updateConfigValues(); 265 243 266 private: 244 267 ConfigFileSection* getSection(const std::string& section); … … 246 269 247 270 std::string filename_; 271 ConfigFileType type_; 248 272 std::list<ConfigFileSection*> sections_; 249 273 bool bUpdated_; … … 257 281 { 258 282 public: 259 static ConfigFileManager& getInstance(); 260 261 void setFile(ConfigFileType type, const std::string& filename, bool bCreateIfNotExisting = true); 262 263 void load(bool bCreateIfNotExisting = true); 283 ConfigFileManager(); 284 ~ConfigFileManager(); 285 286 void load(); 264 287 void save(); 265 288 void clean(bool bCleanComments = false); 266 289 267 void load(ConfigFileType type, bool bCreateIfNotExisting = true); 290 void setFilename(ConfigFileType type, const std::string& filename); 291 const std::string& getFilename(ConfigFileType type); 292 293 ConfigFileType getNewConfigFileType() { return mininmalFreeType_++; } 294 295 void load(ConfigFileType type); 268 296 void save(ConfigFileType type); 269 void save (ConfigFileType type, const std::string& filename);297 void saveAs(ConfigFileType type, const std::string& saveFilename); 270 298 void clean(ConfigFileType type, bool bCleanComments = false); 271 299 … … 285 313 { return this->getFile(type)->getVectorSize(section, name); } 286 314 287 void updateConfigValues() const;288 void updateConfigValues(ConfigFileType type) const;289 290 private:291 ConfigFileManager(); 292 ConfigFileManager(const ConfigFileManager& other);293 ~ConfigFileManager();315 void updateConfigValues(); 316 void updateConfigValues(ConfigFileType type); 317 318 static ConfigFileManager& getInstance() { assert(singletonRef_s); return *singletonRef_s; } 319 320 private: 321 ConfigFileManager(const ConfigFileManager&); 294 322 295 323 ConfigFile* getFile(ConfigFileType type); 296 324 297 std::string getFilePath(const std::string& name) const;298 299 325 std::map<ConfigFileType, ConfigFile*> configFiles_; 326 unsigned int mininmalFreeType_; 327 328 static ConfigFileManager* singletonRef_s; 300 329 }; 301 330 } -
code/branches/objecthierarchy/src/core/ConfigValueIncludes.h
r1887 r2101 52 52 if (!container##varname) \ 53 53 { \ 54 container##varname = new orxonox::ConfigValueContainer(C FT_Settings, identifier##varname, identifier##varname->getName(), #varname, defvalue, varname); \54 container##varname = new orxonox::ConfigValueContainer(ConfigFileType::Settings, identifier##varname, identifier##varname->getName(), #varname, defvalue, varname); \ 55 55 identifier##varname->addConfigValueContainer(#varname, container##varname); \ 56 56 } \ 57 57 container##varname->getValue(&varname, this) 58 58 59 #define SetConfigValue(varname, defvalue) SetConfigValueGeneric(CFT_Settings, varname, defvalue) 60 #define SetKeybindingValue(varname, defvalue) SetConfigValueGeneric(CFT_Keybindings, varname, defvalue) 59 #define SetConfigValue(varname, defvalue) SetConfigValueGeneric(ConfigFileType::Settings, varname, defvalue) 61 60 62 61 … … 71 70 if (!container##varname) \ 72 71 { \ 73 container##varname = new orxonox::ConfigValueContainer(C FT_Settings, identifier##varname, identifier##varname->getName(), #varname, defvalue); \72 container##varname = new orxonox::ConfigValueContainer(ConfigFileType::Settings, identifier##varname, identifier##varname->getName(), #varname, defvalue); \ 74 73 identifier##varname->addConfigValueContainer(#varname, container##varname); \ 75 74 } \ 76 75 container##varname->getValue(&varname, this) 77 76 78 #define SetConfigValueVector(varname, defvalue) SetConfigValueVectorGeneric(CFT_Settings, varname, defvalue) 79 #define SetKeybindingValueVector(varname, defvalue) SetConfigValueVectorGeneric(CFT_Keybindings, varname, defvalue) 77 #define SetConfigValueVector(varname, defvalue) SetConfigValueVectorGeneric(ConfigFileType::Settings, varname, defvalue) 80 78 81 79 -
code/branches/objecthierarchy/src/core/CoreIncludes.h
r2084 r2101 135 135 #define RegisterConstructionCallback(ThisClassName, TargetClassName, FunctionName) \ 136 136 orxonox::ClassIdentifier<TargetClassName>::getIdentifier()->addConstructionCallback( \ 137 createFunctor(&ThisClassName::FunctionName)->setObject(this))137 orxonox::createFunctor(&ThisClassName::FunctionName)->setObject(this)) 138 138 139 139 #endif /* _CoreIncludes_H__ */ -
code/branches/objecthierarchy/src/core/Identifier.h
r2086 r2101 485 485 You can only assign an Identifier that belongs to a class T (or derived) to a SubclassIdentifier<T>. 486 486 If you assign something else, the program aborts. 487 Because we know the minim altype, a dynamic_cast is done, which makes it easier to create a new object.487 Because we know the minimum type, a dynamic_cast is done, which makes it easier to create a new object. 488 488 */ 489 489 template <class T> -
code/branches/objecthierarchy/src/core/Language.cc
r1747 r2101 137 137 } 138 138 139 COUT(2) << "Warning: Language entry " << label << " is duplicate in " << getFile Name(this->defaultLanguage_) << "!" << std::endl;139 COUT(2) << "Warning: Language entry " << label << " is duplicate in " << getFilename(this->defaultLanguage_) << "!" << std::endl; 140 140 return it->second; 141 141 } … … 194 194 @return The filename 195 195 */ 196 const std::string Language::getFile Name(const std::string& language)196 const std::string Language::getFilename(const std::string& language) 197 197 { 198 198 return std::string("translation_" + language + ".lang"); … … 208 208 // This creates the file if it's not existing 209 209 std::ofstream createFile; 210 createFile.open(getFile Name(this->defaultLanguage_).c_str(), std::fstream::app);210 createFile.open(getFilename(this->defaultLanguage_).c_str(), std::fstream::app); 211 211 createFile.close(); 212 212 213 213 // Open the file 214 214 std::ifstream file; 215 file.open(getFile Name(this->defaultLanguage_).c_str(), std::fstream::in);215 file.open(getFilename(this->defaultLanguage_).c_str(), std::fstream::in); 216 216 217 217 if (!file.is_open()) 218 218 { 219 219 COUT(1) << "An error occurred in Language.cc:" << std::endl; 220 COUT(1) << "Error: Couldn't open file " << getFile Name(this->defaultLanguage_) << " to read the default language entries!" << std::endl;220 COUT(1) << "Error: Couldn't open file " << getFilename(this->defaultLanguage_) << " to read the default language entries!" << std::endl; 221 221 return; 222 222 } … … 240 240 else 241 241 { 242 COUT(2) << "Warning: Invalid language entry \"" << lineString << "\" in " << getFile Name(this->defaultLanguage_) << std::endl;242 COUT(2) << "Warning: Invalid language entry \"" << lineString << "\" in " << getFilename(this->defaultLanguage_) << std::endl; 243 243 } 244 244 } … … 257 257 // Open the file 258 258 std::ifstream file; 259 file.open(getFile Name(Core::getLanguage()).c_str(), std::fstream::in);259 file.open(getFilename(Core::getLanguage()).c_str(), std::fstream::in); 260 260 261 261 if (!file.is_open()) 262 262 { 263 263 COUT(1) << "An error occurred in Language.cc:" << std::endl; 264 COUT(1) << "Error: Couldn't open file " << getFile Name(Core::getLanguage()) << " to read the translated language entries!" << std::endl;264 COUT(1) << "Error: Couldn't open file " << getFilename(Core::getLanguage()) << " to read the translated language entries!" << std::endl; 265 265 Core::resetLanguage(); 266 266 COUT(3) << "Info: Reset language to " << this->defaultLanguage_ << "." << std::endl; … … 294 294 else 295 295 { 296 COUT(2) << "Warning: Invalid language entry \"" << lineString << "\" in " << getFile Name(Core::getLanguage()) << std::endl;296 COUT(2) << "Warning: Invalid language entry \"" << lineString << "\" in " << getFilename(Core::getLanguage()) << std::endl; 297 297 } 298 298 } … … 311 311 // Open the file 312 312 std::ofstream file; 313 file.open(getFile Name(this->defaultLanguage_).c_str(), std::fstream::out);313 file.open(getFilename(this->defaultLanguage_).c_str(), std::fstream::out); 314 314 315 315 if (!file.is_open()) 316 316 { 317 317 COUT(1) << "An error occurred in Language.cc:" << std::endl; 318 COUT(1) << "Error: Couldn't open file " << getFile Name(this->defaultLanguage_) << " to write the default language entries!" << std::endl;318 COUT(1) << "Error: Couldn't open file " << getFilename(this->defaultLanguage_) << " to write the default language entries!" << std::endl; 319 319 return; 320 320 } -
code/branches/objecthierarchy/src/core/Language.h
r1747 r2101 128 128 void readTranslatedLanguageFile(); 129 129 void writeDefaultLanguageFile() const; 130 static const std::string getFile Name(const std::string& language);130 static const std::string getFilename(const std::string& language); 131 131 LanguageEntry* createEntry(const LanguageEntryLabel& label, const std::string& entry); 132 132 -
code/branches/objecthierarchy/src/core/RootGameState.cc
r2003 r2101 29 29 #include "RootGameState.h" 30 30 31 #include "util/String.h"32 #include "util/SubString.h"33 31 #include "util/Debug.h" 34 32 #include "util/Exception.h" … … 130 128 State to start with (usually main menu or specified by command line) 131 129 */ 132 void RootGameState::start( int argc, char** argv)130 void RootGameState::start() 133 131 { 134 132 #ifdef NDEBUG … … 141 139 // create the Core settings to configure the output level 142 140 Core::getInstance(); 143 144 parseArguments(argc, argv);145 141 146 142 this->activate(); … … 168 164 COUT(1) << ex.what() << std::endl; 169 165 COUT(1) << "Program aborted." << std::endl; 170 abort();171 166 } 172 167 // anything that doesn't inherit from std::exception … … 174 169 { 175 170 COUT(1) << "An unidentifiable exception has occured. Program aborted." << std::endl; 176 abort();177 171 } 178 172 #endif 179 173 } 180 181 /**182 @brief183 Parses both command line and start.ini for CommandLineArguments.184 */185 void RootGameState::parseArguments(int argc, char** argv)186 {187 // parse command line first188 std::vector<std::string> args;189 for (int i = 1; i < argc; ++i)190 args.push_back(argv[i]);191 192 try193 {194 orxonox::CommandLine::parse(args);195 }196 catch (orxonox::ArgumentException& ex)197 {198 COUT(1) << ex.what() << std::endl;199 COUT(0) << "Usage:" << std::endl << "orxonox " << CommandLine::getUsageInformation() << std::endl;200 }201 202 // look for additional arguments in start.ini203 std::ifstream file;204 file.open("start.ini");205 args.clear();206 if (file)207 {208 while (!file.eof())209 {210 std::string line;211 std::getline(file, line);212 line = removeTrailingWhitespaces(line);213 //if (!(line[0] == '#' || line[0] == '%'))214 //{215 SubString tokens(line, " ", " ", false, 92, false, 34, false, 40, 41, false, '#');216 for (unsigned i = 0; i < tokens.size(); ++i)217 if (tokens[i][0] != '#')218 args.push_back(tokens[i]);219 //args.insert(args.end(), tokens.getAllStrings().begin(), tokens.getAllStrings().end());220 //}221 }222 file.close();223 }224 225 try226 {227 orxonox::CommandLine::parse(args);228 }229 catch (orxonox::ArgumentException& ex)230 {231 COUT(1) << "An Exception occured while parsing start.ini" << std::endl;232 COUT(1) << ex.what() << std::endl;233 COUT(0) << "Usage:" << std::endl << "orxonox " << CommandLine::getUsageInformation() << std::endl;234 }235 }236 174 } -
code/branches/objecthierarchy/src/core/RootGameState.h
r1755 r2101 42 42 43 43 void requestState(const std::string& name); 44 void start( int argc, char** argv);44 void start(); 45 45 46 46 private: 47 47 void makeTransition(GameStateBase* source, GameStateBase* destination); 48 48 void gotoState(const std::string& name); 49 50 void parseArguments(int argc, char** argv);51 49 52 50 std::string stateRequest_; -
code/branches/objecthierarchy/src/core/input/Button.cc
r2001 r2101 82 82 } 83 83 84 void Button::readConfigValue( )84 void Button::readConfigValue(ConfigFileType configFile) 85 85 { 86 86 // create/get ConfigValueContainer 87 87 if (!configContainer_) 88 88 { 89 configContainer_ = new ConfigValueContainer( CFT_Keybindings, 0, groupName_, name_, "", name_);89 configContainer_ = new ConfigValueContainer(configFile, 0, groupName_, name_, "", name_); 90 90 configContainer_->callback(this, &Button::parse); 91 91 } -
code/branches/objecthierarchy/src/core/input/Button.h
r1887 r2101 41 41 #include <vector> 42 42 #include "InputCommands.h" 43 #include "core/ConfigFileManager.h" 43 44 44 45 namespace orxonox … … 52 53 virtual bool addParamCommand(ParamCommand* command) { return false; } 53 54 void parse(); 54 void readConfigValue( );55 void readConfigValue(ConfigFileType configFile); 55 56 bool execute(KeybindMode::Enum mode, float abs = 1.0f, float rel = 1.0f); 56 57 -
code/branches/objecthierarchy/src/core/input/InputManager.cc
r1887 r2101 395 395 if (!cont) 396 396 { 397 cont = new ConfigValueContainer(C FT_Settings, getIdentifier(), getIdentifier()->getName(), "CoeffPos", coeffPos);397 cont = new ConfigValueContainer(ConfigFileType::Settings, getIdentifier(), getIdentifier()->getName(), "CoeffPos", coeffPos); 398 398 getIdentifier()->addConfigValueContainer("CoeffPos", cont); 399 399 } … … 403 403 if (!cont) 404 404 { 405 cont = new ConfigValueContainer(C FT_Settings, getIdentifier(), getIdentifier()->getName(), "CoeffNeg", coeffNeg);405 cont = new ConfigValueContainer(ConfigFileType::Settings, getIdentifier(), getIdentifier()->getName(), "CoeffNeg", coeffNeg); 406 406 getIdentifier()->addConfigValueContainer("CoeffNeg", cont); 407 407 } … … 411 411 if (!cont) 412 412 { 413 cont = new ConfigValueContainer(C FT_Settings, getIdentifier(), getIdentifier()->getName(), "Zero", zero);413 cont = new ConfigValueContainer(ConfigFileType::Settings, getIdentifier(), getIdentifier()->getName(), "Zero", zero); 414 414 getIdentifier()->addConfigValueContainer("Zero", cont); 415 415 } -
code/branches/objecthierarchy/src/core/input/KeyBinder.cc
r2004 r2101 106 106 } 107 107 108 // Get a new ConfigFileType from the ConfigFileManager 109 this->configFile_ = ConfigFileManager::getInstance().getNewConfigFileType(); 110 108 111 // initialise joy sticks separatly to allow for reloading 109 112 numberOfJoySticks_ = InputManager::getInstance().numberOfJoySticks(); … … 133 136 void KeyBinder::setConfigValues() 134 137 { 135 SetConfigValue(defaultKeybindings_, "def_keybindings.ini")136 .description("Filename of default keybindings.");137 138 SetConfigValue(analogThreshold_, 0.05f) 138 139 .description("Threshold for analog axes until which the state is 0."); … … 173 174 174 175 // load the bindings if required 175 if ( !configFile_.empty())176 if (configFile_ != ConfigFileType::NoType) 176 177 { 177 178 for (unsigned int iDev = oldValue; iDev < numberOfJoySticks_; ++iDev) 178 179 { 179 180 for (unsigned int i = 0; i < JoyStickButtonCode::numberOfButtons; ++i) 180 joyStickButtons_[iDev][i].readConfigValue( );181 joyStickButtons_[iDev][i].readConfigValue(this->configFile_); 181 182 for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; ++i) 182 joyStickAxes_[iDev][i].readConfigValue( );183 joyStickAxes_[iDev][i].readConfigValue(this->configFile_); 183 184 } 184 185 } … … 250 251 True if loading succeeded. 251 252 */ 252 void KeyBinder::loadBindings(const std::string& filename )253 void KeyBinder::loadBindings(const std::string& filename, const std::string& defaultFilename) 253 254 { 254 255 COUT(3) << "KeyBinder: Loading key bindings..." << std::endl; 255 256 256 configFile_ = filename; 257 if (configFile_.empty()) 257 if (filename.empty()) 258 258 return; 259 259 260 260 // get bindings from default file if filename doesn't exist. 261 261 std::ifstream infile; 262 infile.open( configFile_.c_str());262 infile.open(filename.c_str()); 263 263 if (!infile) 264 264 { 265 ConfigFileManager::getInstance().setFile (CFT_Keybindings, defaultKeybindings_);266 ConfigFileManager::getInstance().save (CFT_Keybindings, configFile_);265 ConfigFileManager::getInstance().setFilename(this->configFile_, defaultFilename); 266 ConfigFileManager::getInstance().saveAs(this->configFile_, filename); 267 267 } 268 268 else 269 269 infile.close(); 270 ConfigFileManager::getInstance().setFile (CFT_Keybindings, configFile_);270 ConfigFileManager::getInstance().setFilename(this->configFile_, filename); 271 271 272 272 // Parse bindings and create the ConfigValueContainers if necessary 273 273 clearBindings(); 274 274 for (std::map<std::string, Button*>::const_iterator it = allButtons_.begin(); it != allButtons_.end(); ++it) 275 it->second->readConfigValue( );275 it->second->readConfigValue(this->configFile_); 276 276 277 277 COUT(3) << "KeyBinder: Loading key bindings done." << std::endl; -
code/branches/objecthierarchy/src/core/input/KeyBinder.h
r2001 r2101 44 44 #include "InputCommands.h" 45 45 #include "JoyStickDeviceNumberListener.h" 46 #include "core/ConfigFileManager.h" 46 47 47 48 namespace orxonox … … 59 60 virtual ~KeyBinder(); 60 61 61 void loadBindings(const std::string& filename );62 void loadBindings(const std::string& filename, const std::string& defaultFilename); 62 63 void clearBindings(); 63 64 bool setBinding(const std::string& binding, const std::string& name, bool bTemporary = false); … … 142 143 float deriveTime_; 143 144 144 //! Config file used. ""in case of KeyDetector. Also indicates whether we've already loaded.145 std::stringconfigFile_;145 //! Config file used. ConfigFileType::NoType in case of KeyDetector. Also indicates whether we've already loaded. 146 ConfigFileType configFile_; 146 147 147 148 private: 148 149 //##### ConfigValues ##### 149 //! Filename of default keybindings.150 std::string defaultKeybindings_;151 150 //! Whether to filter small value analog input 152 151 bool bFilterAnalogNoise_; -
code/branches/objecthierarchy/src/orxonox/Main.cc
r2030 r2101 42 42 #include "util/SignalHandler.h" 43 43 #include "core/ConfigFileManager.h" 44 #include "core/CommandLine.h" 44 45 45 46 #include "gamestates/GSRoot.h" … … 51 52 #include "gamestates/GSGUI.h" 52 53 #include "gamestates/GSIOConsole.h" 53 54 using namespace orxonox;55 54 56 55 #if ORXONOX_PLATFORM == ORXONOX_PLATFORM_APPLE … … 86 85 //#endif 87 86 87 SetCommandLineArgument(settingsFile, "orxonox.ini"); 88 88 89 int main(int argc, char** argv) 89 90 { 91 using namespace orxonox; 92 90 93 // create a signal handler (only works for linux) 91 94 SignalHandler::getInstance()->doCatch(argv[0], "orxonox.log"); 92 95 93 // Specifiy config file before creating the GameStates in order to have 96 // Parse command line arguments 97 try 98 { 99 CommandLine::parseAll(argc, argv); 100 } 101 catch (ArgumentException& ex) 102 { 103 COUT(1) << ex.what() << std::endl; 104 COUT(0) << "Usage:" << std::endl << "orxonox " << CommandLine::getUsageInformation() << std::endl; 105 } 106 107 // Create the ConfigFileManager before creating the GameStates in order to have 94 108 // setConfigValues() in the constructor (required). 95 ConfigFileManager::getInstance().setFile(CFT_Settings, "orxonox.ini"); 109 ConfigFileManager* configFileManager = new ConfigFileManager(); 110 configFileManager->setFilename(ConfigFileType::Settings, CommandLine::getValue("settingsFile").getString()); 96 111 97 112 // create the gamestates … … 115 130 116 131 // Here happens the game 117 root.start(argc, argv); 132 root.start(); 133 134 // Destroy ConfigFileManager again. 135 delete configFileManager; 118 136 119 137 return 0; -
code/branches/objecthierarchy/src/orxonox/gamestates/GSGraphics.cc
r2084 r2101 93 93 void GSGraphics::setConfigValues() 94 94 { 95 SetConfigValue(resourceFile_, "resources.cfg").description("Location of the resources file in the data path."); 96 SetConfigValue(ogreConfigFile_, "ogre.cfg").description("Location of the Ogre config file"); 97 SetConfigValue(ogrePluginsFile_, "plugins.cfg").description("Location of the Ogre plugins file"); 98 SetConfigValue(ogreLogFile_, "ogre.log").description("Logfile for messages from Ogre. \ 99 Use \"\" to suppress log file creation."); 100 SetConfigValue(ogreLogLevelTrivial_ , 5).description("Corresponding orxonox debug level for ogre Trivial"); 101 SetConfigValue(ogreLogLevelNormal_ , 4).description("Corresponding orxonox debug level for ogre Normal"); 102 SetConfigValue(ogreLogLevelCritical_, 2).description("Corresponding orxonox debug level for ogre Critical"); 103 SetConfigValue(statisticsRefreshCycle_, 200000).description("Sets the time in microseconds interval at \ 104 which average fps, etc. get updated."); 95 SetConfigValue(resourceFile_, "resources.cfg") 96 .description("Location of the resources file in the data path."); 97 SetConfigValue(ogreConfigFile_, "ogre.cfg") 98 .description("Location of the Ogre config file"); 99 SetConfigValue(ogrePluginsFile_, "plugins.cfg") 100 .description("Location of the Ogre plugins file"); 101 SetConfigValue(ogreLogFile_, "ogre.log") 102 .description("Logfile for messages from Ogre. Use \"\" to suppress log file creation."); 103 SetConfigValue(ogreLogLevelTrivial_ , 5) 104 .description("Corresponding orxonox debug level for ogre Trivial"); 105 SetConfigValue(ogreLogLevelNormal_ , 4) 106 .description("Corresponding orxonox debug level for ogre Normal"); 107 SetConfigValue(ogreLogLevelCritical_, 2) 108 .description("Corresponding orxonox debug level for ogre Critical"); 109 SetConfigValue(statisticsRefreshCycle_, 200000) 110 .description("Sets the time in microseconds interval at which average fps, etc. get updated."); 111 SetConfigValue(defaultMasterKeybindings_, "def_masterKeybindings.ini") 112 .description("Filename of default master keybindings."); 105 113 } 106 114 … … 136 144 inputManager_->initialise(windowHnd, renderWindow_->getWidth(), renderWindow_->getHeight(), true); 137 145 // Configure master input state with a KeyBinder 138 //masterKeyBinder_ = new KeyBinder();139 //masterKeyBinder_->loadBindings("master_keybindings.ini");140 //inputManager_->getMasterInputState()->addKeyHandler(masterKeyBinder_);146 masterKeyBinder_ = new KeyBinder(); 147 masterKeyBinder_->loadBindings("masterKeybindings.ini", defaultMasterKeybindings_); 148 inputManager_->getMasterInputState()->addKeyHandler(masterKeyBinder_); 141 149 142 150 // Load the InGameConsole … … 172 180 173 181 //inputManager_->getMasterInputState()->removeKeyHandler(this->masterKeyBinder_); 174 //delete this->masterKeyBinder_;182 delete this->masterKeyBinder_; 175 183 delete this->inputManager_; 176 184 -
code/branches/objecthierarchy/src/orxonox/gamestates/GSGraphics.h
r2084 r2101 103 103 104 104 // config values 105 std::string resourceFile_; //!< resources file name 106 std::string ogreConfigFile_; //!< ogre config file name 107 std::string ogrePluginsFile_; //!< ogre plugins file name 108 std::string ogreLogFile_; //!< log file name for Ogre log messages 109 int ogreLogLevelTrivial_; //!< Corresponding Orxonx debug level for LL_TRIVIAL 110 int ogreLogLevelNormal_; //!< Corresponding Orxonx debug level for LL_NORMAL 111 int ogreLogLevelCritical_; //!< Corresponding Orxonx debug level for LL_CRITICAL 112 unsigned int detailLevelParticle_; //!< Detail level of particle effects (0: off, 1: low, 2: normal, 3: high) 105 std::string resourceFile_; //!< resources file name 106 std::string ogreConfigFile_; //!< ogre config file name 107 std::string ogrePluginsFile_; //!< ogre plugins file name 108 std::string ogreLogFile_; //!< log file name for Ogre log messages 109 int ogreLogLevelTrivial_; //!< Corresponding Orxonx debug level for LL_TRIVIAL 110 int ogreLogLevelNormal_; //!< Corresponding Orxonx debug level for LL_NORMAL 111 int ogreLogLevelCritical_; //!< Corresponding Orxonx debug level for LL_CRITICAL 112 unsigned int detailLevelParticle_; //!< Detail level of particle effects (0: off, 1: low, 2: normal, 3: high) 113 std::string defaultMasterKeybindings_; //!< Filename of default master keybindings. 113 114 }; 114 115 } -
code/branches/objecthierarchy/src/orxonox/gamestates/GSLevel.cc
r2084 r2101 71 71 { 72 72 SetConfigValue(keyDetectorCallbackCode_, "KeybindBindingStringKeyName="); 73 SetConfigValue(defaultKeybindings_, "def_keybindings.ini") 74 .description("Filename of default keybindings."); 73 75 } 74 76 … … 79 81 inputState_ = InputManager::getInstance().createInputState<SimpleInputState>("game", 20); 80 82 keyBinder_ = new KeyBinder(); 81 keyBinder_->loadBindings("keybindings.ini" );83 keyBinder_->loadBindings("keybindings.ini", defaultKeybindings_); 82 84 inputState_->setHandler(keyBinder_); 83 85 -
code/branches/objecthierarchy/src/orxonox/gamestates/GSLevel.h
r2073 r2101 71 71 LevelManager* levelManager_; 72 72 73 // config values73 //##### ConfigValues ##### 74 74 std::string keyDetectorCallbackCode_; 75 //! Filename of default keybindings. 76 std::string defaultKeybindings_; 75 77 76 78 private: -
code/branches/objecthierarchy/src/util/Exception.cc
r1810 r2101 38 38 { 39 39 Exception::Exception(const std::string& description, int lineNumber, 40 const char* file Name, const char* functionName)40 const char* filename, const char* functionName) 41 41 : description_(description) 42 42 , lineNumber_(lineNumber) 43 43 , functionName_(functionName) 44 , file Name_(fileName)44 , filename_(filename) 45 45 { } 46 46 … … 49 49 , lineNumber_(0) 50 50 , functionName_("") 51 , file Name_("")51 , filename_("") 52 52 { } 53 53 … … 60 60 fullDesc << this->getTypeName() << "_EXCEPTION"; 61 61 62 if (this->file Name_ != "")62 if (this->filename_ != "") 63 63 { 64 fullDesc << " in " << this->file Name_;64 fullDesc << " in " << this->filename_; 65 65 if (this->lineNumber_) 66 66 fullDesc << "(" << this->lineNumber_ << ")"; -
code/branches/objecthierarchy/src/util/Exception.h
r1810 r2101 67 67 68 68 Exception(const std::string& description, int lineNumber, 69 const char* file Name, const char* functionName);69 const char* filename, const char* functionName); 70 70 Exception(const std::string& description); 71 71 … … 87 87 int lineNumber_; 88 88 std::string functionName_; 89 std::string file Name_;89 std::string filename_; 90 90 // mutable because "what()" is a const method 91 91 mutable std::string fullDescription_; … … 98 98 public: 99 99 SpecificException(const std::string& description, int lineNumber, 100 const char* file Name, const char* functionName)101 : Exception(description, lineNumber, file Name, functionName)100 const char* filename, const char* functionName) 101 : Exception(description, lineNumber, filename, functionName) 102 102 { 103 103 // let the catcher decide whether to display the message below level 4 -
code/branches/objecthierarchy/src/util/SignalHandler.cc
r2030 r2101 58 58 * register signal handlers for SIGSEGV and SIGABRT 59 59 * @param appName path to executable eg argv[0] 60 * @param file Name filename to append backtrace to61 */ 62 void SignalHandler::doCatch( const std::string & appName, const std::string & file Name )60 * @param filename filename to append backtrace to 61 */ 62 void SignalHandler::doCatch( const std::string & appName, const std::string & filename ) 63 63 { 64 64 this->appName = appName; 65 this->file Name = fileName;65 this->filename = filename; 66 66 67 67 // prepare for restoring XAutoKeyRepeat … … 326 326 bt.insert(0, timeString); 327 327 328 FILE * f = fopen( getInstance()->file Name.c_str(), "a" );328 FILE * f = fopen( getInstance()->filename.c_str(), "a" ); 329 329 330 330 if ( !f ) 331 331 { 332 perror( ( std::string( "could not append to " ) + getInstance()->file Name ).c_str() );332 perror( ( std::string( "could not append to " ) + getInstance()->filename ).c_str() ); 333 333 exit(EXIT_FAILURE); 334 334 } … … 336 336 if ( fwrite( bt.c_str(), 1, bt.length(), f ) != bt.length() ) 337 337 { 338 COUT(0) << "could not write " << bt.length() << " byte to " << getInstance()->file Name << std::endl;338 COUT(0) << "could not write " << bt.length() << " byte to " << getInstance()->filename << std::endl; 339 339 exit(EXIT_FAILURE); 340 340 } -
code/branches/objecthierarchy/src/util/SignalHandler.h
r2030 r2101 71 71 void registerCallback( SignalCallback cb, void * someData ); 72 72 73 void doCatch( const std::string & appName, const std::string & file Name );73 void doCatch( const std::string & appName, const std::string & filename ); 74 74 void dontCatch(); 75 75 … … 85 85 86 86 std::string appName; 87 std::string file Name;87 std::string filename; 88 88 89 89 // used to turn on KeyAutoRepeat if OIS crashes … … 97 97 public: 98 98 inline static SignalHandler* getInstance() { if (!SignalHandler::singletonRef) SignalHandler::singletonRef = new SignalHandler(); return SignalHandler::singletonRef; }; 99 void doCatch( const std::string & appName, const std::string & file Name ) {};99 void doCatch( const std::string & appName, const std::string & filename ) {}; 100 100 void dontCatch() {}; 101 101 void registerCallback( SignalCallback cb, void * someData ) {};
Note: See TracChangeset
for help on using the changeset viewer.