Merge remote-tracking branch 'zini/master' into animation2

Conflicts:
	apps/openmw/mwrender/actors.cpp
	apps/openmw/mwrender/actors.hpp
This commit is contained in:
Chris Robinson 2013-01-16 07:30:36 -08:00
commit 1ce8eaf52c
9 changed files with 197 additions and 279 deletions

View file

@ -9,6 +9,7 @@
#include <components/bsa/bsa_archive.hpp> #include <components/bsa/bsa_archive.hpp>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#include <components/translation/translation.hpp> #include <components/translation/translation.hpp>
#include <components/nif/nif_file.hpp>
#include <components/nifoverrides/nifoverrides.hpp> #include <components/nifoverrides/nifoverrides.hpp>
#include <components/nifbullet/bullet_nif_loader.hpp> #include <components/nifbullet/bullet_nif_loader.hpp>

View file

@ -84,7 +84,7 @@ namespace MWBase
///< Start playing music from the selected folder ///< Start playing music from the selected folder
/// \param name of the folder that contains the playlist /// \param name of the folder that contains the playlist
virtual void say(MWWorld::Ptr reference, const std::string& filename) = 0; virtual void say(const MWWorld::Ptr &reference, const std::string& filename) = 0;
///< Make an actor say some text. ///< Make an actor say some text.
/// \param filename name of a sound file in "Sound/" in the data directory. /// \param filename name of a sound file in "Sound/" in the data directory.
@ -92,10 +92,10 @@ namespace MWBase
///< Say some text, without an actor ref ///< Say some text, without an actor ref
/// \param filename name of a sound file in "Sound/" in the data directory. /// \param filename name of a sound file in "Sound/" in the data directory.
virtual bool sayDone(MWWorld::Ptr reference=MWWorld::Ptr()) const = 0; virtual bool sayDone(const MWWorld::Ptr &reference=MWWorld::Ptr()) const = 0;
///< Is actor not speaking? ///< Is actor not speaking?
virtual void stopSay(MWWorld::Ptr reference=MWWorld::Ptr()) = 0; virtual void stopSay(const MWWorld::Ptr &reference=MWWorld::Ptr()) = 0;
///< Stop an actor speaking ///< Stop an actor speaking
virtual SoundPtr playTrack(const MWSound::DecoderPtr& decoder, PlayType type) = 0; virtual SoundPtr playTrack(const MWSound::DecoderPtr& decoder, PlayType type) = 0;
@ -105,14 +105,14 @@ namespace MWBase
PlayMode mode=Play_Normal) = 0; PlayMode mode=Play_Normal) = 0;
///< Play a sound, independently of 3D-position ///< Play a sound, independently of 3D-position
virtual SoundPtr playSound3D(MWWorld::Ptr reference, const std::string& soundId, virtual SoundPtr playSound3D(const MWWorld::Ptr &reference, const std::string& soundId,
float volume, float pitch, PlayMode mode=Play_Normal) = 0; float volume, float pitch, PlayMode mode=Play_Normal) = 0;
///< Play a sound from an object ///< Play a sound from an object
virtual void stopSound3D(MWWorld::Ptr reference, const std::string& soundId) = 0; virtual void stopSound3D(const MWWorld::Ptr &reference, const std::string& soundId) = 0;
///< Stop the given object from playing the given sound, ///< Stop the given object from playing the given sound,
virtual void stopSound3D(MWWorld::Ptr reference) = 0; virtual void stopSound3D(const MWWorld::Ptr &reference) = 0;
///< Stop the given object from playing all sounds. ///< Stop the given object from playing all sounds.
virtual void stopSound(const MWWorld::CellStore *cell) = 0; virtual void stopSound(const MWWorld::CellStore *cell) = 0;
@ -121,7 +121,7 @@ namespace MWBase
virtual void stopSound(const std::string& soundId) = 0; virtual void stopSound(const std::string& soundId) = 0;
///< Stop a non-3d looping sound ///< Stop a non-3d looping sound
virtual bool getSoundPlaying(MWWorld::Ptr reference, const std::string& soundId) const = 0; virtual bool getSoundPlaying(const MWWorld::Ptr &reference, const std::string& soundId) const = 0;
///< Is the given sound currently playing on the given object? ///< Is the given sound currently playing on the given object?
virtual void pauseSounds(int types=Play_TypeMask) = 0; virtual void pauseSounds(int types=Play_TypeMask) = 0;

