1 #include "irrlichtwrapper.h"
6 IrrlichtWrapper::IrrlichtWrapper(IrrlichtDevice *device)
9 m_main_thread = get_current_thread_id();
10 m_device_mutex.Init();
14 void IrrlichtWrapper::Run()
19 if(m_get_texture_queue.size() > 0)
21 GetRequest<TextureSpec, video::ITexture*, u8, u8>
22 request = m_get_texture_queue.pop();
24 dstream<<"got texture request with"
25 <<" key.tids[0]="<<request.key.tids[0]
26 <<" [1]="<<request.key.tids[1]
29 GetResult<TextureSpec, video::ITexture*, u8, u8>
31 result.key = request.key;
32 result.callers = request.callers;
33 result.item = getTextureDirect(request.key);
35 request.dest->push_back(result);
39 void IrrlichtWrapper::Shutdown(bool shutdown)
41 m_running = !shutdown;
44 textureid_t IrrlichtWrapper::getTextureId(const std::string &name)
46 u32 id = m_namecache.getId(name);
50 std::string IrrlichtWrapper::getTextureName(textureid_t id)
53 m_namecache.getValue(id, name);
54 // In case it was found, return the name; otherwise return an empty name.
58 video::ITexture* IrrlichtWrapper::getTexture(const std::string &name)
60 TextureSpec spec(getTextureId(name));
61 return getTexture(spec);
64 video::ITexture* IrrlichtWrapper::getTexture(const TextureSpec &spec)
69 video::ITexture *t = m_texturecache.get(spec);
73 if(get_current_thread_id() == m_main_thread)
75 dstream<<"Getting texture directly: spec.tids[0]="
76 <<spec.tids[0]<<std::endl;
78 t = getTextureDirect(spec);
82 // If irrlicht has shut down, just return NULL
83 if(m_running == false)
86 // We're gonna ask the result to be put into here
87 ResultQueue<TextureSpec, video::ITexture*, u8, u8> result_queue;
90 m_get_texture_queue.add(spec, 0, 0, &result_queue);
92 dstream<<"Waiting for texture from main thread: spec.tids[0]="
93 <<spec.tids[0]<<std::endl;
97 // Wait result for a second
98 GetResult<TextureSpec, video::ITexture*, u8, u8>
99 result = result_queue.pop_front(1000);
101 // Check that at least something worked OK
102 assert(result.key == spec);
106 catch(ItemNotFoundException &e)
108 dstream<<"Waiting for texture timed out."<<std::endl;
113 // Add to cache and return
114 m_texturecache.set(spec, t);
118 // Draw a progress bar on the image
119 void make_progressbar(float value, video::IImage *image);
122 Texture fetcher/maker function, called always from the main thread
125 video::ITexture* IrrlichtWrapper::getTextureDirect(const TextureSpec &spec)
127 // This would result in NULL image
131 // Don't generate existing stuff
132 video::ITexture *t = m_texturecache.get(spec);
135 dstream<<"WARNING: Existing stuff requested from "
136 "getTextureDirect()"<<std::endl;
140 video::IVideoDriver* driver = m_device->getVideoDriver();
143 An image will be built from files and then converted into a texture.
145 video::IImage *baseimg = NULL;
148 Irrlicht requires a name for every texture, with which it
149 will be stored internally in irrlicht.
151 std::string texture_name;
153 for(u32 i=0; i<TEXTURE_SPEC_TEXTURE_COUNT; i++)
155 textureid_t tid = spec.tids[i];
159 std::string name = getTextureName(tid);
161 // Add something to the name so that it is a unique identifier.
163 texture_name += name;
168 // A normal texture; load it from a file
169 std::string path = porting::getDataPath(name.c_str());
170 dstream<<"getTextureDirect(): Loading path \""<<path
172 video::IImage *image = driver->createImageFromFile(path.c_str());
176 dstream<<"WARNING: Could not load image \""<<name
177 <<"\" from path \""<<path<<"\""
178 <<" while building texture"<<std::endl;
182 // If base image is NULL, load as base.
185 dstream<<"Setting "<<name<<" as base"<<std::endl;
187 Copy it this way to get an alpha channel.
188 Otherwise images with alpha cannot be blitted on
189 images that don't have alpha in the original file.
191 // This is a deprecated method
192 //baseimg = driver->createImage(video::ECF_A8R8G8B8, image);
193 core::dimension2d<u32> dim = image->getDimension();
194 baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
195 image->copyTo(baseimg);
199 // Else blit on base.
202 dstream<<"Blitting "<<name<<" on base"<<std::endl;
203 // Size of the copied area
204 core::dimension2d<u32> dim = image->getDimension();
205 //core::dimension2d<u32> dim(16,16);
206 // Position to copy the blitted to in the base image
207 core::position2d<s32> pos_to(0,0);
208 // Position to copy the blitted from in the blitted image
209 core::position2d<s32> pos_from(0,0);
211 image->copyToWithAlpha(baseimg, pos_to,
212 core::rect<s32>(pos_from, dim),
213 video::SColor(255,255,255,255),
221 // A special texture modification
222 dstream<<"getTextureDirect(): generating \""<<name<<"\""
224 if(name.substr(0,6) == "[crack")
226 u16 progression = stoi(name.substr(6));
227 // Size of the base image
228 core::dimension2d<u32> dim(16, 16);
229 // Size of the crack image
230 //core::dimension2d<u32> dim_crack(16, 16 * CRACK_ANIMATION_LENGTH);
231 // Position to copy the crack to in the base image
232 core::position2d<s32> pos_base(0, 0);
233 // Position to copy the crack from in the crack image
234 core::position2d<s32> pos_other(0, 16 * progression);
236 video::IImage *crackimage = driver->createImageFromFile(
237 porting::getDataPath("crack.png").c_str());
238 crackimage->copyToWithAlpha(baseimg, v2s32(0,0),
239 core::rect<s32>(pos_other, dim),
240 video::SColor(255,255,255,255),
244 else if(name.substr(0,12) == "[progressbar")
246 float value = stof(name.substr(12));
247 make_progressbar(value, baseimg);
251 dstream<<"WARNING: getTextureDirect(): Invalid "
252 " texture: \""<<name<<"\""<<std::endl;
257 // If no resulting image, return NULL
260 dstream<<"getTextureDirect(): baseimg is NULL (attempted to"
261 " create texture \""<<texture_name<<"\""<<std::endl;
265 /*// DEBUG: Paint some pixels
266 video::SColor c(255,255,0,0);
267 baseimg->setPixel(1,1, c);
268 baseimg->setPixel(1,14, c);
269 baseimg->setPixel(14,1, c);
270 baseimg->setPixel(14,14, c);*/
272 // Create texture from resulting image
273 t = driver->addTexture(texture_name.c_str(), baseimg);
276 dstream<<"getTextureDirect(): created texture \""<<texture_name
283 void make_progressbar(float value, video::IImage *image)
288 core::dimension2d<u32> size = image->getDimension();
293 u32 barwidth = size.Width - barpad_x*2;
294 v2u32 barpos(barpad_x, size.Height - barheight - barpad_y);
296 u32 barvalue_i = (u32)(((float)barwidth * value) + 0.5);
298 video::SColor active(255,255,0,0);
299 video::SColor inactive(255,0,0,0);
300 for(u32 x0=0; x0<barwidth; x0++)
307 u32 x = x0 + barpos.X;
308 for(u32 y=barpos.Y; y<barpos.Y+barheight; y++)
310 image->setPixel(x,y, *c);