diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index ef984c0ca..a7809f3e3 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -269,11 +269,11 @@ void CSMDoc::Document::createBase() } } -CSMDoc::Document::Document (const VFS::Manager* vfs, const Files::ConfigurationManager& configuration, +CSMDoc::Document::Document (VFS::Manager* vfs, const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, bool new_, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, const Fallback::Map* fallback, - ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager, + ToUTF8::FromType encoding, CSMWorld::ResourcesManager& resourcesManager, const std::vector& blacklistedScripts) : mVFS(vfs), mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager, fallback, resDir), mTools (*this, encoding), diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 030a0174e..ad0201407 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -59,7 +59,7 @@ namespace CSMDoc private: - const VFS::Manager* mVFS; + VFS::Manager* mVFS; boost::filesystem::path mSavePath; std::vector mContentFiles; bool mNew; @@ -102,11 +102,11 @@ namespace CSMDoc public: - Document (const VFS::Manager* vfs, const Files::ConfigurationManager& configuration, + Document (VFS::Manager* vfs, const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, bool new_, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, const Fallback::Map* fallback, - ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager, + ToUTF8::FromType encoding, CSMWorld::ResourcesManager& resourcesManager, const std::vector& blacklistedScripts); ~Document(); diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index 098d7bad5..11378cab4 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -127,7 +127,7 @@ void CSMDoc::DocumentManager::documentNotLoaded (Document *document, const std:: removeDocument (document); } -void CSMDoc::DocumentManager::setVFS(const VFS::Manager *vfs) +void CSMDoc::DocumentManager::setVFS(VFS::Manager *vfs) { mResourcesManager.setVFS(vfs); mVFS = vfs; diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index ed8e327d7..771afe8e5 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -41,7 +41,7 @@ namespace CSMDoc ToUTF8::FromType mEncoding; CSMWorld::ResourcesManager mResourcesManager; std::vector mBlacklistedScripts; - const VFS::Manager* mVFS; + VFS::Manager* mVFS; DocumentManager (const DocumentManager&); DocumentManager& operator= (const DocumentManager&); @@ -74,7 +74,7 @@ namespace CSMDoc void setBlacklistedScripts (const std::vector& scriptIds); - void setVFS(const VFS::Manager* vfs); + void setVFS(VFS::Manager* vfs); bool isEmpty(); diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index c87e283a8..5c0b2e282 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -259,6 +259,7 @@ void CSMPrefs::State::declare() declareShortcut ("document-character-topicinfos", "Open Topic Info List", QKeySequence()); declareShortcut ("document-character-journalinfos", "Open Journal Info List", QKeySequence()); declareShortcut ("document-character-bodyparts", "Open Body Part List", QKeySequence()); + declareShortcut ("document-assets-reload", "Reload Assets", QKeySequence(Qt::Key_F5)); declareShortcut ("document-assets-sounds", "Open Sound Asset List", QKeySequence()); declareShortcut ("document-assets-soundgens", "Open Sound Generator List", QKeySequence()); declareShortcut ("document-assets-meshes", "Open Mesh Asset List", QKeySequence()); diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index ee9e4329c..8c25faaa5 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -11,6 +11,7 @@ #include #include +#include #include "idtable.hpp" #include "idtree.hpp" @@ -61,7 +62,7 @@ int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collec return number; } -CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager, const Fallback::Map* fallback, const boost::filesystem::path& resDir) +CSMWorld::Data::Data (ToUTF8::FromType encoding, ResourcesManager& resourcesManager, const Fallback::Map* fallback, const boost::filesystem::path& resDir) : mEncoder (encoding), mPathgrids (mCells), mRefs (mCells), mResourcesManager (resourcesManager), mFallbackMap(fallback), mReader (0), mDialogue (0), mReaderIndex(1), mResourceSystem(new Resource::ResourceSystem(resourcesManager.getVFS())) @@ -1215,6 +1216,36 @@ std::vector CSMWorld::Data::getIds (bool listDeleted) const return ids; } +void CSMWorld::Data::assetsChanged() +{ + VFS::Manager* vfs = mResourcesManager.getVFS(); + vfs->rebuildIndex(); + + ResourceTable* meshTable = static_cast(getTableModel(UniversalId::Type_Meshes)); + ResourceTable* iconTable = static_cast(getTableModel(UniversalId::Type_Icons)); + ResourceTable* musicTable = static_cast(getTableModel(UniversalId::Type_Musics)); + ResourceTable* soundResTable = static_cast(getTableModel(UniversalId::Type_SoundsRes)); + ResourceTable* texTable = static_cast(getTableModel(UniversalId::Type_Textures)); + ResourceTable* vidTable = static_cast(getTableModel(UniversalId::Type_Videos)); + + meshTable->beginReset(); + iconTable->beginReset(); + musicTable->beginReset(); + soundResTable->beginReset(); + texTable->beginReset(); + vidTable->beginReset(); + + // Trigger recreation + mResourcesManager.recreateResources(); + + meshTable->endReset(); + iconTable->endReset(); + musicTable->endReset(); + soundResTable->endReset(); + texTable->endReset(); + vidTable->endReset(); +} + void CSMWorld::Data::dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) { if (topLeft.column()<=0) diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index f96003e44..8bc1c4271 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -108,7 +108,7 @@ namespace CSMWorld RefCollection mRefs; IdCollection mFilters; Collection mMetaData; - const ResourcesManager& mResourcesManager; + ResourcesManager& mResourcesManager; const Fallback::Map* mFallbackMap; std::vector mModels; std::map mModelIndex; @@ -140,7 +140,7 @@ namespace CSMWorld public: - Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager, const Fallback::Map* fallback, const boost::filesystem::path& resDir); + Data (ToUTF8::FromType encoding, ResourcesManager& resourcesManager, const Fallback::Map* fallback, const boost::filesystem::path& resDir); virtual ~Data(); @@ -306,6 +306,8 @@ namespace CSMWorld private slots: + void assetsChanged(); + void dataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight); void rowsChanged (const QModelIndex& parent, int start, int end); diff --git a/apps/opencs/model/world/resources.cpp b/apps/opencs/model/world/resources.cpp index 5fe9194d7..5bf0267bb 100644 --- a/apps/opencs/model/world/resources.cpp +++ b/apps/opencs/model/world/resources.cpp @@ -12,6 +12,14 @@ CSMWorld::Resources::Resources (const VFS::Manager* vfs, const std::string& base const char * const *extensions) : mBaseDirectory (baseDirectory), mType (type) { + recreate(vfs, extensions); +} + +void CSMWorld::Resources::recreate(const VFS::Manager* vfs, const char * const *extensions) +{ + mFiles.clear(); + mIndex.clear(); + int baseSize = mBaseDirectory.size(); const std::map& index = vfs->getIndex(); diff --git a/apps/opencs/model/world/resources.hpp b/apps/opencs/model/world/resources.hpp index d6998da9f..5e9872ea8 100644 --- a/apps/opencs/model/world/resources.hpp +++ b/apps/opencs/model/world/resources.hpp @@ -27,6 +27,8 @@ namespace CSMWorld Resources (const VFS::Manager* vfs, const std::string& baseDirectory, UniversalId::Type type, const char * const *extensions = 0); + void recreate(const VFS::Manager* vfs, const char * const *extensions = 0); + int getSize() const; std::string getId (int index) const; diff --git a/apps/opencs/model/world/resourcesmanager.cpp b/apps/opencs/model/world/resourcesmanager.cpp index 016799be3..6b271c276 100644 --- a/apps/opencs/model/world/resourcesmanager.cpp +++ b/apps/opencs/model/world/resourcesmanager.cpp @@ -14,7 +14,7 @@ void CSMWorld::ResourcesManager::addResources (const Resources& resources) resources)); } -void CSMWorld::ResourcesManager::setVFS(const VFS::Manager *vfs) +void CSMWorld::ResourcesManager::setVFS(VFS::Manager *vfs) { mVFS = vfs; mResources.clear(); @@ -31,11 +31,26 @@ void CSMWorld::ResourcesManager::setVFS(const VFS::Manager *vfs) addResources (Resources (vfs, "videos", UniversalId::Type_Video)); } -const VFS::Manager* CSMWorld::ResourcesManager::getVFS() const +VFS::Manager* CSMWorld::ResourcesManager::getVFS() const { return mVFS; } +void CSMWorld::ResourcesManager::recreateResources() +{ + // TODO make this shared with setVFS function + static const char * const sMeshTypes[] = { "nif", "osg", "osgt", "osgb", "osgx", "osg2", 0 }; + + std::map::iterator it = mResources.begin(); + for ( ; it != mResources.end(); ++it) + { + if (it->first == UniversalId::Type_Mesh) + it->second.recreate(mVFS, sMeshTypes); + else + it->second.recreate(mVFS); + } +} + const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type type) const { std::map::const_iterator iter = mResources.find (type); diff --git a/apps/opencs/model/world/resourcesmanager.hpp b/apps/opencs/model/world/resourcesmanager.hpp index 1ce06f2d3..969666856 100644 --- a/apps/opencs/model/world/resourcesmanager.hpp +++ b/apps/opencs/model/world/resourcesmanager.hpp @@ -16,7 +16,7 @@ namespace CSMWorld class ResourcesManager { std::map mResources; - const VFS::Manager* mVFS; + VFS::Manager* mVFS; private: @@ -26,9 +26,11 @@ namespace CSMWorld ResourcesManager(); - const VFS::Manager* getVFS() const; + VFS::Manager* getVFS() const; - void setVFS(const VFS::Manager* vfs); + void setVFS(VFS::Manager* vfs); + + void recreateResources(); const Resources& get (UniversalId::Type type) const; }; diff --git a/apps/opencs/model/world/resourcetable.cpp b/apps/opencs/model/world/resourcetable.cpp index 5227ec3e6..f55f87873 100644 --- a/apps/opencs/model/world/resourcetable.cpp +++ b/apps/opencs/model/world/resourcetable.cpp @@ -154,3 +154,13 @@ int CSMWorld::ResourceTable::getColumnId (int column) const return -1; } + +void CSMWorld::ResourceTable::beginReset() +{ + beginResetModel(); +} + +void CSMWorld::ResourceTable::endReset() +{ + endResetModel(); +} diff --git a/apps/opencs/model/world/resourcetable.hpp b/apps/opencs/model/world/resourcetable.hpp index 88dcc24b0..7d538df53 100644 --- a/apps/opencs/model/world/resourcetable.hpp +++ b/apps/opencs/model/world/resourcetable.hpp @@ -52,7 +52,12 @@ namespace CSMWorld /// Is \a id flagged as deleted? virtual bool isDeleted (const std::string& id) const; - virtual int getColumnId (int column) const; + virtual int getColumnId (int column) const; + + /// Signal Qt that the data is about to change. + void beginReset(); + /// Signal Qt that the data has been changed. + void endReset(); }; } diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index ff49a90fd..92ed07daf 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -284,6 +284,13 @@ void CSVDoc::View::setupAssetsMenu() { QMenu *assets = menuBar()->addMenu (tr ("Assets")); + QAction *reload = new QAction (tr ("Reload"), this); + connect (reload, SIGNAL (triggered()), &mDocument->getData(), SLOT (assetsChanged())); + setupShortcut("document-assets-reload", reload); + assets->addAction (reload); + + assets->addSeparator(); + QAction *sounds = new QAction (tr ("Sounds"), this); connect (sounds, SIGNAL (triggered()), this, SLOT (addSoundsSubView())); setupShortcut("document-assets-sounds", sounds); @@ -889,6 +896,7 @@ void CSVDoc::View::addMetaDataSubView() addSubView (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_MetaData, "sys::meta")); } + void CSVDoc::View::abortOperation (int type) { mDocument->abortOperation (type); diff --git a/components/vfs/archive.hpp b/components/vfs/archive.hpp index b36c7117b..9bdf12c23 100644 --- a/components/vfs/archive.hpp +++ b/components/vfs/archive.hpp @@ -21,6 +21,9 @@ namespace VFS public: virtual ~Archive() {} + /// Clears cached data for archives that may change. + virtual void resetIfNotStatic(){}; + /// List all resources contained in this archive, and run the resource names through the given normalize function. virtual void listResources(std::map& out, char (*normalize_function) (char)) = 0; }; diff --git a/components/vfs/filesystemarchive.cpp b/components/vfs/filesystemarchive.cpp index ad5150a44..9240909ad 100644 --- a/components/vfs/filesystemarchive.cpp +++ b/components/vfs/filesystemarchive.cpp @@ -12,6 +12,12 @@ namespace VFS } + void FileSystemArchive::resetIfNotStatic() + { + mIndex.clear(); + mBuiltIndex = false; + } + void FileSystemArchive::listResources(std::map &out, char (*normalize_function)(char)) { if (!mBuiltIndex) diff --git a/components/vfs/filesystemarchive.hpp b/components/vfs/filesystemarchive.hpp index 6c8e1b82b..16c2d65ea 100644 --- a/components/vfs/filesystemarchive.hpp +++ b/components/vfs/filesystemarchive.hpp @@ -23,6 +23,8 @@ namespace VFS public: FileSystemArchive(const std::string& path); + virtual void resetIfNotStatic(); + virtual void listResources(std::map& out, char (*normalize_function) (char)); diff --git a/components/vfs/manager.cpp b/components/vfs/manager.cpp index 457947d40..037fef325 100644 --- a/components/vfs/manager.cpp +++ b/components/vfs/manager.cpp @@ -57,6 +57,14 @@ namespace VFS (*it)->listResources(mIndex, mStrict ? &strict_normalize_char : &nonstrict_normalize_char); } + void Manager::rebuildIndex() + { + for (std::vector::const_iterator it = mArchives.begin(); it != mArchives.end(); ++it) + (*it)->resetIfNotStatic(); + + buildIndex(); + } + Files::IStreamPtr Manager::get(const std::string &name) const { std::string normalized = name; diff --git a/components/vfs/manager.hpp b/components/vfs/manager.hpp index 6592a65a8..2ad7cf643 100644 --- a/components/vfs/manager.hpp +++ b/components/vfs/manager.hpp @@ -33,6 +33,9 @@ namespace VFS /// Build the file index. Should be called when all archives have been registered. void buildIndex(); + /// Rebuild the file index. New/deleted files (actual files, not bsa's) will be reflected. + void rebuildIndex(); + /// Does a file with this name exist? /// @note May be called from any thread once the index has been built. bool exists(const std::string& name) const;