Resource.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #include "../Precompiled.h"
  4. #include "../Core/Profiler.h"
  5. #include "../IO/File.h"
  6. #include "../IO/Log.h"
  7. #include "../Resource/Resource.h"
  8. #include "../Resource/XMLElement.h"
  9. namespace Urho3D
  10. {
  11. Resource::Resource(Context* context) :
  12. Object(context),
  13. memoryUse_(0),
  14. asyncLoadState_(ASYNC_DONE)
  15. {
  16. }
  17. bool Resource::Load(Deserializer& source)
  18. {
  19. // Because BeginLoad() / EndLoad() can be called from worker threads, where profiling would be a no-op,
  20. // create a type name -based profile block here
  21. #ifdef URHO3D_TRACY_PROFILING
  22. URHO3D_PROFILE_COLOR(Load, URHO3D_PROFILE_RESOURCE_COLOR);
  23. String profileBlockName("Load" + GetTypeName());
  24. URHO3D_PROFILE_STR(profileBlockName.CString(), profileBlockName.Length());
  25. #elif defined(URHO3D_PROFILING)
  26. String profileBlockName("Load" + GetTypeName());
  27. auto* profiler = GetSubsystem<Profiler>();
  28. if (profiler)
  29. profiler->BeginBlock(profileBlockName.CString());
  30. #endif
  31. // If we are loading synchronously in a non-main thread, behave as if async loading (for example use
  32. // GetTempResource() instead of GetResource() to load resource dependencies)
  33. SetAsyncLoadState(Thread::IsMainThread() ? ASYNC_DONE : ASYNC_LOADING);
  34. bool success = BeginLoad(source);
  35. if (success)
  36. success &= EndLoad();
  37. SetAsyncLoadState(ASYNC_DONE);
  38. #ifdef URHO3D_PROFILING
  39. if (profiler)
  40. profiler->EndBlock();
  41. #endif
  42. return success;
  43. }
  44. bool Resource::BeginLoad(Deserializer& source)
  45. {
  46. // This always needs to be overridden by subclasses
  47. return false;
  48. }
  49. bool Resource::EndLoad()
  50. {
  51. // If no GPU upload step is necessary, no override is necessary
  52. return true;
  53. }
  54. bool Resource::Save(Serializer& dest) const
  55. {
  56. URHO3D_LOGERROR("Save not supported for " + GetTypeName());
  57. return false;
  58. }
  59. bool Resource::LoadFile(const String& fileName)
  60. {
  61. File file(context_);
  62. return file.Open(fileName, FILE_READ) && Load(file);
  63. }
  64. bool Resource::SaveFile(const String& fileName) const
  65. {
  66. File file(context_);
  67. return file.Open(fileName, FILE_WRITE) && Save(file);
  68. }
  69. void Resource::SetName(const String& name)
  70. {
  71. name_ = name;
  72. nameHash_ = name;
  73. }
  74. void Resource::SetMemoryUse(i32 size)
  75. {
  76. assert(size >= 0);
  77. memoryUse_ = size;
  78. }
  79. void Resource::ResetUseTimer()
  80. {
  81. useTimer_.Reset();
  82. }
  83. void Resource::SetAsyncLoadState(AsyncLoadState newState)
  84. {
  85. asyncLoadState_ = newState;
  86. }
  87. unsigned Resource::GetUseTimer()
  88. {
  89. // If more references than the resource cache, return always 0 & reset the timer
  90. if (Refs() > 1)
  91. {
  92. useTimer_.Reset();
  93. return 0;
  94. }
  95. else
  96. return useTimer_.GetMSec(false);
  97. }
  98. void ResourceWithMetadata::AddMetadata(const String& name, const Variant& value)
  99. {
  100. bool exists;
  101. metadata_.Insert(MakePair(StringHash(name), value), exists);
  102. if (!exists)
  103. metadataKeys_.Push(name);
  104. }
  105. void ResourceWithMetadata::RemoveMetadata(const String& name)
  106. {
  107. metadata_.Erase(name);
  108. metadataKeys_.Remove(name);
  109. }
  110. void ResourceWithMetadata::RemoveAllMetadata()
  111. {
  112. metadata_.Clear();
  113. metadataKeys_.Clear();
  114. }
  115. const Urho3D::Variant& ResourceWithMetadata::GetMetadata(const String& name) const
  116. {
  117. const Variant* value = metadata_[name];
  118. return value ? *value : Variant::EMPTY;
  119. }
  120. bool ResourceWithMetadata::HasMetadata() const
  121. {
  122. return !metadata_.Empty();
  123. }
  124. void ResourceWithMetadata::LoadMetadataFromXML(const XMLElement& source)
  125. {
  126. for (XMLElement elem = source.GetChild("metadata"); elem; elem = elem.GetNext("metadata"))
  127. AddMetadata(elem.GetAttribute("name"), elem.GetVariant());
  128. }
  129. void ResourceWithMetadata::LoadMetadataFromJSON(const JSONArray& array)
  130. {
  131. for (const JSONValue& value : array)
  132. AddMetadata(value.Get("name").GetString(), value.GetVariant());
  133. }
  134. void ResourceWithMetadata::SaveMetadataToXML(XMLElement& destination) const
  135. {
  136. for (const String& metadataKey : metadataKeys_)
  137. {
  138. XMLElement elem = destination.CreateChild("metadata");
  139. elem.SetString("name", metadataKey);
  140. elem.SetVariant(GetMetadata(metadataKey));
  141. }
  142. }
  143. void ResourceWithMetadata::CopyMetadata(const ResourceWithMetadata& source)
  144. {
  145. metadata_ = source.metadata_;
  146. metadataKeys_ = source.metadataKeys_;
  147. }
  148. }