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
175 dstream<<"DEBUG CODE: Loading base image "
176 "directly to texture"<<std::endl;
177 t = driver->getTexture(path.c_str());
178 driver->renameTexture(t, texture_name.c_str());
182 video::IImage *image = driver->createImageFromFile(path.c_str());
186 dstream<<"WARNING: Could not load image \""<<name
187 <<"\" from path \""<<path<<"\""
188 <<" while building texture"<<std::endl;
192 // If base image is NULL, load as base.
195 dstream<<"Setting "<<name<<" as base"<<std::endl;
197 Copy it this way to get an alpha channel.
198 Otherwise images with alpha cannot be blitted on
199 images that don't have alpha in the original file.
201 // This is a deprecated method
202 //baseimg = driver->createImage(video::ECF_A8R8G8B8, image);
203 core::dimension2d<u32> dim = image->getDimension();
204 baseimg = driver->createImage(video::ECF_A8R8G8B8, dim);
205 image->copyTo(baseimg);
209 // Else blit on base.
212 dstream<<"Blitting "<<name<<" on base"<<std::endl;
213 // Size of the copied area
214 core::dimension2d<u32> dim = image->getDimension();
215 //core::dimension2d<u32> dim(16,16);
216 // Position to copy the blitted to in the base image
217 core::position2d<s32> pos_to(0,0);
218 // Position to copy the blitted from in the blitted image
219 core::position2d<s32> pos_from(0,0);
221 image->copyToWithAlpha(baseimg, pos_to,
222 core::rect<s32>(pos_from, dim),
223 video::SColor(255,255,255,255),
231 // A special texture modification
232 dstream<<"getTextureDirect(): generating \""<<name<<"\""
234 if(name.substr(0,6) == "[crack")
236 u16 progression = stoi(name.substr(6));
237 // Size of the base image
238 core::dimension2d<u32> dim(16, 16);
239 // Size of the crack image
240 //core::dimension2d<u32> dim_crack(16, 16 * CRACK_ANIMATION_LENGTH);
241 // Position to copy the crack to in the base image
242 core::position2d<s32> pos_base(0, 0);
243 // Position to copy the crack from in the crack image
244 core::position2d<s32> pos_other(0, 16 * progression);
246 video::IImage *crackimage = driver->createImageFromFile(
247 porting::getDataPath("crack.png").c_str());
248 crackimage->copyToWithAlpha(baseimg, v2s32(0,0),
249 core::rect<s32>(pos_other, dim),
250 video::SColor(255,255,255,255),
254 else if(name.substr(0,12) == "[progressbar")
256 float value = stof(name.substr(12));
257 make_progressbar(value, baseimg);
261 dstream<<"WARNING: getTextureDirect(): Invalid "
262 " texture: \""<<name<<"\""<<std::endl;
267 // If no resulting image, return NULL
270 dstream<<"getTextureDirect(): baseimg is NULL (attempted to"
271 " create texture \""<<texture_name<<"\""<<std::endl;
275 /*// DEBUG: Paint some pixels
276 video::SColor c(255,255,0,0);
277 baseimg->setPixel(1,1, c);
278 baseimg->setPixel(1,14, c);
279 baseimg->setPixel(14,1, c);
280 baseimg->setPixel(14,14, c);*/
282 // Create texture from resulting image
283 t = driver->addTexture(texture_name.c_str(), baseimg);
286 dstream<<"getTextureDirect(): created texture \""<<texture_name
293 void make_progressbar(float value, video::IImage *image)
298 core::dimension2d<u32> size = image->getDimension();
303 u32 barwidth = size.Width - barpad_x*2;
304 v2u32 barpos(barpad_x, size.Height - barheight - barpad_y);
306 u32 barvalue_i = (u32)(((float)barwidth * value) + 0.5);
308 video::SColor active(255,255,0,0);
309 video::SColor inactive(255,0,0,0);
310 for(u32 x0=0; x0<barwidth; x0++)
317 u32 x = x0 + barpos.X;
318 for(u32 y=barpos.Y; y<barpos.Y+barheight; y++)
320 image->setPixel(x,y, *c);