From 879ab49e9ccd973400cc37a24b9b7511c245dba0 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 4 Jul 2014 12:46:57 +0200 Subject: [PATCH] added resources manager --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/editor.cpp | 2 + apps/opencs/model/doc/document.cpp | 6 +- apps/opencs/model/doc/document.hpp | 7 +- apps/opencs/model/doc/documentmanager.cpp | 7 +- apps/opencs/model/doc/documentmanager.hpp | 6 ++ apps/opencs/model/world/data.cpp | 11 ++- apps/opencs/model/world/data.hpp | 9 ++- apps/opencs/model/world/resources.cpp | 78 ++++++++++++++++++++ apps/opencs/model/world/resources.hpp | 30 ++++++++ apps/opencs/model/world/resourcesmanager.cpp | 24 ++++++ apps/opencs/model/world/resourcesmanager.hpp | 24 ++++++ apps/opencs/model/world/universalid.cpp | 15 +++- apps/opencs/model/world/universalid.hpp | 19 ++++- 14 files changed, 228 insertions(+), 12 deletions(-) create mode 100644 apps/opencs/model/world/resources.cpp create mode 100644 apps/opencs/model/world/resources.hpp create mode 100644 apps/opencs/model/world/resourcesmanager.cpp create mode 100644 apps/opencs/model/world/resourcesmanager.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index c52f9d9bca..0addaab524 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -24,7 +24,7 @@ opencs_units (model/world opencs_units_noqt (model/world universalid record commands columnbase scriptcontext cell refidcollection - refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection + refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager ) opencs_hdrs_noqt (model/world diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index b003735874..b3513a7f15 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -35,6 +35,8 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit) Bsa::registerResources (Files::Collections (config.first, !mFsStrict), config.second, true, mFsStrict); + mDocumentManager.listResources(); + mNewGame.setLocalData (mLocal); mFileDialog.setLocalData (mLocal); diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index f452008ac9..23a47b3130 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2205,9 +2205,9 @@ void CSMDoc::Document::createBase() CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, bool new_, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, - ToUTF8::FromType encoding) -: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding), mTools (mData), - mResDir(resDir), + ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager) +: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager), + mTools (mData), mResDir(resDir), mProjectPath ((configuration.getUserDataPath() / "projects") / (savePath.filename().string() + ".project")), mSaving (*this, mProjectPath, encoding) diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index a6f8aaae28..d092b47c8a 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -31,6 +31,11 @@ namespace Files class ConfigurationManager; } +namespace CSMWorld +{ + class ResourcesManager; +} + namespace CSMDoc { class Document : public QObject @@ -73,7 +78,7 @@ namespace CSMDoc Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, bool new_, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, - ToUTF8::FromType encoding); + ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager); ~Document(); diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index 4020a8f72c..6953db0edb 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -52,7 +52,7 @@ CSMDoc::DocumentManager::~DocumentManager() void CSMDoc::DocumentManager::addDocument (const std::vector& files, const boost::filesystem::path& savePath, bool new_) { - Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding); + Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager); mDocuments.push_back (document); @@ -85,6 +85,11 @@ void CSMDoc::DocumentManager::setEncoding (ToUTF8::FromType encoding) mEncoding = encoding; } +void CSMDoc::DocumentManager::listResources() +{ + mResourcesManager.listResources(); +} + void CSMDoc::DocumentManager::documentLoaded (Document *document) { emit documentAdded (document); diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index d6824112bb..cebae6f6d4 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -11,6 +11,8 @@ #include +#include "../world/resourcesmanager.hpp" + #include "loader.hpp" namespace Files @@ -31,6 +33,7 @@ namespace CSMDoc QThread mLoaderThread; Loader mLoader; ToUTF8::FromType mEncoding; + CSMWorld::ResourcesManager mResourcesManager; DocumentManager (const DocumentManager&); DocumentManager& operator= (const DocumentManager&); @@ -50,6 +53,9 @@ namespace CSMDoc void setEncoding (ToUTF8::FromType encoding); + /// Ask OGRE for a list of available resources. + void listResources(); + private: boost::filesystem::path mResDir; diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index d07e8784e3..823a14395f 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -15,6 +15,7 @@ #include "columnimp.hpp" #include "regionmap.hpp" #include "columns.hpp" +#include "resourcesmanager.hpp" void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type, bool update) { @@ -56,8 +57,9 @@ int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collec return number; } -CSMWorld::Data::Data (ToUTF8::FromType encoding) -: mEncoder (encoding), mRefs (mCells), mReader (0), mDialogue (0) +CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager) +: mEncoder (encoding), mRefs (mCells), mResourcesManager (resourcesManager), mReader (0), + mDialogue (0) { mGlobals.addColumn (new StringIdColumn); mGlobals.addColumn (new RecordStateColumn); @@ -498,6 +500,11 @@ CSMWorld::IdCollection& CSMWorld::Data::getBodyParts() return mBodyParts; } +const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) const +{ + return mResourcesManager.get (UniversalId::getParentType (id.getType())); +} + QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 9bdb449e0a..cbf13d8b1b 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -47,6 +47,9 @@ namespace ESM namespace CSMWorld { + class ResourcesManager; + class Resources; + class Data : public QObject { Q_OBJECT @@ -73,6 +76,7 @@ namespace CSMWorld RefIdCollection mReferenceables; RefCollection mRefs; IdCollection mFilters; + const ResourcesManager& mResourcesManager; std::vector mModels; std::map mModelIndex; std::string mAuthor; @@ -98,7 +102,7 @@ namespace CSMWorld public: - Data (ToUTF8::FromType encoding); + Data (ToUTF8::FromType encoding, const ResourcesManager& resourcesManager); virtual ~Data(); @@ -186,6 +190,9 @@ namespace CSMWorld IdCollection& getBodyParts(); + /// Throws an exception, if \a id does not match a resources list. + const Resources& getResources (const UniversalId& id) const; + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// diff --git a/apps/opencs/model/world/resources.cpp b/apps/opencs/model/world/resources.cpp new file mode 100644 index 0000000000..c819283e18 --- /dev/null +++ b/apps/opencs/model/world/resources.cpp @@ -0,0 +1,78 @@ + +#include "resources.hpp" + +#include +#include + +#include + +#include + +CSMWorld::Resources::Resources (const std::string& baseDirectory) +: mBaseDirectory (baseDirectory) +{ + int baseSize = mBaseDirectory.size(); + + Ogre::StringVector resourcesGroups = + Ogre::ResourceGroupManager::getSingleton().getResourceGroups(); + + for (Ogre::StringVector::iterator iter (resourcesGroups.begin()); + iter!=resourcesGroups.end(); ++iter) + { + if (*iter=="General" || *iter=="Internal" || *iter=="Autodetect") + continue; + + Ogre::StringVectorPtr resources = + Ogre::ResourceGroupManager::getSingleton().listResourceNames (*iter); + + for (Ogre::StringVector::const_iterator iter (resources->begin()); + iter!=resources->end(); ++iter) + { + if (static_cast (iter->size())>=baseSize+1 && + iter->substr (0, baseSize)==mBaseDirectory && + ((*iter)[baseSize]=='/' || (*iter)[baseSize]=='\\')) + { + std::string file = iter->substr (baseSize+1); + mFiles.push_back (file); + mIndex.insert (std::make_pair (file, static_cast (mFiles.size())-1)); + } + } + } +} + +int CSMWorld::Resources::getSize() const +{ + return mFiles.size(); +} + +std::string CSMWorld::Resources::getId (int index) const +{ + return mFiles.at (index); +} + +int CSMWorld::Resources::getIndex (const std::string& id) const +{ + int index = searchId (id); + + if (index==-1) + { + std::ostringstream stream; + stream << "Invalid resource: " << mBaseDirectory << '/' << id; + + throw std::runtime_error (stream.str().c_str()); + } + + return index; +} + +int CSMWorld::Resources::searchId (const std::string& id) const +{ + std::string id2 = Misc::StringUtils::lowerCase (id); + + std::map::const_iterator iter = mIndex.find (id2); + + if (iter==mIndex.end()) + return -1; + + return iter->second; +} \ No newline at end of file diff --git a/apps/opencs/model/world/resources.hpp b/apps/opencs/model/world/resources.hpp new file mode 100644 index 0000000000..54c4fa8214 --- /dev/null +++ b/apps/opencs/model/world/resources.hpp @@ -0,0 +1,30 @@ +#ifndef CSM_WOLRD_RESOURCES_H +#define CSM_WOLRD_RESOURCES_H + +#include +#include +#include + +namespace CSMWorld +{ + class Resources + { + std::map mIndex; + std::vector mFiles; + std::string mBaseDirectory; + + public: + + Resources (const std::string& baseDirectory); + + int getSize() const; + + std::string getId (int index) const; + + int getIndex (const std::string& id) const; + + int searchId (const std::string& id) const; + }; +} + +#endif diff --git a/apps/opencs/model/world/resourcesmanager.cpp b/apps/opencs/model/world/resourcesmanager.cpp new file mode 100644 index 0000000000..980e099f4b --- /dev/null +++ b/apps/opencs/model/world/resourcesmanager.cpp @@ -0,0 +1,24 @@ + +#include "resourcesmanager.hpp" + +#include + +void CSMWorld::ResourcesManager::listResources() +{ + mResources.insert (std::make_pair (UniversalId::Type_Mesh, "meshes")); + mResources.insert (std::make_pair (UniversalId::Type_Icon, "icons")); + mResources.insert (std::make_pair (UniversalId::Type_Music, "music")); + mResources.insert (std::make_pair (UniversalId::Type_SoundRes, "sound")); + mResources.insert (std::make_pair (UniversalId::Type_Texture, "textures")); + mResources.insert (std::make_pair (UniversalId::Type_Video, "videos")); +} + +const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type type) const +{ + std::map::const_iterator iter = mResources.find (type); + + if (iter==mResources.end()) + throw std::logic_error ("Unknown resource type"); + + return iter->second; +} \ No newline at end of file diff --git a/apps/opencs/model/world/resourcesmanager.hpp b/apps/opencs/model/world/resourcesmanager.hpp new file mode 100644 index 0000000000..e3bbd8a2a3 --- /dev/null +++ b/apps/opencs/model/world/resourcesmanager.hpp @@ -0,0 +1,24 @@ +#ifndef CSM_WOLRD_RESOURCESMANAGER_H +#define CSM_WOLRD_RESOURCESMANAGER_H + +#include + +#include "universalid.hpp" +#include "resources.hpp" + +namespace CSMWorld +{ + class ResourcesManager + { + std::map mResources; + + public: + + /// Ask OGRE for a list of available resources. + void listResources(); + + const Resources& get (UniversalId::Type type) const; + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 3a5f3f0439..2056b0c4c0 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -44,6 +44,12 @@ namespace { CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap, "Region Map", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", 0 }, + { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Meshes, "Meshes", 0 }, + { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Icons, "Icons", 0 }, + { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Musics, "Musics", 0 }, + { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_SoundsRes, "Sounds", 0 }, + { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Textures, "Textures", 0 }, + { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Videos, "Videos", 0 }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; @@ -97,6 +103,12 @@ namespace { CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Enchantment, "Enchantment", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_BodyPart, "Body Part", 0 }, + { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Mesh, "Mesh", 0 }, + { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Icon, "Icon", 0 }, + { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Music, "Music", 0 }, + { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_SoundRes, "Sound", 0 }, + { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Texture, "Texture", 0 }, + { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Video, "Video", 0 }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; @@ -331,7 +343,8 @@ CSMWorld::UniversalId::Type CSMWorld::UniversalId::getParentType (Type type) if (sIdArg[i].mClass==Class_RefRecord) return Type_Referenceables; - if (sIdArg[i].mClass==Class_SubRecord || sIdArg[i].mClass==Class_Record) + if (sIdArg[i].mClass==Class_SubRecord || sIdArg[i].mClass==Class_Record || + sIdArg[i].mClass==Class_Resource) { if (type==Type_Cell_Missing) return Type_Cells; diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index c7514336f1..3d3f215d65 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -22,7 +22,10 @@ namespace CSMWorld Class_RecordList, Class_Collection, // multiple types of records combined Class_Transient, // not part of the world data or the project data - Class_NonRecord // record like data that is not part of the world + Class_NonRecord, // record like data that is not part of the world + Class_Resource, ///< \attention Resource IDs are unique only within the + /// respective collection + Class_ResourceList }; enum ArgumentType @@ -104,7 +107,19 @@ namespace CSMWorld Type_Enchantments, Type_Enchantment, Type_BodyParts, - Type_BodyPart + Type_BodyPart, + Type_Meshes, + Type_Mesh, + Type_Icons, + Type_Icon, + Type_Musics, + Type_Music, + Type_SoundsRes, + Type_SoundRes, + Type_Textures, + Type_Texture, + Type_Videos, + Type_Video }; enum { NumberOfTypes = Type_BodyPart+1 };