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"
27 #include "inventory.h"
28 #include "client/tile.h"
29 #include "localplayer.h"
32 #include "fontengine.h"
33 #include "guiscalingfilter.h"
35 #include "wieldmesh.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, Client *client, LocalPlayer *player,
46 this->driver = driver;
48 this->guienv = guienv;
49 this->client = client;
50 this->player = player;
51 this->inventory = inventory;
53 m_hud_scaling = g_settings->getFloat("hud_scaling");
54 m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE * porting::getDisplayDensity() + 0.5);
55 m_hotbar_imagesize *= m_hud_scaling;
56 m_padding = m_hotbar_imagesize / 12;
58 for (unsigned int i = 0; i < 4; i++)
59 hbar_colors[i] = video::SColor(255, 255, 255, 255);
61 tsrc = client->getTextureSource();
63 v3f crosshair_color = g_settings->getV3F("crosshair_color");
64 u32 cross_r = rangelim(myround(crosshair_color.X), 0, 255);
65 u32 cross_g = rangelim(myround(crosshair_color.Y), 0, 255);
66 u32 cross_b = rangelim(myround(crosshair_color.Z), 0, 255);
67 u32 cross_a = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255);
68 crosshair_argb = video::SColor(cross_a, cross_r, cross_g, cross_b);
70 v3f selectionbox_color = g_settings->getV3F("selectionbox_color");
71 u32 sbox_r = rangelim(myround(selectionbox_color.X), 0, 255);
72 u32 sbox_g = rangelim(myround(selectionbox_color.Y), 0, 255);
73 u32 sbox_b = rangelim(myround(selectionbox_color.Z), 0, 255);
74 selectionbox_argb = video::SColor(255, sbox_r, sbox_g, sbox_b);
76 use_crosshair_image = tsrc->isKnownSourceImage("crosshair.png");
78 m_selection_boxes.clear();
81 std::string mode_setting = g_settings->get("node_highlighting");
83 if (mode_setting == "halo") {
84 m_mode = HIGHLIGHT_HALO;
85 } else if (mode_setting == "none") {
86 m_mode = HIGHLIGHT_NONE;
88 m_mode = HIGHLIGHT_BOX;
91 m_selection_material.Lighting = false;
93 if (g_settings->getBool("enable_shaders")) {
94 IShaderSource *shdrsrc = client->getShaderSource();
95 u16 shader_id = shdrsrc->getShader(
96 m_mode == HIGHLIGHT_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;
102 if (m_mode == HIGHLIGHT_BOX) {
103 m_selection_material.Thickness =
104 rangelim(g_settings->getS16("selectionbox_width"), 1, 5);
105 } else if (m_mode == HIGHLIGHT_HALO) {
106 m_selection_material.setTexture(0, tsrc->getTextureForMesh("halo.png"));
107 m_selection_material.setFlag(video::EMF_BACK_FACE_CULLING, true);
109 m_selection_material.MaterialType = video::EMT_SOLID;
115 if (m_selection_mesh)
116 m_selection_mesh->drop();
119 void Hud::drawItem(const ItemStack &item, const core::rect<s32>& rect,
123 /* draw hihlighting around selected item */
124 if (use_hotbar_selected_image) {
125 core::rect<s32> imgrect2 = rect;
126 imgrect2.UpperLeftCorner.X -= (m_padding*2);
127 imgrect2.UpperLeftCorner.Y -= (m_padding*2);
128 imgrect2.LowerRightCorner.X += (m_padding*2);
129 imgrect2.LowerRightCorner.Y += (m_padding*2);
130 video::ITexture *texture = tsrc->getTexture(hotbar_selected_image);
131 core::dimension2di imgsize(texture->getOriginalSize());
132 draw2DImageFilterScaled(driver, texture, imgrect2,
133 core::rect<s32>(core::position2d<s32>(0,0), imgsize),
134 NULL, hbar_colors, true);
136 video::SColor c_outside(255,255,0,0);
137 //video::SColor c_outside(255,0,0,0);
138 //video::SColor c_inside(255,192,192,192);
139 s32 x1 = rect.UpperLeftCorner.X;
140 s32 y1 = rect.UpperLeftCorner.Y;
141 s32 x2 = rect.LowerRightCorner.X;
142 s32 y2 = rect.LowerRightCorner.Y;
143 // Black base borders
144 driver->draw2DRectangle(c_outside,
146 v2s32(x1 - m_padding, y1 - m_padding),
147 v2s32(x2 + m_padding, y1)
149 driver->draw2DRectangle(c_outside,
151 v2s32(x1 - m_padding, y2),
152 v2s32(x2 + m_padding, y2 + m_padding)
154 driver->draw2DRectangle(c_outside,
156 v2s32(x1 - m_padding, y1),
159 driver->draw2DRectangle(c_outside,
162 v2s32(x2 + m_padding, y2)
164 /*// Light inside borders
165 driver->draw2DRectangle(c_inside,
167 v2s32(x1 - padding/2, y1 - padding/2),
168 v2s32(x2 + padding/2, y1)
170 driver->draw2DRectangle(c_inside,
172 v2s32(x1 - padding/2, y2),
173 v2s32(x2 + padding/2, y2 + padding/2)
175 driver->draw2DRectangle(c_inside,
177 v2s32(x1 - padding/2, y1),
180 driver->draw2DRectangle(c_inside,
183 v2s32(x2 + padding/2, y2)
189 video::SColor bgcolor2(128, 0, 0, 0);
190 if (!use_hotbar_image)
191 driver->draw2DRectangle(bgcolor2, rect, NULL);
192 drawItemStack(driver, g_fontengine->getFont(), item, rect, NULL,
193 client, selected ? IT_ROT_SELECTED : IT_ROT_NONE);
196 //NOTE: selectitem = 0 -> no selected; selectitem 1-based
197 void Hud::drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount,
198 s32 inv_offset, InventoryList *mainlist, u16 selectitem, u16 direction)
200 #ifdef HAVE_TOUCHSCREENGUI
201 if (g_touchscreengui && inv_offset == 0)
202 g_touchscreengui->resetHud();
205 s32 height = m_hotbar_imagesize + m_padding * 2;
206 s32 width = (itemcount - inv_offset) * (m_hotbar_imagesize + m_padding * 2);
208 if (direction == HUD_DIR_TOP_BOTTOM || direction == HUD_DIR_BOTTOM_TOP) {
214 // Position of upper left corner of bar
215 v2s32 pos = screen_offset;
216 pos.X *= m_hud_scaling * porting::getDisplayDensity();
217 pos.Y *= m_hud_scaling * porting::getDisplayDensity();
220 // Store hotbar_image in member variable, used by drawItem()
221 if (hotbar_image != player->hotbar_image) {
222 hotbar_image = player->hotbar_image;
223 if (hotbar_image != "")
224 use_hotbar_image = tsrc->isKnownSourceImage(hotbar_image);
226 use_hotbar_image = false;
229 // Store hotbar_selected_image in member variable, used by drawItem()
230 if (hotbar_selected_image != player->hotbar_selected_image) {
231 hotbar_selected_image = player->hotbar_selected_image;
232 if (hotbar_selected_image != "")
233 use_hotbar_selected_image = tsrc->isKnownSourceImage(hotbar_selected_image);
235 use_hotbar_selected_image = false;
238 // draw customized item background
239 if (use_hotbar_image) {
240 core::rect<s32> imgrect2(-m_padding/2, -m_padding/2,
241 width+m_padding/2, height+m_padding/2);
242 core::rect<s32> rect2 = imgrect2 + pos;
243 video::ITexture *texture = tsrc->getTexture(hotbar_image);
244 core::dimension2di imgsize(texture->getOriginalSize());
245 draw2DImageFilterScaled(driver, texture, rect2,
246 core::rect<s32>(core::position2d<s32>(0,0), imgsize),
247 NULL, hbar_colors, true);
251 core::rect<s32> imgrect(0, 0, m_hotbar_imagesize, m_hotbar_imagesize);
252 for (s32 i = inv_offset; i < itemcount && (size_t)i < mainlist->getSize(); i++) {
253 s32 fullimglen = m_hotbar_imagesize + m_padding * 2;
257 case HUD_DIR_RIGHT_LEFT:
258 steppos = v2s32(-(m_padding + (i - inv_offset) * fullimglen), m_padding);
260 case HUD_DIR_TOP_BOTTOM:
261 steppos = v2s32(m_padding, m_padding + (i - inv_offset) * fullimglen);
263 case HUD_DIR_BOTTOM_TOP:
264 steppos = v2s32(m_padding, -(m_padding + (i - inv_offset) * fullimglen));
267 steppos = v2s32(m_padding + (i - inv_offset) * fullimglen, m_padding);
271 drawItem(mainlist->getItem(i), (imgrect + pos + steppos), (i + 1) == selectitem);
273 #ifdef HAVE_TOUCHSCREENGUI
274 if (g_touchscreengui)
275 g_touchscreengui->registerHudItem(i, (imgrect + pos + steppos));
281 void Hud::drawLuaElements(const v3s16 &camera_offset)
283 u32 text_height = g_fontengine->getTextHeight();
284 irr::gui::IGUIFont* font = g_fontengine->getFont();
285 for (size_t i = 0; i != player->maxHudId(); i++) {
286 HudElement *e = player->getHud(i);
290 v2s32 pos(floor(e->pos.X * (float) m_screensize.X + 0.5),
291 floor(e->pos.Y * (float) m_screensize.Y + 0.5));
293 case HUD_ELEM_IMAGE: {
294 video::ITexture *texture = tsrc->getTexture(e->text);
298 const video::SColor color(255, 255, 255, 255);
299 const video::SColor colors[] = {color, color, color, color};
300 core::dimension2di imgsize(texture->getOriginalSize());
301 v2s32 dstsize(imgsize.Width * e->scale.X,
302 imgsize.Height * e->scale.Y);
304 dstsize.X = m_screensize.X * (e->scale.X * -0.01);
306 dstsize.Y = m_screensize.Y * (e->scale.Y * -0.01);
307 v2s32 offset((e->align.X - 1.0) * dstsize.X / 2,
308 (e->align.Y - 1.0) * dstsize.Y / 2);
309 core::rect<s32> rect(0, 0, dstsize.X, dstsize.Y);
310 rect += pos + offset + v2s32(e->offset.X, e->offset.Y);
311 draw2DImageFilterScaled(driver, texture, rect,
312 core::rect<s32>(core::position2d<s32>(0,0), imgsize),
315 case HUD_ELEM_TEXT: {
316 video::SColor color(255, (e->number >> 16) & 0xFF,
317 (e->number >> 8) & 0xFF,
318 (e->number >> 0) & 0xFF);
319 core::rect<s32> size(0, 0, e->scale.X, text_height * e->scale.Y);
320 std::wstring text = unescape_enriched(utf8_to_wide(e->text));
321 core::dimension2d<u32> textsize = font->getDimension(text.c_str());
322 v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2),
323 (e->align.Y - 1.0) * (textsize.Height / 2));
324 v2s32 offs(e->offset.X, e->offset.Y);
325 font->draw(text.c_str(), size + pos + offset + offs, color);
327 case HUD_ELEM_STATBAR: {
328 v2s32 offs(e->offset.X, e->offset.Y);
329 drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number, offs, e->size);
331 case HUD_ELEM_INVENTORY: {
332 InventoryList *inv = inventory->getList(e->text);
333 drawItems(pos, v2s32(e->offset.X, e->offset.Y), e->number, 0,
334 inv, e->item, e->dir);
336 case HUD_ELEM_WAYPOINT: {
337 v3f p_pos = player->getPosition() / BS;
338 v3f w_pos = e->world_pos * BS;
339 float distance = floor(10 * p_pos.getDistanceFrom(e->world_pos)) / 10;
340 scene::ICameraSceneNode* camera = smgr->getActiveCamera();
341 w_pos -= intToFloat(camera_offset, BS);
342 core::matrix4 trans = camera->getProjectionMatrix();
343 trans *= camera->getViewMatrix();
344 f32 transformed_pos[4] = { w_pos.X, w_pos.Y, w_pos.Z, 1.0f };
345 trans.multiplyWith1x4Matrix(transformed_pos);
346 if (transformed_pos[3] < 0)
348 f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f :
349 core::reciprocal(transformed_pos[3]);
350 pos.X = m_screensize.X * (0.5 * transformed_pos[0] * zDiv + 0.5);
351 pos.Y = m_screensize.Y * (0.5 - transformed_pos[1] * zDiv * 0.5);
352 video::SColor color(255, (e->number >> 16) & 0xFF,
353 (e->number >> 8) & 0xFF,
354 (e->number >> 0) & 0xFF);
355 core::rect<s32> size(0, 0, 200, 2 * text_height);
356 std::wstring text = unescape_enriched(utf8_to_wide(e->name));
357 font->draw(text.c_str(), size + pos, color);
358 std::ostringstream os;
359 os << distance << e->text;
360 text = unescape_enriched(utf8_to_wide(os.str()));
361 pos.Y += text_height;
362 font->draw(text.c_str(), size + pos, color);
365 infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
366 " of hud element ID " << i << " due to unrecognized type" << std::endl;
372 void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture,
373 s32 count, v2s32 offset, v2s32 size)
375 const video::SColor color(255, 255, 255, 255);
376 const video::SColor colors[] = {color, color, color, color};
378 video::ITexture *stat_texture = tsrc->getTexture(texture);
382 core::dimension2di srcd(stat_texture->getOriginalSize());
383 core::dimension2di dstd;
384 if (size == v2s32()) {
387 float size_factor = m_hud_scaling * porting::getDisplayDensity();
388 dstd.Height = size.Y * size_factor;
389 dstd.Width = size.X * size_factor;
390 offset.X *= size_factor;
391 offset.Y *= size_factor;
395 if (corner & HUD_CORNER_LOWER)
402 case HUD_DIR_RIGHT_LEFT:
403 steppos = v2s32(-1, 0);
405 case HUD_DIR_TOP_BOTTOM:
406 steppos = v2s32(0, 1);
408 case HUD_DIR_BOTTOM_TOP:
409 steppos = v2s32(0, -1);
412 steppos = v2s32(1, 0);
414 steppos.X *= dstd.Width;
415 steppos.Y *= dstd.Height;
417 for (s32 i = 0; i < count / 2; i++)
419 core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
420 core::rect<s32> dstrect(0,0, dstd.Width, dstd.Height);
423 draw2DImageFilterScaled(driver, stat_texture, dstrect, srcrect, NULL, colors, true);
429 core::rect<s32> srcrect(0, 0, srcd.Width / 2, srcd.Height);
430 core::rect<s32> dstrect(0,0, dstd.Width / 2, dstd.Height);
433 draw2DImageFilterScaled(driver, stat_texture, dstrect, srcrect, NULL, colors, true);
438 void Hud::drawHotbar(u16 playeritem) {
440 v2s32 centerlowerpos(m_displaycenter.X, m_screensize.Y);
442 InventoryList *mainlist = inventory->getList("main");
443 if (mainlist == NULL) {
444 //silently ignore this we may not be initialized completely
448 s32 hotbar_itemcount = player->hud_hotbar_itemcount;
449 s32 width = hotbar_itemcount * (m_hotbar_imagesize + m_padding * 2);
450 v2s32 pos = centerlowerpos - v2s32(width / 2, m_hotbar_imagesize + m_padding * 3);
452 if ( (float) width / (float) porting::getWindowSize().X <=
453 g_settings->getFloat("hud_hotbar_max_width")) {
454 if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
455 drawItems(pos, v2s32(0, 0), hotbar_itemcount, 0, mainlist, playeritem + 1, 0);
460 v2s32 secondpos = pos;
461 pos = pos - v2s32(0, m_hotbar_imagesize + m_padding);
463 if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
464 drawItems(pos, v2s32(0, 0), hotbar_itemcount / 2, 0,
465 mainlist, playeritem + 1, 0);
466 drawItems(secondpos, v2s32(0, 0), hotbar_itemcount,
467 hotbar_itemcount / 2, mainlist, playeritem + 1, 0);
471 //////////////////////////// compatibility code to be removed //////////////
472 // this is ugly as hell but there's no other way to keep compatibility to
474 if ((player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE)) {
475 drawStatbar(v2s32(floor(0.5 * (float)m_screensize.X + 0.5),
476 floor(1 * (float) m_screensize.Y + 0.5)),
477 HUD_CORNER_UPPER, 0, "heart.png",
478 player->hp, v2s32((-10*24)-25,-(48+24+10)), v2s32(24,24));
481 if ((player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE) &&
482 (player->getBreath() < 11)) {
483 drawStatbar(v2s32(floor(0.5 * (float)m_screensize.X + 0.5),
484 floor(1 * (float) m_screensize.Y + 0.5)),
485 HUD_CORNER_UPPER, 0, "bubble.png",
486 player->getBreath(), v2s32(25,-(48+24+10)), v2s32(24,24));
488 ////////////////////////////////////////////////////////////////////////////
492 void Hud::drawCrosshair()
494 if (use_crosshair_image) {
495 video::ITexture *crosshair = tsrc->getTexture("crosshair.png");
496 v2u32 size = crosshair->getOriginalSize();
497 v2s32 lsize = v2s32(m_displaycenter.X - (size.X / 2),
498 m_displaycenter.Y - (size.Y / 2));
499 driver->draw2DImage(crosshair, lsize,
500 core::rect<s32>(0, 0, size.X, size.Y),
501 0, crosshair_argb, true);
503 driver->draw2DLine(m_displaycenter - v2s32(10, 0),
504 m_displaycenter + v2s32(10, 0), crosshair_argb);
505 driver->draw2DLine(m_displaycenter - v2s32(0, 10),
506 m_displaycenter + v2s32(0, 10), crosshair_argb);
510 void Hud::setSelectionPos(const v3f &pos, const v3s16 &camera_offset)
512 m_camera_offset = camera_offset;
513 m_selection_pos = pos;
514 m_selection_pos_with_offset = pos - intToFloat(camera_offset, BS);
517 void Hud::drawSelectionMesh()
519 if (m_mode == HIGHLIGHT_BOX) {
520 // Draw 3D selection boxes
521 video::SMaterial oldmaterial = driver->getMaterial2D();
522 driver->setMaterial(m_selection_material);
523 for (std::vector<aabb3f>::const_iterator
524 i = m_selection_boxes.begin();
525 i != m_selection_boxes.end(); ++i) {
527 i->MinEdge + m_selection_pos_with_offset,
528 i->MaxEdge + m_selection_pos_with_offset);
530 u32 r = (selectionbox_argb.getRed() *
531 m_selection_mesh_color.getRed() / 255);
532 u32 g = (selectionbox_argb.getGreen() *
533 m_selection_mesh_color.getGreen() / 255);
534 u32 b = (selectionbox_argb.getBlue() *
535 m_selection_mesh_color.getBlue() / 255);
536 driver->draw3DBox(box, video::SColor(255, r, g, b));
538 driver->setMaterial(oldmaterial);
539 } else if (m_mode == HIGHLIGHT_HALO && m_selection_mesh) {
540 // Draw selection mesh
541 video::SMaterial oldmaterial = driver->getMaterial2D();
542 driver->setMaterial(m_selection_material);
543 setMeshColor(m_selection_mesh, m_selection_mesh_color);
544 video::SColor face_color(0,
545 MYMIN(255, m_selection_mesh_color.getRed() * 1.5),
546 MYMIN(255, m_selection_mesh_color.getGreen() * 1.5),
547 MYMIN(255, m_selection_mesh_color.getBlue() * 1.5));
548 setMeshColorByNormal(m_selection_mesh, m_selected_face_normal,
550 scene::IMesh* mesh = cloneMesh(m_selection_mesh);
551 translateMesh(mesh, m_selection_pos_with_offset);
552 u32 mc = m_selection_mesh->getMeshBufferCount();
553 for (u32 i = 0; i < mc; i++) {
554 scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
555 driver->drawMeshBuffer(buf);
558 driver->setMaterial(oldmaterial);
562 void Hud::updateSelectionMesh(const v3s16 &camera_offset)
564 m_camera_offset = camera_offset;
565 if (m_mode != HIGHLIGHT_HALO)
568 if (m_selection_mesh) {
569 m_selection_mesh->drop();
570 m_selection_mesh = NULL;
573 if (!m_selection_boxes.size()) {
578 // New pointed object, create new mesh.
580 // Texture UV coordinates for selection boxes
581 static f32 texture_uv[24] = {
590 // Use single halo box instead of multiple overlapping boxes.
591 // Temporary solution - problem can be solved with multiple
592 // rendering targets, or some method to remove inner surfaces.
593 // Thats because of halo transparency.
595 aabb3f halo_box(100.0, 100.0, 100.0, -100.0, -100.0, -100.0);
596 m_halo_boxes.clear();
598 for (std::vector<aabb3f>::iterator
599 i = m_selection_boxes.begin();
600 i != m_selection_boxes.end(); ++i) {
601 halo_box.addInternalBox(*i);
604 m_halo_boxes.push_back(halo_box);
605 m_selection_mesh = convertNodeboxesToMesh(
606 m_halo_boxes, texture_uv, 0.5);
609 void Hud::resizeHotbar() {
610 if (m_screensize != porting::getWindowSize()) {
611 m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE * porting::getDisplayDensity() + 0.5);
612 m_hotbar_imagesize *= m_hud_scaling;
613 m_padding = m_hotbar_imagesize / 12;
614 m_screensize = porting::getWindowSize();
615 m_displaycenter = v2s32(m_screensize.X/2,m_screensize.Y/2);
619 struct MeshTimeInfo {
624 void drawItemStack(video::IVideoDriver *driver,
626 const ItemStack &item,
627 const core::rect<s32> &rect,
628 const core::rect<s32> *clip,
630 ItemRotationKind rotation_kind)
632 static MeshTimeInfo rotation_time_infos[IT_ROT_NONE];
633 static thread_local bool enable_animations =
634 g_settings->getBool("inventory_items_animations");
637 if (rotation_kind < IT_ROT_NONE) {
638 rotation_time_infos[rotation_kind].mesh = NULL;
643 const ItemDefinition &def = item.getDefinition(client->idef());
644 ItemMesh *imesh = client->idef()->getWieldMesh(def.name, client);
646 if (imesh && imesh->mesh) {
647 scene::IMesh *mesh = imesh->mesh;
648 driver->clearZBuffer();
650 if (rotation_kind < IT_ROT_NONE) {
651 MeshTimeInfo &ti = rotation_time_infos[rotation_kind];
652 if (mesh != ti.mesh) {
654 ti.time = porting::getTimeMs();
656 delta = porting::getDeltaMs(ti.time, porting::getTimeMs()) % 100000;
659 core::rect<s32> oldViewPort = driver->getViewPort();
660 core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION);
661 core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW);
662 core::matrix4 ProjMatrix;
663 ProjMatrix.buildProjectionMatrixOrthoLH(2, 2, -1, 100);
664 driver->setTransform(video::ETS_PROJECTION, ProjMatrix);
665 driver->setTransform(video::ETS_VIEW, ProjMatrix);
666 core::matrix4 matrix;
667 matrix.makeIdentity();
669 if (enable_animations) {
670 float timer_f = (float) delta / 5000.0;
671 matrix.setRotationDegrees(core::vector3df(0, 360 * timer_f, 0));
674 driver->setTransform(video::ETS_WORLD, matrix);
675 driver->setViewPort(rect);
677 video::SColor basecolor =
678 client->idef()->getItemstackColor(item, client);
680 u32 mc = mesh->getMeshBufferCount();
681 for (u32 j = 0; j < mc; ++j) {
682 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
683 // we can modify vertices relatively fast,
684 // because these meshes are not buffered.
685 assert(buf->getHardwareMappingHint_Vertex() == scene::EHM_NEVER);
686 video::SColor c = basecolor;
687 if (imesh->buffer_colors.size() > j) {
688 ItemPartColor *p = &imesh->buffer_colors[j];
689 if (p->override_base)
692 if (imesh->needs_shading)
693 colorizeMeshBuffer(buf, &c);
695 setMeshBufferColor(buf, c);
696 video::SMaterial &material = buf->getMaterial();
697 material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
698 material.Lighting = false;
699 driver->setMaterial(material);
700 driver->drawMeshBuffer(buf);
703 driver->setTransform(video::ETS_VIEW, oldViewMat);
704 driver->setTransform(video::ETS_PROJECTION, oldProjMat);
705 driver->setViewPort(oldViewPort);
708 if(def.type == ITEM_TOOL && item.wear != 0)
710 // Draw a progressbar
711 float barheight = rect.getHeight()/16;
712 float barpad_x = rect.getWidth()/16;
713 float barpad_y = rect.getHeight()/16;
714 core::rect<s32> progressrect(
715 rect.UpperLeftCorner.X + barpad_x,
716 rect.LowerRightCorner.Y - barpad_y - barheight,
717 rect.LowerRightCorner.X - barpad_x,
718 rect.LowerRightCorner.Y - barpad_y);
720 // Shrink progressrect by amount of tool damage
721 float wear = item.wear / 65535.0;
723 wear * progressrect.UpperLeftCorner.X +
724 (1-wear) * progressrect.LowerRightCorner.X;
726 // Compute progressbar color
728 // wear = 0.5: yellow
730 video::SColor color(255,255,255,255);
731 int wear_i = MYMIN(floor(wear * 600), 511);
732 wear_i = MYMIN(wear_i + 10, 511);
734 color.set(255, wear_i, 255, 0);
736 color.set(255, 255, 511-wear_i, 0);
738 core::rect<s32> progressrect2 = progressrect;
739 progressrect2.LowerRightCorner.X = progressmid;
740 driver->draw2DRectangle(color, progressrect2, clip);
742 color = video::SColor(255,0,0,0);
743 progressrect2 = progressrect;
744 progressrect2.UpperLeftCorner.X = progressmid;
745 driver->draw2DRectangle(color, progressrect2, clip);
748 if(font != NULL && item.count >= 2)
750 // Get the item count as a string
751 std::string text = itos(item.count);
752 v2u32 dim = font->getDimension(utf8_to_wide(text).c_str());
753 v2s32 sdim(dim.X,dim.Y);
755 core::rect<s32> rect2(
756 /*rect.UpperLeftCorner,
757 core::dimension2d<u32>(rect.getWidth(), 15)*/
758 rect.LowerRightCorner - sdim,
762 video::SColor bgcolor(128,0,0,0);
763 driver->draw2DRectangle(bgcolor, rect2, clip);
765 video::SColor color(255,255,255,255);
766 font->draw(text.c_str(), rect2, color, false, false, clip);