+ static void set_search_paths(const std::string& paths);
+
+ /**
+ * Get the path to a resource of a given name. This uses the search
+ * path(s) and resources prefixes to locate resource files.
+ * \param name The name or partial path of the resource to find.
+ * \return The full path of the resource.
+ */
+ static std::string find_file(const std::string& name);
+
+ /**
+ * Get the path to a resource of a given name and explicit type. This
+ * uses the search path(s) and resources prefixes to locate resource
+ * files.
+ * \param name The name or partial path of the resource to find.
+ * \param ext The extension is appended to the name if the same
+ * extension is not already a part of name.
+ * \return The full path of the resource.
+ */
+ static std::string
+ find_file(const std::string& name, const std::string& ext);
+
+ /**
+ * Register a type with the extension of files which this type can
+ * load. If any type has already been registered with the given file
+ * extension, it will be replaced.
+ * \param extension The file extension.
+ */
+ template <class T>
+ static void register_type(const std::string& extension,
+ const std::string& prefix = "")
+ {
+ loader_ptr loader(new specific_loader<T>(prefix));
+ call_registry(extension, loader, set);
+ }
+
+ /**
+ * Unregister the type associated with a file extension. Resources of
+ * this type will no longer be loadable, although resources which are
+ * already loaded will remain loaded.
+ * \param extension The file extension.
+ */
+ static void unregister_type(const std::string& extension)
+ {
+ loader_ptr loader;
+ call_registry(extension, loader, set);
+ }
+
+ /**
+ * Find and load a resource by name or path.
+ * \param name The name or partial path of the resource. This should
+ * include the extension so that the correct loader can be chosen.
+ * \return The resource.
+ */
+ static resource_ptr load(const std::string& name);
+
+ /**
+ * Find and load a resource by name or path.
+ * \param name The name or partial path of the resource. This should
+ * include the extension so that the correct loader can be chosen.
+ * \param
+ * \return The resource.
+ */
+ static resource_ptr
+ load(const std::string& name, const std::string& ext);
+
+ /**
+ * Reload the resource data. This will cause the resource file to be
+ * reread, and the underlying resource data will change.
+ */
+ void reload();
+
+ /**
+ * Get the path of file from which this resource was loaded.
+ * \return The path.
+ */
+ std::string path() const
+ {
+ return path_;
+ }
+
+ /**
+ * Reloads some resources which have been modified on disk since they
+ * were loaded. Hotloading must have been enabled at compile-time.
+ * \return The number of resources reloaded.
+ */
+ static int reload_as_needed();
+
+ /**
+ * Get whether or not the type of the underlying resource data matches
+ * an expected type.
+ * \return True if the types match, false otherwise.
+ */
+ template <class T>
+ bool check() const
+ {
+ return *typeinfo_ == typeid(T);
+ }
+
+ /**
+ * Get a pointer to the underlying resource data as long as the type of
+ * the resource data matches the expected type.
+ * \return The resource data, or null if there is a type mismatch.
+ */
+ template <class T>
+ T* get() const
+ {
+ if (check<T>()) return (T*)resource_;
+ return 0;
+ }
+
+ /**
+ * Deconstruct a resource container.
+ */
+ virtual ~resource();
+
+private:
+
+ template <class T>
+ explicit resource(T* ptr) :
+ resource_(ptr),
+ typeinfo_(const_cast<std::type_info*>(&typeid(T))),
+ unloader_(new specific_unloader<T>(ptr)),
+ wd_(-1) {}
+
+ static resource_ptr
+ load_with_path(const std::string& path, const std::string& extension);
+
+ class loader
+ {
+ public:
+
+ loader(const std::string& prefix) :
+ prefix_(prefix) {}
+
+ virtual ~loader() {}
+
+ virtual resource* load(const std::string& path)
+ {
+ return 0;
+ }
+
+ const std::string& prefix() const
+ {
+ return prefix_;
+ }
+
+ private:
+
+ std::string prefix_;
+ };
+
+ typedef boost::shared_ptr<loader> loader_ptr;
+
+ template <class T>
+ class specific_loader : public loader
+ {
+ public:
+
+ specific_loader(const std::string& prefix) :
+ loader(prefix) {}
+
+ virtual resource* load(const std::string& path)
+ {
+ return new resource(new T(path));
+ }
+ };
+
+ class unloader
+ {
+ public:
+
+ virtual ~unloader() {};
+ };
+
+ typedef boost::shared_ptr<unloader> unloader_ptr;
+
+ template <class T>
+ class specific_unloader : public unloader
+ {
+ public:
+
+ specific_unloader(T* object = 0) :
+ object_(object) {}
+
+ virtual ~specific_unloader()
+ {
+ delete object_;
+ }
+
+ private:
+
+ T* object_;
+ };
+
+ enum registry_action
+ {
+ lookup,
+ set
+ };
+
+ static bool call_registry(const std::string& extension,
+ loader_ptr& loader, registry_action action);
+
+ void* resource_;
+ std::type_info* typeinfo_;
+ unloader_ptr unloader_;
+ int wd_;
+ std::string path_;
+ std::string type_;
+};
+
+
+/**
+ * The resource handle class provides a nicer way to work with resources.
+ * It allows you to work with a resource pointer as if you already know the
+ * type of the resource.
+ */
+template <class T>
+class resource_handle
+{
+public:
+
+ /**
+ * Construct a null resource handle.
+ */
+ resource_handle() {}