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>
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.
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.
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.
24 #include "util/numeric.h"
28 #include "inventory.h"
29 #include "client/tile.h"
30 #include "localplayer.h"
33 #include "fontengine.h"
34 #include "guiscalingfilter.h"
36 #include <IGUIStaticText.h>
38 #ifdef HAVE_TOUCHSCREENGUI
39 #include "touchscreengui.h"
42 Hud::Hud(video::IVideoDriver *driver, scene::ISceneManager* smgr,
43 gui::IGUIEnvironment* guienv, IGameDef *gamedef, LocalPlayer *player,
44 Inventory *inventory) {
45 this->driver = driver;
47 this->guienv = guienv;
48 this->gamedef = gamedef;
49 this->player = player;
50 this->inventory = inventory;
52 m_screensize = v2u32(0, 0);
53 m_displaycenter = v2s32(0, 0);
54 m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE * porting::getDisplayDensity() + 0.5);
55 m_hotbar_imagesize *= g_settings->getFloat("hud_scaling");
56 m_padding = m_hotbar_imagesize / 12;
58 const video::SColor hbar_color(255, 255, 255, 255);
59 for (unsigned int i=0; i < 4; i++ ){
60 hbar_colors[i] = hbar_color;
63 tsrc = gamedef->getTextureSource();
65 v3f crosshair_color = g_settings->getV3F("crosshair_color");
66 u32 cross_r = rangelim(myround(crosshair_color.X), 0, 255);
67 u32 cross_g = rangelim(myround(crosshair_color.Y), 0, 255);
68 u32 cross_b = rangelim(myround(crosshair_color.Z), 0, 255);
69 u32 cross_a = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255);
70 crosshair_argb = video::SColor(cross_a, cross_r, cross_g, cross_b);
72 v3f selectionbox_color = g_settings->getV3F("selectionbox_color");
73 u32 sbox_r = rangelim(myround(selectionbox_color.X), 0, 255);
74 u32 sbox_g = rangelim(myround(selectionbox_color.Y), 0, 255);
75 u32 sbox_b = rangelim(myround(selectionbox_color.Z), 0, 255);
76 selectionbox_argb = video::SColor(255, sbox_r, sbox_g, sbox_b);
78 use_crosshair_image = tsrc->isKnownSourceImage("crosshair.png");
81 use_hotbar_image = false;
82 hotbar_selected_image = "";
83 use_hotbar_selected_image = false;
85 m_selection_mesh = NULL;
86 m_selection_boxes.clear();
89 m_selection_pos = v3f(0.0, 0.0, 0.0);
90 std::string mode = g_settings->get("node_highlighting");
91 m_selection_material.Lighting = false;
93 if (g_settings->getBool("enable_shaders")) {
94 IShaderSource *shdrsrc = gamedef->getShaderSource();
95 u16 shader_id = shdrsrc->getShader(
96 mode == "halo" ? "selection_shader" : "default_shader", 1, 1);
97 m_selection_material.MaterialType = shdrsrc->getShaderInfo(shader_id).material;
99 m_selection_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
103 m_use_selection_mesh = false;
104 m_selection_material.Thickness =
105 rangelim(g_settings->getS16("selectionbox_width"), 1, 5);
106 } else if (mode == "halo") {
107 m_use_selection_mesh = true;
108 m_selection_material.setTexture(0, tsrc->getTextureForMesh("halo.png"));
109 m_selection_material.setFlag(video::EMF_BACK_FACE_CULLING, true);
111 m_selection_material.MaterialType = video::EMT_SOLID;
117 if (m_selection_mesh)
118 m_selection_mesh->drop();
121 void Hud::drawItem(const ItemStack &item, const core::rect<s32>& rect,
125 /* draw hihlighting around selected item */
126 if (use_hotbar_selected_image) {
127 core::rect<s32> imgrect2 = rect;
128 imgrect2.UpperLeftCorner.X -= (m_padding*2);
129 imgrect2.UpperLeftCorner.Y -= (m_padding*2);
130 imgrect2.LowerRightCorner.X += (m_padding*2);
131 imgrect2.LowerRightCorner.Y += (m_padding*2);
132 video::ITexture *texture = tsrc->getTexture(hotbar_selected_image);
133 core::dimension2di imgsize(texture->getOriginalSize());
134 draw2DImageFilterScaled(driver, texture, imgrect2,
135 core::rect<s32>(core::position2d<s32>(0,0), imgsize),
136 NULL, hbar_colors, true);
138 video::SColor c_outside(255,255,0,0);
139 //video::SColor c_outside(255,0,0,0);
140 //video::SColor c_inside(255,192,192,192);
141 s32 x1 = rect.UpperLeftCorner.X;
142 s32 y1 = rect.UpperLeftCorner.Y;
143 s32 x2 = rect.LowerRightCorner.X;
144 s32 y2 = rect.LowerRightCorner.Y;
145 // Black base borders
146 driver->draw2DRectangle(c_outside,
148 v2s32(x1 - m_padding, y1 - m_padding),
149 v2s32(x2 + m_padding, y1)
151 driver->draw2DRectangle(c_outside,
153 v2s32(x1 - m_padding, y2),
154 v2s32(x2 + m_padding, y2 + m_padding)
156 driver->draw2DRectangle(c_outside,
158 v2s32(x1 - m_padding, y1),
161 driver->draw2DRectangle(c_outside,
164 v2s32(x2 + m_padding, y2)
166 /*// Light inside borders
167 driver->draw2DRectangle(c_inside,
169 v2s32(x1 - padding/2, y1 - padding/2),
170 v2s32(x2 + padding/2, y1)
172 driver->draw2DRectangle(c_inside,
174 v2s32(x1 - padding/2, y2),
175 v2s32(x2 + padding/2, y2 + padding/2)
177 driver->draw2DRectangle(c_inside,
179 v2s32(x1 - padding/2, y1),
182 driver->draw2DRectangle(c_inside,
185 v2s32(x2 + padding/2, y2)
191 video::SColor bgcolor2(128, 0, 0, 0);
192 if (!use_hotbar_image)
193 driver->draw2DRectangle(bgcolor2, rect, NULL);
194 drawItemStack(driver, g_fontengine->getFont(), item, rect, NULL,
195 gamedef, selected ? IT_ROT_SELECTED : IT_ROT_NONE);
198 //NOTE: selectitem = 0 -> no selected; selectitem 1-based
199 void Hud::drawItems(v2s32 upperleftpos, s32 itemcount, s32 offset,
200 InventoryList *mainlist, u16 selectitem, u16 direction)
202 #ifdef HAVE_TOUCHSCREENGUI
203 if ( (g_touchscreengui) && (offset == 0))
204 g_touchscreengui->resetHud();
207 s32 height = m_hotbar_imagesize + m_padding * 2;
208 s32 width = (itemcount - offset) * (m_hotbar_imagesize + m_padding * 2);
210 if (direction == HUD_DIR_TOP_BOTTOM || direction == HUD_DIR_BOTTOM_TOP) {
211 width = m_hotbar_imagesize + m_padding * 2;
212 height = (itemcount - offset) * (m_hotbar_imagesize + m_padding * 2);
215 // Position of upper left corner of bar
216 v2s32 pos = upperleftpos;
218 if (hotbar_image != player->hotbar_image) {
219 hotbar_image = player->hotbar_image;
220 if (hotbar_image != "")
221 use_hotbar_image = tsrc->isKnownSourceImage(hotbar_image);
223 use_hotbar_image = false;
226 if (hotbar_selected_image != player->hotbar_selected_image) {
227 hotbar_selected_image = player->hotbar_selected_image;
228 if (hotbar_selected_image != "")
229 use_hotbar_selected_image = tsrc->isKnownSourceImage(hotbar_selected_image);
231 use_hotbar_selected_image = false;
234 /* draw customized item background */
235 if (use_hotbar_image) {
236 core::rect<s32> imgrect2(-m_padding/2, -m_padding/2,
237 width+m_padding/2, height+m_padding/2);
238 core::rect<s32> rect2 = imgrect2 + pos;
239 video::ITexture *texture = tsrc->getTexture(hotbar_image);
240 core::dimension2di imgsize(texture->getOriginalSize());
241 draw2DImageFilterScaled(driver, texture, rect2,
242 core::rect<s32>(core::position2d<s32>(0,0), imgsize),
243 NULL, hbar_colors, true);
246 for (s32 i = offset; i < itemcount && (size_t)i < mainlist->getSize(); i++)
249 s32 fullimglen = m_hotbar_imagesize + m_padding * 2;
251 core::rect<s32> imgrect(0, 0, m_hotbar_imagesize, m_hotbar_imagesize);
254 case HUD_DIR_RIGHT_LEFT:
255 steppos = v2s32(-(m_padding + (i - offset) * fullimglen), m_padding);
257 case HUD_DIR_TOP_BOTTOM:
258 steppos = v2s32(m_padding, m_padding + (i - offset) * fullimglen);
260 case HUD_DIR_BOTTOM_TOP:
261 steppos = v2s32(m_padding, -(m_padding + (i - offset) * fullimglen));
264 steppos = v2s32(m_padding + (i - offset) * fullimglen, m_padding);
268 drawItem(mainlist->getItem(i), (imgrect + pos + steppos), (i +1) == selectitem );
270 #ifdef HAVE_TOUCHSCREENGUI
271 if (g_touchscreengui)
272 g_touchscreengui->registerHudItem(i, (imgrect + pos + steppos));
278 void Hud::drawLuaElements(const v3s16 &camera_offset) {
279 u32 text_height = g_fontengine->getTextHeight();
280 irr::gui::IGUIFont* font = g_fontengine->getFont();
281 for (size_t i = 0; i != player->maxHudId(); i++) {
282 HudElement *e = player->getHud(i);
286 v2s32 pos(floor(e->pos.X * (float) m_screensize.X + 0.5),
287 floor(e->pos.Y * (float) m_screensize.Y + 0.5));
289 case HUD_ELEM_IMAGE: {
290 video::ITexture *texture = tsrc->getTexture(e->text);
294 const video::SColor color(255, 255, 255, 255);
295 const video::SColor colors[] = {color, color, color, color};
296 core::dimension2di imgsize(texture->getOriginalSize());
297 v2s32 dstsize(imgsize.Width * e->scale.X,
298 imgsize.Height * e->scale.Y);
300 dstsize.X = m_screensize.X * (e->scale.X * -0.01);
302 dstsize.Y = m_screensize.Y * (e->scale.Y * -0.01);
303 v2s32 offset((e->align.X - 1.0) * dstsize.X / 2,
304 (e->align.Y - 1.0) * dstsize.Y / 2);
305 core::rect<s32> rect(0, 0, dstsize.X, dstsize.Y);
306 rect += pos + offset + v2s32(e->offset.X, e->offset.Y);
307 draw2DImageFilterScaled(driver, texture, rect,
308 core::rect<s32>(core::position2d<s32>(0,0), imgsize),
311 case HUD_ELEM_TEXT: {
312 video::SColor color(255, (e->number >> 16) & 0xFF,
313 (e->number >> 8) & 0xFF,
314 (e->number >> 0) & 0xFF);
315 core::rect<s32> size(0, 0, e->scale.X, text_height * e->scale.Y);
316 std::wstring text = utf8_to_wide(e->text);
317 core::dimension2d<u32> textsize = font->getDimension(text.c_str());
318 v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2),
319 (e->align.Y - 1.0) * (textsize.Height / 2));
320 v2s32 offs(e->offset.X, e->offset.Y);
321 font->draw(text.c_str(), size + pos + offset + offs, color);
323 case HUD_ELEM_STATBAR: {
324 v2s32 offs(e->offset.X, e->offset.Y);
325 drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number, offs, e->size);
327 case HUD_ELEM_INVENTORY: {
328 InventoryList *inv = inventory->getList(e->text);
329 drawItems(pos, e->number, 0, inv, e->item, e->dir);
331 case HUD_ELEM_WAYPOINT: {
332 v3f p_pos = player->getPosition() / BS;
333 v3f w_pos = e->world_pos * BS;
334 float distance = floor(10 * p_pos.getDistanceFrom(e->world_pos)) / 10;
335 scene::ICameraSceneNode* camera = smgr->getActiveCamera();
336 w_pos -= intToFloat(camera_offset, BS);
337 core::matrix4 trans = camera->getProjectionMatrix();
338 trans *= camera->getViewMatrix();
339 f32 transformed_pos[4] = { w_pos.X, w_pos.Y, w_pos.Z, 1.0f };
340 trans.multiplyWith1x4Matrix(transformed_pos);
341 if (transformed_pos[3] < 0)
343 f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f :
344 core::reciprocal(transformed_pos[3]);
345 pos.X = m_screensize.X * (0.5 * transformed_pos[0] * zDiv + 0.5);
346 pos.Y = m_screensize.Y * (0.5 - transformed_pos[1] * zDiv * 0.5);
347 video::SColor color(255, (e->number >> 16) & 0xFF,
348 (e->number >> 8) & 0xFF,
349 (e->number >> 0) & 0xFF);
350 core::rect<s32> size(0, 0, 200, 2 * text_height);
351 std::wstring text = utf8_to_wide(e->name);
352 font->draw(text.c_str(), size + pos, color);
353 std::ostringstream os;
354 os << distance << e->text;
355 text = utf8_to_wide(os.str());
356 pos.Y += text_height;
357 font->draw(text.c_str(), size + pos, color);
360 infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
361 " of hud element ID " << i << " due to unrecognized type" << std::endl;
367 void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture,
368 s32 count, v2s32 offset, v2s32 size)
370 const video::SColor color(255, 255, 255, 255);
371 const video::SColor colors[] = {color, color, color, color};
373 video::ITexture *stat_texture = tsrc->getTexture(texture);
377 core::dimension2di srcd(stat_texture->getOriginalSize());
378 core::dimension2di dstd;
379 if (size == v2s32()) {
382 double size_factor = g_settings->getFloat("hud_scaling") *
383 porting::getDisplayDensity();
384 dstd.Height = size.Y * size_factor;
385 dstd.Width = size.X * size_factor;
386 offset.X *= size_factor;
387 offset.Y *= size_factor;
391 if (corner & HUD_CORNER_LOWER)
398 case HUD_DIR_RIGHT_LEFT:
399 steppos = v2s32(-1, 0);
401 case HUD_DIR_TOP_BOTTOM:
402 steppos = v2s32(0, 1);
404 case HUD_DIR_BOTTOM_TOP:
405 steppos = v2s32(0, -1);
408 steppos = v2s32(1, 0);
410 steppos.X *= dstd.Width;
411 steppos.Y *= dstd.Height;
413 for (s32 i = 0; i < count / 2; i++)
415 core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
416 core::rect<s32> dstrect(0,0, dstd.Width, dstd.Height);
419 draw2DImageFilterScaled(driver, stat_texture, dstrect, srcrect, NULL, colors, true);
425 core::rect<s32> srcrect(0, 0, srcd.Width / 2, srcd.Height);
426 core::rect<s32> dstrect(0,0, dstd.Width / 2, dstd.Height);
429 draw2DImageFilterScaled(driver, stat_texture, dstrect, srcrect, NULL, colors, true);
434 void Hud::drawHotbar(u16 playeritem) {
436 v2s32 centerlowerpos(m_displaycenter.X, m_screensize.Y);
438 InventoryList *mainlist = inventory->getList("main");
439 if (mainlist == NULL) {
440 //silently ignore this we may not be initialized completely
444 s32 hotbar_itemcount = player->hud_hotbar_itemcount;
445 s32 width = hotbar_itemcount * (m_hotbar_imagesize + m_padding * 2);
446 v2s32 pos = centerlowerpos - v2s32(width / 2, m_hotbar_imagesize + m_padding * 3);
448 if ( (float) width / (float) porting::getWindowSize().X <=
449 g_settings->getFloat("hud_hotbar_max_width")) {
450 if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
451 drawItems(pos, hotbar_itemcount, 0, mainlist, playeritem + 1, 0);
457 v2s32 secondpos = pos;
458 pos = pos - v2s32(0, m_hotbar_imagesize + m_padding);
460 if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
461 drawItems(pos, hotbar_itemcount/2, 0, mainlist, playeritem + 1, 0);
462 drawItems(secondpos, hotbar_itemcount, hotbar_itemcount/2, mainlist, playeritem + 1, 0);
466 //////////////////////////// compatibility code to be removed //////////////
467 // this is ugly as hell but there's no other way to keep compatibility to
469 if ((player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE)) {
470 drawStatbar(v2s32(floor(0.5 * (float)m_screensize.X + 0.5),
471 floor(1 * (float) m_screensize.Y + 0.5)),
472 HUD_CORNER_UPPER, 0, "heart.png",
473 player->hp, v2s32((-10*24)-25,-(48+24+10)), v2s32(24,24));
476 if ((player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE) &&
477 (player->getBreath() < 11)) {
478 drawStatbar(v2s32(floor(0.5 * (float)m_screensize.X + 0.5),
479 floor(1 * (float) m_screensize.Y + 0.5)),
480 HUD_CORNER_UPPER, 0, "bubble.png",
481 player->getBreath(), v2s32(25,-(48+24+10)), v2s32(24,24));
483 ////////////////////////////////////////////////////////////////////////////
487 void Hud::drawCrosshair() {
489 if (use_crosshair_image) {
490 video::ITexture *crosshair = tsrc->getTexture("crosshair.png");
491 v2u32 size = crosshair->getOriginalSize();
492 v2s32 lsize = v2s32(m_displaycenter.X - (size.X / 2),
493 m_displaycenter.Y - (size.Y / 2));
494 driver->draw2DImage(crosshair, lsize,
495 core::rect<s32>(0, 0, size.X, size.Y),
496 0, crosshair_argb, true);
498 driver->draw2DLine(m_displaycenter - v2s32(10, 0),
499 m_displaycenter + v2s32(10, 0), crosshair_argb);
500 driver->draw2DLine(m_displaycenter - v2s32(0, 10),
501 m_displaycenter + v2s32(0, 10), crosshair_argb);
505 void Hud::setSelectionPos(const v3f &pos, const v3s16 &camera_offset)
507 m_camera_offset = camera_offset;
508 m_selection_pos = pos;
509 m_selection_pos_with_offset = pos - intToFloat(camera_offset, BS);
512 void Hud::drawSelectionMesh()
514 if (!m_use_selection_mesh) {
515 // Draw 3D selection boxes
516 video::SMaterial oldmaterial = driver->getMaterial2D();
517 driver->setMaterial(m_selection_material);
518 for (std::vector<aabb3f>::const_iterator
519 i = m_selection_boxes.begin();
520 i != m_selection_boxes.end(); ++i) {
522 i->MinEdge + m_selection_pos_with_offset,
523 i->MaxEdge + m_selection_pos_with_offset);
525 u32 r = (selectionbox_argb.getRed() *
526 m_selection_mesh_color.getRed() / 255);
527 u32 g = (selectionbox_argb.getGreen() *
528 m_selection_mesh_color.getGreen() / 255);
529 u32 b = (selectionbox_argb.getBlue() *
530 m_selection_mesh_color.getBlue() / 255);
531 driver->draw3DBox(box, video::SColor(255, r, g, b));
533 driver->setMaterial(oldmaterial);
534 } else if (m_selection_mesh) {
535 // Draw selection mesh
536 video::SMaterial oldmaterial = driver->getMaterial2D();
537 driver->setMaterial(m_selection_material);
538 setMeshColor(m_selection_mesh, m_selection_mesh_color);
539 scene::IMesh* mesh = cloneMesh(m_selection_mesh);
540 translateMesh(mesh, m_selection_pos_with_offset);
541 u32 mc = m_selection_mesh->getMeshBufferCount();
542 for (u32 i = 0; i < mc; i++) {
543 scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
544 driver->drawMeshBuffer(buf);
547 driver->setMaterial(oldmaterial);
551 void Hud::updateSelectionMesh(const v3s16 &camera_offset)
553 m_camera_offset = camera_offset;
554 if (!m_use_selection_mesh)
557 if (m_selection_mesh) {
558 m_selection_mesh->drop();
559 m_selection_mesh = NULL;
562 if (!m_selection_boxes.size()) {
567 // New pointed object, create new mesh.
569 // Texture UV coordinates for selection boxes
570 static f32 texture_uv[24] = {
579 // Use single halo box instead of multiple overlapping boxes.
580 // Temporary solution - problem can be solved with multiple
581 // rendering targets, or some method to remove inner surfaces.
582 // Thats because of halo transparency.
584 aabb3f halo_box(100.0, 100.0, 100.0, -100.0, -100.0, -100.0);
585 m_halo_boxes.clear();
587 for (std::vector<aabb3f>::iterator
588 i = m_selection_boxes.begin();
589 i != m_selection_boxes.end(); ++i) {
590 halo_box.addInternalBox(*i);
593 m_halo_boxes.push_back(halo_box);
594 m_selection_mesh = convertNodeboxesToMesh(
595 m_halo_boxes, texture_uv, 0.5);
598 void Hud::resizeHotbar() {
599 if (m_screensize != porting::getWindowSize()) {
600 m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE * porting::getDisplayDensity() + 0.5);
601 m_hotbar_imagesize *= g_settings->getFloat("hud_scaling");
602 m_padding = m_hotbar_imagesize / 12;
603 m_screensize = porting::getWindowSize();
604 m_displaycenter = v2s32(m_screensize.X/2,m_screensize.Y/2);
608 struct MeshTimeInfo {
613 void drawItemStack(video::IVideoDriver *driver,
615 const ItemStack &item,
616 const core::rect<s32> &rect,
617 const core::rect<s32> *clip,
619 ItemRotationKind rotation_kind)
621 static MeshTimeInfo rotation_time_infos[IT_ROT_NONE];
622 static bool enable_animations =
623 g_settings->getBool("inventory_items_animations");
626 if (rotation_kind < IT_ROT_NONE) {
627 rotation_time_infos[rotation_kind].mesh = NULL;
632 const ItemDefinition &def = item.getDefinition(gamedef->idef());
633 scene::IMesh* mesh = gamedef->idef()->getWieldMesh(def.name, gamedef);
636 driver->clearZBuffer();
638 if (rotation_kind < IT_ROT_NONE) {
639 MeshTimeInfo &ti = rotation_time_infos[rotation_kind];
640 if (mesh != ti.mesh) {
642 ti.time = getTimeMs();
644 delta = porting::getDeltaMs(ti.time, getTimeMs()) % 100000;
647 core::rect<s32> oldViewPort = driver->getViewPort();
648 core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION);
649 core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW);
650 core::matrix4 ProjMatrix;
651 ProjMatrix.buildProjectionMatrixOrthoLH(2, 2, -1, 100);
652 driver->setTransform(video::ETS_PROJECTION, ProjMatrix);
653 driver->setTransform(video::ETS_VIEW, ProjMatrix);
654 core::matrix4 matrix;
655 matrix.makeIdentity();
657 if (enable_animations) {
658 float timer_f = (float)delta / 5000.0;
659 matrix.setRotationDegrees(core::vector3df(0, 360 * timer_f, 0));
662 driver->setTransform(video::ETS_WORLD, matrix);
663 driver->setViewPort(rect);
665 u32 mc = mesh->getMeshBufferCount();
666 for (u32 j = 0; j < mc; ++j) {
667 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
668 video::SMaterial &material = buf->getMaterial();
669 material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
670 material.Lighting = false;
671 driver->setMaterial(material);
672 driver->drawMeshBuffer(buf);
675 driver->setTransform(video::ETS_VIEW, oldViewMat);
676 driver->setTransform(video::ETS_PROJECTION, oldProjMat);
677 driver->setViewPort(oldViewPort);
680 if(def.type == ITEM_TOOL && item.wear != 0)
682 // Draw a progressbar
683 float barheight = rect.getHeight()/16;
684 float barpad_x = rect.getWidth()/16;
685 float barpad_y = rect.getHeight()/16;
686 core::rect<s32> progressrect(
687 rect.UpperLeftCorner.X + barpad_x,
688 rect.LowerRightCorner.Y - barpad_y - barheight,
689 rect.LowerRightCorner.X - barpad_x,
690 rect.LowerRightCorner.Y - barpad_y);
692 // Shrink progressrect by amount of tool damage
693 float wear = item.wear / 65535.0;
695 wear * progressrect.UpperLeftCorner.X +
696 (1-wear) * progressrect.LowerRightCorner.X;
698 // Compute progressbar color
700 // wear = 0.5: yellow
702 video::SColor color(255,255,255,255);
703 int wear_i = MYMIN(floor(wear * 600), 511);
704 wear_i = MYMIN(wear_i + 10, 511);
706 color.set(255, wear_i, 255, 0);
708 color.set(255, 255, 511-wear_i, 0);
710 core::rect<s32> progressrect2 = progressrect;
711 progressrect2.LowerRightCorner.X = progressmid;
712 driver->draw2DRectangle(color, progressrect2, clip);
714 color = video::SColor(255,0,0,0);
715 progressrect2 = progressrect;
716 progressrect2.UpperLeftCorner.X = progressmid;
717 driver->draw2DRectangle(color, progressrect2, clip);
720 if(font != NULL && item.count >= 2)
722 // Get the item count as a string
723 std::string text = itos(item.count);
724 v2u32 dim = font->getDimension(utf8_to_wide(text).c_str());
725 v2s32 sdim(dim.X,dim.Y);
727 core::rect<s32> rect2(
728 /*rect.UpperLeftCorner,
729 core::dimension2d<u32>(rect.getWidth(), 15)*/
730 rect.LowerRightCorner - sdim,
734 video::SColor bgcolor(128,0,0,0);
735 driver->draw2DRectangle(bgcolor, rect2, clip);
737 video::SColor color(255,255,255,255);
738 font->draw(text.c_str(), rect2, color, false, false, clip);