diff --git a/CMakeLists.txt b/CMakeLists.txt index 63d03ec0a..54f358f77 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/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); diff --git a/game/engine.cpp b/game/engine.cpp new file mode 100644 index 000000000..f7855847c --- /dev/null +++ b/game/engine.cpp @@ -0,0 +1,142 @@ +#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() +{ + std::string::size_type sep = mMaster.find_last_of ("."); + + if (sep==std::string::npos) + { + mMaster += ".esm"; + } +} + +// Load all BSA files in data directory. + +void OMW::Engine::loadBSA() +{ + boost::filesystem::directory_iterator end; + + for (boost::filesystem::directory_iterator iter (mDataDir); iter!=end; ++iter) + { + 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. + +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) +{ + 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 +// - 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); + + addResourcesDirectory (mDataDir / "Meshes"); + addResourcesDirectory (mDataDir / "Textures"); + + prepareMaster(); + loadBSA(); + + 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..fb6ddbbe4 --- /dev/null +++ b/game/engine.hpp @@ -0,0 +1,55 @@ +#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(); + + /// add resources directory + /// \note This function works recursively. + void addResourcesDirectory (const boost::filesystem::path& path); + + /// Load all BSA files in data directory. + void loadBSA(); + + 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 + /// - 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 5ebd093a4..5d4eb9d03 100644 --- a/game/main.cpp +++ b/game/main.cpp @@ -3,120 +3,70 @@ #include #include -#include "boost/program_options.hpp" +#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; -void maintest (std::string dataDir, const std::string& cellName) -{ - assert (!dataDir.empty()); - - if (dataDir[dataDir.size()-1]!='/' && dataDir[dataDir.size()-1]!='\\') - dataDir += "/"; - - const char* esmFile = "Morrowind.esm"; - const char* bsaFile = "Morrowind.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); - - cout << "Adding " << bsaFile << endl; - addBSA(dataDir + bsaFile); - - cout << "Loading ESM " << esmFile << "\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); - - 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(); +/// Parse command line options and openmw.cfg file (if one exists). Results are directly +/// written to \a engine. +/// \return Run OpenMW? - cout << "Setting up input system\n"; - - // Sets up the input system - MWInput::MWInputManager input(ogre); - - cout << "\nStart! Press Q/ESC or close window to exit.\n"; - - // Start the main rendering loop - ogre.start(); - - cout << "\nThat's all for now!\n"; -} - -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") - ; + ("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; + } + + engine.setDataDir (variables["data"].as()); + engine.setCell (variables["start"].as()); + engine.addMaster (variables["master"].as()); +} + +int main(int argc, char**argv) +{ + try + { + OMW::Engine engine; + + if (parseOptions (argc, argv, engine)) + { + engine.go(); + } } - else - { - maintest (variables["data"].as(), variables["start"].as()); - } - } - catch(exception &e) + catch(exception &e) { - cout << "\nERROR: " << e.what() << endl; - return 1; + cout << "\nERROR: " << e.what() << endl; + return 1; } - return 0; + + return 0; } 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.");