]> git.lizzy.rs Git - minetest.git/blob - src/hud.cpp
Generalize hud_builtin_enable into hud_set_flags
[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         v3f crosshair_color = g_settings->getV3F("crosshair_color");
49         u32 cross_r = rangelim(myround(crosshair_color.X), 0, 255);
50         u32 cross_g = rangelim(myround(crosshair_color.Y), 0, 255);
51         u32 cross_b = rangelim(myround(crosshair_color.Z), 0, 255);
52         u32 cross_a = rangelim(g_settings->getS32("crosshair_alpha"), 0, 255);
53         crosshair_argb = video::SColor(cross_a, cross_r, cross_g, cross_b);
54         
55         v3f selectionbox_color = g_settings->getV3F("selectionbox_color");
56         u32 sbox_r = rangelim(myround(selectionbox_color.X), 0, 255);
57         u32 sbox_g = rangelim(myround(selectionbox_color.Y), 0, 255);
58         u32 sbox_b = rangelim(myround(selectionbox_color.Z), 0, 255);
59         selectionbox_argb = video::SColor(255, sbox_r, sbox_g, sbox_b);
60 }
61
62
63 //NOTE: selectitem = 0 -> no selected; selectitem 1-based
64 void Hud::drawItem(v2s32 upperleftpos, s32 imgsize, s32 itemcount,
65                 InventoryList *mainlist, u16 selectitem, u16 direction)
66 {
67         s32 padding = imgsize / 12;
68         s32 height  = imgsize + padding * 2;
69         s32 width   = itemcount * (imgsize + padding * 2);
70         if (direction == HUD_DIR_TOP_BOTTOM || direction == HUD_DIR_BOTTOM_TOP) {
71                 width  = imgsize + padding * 2;
72                 height = itemcount * (imgsize + padding * 2);
73         }
74         s32 fullimglen = imgsize + padding * 2;
75
76         // Position of upper left corner of bar
77         v2s32 pos = upperleftpos;
78
79         // Draw background color
80         /*core::rect<s32> barrect(0,0,width,height);
81         barrect += pos;
82         video::SColor bgcolor(255,128,128,128);
83         driver->draw2DRectangle(bgcolor, barrect, NULL);*/
84
85         core::rect<s32> imgrect(0, 0, imgsize, imgsize);
86
87         for (s32 i = 0; i < itemcount; i++)
88         {
89                 const ItemStack &item = mainlist->getItem(i);
90
91                 v2s32 steppos;
92                 switch (direction) {
93                         case HUD_DIR_RIGHT_LEFT:
94                                 steppos = v2s32(-(padding + i * fullimglen), padding);
95                                 break;
96                         case HUD_DIR_TOP_BOTTOM:
97                                 steppos = v2s32(padding, padding + i * fullimglen);
98                                 break;
99                         case HUD_DIR_BOTTOM_TOP:
100                                 steppos = v2s32(padding, -(padding + i * fullimglen));
101                                 break;
102                         default:
103                                 steppos = v2s32(padding + i * fullimglen, padding);     
104                 }
105                         
106                 core::rect<s32> rect = imgrect + pos + steppos;
107
108                 if (selectitem == i + 1)
109                 {
110                         video::SColor c_outside(255,255,0,0);
111                         //video::SColor c_outside(255,0,0,0);
112                         //video::SColor c_inside(255,192,192,192);
113                         s32 x1 = rect.UpperLeftCorner.X;
114                         s32 y1 = rect.UpperLeftCorner.Y;
115                         s32 x2 = rect.LowerRightCorner.X;
116                         s32 y2 = rect.LowerRightCorner.Y;
117                         // Black base borders
118                         driver->draw2DRectangle(c_outside,
119                                         core::rect<s32>(
120                                                 v2s32(x1 - padding, y1 - padding),
121                                                 v2s32(x2 + padding, y1)
122                                         ), NULL);
123                         driver->draw2DRectangle(c_outside,
124                                         core::rect<s32>(
125                                                 v2s32(x1 - padding, y2),
126                                                 v2s32(x2 + padding, y2 + padding)
127                                         ), NULL);
128                         driver->draw2DRectangle(c_outside,
129                                         core::rect<s32>(
130                                                 v2s32(x1 - padding, y1),
131                                                 v2s32(x1, y2)
132                                         ), NULL);
133                         driver->draw2DRectangle(c_outside,
134                                         core::rect<s32>(
135                                                 v2s32(x2, y1),
136                                                 v2s32(x2 + padding, y2)
137                                         ), NULL);
138                         /*// Light inside borders
139                         driver->draw2DRectangle(c_inside,
140                                         core::rect<s32>(
141                                                 v2s32(x1 - padding/2, y1 - padding/2),
142                                                 v2s32(x2 + padding/2, y1)
143                                         ), NULL);
144                         driver->draw2DRectangle(c_inside,
145                                         core::rect<s32>(
146                                                 v2s32(x1 - padding/2, y2),
147                                                 v2s32(x2 + padding/2, y2 + padding/2)
148                                         ), NULL);
149                         driver->draw2DRectangle(c_inside,
150                                         core::rect<s32>(
151                                                 v2s32(x1 - padding/2, y1),
152                                                 v2s32(x1, y2)
153                                         ), NULL);
154                         driver->draw2DRectangle(c_inside,
155                                         core::rect<s32>(
156                                                 v2s32(x2, y1),
157                                                 v2s32(x2 + padding/2, y2)
158                                         ), NULL);
159                         */
160                 }
161
162                 video::SColor bgcolor2(128, 0, 0, 0);
163                 driver->draw2DRectangle(bgcolor2, rect, NULL);
164                 drawItemStack(driver, font, item, rect, NULL, gamedef);
165         }
166 }
167
168
169 void Hud::drawLuaElements() {
170         for (size_t i = 0; i != player->hud.size(); i++) {
171                 HudElement *e = player->hud[i];
172                 if (!e)
173                         continue;
174                 
175                 v2s32 pos(e->pos.X * screensize.X, e->pos.Y * screensize.Y);
176                 switch (e->type) {
177                         case HUD_ELEM_IMAGE: {
178                                 video::ITexture *texture =
179                                         gamedef->getTextureSource()->getTextureRaw(e->text);
180                                 if (!texture)
181                                         continue;
182
183                                 const video::SColor color(255, 255, 255, 255);
184                                 const video::SColor colors[] = {color, color, color, color};
185                                 core::dimension2di imgsize(texture->getOriginalSize());
186                                 core::rect<s32> rect(0, 0, imgsize.Width  * e->scale.X,
187                                                                                imgsize.Height * e->scale.X);
188                                 rect += pos;
189                                 v2s32 offset((e->align.X - 1.0) * ((imgsize.Width  * e->scale.X) / 2),
190                                              (e->align.Y - 1.0) * ((imgsize.Height * e->scale.X) / 2));
191                                 rect += offset;
192                                 rect += v2s32(e->offset.X, e->offset.Y);
193                                 driver->draw2DImage(texture, rect,
194                                         core::rect<s32>(core::position2d<s32>(0,0), imgsize),
195                                         NULL, colors, true);
196                                 break; }
197                         case HUD_ELEM_TEXT: {
198                                 video::SColor color(255, (e->number >> 16) & 0xFF,
199                                                                                  (e->number >> 8)  & 0xFF,
200                                                                                  (e->number >> 0)  & 0xFF);
201                                 core::rect<s32> size(0, 0, e->scale.X, text_height * e->scale.Y);
202                                 std::wstring text = narrow_to_wide(e->text);
203                                 core::dimension2d<u32> textsize = font->getDimension(text.c_str());
204                                 v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2),
205                                              (e->align.Y - 1.0) * (textsize.Height / 2));
206                                 v2s32 offs(e->offset.X, e->offset.Y);
207                                 font->draw(text.c_str(), size + pos + offset + offs, color);
208                                 break; }
209                         case HUD_ELEM_STATBAR: {
210                                 v2s32 offs(e->offset.X, e->offset.Y);
211                                 drawStatbar(pos, HUD_CORNER_UPPER, e->dir, e->text, e->number, offs);
212                                 break; }
213                         case HUD_ELEM_INVENTORY: {
214                                 InventoryList *inv = inventory->getList(e->text);
215                                 drawItem(pos, hotbar_imagesize, e->number, inv, e->item, e->dir);
216                                 break; }
217                         default:
218                                 infostream << "Hud::drawLuaElements: ignoring drawform " << e->type <<
219                                         "of hud element ID " << i << " due to unrecognized type" << std::endl;
220                 }
221         }
222 }
223
224
225 void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir, std::string texture, s32 count, v2s32 offset) {
226         const video::SColor color(255, 255, 255, 255);
227         const video::SColor colors[] = {color, color, color, color};
228         
229         video::ITexture *stat_texture =
230                 gamedef->getTextureSource()->getTextureRaw(texture);
231         if (!stat_texture)
232                 return;
233                 
234         core::dimension2di srcd(stat_texture->getOriginalSize());
235
236         v2s32 p = pos;
237         if (corner & HUD_CORNER_LOWER)
238                 p -= srcd.Height;
239
240         p += offset;
241
242         v2s32 steppos;
243         switch (drawdir) {
244                 case HUD_DIR_RIGHT_LEFT:
245                         steppos = v2s32(-1, 0);
246                         break;
247                 case HUD_DIR_TOP_BOTTOM:
248                         steppos = v2s32(0, 1);
249                         break;
250                 case HUD_DIR_BOTTOM_TOP:
251                         steppos = v2s32(0, -1);
252                         break;
253                 default:
254                         steppos = v2s32(1, 0);  
255         }
256         steppos.X *= srcd.Width;
257         steppos.Y *= srcd.Height;
258         
259         for (s32 i = 0; i < count / 2; i++)
260         {
261                 core::rect<s32> srcrect(0, 0, srcd.Width, srcd.Height);
262                 core::rect<s32> dstrect(srcrect);
263
264                 dstrect += p;
265                 driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true);
266                 p += steppos;
267         }
268         
269         if (count % 2 == 1)
270         {
271                 core::rect<s32> srcrect(0, 0, srcd.Width / 2, srcd.Height);
272                 core::rect<s32> dstrect(srcrect);
273
274                 dstrect += p;
275                 driver->draw2DImage(stat_texture, dstrect, srcrect, NULL, colors, true);
276         }
277 }
278
279
280 void Hud::drawHotbar(v2s32 centerlowerpos, s32 halfheartcount, u16 playeritem) {
281         InventoryList *mainlist = inventory->getList("main");
282         if (mainlist == NULL) {
283                 errorstream << "draw_hotbar(): mainlist == NULL" << std::endl;
284                 return;
285         }
286         
287         s32 padding = hotbar_imagesize / 12;
288         s32 width = hotbar_itemcount * (hotbar_imagesize + padding * 2);
289         v2s32 pos = centerlowerpos - v2s32(width / 2, hotbar_imagesize + padding * 2);
290         
291         if (player->hud_flags & HUD_FLAG_HOTBAR_VISIBLE)
292                 drawItem(pos, hotbar_imagesize, hotbar_itemcount, mainlist, playeritem + 1, 0);
293         if (player->hud_flags & HUD_FLAG_HEALTHBAR_VISIBLE)
294                 drawStatbar(pos - v2s32(0, 4), HUD_CORNER_LOWER, HUD_DIR_LEFT_RIGHT,
295                                 "heart.png", halfheartcount, v2s32(0, 0));
296 }
297
298
299 void Hud::drawCrosshair() {
300         if (player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) {
301                 driver->draw2DLine(displaycenter - v2s32(10, 0),
302                                 displaycenter + v2s32(10, 0), crosshair_argb);
303                 driver->draw2DLine(displaycenter - v2s32(0, 10),
304                                 displaycenter + v2s32(0, 10), crosshair_argb);
305         }
306 }
307
308
309 void Hud::drawSelectionBoxes(std::vector<aabb3f> &hilightboxes) {
310         for (std::vector<aabb3f>::const_iterator
311                         i = hilightboxes.begin();
312                         i != hilightboxes.end(); i++) {
313                 driver->draw3DBox(*i, selectionbox_argb);
314         }
315 }
316
317
318 void Hud::resizeHotbar() {
319         if (screensize.Y <= 800)
320                 hotbar_imagesize = 32;
321         else if (screensize.Y <= 1280)
322                 hotbar_imagesize = 48;
323         else
324                 hotbar_imagesize = 64;
325 }