1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-19 21:23:52 +00:00

Merge remote-tracking branch 'upstream/master' into newlauncher

This commit is contained in:
Pieter van der Kloet 2011-05-08 20:21:57 +02:00
commit 7c1f00884d
10 changed files with 304 additions and 25 deletions

View file

@ -183,9 +183,13 @@ source_group(components\\misc FILES ${MISC} ${MISC_HEADER})
set(FILES set(FILES
${COMP_DIR}/files/path.cpp ${COMP_DIR}/files/path.cpp
${COMP_DIR}/files/multidircollection.cpp
${COMP_DIR}/files/collections.cpp
) )
set(FILES_HEADER set(FILES_HEADER
${COMP_DIR}/files/path.hpp ${COMP_DIR}/files/path.hpp
${COMP_DIR}/files/multidircollection.hpp
${COMP_DIR}/files/collections.hpp
) )
source_group(components\\files FILES ${FILES} ${FILES_HEADER}) source_group(components\\files FILES ${FILES} ${FILES_HEADER})

View file

@ -218,6 +218,7 @@ OMW::Engine::Engine()
, mScriptManager (0) , mScriptManager (0)
, mScriptContext (0) , mScriptContext (0)
, mGuiManager (0) , mGuiManager (0)
, mFSStrict (false)
{ {
MWClass::registerClasses(); MWClass::registerClasses();
} }
@ -240,15 +241,12 @@ OMW::Engine::~Engine()
void OMW::Engine::loadBSA() void OMW::Engine::loadBSA()
{ {
boost::filesystem::directory_iterator end; const Files::MultiDirCollection& bsa = mFileCollections.getCollection (".bsa");
for (boost::filesystem::directory_iterator iter (mDataDir); iter!=end; ++iter) for (Files::MultiDirCollection::TIter iter (bsa.begin()); iter!=bsa.end(); ++iter)
{ {
if (boost::filesystem::extension (iter->path())==".bsa") std::cout << "Adding " << iter->second.string() << std::endl;
{ addBSA (iter->second.string());
std::cout << "Adding " << iter->path().string() << std::endl;
addBSA(iter->path().string());
}
} }
} }
@ -261,11 +259,20 @@ void OMW::Engine::addResourcesDirectory (const boost::filesystem::path& path)
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true); Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true);
} }
void OMW::Engine::enableFSStrict()
{
mFSStrict = true;
}
// Set data dir // Set data dir
void OMW::Engine::setDataDir (const boost::filesystem::path& dataDir) void OMW::Engine::setDataDirs (const std::vector<boost::filesystem::path>& dataDirs)
{ {
mDataDir = boost::filesystem::system_complete (dataDir); /// \todo remove mDataDir, once resources system can handle multiple directories
assert (!dataDirs.empty());
mDataDir = dataDirs[0];
mFileCollections = Files::Collections (dataDirs, !mFSStrict);
} }
// Set resource dir // Set resource dir
@ -318,15 +325,12 @@ void OMW::Engine::setNewGame()
void OMW::Engine::go() void OMW::Engine::go()
{ {
assert (!mEnvironment.mWorld); assert (!mEnvironment.mWorld);
assert (!mDataDir.empty());
assert (!mCellName.empty()); assert (!mCellName.empty());
assert (!mMaster.empty()); assert (!mMaster.empty());
test.name = ""; test.name = "";
total = 0; total = 0;
std::cout << "Data directory: " << mDataDir << "\n";
std::string cfgDir = Files::getPath (Files::Path_ConfigGlobal, "openmw", ""); std::string cfgDir = Files::getPath (Files::Path_ConfigGlobal, "openmw", "");
std::string cfgUserDir = Files::getPath (Files::Path_ConfigUser, "openmw", ""); std::string cfgUserDir = Files::getPath (Files::Path_ConfigUser, "openmw", "");
std::string plugCfg = "plugins.cfg"; std::string plugCfg = "plugins.cfg";
@ -358,8 +362,8 @@ void OMW::Engine::go()
mPhysicEngine = new OEngine::Physic::PhysicEngine(shapeLoader); mPhysicEngine = new OEngine::Physic::PhysicEngine(shapeLoader);
// Create the world // Create the world
mEnvironment.mWorld = new MWWorld::World (mOgre, mPhysicEngine, mDataDir, mMaster, mResDir, mNewGame, mEnvironment); mEnvironment.mWorld = new MWWorld::World (mOgre, mPhysicEngine, mFileCollections, mMaster,
mResDir, mNewGame, mEnvironment);
// Set up the GUI system // Set up the GUI system
mGuiManager = new OEngine::GUI::MyGUIManager(mOgre.getWindow(), mOgre.getScene(), false, cfgDir); mGuiManager = new OEngine::GUI::MyGUIManager(mOgre.getWindow(), mOgre.getScene(), false, cfgDir);

View file

@ -10,6 +10,7 @@
#include <openengine/ogre/renderer.hpp> #include <openengine/ogre/renderer.hpp>
#include <openengine/bullet/physic.hpp> #include <openengine/bullet/physic.hpp>
#include <components/compiler/extensions.hpp> #include <components/compiler/extensions.hpp>
#include <components/files/collections.hpp>
#include "mwworld/environment.hpp" #include "mwworld/environment.hpp"
#include "mwworld/ptr.hpp" #include "mwworld/ptr.hpp"
@ -55,8 +56,6 @@ namespace OMW
class Engine : private Ogre::FrameListener class Engine : private Ogre::FrameListener
{ {
//int nFiles;
boost::filesystem::path mDataDir; boost::filesystem::path mDataDir;
boost::filesystem::path mResDir; boost::filesystem::path mResDir;
OEngine::Render::OgreRenderer mOgre; OEngine::Render::OgreRenderer mOgre;
@ -84,6 +83,9 @@ namespace OMW
MWWorld::Ptr mIgnoreLocalPtr; MWWorld::Ptr mIgnoreLocalPtr;
Files::Collections mFileCollections;
bool mFSStrict;
// not implemented // not implemented
Engine (const Engine&); Engine (const Engine&);
Engine& operator= (const Engine&); Engine& operator= (const Engine&);
@ -108,8 +110,14 @@ namespace OMW
~Engine(); ~Engine();
/// Set data dir /// Enable strict filesystem mode (do not fold case)
void setDataDir (const boost::filesystem::path& dataDir); ///
/// \attention The strict mode must be specified before any path-related settings
/// are given to the engine.
void enableFSStrict();
/// Set data dirs
void setDataDirs (const std::vector<boost::filesystem::path>& dataDirs);
/// Set resource dir /// Set resource dir
void setResourceDir (const boost::filesystem::path& parResDir); void setResourceDir (const boost::filesystem::path& parResDir);

View file

@ -42,8 +42,12 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine)
desc.add_options() desc.add_options()
("help", "print help message") ("help", "print help message")
("data", bpo::value<std::string>()->default_value ("data"), ("data", bpo::value<std::vector<std::string> >()
"set data directory") ->default_value (std::vector<std::string>(), "data")
->multitoken(),
"set data directories (later directories have higher priority)")
("data-local", bpo::value<std::string>()->default_value (""),
"set local data directory (highest priority)")
("resources", bpo::value<std::string>()->default_value ("resources"), ("resources", bpo::value<std::string>()->default_value ("resources"),
"set resources directory") "set resources directory")
("start", bpo::value<std::string>()->default_value ("Beshara"), ("start", bpo::value<std::string>()->default_value ("Beshara"),
@ -70,6 +74,9 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine)
( "script-all", boost::program_options::value<bool>()-> ( "script-all", boost::program_options::value<bool>()->
implicit_value (true)->default_value (false), implicit_value (true)->default_value (false),
"compile all scripts (excluding dialogue scripts) at startup") "compile all scripts (excluding dialogue scripts) at startup")
( "fs-strict", boost::program_options::value<bool>()->
implicit_value (true)->default_value (false),
"strict file system handling (no case folding)")
; ;
bpo::variables_map variables; bpo::variables_map variables;
@ -105,7 +112,18 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine)
} }
// directory settings // directory settings
engine.setDataDir (variables["data"].as<std::string>()); if (variables["fs-strict"].as<bool>()==true)
engine.enableFSStrict();
std::vector<std::string> dataDirs = variables["data"].as<std::vector<std::string> >();
std::vector<boost::filesystem::path> dataDirs2 (dataDirs.begin(), dataDirs.end());
std::string local = variables["data-local"].as<std::string>();
if (!local.empty())
dataDirs.push_back (local);
engine.setDataDirs (dataDirs2);
engine.setResourceDir (variables["resources"].as<std::string>()); engine.setResourceDir (variables["resources"].as<std::string>());
// master and plugin // master and plugin

View file

@ -5,6 +5,7 @@
#include <iostream> #include <iostream>
#include <components/bsa/bsa_archive.hpp> #include <components/bsa/bsa_archive.hpp>
#include <components/files/collections.hpp>
#include "../mwrender/sky.hpp" #include "../mwrender/sky.hpp"
#include "../mwrender/interior.hpp" #include "../mwrender/interior.hpp"
@ -406,15 +407,16 @@ namespace MWWorld
mCellChanged = true; mCellChanged = true;
} }
World::World (OEngine::Render::OgreRenderer& renderer, OEngine::Physic::PhysicEngine* physEng, const boost::filesystem::path& dataDir, World::World (OEngine::Render::OgreRenderer& renderer, OEngine::Physic::PhysicEngine* physEng,
const Files::Collections& fileCollections,
const std::string& master, const boost::filesystem::path& resDir, const std::string& master, const boost::filesystem::path& resDir,
bool newGame, Environment& environment) bool newGame, Environment& environment)
: mSkyManager (0), mScene (renderer,physEng), mPlayer (0), mCurrentCell (0), mGlobalVariables (0), : mSkyManager (0), mScene (renderer,physEng), mPlayer (0), mCurrentCell (0), mGlobalVariables (0),
mSky (false), mCellChanged (false), mEnvironment (environment) mSky (false), mCellChanged (false), mEnvironment (environment)
{ {
mPhysEngine = physEng; mPhysEngine = physEng;
boost::filesystem::path masterPath (dataDir);
masterPath /= master; boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master));
std::cout << "Loading ESM " << masterPath.string() << "\n"; std::cout << "Loading ESM " << masterPath.string() << "\n";

