// // Copyright (c) 2008-2017 the Urho3D project. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // #pragma once #include "../Core/Object.h" #include "../Core/Timer.h" #include "../Resource/JSONValue.h" namespace Atomic { class Deserializer; class Serializer; class XMLElement; /// Asynchronous loading state of a resource. enum AsyncLoadState { /// No async operation in progress. ASYNC_DONE = 0, /// Queued for asynchronous loading. ASYNC_QUEUED = 1, /// In progress of calling BeginLoad() in a worker thread. ASYNC_LOADING = 2, /// BeginLoad() succeeded. EndLoad() can be called in the main thread. ASYNC_SUCCESS = 3, /// BeginLoad() failed. ASYNC_FAIL = 4 }; /// Base class for resources. class ATOMIC_API Resource : public Object { ATOMIC_OBJECT(Resource, Object); public: /// Construct. Resource(Context* context); /// Load resource synchronously. Call both BeginLoad() & EndLoad() and return true if both succeeded. bool Load(Deserializer& source); /// Load resource from stream. May be called from a worker thread. Return true if successful. virtual bool BeginLoad(Deserializer& source); /// Finish resource loading. Always called from the main thread. Return true if successful. virtual bool EndLoad(); /// Save resource. Return true if successful. virtual bool Save(Serializer& dest) const; /// Load resource from file. bool LoadFile(const String& fileName); /// Save resource to file. virtual bool SaveFile(const String& fileName) const; /// Set name. void SetName(const String& name); /// Set memory use in bytes, possibly approximate. void SetMemoryUse(unsigned size); /// Reset last used timer. void ResetUseTimer(); /// Set the asynchronous loading state. Called by ResourceCache. Resources in the middle of asynchronous loading are not normally returned to user. void SetAsyncLoadState(AsyncLoadState newState); /// Return name. const String& GetName() const { return name_; } /// Return name hash. StringHash GetNameHash() const { return nameHash_; } /// Return memory use in bytes, possibly approximate. unsigned GetMemoryUse() const { return memoryUse_; } /// Return time since last use in milliseconds. If referred to elsewhere than in the resource cache, returns always zero. unsigned GetUseTimer(); /// Return the asynchronous loading state. AsyncLoadState GetAsyncLoadState() const { return asyncLoadState_; } private: /// Name. String name_; /// Name hash. StringHash nameHash_; /// Last used timer. Timer useTimer_; /// Memory use in bytes. unsigned memoryUse_; /// Asynchronous loading state. AsyncLoadState asyncLoadState_; }; /// Base class for resources that support arbitrary metadata stored. Metadata serialization shall be implemented in derived classes. class ATOMIC_API ResourceWithMetadata : public Resource { ATOMIC_OBJECT(ResourceWithMetadata, Resource); public: /// Construct. ResourceWithMetadata(Context* context) : Resource(context) {} /// Add new metadata variable or overwrite old value. void AddMetadata(const String& name, const Variant& value); /// Remove metadata variable. void RemoveMetadata(const String& name); /// Remove all metadata variables. void RemoveAllMetadata(); /// Return metadata variable. const Variant& GetMetadata(const String& name) const; /// Return whether the resource has metadata. bool HasMetadata() const; protected: /// Load metadata from children of XML element. void LoadMetadataFromXML(const XMLElement& source); /// Load metadata from JSON array.float void LoadMetadataFromJSON(const JSONArray& array); /// Save as children of XML element. void SaveMetadataToXML(XMLElement& destination) const; /// Copy metadata from another resource. void CopyMetadata(const ResourceWithMetadata& source); private: /// Animation metadata variables. VariantMap metadata_; /// Animation metadata keys. StringVector metadataKeys_; }; inline const String& GetResourceName(Resource* resource) { return resource ? resource->GetName() : String::EMPTY; } inline StringHash GetResourceType(Resource* resource, StringHash defaultType) { return resource ? resource->GetType() : defaultType; } inline ResourceRef GetResourceRef(Resource* resource, StringHash defaultType) { return ResourceRef(GetResourceType(resource, defaultType), GetResourceName(resource)); } template Vector GetResourceNames(const Vector >& resources) { Vector ret(resources.Size()); for (unsigned i = 0; i < resources.Size(); ++i) ret[i] = GetResourceName(resources[i]); return ret; } template ResourceRefList GetResourceRefList(const Vector >& resources) { return ResourceRefList(T::GetTypeStatic(), GetResourceNames(resources)); } }