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;
47 tsrc = gamedef->getTextureSource();
49 v3f crosshair_color = g_settings->getV3F("crosshair_color");
50 u32 cross_r = rangelim(myround(crosshair_color.X), 0, 255);
51 u32 cross_g = rangelim(myround(crosshair_color.Y), 0, 255);
52 u32 cross_b = rangelim(myround(crosshair_color.Z), 0, 255);
53 u32 cross_a = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255);
54 crosshair_argb = video::SColor(cross_a, cross_r, cross_g, cross_b);
56 v3f selectionbox_color = g_settings->getV3F("selectionbox_color");
57 u32 sbox_r = rangelim(myround(selectionbox_color.X), 0, 255);
58 u32 sbox_g = rangelim(myround(selectionbox_color.Y), 0, 255);
59 u32 sbox_b = rangelim(myround(selectionbox_color.Z), 0, 255);
60 selectionbox_argb = video::SColor(255, sbox_r, sbox_g, sbox_b);
62 use_crosshair_image = tsrc->isKnownSourceImage("crosshair.png");
66 //NOTE: selectitem = 0 -> no selected; selectitem 1-based
67 void Hud::drawItem(v2s32 upperleftpos, s32 imgsize, s32 itemcount,
68 InventoryList *mainlist, u16 selectitem, u16 direction)
70 s32 padding = imgsize / 12;
71 s32 height = imgsize + padding * 2;
72 s32 width = itemcount * (imgsize + padding * 2);
73 if (direction == HUD_DIR_TOP_BOTTOM || direction == HUD_DIR_BOTTOM_TOP) {
74 width = imgsize + padding * 2;
75 height = itemcount * (imgsize + padding * 2);
77 s32 fullimglen = imgsize + padding * 2;
79 // Position of upper left corner of bar
80 v2s32 pos = upperleftpos;
82 // Draw background color
83 /*core::rect<s32> barrect(0,0,width,height);
85 video::SColor bgcolor(255,128,128,128);
86 driver->draw2DRectangle(bgcolor, barrect, NULL);*/
88 core::rect<s32> imgrect(0, 0, imgsize, imgsize);
90 for (s32 i = 0; i < itemcount; i++)
92 const ItemStack &item = mainlist->getItem(i);
96 case HUD_DIR_RIGHT_LEFT:
97 steppos = v2s32(-(padding + i * fullimglen), padding);
99 case HUD_DIR_TOP_BOTTOM:
100 steppos = v2s32(padding, padding + i * fullimglen);
102 case HUD_DIR_BOTTOM_TOP:
103 steppos = v2s32(padding, -(padding + i * fullimglen));
106 steppos = v2s32(padding + i * fullimglen, padding);
109 core::rect<s32> rect = imgrect + pos + steppos;
111 if (selectitem == i + 1)
113 video::SColor c_outside(255,255,0,0);
114 //video::SColor c_outside(255,0,0,0);
115 //video::SColor c_inside(255,192,192,192);
116 s32 x1 = rect.UpperLeftCorner.X;
117 s32 y1 = rect.UpperLeftCorner.Y;
118 s32 x2 = rect.LowerRightCorner.X;
119 s32 y2 = rect.LowerRightCorner.Y;
120 // Black base borders
121 driver->draw2DRectangle(c_outside,
123 v2s32(x1 - padding, y1 - padding),
124 v2s32(x2 + padding, y1)
126 driver->draw2DRectangle(c_outside,
128 v2s32(x1 - padding, y2),
129 v2s32(x2 + padding, y2 + padding)
131 driver->draw2DRectangle(c_outside,
133 v2s32(x1 - padding, y1),
136 driver->draw2DRectangle(c_outside,
139 v2s32(x2 + padding, y2)
141 /*// Light inside borders
142 driver->draw2DRectangle(c_inside,
144 v2s32(x1 - padding/2, y1 - padding/2),
145 v2s32(x2 + padding/2, y1)
147 driver->draw2DRectangle(c_inside,
149 v2s32(x1 - padding/2, y2),
150 v2s32(x2 + padding/2, y2 + padding/2)
152 driver->draw2DRectangle(c_inside,
154 v2s32(x1 - padding/2, y1),
157 driver->draw2DRectangle(c_inside,
160 v2s32(x2 + padding/2, y2)
165 video::SColor bgcolor2(128, 0, 0, 0);
166 driver->draw2DRectangle(bgcolor2, rect, NULL);
167 drawItemStack(driver, font, item, rect, NULL, gamedef);
172 void Hud::drawLuaElements() {
173 for (size_t i = 0; i != player->hud.size(); i++) {
174 HudElement *e = player->hud[i];
178 v2s32 pos(e->pos.X * screensize.X, e->pos.Y * screensize.Y);
180 case HUD_ELEM_IMAGE: {
181 video::ITexture *texture = tsrc->getTexture(e->text);
185 const video::SColor color(255, 255, 255, 255);
186 const video::SColor colors[] = {color, color, color, color};
187 core::dimension2di imgsize(texture->getOriginalSize());
188 core::rect<s32> rect(0, 0, imgsize.Width * e->scale.X,
189 imgsize.Height * e->scale.X);
191 v2s32 offset((e->align.X - 1.0) * ((imgsize.Width * e->scale.X) / 2),
192 (e->align.Y - 1.0) * ((imgsize.Height * e->scale.X) / 2));
194 rect += v2s32(e->offset.X, e->offset.Y);
195 driver->draw2DImage(texture, rect,
196 core::rect<s32>(core::position2d<s32>(0,0), imgsize),
199 case HUD_ELEM_TEXT: {
200 video::SColor color(255, (e->number >> 16) & 0xFF,
201 (e->number >> 8) & 0xFF,
202 (e->number >> 0) & 0xFF);
203 core::rect<s32> size(0, 0, e->scale.X, text_height * e->scale.Y);
204 std::wstring text = narrow_to_wide(e->text);
205 core::dimension2d<u32> textsize = font->getDimension(text.c_str());
206 v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2),
207 (e->align.Y - 1.0) * (textsize.Height / 2));
208 v2s32 offs(e->offset.X, e->offset.Y);
209 font->draw(text.c_str(), size + pos + offset + offs, color);
211 case HUD_ELEM_STATBAR: {
212 v2s32 offs(e->offset.X, e->offset.Y);
213 drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number, offs);
215 case HUD_ELEM_INVENTORY: {
216 InventoryList *inv = inventory->getList(e->text);
217 drawItem(pos, hotbar_imagesize, e->number, inv, e->item, e->dir);
220 infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
221 "of hud element ID " << i << " due to unrecognized type" << std::endl;
227 void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s32 count, v2s32 offset) {
228 const video::SColor color(255, 255, 255, 255);
229 const video::SColor colors[] = {color, color, color, color};
231 video::ITexture *stat_texture = tsrc->getTexture(texture);
235 core::dimension2di srcd(stat_texture->getOriginalSize());
238 if (corner & HUD_CORNER_LOWER)
245 case HUD_DIR_RIGHT_LEFT:
246 steppos = v2s32(-1, 0);
248 case HUD_DIR_TOP_BOTTOM:
249 steppos = v2s32(0, 1);
251 case HUD_DIR_BOTTOM_TOP:
252 steppos = v2s32(0, -1);
255 steppos = v2s32(1, 0);
257 steppos.X *= srcd.Width;
258 steppos.Y *= srcd.Height;
260 for (s32 i = 0; i < count / 2; i++)
262 core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
263 core::rect<s32> dstrect(srcrect);
266 driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true);
272 core::rect<s32> srcrect(0, 0, srcd.Width / 2, srcd.Height);
273 core::rect<s32> dstrect(srcrect);
276 driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true);
281 void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem, s32 breath) {
282 InventoryList *mainlist = inventory->getList("main");
283 if (mainlist == NULL) {
284 errorstream << "draw_hotbar(): mainlist == NULL" << std::endl;
288 s32 hotbar_itemcount = player->hud_hotbar_itemcount;
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));
298 if (player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE && breath <= 10)
299 drawStatbar(pos - v2s32(-180, 4), HUD_CORNER_LOWER, HUD_DIR_LEFT_RIGHT,
300 "bubble.png", breath*2, v2s32(0, 0));
304 void Hud::drawCrosshair() {
305 if (!(player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE))
308 if (use_crosshair_image) {
309 video::ITexture *crosshair = tsrc->getTexture("crosshair.png");
310 v2u32 size = crosshair->getOriginalSize();
311 v2s32 lsize = v2s32(displaycenter.X - (size.X / 2),
312 displaycenter.Y - (size.Y / 2));
313 driver->draw2DImage(crosshair, lsize,
314 core::rect<s32>(0, 0, size.X, size.Y),
315 0, crosshair_argb, true);
317 driver->draw2DLine(displaycenter - v2s32(10, 0),
318 displaycenter + v2s32(10, 0), crosshair_argb);
319 driver->draw2DLine(displaycenter - v2s32(0, 10),
320 displaycenter + v2s32(0, 10), crosshair_argb);
325 void Hud::drawSelectionBoxes(std::vector<aabb3f> &hilightboxes) {
326 for (std::vector<aabb3f>::const_iterator
327 i = hilightboxes.begin();
328 i != hilightboxes.end(); i++) {
329 driver->draw3DBox(*i, selectionbox_argb);
334 void Hud::resizeHotbar() {
335 if (screensize.Y <= 800)
336 hotbar_imagesize = 32;
337 else if (screensize.Y <= 1280)
338 hotbar_imagesize = 48;
340 hotbar_imagesize = 64;