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(gui::IGUIEnvironment *guienv, Client *client, LocalPlayer *player,
46 driver = RenderingEngine::get_video_driver();
47 this->guienv = guienv;
48 this->client = client;
49 this->player = player;
50 this->inventory = inventory;
52 m_hud_scaling = g_settings->getFloat("hud_scaling");
53 m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE *
54 RenderingEngine::getDisplayDensity() + 0.5f);
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 * RenderingEngine::getDisplayDensity();
217 pos.Y *= m_hud_scaling * RenderingEngine::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 =
341 RenderingEngine::get_scene_manager()->getActiveCamera();
342 w_pos -= intToFloat(camera_offset, BS);
343 core::matrix4 trans = camera->getProjectionMatrix();
344 trans *= camera->getViewMatrix();
345 f32 transformed_pos[4] = { w_pos.X, w_pos.Y, w_pos.Z, 1.0f };
346 trans.multiplyWith1x4Matrix(transformed_pos);
347 if (transformed_pos[3] < 0)
349 f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f :
350 core::reciprocal(transformed_pos[3]);
351 pos.X = m_screensize.X * (0.5 * transformed_pos[0] * zDiv + 0.5);
352 pos.Y = m_screensize.Y * (0.5 - transformed_pos[1] * zDiv * 0.5);
353 video::SColor color(255, (e->number >> 16) & 0xFF,
354 (e->number >> 8) & 0xFF,
355 (e->number >> 0) & 0xFF);
356 core::rect<s32> size(0, 0, 200, 2 * text_height);
357 std::wstring text = unescape_enriched(utf8_to_wide(e->name));
358 font->draw(text.c_str(), size + pos, color);
359 std::ostringstream os;
360 os << distance << e->text;
361 text = unescape_enriched(utf8_to_wide(os.str()));
362 pos.Y += text_height;
363 font->draw(text.c_str(), size + pos, color);
366 infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
367 " of hud element ID " << i << " due to unrecognized type" << std::endl;
373 void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture,
374 s32 count, v2s32 offset, v2s32 size)
376 const video::SColor color(255, 255, 255, 255);
377 const video::SColor colors[] = {color, color, color, color};
379 video::ITexture *stat_texture = tsrc->getTexture(texture);
383 core::dimension2di srcd(stat_texture->getOriginalSize());
384 core::dimension2di dstd;
385 if (size == v2s32()) {
388 float size_factor = m_hud_scaling * RenderingEngine::getDisplayDensity();
389 dstd.Height = size.Y * size_factor;
390 dstd.Width = size.X * size_factor;
391 offset.X *= size_factor;
392 offset.Y *= size_factor;
396 if (corner & HUD_CORNER_LOWER)
403 case HUD_DIR_RIGHT_LEFT:
404 steppos = v2s32(-1, 0);
406 case HUD_DIR_TOP_BOTTOM:
407 steppos = v2s32(0, 1);
409 case HUD_DIR_BOTTOM_TOP:
410 steppos = v2s32(0, -1);
413 steppos = v2s32(1, 0);
415 steppos.X *= dstd.Width;
416 steppos.Y *= dstd.Height;
418 for (s32 i = 0; i < count / 2; i++)
420 core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
421 core::rect<s32> dstrect(0,0, dstd.Width, dstd.Height);
424 draw2DImageFilterScaled(driver, stat_texture, dstrect, srcrect, NULL, colors, true);
430 core::rect<s32> srcrect(0, 0, srcd.Width / 2, srcd.Height);
431 core::rect<s32> dstrect(0,0, dstd.Width / 2, dstd.Height);
434 draw2DImageFilterScaled(driver, stat_texture, dstrect, srcrect, NULL, colors, true);
439 void Hud::drawHotbar(u16 playeritem) {
441 v2s32 centerlowerpos(m_displaycenter.X, m_screensize.Y);
443 InventoryList *mainlist = inventory->getList("main");
444 if (mainlist == NULL) {
445 //silently ignore this we may not be initialized completely
449 s32 hotbar_itemcount = player->hud_hotbar_itemcount;
450 s32 width = hotbar_itemcount * (m_hotbar_imagesize + m_padding * 2);
451 v2s32 pos = centerlowerpos - v2s32(width / 2, m_hotbar_imagesize + m_padding * 3);
453 const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize();
454 if ( (float) width / (float) window_size.X <=
455 g_settings->getFloat("hud_hotbar_max_width")) {
456 if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
457 drawItems(pos, v2s32(0, 0), hotbar_itemcount, 0, mainlist, playeritem + 1, 0);
462 v2s32 secondpos = pos;
463 pos = pos - v2s32(0, m_hotbar_imagesize + m_padding);
465 if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
466 drawItems(pos, v2s32(0, 0), hotbar_itemcount / 2, 0,
467 mainlist, playeritem + 1, 0);
468 drawItems(secondpos, v2s32(0, 0), hotbar_itemcount,
469 hotbar_itemcount / 2, mainlist, playeritem + 1, 0);
473 //////////////////////////// compatibility code to be removed //////////////
474 // this is ugly as hell but there's no other way to keep compatibility to
476 if ((player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE)) {
477 drawStatbar(v2s32(floor(0.5 * (float)m_screensize.X + 0.5),
478 floor(1 * (float) m_screensize.Y + 0.5)),
479 HUD_CORNER_UPPER, 0, "heart.png",
480 player->hp, v2s32((-10*24)-25,-(48+24+10)), v2s32(24,24));
483 if ((player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE) &&
484 (player->getBreath() < 11)) {
485 drawStatbar(v2s32(floor(0.5 * (float)m_screensize.X + 0.5),
486 floor(1 * (float) m_screensize.Y + 0.5)),
487 HUD_CORNER_UPPER, 0, "bubble.png",
488 player->getBreath(), v2s32(25,-(48+24+10)), v2s32(24,24));
490 ////////////////////////////////////////////////////////////////////////////
494 void Hud::drawCrosshair()
496 if (use_crosshair_image) {
497 video::ITexture *crosshair = tsrc->getTexture("crosshair.png");
498 v2u32 size = crosshair->getOriginalSize();
499 v2s32 lsize = v2s32(m_displaycenter.X - (size.X / 2),
500 m_displaycenter.Y - (size.Y / 2));
501 driver->draw2DImage(crosshair, lsize,
502 core::rect<s32>(0, 0, size.X, size.Y),
503 0, crosshair_argb, true);
505 driver->draw2DLine(m_displaycenter - v2s32(10, 0),
506 m_displaycenter + v2s32(10, 0), crosshair_argb);
507 driver->draw2DLine(m_displaycenter - v2s32(0, 10),
508 m_displaycenter + v2s32(0, 10), crosshair_argb);
512 void Hud::setSelectionPos(const v3f &pos, const v3s16 &camera_offset)
514 m_camera_offset = camera_offset;
515 m_selection_pos = pos;
516 m_selection_pos_with_offset = pos - intToFloat(camera_offset, BS);
519 void Hud::drawSelectionMesh()
521 if (m_mode == HIGHLIGHT_BOX) {
522 // Draw 3D selection boxes
523 video::SMaterial oldmaterial = driver->getMaterial2D();
524 driver->setMaterial(m_selection_material);
525 for (std::vector<aabb3f>::const_iterator
526 i = m_selection_boxes.begin();
527 i != m_selection_boxes.end(); ++i) {
529 i->MinEdge + m_selection_pos_with_offset,
530 i->MaxEdge + m_selection_pos_with_offset);
532 u32 r = (selectionbox_argb.getRed() *
533 m_selection_mesh_color.getRed() / 255);
534 u32 g = (selectionbox_argb.getGreen() *
535 m_selection_mesh_color.getGreen() / 255);
536 u32 b = (selectionbox_argb.getBlue() *
537 m_selection_mesh_color.getBlue() / 255);
538 driver->draw3DBox(box, video::SColor(255, r, g, b));
540 driver->setMaterial(oldmaterial);
541 } else if (m_mode == HIGHLIGHT_HALO && m_selection_mesh) {
542 // Draw selection mesh
543 video::SMaterial oldmaterial = driver->getMaterial2D();
544 driver->setMaterial(m_selection_material);
545 setMeshColor(m_selection_mesh, m_selection_mesh_color);
546 video::SColor face_color(0,
547 MYMIN(255, m_selection_mesh_color.getRed() * 1.5),
548 MYMIN(255, m_selection_mesh_color.getGreen() * 1.5),
549 MYMIN(255, m_selection_mesh_color.getBlue() * 1.5));
550 setMeshColorByNormal(m_selection_mesh, m_selected_face_normal,
552 scene::IMesh* mesh = cloneMesh(m_selection_mesh);
553 translateMesh(mesh, m_selection_pos_with_offset);
554 u32 mc = m_selection_mesh->getMeshBufferCount();
555 for (u32 i = 0; i < mc; i++) {
556 scene::IMeshBuffer *buf = mesh->getMeshBuffer(i);
557 driver->drawMeshBuffer(buf);
560 driver->setMaterial(oldmaterial);
564 void Hud::updateSelectionMesh(const v3s16 &camera_offset)
566 m_camera_offset = camera_offset;
567 if (m_mode != HIGHLIGHT_HALO)
570 if (m_selection_mesh) {
571 m_selection_mesh->drop();
572 m_selection_mesh = NULL;
575 if (!m_selection_boxes.size()) {
580 // New pointed object, create new mesh.
582 // Texture UV coordinates for selection boxes
583 static f32 texture_uv[24] = {
592 // Use single halo box instead of multiple overlapping boxes.
593 // Temporary solution - problem can be solved with multiple
594 // rendering targets, or some method to remove inner surfaces.
595 // Thats because of halo transparency.
597 aabb3f halo_box(100.0, 100.0, 100.0, -100.0, -100.0, -100.0);
598 m_halo_boxes.clear();
600 for (std::vector<aabb3f>::iterator
601 i = m_selection_boxes.begin();
602 i != m_selection_boxes.end(); ++i) {
603 halo_box.addInternalBox(*i);
606 m_halo_boxes.push_back(halo_box);
607 m_selection_mesh = convertNodeboxesToMesh(
608 m_halo_boxes, texture_uv, 0.5);
611 void Hud::resizeHotbar() {
612 const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize();
614 if (m_screensize != window_size) {
615 m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE *
616 RenderingEngine::getDisplayDensity() + 0.5);
617 m_hotbar_imagesize *= m_hud_scaling;
618 m_padding = m_hotbar_imagesize / 12;
619 m_screensize = window_size;
620 m_displaycenter = v2s32(m_screensize.X/2,m_screensize.Y/2);
624 struct MeshTimeInfo {
629 void drawItemStack(video::IVideoDriver *driver,
631 const ItemStack &item,
632 const core::rect<s32> &rect,
633 const core::rect<s32> *clip,
635 ItemRotationKind rotation_kind)
637 static MeshTimeInfo rotation_time_infos[IT_ROT_NONE];
638 static thread_local bool enable_animations =
639 g_settings->getBool("inventory_items_animations");
642 if (rotation_kind < IT_ROT_NONE) {
643 rotation_time_infos[rotation_kind].mesh = NULL;
648 const ItemDefinition &def = item.getDefinition(client->idef());
649 ItemMesh *imesh = client->idef()->getWieldMesh(def.name, client);
651 if (imesh && imesh->mesh) {
652 scene::IMesh *mesh = imesh->mesh;
653 driver->clearZBuffer();
655 if (rotation_kind < IT_ROT_NONE) {
656 MeshTimeInfo &ti = rotation_time_infos[rotation_kind];
657 if (mesh != ti.mesh) {
659 ti.time = porting::getTimeMs();
661 delta = porting::getDeltaMs(ti.time, porting::getTimeMs()) % 100000;
664 core::rect<s32> oldViewPort = driver->getViewPort();
665 core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION);
666 core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW);
667 core::matrix4 ProjMatrix;
668 ProjMatrix.buildProjectionMatrixOrthoLH(2, 2, -1, 100);
669 driver->setTransform(video::ETS_PROJECTION, ProjMatrix);
670 driver->setTransform(video::ETS_VIEW, ProjMatrix);
671 core::matrix4 matrix;
672 matrix.makeIdentity();
674 if (enable_animations) {
675 float timer_f = (float) delta / 5000.0;
676 matrix.setRotationDegrees(core::vector3df(0, 360 * timer_f, 0));
679 driver->setTransform(video::ETS_WORLD, matrix);
680 driver->setViewPort(rect);
682 video::SColor basecolor =
683 client->idef()->getItemstackColor(item, client);
685 u32 mc = mesh->getMeshBufferCount();
686 for (u32 j = 0; j < mc; ++j) {
687 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
688 // we can modify vertices relatively fast,
689 // because these meshes are not buffered.
690 assert(buf->getHardwareMappingHint_Vertex() == scene::EHM_NEVER);
691 video::SColor c = basecolor;
692 if (imesh->buffer_colors.size() > j) {
693 ItemPartColor *p = &imesh->buffer_colors[j];
694 if (p->override_base)
697 if (imesh->needs_shading)
698 colorizeMeshBuffer(buf, &c);
700 setMeshBufferColor(buf, c);
701 video::SMaterial &material = buf->getMaterial();
702 material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
703 material.Lighting = false;
704 driver->setMaterial(material);
705 driver->drawMeshBuffer(buf);
708 driver->setTransform(video::ETS_VIEW, oldViewMat);
709 driver->setTransform(video::ETS_PROJECTION, oldProjMat);
710 driver->setViewPort(oldViewPort);
713 if(def.type == ITEM_TOOL && item.wear != 0)
715 // Draw a progressbar
716 float barheight = rect.getHeight()/16;
717 float barpad_x = rect.getWidth()/16;
718 float barpad_y = rect.getHeight()/16;
719 core::rect<s32> progressrect(
720 rect.UpperLeftCorner.X + barpad_x,
721 rect.LowerRightCorner.Y - barpad_y - barheight,
722 rect.LowerRightCorner.X - barpad_x,
723 rect.LowerRightCorner.Y - barpad_y);
725 // Shrink progressrect by amount of tool damage
726 float wear = item.wear / 65535.0;
728 wear * progressrect.UpperLeftCorner.X +
729 (1-wear) * progressrect.LowerRightCorner.X;
731 // Compute progressbar color
733 // wear = 0.5: yellow
735 video::SColor color(255,255,255,255);
736 int wear_i = MYMIN(floor(wear * 600), 511);
737 wear_i = MYMIN(wear_i + 10, 511);
739 color.set(255, wear_i, 255, 0);
741 color.set(255, 255, 511-wear_i, 0);
743 core::rect<s32> progressrect2 = progressrect;
744 progressrect2.LowerRightCorner.X = progressmid;
745 driver->draw2DRectangle(color, progressrect2, clip);
747 color = video::SColor(255,0,0,0);
748 progressrect2 = progressrect;
749 progressrect2.UpperLeftCorner.X = progressmid;
750 driver->draw2DRectangle(color, progressrect2, clip);
753 if(font != NULL && item.count >= 2)
755 // Get the item count as a string
756 std::string text = itos(item.count);
757 v2u32 dim = font->getDimension(utf8_to_wide(text).c_str());
758 v2s32 sdim(dim.X,dim.Y);
760 core::rect<s32> rect2(
761 /*rect.UpperLeftCorner,
762 core::dimension2d<u32>(rect.getWidth(), 15)*/
763 rect.LowerRightCorner - sdim,
767 video::SColor bgcolor(128,0,0,0);
768 driver->draw2DRectangle(bgcolor, rect2, clip);
770 video::SColor color(255,255,255,255);
771 font->draw(text.c_str(), rect2, color, false, false, clip);