UnknownComponent.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #include "../Precompiled.h"
  4. #include "../Core/Context.h"
  5. #include "../IO/Deserializer.h"
  6. #include "../IO/Log.h"
  7. #include "../IO/Serializer.h"
  8. #include "../Resource/XMLElement.h"
  9. #include "../Resource/JSONValue.h"
  10. #include "../Scene/UnknownComponent.h"
  11. #include "../DebugNew.h"
  12. namespace Urho3D
  13. {
  14. static HashMap<StringHash, String> unknownTypeToName;
  15. static String letters("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
  16. static String GenerateNameFromType(StringHash typeHash)
  17. {
  18. if (unknownTypeToName.Contains(typeHash))
  19. return unknownTypeToName[typeHash];
  20. String test;
  21. // Begin brute-force search
  22. unsigned numLetters = letters.Length();
  23. unsigned combinations = numLetters;
  24. bool found = false;
  25. for (unsigned i = 1; i < 6; ++i)
  26. {
  27. test.Resize(i);
  28. for (unsigned j = 0; j < combinations; ++j)
  29. {
  30. unsigned current = j;
  31. for (unsigned k = 0; k < i; ++k)
  32. {
  33. test[k] = letters[current % numLetters];
  34. current /= numLetters;
  35. }
  36. if (StringHash(test) == typeHash)
  37. {
  38. found = true;
  39. break;
  40. }
  41. }
  42. if (found)
  43. break;
  44. combinations *= numLetters;
  45. }
  46. unknownTypeToName[typeHash] = test;
  47. return test;
  48. }
  49. UnknownComponent::UnknownComponent(Context* context) :
  50. Component(context),
  51. useXML_(false)
  52. {
  53. }
  54. void UnknownComponent::RegisterObject(Context* context)
  55. {
  56. context->RegisterFactory<UnknownComponent>();
  57. }
  58. bool UnknownComponent::Load(Deserializer& source)
  59. {
  60. useXML_ = false;
  61. xmlAttributes_.Clear();
  62. xmlAttributeInfos_.Clear();
  63. // Assume we are reading from a component data buffer, and the type has already been read
  64. unsigned dataSize = source.GetSize() - source.GetPosition();
  65. binaryAttributes_.Resize(dataSize);
  66. return dataSize ? source.Read(&binaryAttributes_[0], dataSize) == dataSize : true;
  67. }
  68. bool UnknownComponent::LoadXML(const XMLElement& source)
  69. {
  70. useXML_ = true;
  71. xmlAttributes_.Clear();
  72. xmlAttributeInfos_.Clear();
  73. binaryAttributes_.Clear();
  74. XMLElement attrElem = source.GetChild("attribute");
  75. while (attrElem)
  76. {
  77. AttributeInfo attr;
  78. attr.mode_ = AM_FILE;
  79. attr.name_ = attrElem.GetAttribute("name");
  80. attr.type_ = VAR_STRING;
  81. if (!attr.name_.Empty())
  82. {
  83. String attrValue = attrElem.GetAttribute("value");
  84. attr.defaultValue_ = String::EMPTY;
  85. xmlAttributeInfos_.Push(attr);
  86. xmlAttributes_.Push(attrValue);
  87. }
  88. attrElem = attrElem.GetNext("attribute");
  89. }
  90. // Fix up pointers to the attributes after all have been read
  91. for (unsigned i = 0; i < xmlAttributeInfos_.Size(); ++i)
  92. xmlAttributeInfos_[i].ptr_ = &xmlAttributes_[i];
  93. return true;
  94. }
  95. bool UnknownComponent::LoadJSON(const JSONValue& source)
  96. {
  97. useXML_ = true;
  98. xmlAttributes_.Clear();
  99. xmlAttributeInfos_.Clear();
  100. binaryAttributes_.Clear();
  101. JSONArray attributesArray = source.Get("attributes").GetArray();
  102. for (unsigned i = 0; i < attributesArray.Size(); i++)
  103. {
  104. const JSONValue& attrVal = attributesArray.At(i);
  105. AttributeInfo attr;
  106. attr.mode_ = AM_FILE;
  107. attr.name_ = attrVal.Get("name").GetString();
  108. attr.type_ = VAR_STRING;
  109. if (!attr.name_.Empty())
  110. {
  111. String attrValue = attrVal.Get("value").GetString();
  112. attr.defaultValue_ = String::EMPTY;
  113. xmlAttributeInfos_.Push(attr);
  114. xmlAttributes_.Push(attrValue);
  115. }
  116. }
  117. // Fix up pointers to the attributes after all have been read
  118. for (unsigned i = 0; i < xmlAttributeInfos_.Size(); ++i)
  119. xmlAttributeInfos_[i].ptr_ = &xmlAttributes_[i];
  120. return true;
  121. }
  122. bool UnknownComponent::Save(Serializer& dest) const
  123. {
  124. if (useXML_)
  125. URHO3D_LOGWARNING("UnknownComponent loaded in XML mode, attributes will be empty for binary save");
  126. // Write type and ID
  127. if (!dest.WriteStringHash(GetType()))
  128. return false;
  129. if (!dest.WriteU32(id_))
  130. return false;
  131. if (!binaryAttributes_.Size())
  132. return true;
  133. else
  134. return dest.Write(&binaryAttributes_[0], binaryAttributes_.Size()) == binaryAttributes_.Size();
  135. }
  136. bool UnknownComponent::SaveXML(XMLElement& dest) const
  137. {
  138. if (dest.IsNull())
  139. {
  140. URHO3D_LOGERROR("Could not save " + GetTypeName() + ", null destination element");
  141. return false;
  142. }
  143. if (!useXML_)
  144. URHO3D_LOGWARNING("UnknownComponent loaded in binary or JSON mode, attributes will be empty for XML save");
  145. // Write type and ID
  146. if (!dest.SetString("type", GetTypeName()))
  147. return false;
  148. if (!dest.SetI32("id", id_))
  149. return false;
  150. for (unsigned i = 0; i < xmlAttributeInfos_.Size(); ++i)
  151. {
  152. XMLElement attrElem = dest.CreateChild("attribute");
  153. attrElem.SetAttribute("name", xmlAttributeInfos_[i].name_);
  154. attrElem.SetAttribute("value", xmlAttributes_[i]);
  155. }
  156. return true;
  157. }
  158. bool UnknownComponent::SaveJSON(JSONValue& dest) const
  159. {
  160. if (!useXML_)
  161. URHO3D_LOGWARNING("UnknownComponent loaded in binary mode, attributes will be empty for JSON save");
  162. // Write type and ID
  163. dest.Set("type", GetTypeName());
  164. dest.Set("id", (int) id_);
  165. JSONArray attributesArray;
  166. attributesArray.Reserve(xmlAttributeInfos_.Size());
  167. for (unsigned i = 0; i < xmlAttributeInfos_.Size(); ++i)
  168. {
  169. JSONValue attrVal;
  170. attrVal.Set("name", xmlAttributeInfos_[i].name_);
  171. attrVal.Set("value", xmlAttributes_[i]);
  172. attributesArray.Push(attrVal);
  173. }
  174. dest.Set("attributes", attributesArray);
  175. return true;
  176. }
  177. void UnknownComponent::SetTypeName(const String& typeName)
  178. {
  179. typeName_ = typeName;
  180. typeHash_ = typeName;
  181. }
  182. void UnknownComponent::SetType(StringHash typeHash)
  183. {
  184. typeName_ = GenerateNameFromType(typeHash);
  185. typeHash_ = typeHash;
  186. }
  187. }