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"
29 #include "client/tile.h"
30 #include "localplayer.h"
33 #include "fontengine.h"
34 #include "guiscalingfilter.h"
36 #include "wieldmesh.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 (auto &hbar_color : hbar_colors)
59 hbar_color = 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.empty())
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.empty())
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.empty()) {
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 (const auto &selection_box : m_selection_boxes) {
601 halo_box.addInternalBox(selection_box);
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 const v2u32 &window_size = RenderingEngine::get_instance()->getWindowSize();
612 if (m_screensize != window_size) {
613 m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE *
614 RenderingEngine::getDisplayDensity() + 0.5);
615 m_hotbar_imagesize *= m_hud_scaling;
616 m_padding = m_hotbar_imagesize / 12;
617 m_screensize = window_size;
618 m_displaycenter = v2s32(m_screensize.X/2,m_screensize.Y/2);
622 struct MeshTimeInfo {
627 void drawItemStack(video::IVideoDriver *driver,
629 const ItemStack &item,
630 const core::rect<s32> &rect,
631 const core::rect<s32> *clip,
633 ItemRotationKind rotation_kind)
635 static MeshTimeInfo rotation_time_infos[IT_ROT_NONE];
636 static thread_local bool enable_animations =
637 g_settings->getBool("inventory_items_animations");
640 if (rotation_kind < IT_ROT_NONE) {
641 rotation_time_infos[rotation_kind].mesh = NULL;
646 const ItemDefinition &def = item.getDefinition(client->idef());
647 ItemMesh *imesh = client->idef()->getWieldMesh(def.name, client);
649 if (imesh && imesh->mesh) {
650 scene::IMesh *mesh = imesh->mesh;
651 driver->clearZBuffer();
653 if (rotation_kind < IT_ROT_NONE) {
654 MeshTimeInfo &ti = rotation_time_infos[rotation_kind];
655 if (mesh != ti.mesh) {
657 ti.time = porting::getTimeMs();
659 delta = porting::getDeltaMs(ti.time, porting::getTimeMs()) % 100000;
662 core::rect<s32> oldViewPort = driver->getViewPort();
663 core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION);
664 core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW);
665 core::matrix4 ProjMatrix;
666 ProjMatrix.buildProjectionMatrixOrthoLH(2, 2, -1, 100);
667 driver->setTransform(video::ETS_PROJECTION, ProjMatrix);
668 driver->setTransform(video::ETS_VIEW, ProjMatrix);
669 core::matrix4 matrix;
670 matrix.makeIdentity();
672 if (enable_animations) {
673 float timer_f = (float) delta / 5000.0;
674 matrix.setRotationDegrees(core::vector3df(0, 360 * timer_f, 0));
677 driver->setTransform(video::ETS_WORLD, matrix);
678 driver->setViewPort(rect);
680 video::SColor basecolor =
681 client->idef()->getItemstackColor(item, client);
683 u32 mc = mesh->getMeshBufferCount();
684 for (u32 j = 0; j < mc; ++j) {
685 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
686 // we can modify vertices relatively fast,
687 // because these meshes are not buffered.
688 assert(buf->getHardwareMappingHint_Vertex() == scene::EHM_NEVER);
689 video::SColor c = basecolor;
690 if (imesh->buffer_colors.size() > j) {
691 ItemPartColor *p = &imesh->buffer_colors[j];
692 if (p->override_base)
695 if (imesh->needs_shading)
696 colorizeMeshBuffer(buf, &c);
698 setMeshBufferColor(buf, c);
699 video::SMaterial &material = buf->getMaterial();
700 material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
701 material.Lighting = false;
702 driver->setMaterial(material);
703 driver->drawMeshBuffer(buf);
706 driver->setTransform(video::ETS_VIEW, oldViewMat);
707 driver->setTransform(video::ETS_PROJECTION, oldProjMat);
708 driver->setViewPort(oldViewPort);
711 if(def.type == ITEM_TOOL && item.wear != 0)
713 // Draw a progressbar
714 float barheight = rect.getHeight()/16;
715 float barpad_x = rect.getWidth()/16;
716 float barpad_y = rect.getHeight()/16;
717 core::rect<s32> progressrect(
718 rect.UpperLeftCorner.X + barpad_x,
719 rect.LowerRightCorner.Y - barpad_y - barheight,
720 rect.LowerRightCorner.X - barpad_x,
721 rect.LowerRightCorner.Y - barpad_y);
723 // Shrink progressrect by amount of tool damage
724 float wear = item.wear / 65535.0;
726 wear * progressrect.UpperLeftCorner.X +
727 (1-wear) * progressrect.LowerRightCorner.X;
729 // Compute progressbar color
731 // wear = 0.5: yellow
733 video::SColor color(255,255,255,255);
734 int wear_i = MYMIN(floor(wear * 600), 511);
735 wear_i = MYMIN(wear_i + 10, 511);
737 color.set(255, wear_i, 255, 0);
739 color.set(255, 255, 511-wear_i, 0);
741 core::rect<s32> progressrect2 = progressrect;
742 progressrect2.LowerRightCorner.X = progressmid;
743 driver->draw2DRectangle(color, progressrect2, clip);
745 color = video::SColor(255,0,0,0);
746 progressrect2 = progressrect;
747 progressrect2.UpperLeftCorner.X = progressmid;
748 driver->draw2DRectangle(color, progressrect2, clip);
751 if(font != NULL && item.count >= 2)
753 // Get the item count as a string
754 std::string text = itos(item.count);
755 v2u32 dim = font->getDimension(utf8_to_wide(text).c_str());
756 v2s32 sdim(dim.X,dim.Y);
758 core::rect<s32> rect2(
759 /*rect.UpperLeftCorner,
760 core::dimension2d<u32>(rect.getWidth(), 15)*/
761 rect.LowerRightCorner - sdim,
765 video::SColor bgcolor(128,0,0,0);
766 driver->draw2DRectangle(bgcolor, rect2, clip);
768 video::SColor color(255,255,255,255);
769 font->draw(text.c_str(), rect2, color, false, false, clip);