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>
37 #include "client/renderingengine.h"
39 #ifdef HAVE_TOUCHSCREENGUI
40 #include "touchscreengui.h"
43 Hud::Hud(video::IVideoDriver *driver, scene::ISceneManager* smgr,
44 gui::IGUIEnvironment* guienv, Client *client, LocalPlayer *player,
47 this->driver = driver;
49 this->guienv = guienv;
50 this->client = client;
51 this->player = player;
52 this->inventory = inventory;
54 m_hud_scaling = g_settings->getFloat("hud_scaling");
55 m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE *
56 RenderingEngine::getDisplayDensity() + 0.5f);
57 m_hotbar_imagesize *= m_hud_scaling;
58 m_padding = m_hotbar_imagesize / 12;
60 for (unsigned int i = 0; i < 4; i++)
61 hbar_colors[i] = video::SColor(255, 255, 255, 255);
63 tsrc = client->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");
80 m_selection_boxes.clear();
83 std::string mode_setting = g_settings->get("node_highlighting");
85 if (mode_setting == "halo") {
86 m_mode = HIGHLIGHT_HALO;
87 } else if (mode_setting == "none") {
88 m_mode = HIGHLIGHT_NONE;
90 m_mode = HIGHLIGHT_BOX;
93 m_selection_material.Lighting = false;
95 if (g_settings->getBool("enable_shaders")) {
96 IShaderSource *shdrsrc = client->getShaderSource();
97 u16 shader_id = shdrsrc->getShader(
98 m_mode == HIGHLIGHT_HALO ? "selection_shader" : "default_shader", 1, 1);
99 m_selection_material.MaterialType = shdrsrc->getShaderInfo(shader_id).material;
101 m_selection_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
104 if (m_mode == HIGHLIGHT_BOX) {
105 m_selection_material.Thickness =
106 rangelim(g_settings->getS16("selectionbox_width"), 1, 5);
107 } else if (m_mode == HIGHLIGHT_HALO) {
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 client, selected ? IT_ROT_SELECTED : IT_ROT_NONE);
198 //NOTE: selectitem = 0 -> no selected; selectitem 1-based
199 void Hud::drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount,
200 s32 inv_offset, InventoryList *mainlist, u16 selectitem, u16 direction)
202 #ifdef HAVE_TOUCHSCREENGUI
203 if (g_touchscreengui && inv_offset == 0)
204 g_touchscreengui->resetHud();
207 s32 height = m_hotbar_imagesize + m_padding * 2;
208 s32 width = (itemcount - inv_offset) * (m_hotbar_imagesize + m_padding * 2);
210 if (direction == HUD_DIR_TOP_BOTTOM || direction == HUD_DIR_BOTTOM_TOP) {
216 // Position of upper left corner of bar
217 v2s32 pos = screen_offset;
218 pos.X *= m_hud_scaling * RenderingEngine::getDisplayDensity();
219 pos.Y *= m_hud_scaling * RenderingEngine::getDisplayDensity();
222 // Store hotbar_image in member variable, used by drawItem()
223 if (hotbar_image != player->hotbar_image) {
224 hotbar_image = player->hotbar_image;
225 if (hotbar_image != "")
226 use_hotbar_image = tsrc->isKnownSourceImage(hotbar_image);
228 use_hotbar_image = false;
231 // Store hotbar_selected_image in member variable, used by drawItem()
232 if (hotbar_selected_image != player->hotbar_selected_image) {
233 hotbar_selected_image = player->hotbar_selected_image;
234 if (hotbar_selected_image != "")
235 use_hotbar_selected_image = tsrc->isKnownSourceImage(hotbar_selected_image);
237 use_hotbar_selected_image = false;
240 // draw customized item background
241 if (use_hotbar_image) {
242 core::rect<s32> imgrect2(-m_padding/2, -m_padding/2,
243 width+m_padding/2, height+m_padding/2);
244 core::rect<s32> rect2 = imgrect2 + pos;
245 video::ITexture *texture = tsrc->getTexture(hotbar_image);
246 core::dimension2di imgsize(texture->getOriginalSize());
247 draw2DImageFilterScaled(driver, texture, rect2,
248 core::rect<s32>(core::position2d<s32>(0,0), imgsize),
249 NULL, hbar_colors, true);
253 core::rect<s32> imgrect(0, 0, m_hotbar_imagesize, m_hotbar_imagesize);
254 for (s32 i = inv_offset; i < itemcount && (size_t)i < mainlist->getSize(); i++) {
255 s32 fullimglen = m_hotbar_imagesize + m_padding * 2;
259 case HUD_DIR_RIGHT_LEFT:
260 steppos = v2s32(-(m_padding + (i - inv_offset) * fullimglen), m_padding);
262 case HUD_DIR_TOP_BOTTOM:
263 steppos = v2s32(m_padding, m_padding + (i - inv_offset) * fullimglen);
265 case HUD_DIR_BOTTOM_TOP:
266 steppos = v2s32(m_padding, -(m_padding + (i - inv_offset) * fullimglen));
269 steppos = v2s32(m_padding + (i - inv_offset) * fullimglen, m_padding);
273 drawItem(mainlist->getItem(i), (imgrect + pos + steppos), (i + 1) == selectitem);
275 #ifdef HAVE_TOUCHSCREENGUI
276 if (g_touchscreengui)
277 g_touchscreengui->registerHudItem(i, (imgrect + pos + steppos));
283 void Hud::drawLuaElements(const v3s16 &camera_offset)
285 u32 text_height = g_fontengine->getTextHeight();
286 irr::gui::IGUIFont* font = g_fontengine->getFont();
287 for (size_t i = 0; i != player->maxHudId(); i++) {
288 HudElement *e = player->getHud(i);
292 v2s32 pos(floor(e->pos.X * (float) m_screensize.X + 0.5),
293 floor(e->pos.Y * (float) m_screensize.Y + 0.5));
295 case HUD_ELEM_IMAGE: {
296 video::ITexture *texture = tsrc->getTexture(e->text);
300 const video::SColor color(255, 255, 255, 255);
301 const video::SColor colors[] = {color, color, color, color};
302 core::dimension2di imgsize(texture->getOriginalSize());
303 v2s32 dstsize(imgsize.Width * e->scale.X,
304 imgsize.Height * e->scale.Y);
306 dstsize.X = m_screensize.X * (e->scale.X * -0.01);
308 dstsize.Y = m_screensize.Y * (e->scale.Y * -0.01);
309 v2s32 offset((e->align.X - 1.0) * dstsize.X / 2,
310 (e->align.Y - 1.0) * dstsize.Y / 2);
311 core::rect<s32> rect(0, 0, dstsize.X, dstsize.Y);
312 rect += pos + offset + v2s32(e->offset.X, e->offset.Y);
313 draw2DImageFilterScaled(driver, texture, rect,
314 core::rect<s32>(core::position2d<s32>(0,0), imgsize),
317 case HUD_ELEM_TEXT: {
318 video::SColor color(255, (e->number >> 16) & 0xFF,
319 (e->number >> 8) & 0xFF,
320 (e->number >> 0) & 0xFF);
321 core::rect<s32> size(0, 0, e->scale.X, text_height * e->scale.Y);
322 std::wstring text = unescape_enriched(utf8_to_wide(e->text));
323 core::dimension2d<u32> textsize = font->getDimension(text.c_str());
324 v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2),
325 (e->align.Y - 1.0) * (textsize.Height / 2));
326 v2s32 offs(e->offset.X, e->offset.Y);
327 font->draw(text.c_str(), size + pos + offset + offs, color);
329 case HUD_ELEM_STATBAR: {
330 v2s32 offs(e->offset.X, e->offset.Y);
331 drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number, offs, e->size);
333 case HUD_ELEM_INVENTORY: {
334 InventoryList *inv = inventory->getList(e->text);
335 drawItems(pos, v2s32(e->offset.X, e->offset.Y), e->number, 0,
336 inv, e->item, e->dir);
338 case HUD_ELEM_WAYPOINT: {
339 v3f p_pos = player->getPosition() / BS;
340 v3f w_pos = e->world_pos * BS;
341 float distance = floor(10 * p_pos.getDistanceFrom(e->world_pos)) / 10;
342 scene::ICameraSceneNode* camera = smgr->getActiveCamera();
343 w_pos -= intToFloat(camera_offset, BS);
344 core::matrix4 trans = camera->getProjectionMatrix();
345 trans *= camera->getViewMatrix();
346 f32 transformed_pos[4] = { w_pos.X, w_pos.Y, w_pos.Z, 1.0f };
347 trans.multiplyWith1x4Matrix(transformed_pos);
348 if (transformed_pos[3] < 0)
350 f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f :
351 core::reciprocal(transformed_pos[3]);
352 pos.X = m_screensize.X * (0.5 * transformed_pos[0] * zDiv + 0.5);
353 pos.Y = m_screensize.Y * (0.5 - transformed_pos[1] * zDiv * 0.5);
354 video::SColor color(255, (e->number >> 16) & 0xFF,
355 (e->number >> 8) & 0xFF,
356 (e->number >> 0) & 0xFF);
357 core::rect<s32> size(0, 0, 200, 2 * text_height);
358 std::wstring text = unescape_enriched(utf8_to_wide(e->name));
359 font->draw(text.c_str(), size + pos, color);
360 std::ostringstream os;
361 os << distance << e->text;
362 text = unescape_enriched(utf8_to_wide(os.str()));
363 pos.Y += text_height;
364 font->draw(text.c_str(), size + pos, color);
367 infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
368 " of hud element ID " << i << " due to unrecognized type" << std::endl;
374 void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture,
375 s32 count, v2s32 offset, v2s32 size)
377 const video::SColor color(255, 255, 255, 255);
378 const video::SColor colors[] = {color, color, color, color};
380 video::ITexture *stat_texture = tsrc->getTexture(texture);
384 core::dimension2di srcd(stat_texture->getOriginalSize());
385 core::dimension2di dstd;
386 if (size == v2s32()) {
389 float size_factor = m_hud_scaling * RenderingEngine::getDisplayDensity();
390 dstd.Height = size.Y * size_factor;
391 dstd.Width = size.X * size_factor;
392 offset.X *= size_factor;
393 offset.Y *= size_factor;
397 if (corner & HUD_CORNER_LOWER)
404 case HUD_DIR_RIGHT_LEFT:
405 steppos = v2s32(-1, 0);
407 case HUD_DIR_TOP_BOTTOM:
408 steppos = v2s32(0, 1);
410 case HUD_DIR_BOTTOM_TOP:
411 steppos = v2s32(0, -1);
414 steppos = v2s32(1, 0);
416 steppos.X *= dstd.Width;
417 steppos.Y *= dstd.Height;
419 for (s32 i = 0; i < count / 2; i++)
421 core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
422 core::rect<s32> dstrect(0,0, dstd.Width, dstd.Height);
425 draw2DImageFilterScaled(driver, stat_texture, dstrect, srcrect, NULL, colors, true);
431 core::rect<s32> srcrect(0, 0, srcd.Width / 2, srcd.Height);
432 core::rect<s32> dstrect(0,0, dstd.Width / 2, dstd.Height);
435 draw2DImageFilterScaled(driver, stat_texture, dstrect, srcrect, NULL, colors, true);
440 void Hud::drawHotbar(u16 playeritem) {
442 v2s32 centerlowerpos(m_displaycenter.X, m_screensize.Y);
444 InventoryList *mainlist = inventory->getList("main");
445 if (mainlist == NULL) {
446 //silently ignore this we may not be initialized completely
450 s32 hotbar_itemcount = player->hud_hotbar_itemcount;
451 s32 width = hotbar_itemcount * (m_hotbar_imagesize + m_padding * 2);
452 v2s32 pos = centerlowerpos - v2s32(width / 2, m_hotbar_imagesize + m_padding * 3);
454 const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize();
455 if ( (float) width / (float) window_size.X <=
456 g_settings->getFloat("hud_hotbar_max_width")) {
457 if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
458 drawItems(pos, v2s32(0, 0), hotbar_itemcount, 0, mainlist, playeritem + 1, 0);
463 v2s32 secondpos = pos;
464 pos = pos - v2s32(0, m_hotbar_imagesize + m_padding);
466 if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
467 drawItems(pos, v2s32(0, 0), hotbar_itemcount / 2, 0,
468 mainlist, playeritem + 1, 0);
469 drawItems(secondpos, v2s32(0, 0), hotbar_itemcount,
470 hotbar_itemcount / 2, mainlist, playeritem + 1, 0);
474 //////////////////////////// compatibility code to be removed //////////////
475 // this is ugly as hell but there's no other way to keep compatibility to
477 if ((player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE)) {
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, "heart.png",
481 player->hp, v2s32((-10*24)-25,-(48+24+10)), v2s32(24,24));
484 if ((player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE) &&
485 (player->getBreath() < 11)) {
486 drawStatbar(v2s32(floor(0.5 * (float)m_screensize.X + 0.5),
487 floor(1 * (float) m_screensize.Y + 0.5)),
488 HUD_CORNER_UPPER, 0, "bubble.png",
489 player->getBreath(), v2s32(25,-(48+24+10)), v2s32(24,24));
491 ////////////////////////////////////////////////////////////////////////////
495 void Hud::drawCrosshair()
497 if (use_crosshair_image) {
498 video::ITexture *crosshair = tsrc->getTexture("crosshair.png");
499 v2u32 size = crosshair->getOriginalSize();
500 v2s32 lsize = v2s32(m_displaycenter.X - (size.X / 2),
501 m_displaycenter.Y - (size.Y / 2));
502 driver->draw2DImage(crosshair, lsize,
503 core::rect<s32>(0, 0, size.X, size.Y),
504 0, crosshair_argb, true);
506 driver->draw2DLine(m_displaycenter - v2s32(10, 0),
507 m_displaycenter + v2s32(10, 0), crosshair_argb);
508 driver->draw2DLine(m_displaycenter - v2s32(0, 10),
509 m_displaycenter + v2s32(0, 10), crosshair_argb);
513 void Hud::setSelectionPos(const v3f &pos, const v3s16 &camera_offset)
515 m_camera_offset = camera_offset;
516 m_selection_pos = pos;
517 m_selection_pos_with_offset = pos - intToFloat(camera_offset, BS);
520 void Hud::drawSelectionMesh()
522 if (m_mode == HIGHLIGHT_BOX) {
523 // Draw 3D selection boxes
524 video::SMaterial oldmaterial = driver->getMaterial2D();
525 driver->setMaterial(m_selection_material);
526 for (std::vector<aabb3f>::const_iterator
527 i = m_selection_boxes.begin();
528 i != m_selection_boxes.end(); ++i) {
530 i->MinEdge + m_selection_pos_with_offset,
531 i->MaxEdge + m_selection_pos_with_offset);
533 u32 r = (selectionbox_argb.getRed() *
534 m_selection_mesh_color.getRed() / 255);
535 u32 g = (selectionbox_argb.getGreen() *
536 m_selection_mesh_color.getGreen() / 255);
537 u32 b = (selectionbox_argb.getBlue() *
538 m_selection_mesh_color.getBlue() / 255);
539 driver->draw3DBox(box, video::SColor(255, r, g, b));
541 driver->setMaterial(oldmaterial);
542 } else if (m_mode == HIGHLIGHT_HALO && m_selection_mesh) {
543 // Draw selection mesh
544 video::SMaterial oldmaterial = driver->getMaterial2D();
545 driver->setMaterial(m_selection_material);
546 setMeshColor(m_selection_mesh, m_selection_mesh_color);
547 video::SColor face_color(0,
548 MYMIN(255, m_selection_mesh_color.getRed() * 1.5),
549 MYMIN(255, m_selection_mesh_color.getGreen() * 1.5),
550 MYMIN(255, m_selection_mesh_color.getBlue() * 1.5));
551 setMeshColorByNormal(m_selection_mesh, m_selected_face_normal,
553 scene::IMesh* mesh = cloneMesh(m_selection_mesh);
554 translateMesh(mesh, m_selection_pos_with_offset);
555 u32 mc = m_selection_mesh->getMeshBufferCount();
556 for (u32 i = 0; i < mc; i++) {
557 scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
558 driver->drawMeshBuffer(buf);
561 driver->setMaterial(oldmaterial);
565 void Hud::updateSelectionMesh(const v3s16 &camera_offset)
567 m_camera_offset = camera_offset;
568 if (m_mode != HIGHLIGHT_HALO)
571 if (m_selection_mesh) {
572 m_selection_mesh->drop();
573 m_selection_mesh = NULL;
576 if (!m_selection_boxes.size()) {
581 // New pointed object, create new mesh.
583 // Texture UV coordinates for selection boxes
584 static f32 texture_uv[24] = {
593 // Use single halo box instead of multiple overlapping boxes.
594 // Temporary solution - problem can be solved with multiple
595 // rendering targets, or some method to remove inner surfaces.
596 // Thats because of halo transparency.
598 aabb3f halo_box(100.0, 100.0, 100.0, -100.0, -100.0, -100.0);
599 m_halo_boxes.clear();
601 for (std::vector<aabb3f>::iterator
602 i = m_selection_boxes.begin();
603 i != m_selection_boxes.end(); ++i) {
604 halo_box.addInternalBox(*i);
607 m_halo_boxes.push_back(halo_box);
608 m_selection_mesh = convertNodeboxesToMesh(
609 m_halo_boxes, texture_uv, 0.5);
612 void Hud::resizeHotbar() {
613 const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize();
615 if (m_screensize != window_size) {
616 m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE *
617 RenderingEngine::getDisplayDensity() + 0.5);
618 m_hotbar_imagesize *= m_hud_scaling;
619 m_padding = m_hotbar_imagesize / 12;
620 m_screensize = window_size;
621 m_displaycenter = v2s32(m_screensize.X/2,m_screensize.Y/2);
625 struct MeshTimeInfo {
630 void drawItemStack(video::IVideoDriver *driver,
632 const ItemStack &item,
633 const core::rect<s32> &rect,
634 const core::rect<s32> *clip,
636 ItemRotationKind rotation_kind)
638 static MeshTimeInfo rotation_time_infos[IT_ROT_NONE];
639 static thread_local bool enable_animations =
640 g_settings->getBool("inventory_items_animations");
643 if (rotation_kind < IT_ROT_NONE) {
644 rotation_time_infos[rotation_kind].mesh = NULL;
649 const ItemDefinition &def = item.getDefinition(client->idef());
650 ItemMesh *imesh = client->idef()->getWieldMesh(def.name, client);
652 if (imesh && imesh->mesh) {
653 scene::IMesh *mesh = imesh->mesh;
654 driver->clearZBuffer();
656 if (rotation_kind < IT_ROT_NONE) {
657 MeshTimeInfo &ti = rotation_time_infos[rotation_kind];
658 if (mesh != ti.mesh) {
660 ti.time = porting::getTimeMs();
662 delta = porting::getDeltaMs(ti.time, porting::getTimeMs()) % 100000;
665 core::rect<s32> oldViewPort = driver->getViewPort();
666 core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION);
667 core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW);
668 core::matrix4 ProjMatrix;
669 ProjMatrix.buildProjectionMatrixOrthoLH(2, 2, -1, 100);
670 driver->setTransform(video::ETS_PROJECTION, ProjMatrix);
671 driver->setTransform(video::ETS_VIEW, ProjMatrix);
672 core::matrix4 matrix;
673 matrix.makeIdentity();
675 if (enable_animations) {
676 float timer_f = (float) delta / 5000.0;
677 matrix.setRotationDegrees(core::vector3df(0, 360 * timer_f, 0));
680 driver->setTransform(video::ETS_WORLD, matrix);
681 driver->setViewPort(rect);
683 video::SColor basecolor =
684 client->idef()->getItemstackColor(item, client);
686 u32 mc = mesh->getMeshBufferCount();
687 for (u32 j = 0; j < mc; ++j) {
688 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
689 // we can modify vertices relatively fast,
690 // because these meshes are not buffered.
691 assert(buf->getHardwareMappingHint_Vertex() == scene::EHM_NEVER);
692 video::SColor c = basecolor;
693 if (imesh->buffer_colors.size() > j) {
694 ItemPartColor *p = &imesh->buffer_colors[j];
695 if (p->override_base)
698 if (imesh->needs_shading)
699 colorizeMeshBuffer(buf, &c);
701 setMeshBufferColor(buf, c);
702 video::SMaterial &material = buf->getMaterial();
703 material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
704 material.Lighting = false;
705 driver->setMaterial(material);
706 driver->drawMeshBuffer(buf);
709 driver->setTransform(video::ETS_VIEW, oldViewMat);
710 driver->setTransform(video::ETS_PROJECTION, oldProjMat);
711 driver->setViewPort(oldViewPort);
714 if(def.type == ITEM_TOOL && item.wear != 0)
716 // Draw a progressbar
717 float barheight = rect.getHeight()/16;
718 float barpad_x = rect.getWidth()/16;
719 float barpad_y = rect.getHeight()/16;
720 core::rect<s32> progressrect(
721 rect.UpperLeftCorner.X + barpad_x,
722 rect.LowerRightCorner.Y - barpad_y - barheight,
723 rect.LowerRightCorner.X - barpad_x,
724 rect.LowerRightCorner.Y - barpad_y);
726 // Shrink progressrect by amount of tool damage
727 float wear = item.wear / 65535.0;
729 wear * progressrect.UpperLeftCorner.X +
730 (1-wear) * progressrect.LowerRightCorner.X;
732 // Compute progressbar color
734 // wear = 0.5: yellow
736 video::SColor color(255,255,255,255);
737 int wear_i = MYMIN(floor(wear * 600), 511);
738 wear_i = MYMIN(wear_i + 10, 511);
740 color.set(255, wear_i, 255, 0);
742 color.set(255, 255, 511-wear_i, 0);
744 core::rect<s32> progressrect2 = progressrect;
745 progressrect2.LowerRightCorner.X = progressmid;
746 driver->draw2DRectangle(color, progressrect2, clip);
748 color = video::SColor(255,0,0,0);
749 progressrect2 = progressrect;
750 progressrect2.UpperLeftCorner.X = progressmid;
751 driver->draw2DRectangle(color, progressrect2, clip);
754 if(font != NULL && item.count >= 2)
756 // Get the item count as a string
757 std::string text = itos(item.count);
758 v2u32 dim = font->getDimension(utf8_to_wide(text).c_str());
759 v2s32 sdim(dim.X,dim.Y);
761 core::rect<s32> rect2(
762 /*rect.UpperLeftCorner,
763 core::dimension2d<u32>(rect.getWidth(), 15)*/
764 rect.LowerRightCorner - sdim,
768 video::SColor bgcolor(128,0,0,0);
769 driver->draw2DRectangle(bgcolor, rect2, clip);
771 video::SColor color(255,255,255,255);
772 font->draw(text.c_str(), rect2, color, false, false, clip);