#pragma once #include "Adept.hpp" #include namespace Adept {class ResourceID;} #if !defined(Spew) void Spew( const char* group, const Adept::ResourceID& id ); #endif namespace GetHashFunctions { unsigned GetHashValue(const Adept::ResourceID &value); } namespace Stuff { bool Close_Enough( const Adept::ResourceID &id1, const Adept::ResourceID &id2, Scalar e = SMALL ); } namespace Adept { class ResourceFile; //########################################################################## //########################## ResourceID ############################## //########################################################################## // // The resource ID holds the file ID and record ID together. It is used // for storing a unique identifier for the resource, and for indexing into // the data structures holding the data. // class ResourceID { public: ResourceID(): m_fileID(-1), m_recordID(0) {} explicit ResourceID(ResourceFile *file); ResourceID(const ResourceID& resource_id): m_fileID(resource_id.m_fileID), m_recordID(resource_id.m_recordID) {} ResourceID( short file_id, WORD record_id ): m_fileID(file_id), m_recordID(record_id) {} bool TestInstance() const {return true;} //Accessor Functions public: short GetFileID() const {return m_fileID;} WORD GetRecordID() const {return m_recordID;} public: ResourceID& operator=(const ResourceID& resource_id) { Check_Pointer(this); Check_Object(&resource_id); m_fileID = resource_id.m_fileID; m_recordID = resource_id.m_recordID; return *this; } bool operator==(const ResourceID& resource_id) const { return m_fileID == resource_id.m_fileID && m_recordID == resource_id.m_recordID; } bool operator!=(const ResourceID& resource_id) const { return m_fileID != resource_id.m_fileID || m_recordID != resource_id.m_recordID; } bool operator>(const ResourceID& resource_id) const { return (m_fileID == resource_id.m_fileID) ? (m_recordID > resource_id.m_recordID) : (m_fileID > resource_id.m_fileID); } bool operator!() const {return operator==(Null);} friend bool Stuff::Close_Enough( const Adept::ResourceID &id1, const Adept::ResourceID &id2, Scalar e ); #if !defined(Spew) friend void ::Spew( const char* group, const ResourceID& resource_id ) { Check_Object(&resource_id); SPEW(( group, "%d:%d+", resource_id.m_fileID, resource_id.m_recordID )); } #endif friend unsigned GetHashFunctions::GetHashValue(const ResourceID &value) { // // Verify that the unsigned is 32 bits wide // Hash value is first 16 bits of m_fileID and first 16 bits of m_recordID // return ((value.m_fileID) << 16 | value.m_recordID); } static ResourceID Null; enum { BuildDependenciesRecordID, FirstFreeRecordID }; short m_fileID; WORD m_recordID; }; //########################################################################## //########################### Resource ############################### //########################################################################## class Resource: public Stuff::MemoryStream { friend class ResourceManager; friend class ResourceFile; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Constructors, Destructors, & Testing // public: // // This constructor is used to provide a return mechanism for building // resources in another function // Resource(); // // These constructors will find the resource and load it // explicit Resource(const ResourceID &resource_id, bool load=true); explicit Resource(const char* name, bool load=false); explicit Resource(const char* name, ResourceFile *resource_file, bool load=false); ~Resource(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Accessors // public: void FindID(const ResourceID &resource_id, bool load=true); void FindName(const char* name, bool load=false); void LoadData(); void UnloadData(); void AbandonData(); int GetDiskOffset(); DWORD GetCompressedSize() { return m_handle.GetRealRecordSize();} void First(ResourceFile *file); bool ReadAndNext(); const ResourceID& GetResourceID() {Check_Object(this); return m_ID;} const char* GetName() {Check_Object(this); return m_handle.m_name;} protected: Stuff::RecordHandle m_handle; ResourceID m_ID; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Building functions // public: bool DoesResourceExist() { Check_Object(this); return m_handle.m_record != NULL && streamSize>0; } bool IsResourceUpToDate(); bool IsRegistered(); void Save( Stuff::MemoryStream *stream, const Stuff::FileDependencies *dependencies ); void ChangeName(const char* new_name); void AddFileDependenciesTo(Stuff::FileDependencies *dependencies); void GetFileDependencies(Stuff::FileDependencies *dependencies); static Stuff::FileDependencies *ParentFileDependencies; }; //########################################################################## //####################### ResourceFile ############################### //########################################################################## class ResourceFile: public Stuff::Plug { friend class ResourceManager; friend class Resource; friend class ResourceID; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Constructors, Destructors, & Testing // public: ResourceFile( Stuff::DatabaseHandle *handle, Stuff::DatabaseHandle *dependency_handle, short file_id, bool does_auto_close ): Plug(DefaultData), m_fileHandle(handle), m_dependencyHandle(dependency_handle), m_fileID(file_id), m_lastRegisteredRecordID(-1), m_doesCloseOnCloseAll(does_auto_close) {Check_Pointer(this);} ~ResourceFile(); void Save(); void SaveAs(const char* filename); void ScatterSave(); void UnloadRecordData(); void SetLastRegisteredResourceID(const ResourceID &res_id); __int64 CalculateCRC(int core_key); __int64 CalculateDateCRC() {Check_Object(this); Check_Object(m_fileHandle); return m_fileHandle->CalculateDateCRC();}; short GetFileID() {Check_Object(this); return m_fileID;} HGOSFILE GetFileHandle() {Check_Object(this); return m_fileHandle->GetFileHandle();} Stuff::MString GetFileName() {Check_Object(this); return m_fileHandle->GetFileName();} bool DoesCloseOnCloseAll() {Check_Object(this); return m_doesCloseOnCloseAll;} protected: Stuff::DatabaseHandle *m_fileHandle, *m_dependencyHandle; WORD m_lastRegisteredRecordID; short m_fileID; bool m_doesCloseOnCloseAll; }; inline ResourceID::ResourceID(ResourceFile *file): m_fileID(file->m_fileID), m_recordID(0) { } //########################################################################## //####################### ResourceManager ############################ //########################################################################## // // The resource manager maintains the list of open resource files, a cache // of recently opened resources, and a file that overrides the static // resources. // class ResourceManager: public Stuff::Plug { friend class Resource; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Constructors, Destructors, & Testing // public: explicit ResourceManager(); ~ResourceManager(); static void TestClass(); static ResourceManager *Instance; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Public Interface // // OpenResourceFile - Opens a resource file of name file_name and gives // it file ID file_ID. The file may be opened in read only mode. If // the file is opened in read/write mode, the current file may be // overwritten. // // Close - Closes a resource file // public: ResourceFile* OpenResourceFile( const char *file_name, const char *dep_file, short file_ID, DWORD content_version, bool core, bool overwrite, bool close_on_close_all = true //This parameter is for the CloseAllButCore Function ); ResourceFile* OpenResourceFile( Stuff::DatabaseHandle *database, short file_ID, bool core, bool close_on_close_all = true //This parameter is for the CloseAllButCore Function ); ResourceFile* OpenResourceFile( Stuff::DatabaseHandle *database, const char *dep_file, short file_ID, DWORD content_version, bool core, bool overwrite, bool close_on_close_all = true //This parameter is for the CloseAllButCore Function ); ResourceFile* OpenResourceFile( Stuff::MemoryStream *stream, const char *file_name, const char *dep_file, short file_ID, DWORD content_version, bool core, bool close_on_close_all = true //This parameter is for the CloseAllButCore Function ); void SaveAll(); void CloseAllButCore(); void SpewLoadedResources(); ResourceFile* GetResourceFile(short file_id) {Check_Object(this); return m_openedFiles.Find(file_id);} short AllocateResourceFileID() {Check_Object(this); return m_nextResourceFileID++;} short FindOpenResourceID(); protected: short m_nextResourceFileID; Stuff::TableOf m_openedFiles; Stuff::ChainOf m_nonCoreFiles; }; } namespace MemoryStreamIO { inline Stuff::MemoryStream& Read( Stuff::MemoryStream *stream, Adept::ResourceID *output ) { Check_Object(stream); return stream->ReadBytes(output, sizeof(*output)); } inline Stuff::MemoryStream& Write( Stuff::MemoryStream *stream, const Adept::ResourceID *input ) { Check_Object(stream); return stream->WriteBytes(input, sizeof(*input)); } }