SpriteSheet2D.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. //
  2. // Copyright (c) 2008-2015 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "../Precompiled.h"
  23. #include "../Core/Context.h"
  24. #include "../Graphics/Texture2D.h"
  25. #include "../IO/Deserializer.h"
  26. #include "../IO/FileSystem.h"
  27. #include "../IO/Log.h"
  28. #include "../Resource/PListFile.h"
  29. #include "../Resource/ResourceCache.h"
  30. #include "../Resource/XMLFile.h"
  31. #include "../Atomic2D/Sprite2D.h"
  32. #include "../Atomic2D/SpriteSheet2D.h"
  33. #include "../DebugNew.h"
  34. namespace Atomic
  35. {
  36. SpriteSheet2D::SpriteSheet2D(Context* context) :
  37. Resource(context)
  38. {
  39. }
  40. SpriteSheet2D::~SpriteSheet2D()
  41. {
  42. }
  43. void SpriteSheet2D::RegisterObject(Context* context)
  44. {
  45. context->RegisterFactory<SpriteSheet2D>();
  46. }
  47. bool SpriteSheet2D::BeginLoad(Deserializer& source)
  48. {
  49. if (GetName().Empty())
  50. SetName(source.GetName());
  51. loadTextureName_.Clear();
  52. spriteMapping_.Clear();
  53. String extension = GetExtension(source.GetName());
  54. if (extension == ".plist")
  55. return BeginLoadFromPListFile(source);
  56. if (extension == ".xml")
  57. return BeginLoadFromXMLFile(source);
  58. LOGERROR("Unsupported file type");
  59. return false;
  60. }
  61. bool SpriteSheet2D::EndLoad()
  62. {
  63. if (loadPListFile_)
  64. return EndLoadFromPListFile();
  65. if (loadXMLFile_)
  66. return EndLoadFromXMLFile();
  67. return false;
  68. }
  69. Sprite2D* SpriteSheet2D::GetSprite(const String& name) const
  70. {
  71. HashMap<String, SharedPtr<Sprite2D> >::ConstIterator i = spriteMapping_.Find(name);
  72. if (i == spriteMapping_.End())
  73. return 0;
  74. return i->second_;
  75. }
  76. void SpriteSheet2D::DefineSprite(const String& name, const IntRect& rectangle, const Vector2& hotSpot, const IntVector2& offset)
  77. {
  78. if (!texture_)
  79. return;
  80. if (GetSprite(name))
  81. return;
  82. SharedPtr<Sprite2D> sprite(new Sprite2D(context_));
  83. sprite->SetName(name);
  84. sprite->SetTexture(texture_);
  85. sprite->SetRectangle(rectangle);
  86. sprite->SetHotSpot(hotSpot);
  87. sprite->SetOffset(offset);
  88. sprite->SetSpriteSheet(this);
  89. spriteMapping_[name] = sprite;
  90. }
  91. bool SpriteSheet2D::BeginLoadFromPListFile(Deserializer& source)
  92. {
  93. loadPListFile_ = new PListFile(context_);
  94. if (!loadPListFile_->Load(source))
  95. {
  96. LOGERROR("Could not load sprite sheet");
  97. loadPListFile_.Reset();
  98. return false;
  99. }
  100. SetMemoryUse(source.GetSize());
  101. const PListValueMap& root = loadPListFile_->GetRoot();
  102. const PListValueMap& metadata = root["metadata"]->GetValueMap();
  103. const String& textureFileName = metadata["realTextureFileName"]->GetString();
  104. // If we're async loading, request the texture now. Finish during EndLoad().
  105. loadTextureName_ = GetParentPath(GetName()) + textureFileName;
  106. if (GetAsyncLoadState() == ASYNC_LOADING)
  107. GetSubsystem<ResourceCache>()->BackgroundLoadResource<Texture2D>(loadTextureName_, true, this);
  108. return true;
  109. }
  110. bool SpriteSheet2D::EndLoadFromPListFile()
  111. {
  112. ResourceCache* cache = GetSubsystem<ResourceCache>();
  113. texture_ = cache->GetResource<Texture2D>(loadTextureName_);
  114. if (!texture_)
  115. {
  116. LOGERROR("Could not load texture " + loadTextureName_);
  117. loadXMLFile_.Reset();
  118. loadTextureName_.Clear();
  119. return false;
  120. }
  121. const PListValueMap& root = loadPListFile_->GetRoot();
  122. const PListValueMap& frames = root["frames"]->GetValueMap();
  123. for (PListValueMap::ConstIterator i = frames.Begin(); i != frames.End(); ++i)
  124. {
  125. String name = i->first_.Split('.')[0];
  126. const PListValueMap& frameInfo = i->second_.GetValueMap();
  127. if (frameInfo["rotated"]->GetBool())
  128. {
  129. LOGWARNING("Rotated sprite is not support now");
  130. continue;
  131. }
  132. IntRect rectangle = frameInfo["frame"]->GetIntRect();
  133. Vector2 hotSpot(0.5f, 0.5f);
  134. IntVector2 offset(0, 0);
  135. IntRect sourceColorRect = frameInfo["sourceColorRect"]->GetIntRect();
  136. if (sourceColorRect.left_ != 0 && sourceColorRect.top_ != 0)
  137. {
  138. offset.x_ = -sourceColorRect.left_;
  139. offset.y_ = -sourceColorRect.top_;
  140. IntVector2 sourceSize = frameInfo["sourceSize"]->GetIntVector2();
  141. hotSpot.x_ = ((float)offset.x_ + sourceSize.x_ / 2) / rectangle.Width();
  142. hotSpot.y_ = 1.0f - ((float)offset.y_ + sourceSize.y_ / 2) / rectangle.Height();
  143. }
  144. DefineSprite(name, rectangle, hotSpot, offset);
  145. }
  146. loadXMLFile_.Reset();
  147. loadTextureName_.Clear();
  148. return true;
  149. }
  150. bool SpriteSheet2D::BeginLoadFromXMLFile(Deserializer& source)
  151. {
  152. loadXMLFile_ = new XMLFile(context_);
  153. if (!loadXMLFile_->Load(source))
  154. {
  155. LOGERROR("Could not load sprite sheet");
  156. loadXMLFile_.Reset();
  157. return false;
  158. }
  159. SetMemoryUse(source.GetSize());
  160. XMLElement rootElem = loadXMLFile_->GetRoot("TextureAtlas");
  161. if (!rootElem)
  162. {
  163. LOGERROR("Invalid sprite sheet");
  164. loadXMLFile_.Reset();
  165. return false;
  166. }
  167. // If we're async loading, request the texture now. Finish during EndLoad().
  168. loadTextureName_ = GetParentPath(GetName()) + rootElem.GetAttribute("imagePath");
  169. if (GetAsyncLoadState() == ASYNC_LOADING)
  170. GetSubsystem<ResourceCache>()->BackgroundLoadResource<Texture2D>(loadTextureName_, true, this);
  171. return true;
  172. }
  173. bool SpriteSheet2D::EndLoadFromXMLFile()
  174. {
  175. ResourceCache* cache = GetSubsystem<ResourceCache>();
  176. texture_ = cache->GetResource<Texture2D>(loadTextureName_);
  177. if (!texture_)
  178. {
  179. LOGERROR("Could not load texture " + loadTextureName_);
  180. loadXMLFile_.Reset();
  181. loadTextureName_.Clear();
  182. return false;
  183. }
  184. XMLElement rootElem = loadXMLFile_->GetRoot("TextureAtlas");
  185. XMLElement subTextureElem = rootElem.GetChild("SubTexture");
  186. while (subTextureElem)
  187. {
  188. String name = subTextureElem.GetAttribute("name");
  189. int x = subTextureElem.GetInt("x");
  190. int y = subTextureElem.GetInt("y");
  191. int width = subTextureElem.GetInt("width");
  192. int height = subTextureElem.GetInt("height");
  193. IntRect rectangle(x, y, x + width, y + height);
  194. Vector2 hotSpot(0.5f, 0.5f);
  195. IntVector2 offset(0, 0);
  196. if (subTextureElem.HasAttribute("frameWidth") && subTextureElem.HasAttribute("frameHeight"))
  197. {
  198. offset.x_ = subTextureElem.GetInt("frameX");
  199. offset.y_ = subTextureElem.GetInt("frameY");
  200. int frameWidth = subTextureElem.GetInt("frameWidth");
  201. int frameHeight = subTextureElem.GetInt("frameHeight");
  202. hotSpot.x_ = ((float)offset.x_ + frameWidth / 2) / width;
  203. hotSpot.y_ = 1.0f - ((float)offset.y_ + frameHeight / 2) / height;
  204. }
  205. DefineSprite(name, rectangle, hotSpot, offset);
  206. subTextureElem = subTextureElem.GetNext("SubTexture");
  207. }
  208. loadXMLFile_.Reset();
  209. loadTextureName_.Clear();
  210. return true;
  211. }
  212. }