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.
22 #include "client/hud.h"
25 #include "util/numeric.h"
28 #include "inventory.h"
30 #include "client/tile.h"
31 #include "localplayer.h"
34 #include "fontengine.h"
35 #include "guiscalingfilter.h"
37 #include "wieldmesh.h"
38 #include "client/renderingengine.h"
40 #ifdef HAVE_TOUCHSCREENGUI
41 #include "gui/touchscreengui.h"
44 Hud::Hud(gui::IGUIEnvironment *guienv, Client *client, LocalPlayer *player,
47 driver = RenderingEngine::get_video_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 = std::floor(HOTBAR_IMAGE_SIZE *
55 RenderingEngine::getDisplayDensity() + 0.5f);
56 m_hotbar_imagesize *= m_hud_scaling;
57 m_padding = m_hotbar_imagesize / 12;
59 for (auto &hbar_color : hbar_colors)
60 hbar_color = video::SColor(255, 255, 255, 255);
62 tsrc = client->getTextureSource();
64 v3f crosshair_color = g_settings->getV3F("crosshair_color");
65 u32 cross_r = rangelim(myround(crosshair_color.X), 0, 255);
66 u32 cross_g = rangelim(myround(crosshair_color.Y), 0, 255);
67 u32 cross_b = rangelim(myround(crosshair_color.Z), 0, 255);
68 u32 cross_a = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255);
69 crosshair_argb = video::SColor(cross_a, cross_r, cross_g, cross_b);
71 v3f selectionbox_color = g_settings->getV3F("selectionbox_color");
72 u32 sbox_r = rangelim(myround(selectionbox_color.X), 0, 255);
73 u32 sbox_g = rangelim(myround(selectionbox_color.Y), 0, 255);
74 u32 sbox_b = rangelim(myround(selectionbox_color.Z), 0, 255);
75 selectionbox_argb = video::SColor(255, sbox_r, sbox_g, sbox_b);
77 use_crosshair_image = tsrc->isKnownSourceImage("crosshair.png");
79 m_selection_boxes.clear();
82 std::string mode_setting = g_settings->get("node_highlighting");
84 if (mode_setting == "halo") {
85 m_mode = HIGHLIGHT_HALO;
86 } else if (mode_setting == "none") {
87 m_mode = HIGHLIGHT_NONE;
89 m_mode = HIGHLIGHT_BOX;
92 m_selection_material.Lighting = false;
94 if (g_settings->getBool("enable_shaders")) {
95 IShaderSource *shdrsrc = client->getShaderSource();
96 u16 shader_id = shdrsrc->getShader(
97 m_mode == HIGHLIGHT_HALO ? "selection_shader" : "default_shader", 1, 1);
98 m_selection_material.MaterialType = shdrsrc->getShaderInfo(shader_id).material;
100 m_selection_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
103 if (m_mode == HIGHLIGHT_BOX) {
104 m_selection_material.Thickness =
105 rangelim(g_settings->getS16("selectionbox_width"), 1, 5);
106 } else if (m_mode == HIGHLIGHT_HALO) {
107 m_selection_material.setTexture(0, tsrc->getTextureForMesh("halo.png"));
108 m_selection_material.setFlag(video::EMF_BACK_FACE_CULLING, true);
110 m_selection_material.MaterialType = video::EMT_SOLID;
116 if (m_selection_mesh)
117 m_selection_mesh->drop();
120 void Hud::drawItem(const ItemStack &item, const core::rect<s32>& rect,
124 /* draw hihlighting around selected item */
125 if (use_hotbar_selected_image) {
126 core::rect<s32> imgrect2 = rect;
127 imgrect2.UpperLeftCorner.X -= (m_padding*2);
128 imgrect2.UpperLeftCorner.Y -= (m_padding*2);
129 imgrect2.LowerRightCorner.X += (m_padding*2);
130 imgrect2.LowerRightCorner.Y += (m_padding*2);
131 video::ITexture *texture = tsrc->getTexture(hotbar_selected_image);
132 core::dimension2di imgsize(texture->getOriginalSize());
133 draw2DImageFilterScaled(driver, texture, imgrect2,
134 core::rect<s32>(core::position2d<s32>(0,0), imgsize),
135 NULL, hbar_colors, true);
137 video::SColor c_outside(255,255,0,0);
138 //video::SColor c_outside(255,0,0,0);
139 //video::SColor c_inside(255,192,192,192);
140 s32 x1 = rect.UpperLeftCorner.X;
141 s32 y1 = rect.UpperLeftCorner.Y;
142 s32 x2 = rect.LowerRightCorner.X;
143 s32 y2 = rect.LowerRightCorner.Y;
144 // Black base borders
145 driver->draw2DRectangle(c_outside,
147 v2s32(x1 - m_padding, y1 - m_padding),
148 v2s32(x2 + m_padding, y1)
150 driver->draw2DRectangle(c_outside,
152 v2s32(x1 - m_padding, y2),
153 v2s32(x2 + m_padding, y2 + m_padding)
155 driver->draw2DRectangle(c_outside,
157 v2s32(x1 - m_padding, y1),
160 driver->draw2DRectangle(c_outside,
163 v2s32(x2 + m_padding, y2)
165 /*// Light inside borders
166 driver->draw2DRectangle(c_inside,
168 v2s32(x1 - padding/2, y1 - padding/2),
169 v2s32(x2 + padding/2, y1)
171 driver->draw2DRectangle(c_inside,
173 v2s32(x1 - padding/2, y2),
174 v2s32(x2 + padding/2, y2 + padding/2)
176 driver->draw2DRectangle(c_inside,
178 v2s32(x1 - padding/2, y1),
181 driver->draw2DRectangle(c_inside,
184 v2s32(x2 + padding/2, y2)
190 video::SColor bgcolor2(128, 0, 0, 0);
191 if (!use_hotbar_image)
192 driver->draw2DRectangle(bgcolor2, rect, NULL);
193 drawItemStack(driver, g_fontengine->getFont(), item, rect, NULL,
194 client, selected ? IT_ROT_SELECTED : IT_ROT_NONE);
197 //NOTE: selectitem = 0 -> no selected; selectitem 1-based
198 void Hud::drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount,
199 s32 inv_offset, InventoryList *mainlist, u16 selectitem, u16 direction)
201 #ifdef HAVE_TOUCHSCREENGUI
202 if (g_touchscreengui && inv_offset == 0)
203 g_touchscreengui->resetHud();
206 s32 height = m_hotbar_imagesize + m_padding * 2;
207 s32 width = (itemcount - inv_offset) * (m_hotbar_imagesize + m_padding * 2);
209 if (direction == HUD_DIR_TOP_BOTTOM || direction == HUD_DIR_BOTTOM_TOP) {
215 // Position of upper left corner of bar
216 v2s32 pos = screen_offset;
217 pos.X *= m_hud_scaling * RenderingEngine::getDisplayDensity();
218 pos.Y *= m_hud_scaling * RenderingEngine::getDisplayDensity();
221 // Store hotbar_image in member variable, used by drawItem()
222 if (hotbar_image != player->hotbar_image) {
223 hotbar_image = player->hotbar_image;
224 if (!hotbar_image.empty())
225 use_hotbar_image = tsrc->isKnownSourceImage(hotbar_image);
227 use_hotbar_image = false;
230 // Store hotbar_selected_image in member variable, used by drawItem()
231 if (hotbar_selected_image != player->hotbar_selected_image) {
232 hotbar_selected_image = player->hotbar_selected_image;
233 if (!hotbar_selected_image.empty())
234 use_hotbar_selected_image = tsrc->isKnownSourceImage(hotbar_selected_image);
236 use_hotbar_selected_image = false;
239 // draw customized item background
240 if (use_hotbar_image) {
241 core::rect<s32> imgrect2(-m_padding/2, -m_padding/2,
242 width+m_padding/2, height+m_padding/2);
243 core::rect<s32> rect2 = imgrect2 + pos;
244 video::ITexture *texture = tsrc->getTexture(hotbar_image);
245 core::dimension2di imgsize(texture->getOriginalSize());
246 draw2DImageFilterScaled(driver, texture, rect2,
247 core::rect<s32>(core::position2d<s32>(0,0), imgsize),
248 NULL, hbar_colors, true);
252 core::rect<s32> imgrect(0, 0, m_hotbar_imagesize, m_hotbar_imagesize);
253 for (s32 i = inv_offset; i < itemcount && (size_t)i < mainlist->getSize(); i++) {
254 s32 fullimglen = m_hotbar_imagesize + m_padding * 2;
258 case HUD_DIR_RIGHT_LEFT:
259 steppos = v2s32(-(m_padding + (i - inv_offset) * fullimglen), m_padding);
261 case HUD_DIR_TOP_BOTTOM:
262 steppos = v2s32(m_padding, m_padding + (i - inv_offset) * fullimglen);
264 case HUD_DIR_BOTTOM_TOP:
265 steppos = v2s32(m_padding, -(m_padding + (i - inv_offset) * fullimglen));
268 steppos = v2s32(m_padding + (i - inv_offset) * fullimglen, m_padding);
272 drawItem(mainlist->getItem(i), (imgrect + pos + steppos), (i + 1) == selectitem);
274 #ifdef HAVE_TOUCHSCREENGUI
275 if (g_touchscreengui)
276 g_touchscreengui->registerHudItem(i, (imgrect + pos + steppos));
282 void Hud::drawLuaElements(const v3s16 &camera_offset)
284 u32 text_height = g_fontengine->getTextHeight();
285 irr::gui::IGUIFont* font = g_fontengine->getFont();
286 for (size_t i = 0; i != player->maxHudId(); i++) {
287 HudElement *e = player->getHud(i);
291 v2s32 pos(floor(e->pos.X * (float) m_screensize.X + 0.5),
292 floor(e->pos.Y * (float) m_screensize.Y + 0.5));
294 case HUD_ELEM_IMAGE: {
295 video::ITexture *texture = tsrc->getTexture(e->text);
299 const video::SColor color(255, 255, 255, 255);
300 const video::SColor colors[] = {color, color, color, color};
301 core::dimension2di imgsize(texture->getOriginalSize());
302 v2s32 dstsize(imgsize.Width * e->scale.X,
303 imgsize.Height * e->scale.Y);
305 dstsize.X = m_screensize.X * (e->scale.X * -0.01);
307 dstsize.Y = m_screensize.Y * (e->scale.Y * -0.01);
308 v2s32 offset((e->align.X - 1.0) * dstsize.X / 2,
309 (e->align.Y - 1.0) * dstsize.Y / 2);
310 core::rect<s32> rect(0, 0, dstsize.X, dstsize.Y);
311 rect += pos + offset + v2s32(e->offset.X, e->offset.Y);
312 draw2DImageFilterScaled(driver, texture, rect,
313 core::rect<s32>(core::position2d<s32>(0,0), imgsize),
316 case HUD_ELEM_TEXT: {
317 video::SColor color(255, (e->number >> 16) & 0xFF,
318 (e->number >> 8) & 0xFF,
319 (e->number >> 0) & 0xFF);
320 core::rect<s32> size(0, 0, e->scale.X, text_height * e->scale.Y);
321 std::wstring text = unescape_translate(utf8_to_wide(e->text));
322 core::dimension2d<u32> textsize = font->getDimension(text.c_str());
323 v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2),
324 (e->align.Y - 1.0) * (textsize.Height / 2));
325 v2s32 offs(e->offset.X, e->offset.Y);
326 font->draw(text.c_str(), size + pos + offset + offs, color);
328 case HUD_ELEM_STATBAR: {
329 v2s32 offs(e->offset.X, e->offset.Y);
330 drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number, offs, e->size);
332 case HUD_ELEM_INVENTORY: {
333 InventoryList *inv = inventory->getList(e->text);
334 drawItems(pos, v2s32(e->offset.X, e->offset.Y), e->number, 0,
335 inv, e->item, e->dir);
337 case HUD_ELEM_WAYPOINT: {
338 v3f p_pos = player->getPosition() / BS;
339 v3f w_pos = e->world_pos * BS;
340 float distance = std::floor(10 * p_pos.getDistanceFrom(e->world_pos)) /
342 scene::ICameraSceneNode* camera =
343 RenderingEngine::get_scene_manager()->getActiveCamera();
344 w_pos -= intToFloat(camera_offset, BS);
345 core::matrix4 trans = camera->getProjectionMatrix();
346 trans *= camera->getViewMatrix();
347 f32 transformed_pos[4] = { w_pos.X, w_pos.Y, w_pos.Z, 1.0f };
348 trans.multiplyWith1x4Matrix(transformed_pos);
349 if (transformed_pos[3] < 0)
351 f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f :
352 core::reciprocal(transformed_pos[3]);
353 pos.X = m_screensize.X * (0.5 * transformed_pos[0] * zDiv + 0.5);
354 pos.Y = m_screensize.Y * (0.5 - transformed_pos[1] * zDiv * 0.5);
355 video::SColor color(255, (e->number >> 16) & 0xFF,
356 (e->number >> 8) & 0xFF,
357 (e->number >> 0) & 0xFF);
358 core::rect<s32> size(0, 0, 200, 2 * text_height);
359 std::wstring text = unescape_translate(utf8_to_wide(e->name));
360 font->draw(text.c_str(), size + pos, color);
361 std::ostringstream os;
362 os << distance << e->text;
363 text = unescape_translate(utf8_to_wide(os.str()));
364 pos.Y += text_height;
365 font->draw(text.c_str(), size + pos, color);
368 infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
369 " of hud element ID " << i << " due to unrecognized type" << std::endl;
375 void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture,
376 s32 count, v2s32 offset, v2s32 size)
378 const video::SColor color(255, 255, 255, 255);
379 const video::SColor colors[] = {color, color, color, color};
381 video::ITexture *stat_texture = tsrc->getTexture(texture);
385 core::dimension2di srcd(stat_texture->getOriginalSize());
386 core::dimension2di dstd;
387 if (size == v2s32()) {
390 float size_factor = m_hud_scaling * RenderingEngine::getDisplayDensity();
391 dstd.Height = size.Y * size_factor;
392 dstd.Width = size.X * size_factor;
393 offset.X *= size_factor;
394 offset.Y *= size_factor;
398 if (corner & HUD_CORNER_LOWER)
404 core::rect<s32> srchalfrect, dsthalfrect;
406 case HUD_DIR_RIGHT_LEFT:
407 steppos = v2s32(-1, 0);
408 srchalfrect = core::rect<s32>(srcd.Width / 2, 0, srcd.Width, srcd.Height);
409 dsthalfrect = core::rect<s32>(dstd.Width / 2, 0, dstd.Width, dstd.Height);
411 case HUD_DIR_TOP_BOTTOM:
412 steppos = v2s32(0, 1);
413 srchalfrect = core::rect<s32>(0, 0, srcd.Width, srcd.Height / 2);
414 dsthalfrect = core::rect<s32>(0, 0, dstd.Width, dstd.Height / 2);
416 case HUD_DIR_BOTTOM_TOP:
417 steppos = v2s32(0, -1);
418 srchalfrect = core::rect<s32>(0, srcd.Height / 2, srcd.Width, srcd.Height);
419 dsthalfrect = core::rect<s32>(0, dstd.Height / 2, dstd.Width, dstd.Height);
422 steppos = v2s32(1, 0);
423 srchalfrect = core::rect<s32>(0, 0, srcd.Width / 2, srcd.Height);
424 dsthalfrect = core::rect<s32>(0, 0, dstd.Width / 2, dstd.Height);
426 steppos.X *= dstd.Width;
427 steppos.Y *= dstd.Height;
429 for (s32 i = 0; i < count / 2; i++) {
430 core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
431 core::rect<s32> dstrect(0,0, dstd.Width, dstd.Height);
434 draw2DImageFilterScaled(driver, stat_texture, dstrect, srcrect, NULL, colors, true);
438 if (count % 2 == 1) {
440 draw2DImageFilterScaled(driver, stat_texture, dsthalfrect, srchalfrect, NULL, colors, true);
445 void Hud::drawHotbar(u16 playeritem) {
447 v2s32 centerlowerpos(m_displaycenter.X, m_screensize.Y);
449 InventoryList *mainlist = inventory->getList("main");
450 if (mainlist == NULL) {
451 //silently ignore this we may not be initialized completely
455 s32 hotbar_itemcount = player->hud_hotbar_itemcount;
456 s32 width = hotbar_itemcount * (m_hotbar_imagesize + m_padding * 2);
457 v2s32 pos = centerlowerpos - v2s32(width / 2, m_hotbar_imagesize + m_padding * 3);
459 const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize();
460 if ( (float) width / (float) window_size.X <=
461 g_settings->getFloat("hud_hotbar_max_width")) {
462 if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
463 drawItems(pos, v2s32(0, 0), hotbar_itemcount, 0, mainlist, playeritem + 1, 0);
468 v2s32 secondpos = pos;
469 pos = pos - v2s32(0, m_hotbar_imagesize + m_padding);
471 if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE) {
472 drawItems(pos, v2s32(0, 0), hotbar_itemcount / 2, 0,
473 mainlist, playeritem + 1, 0);
474 drawItems(secondpos, v2s32(0, 0), hotbar_itemcount,
475 hotbar_itemcount / 2, mainlist, playeritem + 1, 0);
481 void Hud::drawCrosshair()
483 if (use_crosshair_image) {
484 video::ITexture *crosshair = tsrc->getTexture("crosshair.png");
485 v2u32 size = crosshair->getOriginalSize();
486 v2s32 lsize = v2s32(m_displaycenter.X - (size.X / 2),
487 m_displaycenter.Y - (size.Y / 2));
488 driver->draw2DImage(crosshair, lsize,
489 core::rect<s32>(0, 0, size.X, size.Y),
490 0, crosshair_argb, true);
492 driver->draw2DLine(m_displaycenter - v2s32(10, 0),
493 m_displaycenter + v2s32(10, 0), crosshair_argb);
494 driver->draw2DLine(m_displaycenter - v2s32(0, 10),
495 m_displaycenter + v2s32(0, 10), crosshair_argb);
499 void Hud::setSelectionPos(const v3f &pos, const v3s16 &camera_offset)
501 m_camera_offset = camera_offset;
502 m_selection_pos = pos;
503 m_selection_pos_with_offset = pos - intToFloat(camera_offset, BS);
506 void Hud::drawSelectionMesh()
508 if (m_mode == HIGHLIGHT_BOX) {
509 // Draw 3D selection boxes
510 video::SMaterial oldmaterial = driver->getMaterial2D();
511 driver->setMaterial(m_selection_material);
512 for (std::vector<aabb3f>::const_iterator
513 i = m_selection_boxes.begin();
514 i != m_selection_boxes.end(); ++i) {
516 i->MinEdge + m_selection_pos_with_offset,
517 i->MaxEdge + m_selection_pos_with_offset);
519 u32 r = (selectionbox_argb.getRed() *
520 m_selection_mesh_color.getRed() / 255);
521 u32 g = (selectionbox_argb.getGreen() *
522 m_selection_mesh_color.getGreen() / 255);
523 u32 b = (selectionbox_argb.getBlue() *
524 m_selection_mesh_color.getBlue() / 255);
525 driver->draw3DBox(box, video::SColor(255, r, g, b));
527 driver->setMaterial(oldmaterial);
528 } else if (m_mode == HIGHLIGHT_HALO && m_selection_mesh) {
529 // Draw selection mesh
530 video::SMaterial oldmaterial = driver->getMaterial2D();
531 driver->setMaterial(m_selection_material);
532 setMeshColor(m_selection_mesh, m_selection_mesh_color);
533 video::SColor face_color(0,
534 MYMIN(255, m_selection_mesh_color.getRed() * 1.5),
535 MYMIN(255, m_selection_mesh_color.getGreen() * 1.5),
536 MYMIN(255, m_selection_mesh_color.getBlue() * 1.5));
537 setMeshColorByNormal(m_selection_mesh, m_selected_face_normal,
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_mode != HIGHLIGHT_HALO)
557 if (m_selection_mesh) {
558 m_selection_mesh->drop();
559 m_selection_mesh = NULL;
562 if (m_selection_boxes.empty()) {
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 (const auto &selection_box : m_selection_boxes) {
588 halo_box.addInternalBox(selection_box);
591 m_halo_boxes.push_back(halo_box);
592 m_selection_mesh = convertNodeboxesToMesh(
593 m_halo_boxes, texture_uv, 0.5);
596 void Hud::resizeHotbar() {
597 const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize();
599 if (m_screensize != window_size) {
600 m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE *
601 RenderingEngine::getDisplayDensity() + 0.5);
602 m_hotbar_imagesize *= m_hud_scaling;
603 m_padding = m_hotbar_imagesize / 12;
604 m_screensize = window_size;
605 m_displaycenter = v2s32(m_screensize.X/2,m_screensize.Y/2);
609 struct MeshTimeInfo {
614 void drawItemStack(video::IVideoDriver *driver,
616 const ItemStack &item,
617 const core::rect<s32> &rect,
618 const core::rect<s32> *clip,
620 ItemRotationKind rotation_kind)
622 static MeshTimeInfo rotation_time_infos[IT_ROT_NONE];
623 static thread_local bool enable_animations =
624 g_settings->getBool("inventory_items_animations");
627 if (rotation_kind < IT_ROT_NONE) {
628 rotation_time_infos[rotation_kind].mesh = NULL;
633 const ItemDefinition &def = item.getDefinition(client->idef());
634 ItemMesh *imesh = client->idef()->getWieldMesh(def.name, client);
636 if (imesh && imesh->mesh) {
637 scene::IMesh *mesh = imesh->mesh;
638 driver->clearZBuffer();
640 if (rotation_kind < IT_ROT_NONE) {
641 MeshTimeInfo &ti = rotation_time_infos[rotation_kind];
642 if (mesh != ti.mesh) {
644 ti.time = porting::getTimeMs();
646 delta = porting::getDeltaMs(ti.time, porting::getTimeMs()) % 100000;
649 core::rect<s32> oldViewPort = driver->getViewPort();
650 core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION);
651 core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW);
652 core::matrix4 ProjMatrix;
653 ProjMatrix.buildProjectionMatrixOrthoLH(2, 2, -1, 100);
654 driver->setTransform(video::ETS_PROJECTION, ProjMatrix);
655 driver->setTransform(video::ETS_VIEW, ProjMatrix);
656 core::matrix4 matrix;
657 matrix.makeIdentity();
659 if (enable_animations) {
660 float timer_f = (float) delta / 5000.0;
661 matrix.setRotationDegrees(core::vector3df(0, 360 * timer_f, 0));
664 driver->setTransform(video::ETS_WORLD, matrix);
665 driver->setViewPort(rect);
667 video::SColor basecolor =
668 client->idef()->getItemstackColor(item, client);
670 u32 mc = mesh->getMeshBufferCount();
671 for (u32 j = 0; j < mc; ++j) {
672 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
673 // we can modify vertices relatively fast,
674 // because these meshes are not buffered.
675 assert(buf->getHardwareMappingHint_Vertex() == scene::EHM_NEVER);
676 video::SColor c = basecolor;
677 if (imesh->buffer_colors.size() > j) {
678 ItemPartColor *p = &imesh->buffer_colors[j];
679 if (p->override_base)
682 if (imesh->needs_shading)
683 colorizeMeshBuffer(buf, &c);
685 setMeshBufferColor(buf, c);
686 video::SMaterial &material = buf->getMaterial();
687 material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
688 material.Lighting = false;
689 driver->setMaterial(material);
690 driver->drawMeshBuffer(buf);
693 driver->setTransform(video::ETS_VIEW, oldViewMat);
694 driver->setTransform(video::ETS_PROJECTION, oldProjMat);
695 driver->setViewPort(oldViewPort);
698 if(def.type == ITEM_TOOL && item.wear != 0)
700 // Draw a progressbar
701 float barheight = rect.getHeight()/16;
702 float barpad_x = rect.getWidth()/16;
703 float barpad_y = rect.getHeight()/16;
704 core::rect<s32> progressrect(
705 rect.UpperLeftCorner.X + barpad_x,
706 rect.LowerRightCorner.Y - barpad_y - barheight,
707 rect.LowerRightCorner.X - barpad_x,
708 rect.LowerRightCorner.Y - barpad_y);
710 // Shrink progressrect by amount of tool damage
711 float wear = item.wear / 65535.0;
713 wear * progressrect.UpperLeftCorner.X +
714 (1-wear) * progressrect.LowerRightCorner.X;
716 // Compute progressbar color
718 // wear = 0.5: yellow
720 video::SColor color(255,255,255,255);
721 int wear_i = MYMIN(std::floor(wear * 600), 511);
722 wear_i = MYMIN(wear_i + 10, 511);
724 color.set(255, wear_i, 255, 0);
726 color.set(255, 255, 511 - wear_i, 0);
728 core::rect<s32> progressrect2 = progressrect;
729 progressrect2.LowerRightCorner.X = progressmid;
730 driver->draw2DRectangle(color, progressrect2, clip);
732 color = video::SColor(255,0,0,0);
733 progressrect2 = progressrect;
734 progressrect2.UpperLeftCorner.X = progressmid;
735 driver->draw2DRectangle(color, progressrect2, clip);
738 if(font != NULL && item.count >= 2)
740 // Get the item count as a string
741 std::string text = itos(item.count);
742 v2u32 dim = font->getDimension(utf8_to_wide(text).c_str());
743 v2s32 sdim(dim.X,dim.Y);
745 core::rect<s32> rect2(
746 /*rect.UpperLeftCorner,
747 core::dimension2d<u32>(rect.getWidth(), 15)*/
748 rect.LowerRightCorner - sdim,
752 video::SColor bgcolor(128,0,0,0);
753 driver->draw2DRectangle(bgcolor, rect2, clip);
755 video::SColor color(255,255,255,255);
756 font->draw(text.c_str(), rect2, color, false, false, clip);