00001 /*************************************************************************** 00002 * * 00003 * (c) Art Tevs, MPI Informatik Saarbruecken * 00004 * mailto: <tevs@mpi-sb.mpg.de> * 00005 * * 00006 * This program is free software; you can redistribute it and/or modify * 00007 * it under the terms of the GNU General Public License as published by * 00008 * the Free Software Foundation; either version 2 of the License, or * 00009 * (at your option) any later version. * 00010 * * 00011 ***************************************************************************/ 00012 00013 00014 #ifndef _NR_RESOURCE_LOADER_H_ 00015 #define _NR_RESOURCE_LOADER_H_ 00016 00017 00018 //---------------------------------------------------------------------------------- 00019 // Includes 00020 //---------------------------------------------------------------------------------- 00021 #include "Prerequisities.h" 00022 #include "ResourceSystem.h" 00023 #include <boost/enable_shared_from_this.hpp> 00024 00025 namespace nrEngine{ 00026 00027 00028 //! Interface for loading/creating resources 00029 /** 00030 * This is an interface which has to be implemented by each resource loader. 00031 * A resource loader is an object which can load different kind of resources 00032 * from different kind of files. For example there can be a image loader 00033 * which can load PNG, DDS, TGA, .. images and this one can be used to load 00034 * texture resources. In this case you can derive resource loader classes for 00035 * different filetypes from your texture resource loader class or just use 00036 * image loading functions for different types. 00037 * 00038 * Resource loader should be registered by the resource manager. After it is 00039 * registered it will be automaticly used to load files of different types. 00040 * If there is no loader registered for that type, so file will not be loaded, 00041 * error will occurs and empty resource will be used. 00042 * 00043 * Each loader has also to support creating/loading of empty resources. 00044 * By creating of an empty resource it's holder will not hold any resource. 00045 * After you loading the resource it will be initialized with the resource data 00046 * and with the empty resource. 00047 * 00048 * Each loader has a method which says to the manager what kind of resource types 00049 * it supports. By creating of a resource, you should specify the type of to be 00050 * created resource. Manager will look in the database, wich loader can create an instance 00051 * of such a type and will force such a loader to create an instance. 00052 * 00053 * Because only loader does know how to load/unload or create/delete resources 00054 * in/from the memory so it has the full access on the resources. If you remove 00055 * any loader, so all associated resources will be also removed from the memory. 00056 * We need this behaviour also to prevent seg faults by using loaders from plugins, 00057 * which does own own memory. 00058 * 00059 * @note File types and resource types are case sensitive. So *.png and *.PNG are different file types. 00060 * 00061 * \ingroup resource 00062 **/ 00063 class _NRExport IResourceLoader : public boost::enable_shared_from_this<IResourceLoader>{ 00064 public: 00065 00066 /** 00067 * Removing resource loader from the memory, will also remove 00068 * all loaded objects with this loader. 00069 **/ 00070 virtual ~IResourceLoader(); 00071 00072 /** 00073 * This method should create and load a resource from file. The resource does 00074 * know its filename. 00075 * 00076 * @param name Unique name for the resource 00077 * @param group Unique group name for this resource 00078 * @param fileName Name of the file containing the resource 00079 * @param resourceType Unique type name of the resource [optional] 00080 * @param param Define load specific name value pairs. Derived classes 00081 * should know how to handle them. [optional] 00082 * 00083 * @return either OK or an error code 00084 **/ 00085 SharedPtr<IResource> load(const std::string& name, const std::string& group, const std::string& fileName, const std::string& resourceType = std::string(), PropertyList* param = NULL); 00086 00087 /** 00088 * Create an instance of appropriate resource object. Like <code>new ResourceType()</code> 00089 * 00090 * @param name Unique name of the resource 00091 * @param group Unique group name for the resource 00092 * @param resourceType Unique name of the resource type to be created 00093 * @param params Default is NULL, so no parameters. Specify here pairs of string that 00094 * represents the parameters for the creating functions. The derived 00095 * resource loader should know how to handle with them. 00096 * @return Instance of such a resource 00097 * 00098 * NOTE: If a new type of resource will be created, so also a new empty resource 00099 * object will be created of this type. This will be automaticaly registered by the manager. 00100 **/ 00101 SharedPtr<IResource> create(const std::string& name, const std::string& group, const std::string& resourceType, PropertyList* params = NULL); 00102 00103 /** 00104 * This method should return a vector of strings containing information about 00105 * which kind of resource instances can this loader create. Each resource has it's 00106 * unique resource type name. So this vector contains such names. 00107 **/ 00108 NR_FORCEINLINE const std::vector<std::string>& getSupportedResourceTypes(){return mSupportedResourceTypes;} 00109 00110 /** 00111 * This function will return a vector containing information about supported filetypes. 00112 * It means that this loader can load each file of such a filetype. 00113 **/ 00114 NR_FORCEINLINE const std::vector<std::string>& getSupportedFileTypes(){return mSupportedFileTypes;} 00115 00116 /** 00117 * This method will say if this loader does support creating of resource of the given 00118 * resource type. 00119 * 00120 * @param resourceType Unique name of the resource type 00121 * @return <b>true</b> if this loader can create instances of such a type, false otherwise 00122 **/ 00123 bool supportResourceType(const std::string& resourceType) const; 00124 00125 /** 00126 * This method will say if this loader does support loading of resource of the given 00127 * file type. 00128 * 00129 * @param fileType File type name 00130 * @return <b>true</b> if this loader can load such files, false otherwise 00131 **/ 00132 bool supportFileType(const std::string& fileType) const ; 00133 00134 #if 0 00135 /** 00136 * Unload the given resource. Unloading of a resource does not mean that the 00137 * resource is removed from the memory. It just release almost all used 00138 * memory and an empty resource will be used instead. To remove it completly 00139 * from the memory call remove() instead. 00140 * 00141 * This method will be called by the manager or the resource, as soon as a resource must 00142 * be unloaded. 00143 **/ 00144 Result unload(SharedPtr<IResource> resource); 00145 00146 /** 00147 * Reload a certain resource again. A resource object has to be created before. 00148 * If the resource object is loaded, so it will be unloaded and loaded again. Also 00149 * the resource object will be notified about this event, so it can react on this. 00150 * No new instancies will be created. 00151 **/ 00152 Result reload(SharedPtr<IResource> resource); 00153 #endif 00154 /** 00155 * Remove the resource from the memory. This method will be called 00156 * by the resource manager, so the loader can do the stuff needed 00157 * to remove the resource. 00158 **/ 00159 Result remove(SharedPtr<IResource> resource); 00160 00161 protected: 00162 #if 0 00163 /** 00164 * Unload a certain resource from the memory. 00165 * To unload a resource the IResource::unloadRes() method will be called. Herefor 00166 * each resource should know how to release it's data. However you can overwrite 00167 * this method in derived classes to change this default behaviour. 00168 * 00169 * @param res Pointer to the resource which should be unloaded 00170 * 00171 **/ 00172 virtual Result unloadResourceImpl(IResource* res); 00173 00174 /** 00175 * Each derived class has to implement a bahaviour of reloading 00176 * of a resource. This method will be called to reload a given 00177 * resource object from the file again. All according data is already 00178 * stored in the resource only the data from the file must be reloaded. 00179 * 00180 * The default behaviour of this method is to call loadImpl() again 00181 * with the given resource object and a file name (as user parameters the 00182 * NULL will be passed). 00183 * @param res Resource to be reloaded 00184 **/ 00185 virtual Result reloadResourceImpl(IResource* res); 00186 #endif 00187 /** 00188 * Derived classes must overload this function. This method 00189 * should load a resource for a given file name 00190 * 00191 * @param res Resource instance created before with create() 00192 * @param fileName Name of the file containing the resource 00193 * @param param Specific parameters specified by the user 00194 **/ 00195 virtual Result loadResource(IResource* res, const std::string& fileName, PropertyList* param = NULL) = 0; 00196 00197 /** 00198 * Implement this function to provide functionaliy 00199 * of creating resources of certain types. In this function you do not 00200 * have to check whenever the given resourceType string is valid. This 00201 * method can only be called from the base class, which does already 00202 * have checked this. 00203 * @param resourceType Type of the resource 00204 * @param params Parameter list which can be passed for creating 00205 **/ 00206 virtual IResource* createResource(const std::string& resourceType, PropertyList* params = NULL) = 0; 00207 00208 /** 00209 * Creating of an empty resource object. An empty resource object can be used in 00210 * normal way but contains no data. 00211 * 00212 * @param resourceType Unique name of the resource type to be created 00213 * @return Instance of empty resource 00214 **/ 00215 virtual IResource* createEmptyResource(const std::string& resourceType) = 0; 00216 00217 /** 00218 * Call this function to initilize the loader. Usually initialization of the 00219 * loader does declare supported file and resource types. So because this function 00220 * is pure virtual it must overloaded by derived classes. 00221 * 00222 * This method should be called from the constructor, to declare supported types. 00223 **/ 00224 virtual Result initializeResourceLoader() = 0; 00225 00226 /** 00227 * Create instance of the resource loader. 00228 * @param name Unique name of the loader 00229 **/ 00230 IResourceLoader(const std::string& name); 00231 00232 /** 00233 * Map a certain file type to the resource type. Call this method if 00234 * you want to find out resources of which types will be created 00235 * if you use this filetype. 00236 * 00237 * @param fileType Type of the file (ending *.so, *.bmp, ...) 00238 * @return resource type name which will be create for this file type. If 00239 * the given file type is not supported empty string will be given back 00240 **/ 00241 NR_FORCEINLINE std::string mapFileTypeToResourceType(const std::string& fileType) 00242 { 00243 std::map<std::string, std::string>::const_iterator it = mTypeMap.find(fileType); 00244 if (it == mTypeMap.end()) return std::string(); 00245 return it->second; 00246 } 00247 00248 /** 00249 * Declare the mapping of file types to resource types. 00250 * NOTE: You have to specify supported types before 00251 **/ 00252 NR_FORCEINLINE void declareTypeMap(const std::string& fileType, const std::string& resourceType) 00253 { 00254 if (supportResourceType(resourceType) && supportFileType(fileType)) 00255 mTypeMap[fileType] = resourceType; 00256 } 00257 00258 /** 00259 * Internal function which must be called by all derived classes to 00260 * setup all supported resource types. 00261 * @param name Unique name of supported resource type 00262 */ 00263 NR_FORCEINLINE void declareSupportedResourceType(const std::string& name){ 00264 mSupportedResourceTypes.push_back(name); 00265 } 00266 00267 /** 00268 * Internal function which must be called by all derived classes to 00269 * setup all supported file types. 00270 * @param name Unique name of file type which is supported by the derived loader 00271 */ 00272 NR_FORCEINLINE void declareSupportedFileType(const std::string& name) 00273 { 00274 mSupportedFileTypes.push_back(name); 00275 } 00276 00277 #if 0 00278 /** 00279 * This method will return back a proper suffix according to the resource type. 00280 * Derived classes should overwrite this method, because they know which suffix 00281 * are proper to use. The suffix does not contain dot. Empty suffixes are possible. 00282 * @param resType Resource type for which one suffix is generated 00283 **/ 00284 virtual std::string getSuffix(const std::string& resType){return std::string();} 00285 #endif 00286 /** 00287 * Notify the resource loader that a certain resource object 00288 * will be now removed from the memory. The method should be called, 00289 * by the resource manager, to notify the loader. 00290 **/ 00291 void notifyRemoveResource(SharedPtr<IResource>); 00292 00293 #if 0 00294 /** 00295 * Resource will notify the loader that it has been reloaded through 00296 * this method. Resource loader should 00297 **/ 00298 void notifyUnloadResource(SharedPtr<IResource>); 00299 #endif 00300 00301 private: 00302 00303 //! Resource manager can access the methods here 00304 friend class ResourceManager; 00305 00306 //! List of supported resource types 00307 std::vector< std::string > mSupportedResourceTypes; 00308 00309 //! List of supported file types 00310 std::vector< std::string > mSupportedFileTypes; 00311 00312 //! Mapping from file type to resource type 00313 std::map<std::string, std::string> mTypeMap; 00314 00315 //! Unuque name of the loader 00316 std::string mName; 00317 00318 typedef std::list< SharedPtr<IResource> > ResourceList; 00319 00320 //! List of resources managed by this loader 00321 ResourceList mHandledResources; 00322 00323 00324 /** 00325 * Create an instance of appropriate resource object. 00326 **/ 00327 SharedPtr<IResource> create(const std::string& resourceType, PropertyList* params = NULL); 00328 00329 /** 00330 * Get shared pointer from this class 00331 **/ 00332 SharedPtr<IResourceLoader> getSharedPtrFromThis() 00333 { 00334 return shared_from_this(); 00335 } 00336 00337 #if 0 00338 /** 00339 * Notify unload resource. The method can be called either 00340 * from resource manager or by the resource itself 00341 **/ 00342 void notifyUnloadResource(SharedPtr<IResource>); 00343 #endif 00344 }; 00345 00346 }; 00347 00348 #endif