View file

@ -16,31 +16,31 @@ namespace MWRender
{ {
using namespace Ogre; using namespace Ogre;
Actors::~Actors(){ Actors::~Actors()
std::map<MWWorld::Ptr, Animation*>::iterator it = mAllActors.begin(); {
for (; it != mAllActors.end(); ++it) { PtrAnimationMap::iterator it = mAllActors.begin();
for(;it != mAllActors.end();++it)
{
delete it->second; delete it->second;
it->second = NULL; it->second = NULL;
} }
} }
void Actors::setMwRoot(Ogre::SceneNode* root){ void Actors::setMwRoot(Ogre::SceneNode* root)
mMwRoot = root; { mMwRoot = root; }
}
void Actors::insertBegin (const MWWorld::Ptr& ptr) void Actors::insertBegin(const MWWorld::Ptr &ptr)
{ {
Ogre::SceneNode* cellnode; Ogre::SceneNode* cellnode;
if(mCellSceneNodes.find(ptr.getCell()) == mCellSceneNodes.end()) CellSceneNodeMap::const_iterator celliter = mCellSceneNodes.find(ptr.getCell());
if(celliter != mCellSceneNodes.end())
cellnode = celliter->second;
else
{ {
//Create the scenenode and put it in the map //Create the scenenode and put it in the map
cellnode = mMwRoot->createChildSceneNode(); cellnode = mMwRoot->createChildSceneNode();
mCellSceneNodes[ptr.getCell()] = cellnode; mCellSceneNodes[ptr.getCell()] = cellnode;
} }
else
{
cellnode = mCellSceneNodes[ptr.getCell()];
}
Ogre::SceneNode* insert = cellnode->createChildSceneNode(); Ogre::SceneNode* insert = cellnode->createChildSceneNode();
const float *f = ptr.getRefData().getPosition().pos; const float *f = ptr.getRefData().getPosition().pos;
@ -51,13 +51,13 @@ void Actors::insertBegin (const MWWorld::Ptr& ptr)
f = ptr.getCellRef().mPos.rot; f = ptr.getCellRef().mPos.rot;
// Rotate around X axis // Rotate around X axis
Quaternion xr(Radian(-f[0]), Vector3::UNIT_X); Ogre::Quaternion xr(Ogre::Radian(-f[0]), Ogre::Vector3::UNIT_X);
// Rotate around Y axis // Rotate around Y axis
Quaternion yr(Radian(-f[1]), Vector3::UNIT_Y); Ogre::Quaternion yr(Ogre::Radian(-f[1]), Ogre::Vector3::UNIT_Y);
// Rotate around Z axis // Rotate around Z axis
Quaternion zr(Radian(-f[2]), Vector3::UNIT_Z); Ogre::Quaternion zr(Ogre::Radian(-f[2]), Ogre::Vector3::UNIT_Z);
// Rotates first around z, then y, then x // Rotates first around z, then y, then x
insert->setOrientation(xr*yr*zr); insert->setOrientation(xr*yr*zr);
@ -83,20 +83,21 @@ bool Actors::deleteObject (const MWWorld::Ptr& ptr)
{ {
delete mAllActors[ptr]; delete mAllActors[ptr];
mAllActors.erase(ptr); mAllActors.erase(ptr);
if (Ogre::SceneNode *base = ptr.getRefData().getBaseNode())
if(Ogre::SceneNode *base=ptr.getRefData().getBaseNode())
{ {
Ogre::SceneNode *parent = base->getParentSceneNode(); Ogre::SceneNode *parent = base->getParentSceneNode();
CellSceneNodeMap::const_iterator iter(mCellSceneNodes.begin());
for (std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *>::const_iterator iter ( for(;iter != mCellSceneNodes.end();++iter)
mCellSceneNodes.begin()); iter!=mCellSceneNodes.end(); ++iter) {
if (iter->second==parent) if(iter->second == parent)
{ {
base->removeAndDestroyAllChildren(); base->removeAndDestroyAllChildren();
mRend.getScene()->destroySceneNode (base); mRend.getScene()->destroySceneNode (base);
ptr.getRefData().setBaseNode (0); ptr.getRefData().setBaseNode (0);
return true; return true;
} }
}
return false; return false;
} }
@ -104,57 +105,68 @@ bool Actors::deleteObject (const MWWorld::Ptr& ptr)
return true; return true;
} }
void Actors::removeCell(MWWorld::Ptr::CellStore* store){ void Actors::removeCell(MWWorld::Ptr::CellStore* store)
if(mCellSceneNodes.find(store) != mCellSceneNodes.end()) {
for(PtrAnimationMap::iterator iter = mAllActors.begin();iter != mAllActors.end();)
{ {
Ogre::SceneNode* base = mCellSceneNodes[store]; if(iter->first.getCell() == store)
base->removeAndDestroyAllChildren();
mCellSceneNodes.erase(store);
mRend.getScene()->destroySceneNode(base);
base = 0;
}
for(std::map<MWWorld::Ptr, Animation*>::iterator iter = mAllActors.begin(); iter != mAllActors.end(); )
{ {
if(iter->first.getCell() == store){
delete iter->second; delete iter->second;
mAllActors.erase(iter++); mAllActors.erase(iter++);
} }
else else
++iter; ++iter;
} }
CellSceneNodeMap::iterator celliter = mCellSceneNodes.find(store);
if(celliter != mCellSceneNodes.end())
{
Ogre::SceneNode *base = celliter->second;
base->removeAndDestroyAllChildren();
mRend.getScene()->destroySceneNode(base);
mCellSceneNodes.erase(celliter);
}
} }
void Actors::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number){ void Actors::playAnimationGroup (const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number)
if(mAllActors.find(ptr) != mAllActors.end()) {
mAllActors[ptr]->playGroup(groupName, mode, number); PtrAnimationMap::const_iterator iter = mAllActors.find(ptr);
if(iter != mAllActors.end())
iter->second->playGroup(groupName, mode, number);
} }
void Actors::skipAnimation (const MWWorld::Ptr& ptr){ void Actors::skipAnimation (const MWWorld::Ptr& ptr)
if(mAllActors.find(ptr) != mAllActors.end()) {
mAllActors[ptr]->skipAnim(); PtrAnimationMap::const_iterator iter = mAllActors.find(ptr);
if(iter != mAllActors.end())
iter->second->skipAnim();
} }
void Actors::update (float duration){ void Actors::update (float duration)
for(std::map<MWWorld::Ptr, Animation*>::iterator iter = mAllActors.begin(); iter != mAllActors.end(); iter++) {
for(PtrAnimationMap::const_iterator iter = mAllActors.begin();iter != mAllActors.end();iter++)
iter->second->runAnimation(duration); iter->second->runAnimation(duration);
} }
void void Actors::updateObjectCell(const MWWorld::Ptr &ptr)
Actors::updateObjectCell(const MWWorld::Ptr &ptr)
{ {
Ogre::SceneNode *node; Ogre::SceneNode *node;
MWWorld::CellStore *newCell = ptr.getCell(); MWWorld::CellStore *newCell = ptr.getCell();
if(mCellSceneNodes.find(newCell) == mCellSceneNodes.end()) { CellSceneNodeMap::const_iterator celliter = mCellSceneNodes.find(newCell);
if(celliter != mCellSceneNodes.end())
node = celliter->second;
else
{
node = mMwRoot->createChildSceneNode(); node = mMwRoot->createChildSceneNode();
mCellSceneNodes[newCell] = node; mCellSceneNodes[newCell] = node;
} else {
node = mCellSceneNodes[newCell];
} }
node->addChild(ptr.getRefData().getBaseNode()); node->addChild(ptr.getRefData().getBaseNode());
if (mAllActors.find(ptr) != mAllActors.end()) {
PtrAnimationMap::iterator iter = mAllActors.find(ptr);
if(iter != mAllActors.end())
{
/// \note Update key (Ptr's are compared only with refdata so mCell /// \note Update key (Ptr's are compared only with refdata so mCell
/// on key is outdated), maybe redundant /// on key is outdated), maybe redundant
Animation *anim = mAllActors[ptr]; Animation *anim = iter->second;
mAllActors.erase(ptr); mAllActors.erase(iter);
mAllActors[ptr] = anim; mAllActors[ptr] = anim;
} }
} }

View file

@ -16,14 +16,19 @@ namespace MWRender
class Actors class Actors
{ {
typedef std::map<MWWorld::CellStore*,Ogre::SceneNode*> CellSceneNodeMap;
typedef std::map<MWWorld::Ptr,Animation*> PtrAnimationMap;
OEngine::Render::OgreRenderer &mRend; OEngine::Render::OgreRenderer &mRend;
std::map<MWWorld::CellStore *, Ogre::SceneNode *> mCellSceneNodes;
Ogre::SceneNode* mMwRoot; Ogre::SceneNode* mMwRoot;
std::map<MWWorld::Ptr, Animation*> mAllActors;
CellSceneNodeMap mCellSceneNodes;
PtrAnimationMap mAllActors;
public: public:
Actors(OEngine::Render::OgreRenderer& _rend): mRend(_rend) {} Actors(OEngine::Render::OgreRenderer& _rend): mRend(_rend) {}
~Actors(); ~Actors();
void setMwRoot(Ogre::SceneNode* root); void setMwRoot(Ogre::SceneNode* root);
void insertBegin (const MWWorld::Ptr& ptr); void insertBegin (const MWWorld::Ptr& ptr);
void insertCreature (const MWWorld::Ptr& ptr); void insertCreature (const MWWorld::Ptr& ptr);

View file

@ -13,7 +13,7 @@ namespace Interpreter
namespace MWScript namespace MWScript
{ {
/// \brief Temporaty script functionality limited to the console /// \brief Temporary script functionality limited to the console
namespace User namespace User
{ {
void registerExtensions (Compiler::Extensions& extensions); void registerExtensions (Compiler::Extensions& extensions);

View file

@ -160,7 +160,7 @@ namespace MWSound
return volume; return volume;
} }
bool SoundManager::isPlaying(MWWorld::Ptr ptr, const std::string &id) const bool SoundManager::isPlaying(const MWWorld::Ptr &ptr, const std::string &id) const
{ {
SoundMap::const_iterator snditer = mActiveSounds.begin(); SoundMap::const_iterator snditer = mActiveSounds.begin();
while(snditer != mActiveSounds.end()) while(snditer != mActiveSounds.end())
@ -229,7 +229,7 @@ namespace MWSound
startRandomTitle(); startRandomTitle();
} }
void SoundManager::say(MWWorld::Ptr ptr, const std::string& filename) void SoundManager::say(const MWWorld::Ptr &ptr, const std::string& filename)
{ {
if(!mOutput->isInitialized()) if(!mOutput->isInitialized())
return; return;
@ -269,12 +269,12 @@ namespace MWSound
} }
} }
bool SoundManager::sayDone(MWWorld::Ptr ptr) const bool SoundManager::sayDone(const MWWorld::Ptr &ptr) const
{ {
return !isPlaying(ptr, "_say_sound"); return !isPlaying(ptr, "_say_sound");
} }
void SoundManager::stopSay(MWWorld::Ptr ptr) void SoundManager::stopSay(const MWWorld::Ptr &ptr)
{ {
SoundMap::iterator snditer = mActiveSounds.begin(); SoundMap::iterator snditer = mActiveSounds.begin();
while(snditer != mActiveSounds.end()) while(snditer != mActiveSounds.end())
@ -328,7 +328,7 @@ namespace MWSound
return sound; return sound;
} }
MWBase::SoundPtr SoundManager::playSound3D(MWWorld::Ptr ptr, const std::string& soundId, MWBase::SoundPtr SoundManager::playSound3D(const MWWorld::Ptr &ptr, const std::string& soundId,
float volume, float pitch, PlayMode mode) float volume, float pitch, PlayMode mode)
{ {
MWBase::SoundPtr sound; MWBase::SoundPtr sound;
@ -356,7 +356,7 @@ namespace MWSound
return sound; return sound;
} }
void SoundManager::stopSound3D(MWWorld::Ptr ptr, const std::string& soundId) void SoundManager::stopSound3D(const MWWorld::Ptr &ptr, const std::string& soundId)
{ {
SoundMap::iterator snditer = mActiveSounds.begin(); SoundMap::iterator snditer = mActiveSounds.begin();
while(snditer != mActiveSounds.end()) while(snditer != mActiveSounds.end())
@ -371,7 +371,7 @@ namespace MWSound
} }
} }
void SoundManager::stopSound3D(MWWorld::Ptr ptr) void SoundManager::stopSound3D(const MWWorld::Ptr &ptr)
{ {
SoundMap::iterator snditer = mActiveSounds.begin(); SoundMap::iterator snditer = mActiveSounds.begin();
while(snditer != mActiveSounds.end()) while(snditer != mActiveSounds.end())
@ -418,7 +418,7 @@ namespace MWSound
} }
} }
bool SoundManager::getSoundPlaying(MWWorld::Ptr ptr, const std::string& soundId) const bool SoundManager::getSoundPlaying(const MWWorld::Ptr &ptr, const std::string& soundId) const
{ {
return isPlaying(ptr, soundId); return isPlaying(ptr, soundId);
} }

View file

@ -14,8 +14,6 @@
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
#include "../mwworld/ptr.hpp"
namespace MWSound namespace MWSound
{ {
class Sound_Output; class Sound_Output;
@ -57,7 +55,7 @@ namespace MWSound
std::string lookup(const std::string &soundId, std::string lookup(const std::string &soundId,
float &volume, float &min, float &max); float &volume, float &min, float &max);
void streamMusicFull(const std::string& filename); void streamMusicFull(const std::string& filename);
bool isPlaying(MWWorld::Ptr ptr, const std::string &id) const; bool isPlaying(const MWWorld::Ptr &ptr, const std::string &id) const;
void updateSounds(float duration); void updateSounds(float duration);
void updateRegionSound(float duration); void updateRegionSound(float duration);
@ -93,7 +91,7 @@ namespace MWSound
///< Start playing music from the selected folder ///< Start playing music from the selected folder
/// \param name of the folder that contains the playlist /// \param name of the folder that contains the playlist
virtual void say(MWWorld::Ptr reference, const std::string& filename); virtual void say(const MWWorld::Ptr &reference, const std::string& filename);
///< Make an actor say some text. ///< Make an actor say some text.
/// \param filename name of a sound file in "Sound/" in the data directory. /// \param filename name of a sound file in "Sound/" in the data directory.
@ -101,10 +99,10 @@ namespace MWSound
///< Say some text, without an actor ref ///< Say some text, without an actor ref
/// \param filename name of a sound file in "Sound/" in the data directory. /// \param filename name of a sound file in "Sound/" in the data directory.
virtual bool sayDone(MWWorld::Ptr reference=MWWorld::Ptr()) const; virtual bool sayDone(const MWWorld::Ptr &reference=MWWorld::Ptr()) const;
///< Is actor not speaking? ///< Is actor not speaking?
virtual void stopSay(MWWorld::Ptr reference=MWWorld::Ptr()); virtual void stopSay(const MWWorld::Ptr &reference=MWWorld::Ptr());
///< Stop an actor speaking ///< Stop an actor speaking
virtual MWBase::SoundPtr playTrack(const DecoderPtr& decoder, PlayType type); virtual MWBase::SoundPtr playTrack(const DecoderPtr& decoder, PlayType type);
@ -113,14 +111,14 @@ namespace MWSound
virtual MWBase::SoundPtr playSound(const std::string& soundId, float volume, float pitch, PlayMode mode=Play_Normal); virtual MWBase::SoundPtr playSound(const std::string& soundId, float volume, float pitch, PlayMode mode=Play_Normal);
///< Play a sound, independently of 3D-position ///< Play a sound, independently of 3D-position
virtual MWBase::SoundPtr playSound3D(MWWorld::Ptr reference, const std::string& soundId, virtual MWBase::SoundPtr playSound3D(const MWWorld::Ptr &reference, const std::string& soundId,
float volume, float pitch, PlayMode mode=Play_Normal); float volume, float pitch, PlayMode mode=Play_Normal);
///< Play a sound from an object ///< Play a sound from an object
virtual void stopSound3D(MWWorld::Ptr reference, const std::string& soundId); virtual void stopSound3D(const MWWorld::Ptr &reference, const std::string& soundId);
///< Stop the given object from playing the given sound, ///< Stop the given object from playing the given sound,
virtual void stopSound3D(MWWorld::Ptr reference); virtual void stopSound3D(const MWWorld::Ptr &reference);
///< Stop the given object from playing all sounds. ///< Stop the given object from playing all sounds.
virtual void stopSound(const MWWorld::CellStore *cell); virtual void stopSound(const MWWorld::CellStore *cell);
@ -129,7 +127,7 @@ namespace MWSound
virtual void stopSound(const std::string& soundId); virtual void stopSound(const std::string& soundId);
///< Stop a non-3d looping sound ///< Stop a non-3d looping sound
virtual bool getSoundPlaying(MWWorld::Ptr reference, const std::string& soundId) const; virtual bool getSoundPlaying(const MWWorld::Ptr &reference, const std::string& soundId) const;
///< Is the given sound currently playing on the given object? ///< Is the given sound currently playing on the given object?
virtual void pauseSounds(int types=Play_TypeMask); virtual void pauseSounds(int types=Play_TypeMask);

View file

@ -1,5 +1,6 @@
#include "scene.hpp" #include "scene.hpp"
#include <components/nif/nif_file.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp" /// FIXME #include "../mwbase/world.hpp" /// FIXME

View file

@ -31,150 +31,30 @@
#include "../files/constrainedfiledatastream.hpp" #include "../files/constrainedfiledatastream.hpp"
namespace
{
using namespace Ogre; using namespace Ogre;
using namespace Bsa;
struct PathPatternMatcher
{
PathPatternMatcher (char const * pattern) : pattern (pattern)
{
}
bool operator () (char const * input)
{
char const * p = pattern;
char const * i = input;
while (*p && *i)
{
if (*p == '*')
{
++p;
while (*i && *i != *p && *i != '/' && *i != '\\')
++i;
}
else
if (*p == '?')
{
if (*i == '/' || *i == '\\')
break;
++i, ++p;
}
if (*p == '/' || *p == '\\')
{
if (*i != '/' && *i != '\\')
break;
++i, ++p;
}
else
{
if (*i != *p)
break;
++i, ++p;
}
}
return *p == 0 && *i == 0;
}
private:
char const * pattern;
};
struct FileNameGatherer
{
StringVectorPtr ptr;
FileNameGatherer (StringVectorPtr ptr) : ptr (ptr)
{
}
void operator () (std::string const & filename) const
{
ptr->push_back (filename);
}
};
struct FileInfoGatherer
{
Archive const * archive;
FileInfoListPtr ptr;
FileInfoGatherer (Archive const * archive, FileInfoListPtr ptr) :
archive (archive), ptr (ptr)
{
}
void operator () (std::string filename) const
{
FileInfo fi;
std::size_t pt = filename.rfind ('/');
if (pt == std::string::npos)
pt = 0;
fi.archive = const_cast <Archive *> (archive);
fi.path = filename.substr (0, pt);
fi.filename = filename.substr (pt);
fi.compressedSize = fi.uncompressedSize = 0;
ptr->push_back(fi);
}
};
template <typename file_iterator, typename filename_extractor, typename match_handler>
void matchFiles (bool recursive, std::string const & pattern, file_iterator begin, file_iterator end, filename_extractor filenameExtractor, match_handler matchHandler)
{
if (recursive && pattern == "*")
{
for (file_iterator i = begin; i != end; ++i)
matchHandler (filenameExtractor (*i));
}
else
{
PathPatternMatcher matcher (pattern.c_str ());
if (recursive)
{
for (file_iterator i = begin; i != end; ++i)
{
char const * filename = filenameExtractor (*i);
char const * matchable_part = filename;
for (char const * j = matchable_part; *j; ++j)
{
if (*j == '/' || *j == '\\')
matchable_part = j + 1;
}
if (matcher (matchable_part))
matchHandler (filename);
}
}
else
{
for (file_iterator i = begin; i != end; ++i)
{
char const * filename = filenameExtractor (*i);
if (matcher (filename))
matchHandler (filename);
}
}
}
}
static bool fsstrict = false; static bool fsstrict = false;
static char strict_normalize_char(char ch)
{
return ch == '\\' ? '/' : ch;
}
static char nonstrict_normalize_char(char ch)
{
return ch == '\\' ? '/' : std::tolower(ch);
}
template<typename T1, typename T2>
static std::string normalize_path(T1 begin, T2 end)
{
std::string normalized;
normalized.reserve(std::distance(begin, end));
char (*normalize_char)(char) = fsstrict ? &strict_normalize_char : &nonstrict_normalize_char;
std::transform(begin, end, std::back_inserter(normalized), normalize_char);
return normalized;
}
/// An OGRE Archive wrapping a BSAFile archive /// An OGRE Archive wrapping a BSAFile archive
class DirArchive: public Ogre::Archive class DirArchive: public Ogre::Archive
{ {
@ -182,37 +62,12 @@ class DirArchive: public Ogre::Archive
index mIndex; index mIndex;
static char strict_normalize_char(char ch)
{
return ch == '\\' ? '/' : ch;
}
static char nonstrict_normalize_char(char ch)
{
return ch == '\\' ? '/' : std::tolower (ch);
}
static std::string normalize_path (std::string::const_iterator begin, std::string::const_iterator end)
{
std::string normalized;
normalized.reserve (end-begin);
char (*normalize_char) (char) = fsstrict ? &strict_normalize_char : &nonstrict_normalize_char;
std::transform (begin, end, std::back_inserter (normalized), normalize_char);
return normalized;
}
index::const_iterator lookup_filename (std::string const & filename) const index::const_iterator lookup_filename (std::string const & filename) const
{ {
std::string normalized = normalize_path (filename.begin (), filename.end ()); std::string normalized = normalize_path (filename.begin (), filename.end ());
return mIndex.find (normalized); return mIndex.find (normalized);
} }
static char const * extractFilename (index::value_type const & entry)
{
return entry.first.c_str ();
}
public: public:
DirArchive(const String& name) DirArchive(const String& name)
@ -273,15 +128,20 @@ public:
StringVectorPtr find(const String& pattern, bool recursive = true, StringVectorPtr find(const String& pattern, bool recursive = true,
bool dirs = false) bool dirs = false)
{ {
std::string normalizedPattern = normalize_path (pattern.begin (), pattern.end ()); std::string normalizedPattern = normalize_path(pattern.begin(), pattern.end());
StringVectorPtr ptr = StringVectorPtr(new StringVector()); StringVectorPtr ptr = StringVectorPtr(new StringVector());
matchFiles (recursive, normalizedPattern, mIndex.begin (), mIndex.end (), extractFilename, FileNameGatherer (ptr)); for(index::const_iterator iter = mIndex.begin();iter != mIndex.end();iter++)
{
if(Ogre::StringUtil::match(iter->first, normalizedPattern) ||
(recursive && Ogre::StringUtil::match(iter->first, "*/"+normalizedPattern)))
ptr->push_back(iter->first);
}
return ptr; return ptr;
} }
bool exists(const String& filename) bool exists(const String& filename)
{ {
return lookup_filename (filename) != mIndex.end (); return lookup_filename(filename) != mIndex.end ();
} }
time_t getModifiedTime(const String&) { return 0; } time_t getModifiedTime(const String&) { return 0; }
@ -289,21 +149,44 @@ public:
FileInfoListPtr findFileInfo(const String& pattern, bool recursive = true, FileInfoListPtr findFileInfo(const String& pattern, bool recursive = true,
bool dirs = false) const bool dirs = false) const
{ {
std::string normalizedPattern = normalize_path(pattern.begin(), pattern.end());
FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList()); FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList());
FileInfoGatherer gatherer (this, ptr);
std::string normalizedPattern = normalize_path (pattern.begin (), pattern.end ()); index::const_iterator i = mIndex.find(normalizedPattern);
if(i != mIndex.end())
index::const_iterator i = mIndex.find (normalizedPattern);
if (i != mIndex.end ())
{ {
gatherer (i->first); std::string::size_type pt = i->first.rfind('/');
if(pt == std::string::npos)
pt = 0;
FileInfo fi;
fi.archive = const_cast<DirArchive*>(this);
fi.path = i->first.substr(0, pt);
fi.filename = i->first.substr((i->first[pt]=='/') ? pt+1 : pt);
fi.compressedSize = fi.uncompressedSize = 0;
ptr->push_back(fi);
} }
else else
{ {
for(index::const_iterator iter = mIndex.begin();iter != mIndex.end();iter++)
{
if(Ogre::StringUtil::match(iter->first, normalizedPattern) ||
(recursive && Ogre::StringUtil::match(iter->first, "*/"+normalizedPattern)))
{
std::string::size_type pt = iter->first.rfind('/');
if(pt == std::string::npos)
pt = 0;
matchFiles (recursive, normalizedPattern, mIndex.begin (), mIndex.end (), extractFilename, gatherer); FileInfo fi;
fi.archive = const_cast<DirArchive*>(this);
fi.path = iter->first.substr(0, pt);
fi.filename = iter->first.substr((iter->first[pt]=='/') ? pt+1 : pt);
fi.compressedSize = fi.uncompressedSize = 0;
ptr->push_back(fi);
}
}
} }
return ptr; return ptr;
@ -312,9 +195,9 @@ public:
class BSAArchive : public Archive class BSAArchive : public Archive
{ {
BSAFile arc; Bsa::BSAFile arc;
static char const * extractFilename (BSAFile::FileStruct const & entry) static const char *extractFilename(const Bsa::BSAFile::FileStruct &entry)
{ {
return entry.name; return entry.name;
} }
@ -330,13 +213,13 @@ public:
void load() {} void load() {}
void unload() {} void unload() {}
DataStreamPtr open(const String& filename, bool recursive = true) const DataStreamPtr open(const String& filename, bool readonly = true) const
{ {
// Get a non-const reference to arc. This is a hack and it's all // Get a non-const reference to arc. This is a hack and it's all
// OGRE's fault. You should NOT expect an open() command not to // OGRE's fault. You should NOT expect an open() command not to
// have any side effects on the archive, and hence this function // have any side effects on the archive, and hence this function
// should not have been declared const in the first place. // should not have been declared const in the first place.
BSAFile *narc = const_cast<BSAFile*>(&arc); Bsa::BSAFile *narc = const_cast<Bsa::BSAFile*>(&arc);
// Open the file // Open the file
return narc->getFile(filename.c_str()); return narc->getFile(filename.c_str());
@ -360,30 +243,49 @@ public:
return findFileInfo ("*", recursive, dirs); return findFileInfo ("*", recursive, dirs);
} }
// After load() is called, find("*") is called once. It doesn't seem
// to matter that we return an empty list, exists() gets called on
// the correct files anyway.
StringVectorPtr find(const String& pattern, bool recursive = true, StringVectorPtr find(const String& pattern, bool recursive = true,
bool dirs = false) bool dirs = false)
{ {
std::string normalizedPattern = normalize_path(pattern.begin(), pattern.end());
const Bsa::BSAFile::FileList &filelist = arc.getList();
StringVectorPtr ptr = StringVectorPtr(new StringVector()); StringVectorPtr ptr = StringVectorPtr(new StringVector());
matchFiles (recursive, pattern, arc.getList ().begin (), arc.getList ().end (), extractFilename, FileNameGatherer (ptr)); for(Bsa::BSAFile::FileList::const_iterator iter = filelist.begin();iter != filelist.end();iter++)
{
std::string ent = normalize_path(iter->name, iter->name+std::strlen(iter->name));
if(Ogre::StringUtil::match(ent, normalizedPattern) ||
(recursive && Ogre::StringUtil::match(ent, "*/"+normalizedPattern)))
ptr->push_back(iter->name);
}
return ptr; return ptr;
} }
/* Gets called once for each of the ogre formats, *.program,
*.material etc. We ignore all these.
However, it's also called by MyGUI to find individual textures,
and we can't ignore these since many of the GUI textures are
located in BSAs. So instead we channel it through exists() and
set up a single-element result list if the file is found.
*/
FileInfoListPtr findFileInfo(const String& pattern, bool recursive = true, FileInfoListPtr findFileInfo(const String& pattern, bool recursive = true,
bool dirs = false) const bool dirs = false) const
{ {
std::string normalizedPattern = normalize_path(pattern.begin(), pattern.end());
FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList()); FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList());
matchFiles (recursive, pattern, arc.getList ().begin (), arc.getList ().end (), extractFilename, FileInfoGatherer (this, ptr)); const Bsa::BSAFile::FileList &filelist = arc.getList();
for(Bsa::BSAFile::FileList::const_iterator iter = filelist.begin();iter != filelist.end();iter++)
{
std::string ent = normalize_path(iter->name, iter->name+std::strlen(iter->name));
if(Ogre::StringUtil::match(ent, normalizedPattern) ||
(recursive && Ogre::StringUtil::match(ent, "*/"+normalizedPattern)))
{
std::string::size_type pt = ent.rfind('/');
if(pt == std::string::npos)
pt = 0;
FileInfo fi;
fi.archive = const_cast<BSAArchive*>(this);
fi.path = std::string(iter->name, pt);
fi.filename = std::string(iter->name + ((ent[pt]=='/') ? pt+1 : pt));
fi.compressedSize = fi.uncompressedSize = iter->fileSize;
ptr->push_back(fi);
}
}
return ptr; return ptr;
} }
}; };
@ -445,7 +347,6 @@ static void insertDirFactory()
} }
} }
}
namespace Bsa namespace Bsa
{ {