3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4 Copyright (C) 2010-2013 blue42u, Jonathon Anderson <anderjon@umail.iu.edu>
5 Copyright (C) 2010-2013 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include "util/numeric.h"
27 #include "inventory.h"
28 #include "client/tile.h"
29 #include "localplayer.h"
32 #include "fontengine.h"
33 #include "guiscalingfilter.h"
35 #include "wieldmesh.h"
36 #include <IGUIStaticText.h>
38 #ifdef HAVE_TOUCHSCREENGUI
39 #include "touchscreengui.h"
42 Hud::Hud(video::IVideoDriver *driver, scene::ISceneManager* smgr,
43 gui::IGUIEnvironment* guienv, Client *client, LocalPlayer *player,
46 this->driver = driver;
48 this->guienv = guienv;
49 this->client = client;
50 this->player = player;
51 this->inventory = inventory;
53 m_hud_scaling = g_settings->getFloat("hud_scaling");
54 m_screensize = v2u32(0, 0);
55 m_displaycenter = v2s32(0, 0);
56 m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE * porting::getDisplayDensity() + 0.5);
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");
81 use_hotbar_image = false;
82 hotbar_selected_image = "";
83 use_hotbar_selected_image = false;
85 m_selection_mesh = NULL;
86 m_selection_boxes.clear();
89 m_selection_pos = v3f(0.0, 0.0, 0.0);
90 std::string mode = g_settings->get("node_highlighting");
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 mode == "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;
103 m_use_selection_mesh = false;
104 m_selection_material.Thickness =
105 rangelim(g_settings->getS16("selectionbox_width"), 1, 5);
106 } else if (mode == "halo") {
107 m_use_selection_mesh = true;
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 * porting::getDisplayDensity();
219 pos.Y *= m_hud_scaling * porting::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 * porting::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 if ( (float) width / (float) porting::getWindowSize().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_use_selection_mesh) {
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_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_use_selection_mesh)
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 if (m_screensize != porting::getWindowSize()) {
613 m_hotbar_imagesize = floor(HOTBAR_IMAGE_SIZE * porting::getDisplayDensity() + 0.5);
614 m_hotbar_imagesize *= m_hud_scaling;
615 m_padding = m_hotbar_imagesize / 12;
616 m_screensize = porting::getWindowSize();
617 m_displaycenter = v2s32(m_screensize.X/2,m_screensize.Y/2);
621 struct MeshTimeInfo {
626 void drawItemStack(video::IVideoDriver *driver,
628 const ItemStack &item,
629 const core::rect<s32> &rect,
630 const core::rect<s32> *clip,
632 ItemRotationKind rotation_kind)
634 static MeshTimeInfo rotation_time_infos[IT_ROT_NONE];
635 static bool enable_animations =
636 g_settings->getBool("inventory_items_animations");
639 if (rotation_kind < IT_ROT_NONE) {
640 rotation_time_infos[rotation_kind].mesh = NULL;
645 const ItemDefinition &def = item.getDefinition(client->idef());
646 ItemMesh *imesh = client->idef()->getWieldMesh(def.name, client);
648 if (imesh && imesh->mesh) {
649 scene::IMesh *mesh = imesh->mesh;
650 driver->clearZBuffer();
652 if (rotation_kind < IT_ROT_NONE) {
653 MeshTimeInfo &ti = rotation_time_infos[rotation_kind];
654 if (mesh != ti.mesh) {
656 ti.time = porting::getTimeMs();
658 delta = porting::getDeltaMs(ti.time, porting::getTimeMs()) % 100000;
661 core::rect<s32> oldViewPort = driver->getViewPort();
662 core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION);
663 core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW);
664 core::matrix4 ProjMatrix;
665 ProjMatrix.buildProjectionMatrixOrthoLH(2, 2, -1, 100);
666 driver->setTransform(video::ETS_PROJECTION, ProjMatrix);
667 driver->setTransform(video::ETS_VIEW, ProjMatrix);
668 core::matrix4 matrix;
669 matrix.makeIdentity();
671 if (enable_animations) {
672 float timer_f = (float) delta / 5000.0;
673 matrix.setRotationDegrees(core::vector3df(0, 360 * timer_f, 0));
676 driver->setTransform(video::ETS_WORLD, matrix);
677 driver->setViewPort(rect);
679 video::SColor basecolor =
680 client->idef()->getItemstackColor(item, client);
682 u32 mc = mesh->getMeshBufferCount();
683 for (u32 j = 0; j < mc; ++j) {
684 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
685 // we can modify vertices relatively fast,
686 // because these meshes are not buffered.
687 assert(buf->getHardwareMappingHint_Vertex() == scene::EHM_NEVER);
688 video::SColor c = basecolor;
689 if (imesh->buffer_colors.size() > j) {
690 ItemPartColor *p = &imesh->buffer_colors[j];
691 if (p->override_base)
694 colorizeMeshBuffer(buf, &c);
695 video::SMaterial &material = buf->getMaterial();
696 material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
697 material.Lighting = false;
698 driver->setMaterial(material);
699 driver->drawMeshBuffer(buf);
702 driver->setTransform(video::ETS_VIEW, oldViewMat);
703 driver->setTransform(video::ETS_PROJECTION, oldProjMat);
704 driver->setViewPort(oldViewPort);
707 if(def.type == ITEM_TOOL && item.wear != 0)
709 // Draw a progressbar
710 float barheight = rect.getHeight()/16;
711 float barpad_x = rect.getWidth()/16;
712 float barpad_y = rect.getHeight()/16;
713 core::rect<s32> progressrect(
714 rect.UpperLeftCorner.X + barpad_x,
715 rect.LowerRightCorner.Y - barpad_y - barheight,
716 rect.LowerRightCorner.X - barpad_x,
717 rect.LowerRightCorner.Y - barpad_y);
719 // Shrink progressrect by amount of tool damage
720 float wear = item.wear / 65535.0;
722 wear * progressrect.UpperLeftCorner.X +
723 (1-wear) * progressrect.LowerRightCorner.X;
725 // Compute progressbar color
727 // wear = 0.5: yellow
729 video::SColor color(255,255,255,255);
730 int wear_i = MYMIN(floor(wear * 600), 511);
731 wear_i = MYMIN(wear_i + 10, 511);
733 color.set(255, wear_i, 255, 0);
735 color.set(255, 255, 511-wear_i, 0);
737 core::rect<s32> progressrect2 = progressrect;
738 progressrect2.LowerRightCorner.X = progressmid;
739 driver->draw2DRectangle(color, progressrect2, clip);
741 color = video::SColor(255,0,0,0);
742 progressrect2 = progressrect;
743 progressrect2.UpperLeftCorner.X = progressmid;
744 driver->draw2DRectangle(color, progressrect2, clip);
747 if(font != NULL && item.count >= 2)
749 // Get the item count as a string
750 std::string text = itos(item.count);
751 v2u32 dim = font->getDimension(utf8_to_wide(text).c_str());
752 v2s32 sdim(dim.X,dim.Y);
754 core::rect<s32> rect2(
755 /*rect.UpperLeftCorner,
756 core::dimension2d<u32>(rect.getWidth(), 15)*/
757 rect.LowerRightCorner - sdim,
761 video::SColor bgcolor(128,0,0,0);
762 driver->draw2DRectangle(bgcolor, rect2, clip);
764 video::SColor color(255,255,255,255);
765 font->draw(text.c_str(), rect2, color, false, false, clip);