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 | |
10 | namespace 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 | |