1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "Image/BsSpriteTexture.h"
4#include "Private/RTTI/BsSpriteTextureRTTI.h"
5#include "Image/BsTexture.h"
6#include "Resources/BsResources.h"
7#include "Resources/BsBuiltinResources.h"
8#include "CoreThread/BsCoreObjectSync.h"
9
10namespace bs
11{
12 Rect2 SpriteTextureBase::evaluate(float t) const
13 {
14 if(mPlayback == SpriteAnimationPlayback::None)
15 return Rect2(mUVOffset.x, mUVOffset.y, mUVScale.x, mUVScale.y);
16
17 UINT32 row;
18 UINT32 column;
19 getAnimationFrame(t, row, column);
20
21 Rect2 output;
22
23 // Note: These could be pre-calculated
24 output.width = mUVScale.x / mAnimation.numColumns;
25 output.height = mUVScale.y / mAnimation.numRows;
26
27 output.x = mUVOffset.x + column * output.width;
28 output.y = mUVOffset.y + row * output.height;
29
30 return output;
31 }
32
33 void SpriteTextureBase::getAnimationFrame(float t, UINT32& row, UINT32& column) const
34 {
35 if(mPlayback == SpriteAnimationPlayback::None)
36 {
37 row = 0;
38 column = 0;
39
40 return;
41 }
42
43 // Note: Duration could be pre-calculated
44 float duration = 0.0f;
45 if (mAnimation.fps > 0)
46 duration = mAnimation.count / (float)mAnimation.fps;
47
48 switch(mPlayback)
49 {
50 default:
51 case SpriteAnimationPlayback::Normal:
52 t = Math::clamp(t, 0.0f, duration);
53 break;
54 case SpriteAnimationPlayback::Loop:
55 t = Math::repeat(t, duration);
56 break;
57 case SpriteAnimationPlayback::PingPong:
58 t = Math::pingPong(t, duration);
59 break;
60 }
61
62 const float pct = t / duration;
63 UINT32 frame = 0;
64
65 if(mAnimation.count > 0)
66 frame = Math::clamp(Math::floorToPosInt(pct * mAnimation.count), 0U, mAnimation.count - 1);
67
68 row = frame / mAnimation.numColumns;
69 column = frame % mAnimation.numColumns;
70 }
71
72 template <bool Core>
73 template <class P>
74 void TSpriteTexture<Core>::rttiEnumFields(P p)
75 {
76 p(mUVOffset);
77 p(mUVScale);
78 p(mAnimation);
79 p(mPlayback);
80 p(mAtlasTexture);
81 }
82
83 SpriteTexture::SpriteTexture(const Vector2& uvOffset, const Vector2& uvScale, const HTexture& texture)
84 :TSpriteTexture(uvOffset, uvScale, texture)
85 { }
86
87 const HSpriteTexture& SpriteTexture::dummy()
88 {
89 return BuiltinResources::instance().getDummySpriteTexture();
90 }
91
92 bool SpriteTexture::checkIsLoaded(const HSpriteTexture& tex)
93 {
94 return tex != nullptr && tex.isLoaded(false) && tex->getTexture() != nullptr && tex->getTexture().isLoaded(false);
95 }
96
97 void SpriteTexture::setTexture(const HTexture& texture)
98 {
99 removeResourceDependency(mAtlasTexture);
100 mAtlasTexture = texture;
101 addResourceDependency(mAtlasTexture);
102
103 markDependenciesDirty();
104 }
105
106 UINT32 SpriteTexture::getWidth() const
107 {
108 return Math::roundToInt(mAtlasTexture->getProperties().getWidth() * mUVScale.x);
109 }
110
111 UINT32 SpriteTexture::getHeight() const
112 {
113 return Math::roundToInt(mAtlasTexture->getProperties().getHeight() * mUVScale.y);
114 }
115
116 UINT32 SpriteTexture::getFrameWidth() const
117 {
118 return getWidth() / std::max(1U, mAnimation.numColumns);
119 }
120
121 UINT32 SpriteTexture::getFrameHeight() const
122 {
123 return getHeight() / std::max(1U, mAnimation.numRows);
124 }
125
126 void SpriteTexture::_markCoreDirty()
127 {
128 markCoreDirty();
129 }
130
131 void SpriteTexture::initialize()
132 {
133 addResourceDependency(mAtlasTexture);
134 }
135
136 SPtr<ct::CoreObject> SpriteTexture::createCore() const
137 {
138 SPtr<ct::Texture> texturePtr;
139 if(mAtlasTexture.isLoaded())
140 texturePtr = mAtlasTexture->getCore();
141
142 ct::SpriteTexture* spriteTexture = new (bs_alloc<ct::SpriteTexture>()) ct::SpriteTexture(mUVOffset, mUVScale,
143 std::move(texturePtr), mAnimation, mPlayback);
144
145 SPtr<ct::SpriteTexture> spriteTexPtr = bs_shared_ptr<ct::SpriteTexture>(spriteTexture);
146 spriteTexPtr->_setThisPtr(spriteTexPtr);
147
148 return spriteTexPtr;
149 }
150
151 CoreSyncData SpriteTexture::syncToCore(FrameAlloc* allocator)
152 {
153 UINT32 size = coreSyncGetElemSize(*this);
154
155 UINT8* buffer = allocator->alloc(size);
156 char* dataPtr = (char*)buffer;
157 dataPtr = coreSyncWriteElem(*this, dataPtr);
158
159 return CoreSyncData(buffer, size);
160 }
161
162 void SpriteTexture::getCoreDependencies(Vector<CoreObject*>& dependencies)
163 {
164 if (mAtlasTexture.isLoaded())
165 dependencies.push_back(mAtlasTexture.get());
166 }
167
168 SPtr<ct::SpriteTexture> SpriteTexture::getCore() const
169 {
170 return std::static_pointer_cast<ct::SpriteTexture>(mCoreSpecific);
171 }
172
173 HSpriteTexture SpriteTexture::create(const HTexture& texture)
174 {
175 SPtr<SpriteTexture> texturePtr = _createPtr(texture);
176
177 return static_resource_cast<SpriteTexture>(gResources()._createResourceHandle(texturePtr));
178 }
179
180 HSpriteTexture SpriteTexture::create(const Vector2& uvOffset, const Vector2& uvScale, const HTexture& texture)
181 {
182 SPtr<SpriteTexture> texturePtr = _createPtr(uvOffset, uvScale, texture);
183
184 return static_resource_cast<SpriteTexture>(gResources()._createResourceHandle(texturePtr));
185 }
186
187 SPtr<SpriteTexture> SpriteTexture::_createPtr(const HTexture& texture)
188 {
189 SPtr<SpriteTexture> texturePtr = bs_core_ptr<SpriteTexture>
190 (new (bs_alloc<SpriteTexture>()) SpriteTexture(Vector2(0.0f, 0.0f), Vector2(1.0f, 1.0f), texture));
191
192 texturePtr->_setThisPtr(texturePtr);
193 texturePtr->initialize();
194
195 return texturePtr;
196 }
197
198 SPtr<SpriteTexture> SpriteTexture::_createPtr(const Vector2& uvOffset, const Vector2& uvScale, const HTexture& texture)
199 {
200 SPtr<SpriteTexture> texturePtr = bs_core_ptr<SpriteTexture>
201 (new (bs_alloc<SpriteTexture>()) SpriteTexture(uvOffset, uvScale, texture));
202
203 texturePtr->_setThisPtr(texturePtr);
204 texturePtr->initialize();
205
206 return texturePtr;
207 }
208
209 SPtr<SpriteTexture> SpriteTexture::createEmpty()
210 {
211 SPtr<SpriteTexture> texturePtr = bs_core_ptr<SpriteTexture>
212 (new (bs_alloc<SpriteTexture>()) SpriteTexture(Vector2(0.0f, 0.0f), Vector2(1.0f, 1.0f), HTexture()));
213
214 texturePtr->_setThisPtr(texturePtr);
215
216 return texturePtr;
217 }
218
219 RTTITypeBase* SpriteTexture::getRTTIStatic()
220 {
221 return SpriteTextureRTTI::instance();
222 }
223
224 RTTITypeBase* SpriteTexture::getRTTI() const
225 {
226 return SpriteTexture::getRTTIStatic();
227 }
228
229 namespace ct
230 {
231 SpriteTexture::SpriteTexture(const Vector2& uvOffset, const Vector2& uvScale, SPtr<Texture> texture,
232 const SpriteSheetGridAnimation& anim, SpriteAnimationPlayback playback)
233 :TSpriteTexture(uvOffset, uvScale, texture)
234 {
235 mAnimation = anim;
236 mPlayback = playback;
237 }
238
239 void SpriteTexture::syncToCore(const CoreSyncData& data)
240 {
241 char* dataPtr = (char*)data.getBuffer();
242 dataPtr = coreSyncReadElem(*this, dataPtr);
243 }
244 }
245}
246