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 <IGUIStaticText.h>
24 #include "guiFormSpecMenu.h"
26 #include "util/numeric.h"
32 Hud::Hud(video::IVideoDriver *driver, gui::IGUIEnvironment* guienv,
33 gui::IGUIFont *font, u32 text_height, IGameDef *gamedef,
34 LocalPlayer *player, Inventory *inventory) {
35 this->driver = driver;
36 this->guienv = guienv;
38 this->text_height = text_height;
39 this->gamedef = gamedef;
40 this->player = player;
41 this->inventory = inventory;
43 screensize = v2u32(0, 0);
44 displaycenter = v2s32(0, 0);
45 hotbar_imagesize = 48;
48 tsrc = gamedef->getTextureSource();
50 v3f crosshair_color = g_settings->getV3F("crosshair_color");
51 u32 cross_r = rangelim(myround(crosshair_color.X), 0, 255);
52 u32 cross_g = rangelim(myround(crosshair_color.Y), 0, 255);
53 u32 cross_b = rangelim(myround(crosshair_color.Z), 0, 255);
54 u32 cross_a = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255);
55 crosshair_argb = video::SColor(cross_a, cross_r, cross_g, cross_b);
57 v3f selectionbox_color = g_settings->getV3F("selectionbox_color");
58 u32 sbox_r = rangelim(myround(selectionbox_color.X), 0, 255);
59 u32 sbox_g = rangelim(myround(selectionbox_color.Y), 0, 255);
60 u32 sbox_b = rangelim(myround(selectionbox_color.Z), 0, 255);
61 selectionbox_argb = video::SColor(255, sbox_r, sbox_g, sbox_b);
63 use_crosshair_image = tsrc->isKnownSourceImage("crosshair.png");
67 //NOTE: selectitem = 0 -> no selected; selectitem 1-based
68 void Hud::drawItem(v2s32 upperleftpos, s32 imgsize, s32 itemcount,
69 InventoryList *mainlist, u16 selectitem, u16 direction)
71 s32 padding = imgsize / 12;
72 s32 height = imgsize + padding * 2;
73 s32 width = itemcount * (imgsize + padding * 2);
74 if (direction == HUD_DIR_TOP_BOTTOM || direction == HUD_DIR_BOTTOM_TOP) {
75 width = imgsize + padding * 2;
76 height = itemcount * (imgsize + padding * 2);
78 s32 fullimglen = imgsize + padding * 2;
80 // Position of upper left corner of bar
81 v2s32 pos = upperleftpos;
83 // Draw background color
84 /*core::rect<s32> barrect(0,0,width,height);
86 video::SColor bgcolor(255,128,128,128);
87 driver->draw2DRectangle(bgcolor, barrect, NULL);*/
89 core::rect<s32> imgrect(0, 0, imgsize, imgsize);
91 for (s32 i = 0; i < itemcount; i++)
93 const ItemStack &item = mainlist->getItem(i);
97 case HUD_DIR_RIGHT_LEFT:
98 steppos = v2s32(-(padding + i * fullimglen), padding);
100 case HUD_DIR_TOP_BOTTOM:
101 steppos = v2s32(padding, padding + i * fullimglen);
103 case HUD_DIR_BOTTOM_TOP:
104 steppos = v2s32(padding, -(padding + i * fullimglen));
107 steppos = v2s32(padding + i * fullimglen, padding);
110 core::rect<s32> rect = imgrect + pos + steppos;
112 if (selectitem == i + 1)
114 video::SColor c_outside(255,255,0,0);
115 //video::SColor c_outside(255,0,0,0);
116 //video::SColor c_inside(255,192,192,192);
117 s32 x1 = rect.UpperLeftCorner.X;
118 s32 y1 = rect.UpperLeftCorner.Y;
119 s32 x2 = rect.LowerRightCorner.X;
120 s32 y2 = rect.LowerRightCorner.Y;
121 // Black base borders
122 driver->draw2DRectangle(c_outside,
124 v2s32(x1 - padding, y1 - padding),
125 v2s32(x2 + padding, y1)
127 driver->draw2DRectangle(c_outside,
129 v2s32(x1 - padding, y2),
130 v2s32(x2 + padding, y2 + padding)
132 driver->draw2DRectangle(c_outside,
134 v2s32(x1 - padding, y1),
137 driver->draw2DRectangle(c_outside,
140 v2s32(x2 + padding, y2)
142 /*// Light inside borders
143 driver->draw2DRectangle(c_inside,
145 v2s32(x1 - padding/2, y1 - padding/2),
146 v2s32(x2 + padding/2, y1)
148 driver->draw2DRectangle(c_inside,
150 v2s32(x1 - padding/2, y2),
151 v2s32(x2 + padding/2, y2 + padding/2)
153 driver->draw2DRectangle(c_inside,
155 v2s32(x1 - padding/2, y1),
158 driver->draw2DRectangle(c_inside,
161 v2s32(x2 + padding/2, y2)
166 video::SColor bgcolor2(128, 0, 0, 0);
167 driver->draw2DRectangle(bgcolor2, rect, NULL);
168 drawItemStack(driver, font, item, rect, NULL, gamedef);
173 void Hud::drawLuaElements() {
174 for (size_t i = 0; i != player->hud.size(); i++) {
175 HudElement *e = player->hud[i];
179 v2s32 pos(e->pos.X * screensize.X, e->pos.Y * screensize.Y);
181 case HUD_ELEM_IMAGE: {
182 video::ITexture *texture = tsrc->getTextureRaw(e->text);
186 const video::SColor color(255, 255, 255, 255);
187 const video::SColor colors[] = {color, color, color, color};
188 core::dimension2di imgsize(texture->getOriginalSize());
189 core::rect<s32> rect(0, 0, imgsize.Width * e->scale.X,
190 imgsize.Height * e->scale.X);
192 v2s32 offset((e->align.X - 1.0) * ((imgsize.Width * e->scale.X) / 2),
193 (e->align.Y - 1.0) * ((imgsize.Height * e->scale.X) / 2));
195 rect += v2s32(e->offset.X, e->offset.Y);
196 driver->draw2DImage(texture, rect,
197 core::rect<s32>(core::position2d<s32>(0,0), imgsize),
200 case HUD_ELEM_TEXT: {
201 video::SColor color(255, (e->number >> 16) & 0xFF,
202 (e->number >> 8) & 0xFF,
203 (e->number >> 0) & 0xFF);
204 core::rect<s32> size(0, 0, e->scale.X, text_height * e->scale.Y);
205 std::wstring text = narrow_to_wide(e->text);
206 core::dimension2d<u32> textsize = font->getDimension(text.c_str());
207 v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2),
208 (e->align.Y - 1.0) * (textsize.Height / 2));
209 v2s32 offs(e->offset.X, e->offset.Y);
210 font->draw(text.c_str(), size + pos + offset + offs, color);
212 case HUD_ELEM_STATBAR: {
213 v2s32 offs(e->offset.X, e->offset.Y);
214 drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number, offs);
216 case HUD_ELEM_INVENTORY: {
217 InventoryList *inv = inventory->getList(e->text);
218 drawItem(pos, hotbar_imagesize, e->number, inv, e->item, e->dir);
221 infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
222 "of hud element ID " << i << " due to unrecognized type" << std::endl;
228 void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s32 count, v2s32 offset) {
229 const video::SColor color(255, 255, 255, 255);
230 const video::SColor colors[] = {color, color, color, color};
232 video::ITexture *stat_texture = tsrc->getTextureRaw(texture);
236 core::dimension2di srcd(stat_texture->getOriginalSize());
239 if (corner & HUD_CORNER_LOWER)
246 case HUD_DIR_RIGHT_LEFT:
247 steppos = v2s32(-1, 0);
249 case HUD_DIR_TOP_BOTTOM:
250 steppos = v2s32(0, 1);
252 case HUD_DIR_BOTTOM_TOP:
253 steppos = v2s32(0, -1);
256 steppos = v2s32(1, 0);
258 steppos.X *= srcd.Width;
259 steppos.Y *= srcd.Height;
261 for (s32 i = 0; i < count / 2; i++)
263 core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
264 core::rect<s32> dstrect(srcrect);
267 driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true);
273 core::rect<s32> srcrect(0, 0, srcd.Width / 2, srcd.Height);
274 core::rect<s32> dstrect(srcrect);
277 driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true);
282 void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem) {
283 InventoryList *mainlist = inventory->getList("main");
284 if (mainlist == NULL) {
285 errorstream << "draw_hotbar(): mainlist == NULL" << std::endl;
289 s32 padding = hotbar_imagesize / 12;
290 s32 width = hotbar_itemcount * (hotbar_imagesize + padding * 2);
291 v2s32 pos = centerlowerpos - v2s32(width / 2, hotbar_imagesize + padding * 2);
293 if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE)
294 drawItem(pos, hotbar_imagesize, hotbar_itemcount, mainlist, playeritem + 1, 0);
295 if (player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE)
296 drawStatbar(pos - v2s32(0, 4), HUD_CORNER_LOWER, HUD_DIR_LEFT_RIGHT,
297 "heart.png", halfheartcount, v2s32(0, 0));
301 void Hud::drawCrosshair() {
302 if (!(player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE))
305 if (use_crosshair_image) {
306 video::ITexture *crosshair = tsrc->getTextureRaw("crosshair.png");
307 v2u32 size = crosshair->getOriginalSize();
308 v2s32 lsize = v2s32(displaycenter.X - (size.X / 2),
309 displaycenter.Y - (size.Y / 2));
310 driver->draw2DImage(crosshair, lsize,
311 core::rect<s32>(0, 0, size.X, size.Y),
312 0, crosshair_argb, true);
314 driver->draw2DLine(displaycenter - v2s32(10, 0),
315 displaycenter + v2s32(10, 0), crosshair_argb);
316 driver->draw2DLine(displaycenter - v2s32(0, 10),
317 displaycenter + v2s32(0, 10), crosshair_argb);
322 void Hud::drawSelectionBoxes(std::vector<aabb3f> &hilightboxes) {
323 for (std::vector<aabb3f>::const_iterator
324 i = hilightboxes.begin();
325 i != hilightboxes.end(); i++) {
326 driver->draw3DBox(*i, selectionbox_argb);
331 void Hud::resizeHotbar() {
332 if (screensize.Y <= 800)
333 hotbar_imagesize = 32;
334 else if (screensize.Y <= 1280)
335 hotbar_imagesize = 48;
337 hotbar_imagesize = 64;