]> git.lizzy.rs Git - dragonfireclient.git/blob - src/irrlichtwrapper.cpp
30de6846cf501f73c02aacc29b99128a5d60b80e
[dragonfireclient.git] / src / irrlichtwrapper.cpp
1 #include "irrlichtwrapper.h"
2
3 IrrlichtWrapper::IrrlichtWrapper(IrrlichtDevice *device)
4 {
5         m_main_thread = get_current_thread_id();
6         m_device_mutex.Init();
7         m_device = device;
8 }
9
10 void IrrlichtWrapper::Run()
11 {
12         /*
13                 Fetch textures
14         */
15         if(m_get_texture_queue.size() > 0)
16         {
17                 GetRequest<TextureSpec, video::ITexture*, u8, u8>
18                                 request = m_get_texture_queue.pop();
19
20                 dstream<<"got texture request with key.name="
21                                 <<request.key.name<<std::endl;
22
23                 GetResult<TextureSpec, video::ITexture*, u8, u8>
24                                 result;
25                 result.key = request.key;
26                 result.callers = request.callers;
27                 result.item = getTextureDirect(request.key);
28
29                 request.dest->push_back(result);
30         }
31 }
32
33 video::ITexture* IrrlichtWrapper::getTexture(TextureSpec spec)
34 {
35         video::ITexture *t = m_texturecache.get(spec.name);
36         if(t != NULL)
37                 return t;
38         
39         if(get_current_thread_id() == m_main_thread)
40         {
41                 dstream<<"Getting texture directly: name="
42                                 <<spec.name<<std::endl;
43                                 
44                 t = getTextureDirect(spec);
45         }
46         else
47         {
48                 // We're gonna ask the result to be put into here
49                 ResultQueue<TextureSpec, video::ITexture*, u8, u8> result_queue;
50                 
51                 // Throw a request in
52                 m_get_texture_queue.add(spec, 0, 0, &result_queue);
53                 
54                 dstream<<"Waiting for texture from main thread: "
55                                 <<spec.name<<std::endl;
56                 
57                 try
58                 {
59                         // Wait result for a second
60                         GetResult<TextureSpec, video::ITexture*, u8, u8>
61                                         result = result_queue.pop_front(1000);
62                 
63                         // Check that at least something worked OK
64                         assert(result.key.name == spec.name);
65
66                         t = result.item;
67                 }
68                 catch(ItemNotFoundException &e)
69                 {
70                         dstream<<"Waiting for texture timed out."<<std::endl;
71                         t = NULL;
72                 }
73         }
74
75         // Add to cache and return
76         m_texturecache.set(spec.name, t);
77         return t;
78 }
79
80 video::ITexture* IrrlichtWrapper::getTexture(const std::string &path)
81 {
82         return getTexture(TextureSpec(path, path, NULL));
83 }
84
85 /*
86         Non-thread-safe functions
87 */
88
89 video::ITexture* IrrlichtWrapper::getTextureDirect(TextureSpec spec)
90 {
91         video::IVideoDriver* driver = m_device->getVideoDriver();
92         
93         if(spec.mod == NULL)
94         {
95                 dstream<<"IrrlichtWrapper::getTextureDirect: Loading texture "
96                                 <<spec.path<<std::endl;
97                 return driver->getTexture(spec.path.c_str());
98         }
99
100         dstream<<"IrrlichtWrapper::getTextureDirect: Loading and modifying "
101                         "texture "<<spec.path<<" to make "<<spec.name<<std::endl;
102
103         video::ITexture *base = driver->getTexture(spec.path.c_str());
104         video::ITexture *result = spec.mod->make(base, spec.name.c_str(), driver);
105
106         delete spec.mod;
107         
108         return result;
109 }
110
111 video::ITexture * CrackTextureMod::make(video::ITexture *original,
112                 const char *newname, video::IVideoDriver* driver)
113 {
114         core::dimension2d<u32> dim(16, 16);
115         core::position2d<s32> pos_base(0, 0);
116         core::position2d<s32> pos_other(0, 16 * progression);
117
118         video::IImage *baseimage = driver->createImage(original, pos_base, dim);
119         assert(baseimage);
120         
121         video::ITexture *other = driver->getTexture("../data/crack.png");
122         // We have to get the whole texture because getting a smaller area
123         // messes the whole thing. It is probably a bug in Irrlicht.
124         video::IImage *otherimage = driver->createImage(
125                         other, core::position2d<s32>(0,0), other->getSize());
126
127         assert(otherimage);
128         
129         /*core::rect<s32> clip_rect(v2s32(0,0), dim);
130         otherimage->copyToWithAlpha(baseimage, v2s32(0,0),
131                         core::rect<s32>(pos_other, dim),
132                         video::SColor(255,255,255,255),
133                         &clip_rect);*/
134         
135         otherimage->copyToWithAlpha(baseimage, v2s32(0,0),
136                         core::rect<s32>(pos_other, dim),
137                         video::SColor(255,255,255,255),
138                         NULL);
139         
140         otherimage->drop();
141
142         video::ITexture *newtexture = driver->addTexture(newname, baseimage);
143
144         baseimage->drop();
145
146         return newtexture;
147 }
148
149 video::ITexture * ProgressBarTextureMod::make(video::ITexture *original,
150                 const char *newname, video::IVideoDriver* driver)
151 {
152         core::position2d<s32> pos_base(0, 0);
153         core::dimension2d<u32> dim = original->getOriginalSize();
154
155         video::IImage *baseimage = driver->createImage(original, pos_base, dim);
156         assert(baseimage);
157         
158         core::dimension2d<u32> size = baseimage->getDimension();
159
160         u32 barheight = 1;
161         u32 barpad_x = 1;
162         u32 barpad_y = 1;
163         u32 barwidth = size.Width - barpad_x*2;
164         v2u32 barpos(barpad_x, size.Height - barheight - barpad_y);
165
166         u32 barvalue_i = (u32)(((float)barwidth * value) + 0.5);
167
168         video::SColor active(255,255,0,0);
169         video::SColor inactive(255,0,0,0);
170         for(u32 x0=0; x0<barwidth; x0++)
171         {
172                 video::SColor *c;
173                 if(x0 < barvalue_i)
174                         c = &active;
175                 else
176                         c = &inactive;
177                 u32 x = x0 + barpos.X;
178                 for(u32 y=barpos.Y; y<barpos.Y+barheight; y++)
179                 {
180                         baseimage->setPixel(x,y, *c);
181                 }
182         }
183         
184         video::ITexture *newtexture = driver->addTexture(newname, baseimage);
185
186         baseimage->drop();
187
188         return newtexture;
189 }
190