diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 08b05f417e..5503a7c1a8 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -12,12 +12,22 @@ MwIniImporter::MwIniImporter() { const char *map[][2] = { { "fps", "General:Show FPS" }, + { "nosound", "General:Disable Audio" }, { 0, 0 } }; + const char *fallback[] = { + "Weather:Sunrise Time", + "Weather:Sunset Time", + 0 + }; for(int i=0; map[i][0]; i++) { mMergeMap.insert(std::make_pair(map[i][0], map[i][1])); } + + for(int i=0; fallback[i]; i++) { + mMergeFallback.push_back(fallback[i]); + } } void MwIniImporter::setVerbose(bool verbose) { @@ -116,16 +126,38 @@ void MwIniImporter::merge(multistrmap &cfg, multistrmap &ini) { multistrmap::iterator iniIt; for(strmap::iterator it=mMergeMap.begin(); it!=mMergeMap.end(); it++) { if((iniIt = ini.find(it->second)) != ini.end()) { - cfg.erase(it->first); - if(!this->specialMerge(it->first, it->second, cfg, ini)) { - cfg.insert(std::make_pair >(it->first, iniIt->second)); + for(std::vector::iterator vc = iniIt->second.begin(); vc != iniIt->second.end(); vc++) { + cfg.erase(it->first); + insertMultistrmap(cfg, it->first, *vc); } } } } -bool MwIniImporter::specialMerge(std::string cfgKey, std::string iniKey, multistrmap &cfg, multistrmap &ini) { - return false; +void MwIniImporter::mergeFallback(multistrmap &cfg, multistrmap &ini) { + cfg.erase("fallback"); + + multistrmap::iterator cfgIt; + multistrmap::iterator iniIt; + for(std::vector::iterator it=mMergeFallback.begin(); it!=mMergeFallback.end(); it++) { + if((iniIt = ini.find(*it)) != ini.end()) { + for(std::vector::iterator vc = iniIt->second.begin(); vc != iniIt->second.end(); vc++) { + std::string value(*it); + std::replace( value.begin(), value.end(), ' ', '_' ); + std::replace( value.begin(), value.end(), ':', '_' ); + value.append(",").append(vc->substr(0,vc->length()-1)); + insertMultistrmap(cfg, "fallback", value); + } + } + } +}; + +void MwIniImporter::insertMultistrmap(multistrmap &cfg, std::string key, std::string value) { + multistrmap::iterator it = cfg.find(key); + if(it == cfg.end()) { + cfg.insert(std::make_pair >(key, std::vector() )); + } + cfg[key].push_back(value); } void MwIniImporter::importGameFiles(multistrmap &cfg, multistrmap &ini) { diff --git a/apps/mwiniimporter/importer.hpp b/apps/mwiniimporter/importer.hpp index 988f10255e..ced332a72d 100644 --- a/apps/mwiniimporter/importer.hpp +++ b/apps/mwiniimporter/importer.hpp @@ -18,14 +18,16 @@ class MwIniImporter { multistrmap loadIniFile(std::string filename); multistrmap loadCfgFile(std::string filename); void merge(multistrmap &cfg, multistrmap &ini); + void mergeFallback(multistrmap &cfg, multistrmap &ini); void importGameFiles(multistrmap &cfg, multistrmap &ini); void writeToFile(boost::iostreams::stream &out, multistrmap &cfg); private: - bool specialMerge(std::string cfgKey, std::string iniKey, multistrmap &cfg, multistrmap &ini); + void insertMultistrmap(multistrmap &cfg, std::string key, std::string value); std::string numberToString(int n); bool mVerbose; strmap mMergeMap; + std::vector mMergeFallback; }; diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index 9a6e61645d..234d7d57d4 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -9,7 +9,8 @@ namespace bpo = boost::program_options; int main(int argc, char *argv[]) { - bpo::options_description desc("Syntax: mwiniimporter \nAllowed options"); + bpo::options_description desc("Syntax: mwiniimporter inifile configfile\nAllowed options"); + bpo::positional_options_description p_desc; desc.add_options() ("help,h", "produce help message") ("verbose,v", "verbose output") @@ -18,28 +19,22 @@ int main(int argc, char *argv[]) { ("output,o", bpo::value()->default_value(""), "openmw.cfg file") ("game-files,g", "import esm and esp files") ; + p_desc.add("ini", 1).add("cfg", 1); bpo::variables_map vm; - try { - bpo::store(boost::program_options::parse_command_line(argc, argv, desc), vm); + bpo::parsed_options parsed = bpo::command_line_parser(argc, argv) + .options(desc) + .positional(p_desc) + .run(); + + bpo::store(parsed, vm); - // parse help before calling notify because we dont want it to throw an error if help is set - if(vm.count("help")) { - std::cout << desc; - return 0; - } + if(vm.count("help") || !vm.count("ini") || !vm.count("cfg")) { + std::cout << desc; + return 0; + } - bpo::notify(vm); - - } - catch(std::exception& e) { - std::cerr << "Error:" << e.what() << std::endl; - return -1; - } - catch(...) { - std::cerr << "Error" << std::endl; - return -2; - } + bpo::notify(vm); std::string iniFile = vm["ini"].as(); std::string cfgFile = vm["cfg"].as(); @@ -58,21 +53,22 @@ int main(int argc, char *argv[]) { std::cerr << "cfg file does not exist" << std::endl; return -4; } - + MwIniImporter importer; importer.setVerbose(vm.count("verbose")); - boost::iostreams::stream file(outputFile); MwIniImporter::multistrmap ini = importer.loadIniFile(iniFile); MwIniImporter::multistrmap cfg = importer.loadCfgFile(cfgFile); importer.merge(cfg, ini); - + importer.mergeFallback(cfg, ini); + if(vm.count("game-files")) { importer.importGameFiles(cfg, ini); } std::cout << "write to: " << outputFile << std::endl; + boost::iostreams::stream file(outputFile); importer.writeToFile(file, cfg); return 0; diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index cfcf9f76b9..3d88fd1415 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -365,7 +365,7 @@ void OMW::Engine::go() // Create the world mEnvironment.mWorld = new MWWorld::World (*mOgre, mFileCollections, mMaster, - mResDir, mNewGame, mEnvironment, mEncoding); + mResDir, mNewGame, mEnvironment, mEncoding, mFallbackMap); // Create window manager - this manages all the MW-specific GUI windows MWScript::registerExtensions (mExtensions); @@ -535,3 +535,8 @@ void OMW::Engine::setEncoding(const std::string& encoding) { mEncoding = encoding; } + +void OMW::Engine::setFallbackValues(std::map fallbackMap) +{ + mFallbackMap = fallbackMap; +} diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 690430784b..6eae20cc0f 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -76,6 +76,7 @@ namespace OMW bool mReportFocus; float mFocusTDiff; std::string mFocusName; + std::map mFallbackMap; MWWorld::Environment mEnvironment; Compiler::Extensions mExtensions; @@ -163,6 +164,8 @@ namespace OMW void setAnimationVerbose(bool animverbose); + void setFallbackValues(std::map map); + private: Files::ConfigurationManager& mCfgMgr; }; diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index a5e5c99e6a..df52faab14 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -54,6 +54,41 @@ inline boost::filesystem::path lexical_cast mMap; +}; + +void validate(boost::any &v, std::vector const &tokens, FallbackMap*, int) +{ + if(v.empty()) + { + v = boost::any(FallbackMap()); + } + + FallbackMap *map = boost::any_cast(&v); + + std::map::iterator mapIt; + for(std::vector::const_iterator it=tokens.begin(); it != tokens.end(); it++) + { + int sep = it->find(","); + if(sep < 1 || sep == (int)it->length()-1) +#if (BOOST_VERSION < 104200) + throw boost::program_options::validation_error("invalid value"); +#else + throw boost::program_options::validation_error(boost::program_options::validation_error::invalid_option_value); +#endif + + std::string key(it->substr(0,sep)); + std::string value(it->substr(sep+1)); + + if((mapIt = map->mMap.find(key)) == map->mMap.end()) + { + map->mMap.insert(std::make_pair(key,value)); + } + } +} + + /** * \brief Parses application command line and calls \ref Cfg::ConfigurationManager * to parse configuration files. @@ -92,36 +127,40 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat ("plugin", bpo::value()->default_value(StringsVector(), "") ->multitoken(), "plugin file(s)") - ("anim-verbose", boost::program_options::value()->implicit_value(true) + ("anim-verbose", bpo::value()->implicit_value(true) ->default_value(false), "output animation indices files") - ("debug", boost::program_options::value()->implicit_value(true) + ("debug", bpo::value()->implicit_value(true) ->default_value(false), "debug mode") - ("nosound", boost::program_options::value()->implicit_value(true) + ("nosound", bpo::value()->implicit_value(true) ->default_value(false), "disable all sounds") - ("script-verbose", boost::program_options::value()->implicit_value(true) + ("script-verbose", bpo::value()->implicit_value(true) ->default_value(false), "verbose script output") - ("new-game", boost::program_options::value()->implicit_value(true) + ("new-game", bpo::value()->implicit_value(true) ->default_value(false), "activate char gen/new game mechanics") - ("script-all", boost::program_options::value()->implicit_value(true) + ("script-all", bpo::value()->implicit_value(true) ->default_value(false), "compile all scripts (excluding dialogue scripts) at startup") - ("fs-strict", boost::program_options::value()->implicit_value(true) + ("fs-strict", bpo::value()->implicit_value(true) ->default_value(false), "strict file system handling (no case folding)") - ( "encoding", boost::program_options::value()-> + ( "encoding", bpo::value()-> default_value("win1252"), "Character encoding used in OpenMW game messages:\n" "\n\twin1250 - Central and Eastern European such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian, Serbian (Latin script), Romanian and Albanian languages\n" "\n\twin1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages\n" "\n\twin1252 - Western European (Latin) alphabet, used by default") - ("report-focus", boost::program_options::value()->implicit_value(true) + ("report-focus", bpo::value()->implicit_value(true) ->default_value(false), "write name of focussed object to cout") + + ("fallback", bpo::value()->default_value(FallbackMap(), "") + ->multitoken()->composing(), "fallback values") + ; bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv) @@ -228,6 +267,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat engine.setCompileAll(variables["script-all"].as()); engine.setReportFocus(variables["report-focus"].as()); engine.setAnimationVerbose(variables["anim-verbose"].as()); + engine.setFallbackValues(variables["fallback"].as().mMap); return true; } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index a7252353dd..1c64039d4c 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -152,10 +152,30 @@ namespace MWWorld mRendering->skyDisable(); } + void World::setFallbackValues(std::map fallbackMap) + { + mFallback = fallbackMap; + } + + std::string World::getFallback(std::string key) + { + return getFallback(key, ""); + } + + std::string World::getFallback(std::string key, std::string def) + { + std::map::iterator it; + if((it = mFallback.find(key)) == mFallback.end()) + { + return def; + } + return it->second; + } + World::World (OEngine::Render::OgreRenderer& renderer, const Files::Collections& fileCollections, const std::string& master, const boost::filesystem::path& resDir, - bool newGame, Environment& environment, const std::string& encoding) + bool newGame, Environment& environment, const std::string& encoding, std::map fallbackMap) : mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), mSky (true), mEnvironment (environment), mNextDynamicRecord (0), mCells (mStore, mEsm, *this), mNumFacing(0) @@ -191,6 +211,8 @@ namespace MWWorld mWorldScene = new Scene(environment, this, *mRendering, mPhysics); + setFallbackValues(fallbackMap); + } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 92540f82b7..8dd370ad76 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -100,6 +100,7 @@ namespace MWWorld std::string mFaced1Name; std::string mFaced2Name; int mNumFacing; + std::map mFallback; int getDaysPerMonth (int month) const; @@ -110,7 +111,7 @@ namespace MWWorld World (OEngine::Render::OgreRenderer& renderer, const Files::Collections& fileCollections, const std::string& master, const boost::filesystem::path& resDir, bool newGame, - Environment& environment, const std::string& encoding); + Environment& environment, const std::string& encoding, std::map fallbackMap); ~World(); @@ -125,6 +126,12 @@ namespace MWWorld void adjustSky(); + void setFallbackValues(std::map fallbackMap); + + std::string getFallback(std::string key); + + std::string getFallback(std::string key, std::string def); + MWWorld::Player& getPlayer(); const ESMS::ESMStore& getStore() const;