From f32105a2ae41dce4c637772a60db3ef5771982d5 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 15 Jun 2010 19:04:52 +0200 Subject: [PATCH 1/7] added --master option; reimplemented file handling with boost::filesystem --- game/main.cpp | 104 +++++++++++++++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 40 deletions(-) diff --git a/game/main.cpp b/game/main.cpp index 5ebd093a4..58d894a66 100644 --- a/game/main.cpp +++ b/game/main.cpp @@ -3,7 +3,8 @@ #include #include -#include "boost/program_options.hpp" +#include +#include #include "esm_store/cell_store.hpp" #include "bsa/bsa_archive.hpp" @@ -16,65 +17,85 @@ using namespace std; -void maintest (std::string dataDir, const std::string& cellName) +void maintest (boost::filesystem::path dataDir, const std::string& cellName, + std::string master) { - assert (!dataDir.empty()); + assert (!dataDir.empty()); - if (dataDir[dataDir.size()-1]!='/' && dataDir[dataDir.size()-1]!='\\') - dataDir += "/"; + dataDir = boost::filesystem::system_complete (dataDir); - const char* esmFile = "Morrowind.esm"; - const char* bsaFile = "Morrowind.bsa"; + std::string masterName; // name without extension + + std::string::size_type sep = master.find_last_of ("."); + + if (sep==std::string::npos) + { + masterName = master; + master += ".esm"; + } + else + { + masterName = master.substr (0, sep); + } + + boost::filesystem::path masterPath (dataDir); + masterPath /= master; + + boost::filesystem::path bsa (dataDir); + bsa /= masterName + ".bsa"; - const char* plugCfg = "plugins.cfg"; + const char* plugCfg = "plugins.cfg"; - cout << "Hello, fellow traveler!\n"; + cout << "Hello, fellow traveler!\n"; - cout << "Your data directory for today is: " << dataDir << "\n"; + cout << "Your data directory for today is: " << dataDir << "\n"; - cout << "Initializing OGRE\n"; - Render::OgreRenderer ogre; - ogre.configure(!isFile("ogre.cfg"), plugCfg, false); + cout << "Initializing OGRE\n"; + Render::OgreRenderer ogre; + ogre.configure(!isFile("ogre.cfg"), plugCfg, false); - cout << "Adding " << bsaFile << endl; - addBSA(dataDir + bsaFile); + if (boost::filesystem::exists (bsa)) + { + cout << "Adding " << bsa.string() << endl; + addBSA(bsa.file_string()); + } - cout << "Loading ESM " << esmFile << "\n"; - ESM::ESMReader esm; - ESMS::ESMStore store; - ESMS::CellStore cell; + cout << "Loading ESM " << masterPath.string() << "\n"; + ESM::ESMReader esm; + ESMS::ESMStore store; + ESMS::CellStore cell; - // This parses the ESM file and loads a sample cell - esm.open(dataDir + esmFile); - store.load(esm); + // This parses the ESM file and loads a sample cell + esm.open(masterPath.file_string()); + store.load(esm); - cell.loadInt(cellName, store, esm); + cell.loadInt(cellName, store, esm); - // Create the window - ogre.createWindow("OpenMW"); + // Create the window + ogre.createWindow("OpenMW"); - cout << "\nSetting up cell rendering\n"; + cout << "\nSetting up cell rendering\n"; - // Sets up camera, scene manager etc - MWRender::MWScene scene(ogre); + // Sets up camera, scene manager etc + MWRender::MWScene scene(ogre); - // This connects the cell data with the rendering scene. - MWRender::InteriorCellRender rend(cell, scene); + // This connects the cell data with the rendering scene. + MWRender::InteriorCellRender rend(cell, scene); - // Load the cell and insert it into the renderer - rend.show(); + // Load the cell and insert it into the renderer + rend.show(); - cout << "Setting up input system\n"; + cout << "Setting up input system\n"; - // Sets up the input system - MWInput::MWInputManager input(ogre); + // Sets up the input system + MWInput::MWInputManager input(ogre); - cout << "\nStart! Press Q/ESC or close window to exit.\n"; + cout << "\nStart! Press Q/ESC or close window to exit.\n"; - // Start the main rendering loop - ogre.start(); + // Start the main rendering loop + ogre.start(); - cout << "\nThat's all for now!\n"; + cout << "\nThat's all for now!\n"; } int main(int argc, char**argv) @@ -90,6 +111,8 @@ int main(int argc, char**argv) "set data directory") ("start", boost::program_options::value()->default_value ("Beshara"), "set initial cell (only interior cells supported at the moment") + ("master", boost::program_options::value()->default_value ("Morrowind"), + "master file") ; boost::program_options::variables_map variables; @@ -110,7 +133,8 @@ int main(int argc, char**argv) } else { - maintest (variables["data"].as(), variables["start"].as()); + maintest (variables["data"].as(), variables["start"].as(), + variables["master"].as()); } } catch(exception &e) From 04037fb01af5c3e598131cf4f42dd8cfbfd8160b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 16 Jun 2010 12:13:21 +0200 Subject: [PATCH 2/7] first round of main refactoring; moving functionality out to a separate class --- CMakeLists.txt | 4 +- game/engine.cpp | 133 ++++++++++++++++++++++++++++++++++++++++++++++++ game/engine.hpp | 49 ++++++++++++++++++ game/main.cpp | 84 +++--------------------------- 4 files changed, 190 insertions(+), 80 deletions(-) create mode 100644 game/engine.cpp create mode 100644 game/engine.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f063e261..41fd6b77f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,8 +30,8 @@ set(OGRE_HEADER ogre/renderer.hpp) set(INPUT input/oismanager.cpp) set(INPUT_HEADER input/oismanager.hpp input/listener.hpp input/func_binder.hpp input/dispatch_map.hpp input/dispatcher.hpp) -set(GAME game/main.cpp) -set(GAME_HEADER game/mwinput/inputmanager.hpp) +set(GAME game/main.cpp game/engine.cpp) +set(GAME_HEADER game/mwinput/inputmanager.hpp game/engine.hpp) set(ESM_STORE esm_store/store.cpp esm_store/cell_store.cpp) set(ESM_STORE_HEADER esm_store/cell_store.hpp esm_store/reclists.hpp esm_store/store.hpp) diff --git a/game/engine.cpp b/game/engine.cpp new file mode 100644 index 000000000..4a1133114 --- /dev/null +++ b/game/engine.cpp @@ -0,0 +1,133 @@ +#include "engine.hpp" + +#include + +#include + +#include "esm_store/cell_store.hpp" +#include "bsa/bsa_archive.hpp" +#include "ogre/renderer.hpp" +#include "tools/fileops.hpp" + +#include "mwrender/interior.hpp" +#include "mwinput/inputmanager.hpp" + +OMW::Engine::Engine() {} + +// adjust name and load bsa + +void OMW::Engine::prepareMaster() +{ + assert (!mDataDir.empty()); + + std::string masterName; // name without extension + + std::string::size_type sep = mMaster.find_last_of ("."); + + if (sep==std::string::npos) + { + masterName = mMaster; + mMaster += ".esm"; + } + else + { + masterName = mMaster.substr (0, sep); + } + + // bsa + boost::filesystem::path bsa (mDataDir); + bsa /= masterName + ".bsa"; + + if (boost::filesystem::exists (bsa)) + { + std::cout << "Adding " << bsa.string() << std::endl; + addBSA(bsa.file_string()); + } +} + +// Set data dir + +void OMW::Engine::setDataDir (const boost::filesystem::path& dataDir) +{ + mDataDir = boost::filesystem::system_complete (dataDir); +} + +// Set start cell name (only interiors for now) + +void OMW::Engine::setCell (const std::string& cellName) +{ + mCellName = cellName; +} + +// Set master file (esm) +// - If the given name does not have an extension, ".esm" is added automatically +// - If there is a bsa file with the same name, OpenMW will load it. +// - Currently OpenMW only supports one master at the same time. + +void OMW::Engine::addMaster (const std::string& master) +{ + assert (mMaster.empty()); + mMaster = master; +} + +// Initialise and enter main loop. + +void OMW::Engine::go() +{ + assert (!mDataDir.empty()); + assert (!mCellName.empty()); + assert (!mMaster.empty()); + + std::cout << "Hello, fellow traveler!\n"; + + std::cout << "Your data directory for today is: " << mDataDir << "\n"; + + std::cout << "Initializing OGRE\n"; + + const char* plugCfg = "plugins.cfg"; + + mOgre.configure(!isFile("ogre.cfg"), plugCfg, false); + + prepareMaster(); + + boost::filesystem::path masterPath (mDataDir); + masterPath /= mMaster; + + std::cout << "Loading ESM " << masterPath.string() << "\n"; + ESM::ESMReader esm; + ESMS::ESMStore store; + ESMS::CellStore cell; + + // This parses the ESM file and loads a sample cell + esm.open(masterPath.file_string()); + store.load(esm); + + cell.loadInt(mCellName, store, esm); + + // Create the window + mOgre.createWindow("OpenMW"); + + std::cout << "\nSetting up cell rendering\n"; + + // Sets up camera, scene manager etc + MWRender::MWScene scene(mOgre); + + // This connects the cell data with the rendering scene. + MWRender::InteriorCellRender rend(cell, scene); + + // Load the cell and insert it into the renderer + rend.show(); + + std::cout << "Setting up input system\n"; + + // Sets up the input system + MWInput::MWInputManager input(mOgre); + + std::cout << "\nStart! Press Q/ESC or close window to exit.\n"; + + // Start the main rendering loop + mOgre.start(); + + std::cout << "\nThat's all for now!\n"; +} + diff --git a/game/engine.hpp b/game/engine.hpp new file mode 100644 index 000000000..31e94775d --- /dev/null +++ b/game/engine.hpp @@ -0,0 +1,49 @@ +#ifndef ENGINE_H +#define ENGINE_H + +#include + +#include + +#include "mwrender/mwscene.hpp" + +namespace OMW +{ + /// \brief Main engine class, that brings together all the components of OpenMW + + class Engine + { + boost::filesystem::path mDataDir; + Render::OgreRenderer mOgre; + std::string mCellName; + std::string mMaster; + + // not implemented + Engine (const Engine&); + Engine& operator= (const Engine&); + + /// adjust name and load bsa + void prepareMaster(); + + public: + + Engine(); + + /// Set data dir + void setDataDir (const boost::filesystem::path& dataDir); + + /// Set start cell name (only interiors for now) + void setCell (const std::string& cellName); + + /// Set master file (esm) + /// - If the given name does not have an extension, ".esm" is added automatically + /// - If there is a bsa file with the same name, OpenMW will load it. + /// - Currently OpenMW only supports one master at the same time. + void addMaster (const std::string& master); + + /// Initialise and enter main loop. + void go(); + }; +} + +#endif diff --git a/game/main.cpp b/game/main.cpp index 58d894a66..4271ec397 100644 --- a/game/main.cpp +++ b/game/main.cpp @@ -6,14 +6,7 @@ #include #include -#include "esm_store/cell_store.hpp" -#include "bsa/bsa_archive.hpp" -#include "ogre/renderer.hpp" -#include "tools/fileops.hpp" - -#include "mwrender/interior.hpp" -#include "mwrender/mwscene.hpp" -#include "mwinput/inputmanager.hpp" +#include "engine.hpp" using namespace std; @@ -22,80 +15,15 @@ void maintest (boost::filesystem::path dataDir, const std::string& cellName, { assert (!dataDir.empty()); - dataDir = boost::filesystem::system_complete (dataDir); - - std::string masterName; // name without extension - - std::string::size_type sep = master.find_last_of ("."); - - if (sep==std::string::npos) - { - masterName = master; - master += ".esm"; - } - else - { - masterName = master.substr (0, sep); - } - - boost::filesystem::path masterPath (dataDir); - masterPath /= master; - - boost::filesystem::path bsa (dataDir); - bsa /= masterName + ".bsa"; - - const char* plugCfg = "plugins.cfg"; - - cout << "Hello, fellow traveler!\n"; - - cout << "Your data directory for today is: " << dataDir << "\n"; - - cout << "Initializing OGRE\n"; - Render::OgreRenderer ogre; - ogre.configure(!isFile("ogre.cfg"), plugCfg, false); - - if (boost::filesystem::exists (bsa)) - { - cout << "Adding " << bsa.string() << endl; - addBSA(bsa.file_string()); - } - - cout << "Loading ESM " << masterPath.string() << "\n"; - ESM::ESMReader esm; - ESMS::ESMStore store; - ESMS::CellStore cell; - - // This parses the ESM file and loads a sample cell - esm.open(masterPath.file_string()); - store.load(esm); - - cell.loadInt(cellName, store, esm); - - // Create the window - ogre.createWindow("OpenMW"); - - cout << "\nSetting up cell rendering\n"; - - // Sets up camera, scene manager etc - MWRender::MWScene scene(ogre); - - // This connects the cell data with the rendering scene. - MWRender::InteriorCellRender rend(cell, scene); - - // Load the cell and insert it into the renderer - rend.show(); - - cout << "Setting up input system\n"; + OMW::Engine engine; - // Sets up the input system - MWInput::MWInputManager input(ogre); + engine.setDataDir (dataDir); - cout << "\nStart! Press Q/ESC or close window to exit.\n"; + engine.setCell (cellName); - // Start the main rendering loop - ogre.start(); + engine.addMaster (master); - cout << "\nThat's all for now!\n"; + engine.go(); } int main(int argc, char**argv) From b7db6dcda3c1b101a49761930feff07eaf9a2903 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 16 Jun 2010 12:21:02 +0200 Subject: [PATCH 3/7] second round of refactoring; moving configuration handling out of main function --- game/main.cpp | 82 +++++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/game/main.cpp b/game/main.cpp index 4271ec397..5d4eb9d03 100644 --- a/game/main.cpp +++ b/game/main.cpp @@ -4,71 +4,69 @@ #include #include -#include #include "engine.hpp" using namespace std; -void maintest (boost::filesystem::path dataDir, const std::string& cellName, - std::string master) -{ - assert (!dataDir.empty()); - - OMW::Engine engine; - - engine.setDataDir (dataDir); - - engine.setCell (cellName); - - engine.addMaster (master); +/// Parse command line options and openmw.cfg file (if one exists). Results are directly +/// written to \a engine. +/// \return Run OpenMW? - engine.go(); -} - -int main(int argc, char**argv) +bool parseOptions (int argc, char**argv, OMW::Engine& engine) { - try - { boost::program_options::options_description desc ( - "Syntax: openmw \nAllowed options"); + "Syntax: openmw \nAllowed options"); desc.add_options() - ("help", "print help message") - ("data", boost::program_options::value()->default_value ("data"), - "set data directory") - ("start", boost::program_options::value()->default_value ("Beshara"), - "set initial cell (only interior cells supported at the moment") - ("master", boost::program_options::value()->default_value ("Morrowind"), - "master file") - ; + ("help", "print help message") + ("data", boost::program_options::value()->default_value ("data"), + "set data directory") + ("start", boost::program_options::value()->default_value ("Beshara"), + "set initial cell (only interior cells supported at the moment") + ("master", boost::program_options::value()->default_value ("Morrowind"), + "master file") + ; boost::program_options::variables_map variables; std::ifstream configFile ("openmw.cfg"); boost::program_options::store ( - boost::program_options::parse_command_line (argc, argv, desc), variables); + boost::program_options::parse_command_line (argc, argv, desc), variables); boost::program_options::notify (variables); if (configFile.is_open()) - boost::program_options::store ( - boost::program_options::parse_config_file (configFile, desc), variables); + boost::program_options::store ( + boost::program_options::parse_config_file (configFile, desc), variables); if (variables.count ("help")) { - std::cout << desc << std::endl; + std::cout << desc << std::endl; + return false; } - else - { - maintest (variables["data"].as(), variables["start"].as(), - variables["master"].as()); - } - } - catch(exception &e) + + engine.setDataDir (variables["data"].as()); + engine.setCell (variables["start"].as()); + engine.addMaster (variables["master"].as()); +} + +int main(int argc, char**argv) +{ + try { - cout << "\nERROR: " << e.what() << endl; - return 1; + OMW::Engine engine; + + if (parseOptions (argc, argv, engine)) + { + engine.go(); + } + } + catch(exception &e) + { + cout << "\nERROR: " << e.what() << endl; + return 1; } - return 0; + + return 0; } From 92bf5b4b6eaa18505b5ba596ba731c062f012142 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 16 Jun 2010 12:58:53 +0200 Subject: [PATCH 4/7] added 'Meshes' and 'Textures' sub-directories as Ogre resources location --- game/engine.cpp | 12 ++++++++++++ game/engine.hpp | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/game/engine.cpp b/game/engine.cpp index 4a1133114..a0803838e 100644 --- a/game/engine.cpp +++ b/game/engine.cpp @@ -45,6 +45,15 @@ void OMW::Engine::prepareMaster() } } +// add resources directory +// \note This function works recursively. + +void OMW::Engine::addResourcesDirectory (const boost::filesystem::path& path) +{ + mOgre.getRoot()->addResourceLocation (path.file_string(), "FileSystem", + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true); +} + // Set data dir void OMW::Engine::setDataDir (const boost::filesystem::path& dataDir) @@ -88,6 +97,9 @@ void OMW::Engine::go() mOgre.configure(!isFile("ogre.cfg"), plugCfg, false); + addResourcesDirectory (mDataDir / "Meshes"); + addResourcesDirectory (mDataDir / "Textures"); + prepareMaster(); boost::filesystem::path masterPath (mDataDir); diff --git a/game/engine.hpp b/game/engine.hpp index 31e94775d..55c8285e0 100644 --- a/game/engine.hpp +++ b/game/engine.hpp @@ -25,6 +25,10 @@ namespace OMW /// adjust name and load bsa void prepareMaster(); + /// add resources directory + /// \note This function works recursively. + void addResourcesDirectory (const boost::filesystem::path& path); + public: Engine(); From 223d8ffd9be810c6f1a55008b0691e8223598b77 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 16 Jun 2010 19:51:59 +0200 Subject: [PATCH 5/7] Redemption compatibility fix --- esm/loadalch.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esm/loadalch.hpp b/esm/loadalch.hpp index 7fc649b45..a556350b0 100644 --- a/esm/loadalch.hpp +++ b/esm/loadalch.hpp @@ -26,7 +26,7 @@ struct Potion void load(ESMReader &esm) { model = esm.getHNString("MODL"); - icon = esm.getHNString("TEXT"); // not ITEX here for some reason + icon = esm.getHNOString("TEXT"); // not ITEX here for some reason script = esm.getHNOString("SCRI"); name = esm.getHNOString("FNAM"); esm.getHNT(data, "ALDT", 12); From 7e4f6559399b74263cfccc345eaa753a026870cf Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 16 Jun 2010 20:15:48 +0200 Subject: [PATCH 6/7] pull in all bsa files instead of only the bsa file matching the master --- game/engine.cpp | 33 +++++++++++++++------------------ game/engine.hpp | 4 +++- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/game/engine.cpp b/game/engine.cpp index a0803838e..f7855847c 100644 --- a/game/engine.cpp +++ b/game/engine.cpp @@ -18,33 +18,30 @@ OMW::Engine::Engine() {} void OMW::Engine::prepareMaster() { - assert (!mDataDir.empty()); - - std::string masterName; // name without extension - std::string::size_type sep = mMaster.find_last_of ("."); if (sep==std::string::npos) { - masterName = mMaster; mMaster += ".esm"; } - else - { - masterName = mMaster.substr (0, sep); - } - - // bsa - boost::filesystem::path bsa (mDataDir); - bsa /= masterName + ".bsa"; +} + +// Load all BSA files in data directory. - if (boost::filesystem::exists (bsa)) +void OMW::Engine::loadBSA() +{ + boost::filesystem::directory_iterator end; + + for (boost::filesystem::directory_iterator iter (mDataDir); iter!=end; ++iter) { - std::cout << "Adding " << bsa.string() << std::endl; - addBSA(bsa.file_string()); + if (boost::filesystem::extension (iter->path())==".bsa") + { + std::cout << "Adding " << iter->path().string() << std::endl; + addBSA(iter->path().file_string()); + } } } - + // add resources directory // \note This function works recursively. @@ -70,7 +67,6 @@ void OMW::Engine::setCell (const std::string& cellName) // Set master file (esm) // - If the given name does not have an extension, ".esm" is added automatically -// - If there is a bsa file with the same name, OpenMW will load it. // - Currently OpenMW only supports one master at the same time. void OMW::Engine::addMaster (const std::string& master) @@ -101,6 +97,7 @@ void OMW::Engine::go() addResourcesDirectory (mDataDir / "Textures"); prepareMaster(); + loadBSA(); boost::filesystem::path masterPath (mDataDir); masterPath /= mMaster; diff --git a/game/engine.hpp b/game/engine.hpp index 55c8285e0..fb6ddbbe4 100644 --- a/game/engine.hpp +++ b/game/engine.hpp @@ -29,6 +29,9 @@ namespace OMW /// \note This function works recursively. void addResourcesDirectory (const boost::filesystem::path& path); + /// Load all BSA files in data directory. + void loadBSA(); + public: Engine(); @@ -41,7 +44,6 @@ namespace OMW /// Set master file (esm) /// - If the given name does not have an extension, ".esm" is added automatically - /// - If there is a bsa file with the same name, OpenMW will load it. /// - Currently OpenMW only supports one master at the same time. void addMaster (const std::string& master); From a8f4b3e66c85d68ece1edcb1026186651ab13c30 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 21 Jun 2010 16:45:12 +0200 Subject: [PATCH 7/7] fixed NIF loader problem with NiTriShape as root node --- nifogre/ogre_nif_loader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nifogre/ogre_nif_loader.cpp b/nifogre/ogre_nif_loader.cpp index a7a887c24..8cee7d186 100644 --- a/nifogre/ogre_nif_loader.cpp +++ b/nifogre/ogre_nif_loader.cpp @@ -604,7 +604,7 @@ void NIFLoader::loadResource(Resource *resource) Record *r = nif.getRecord(0); assert(r != NULL); - if(r->recType != RC_NiNode) + if(r->recType != RC_NiNode && r->recType != RC_NiTriShape) { warn("First record in file was not a NiNode, but a " + r->recName.toString() + ". Skipping file.");