]> git.lizzy.rs Git - dragonfireclient.git/blob - src/hud.cpp
2d22f963c02482890b6222e6e5a05e0c8be07fcb
[dragonfireclient.git] / src / hud.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4 Copyright (C) 2010-2013 blue42u, Jonathon Anderson <anderjon@umail.iu.edu>
5 Copyright (C) 2010-2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22 #include "hud.h"
23 #include "settings.h"
24 #include "util/numeric.h"
25 #include "log.h"
26 #include "gamedef.h"
27 #include "itemdef.h"
28 #include "inventory.h"
29 #include "client/tile.h"
30 #include "localplayer.h"
31 #include "camera.h"
32 #include "porting.h"
33 #include "fontengine.h"
34 #include "guiscalingfilter.h"
35 #include <IGUIStaticText.h>
36
37 #ifdef HAVE_TOUCHSCREENGUI
38 #include "touchscreengui.h"
39 #endif
40
41 Hud::Hud(video::IVideoDriver *driver, scene::ISceneManager* smgr,
42                 gui::IGUIEnvironment* guienv, IGameDef *gamedef, LocalPlayer *player,
43                 Inventory *inventory) {
44         this->driver      = driver;
45         this->smgr        = smgr;
46         this->guienv      = guienv;
47         this->gamedef     = gamedef;
48         this->player      = player;
49         this->inventory   = inventory;
50
51         m_screensize       = v2u32(0, 0);
52         m_displaycenter    = v2s32(0, 0);
53         m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE * porting::getDisplayDensity() + 0.5);
54         m_hotbar_imagesize *= g_settings->getFloat("hud_scaling");
55         m_padding = m_hotbar_imagesize / 12;
56
57         const video::SColor hbar_color(255, 255, 255, 255);
58         for (unsigned int i=0; i < 4; i++ ){
59                 hbar_colors[i] = hbar_color;
60         }
61
62         tsrc = gamedef->getTextureSource();
63
64         v3f crosshair_color = g_settings->getV3F("crosshair_color");
65         u32 cross_r = rangelim(myround(crosshair_color.X), 0, 255);
66         u32 cross_g = rangelim(myround(crosshair_color.Y), 0, 255);
67         u32 cross_b = rangelim(myround(crosshair_color.Z), 0, 255);
68         u32 cross_a = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255);
69         crosshair_argb = video::SColor(cross_a, cross_r, cross_g, cross_b);
70
71         v3f selectionbox_color = g_settings->getV3F("selectionbox_color");
72         u32 sbox_r = rangelim(myround(selectionbox_color.X), 0, 255);
73         u32 sbox_g = rangelim(myround(selectionbox_color.Y), 0, 255);
74         u32 sbox_b = rangelim(myround(selectionbox_color.Z), 0, 255);
75         selectionbox_argb = video::SColor(255, sbox_r, sbox_g, sbox_b);
76
77         use_crosshair_image = tsrc->isKnownSourceImage("crosshair.png");
78
79         hotbar_image = "";
80         use_hotbar_image = false;
81         hotbar_selected_image = "";
82         use_hotbar_selected_image = false;
83 }
84
85 void Hud::drawItem(const ItemStack &item, const core::rect<s32>& rect,
86                 bool selected)
87 {
88         if (selected) {
89                         /* draw hihlighting around selected item */
90                         if (use_hotbar_selected_image) {
91                                 core::rect<s32> imgrect2 = rect;
92                                 imgrect2.UpperLeftCorner.X  -= (m_padding*2);
93                                 imgrect2.UpperLeftCorner.Y  -= (m_padding*2);
94                                 imgrect2.LowerRightCorner.X += (m_padding*2);
95                                 imgrect2.LowerRightCorner.Y += (m_padding*2);
96                                         video::ITexture *texture = tsrc->getTexture(hotbar_selected_image);
97                                         core::dimension2di imgsize(texture->getOriginalSize());
98                                 draw2DImageFilterScaled(driver, texture, imgrect2,
99                                                 core::rect<s32>(core::position2d<s32>(0,0), imgsize),
100                                                 NULL, hbar_colors, true);
101                         } else {
102                                 video::SColor c_outside(255,255,0,0);
103                                 //video::SColor c_outside(255,0,0,0);
104                                 //video::SColor c_inside(255,192,192,192);
105                                 s32 x1 = rect.UpperLeftCorner.X;
106                                 s32 y1 = rect.UpperLeftCorner.Y;
107                                 s32 x2 = rect.LowerRightCorner.X;
108                                 s32 y2 = rect.LowerRightCorner.Y;
109                                 // Black base borders
110                                 driver->draw2DRectangle(c_outside,
111                                         core::rect<s32>(
112                                         v2s32(x1 - m_padding, y1 - m_padding),
113                                         v2s32(x2 + m_padding, y1)
114                                         ), NULL);
115                                 driver->draw2DRectangle(c_outside,
116                                         core::rect<s32>(
117                                         v2s32(x1 - m_padding, y2),
118                                         v2s32(x2 + m_padding, y2 + m_padding)
119                                         ), NULL);
120                                 driver->draw2DRectangle(c_outside,
121                                         core::rect<s32>(
122                                         v2s32(x1 - m_padding, y1),
123                                                 v2s32(x1, y2)
124                                         ), NULL);
125                                 driver->draw2DRectangle(c_outside,
126                                         core::rect<s32>(
127                                                 v2s32(x2, y1),
128                                         v2s32(x2 + m_padding, y2)
129                                         ), NULL);
130                                 /*// Light inside borders
131                                 driver->draw2DRectangle(c_inside,
132                                         core::rect<s32>(
133                                                 v2s32(x1 - padding/2, y1 - padding/2),
134                                                 v2s32(x2 + padding/2, y1)
135                                         ), NULL);
136                                 driver->draw2DRectangle(c_inside,
137                                         core::rect<s32>(
138                                                 v2s32(x1 - padding/2, y2),
139                                                 v2s32(x2 + padding/2, y2 + padding/2)
140                                         ), NULL);
141                                 driver->draw2DRectangle(c_inside,
142                                         core::rect<s32>(
143                                                 v2s32(x1 - padding/2, y1),
144                                                 v2s32(x1, y2)
145                                         ), NULL);
146                                 driver->draw2DRectangle(c_inside,
147                                         core::rect<s32>(
148                                                 v2s32(x2, y1),
149                                                 v2s32(x2 + padding/2, y2)
150                                         ), NULL);
151                                 */
152                         }
153                 }
154
155                 video::SColor bgcolor2(128, 0, 0, 0);
156                 if (!use_hotbar_image)
157                         driver->draw2DRectangle(bgcolor2, rect, NULL);
158                 drawItemStack(driver, g_fontengine->getFont(), item, rect, NULL,
159                         gamedef, selected, false, false);
160         }
161
162 //NOTE: selectitem = 0 -> no selected; selectitem 1-based
163 void Hud::drawItems(v2s32 upperleftpos, s32 itemcount, s32 offset,
164                 InventoryList *mainlist, u16 selectitem, u16 direction)
165 {
166 #ifdef HAVE_TOUCHSCREENGUI
167         if ( (g_touchscreengui) && (offset == 0))
168                 g_touchscreengui->resetHud();
169 #endif
170
171         s32 height  = m_hotbar_imagesize + m_padding * 2;
172         s32 width   = (itemcount - offset) * (m_hotbar_imagesize + m_padding * 2);
173
174         if (direction == HUD_DIR_TOP_BOTTOM || direction == HUD_DIR_BOTTOM_TOP) {
175                 width  = m_hotbar_imagesize + m_padding * 2;
176                 height = (itemcount - offset) * (m_hotbar_imagesize + m_padding * 2);
177         }
178
179         // Position of upper left corner of bar
180         v2s32 pos = upperleftpos;
181
182         if (hotbar_image != player->hotbar_image) {
183                 hotbar_image = player->hotbar_image;
184                 if (hotbar_image != "")
185                         use_hotbar_image = tsrc->isKnownSourceImage(hotbar_image);
186                 else
187                         use_hotbar_image = false;
188         }
189
190         if (hotbar_selected_image != player->hotbar_selected_image) {
191                 hotbar_selected_image = player->hotbar_selected_image;
192                 if (hotbar_selected_image != "")
193                         use_hotbar_selected_image = tsrc->isKnownSourceImage(hotbar_selected_image);
194                 else
195                         use_hotbar_selected_image = false;
196         }
197
198         /* draw customized item background */
199         if (use_hotbar_image) {
200                 core::rect<s32> imgrect2(-m_padding/2, -m_padding/2,
201                                 width+m_padding/2, height+m_padding/2);
202                 core::rect<s32> rect2 = imgrect2 + pos;
203                 video::ITexture *texture = tsrc->getTexture(hotbar_image);
204                 core::dimension2di imgsize(texture->getOriginalSize());
205                 draw2DImageFilterScaled(driver, texture, rect2,
206                         core::rect<s32>(core::position2d<s32>(0,0), imgsize),
207                         NULL, hbar_colors, true);
208         }
209
210         for (s32 i = offset; i < itemcount && (size_t)i < mainlist->getSize(); i++)
211         {
212                 v2s32 steppos;
213                 s32 fullimglen = m_hotbar_imagesize + m_padding * 2;
214
215                 core::rect<s32> imgrect(0, 0, m_hotbar_imagesize, m_hotbar_imagesize);
216
217                 switch (direction) {
218                         case HUD_DIR_RIGHT_LEFT:
219                                 steppos = v2s32(-(m_padding + (i - offset) * fullimglen), m_padding);
220                                 break;
221                         case HUD_DIR_TOP_BOTTOM:
222                                 steppos = v2s32(m_padding, m_padding + (i - offset) * fullimglen);
223                                 break;
224                         case HUD_DIR_BOTTOM_TOP:
225                                 steppos = v2s32(m_padding, -(m_padding + (i - offset) * fullimglen));
226                                 break;
227                         default:
228                                 steppos = v2s32(m_padding + (i - offset) * fullimglen, m_padding);
229                                 break;
230                 }
231
232                 drawItem(mainlist->getItem(i), (imgrect + pos + steppos), (i +1) == selectitem );
233
234 #ifdef HAVE_TOUCHSCREENGUI
235                 if (g_touchscreengui)
236                         g_touchscreengui->registerHudItem(i, (imgrect + pos + steppos));
237 #endif
238         }
239 }
240
241
242 void Hud::drawLuaElements(v3s16 camera_offset) {
243         u32 text_height = g_fontengine->getTextHeight();
244         irr::gui::IGUIFont* font = g_fontengine->getFont();
245         for (size_t i = 0; i != player->maxHudId(); i++) {
246                 HudElement *e = player->getHud(i);
247                 if (!e)
248                         continue;
249
250                 v2s32 pos(floor(e->pos.X * (float) m_screensize.X + 0.5),
251                                 floor(e->pos.Y * (float) m_screensize.Y + 0.5));
252                 switch (e->type) {
253                         case HUD_ELEM_IMAGE: {
254                                 video::ITexture *texture = tsrc->getTexture(e->text);
255                                 if (!texture)
256                                         continue;
257
258                                 const video::SColor color(255, 255, 255, 255);
259                                 const video::SColor colors[] = {color, color, color, color};
260                                 core::dimension2di imgsize(texture->getOriginalSize());
261                                 v2s32 dstsize(imgsize.Width * e->scale.X,
262                                               imgsize.Height * e->scale.Y);
263                                 if (e->scale.X < 0)
264                                         dstsize.X = m_screensize.X * (e->scale.X * -0.01);
265                                 if (e->scale.Y < 0)
266                                         dstsize.Y = m_screensize.Y * (e->scale.Y * -0.01);
267                                 v2s32 offset((e->align.X - 1.0) * dstsize.X / 2,
268                                              (e->align.Y - 1.0) * dstsize.Y / 2);
269                                 core::rect<s32> rect(0, 0, dstsize.X, dstsize.Y);
270                                 rect += pos + offset + v2s32(e->offset.X, e->offset.Y);
271                                 draw2DImageFilterScaled(driver, texture, rect,
272                                         core::rect<s32>(core::position2d<s32>(0,0), imgsize),
273                                         NULL, colors, true);
274                                 break; }
275                         case HUD_ELEM_TEXT: {
276                                 video::SColor color(255, (e->number >> 16) & 0xFF,
277                                                                                  (e->number >> 8)  & 0xFF,
278                                                                                  (e->number >> 0)  & 0xFF);
279                                 core::rect<s32> size(0, 0, e->scale.X, text_height * e->scale.Y);
280                                 std::wstring text = utf8_to_wide(e->text);
281                                 core::dimension2d<u32> textsize = font->getDimension(text.c_str());
282                                 v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2),
283                                              (e->align.Y - 1.0) * (textsize.Height / 2));
284                                 v2s32 offs(e->offset.X, e->offset.Y);
285                                 font->draw(text.c_str(), size + pos + offset + offs, color);
286                                 break; }
287                         case HUD_ELEM_STATBAR: {
288                                 v2s32 offs(e->offset.X, e->offset.Y);
289                                 drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number, offs, e->size);
290                                 break; }
291                         case HUD_ELEM_INVENTORY: {
292                                 InventoryList *inv = inventory->getList(e->text);
293                                 drawItems(pos, e->number, 0, inv, e->item, e->dir);
294                                 break; }
295                         case HUD_ELEM_WAYPOINT: {
296                                 v3f p_pos = player->getPosition() / BS;
297                                 v3f w_pos = e->world_pos * BS;
298                                 float distance = floor(10 * p_pos.getDistanceFrom(e->world_pos)) / 10;
299                                 scene::ICameraSceneNode* camera = smgr->getActiveCamera();
300                                 w_pos -= intToFloat(camera_offset, BS);
301                                 core::matrix4 trans = camera->getProjectionMatrix();
302                                 trans *= camera->getViewMatrix();
303                                 f32 transformed_pos[4] = { w_pos.X, w_pos.Y, w_pos.Z, 1.0f };
304                                 trans.multiplyWith1x4Matrix(transformed_pos);
305                                 if (transformed_pos[3] < 0)
306                                         break;
307                                 f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f :
308                                         core::reciprocal(transformed_pos[3]);
309                                 pos.X = m_screensize.X * (0.5 * transformed_pos[0] * zDiv + 0.5);
310                                 pos.Y = m_screensize.Y * (0.5 - transformed_pos[1] * zDiv * 0.5);
311                                 video::SColor color(255, (e->number >> 16) & 0xFF,
312                                                                                  (e->number >> 8)  & 0xFF,
313                                                                                  (e->number >> 0)  & 0xFF);
314                                 core::rect<s32> size(0, 0, 200, 2 * text_height);
315                                 std::wstring text = utf8_to_wide(e->name);
316                                 font->draw(text.c_str(), size + pos, color);
317                                 std::ostringstream os;
318                                 os << distance << e->text;
319                                 text = utf8_to_wide(os.str());
320                                 pos.Y += text_height;
321                                 font->draw(text.c_str(), size + pos, color);
322                                 break; }
323                         default:
324                                 infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
325                                         " of hud element ID " << i << " due to unrecognized type" << std::endl;
326                 }
327         }
328 }
329
330
331 void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture,
332                 s32 count, v2s32 offset, v2s32 size)
333 {
334         const video::SColor color(255, 255, 255, 255);
335         const video::SColor colors[] = {color, color, color, color};
336
337         video::ITexture *stat_texture = tsrc->getTexture(texture);
338         if (!stat_texture)
339                 return;
340
341         core::dimension2di srcd(stat_texture->getOriginalSize());
342         core::dimension2di dstd;
343         if (size == v2s32()) {
344                 dstd = srcd;
345         } else {
346                 double size_factor = g_settings->getFloat("hud_scaling") *
347                                 porting::getDisplayDensity();
348                 dstd.Height = size.Y * size_factor;
349                 dstd.Width  = size.X * size_factor;
350                 offset.X *= size_factor;
351                 offset.Y *= size_factor;
352         }
353
354         v2s32 p = pos;
355         if (corner & HUD_CORNER_LOWER)
356                 p -= dstd.Height;
357
358         p += offset;
359
360         v2s32 steppos;
361         switch (drawdir) {
362                 case HUD_DIR_RIGHT_LEFT:
363                         steppos = v2s32(-1, 0);
364                         break;
365                 case HUD_DIR_TOP_BOTTOM:
366                         steppos = v2s32(0, 1);
367                         break;
368                 case HUD_DIR_BOTTOM_TOP:
369                         steppos = v2s32(0, -1);
370                         break;
371                 default:
372                         steppos = v2s32(1, 0);
373         }
374         steppos.X *= dstd.Width;
375         steppos.Y *= dstd.Height;
376
377         for (s32 i = 0; i < count / 2; i++)
378         {
379                 core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
380                 core::rect<s32> dstrect(0,0, dstd.Width, dstd.Height);
381
382                 dstrect += p;
383                 draw2DImageFilterScaled(driver, stat_texture, dstrect, srcrect, NULL, colors, true);
384                 p += steppos;
385         }
386
387         if (count % 2 == 1)
388         {
389                 core::rect<s32> srcrect(0, 0, srcd.Width / 2, srcd.Height);
390                 core::rect<s32> dstrect(0,0, dstd.Width / 2, dstd.Height);
391
392                 dstrect += p;
393                 draw2DImageFilterScaled(driver, stat_texture, dstrect, srcrect, NULL, colors, true);
394         }
395 }
396
397
398 void Hud::drawHotbar(u16 playeritem) {
399
400         v2s32 centerlowerpos(m_displaycenter.X, m_screensize.Y);
401
402         InventoryList *mainlist = inventory->getList("main");
403         if (mainlist == NULL) {
404                 //silently ignore this we may not be initialized completely
405                 return;
406         }
407
408         s32 hotbar_itemcount = player->hud_hotbar_itemcount;
409         s32 width = hotbar_itemcount * (m_hotbar_imagesize + m_padding * 2);
410         v2s32 pos = centerlowerpos - v2s32(width / 2, m_hotbar_imagesize + m_padding * 3);
411
412         if ( (float) width / (float) porting::getWindowSize().X <=
413                         g_settings->getFloat("hud_hotbar_max_width")) {
414                 if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
415                         drawItems(pos, hotbar_itemcount, 0, mainlist, playeritem + 1, 0);
416                 }
417         }
418         else {
419                 pos.X += width/4;
420
421                 v2s32 secondpos = pos;
422                 pos = pos - v2s32(0, m_hotbar_imagesize + m_padding);
423
424                 if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
425                         drawItems(pos, hotbar_itemcount/2, 0, mainlist, playeritem + 1, 0);
426                         drawItems(secondpos, hotbar_itemcount, hotbar_itemcount/2, mainlist, playeritem + 1, 0);
427                 }
428         }
429
430         //////////////////////////// compatibility code to be removed //////////////
431         // this is ugly as hell but there's no other way to keep compatibility to
432         // old servers
433         if ((player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE)) {
434                 drawStatbar(v2s32(floor(0.5 * (float)m_screensize.X + 0.5),
435                         floor(1 * (float) m_screensize.Y + 0.5)),
436                         HUD_CORNER_UPPER, 0, "heart.png",
437                         player->hp, v2s32((-10*24)-25,-(48+24+10)), v2s32(24,24));
438         }
439
440         if ((player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE) &&
441                         (player->getBreath() < 11)) {
442                 drawStatbar(v2s32(floor(0.5 * (float)m_screensize.X + 0.5),
443                         floor(1 * (float) m_screensize.Y + 0.5)),
444                         HUD_CORNER_UPPER, 0, "bubble.png",
445                         player->getBreath(), v2s32(25,-(48+24+10)), v2s32(24,24));
446         }
447         ////////////////////////////////////////////////////////////////////////////
448 }
449
450
451 void Hud::drawCrosshair() {
452
453         if (use_crosshair_image) {
454                 video::ITexture *crosshair = tsrc->getTexture("crosshair.png");
455                 v2u32 size  = crosshair->getOriginalSize();
456                 v2s32 lsize = v2s32(m_displaycenter.X - (size.X / 2),
457                                 m_displaycenter.Y - (size.Y / 2));
458                 driver->draw2DImage(crosshair, lsize,
459                                 core::rect<s32>(0, 0, size.X, size.Y),
460                                 0, crosshair_argb, true);
461         } else {
462                 driver->draw2DLine(m_displaycenter - v2s32(10, 0),
463                                 m_displaycenter + v2s32(10, 0), crosshair_argb);
464                 driver->draw2DLine(m_displaycenter - v2s32(0, 10),
465                                 m_displaycenter + v2s32(0, 10), crosshair_argb);
466         }
467 }
468
469
470 void Hud::drawSelectionBoxes(std::vector<aabb3f> &hilightboxes) {
471         for (std::vector<aabb3f>::const_iterator
472                         i = hilightboxes.begin();
473                         i != hilightboxes.end(); ++i) {
474                 driver->draw3DBox(*i, selectionbox_argb);
475         }
476 }
477
478
479 void Hud::resizeHotbar() {
480         if (m_screensize != porting::getWindowSize()) {
481                 m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE * porting::getDisplayDensity() + 0.5);
482                 m_hotbar_imagesize *= g_settings->getFloat("hud_scaling");
483                 m_padding = m_hotbar_imagesize / 12;
484                 m_screensize = porting::getWindowSize();
485                 m_displaycenter = v2s32(m_screensize.X/2,m_screensize.Y/2);
486         }
487 }
488
489 void drawItemStack(video::IVideoDriver *driver,
490                 gui::IGUIFont *font,
491                 const ItemStack &item,
492                 const core::rect<s32> &rect,
493                 const core::rect<s32> *clip,
494                 IGameDef *gamedef,
495                 bool selected,
496                 bool hovered,
497                 bool dragged)
498 {
499         static s32 hovered_time;
500         static s32 selected_time;
501         static s32 dragged_time;
502         static scene::IMesh *hovered_mesh;
503         static scene::IMesh *selected_mesh;
504         static scene::IMesh *dragged_mesh;
505         bool enable_animations =
506                 g_settings->getBool("inventory_items_animations");
507
508         if (item.empty()) {
509                 if (selected) {
510                         selected_mesh = NULL;
511                 } else if (hovered) {
512                         hovered_mesh = NULL;
513                 } else if (dragged) {
514                         dragged_mesh = NULL;
515                 }
516                 return;
517         }
518
519         const ItemDefinition &def = item.getDefinition(gamedef->idef());
520         scene::IMesh* mesh = gamedef->idef()->getWieldMesh(def.name, gamedef);
521
522         if (mesh) {
523                 driver->clearZBuffer();
524                 s32 delta = 0;
525                 if (selected) {
526                         if (mesh != selected_mesh) {
527                                 selected_mesh = mesh;
528                                 selected_time = getTimeMs();
529                         } else {
530                                 delta = porting::getDeltaMs(selected_time, getTimeMs()) % 100000;
531                         }
532                 } else if (hovered) {
533                         if (mesh != hovered_mesh) {
534                                 hovered_mesh = mesh;
535                                 hovered_time = getTimeMs();
536                         } else {
537                                 delta = porting::getDeltaMs(hovered_time, getTimeMs()) % 100000;
538                         }
539                 } else if (dragged) {
540                         if (mesh != dragged_mesh) {
541                                 dragged_mesh = mesh;
542                                 dragged_time = getTimeMs();
543                         } else {
544                                 delta = porting::getDeltaMs(dragged_time, getTimeMs()) % 100000;
545                         }
546                 }
547                 core::rect<s32> oldViewPort = driver->getViewPort();
548                 core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION);
549                 core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW);
550                 core::matrix4 ProjMatrix;
551                 ProjMatrix.buildProjectionMatrixOrthoLH(2, 2, -1, 100);
552                 driver->setTransform(video::ETS_PROJECTION, ProjMatrix);
553                 driver->setTransform(video::ETS_VIEW, ProjMatrix);
554                 core::matrix4 matrix;
555                 matrix.makeIdentity();
556
557                 if (enable_animations) {
558                         float timer_f = (float)delta / 5000.0;
559                         matrix.setRotationDegrees(core::vector3df(0, 360 * timer_f, 0));
560                 }
561
562                 driver->setTransform(video::ETS_WORLD, matrix);
563                 driver->setViewPort(rect);
564
565                 u32 mc = mesh->getMeshBufferCount();
566                 for (u32 j = 0; j < mc; ++j) {
567                         scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
568                         video::SMaterial &material = buf->getMaterial();
569                         material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
570                         material.Lighting = false;
571                         driver->setMaterial(material);
572                         driver->drawMeshBuffer(buf);
573                 }
574
575                 driver->setTransform(video::ETS_VIEW, oldViewMat);
576                 driver->setTransform(video::ETS_PROJECTION, oldProjMat);
577                 driver->setViewPort(oldViewPort);
578         }
579
580         if(def.type == ITEM_TOOL && item.wear != 0)
581         {
582                 // Draw a progressbar
583                 float barheight = rect.getHeight()/16;
584                 float barpad_x = rect.getWidth()/16;
585                 float barpad_y = rect.getHeight()/16;
586                 core::rect<s32> progressrect(
587                         rect.UpperLeftCorner.X + barpad_x,
588                         rect.LowerRightCorner.Y - barpad_y - barheight,
589                         rect.LowerRightCorner.X - barpad_x,
590                         rect.LowerRightCorner.Y - barpad_y);
591
592                 // Shrink progressrect by amount of tool damage
593                 float wear = item.wear / 65535.0;
594                 int progressmid =
595                         wear * progressrect.UpperLeftCorner.X +
596                         (1-wear) * progressrect.LowerRightCorner.X;
597
598                 // Compute progressbar color
599                 //   wear = 0.0: green
600                 //   wear = 0.5: yellow
601                 //   wear = 1.0: red
602                 video::SColor color(255,255,255,255);
603                 int wear_i = MYMIN(floor(wear * 600), 511);
604                 wear_i = MYMIN(wear_i + 10, 511);
605                 if(wear_i <= 255)
606                         color.set(255, wear_i, 255, 0);
607                 else
608                         color.set(255, 255, 511-wear_i, 0);
609
610                 core::rect<s32> progressrect2 = progressrect;
611                 progressrect2.LowerRightCorner.X = progressmid;
612                 driver->draw2DRectangle(color, progressrect2, clip);
613
614                 color = video::SColor(255,0,0,0);
615                 progressrect2 = progressrect;
616                 progressrect2.UpperLeftCorner.X = progressmid;
617                 driver->draw2DRectangle(color, progressrect2, clip);
618         }
619
620         if(font != NULL && item.count >= 2)
621         {
622                 // Get the item count as a string
623                 std::string text = itos(item.count);
624                 v2u32 dim = font->getDimension(utf8_to_wide(text).c_str());
625                 v2s32 sdim(dim.X,dim.Y);
626
627                 core::rect<s32> rect2(
628                         /*rect.UpperLeftCorner,
629                         core::dimension2d<u32>(rect.getWidth(), 15)*/
630                         rect.LowerRightCorner - sdim,
631                         sdim
632                 );
633
634                 video::SColor bgcolor(128,0,0,0);
635                 driver->draw2DRectangle(bgcolor, rect2, clip);
636
637                 video::SColor color(255,255,255,255);
638                 font->draw(text.c_str(), rect2, color, false, false, clip);
639         }
640 }