View file

@ -26,6 +26,11 @@ namespace ESM
struct Position; struct Position;
} }
namespace Files
{
class Collections;
}
namespace Render namespace Render
{ {
class OgreRenderer; class OgreRenderer;
@ -107,7 +112,8 @@ namespace MWWorld
/// interior cell. /// interior cell.
public: public:
World (OEngine::Render::OgreRenderer& renderer, OEngine::Physic::PhysicEngine* physEng, const boost::filesystem::path& dataDir, World (OEngine::Render::OgreRenderer& renderer, OEngine::Physic::PhysicEngine* physEng,
const Files::Collections& fileCollections,
const std::string& master, const boost::filesystem::path& resDir, bool newGame, const std::string& master, const boost::filesystem::path& resDir, bool newGame,
Environment& environment); Environment& environment);

View file

@ -0,0 +1,27 @@
#include "collections.hpp"
namespace Files
{
Collections::Collections() : mFoldCase (false) {}
Collections::Collections (const std::vector<boost::filesystem::path>& directories, bool foldCase)
: mDirectories (directories), mFoldCase (foldCase)
{}
const MultiDirCollection& Collections::getCollection (const std::string& extension) const
{
std::map<std::string, MultiDirCollection>::iterator iter = mCollections.find (extension);
if (iter==mCollections.end())
{
std::pair<std::map<std::string, MultiDirCollection>::iterator, bool> result =
mCollections.insert (std::make_pair (extension,
MultiDirCollection (mDirectories, extension, mFoldCase)));
iter = result.first;
}
return iter->second;
}
}

View file

@ -0,0 +1,28 @@
#ifndef COMPONENTS_FILES_COLLECTION_HPP
#define COMPONENTS_FILES_COLLECTION_HPP
#include "multidircollection.hpp"
namespace Files
{
class Collections
{
std::vector<boost::filesystem::path> mDirectories;
bool mFoldCase;
mutable std::map<std::string, MultiDirCollection> mCollections;
public:
Collections();
Collections (const std::vector<boost::filesystem::path>& directories, bool foldCase);
///< Directories are listed with increasing priority.
const MultiDirCollection& getCollection (const std::string& extension) const;
///< Return a file collection for the given extension. Extension must contain the
/// leading dot and must be all lower-case.
};
}
#endif

View file

@ -0,0 +1,102 @@
#include "multidircollection.hpp"
#include <cctype>
#include <algorithm>
#include <stdexcept>
#include <boost/filesystem.hpp>
namespace Files
{
struct NameEqual
{
bool mStrict;
NameEqual (bool strict) : mStrict (strict) {}
bool operator() (const std::string& left, const std::string& right) const
{
if (mStrict)
return left==right;
std::size_t len = left.length();
if (len!=right.length())
return false;
for (std::size_t i=0; i<len; ++i)
{
char l = std::tolower (left[i]);
char r = std::tolower (right[i]);
if (l!=r)
return false;
}
return true;
}
};
MultiDirCollection::MultiDirCollection (const std::vector<boost::filesystem::path>& directories,
const std::string& extension, bool foldCase)
: mFiles (NameLess (!foldCase))
{
NameEqual equal (!foldCase);
for (std::vector<boost::filesystem::path>::const_iterator iter = directories.begin();
iter!=directories.end(); ++iter)
{
boost::filesystem::path dataDirectory = *iter;
for (boost::filesystem::directory_iterator iter (dataDirectory);
iter!=boost::filesystem::directory_iterator(); ++iter)
{
boost::filesystem::path path = *iter;
if (!equal (extension, path.extension()))
continue;
std::string filename = path.filename();
TIter result = mFiles.find (filename);
if (result==mFiles.end())
{
mFiles.insert (std::make_pair (filename, path));
}
else if (result->first==filename)
{
mFiles[filename] = path;
}
else
{
// handle case folding
mFiles.erase (result->first);
mFiles.insert (std::make_pair (filename, path));
}
}
}
}
boost::filesystem::path MultiDirCollection::getPath (const std::string& file) const
{
TIter iter = mFiles.find (file);
if (iter==mFiles.end())
throw std::runtime_error ("file " + file + " not found");
return iter->second;
}
MultiDirCollection::TIter MultiDirCollection::begin() const
{
return mFiles.begin();
}
MultiDirCollection::TIter MultiDirCollection::end() const
{
return mFiles.end();
}
}

View file

@ -0,0 +1,80 @@
#ifndef COMPONENTS_FILES_MULTIDIRSOLLECTION_HPP
#define COMPONENTS_FILES_MULTIDIRSOLLECTION_HPP
#include <map>
#include <vector>
#include <string>
#include <boost/filesystem/path.hpp>
namespace Files
{
struct NameLess
{
bool mStrict;
NameLess (bool strict) : mStrict (strict) {}
bool operator() (const std::string& left, const std::string& right) const
{
if (mStrict)
return left<right;
std::size_t min = std::min (left.length(), right.length());
for (std::size_t i=0; i<min; ++i)
{
char l = std::tolower (left[i]);
char r = std::tolower (right[i]);
if (l<r)
return true;
if (l>r)
return false;
}
return left.length()<right.length();
}
};
/// \brief File collection across several directories
///
/// This class lists all files with one specific extensions within one or more
/// directories. If the same file appears more than once, the file in the directory
/// with the higher priority is used.
class MultiDirCollection
{
public:
typedef std::map<std::string, boost::filesystem::path, NameLess> TContainer;
typedef TContainer::const_iterator TIter;
private:
TContainer mFiles;
public:
MultiDirCollection (const std::vector<boost::filesystem::path>& directories,
const std::string& extension, bool foldCase);
///< Directories are listed with increasing priority.
/// \param extension The extension that should be listed in this collection. Must
/// contain the leading dot.
/// \param foldCase Ignore filename case
boost::filesystem::path getPath (const std::string& file) const;
///< Return full path (including filename) of \æ file.
///
/// If the file does not exist, an exception is thrown. \a file must include
/// the extension.
TIter begin() const;
///< Return iterator pointing to the first file.
TIter end() const;
///< Return iterator pointing past the last file.
};
}
#endif