]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CGUISpriteBank.cpp
8f5fb67345e50bea20aa71fab8b225d3ab5916af
[irrlicht.git] / source / Irrlicht / CGUISpriteBank.cpp
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 #include "CGUISpriteBank.h"\r
6 \r
7 #include "IGUIEnvironment.h"\r
8 #include "IVideoDriver.h"\r
9 #include "ITexture.h"\r
10 \r
11 namespace irr\r
12 {\r
13 namespace gui\r
14 {\r
15 \r
16 CGUISpriteBank::CGUISpriteBank(IGUIEnvironment* env) :\r
17         Environment(env), Driver(0)\r
18 {\r
19         #ifdef _DEBUG\r
20         setDebugName("CGUISpriteBank");\r
21         #endif\r
22 \r
23         if (Environment)\r
24         {\r
25                 Driver = Environment->getVideoDriver();\r
26                 if (Driver)\r
27                         Driver->grab();\r
28         }\r
29 }\r
30 \r
31 \r
32 CGUISpriteBank::~CGUISpriteBank()\r
33 {\r
34         // drop textures\r
35         for (u32 i=0; i<Textures.size(); ++i)\r
36                 if (Textures[i])\r
37                         Textures[i]->drop();\r
38 \r
39         // drop video driver\r
40         if (Driver)\r
41                 Driver->drop();\r
42 }\r
43 \r
44 \r
45 core::array< core::rect<s32> >& CGUISpriteBank::getPositions()\r
46 {\r
47         return Rectangles;\r
48 }\r
49 \r
50 \r
51 core::array< SGUISprite >& CGUISpriteBank::getSprites()\r
52 {\r
53         return Sprites;\r
54 }\r
55 \r
56 \r
57 u32 CGUISpriteBank::getTextureCount() const\r
58 {\r
59         return Textures.size();\r
60 }\r
61 \r
62 \r
63 video::ITexture* CGUISpriteBank::getTexture(u32 index) const\r
64 {\r
65         if (index < Textures.size())\r
66                 return Textures[index];\r
67         else\r
68                 return 0;\r
69 }\r
70 \r
71 \r
72 void CGUISpriteBank::addTexture(video::ITexture* texture)\r
73 {\r
74         if (texture)\r
75                 texture->grab();\r
76 \r
77         Textures.push_back(texture);\r
78 }\r
79 \r
80 \r
81 void CGUISpriteBank::setTexture(u32 index, video::ITexture* texture)\r
82 {\r
83         while (index >= Textures.size())\r
84                 Textures.push_back(0);\r
85 \r
86         if (texture)\r
87                 texture->grab();\r
88 \r
89         if (Textures[index])\r
90                 Textures[index]->drop();\r
91 \r
92         Textures[index] = texture;\r
93 }\r
94 \r
95 \r
96 //! clear everything\r
97 void CGUISpriteBank::clear()\r
98 {\r
99         // drop textures\r
100         for (u32 i=0; i<Textures.size(); ++i)\r
101         {\r
102                 if (Textures[i])\r
103                         Textures[i]->drop();\r
104         }\r
105         Textures.clear();\r
106         Sprites.clear();\r
107         Rectangles.clear();\r
108 }\r
109 \r
110 //! Add the texture and use it for a single non-animated sprite.\r
111 s32 CGUISpriteBank::addTextureAsSprite(video::ITexture* texture)\r
112 {\r
113         if ( !texture )\r
114                 return -1;\r
115 \r
116         addTexture(texture);\r
117         u32 textureIndex = getTextureCount() - 1;\r
118 \r
119         u32 rectangleIndex = Rectangles.size();\r
120         Rectangles.push_back( core::rect<s32>(0,0, texture->getOriginalSize().Width, texture->getOriginalSize().Height) );\r
121 \r
122         SGUISprite sprite;\r
123         sprite.frameTime = 0;\r
124 \r
125         SGUISpriteFrame frame;\r
126         frame.textureNumber = textureIndex;\r
127         frame.rectNumber = rectangleIndex;\r
128         sprite.Frames.push_back( frame );\r
129 \r
130         Sprites.push_back( sprite );\r
131 \r
132         return Sprites.size() - 1;\r
133 }\r
134 \r
135 //! draws a sprite in 2d with scale and color\r
136 void CGUISpriteBank::draw2DSprite(u32 index, const core::position2di& pos,\r
137                 const core::rect<s32>* clip, const video::SColor& color,\r
138                 u32 starttime, u32 currenttime, bool loop, bool center)\r
139 {\r
140         if (index >= Sprites.size() || Sprites[index].Frames.empty() )\r
141                 return;\r
142 \r
143         u32 frame = getFrameNr(index, currenttime - starttime, loop);\r
144         const video::ITexture* tex = getTexture(Sprites[index].Frames[frame].textureNumber);\r
145         if (!tex)\r
146                 return;\r
147 \r
148         const u32 rn = Sprites[index].Frames[frame].rectNumber;\r
149         if (rn >= Rectangles.size())\r
150                 return;\r
151 \r
152         const core::rect<s32>& r = Rectangles[rn];\r
153         core::position2di p(pos);\r
154         if (center)\r
155         {\r
156                 p -= r.getSize() / 2;\r
157         }\r
158         Driver->draw2DImage(tex, p, r, clip, color, true);\r
159 }\r
160 \r
161 void CGUISpriteBank::draw2DSprite(u32 index, const core::rect<s32>& destRect,\r
162                 const core::rect<s32>* clip, const video::SColor * const colors,\r
163                 u32 timeTicks, bool loop)\r
164 {\r
165         if (index >= Sprites.size() || Sprites[index].Frames.empty() )\r
166                 return;\r
167 \r
168         u32 frame = getFrameNr(index, timeTicks, loop);\r
169         const video::ITexture* tex = getTexture(Sprites[index].Frames[frame].textureNumber);\r
170         if (!tex)\r
171                 return;\r
172 \r
173         const u32 rn = Sprites[index].Frames[frame].rectNumber;\r
174         if (rn >= Rectangles.size())\r
175                 return;\r
176 \r
177         Driver->draw2DImage(tex, destRect, Rectangles[rn], clip, colors, true);\r
178 }\r
179 \r
180 void CGUISpriteBank::draw2DSpriteBatch( const core::array<u32>& indices,\r
181                                                                                 const core::array<core::position2di>& pos,\r
182                                                                                 const core::rect<s32>* clip,\r
183                                                                                 const video::SColor& color,\r
184                                                                                 u32 starttime, u32 currenttime,\r
185                                                                                 bool loop, bool center)\r
186 {\r
187         const irr::u32 drawCount = core::min_<u32>(indices.size(), pos.size());\r
188 \r
189         if (!getTextureCount())\r
190                 return;\r
191         core::array<SDrawBatch> drawBatches(getTextureCount());\r
192         for (u32 i=0; i < Textures.size(); ++i)\r
193         {\r
194                 drawBatches.push_back(SDrawBatch());\r
195                 drawBatches[i].positions.reallocate(drawCount);\r
196                 drawBatches[i].sourceRects.reallocate(drawCount);\r
197         }\r
198 \r
199         for (u32 i = 0; i < drawCount; ++i)\r
200         {\r
201                 const u32 index = indices[i];\r
202 \r
203                 if (index >= Sprites.size() || Sprites[index].Frames.empty() )\r
204                         continue;\r
205 \r
206                 // work out frame number\r
207                 u32 frame = 0;\r
208                 if (Sprites[index].frameTime)\r
209                 {\r
210                         u32 f = ((currenttime - starttime) / Sprites[index].frameTime);\r
211                         if (loop)\r
212                                 frame = f % Sprites[index].Frames.size();\r
213                         else\r
214                                 frame = (f >= Sprites[index].Frames.size()) ? Sprites[index].Frames.size()-1 : f;\r
215                 }\r
216 \r
217                 const u32 texNum = Sprites[index].Frames[frame].textureNumber;\r
218                 SDrawBatch& currentBatch = drawBatches[texNum];\r
219 \r
220                 const u32 rn = Sprites[index].Frames[frame].rectNumber;\r
221                 if (rn >= Rectangles.size())\r
222                         return;\r
223 \r
224                 const core::rect<s32>& r = Rectangles[rn];\r
225 \r
226                 if (center)\r
227                 {\r
228                         core::position2di p = pos[i];\r
229                         p -= r.getSize() / 2;\r
230 \r
231                         currentBatch.positions.push_back(p);\r
232                         currentBatch.sourceRects.push_back(r);\r
233                 }\r
234                 else\r
235                 {\r
236                         currentBatch.positions.push_back(pos[i]);\r
237                         currentBatch.sourceRects.push_back(r);\r
238                 }\r
239         }\r
240 \r
241         for(u32 i = 0;i < drawBatches.size();i++)\r
242         {\r
243                 if(!drawBatches[i].positions.empty() && !drawBatches[i].sourceRects.empty())\r
244                         Driver->draw2DImageBatch(getTexture(i), drawBatches[i].positions,\r
245                                 drawBatches[i].sourceRects, clip, color, true);\r
246         }\r
247 }\r
248 \r
249 } // namespace gui\r
250 } // namespace irr\r