From 857bb42297f92d2fa3f911cfb9e7e2c0d1660558 Mon Sep 17 00:00:00 2001 From: Jordan Milne Date: Wed, 9 Jan 2013 01:44:15 -0400 Subject: [PATCH 1/3] Create a separate scenemanager for each CharacterPreview instance --- apps/openmw/mwgui/inventorywindow.cpp | 2 +- apps/openmw/mwgui/race.cpp | 2 +- apps/openmw/mwrender/characterpreview.cpp | 13 ++++++++++--- apps/openmw/mwrender/characterpreview.hpp | 4 ++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwgui/inventorywindow.cpp b/apps/openmw/mwgui/inventorywindow.cpp index ffb6c5282e..5390f1602e 100644 --- a/apps/openmw/mwgui/inventorywindow.cpp +++ b/apps/openmw/mwgui/inventorywindow.cpp @@ -67,7 +67,7 @@ namespace MWGui setCoord(0, 342, 498, 258); - MWBase::Environment::get().getWorld ()->setupExternalRendering (mPreview); + mPreview.setup(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer(); openContainer(player); diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index d2714fb510..df6c993401 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -106,7 +106,7 @@ void RaceDialog::open() updateSpellPowers(); mPreview = new MWRender::RaceSelectionPreview(); - MWBase::Environment::get().getWorld ()->setupExternalRendering (*mPreview); + mPreview->setup(); mPreview->update (0); const ESM::NPC proto = mPreview->getPrototype(); diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 0a11dc2814..b034e098bc 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -2,6 +2,7 @@ #include +#include #include #include @@ -35,13 +36,18 @@ namespace MWRender } - void CharacterPreview::setup (Ogre::SceneManager *sceneManager) + void CharacterPreview::setup () { - mSceneMgr = sceneManager; + mSceneMgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC); mCamera = mSceneMgr->createCamera (mName); mCamera->setAspectRatio (float(mSizeX) / float(mSizeY)); - mNode = static_cast(mSceneMgr->getRootSceneNode()->getChild("mwRoot"))->createChildSceneNode (); + Ogre::SceneNode* renderRoot = mSceneMgr->getRootSceneNode()->createChildSceneNode("renderRoot"); + + //we do this with mwRoot in renderingManager, do it here too. + renderRoot->pitch(Ogre::Degree(-90)); + + mNode = renderRoot->createChildSceneNode(); mAnimation = new NpcAnimation(mCharacter, mNode, MWWorld::Class::get(mCharacter).getInventoryStore (mCharacter), RV_PlayerPreview); @@ -79,6 +85,7 @@ namespace MWRender //Ogre::TextureManager::getSingleton().remove(mName); mSceneMgr->destroyCamera (mName); delete mAnimation; + Ogre::Root::getSingleton().destroySceneManager(mSceneMgr); } void CharacterPreview::rebuild() diff --git a/apps/openmw/mwrender/characterpreview.hpp b/apps/openmw/mwrender/characterpreview.hpp index 18362d1db6..d07a03be7d 100644 --- a/apps/openmw/mwrender/characterpreview.hpp +++ b/apps/openmw/mwrender/characterpreview.hpp @@ -23,14 +23,14 @@ namespace MWRender class NpcAnimation; - class CharacterPreview : public ExternalRendering + class CharacterPreview { public: CharacterPreview(MWWorld::Ptr character, int sizeX, int sizeY, const std::string& name, Ogre::Vector3 position, Ogre::Vector3 lookAt); virtual ~CharacterPreview(); - virtual void setup (Ogre::SceneManager *sceneManager); + virtual void setup (); virtual void onSetup(); virtual void rebuild(); From 43cd88a24eece09e6f83e586fd3248f4a211636a Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Fri, 4 Jan 2013 00:02:57 -0800 Subject: [PATCH 2/3] include members of BSAArchives in Ogres resource indices --- components/bsa/bsa_archive.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/components/bsa/bsa_archive.cpp b/components/bsa/bsa_archive.cpp index 8380b08388..671744a778 100644 --- a/components/bsa/bsa_archive.cpp +++ b/components/bsa/bsa_archive.cpp @@ -249,6 +249,13 @@ public: //std::cout << "find(" << pattern << ", " << recursive // << ", " << dirs << ")\n"; StringVectorPtr ptr = StringVectorPtr(new StringVector()); + + BSAFile::FileList const & files = arc.getList (); + + if (pattern == "*") + for (BSAFile::FileList::const_iterator i = files.begin (); i != files.end (); ++i) + ptr->push_back (i->name); + return ptr; } From 67491f6c49b37f02ce376053195c73c9929ec76b Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Fri, 4 Jan 2013 09:32:42 -0800 Subject: [PATCH 3/3] reworked DirArchive to improve performance Replaced old file index with a simple map. The map works by storing the file's relative path with path seperators normalized, and in lower case if not in strict mode. Incoming searches are normalized in the same way then the name is searched in the map. The value in the map is the original full path to the file which is then used to created a ConstrainedDataStream. In addition to changing the index, the commonly used Archive methods are implemented so that they don't fall back on the default FileSystemArchive implementations. --- components/bsa/bsa_archive.cpp | 212 +++++++++++++++++---------------- 1 file changed, 112 insertions(+), 100 deletions(-) diff --git a/components/bsa/bsa_archive.cpp b/components/bsa/bsa_archive.cpp index 671744a778..b067c5290b 100644 --- a/components/bsa/bsa_archive.cpp +++ b/components/bsa/bsa_archive.cpp @@ -29,6 +29,8 @@ #include #include "bsa_file.hpp" +#include "../files/constrainedfiledatastream.hpp" + namespace { @@ -60,104 +62,64 @@ public: static bool fsstrict = false; /// An OGRE Archive wrapping a BSAFile archive -class DirArchive: public Ogre::FileSystemArchive +class DirArchive: public Ogre::Archive { - boost::filesystem::path currentdir; - std::map, ciLessBoost> m; - unsigned int cutoff; + typedef std::map index; - bool findFile(const String& filename, std::string& copy) const + index mIndex; + + static char strict_normalize_char(char ch) { - copy = filename; - std::replace(copy.begin(), copy.end(), '\\', '/'); - - if(copy.at(0) == '/') - copy.erase(0, 1); - - if(fsstrict == true) - return true; - - std::string folder; - //int delimiter = 0; - size_t lastSlash = copy.rfind('/'); - if (lastSlash != std::string::npos) - { - folder = copy.substr(0, lastSlash); - //delimiter = lastSlash+1; - } - - std::vector current; - { - std::map,ciLessBoost>::const_iterator found = m.find(folder); - - if (found == m.end()) - { - return false; - } - else - current = found->second; - } - - std::vector::iterator find = std::lower_bound(current.begin(), current.end(), copy, ciLessBoost()); - if (find != current.end() && !ciLessBoost()(copy, current.front())) - { - if (!boost::iequals(copy, *find)) - if ((find = std::find_if(current.begin(), current.end(), pathComparer(copy))) == current.end()) //\todo Check if this line is actually needed - return false; - - copy = *find; - return true; - } - - return false; + return ch == '\\' ? '/' : ch; } - public: + 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 + { + std::string normalized = normalize_path (filename.begin (), filename.end ()); + + return mIndex.find (normalized); + } + +public: DirArchive(const String& name) - : FileSystemArchive(name, "Dir"), currentdir (name) + : Archive(name, "Dir") { - mType = "Dir"; - std::string s = name; - cutoff = s.size() + 1; - if(fsstrict == false) - populateMap(currentdir); + typedef boost::filesystem::recursive_directory_iterator directory_iterator; - } - void populateMap(boost::filesystem::path d){ - //need to cut off first - boost::filesystem::directory_iterator dir_iter(d), dir_end; - std::vector filesind; - for(;dir_iter != dir_end; dir_iter++) - { - if(boost::filesystem::is_directory(*dir_iter)) - populateMap(*dir_iter); - else + directory_iterator end; + + size_t prefix = name.size (); + + if (name.size () > 0 && name [prefix - 1] != '\\' && name [prefix - 1] != '/') + ++prefix; + + for (directory_iterator i (name); i != end; ++i) { - std::string s = dir_iter->path().string(); - std::replace(s.begin(), s.end(), '\\', '/'); + if(boost::filesystem::is_directory (*i)) + continue; - std::string small; - if(cutoff < s.size()) - small = s.substr(cutoff, s.size() - cutoff); - else - small = s.substr(cutoff - 1, s.size() - cutoff); + std::string proper = i->path ().string (); - filesind.push_back(small); + std::string searchable = normalize_path (proper.begin () + prefix, proper.end ()); + + mIndex.insert (std::make_pair (std::move (searchable), std::move (proper))); } } - std::sort(filesind.begin(), filesind.end(), ciLessBoost()); - - std::string small; - std::string original = d.string(); - std::replace(original.begin(), original.end(), '\\', '/'); - if(cutoff < original.size()) - small = original.substr(cutoff, original.size() - cutoff); - else - small = original.substr(cutoff - 1, original.size() - cutoff); - - m[small] = filesind; - } bool isCaseSensitive() const { return fsstrict; } @@ -165,26 +127,76 @@ class DirArchive: public Ogre::FileSystemArchive void load() {} void unload() {} - bool exists(const String& filename) { - std::string copy; - - if (findFile(filename, copy)) - return FileSystemArchive::exists(copy); - - return false; - } - DataStreamPtr open(const String& filename, bool readonly = true) const - { - std::string copy; + { + index::const_iterator i = lookup_filename (filename); - if (findFile(filename, copy)) - return FileSystemArchive::open(copy, readonly); + if (i == mIndex.end ()) + { + std::ostringstream os; + os << "The file '" << filename << "' could not be found."; + throw std::runtime_error (os.str ()); + } - DataStreamPtr p; - return p; - } + return openConstrainedFileDataStream (i->second.c_str ()); + } + StringVectorPtr list(bool recursive = true, bool dirs = false) + { + StringVectorPtr ptr = StringVectorPtr(new StringVector()); + std::cout << "DirArchive<" << getName () << ">::list" << std::endl; + return ptr; + } + + FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false) + { + FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList()); + std::cout << "DirArchive<" << getName () << ">::listFileInfo" << std::endl; + return ptr; + } + + StringVectorPtr find(const String& pattern, bool recursive = true, + bool dirs = false) + { + StringVectorPtr ptr = StringVectorPtr(new StringVector()); + + if (pattern == "*") + for (index::const_iterator i = mIndex.begin (); i != mIndex.end (); ++i) + ptr->push_back (i->first); + + return ptr; + } + + bool exists(const String& filename) + { + return lookup_filename (filename) != mIndex.end (); + } + + time_t getModifiedTime(const String&) { return 0; } + + FileInfoListPtr findFileInfo(const String& pattern, bool recursive = true, + bool dirs = false) const + { + FileInfoListPtr ptr = FileInfoListPtr(new FileInfoList()); + + index::const_iterator i = lookup_filename (pattern); + + if (i != mIndex.end ()) + { + FileInfo fi; + + std::size_t npos = i->first.rfind ('/'); + + fi.archive = this; + fi.filename = npos != -1 ? i->first.substr (npos) : i->first; + fi.path = npos != -1 ? i->first.substr (0, npos) : ""; + fi.compressedSize = fi.uncompressedSize = 0; + + ptr->push_back(fi); + } + + return ptr; + } }; class BSAArchive : public Archive