]> git.lizzy.rs Git - minetest.git/blob - src/hud.cpp
Fix lava damage on player's upper body
[minetest.git] / src / hud.cpp
1 /*
2 Minetest
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>
6
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.
11
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.
16
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.
20 */
21
22 #include <IGUIStaticText.h>
23
24 #include "guiFormSpecMenu.h"
25 #include "main.h"
26 #include "util/numeric.h"
27 #include "log.h"
28 #include "client.h"
29 #include "hud.h"
30
31
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;
37         this->font        = font;
38         this->text_height = text_height;
39         this->gamedef     = gamedef;
40         this->player      = player;
41         this->inventory   = inventory;
42         
43         screensize       = v2u32(0, 0);
44         displaycenter    = v2s32(0, 0);
45         hotbar_imagesize = 48;
46         hotbar_itemcount = 8;
47         
48         tsrc = gamedef->getTextureSource();
49         
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);
56         
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);
62         
63         use_crosshair_image = tsrc->isKnownSourceImage("crosshair.png");
64 }
65
66
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)
70 {
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);
77         }
78         s32 fullimglen = imgsize + padding * 2;
79
80         // Position of upper left corner of bar
81         v2s32 pos = upperleftpos;
82
83         // Draw background color
84         /*core::rect<s32> barrect(0,0,width,height);
85         barrect += pos;
86         video::SColor bgcolor(255,128,128,128);
87         driver->draw2DRectangle(bgcolor, barrect, NULL);*/
88
89         core::rect<s32> imgrect(0, 0, imgsize, imgsize);
90
91         for (s32 i = 0; i < itemcount; i++)
92         {
93                 const ItemStack &item = mainlist->getItem(i);
94
95                 v2s32 steppos;
96                 switch (direction) {
97                         case HUD_DIR_RIGHT_LEFT:
98                                 steppos = v2s32(-(padding + i * fullimglen), padding);
99                                 break;
100                         case HUD_DIR_TOP_BOTTOM:
101                                 steppos = v2s32(padding, padding + i * fullimglen);
102                                 break;
103                         case HUD_DIR_BOTTOM_TOP:
104                                 steppos = v2s32(padding, -(padding + i * fullimglen));
105                                 break;
106                         default:
107                                 steppos = v2s32(padding + i * fullimglen, padding);     
108                 }
109                         
110                 core::rect<s32> rect = imgrect + pos + steppos;
111
112                 if (selectitem == i + 1)
113                 {
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,
123                                         core::rect<s32>(
124                                                 v2s32(x1 - padding, y1 - padding),
125                                                 v2s32(x2 + padding, y1)
126                                         ), NULL);
127                         driver->draw2DRectangle(c_outside,
128                                         core::rect<s32>(
129                                                 v2s32(x1 - padding, y2),
130                                                 v2s32(x2 + padding, y2 + padding)
131                                         ), NULL);
132                         driver->draw2DRectangle(c_outside,
133                                         core::rect<s32>(
134                                                 v2s32(x1 - padding, y1),
135                                                 v2s32(x1, y2)
136                                         ), NULL);
137                         driver->draw2DRectangle(c_outside,
138                                         core::rect<s32>(
139                                                 v2s32(x2, y1),
140                                                 v2s32(x2 + padding, y2)
141                                         ), NULL);
142                         /*// Light inside borders
143                         driver->draw2DRectangle(c_inside,
144                                         core::rect<s32>(
145                                                 v2s32(x1 - padding/2, y1 - padding/2),
146                                                 v2s32(x2 + padding/2, y1)
147                                         ), NULL);
148                         driver->draw2DRectangle(c_inside,
149                                         core::rect<s32>(
150                                                 v2s32(x1 - padding/2, y2),
151                                                 v2s32(x2 + padding/2, y2 + padding/2)
152                                         ), NULL);
153                         driver->draw2DRectangle(c_inside,
154                                         core::rect<s32>(
155                                                 v2s32(x1 - padding/2, y1),
156                                                 v2s32(x1, y2)
157                                         ), NULL);
158                         driver->draw2DRectangle(c_inside,
159                                         core::rect<s32>(
160                                                 v2s32(x2, y1),
161                                                 v2s32(x2 + padding/2, y2)
162                                         ), NULL);
163                         */
164                 }
165
166                 video::SColor bgcolor2(128, 0, 0, 0);
167                 driver->draw2DRectangle(bgcolor2, rect, NULL);
168                 drawItemStack(driver, font, item, rect, NULL, gamedef);
169         }
170 }
171
172
173 void Hud::drawLuaElements() {
174         for (size_t i = 0; i != player->hud.size(); i++) {
175                 HudElement *e = player->hud[i];
176                 if (!e)
177                         continue;
178                 
179                 v2s32 pos(e->pos.X * screensize.X, e->pos.Y * screensize.Y);
180                 switch (e->type) {
181                         case HUD_ELEM_IMAGE: {
182                                 video::ITexture *texture = tsrc->getTextureRaw(e->text);
183                                 if (!texture)
184                                         continue;
185
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);
191                                 rect += pos;
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));
194                                 rect += offset;
195                                 rect += v2s32(e->offset.X, e->offset.Y);
196                                 driver->draw2DImage(texture, rect,
197                                         core::rect<s32>(core::position2d<s32>(0,0), imgsize),
198                                         NULL, colors, true);
199                                 break; }
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);
211                                 break; }
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);
215                                 break; }
216                         case HUD_ELEM_INVENTORY: {
217                                 InventoryList *inv = inventory->getList(e->text);
218                                 drawItem(pos, hotbar_imagesize, e->number, inv, e->item, e->dir);
219                                 break; }
220                         default:
221                                 infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
222                                         "of hud element ID " << i << " due to unrecognized type" << std::endl;
223                 }
224         }
225 }
226
227
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};
231         
232         video::ITexture *stat_texture = tsrc->getTextureRaw(texture);
233         if (!stat_texture)
234                 return;
235                 
236         core::dimension2di srcd(stat_texture->getOriginalSize());
237
238         v2s32 p = pos;
239         if (corner & HUD_CORNER_LOWER)
240                 p -= srcd.Height;
241
242         p += offset;
243
244         v2s32 steppos;
245         switch (drawdir) {
246                 case HUD_DIR_RIGHT_LEFT:
247                         steppos = v2s32(-1, 0);
248                         break;
249                 case HUD_DIR_TOP_BOTTOM:
250                         steppos = v2s32(0, 1);
251                         break;
252                 case HUD_DIR_BOTTOM_TOP:
253                         steppos = v2s32(0, -1);
254                         break;
255                 default:
256                         steppos = v2s32(1, 0);  
257         }
258         steppos.X *= srcd.Width;
259         steppos.Y *= srcd.Height;
260         
261         for (s32 i = 0; i < count / 2; i++)
262         {
263                 core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
264                 core::rect<s32> dstrect(srcrect);
265
266                 dstrect += p;
267                 driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true);
268                 p += steppos;
269         }
270         
271         if (count % 2 == 1)
272         {
273                 core::rect<s32> srcrect(0, 0, srcd.Width / 2, srcd.Height);
274                 core::rect<s32> dstrect(srcrect);
275
276                 dstrect += p;
277                 driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true);
278         }
279 }
280
281
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;
286                 return;
287         }
288         
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);
292         
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 }
299
300
301 void Hud::drawCrosshair() {
302         if (!(player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE))
303                 return;
304                 
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);
313         } else {
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);
318         }
319 }
320
321
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);
327         }
328 }
329
330
331 void Hud::resizeHotbar() {
332         if (screensize.Y <= 800)
333                 hotbar_imagesize = 32;
334         else if (screensize.Y <= 1280)
335                 hotbar_imagesize = 48;
336         else
337                 hotbar_imagesize = 64;
338 }